web3.js: Estimate gas fee on usdt smart contract transfer

Issue

I’m trying to estimate gas value in eth, for USDT transfer, but we3.js gives me only IVALID OPCODE error…

code example

const Web3 = require('web3');

const web3 = new Web3('https://cloudflare-eth.com/');

const token = new web3.eth.Contract([{
    'constant': false,
    'inputs': [{
        'internalType': 'address',
        'name': 'recipient',
        'type': 'address',
    }, {
        'internalType': 'uint256',
        'name': 'amount',
        'type': 'uint256',
    }],
    'name': 'transfer',
    'outputs': [{
        'internalType': 'bool',
        'name': '',
        'type': 'bool',
    }],
    'payable': false,
    'stateMutability': 'nonpayable',
    'type': 'function',
}], '0xdac17f958d2ee523a2206206994597c13d831ec7');


const to = '0x....';
const from = '0x.....'
token
    .methods
    .transfer(to, web3.utils.toWei('1'))
    .estimateGas({from})
    .then(res=>{
        console.log(res);
    })
;

Error:
enter image description here

can’t find any working example for this. At the end i want to get near same value as metamask gives me…

UPDATE after Petr Hejda answer:

const Web3 = require('web3');

const web3 = new Web3('https://cloudflare-eth.com/');

const token = new web3.eth.Contract([{
    'constant': false,
    'inputs': [{
        'internalType': 'address',
        'name': 'recipient',
        'type': 'address',
    }, {
        'internalType': 'uint256',
        'name': 'amount',
        'type': 'uint256',
    }],
    'name': 'transfer',
    'outputs': [{
        'internalType': 'bool',
        'name': '',
        'type': 'bool',
    }],
    'payable': false,
    'stateMutability': 'nonpayable',
    'type': 'function',
}], '0xdac17f958d2ee523a2206206994597c13d831ec7');


const to = '0x..';
const from = '0x..'
const value = web3.utils.toWei('1', 'mwei');

web3.eth.getGasPrice()
    .then(gasPrice => {
        token
            .methods
            .transfer(to, value)
            .estimateGas({from})
            .then(estimatedGas=>{
                const txPriceWei = estimatedGas * gasPrice;
                const txPriceEth = web3.utils.fromWei(txPriceWei.toString(), 'ether');
                const txPriceUSD = txPriceEth * 1800;
                console.log({
                    estimatedGas, txPriceWei, txPriceEth, txPriceUSD
                });
            })
        ;
    })
;

Now it works, and estimates.. Something. It is near metamask value, but is about 30% less. Where could i miss this 30%?
enter image description here
enter image description here
Thanks.

Solution

Based on the values provided in the code, I’m assuming that you’re trying to calculate gas fees for transfering 1 USDT on the Ethereum mainnet.

The web3js toWei() function convers a number to an EVM-compatible value with 18 decimal places. However, the USDT token uses only 6 decimals.

Because of this discrepancy, your code is effectively tying to calculate gas costs of transferring 1.000.000.000.000 tokens (10^18 / 10^6 = 10^12).

Since the from address doesn’t have a trillion USDT, the transaction is expected to revert. And, in the underlying low-level EVM bytecode, a revert is triggered by the IVALID opcode.

Answered By – Petr Hejda

Answer Checked By – Candace Johnson (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.