0

So, i want a contract to send tokens to users in Batch, I know this code is vulnerable to overflow, but this is just to test if the contract works, and if it works ill add SafeMath libraries, but it doesn't, an error always pops up when im trying to batchTransfer test tokens from the contract to 2 wallet addresses, this is the code in question:

pragma solidity 0.4.16;

contract ERC20 {
   mapping(address => uint256) public balances;

   function transfer(address _to, uint256 _value) public returns (bool);
}

contract TokenPool 
{       
    mapping(address => mapping(address => uint256)) balances;
  function batchTransfer(address _tokenAddress, address[] _receivers, uint256 _value) public returns (bool) {
   ERC20 token = ERC20(_tokenAddress);
   uint cnt = _receivers.length;
   uint256 amount = uint256(cnt) * _value;
   require(cnt > 0 && cnt <= 20);
   require(_value > 0 && balances[_tokenAddress][msg.sender] >= amount);

   balances[_tokenAddress][msg.sender] -= amount;
   for (uint i = 0; i < cnt; i++) {
       balances[_tokenAddress][_receivers[i]] += _value;
       require(token.transfer(_receivers[i], _value));
   }
   return true;
  }
}
3
  • What's the error you're getting?
    – Foxxxey
    Jul 15, 2023 at 22:31
  • its hard to explain, it only works on etherscan, could you try the code? The error message is too long
    – 19216811
    Jul 15, 2023 at 22:56
  • That's the whole contract here? If so, it has absolutely no chance of working. Wait, let me make an answer, i'll explain a bit more.
    – Foxxxey
    Jul 15, 2023 at 23:15

1 Answer 1

0

There are several things that are wrong with this (assuming this is the whole contract)

  1. It's using transfer(), which as i told you on your other question, is not going to work unless the contract is already holding the funds needed to do the transfer.

  2. It's doing require(balances[_tokenAddress][msg.sender] >= amount);, which is never going to pass unless there is a separate function to deposit tokens to the contract

  3. It's recording the balances in a wierd way, you're keeping an internal trace of the contracts storage, and also transferring the tokens. Typically, you'd keep the internal balance mapping only if you need the users to claim the token they're entitled to, like so

  function batchTransfer(address _tokenAddress, address[] _receivers, uint256 _value) public returns (bool) {
   ERC20 token = ERC20(_tokenAddress);
   uint cnt = _receivers.length;
   uint256 amount = uint256(cnt) * _value;
   require(cnt > 0 && cnt <= 20);
   require(_value > 0 && balances[_tokenAddress][msg.sender] >= amount);

   balances[_tokenAddress][msg.sender] -= amount;
   for (uint i = 0; i < cnt; i++) {
       // Here we just update the receiver balance so they can later claim the tokens they should get
       balances[_tokenAddress][_receivers[i]] += _value;
   }
   return true;
   }
  // And then the receiver can use this function to actually get the tokens
  function claim(address tokenAddress) public {
    require(balances[tokenAddress][msg.sender] > 0); 
    ERC20(tokenAddress).transfer(msg.sender, balances[tokenAddress][msg.sender]);
    balances[tokenAddress][msg.sender] = 0;
  }

I believe that's not what you want to do here. Here is some code that i believe is closer to what you actually want :

contract TokenPool 
{       

  function batchTransfer(address _tokenAddress, address[] _receivers, uint256 _value) public returns (bool) {
   ERC20 token = ERC20(_tokenAddress);
   uint cnt = _receivers.length;
   uint256 amount = uint256(cnt) * _value;
   require(cnt > 0 && cnt <= 20);
// We don't need the internal balance mapping, so we're using the token's balanceOf function instead
   require(_value > 0 && token.balanceOf(msg.sender) >= amount);
   // Transferring all the tokens to the contract with transferFrom() then using transfer() to distribute all the tokens gets cheaper overall when there are more than 2 or 3 receivers
   token.transferFrom(msg.sender, address(this), amount);
   for (uint i = 0; i < cnt; i++) {
       require(token.transfer(_receivers[i], _value));
   }
   return true;
  }
}
10
  • I get this error: erer.sol:17:26: TypeError: Member "balanceOf" not found or not visible after argument-dependent lookup in contract ERC20 require(_value > 0 && token.balanceOf(msg.sender) >= amount); ^-------------^
    – 19216811
    Jul 16, 2023 at 12:01
  • Do you have a Discord? So that i can show you what type of error happens
    – 19216811
    Jul 16, 2023 at 13:28
  • Oh. Add function balanceOf(address user) external view returns(uint256); to your interface. But sure, nova5147 @AndyCrypto
    – Foxxxey
    Jul 16, 2023 at 13:53
  • Also, 0.4.16 is several years old and is lacking some important features (formalized interfaces and librairies, built-in over/underflow checks, custom errors...) You should always use the latest solidity version when you're writing smart contracts
    – Foxxxey
    Jul 16, 2023 at 13:56
  • Is it nova#5147?
    – 19216811
    Jul 17, 2023 at 8:31

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.