I've got a smart contract function that takes an erc20 contract address, an array of addresses and an array of amounts and then sends the each amount to each address of the specified token. I've got the contract deployed on Sepolia and it works with erc20 tokens, so I deployed it on mainnet and it fails when using it for USDT.

Here is the error I'm getting:

Error: missing revert data (action="estimateGas", data=null, reason=null, transaction={ "data": "0xa134d6d9000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000968e3524eab348bc5fbebeb74190f6ecf334ad0900000000000000000000000008016e6b9e0122fc993a24a1ba1dfc42662d66a5000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000989680", "from": "0x968E3524EaB348Bc5fBEbEb74190F6EcF334ad09", "to": "0x81B6E79d70DF42b87a7B742c84f568e9C0FD74c6" }, invocation=null, revert=null, code=CALL_EXCEPTION, version=6.8.1)

Here is the function in Solidity:

function erc20sendmany(address contractAddress, address[] calldata addresses, uint256[] calldata amounts) public payable {
        uint totalSent;
        require(addresses.length == amounts.length, "We need equal arrays!");
        uint256 listLength = amounts.length;
        IERC20 token = IERC20(contractAddress);
        for (uint256 i=0; i < listLength; i++) {
            address receivingAddress = addresses[i];
            uint256 amount = amounts[i];
            require(token.balanceOf(msg.sender) >= amount, "Insufficient balance!");
            try token.transferFrom(msg.sender, receivingAddress, amount) {
                totalSent += amount;
            } catch {
                revert("Failed to send to address");
        emit SendSuccessful(totalSent);

Here is the JS function that calls it. Not sure if it's relevant, but I'm using ethers.js and React. :

async function erc20sendmany() {
    if (!addressValidity) {
      alert("Please submit a CSV with valid addresses!")
    console.log("ERC20 sendmany button clicked!");
    const ethers = require("ethers");
    const provider = new ethers.BrowserProvider(window.ethereum);
    const signer = await provider.getSigner();
    const address = signer.getAddress();
    //log the contract address
    console.log("usdtAddress", usdtAddress);
    //connect to the Multisend contract    
    const contract = new ethers.Contract(MultisendJSON.address, MultisendJSON.abi, signer);
    //connect to the erc20 token contract
    const tokenContract = new ethers.Contract(usdtAddress, erc20abi, signer);
    //get the token decimals
    const decimals = await tokenContract.decimals();
    //log the decimals for debugging
    //console.log("Decimals:", decimals);    
    const receivingAddresses = addresses;
    const receivingAmounts = amounts.map((amount)=> Number(amount));
    //format the token amounts based on the tokenContract decimals
    const formattedAmounts = receivingAmounts.map(i => ethers.parseUnits(i.toString(), decimals));
    console.log("receivingAddresses", receivingAddresses);
    console.log("receivingAmounts", receivingAmounts);
    //call the erc20sendmany function from the Multisend contract
    const feeData = await provider.getFeeData();
    console.log("feeData", feeData);
    try {
      const transaction = await contract.erc20sendmany(usdtAddress, receivingAddresses, formattedAmounts,);
      await transaction.wait();
      console.log("erc20sendmany output:", transaction);

    } catch(e) {
      alert("Transaction Error attempting to set gas manually!\n", e);
      const transaction = await contract.erc20sendmany(usdtAddress, receivingAddresses, formattedAmounts,{
        gasLimit: 500000,
      await transaction.wait();
      console.log("erc20sendmany output:", transaction);
    alert("erc20 multisend successful!");

I'm sure I'm missing something here, but I have no idea what I'm doing wrong (like I said, it runs on testnet but not on mainnet). When I run on mainnet with a custom gas limit, I just get a failed transaction and I lose my fee. Any advice here would be greatly appreciated.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.