I am trying to accept ERC20 Tokens as payment in a contract. As I understand it the sender will have to use the approve function to give my contract an allowance first. So far so good. What I do not understand is how does my contract call the transferFrom function to credit itself.

Specifically I want to test if the 'allowance' approved for my contract is equal to a value and if the remaining balance of the sender is equal or greater than my contract's allowance. Conditionally to that I want to execute the 'transferFrom' function of the ERC20 Token.

I am trying to do the following:

if (
         && _Token.call(bytes4(sha3("allowance(owner, this)"))) = 100
         && _Token.call(bytes4(sha3("balanceOf(owner)"))) >= 100
         _Token.call(bytes4(sha3("transferFrom(owner, this, 100)")));

But the Myst compiler says Expected primary expression.

 && _Token.call(bytes4(sha3("allowance(owner, this)"))) = 100

Many thanks.

2 Answers 2


Your code fragment has a _Token variable, which you're treating as a generic address (using call() on it). If you know that this address is an ERC20 token, you can use Solidity to cast that variable to the appropriate type, and then it's a more intuitive function call, rather than figuring out signature hashes:

contract ERC20Token {
  function transferFrom(address from, address to, uint value);

contract MyContract {
  function myFunction(address tokenAddr) {
    ERC20Token tok = ERC20Token(tokenAddr);
    tok.transferFrom(_owner, _recipient, 100);
  • This is of course right, but beware that implementing contract's interfaces can bloat your contract real quick and thus cause higher gas costs, so use with caution.
    – n1cK
    Commented Jun 7, 2017 at 12:10
  • Thanks, @NikitaFuchs; I was unaware of that. Could you provide more details/links on that? Is it a shortcoming in how Solidity compiles the code (and might be fixed in future compiler versions), or should the other form be used in all situations where possible, to save on gas cost? Commented Jun 7, 2017 at 16:33
  • The above form ensures type safety, but if you have lots of instances of a contract to deploy, you should go with function signature sending. Expect frustrating debugging here and there, because the slightest typo in doing it "the raw" way will cause the call tof ail, and there is almost no info on went wrong. you just have to stick to the syntax 200%.
    – n1cK
    Commented Jun 7, 2017 at 17:57
  • Nikita: After playing with this a fair bit I found that the only thing you need to define in your interface are the function signatures with no need to implement the actual functions in the contract. Works well for me.
    – Steve
    Commented Jul 12, 2017 at 7:39

First, you need to be aware that calls only return a true or false in solidity, as they basically just invoke a transaction with a function call to another contract. There is, at least to my knowledge, no way to have data returned like that, in solidity. The only thing you can do is have such a function call trigger another function, which in it's turn sets some var in your calling contract, which you then in turn can use.

Second, in your call parameter, you have to provide a function identifier, which is a hash of the function name and it's datatypes. so assuming your target function takes an integer and an address, you go by

bool success;
success = _Token.call(bytes4(sha3 ("allowance(uint256,address)") ), someInteger, someAddress)
if (!success) { throw; // or something else}

and for the hash string.... don't forget to pack things tightly!

Good luck!

  • Thanks for that. I was under the impression that you can get the value as long as you know the ABI details. Of course I have little to no Idea what I am talking about. If the standard functions in the ERC20 Token standard do not return data, what are they used for?
    – Steve
    Commented Jun 6, 2017 at 18:17
  • They do return data, but you cannot access storage data of a contract >from within other contracts< with solidity. Calling the functions to get some data out of a contract the "conventional way" is just fine ;)
    – n1cK
    Commented Jun 7, 2017 at 12:08
  • .call actually returns 2 values. The first is a boolean success and the second one is bytes memory data. So indeed there is a way to return data from a call. Your second line should look like this: (bool success, bytes memory data) = _Token.call(bytes4(sha3 ("allowance(uint256,address)") ), someInteger, someAddress) Or just (bool success,) = _Token.call(bytes4(sha3 ("allowance(uint256,address)") ), someInteger, someAddress) if you don't need the returned data
    – BonisTech
    Commented Oct 8, 2022 at 19:58

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.