1

I compiled smart contract in solidity on remix.ethereum.org. I made account via MetaMask and want to let other addresses send tokens to themselves using ropsten network. I mean - I am contract owner = A, transfer some tokens to B and let him transfer/withdraw his tokens to address C. There are two transfer functions:

  • transfer, send tokens from contract owner to receiver address and it's working properly
  • transferFrom, is causing problems, send tokens from B to C. I tried to use it via remix, write contract on etherscan and with web3.py but all of them return error.

Firstly I deployed contract with 1000000 tokens (1000.000 with 3 decimals) and sent 1000 (1.000) tokens to B (balanceOf(B) returned 1000), then called approve function with 1000 tokens for B address (allowance returned 1000), and called transferFrom, which threw errors:

  • remix: "Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? gas required exceeds allowance (8000029) or always failing transaction"
  • MetaMask on etherscan: "ALERT: Transaction Error. Exception thrown in contract code."

Another weird thing is sending tokens via transferFrom function from contract owner's address works properly like normal transfer. Also transfer exaclty 0 tokens from B to C works normally. I can not figure out what is wrong, below is contract code:

pragma solidity >=0.4.22 <0.7.0;

contract AnotherCoin {

    string public constant name = "AnotherCoin";
    string public constant symbol = "ATC";
    uint8 public constant decimals = 3;  


    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
    event Transfer(address indexed from, address indexed to, uint tokens);


    mapping(address => uint256) balances;

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

    uint256 totalSupply_;

    using SafeMath for uint256;


    constructor(uint256 total) public {  
        totalSupply_ = total;
        balances[msg.sender] = totalSupply_;
    }  

    function totalSupply() public view returns (uint256) {
        return totalSupply_;
    }

    function balanceOf(address tokenOwner) public view returns (uint) {
        return balances[tokenOwner];
    }

    function transfer(address receiver, uint numTokens) public returns (bool) {
        require(numTokens <= balances[msg.sender]);
        balances[msg.sender] = balances[msg.sender].sub(numTokens);
        balances[receiver] = balances[receiver].add(numTokens);
        emit Transfer(msg.sender, receiver, numTokens);
        return true;
    }

    function approve(address delegate, uint numTokens) public returns (bool) {
        allowed[msg.sender][delegate] = numTokens;
        emit Approval(msg.sender, delegate, numTokens);
        return true;
    }

    function allowance(address owner, address delegate) public view returns (uint) {
        return allowed[owner][delegate];
    }

    function transferFrom(address owner, address buyer, uint numTokens) public payable returns (bool) {
        require(numTokens <= balances[owner]);    
        require(numTokens <= allowed[owner][msg.sender]);

        balances[owner] = balances[owner].sub(numTokens);
        allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
        balances[buyer] = balances[buyer].add(numTokens);
        emit Transfer(owner, buyer, numTokens);
        return true;
    }
}

library SafeMath { 
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
      assert(b <= a);
      return a - b;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
      uint256 c = a + b;
      assert(c >= a);
      return c;
    }
}

I tried compile it on different compiler versions (4.x, 5.x, 6.x) and compilation was succesfull but this single function throw errors. Similiar topics on stack didn't bring the solution.

  • Who does call approve function? Who does call transferFrom? – Ismael Apr 14 at 1:08
  • Both are called by contract owner – WR10 Apr 14 at 7:08
0

So I tried the following thing:

Made your mappings public to see what was happening. After using the approve function where owner was 'A' and delegate was 'B', I checked the allowed mapping and it was still showing 0. So after using approve 2nd time, the mapping was updated(I don't know why) and then I used the transferFrom where owner was 'A', buyer was 'C' and amount was equal to approved amount. The address calling transferFrom was 'B' and it was successful.

You are getting this error because: The mapping is not being updated properly.

Hope this helped

| improve this answer | |
  • I am fresh in this whole thing so let me clear. I am testing and calling all these functions from remix IDE as owner 'A', I guess. If transferFrom where owner was 'A', buyer was 'C' are called by 'B' from which address are substracted tokens? – WR10 Apr 14 at 7:55
  • I changed mappings to public, approved 1000, called allowed - returned 1000 but transferFrom failed. – WR10 Apr 14 at 8:25
  • Tokens are subtracted from owner 'A'. Approve means token owner(in this case 'A') allows someone else (in this case 'B') to transfer his token by someone else – Hackeerrrr Apr 14 at 8:38
  • Try the following: Open your remix ide and deploy the contract with the 1st address(let's call it A). Now call the apporve function where delegate is address 2(let's call it B). Now call allowed function where address1 = A and address2 = B.Call it and see the output. It must be nonzero. If it is, then call transferFrom with address B where owner = A, buyer = some other address , numTokens = approved token number – Hackeerrrr Apr 14 at 8:46
  • Sorry but I don't know how to call function as B, I don't own this address and don't have its private key. – WR10 Apr 14 at 9:55

Your Answer

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

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