Airdrop Low Gas

Hello, is there a way to reduce gas cost in this code?

is there a better way to airdrop token?


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

interface IERC20 {
  function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
  function balanceOf(address account) external view returns (uint256);
  function allowance(address owner, address spender) external view returns (uint256);
}

contract BulkAirdrop {

  function bulkAirdropERC20(IERC20 _token, address[] calldata _to, uint256[] calldata _value) public {
    require(_to.length == _value.length, "Receivers and amounts are different length");
    for (uint256 i = 0; i < _to.length; i++) {
      require(_token.transferFrom(msg.sender, _to[i], _value[i]));
    }
  }
}

In general people prefer to use a merkle-tree claim system which puts the action on the user side and they would pay the gas fee. Also when the user claims the airdrop you directly know which address so you don't have to loop over all the addresses

If you do want to airdrop it directly, and not use on of the online systems that can already do this for you then i advice you to check out:

which contains some information about saving gas and as a bonus included an example of exactly what you want at the end.

transferFrom will check and update the approval many times. That is expensive and can be avoided by doing it only once, and than doing a loop of transfers

  function bulkAirdropERC20(IERC20 _token, address[] calldata _to, uint256[] calldata _value) public {
    uint256 length = _to.length;
    require(length == _value.length, "Receivers and amounts are different length");

    uint256 totalValue = 0;
    for (uint256 i = 0; i < length; ++i) {
        totalValue += _value[i];
    }
    require(_token.transferFrom(msg.sender, address(this), totalValue));
    for (uint256 i = 0; i < length; ++i) {
      require(_token.transfer(_to[i], _value[i]));
    }
  }

Other than the generally correct approach of executing an airdrop via Merkle Tree, already described here in a previous answer, there is an obvious optimization shouting out of your code.


This:

_token.transferFrom(msg.sender, _to[i], _value[i]);

Can be replaced with this:

_token.transfer(_to[i], _value[i]);

Which doesn't check AND update the allowance on EVERY iteration.


Of course, don't forget to also replace the approve transaction that you execute prior to the airdrop:

token.approve(yourContractAddress, totalAmount, {from: yourWallet}); //pseudocode

With a transfer transaction:

token.transfer(yourContractAddress, totalAmount, {from: yourWallet}); //pseudocode