javascripterc20

Send ERC-20 Token Transaction using Web3 js and Private Key


I am trying to send a custom ERC-20 token transaction using web3.js and using the sender private key to sign the transaction. Although in my current code i am getting the following error:

Transaction has been reverted by the EVM 

Here I call the function sendToken(Sender Public Key, Sender Secret Key, Receiver Public Key, Amount of Tokens to Send):

sendToken("0x0000_SENDER_PUBLIC_KEY", "0x0000_SENDER_SECRET_KEY", "0x0000_RECIPIENT_PUBLIC_KEY", "0.005");

Here is the function i am using (Min ABI mention bellow):

async function sendToken(tokenHolder, walletSecret, toAddress, amount) { 
    
    const nonce = await web3.eth.getTransactionCount(tokenHolder);
    const gasPrice = await web3.eth.getGasPrice();
    const gasLimit = 200000;

    const params = {
        from: tokenHolder,
        to: toAddress, 
        nonce: web3.utils.toHex(nonce),
        data: minABI,
        value: web3.utils.toHex(web3.utils.toWei(amount, 'ether')),
        gasPrice: web3.utils.toHex(gasPrice),
        gasLimit: web3.utils.toHex(gasLimit),
    };
 
    const signedTx = await web3.eth.accounts.signTransaction(params, walletSecret);

    try { 
        web3.eth.sendSignedTransaction(signedTx.rawTransaction)
        .on('transactionHash', function(hash){
            console.log("txHash", hash);
        })
        .on('receipt', function(receipt){
            console.log("receipt", receipt) 
        })
        .on('confirmation', function(confirmationNumber, receipt){ 
            console.log("confirmationNumber",confirmationNumber,"receipt",receipt) 
        })
        .on('error', console.error); 
    } catch(error) {
        console.log(error);
    } 
}

Minimum ABI data I am using (it works well for other functions like, get account erc-20 tokens Balance):

// The minimum ABI to get ERC20 Token balance
        let minABI = [
        {
            "constant": true,
            "inputs": [
                {
                    "name": "_owner",
                    "type": "address"
                }
            ],
            "name": "balanceOf",
            "outputs": [
                {
                    "name": "balance",
                    "type": "uint256"
                }
            ],
            "payable": false,
            "stateMutability": "view",
            "type": "function"
        },
        ];
 
        // Define the ERC-20 token contract  
        window.web3 = web3;   
        window.minABI = minABI; 
    } 
 

What I am doing wrong? Cheers


Solution

  • Ok i found the issue. It was on the previous params data. In "to" and "from". Also the contract ABI was incorrect.

    The full working code:

    <script>
    "use strict"
    
         async function sendToken(tokenHolder, HolderSecretKey, toAddress, amount) { 
                 
                const gasPrice = await web3.eth.getGasPrice();
                const gasLimit = 200000;
                const walletSecret = HolderSecretKey; 
          
                // Creating a signing account from a private key
                const signer = web3.eth.accounts.privateKeyToAccount(walletSecret);
                web3.eth.accounts.wallet.add(signer); 
                const nedTokenContractAddress = "0x00MY_ERC20_CONTRACTADRESS";
                const web3contract = new web3.eth.Contract(transferABI, nedTokenContractAddress, { from: signer.address } )
                const amountInWei = web3.utils.toWei(amount, "ether");
                
                const params = {
                    from: tokenHolder,
                    to: nedTokenContractAddress, 
                    nonce: await web3.eth.getTransactionCount(tokenHolder),
                    value: '0x00',
                    data: web3contract.methods.transfer(toAddress, amountInWei).encodeABI(), 
                    gasPrice: web3.utils.toHex(gasPrice),
                    gasLimit: web3.utils.toHex(gasLimit),  
                };
        
                const signedTx = await web3.eth.accounts.signTransaction(params, walletSecret); 
        
                const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction)
                .once("transactionHash", (txhash) => {  
                console.log(`Mining transaction ...`);
                console.log(`https://polygonscan.com/tx/${txhash}`); 
                alert(txhash); 
                });
                // The transaction is now on chain!
                console.log(`Mined in block ${receipt.blockNumber}`); 
            } 
        </script>
    

    And for the ABI use the following:

       // The ABI to send ERC20 Token transfers
        let transferABI = [ 
        {
        "constant": false,
        "inputs": [
        {
            "name": "_to",
            "type": "address"
        },
        {
            "name": "_value",
            "type": "uint256"
        }
        ],
        "name": "transfer",
        "outputs": [
        {
            "name": "",
            "type": "bool"
        }
        ],
        "type": "function"
        }
        ];