1

I'm trying to set up a distribution contract to send an ERC20 token to multiple addresses at the same time. After multiple attempts, the transfer keeps failing. Transactions are approved, the problem is that the contract seems to not be reading the addresses of the receivers, as it sends the tokens back to the distribution contract. I am testing it using the RopstenTesnet and Parity.

  • Steps to reproduce:

    1. Deploy Token Contract. Let's call the token TestToken ( See below for SC code).
    2. Replace Token Address on line 41 of the Distribution Contract (See below for SC code)
    3. Deploy Distribution Contract from the same address you deployed the token.
    4. Send some TestTokens to the Distribution Contract.

      • Here the Distribution Contract should say is active and show the amount of token you've send to the Contract. See picture enter image description here
    5. Execute the Distribution Contract

      • This is how I input the values: enter image description here
      • Here is where I get the error: enter image description here

Smart Contract of TestToken:

        pragma solidity ^0.4.11;

        library SafeMath {
          function mul(uint a, uint b) internal returns (uint) {
            uint c = a * b;
            assert(a == 0 || c / a == b);
            return c;
        }

        function div(uint a, uint b) internal returns (uint) {
          uint c = a / b;
          return c;
        }

        function sub(uint a, uint b) internal returns (uint) {
          assert(b <= a);
          return a - b;
        }

        function add(uint a, uint b) internal returns (uint) {
          uint c = a + b;
          assert(c >= a);
          return c;
        }
        function max64(uint64 a, uint64 b) internal constant 
          returns (uint64) {
          return a >= b ? a : b;
        }
        function min64(uint64 a, uint64 b) internal constant returns (uint64) {
           return a < b ? a : b;
        }

        function max256(uint256 a, uint256 b) internal constant returns (uint256) {
           return a >= b ? a : b;
        }

        function min256(uint256 a, uint256 b) internal constant returns (uint256) {
          return a < b ? a : b;
         }

         function assert(bool assertion) internal {
            if (!assertion) {
                throw;
            }
           }
          }

         contract ERC20Basic {
           uint public totalSupply;
           function balanceOf(address who) constant returns (uint);
           function transfer(address to, uint value);
           event Transfer(address indexed from, address indexed to, uint value);
          }

         contract ERC20 is ERC20Basic {
           function allowance(address owner, address spender) constant returns (uint);
           function transferFrom(address from, address to, uint value);
           function approve(address spender, uint value);
           event Approval(address indexed owner, address indexed spender, uint value);
           }
          contract BasicToken is ERC20Basic {
            using SafeMath for uint;

            mapping(address => uint) balances;

            modifier onlyPayloadSize(uint size) {
               if(msg.data.length < size + 4) {
                  throw;
                }
                _;
             }

          function transfer(address _to, uint _value) onlyPayloadSize(2 * 32){
            require(_to != address(0)); //prevents 0x0 address
            balances[msg.sender] = balances[msg.sender].sub(_value);
            balances[_to] = balances[_to].add(_value);
            Transfer(msg.sender, _to, _value);
           }
          function balanceOf(address _owner) constant returns (uint balance) {
             return balances[_owner];
            }

           }

        contract StandardToken is BasicToken, ERC20 {

          mapping (address => mapping (address => uint)) allowed;

         function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32){

           require(_to != address(0)); //prevents 0x0 address
           require(_value <= balances[_from]);

           var _allowance = allowed[_from][msg.sender];
           balances[_to] = balances[_to].add(_value);
           balances[_from] = balances[_from].sub(_value);
           allowed[_from][msg.sender] = _allowance.sub(_value);
           Transfer(_from, _to, _value);
          }
          function approve(address _spender, uint _value) {

          if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw;

          allowed[msg.sender][_spender] = _value;
          Approval(msg.sender, _spender, _value);
         }
         function allowance(address _owner, address _spender) 
          constant returns (uint remaining) {
          return allowed[_owner][_spender];
          }

        }

        contract TestToken is StandardToken {

           string public name = "TestToken";
           string public symbol = "TT";
           uint public decimals = 15;
           uint public INITIAL_SUPPLY = 100000000000000000000000; // initia supply is 100,000,000

           function TestToken() {
           totalSupply = INITIAL_SUPPLY;
           balances[msg.sender] = INITIAL_SUPPLY;
          }
         }

Smart Contract Distribution

     pragma solidity ^0.4.16;

     contract Ownable {

       address public owner;

       function Ownable() {
       owner = msg.sender;
      }

       modifier onlyOwner() {
        require(msg.sender == owner);
       _;
      }

       function transferOwnership(address newOwner) onlyOwner {
         require(newOwner != address(0));
         owner = newOwner;
        }
       }

       interface Token {
         function transfer(address _to, uint256 _value) returns (bool);
         function balanceOf(address _owner) constant returns (uint256 balance);
        }
       contract Distribution is Ownable {

         Token token;

         event TransferredToken(address indexed to, uint256 value);
         event FailedTransfer(address indexed to, uint256 value);

         modifier whenDistributionIsActive() {
            assert(isActive());

           _;
          }

        function Distribution () {
        address _tokenAddr = 0xa7a13cf0ae06a743fd464a9565af38c146a7d14d ; //here pasyr address of  token
         token = Token(_tokenAddr);
        }

       function isActive() constant returns (bool) {
         return (
             tokensAvailable() > 0
           );
         }

        function sendTokens(address[] dests, uint256[] values) whenDistributionIsActive onlyOwner external {
           uint256 i = 0;
           while (i < dests.length) {
              uint256 toSend = values[i] * 10**15;
              sendInternally(dests[i] , toSend, values[i]);
              i++;
             }
            }
        function sendTokensSingleValue(address[] dests, uint256 value) whenDistributionIsActive onlyOwner external {
          uint256 i = 0;
          uint256 toSend = value * 10**15;
          while (i < dests.length) {
             sendInternally(dests[i] , toSend, value);
             i++;
            }
           }

        function sendInternally(address recipient, uint256 tokensToSend, uint256 valueToPresent) internal {
           if(recipient == address(0)) return;

           if(tokensAvailable() >= tokensToSend) {
             token.transfer(recipient, tokensToSend);
             TransferredToken(recipient, valueToPresent);
           } else {
             FailedTransfer(recipient, valueToPresent);
            }
          }

             function tokensAvailable() constant returns (uint256) {
               return token.balanceOf(this);
              }

             function destroy() onlyOwner {
               uint256 balance = tokensAvailable();
               require (balance > 0);
               token.transfer(owner, balance);
               selfdestruct(owner);
               }
              }

Ropsten Transaction log:

  1. Token:0x435aFeceC27E01ba33ef62a57d17FB1d17057930
  2. Distribution: 0x85a65cC398Dd981c616003D6CDe9d58C00777231
  3. Token and Distribution Owner:0x0013d98B46e5528323dB3E89E5e1380eea7452D2
  4. Attempted Recipient:0x00B375c46838912Fd43bEde3A794C9799f168f92
  5. Attempted Transaction 1: 0x31a5087cff3c7ad305fbbc380e4060be0c4b9563cc4fbe8ae1ef41958784c8c7
  6. Attempted Transaction 2: 0x6538486b3929535fae678202492e1a20e63f96a077ba0b3ff3b28ddb283ad36c

Thank you in advance! Please let me know if you have any questions about the process. Thanks guys!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.