5

I'm trying to call the transfer() function on an ERC20 token through the use of delegatecall, my proxy contract however returns false from delegatecall.

When I try to call view functions like balanceOf() my proxy contract returns true. However since there are no possible exceptions in the balanceOf function I would also get 'true' even when returned "0" instead of "100000"

Token contract gets deployed through the constructor of the proxy contract. The owner of the token contract is the proxy contract. When deployed the proxy contract will mint 10000 tokens for the creator.

The imported token.sol contract is from open-zeppelin and works on its own.

pragma solidity ^0.4.20;

import './token.sol';

contract Test {
    Token public token;
    constructor () {
        token = new Token("Test", "TST", 18);
        token.mint(msg.sender, 10000);
    }

    function call(address _to, uint256 _value) returns (bool) {
       return  address(token).delegatecall(bytes4(sha3('transfer(address, uint256)')), _to, _value);
    }
} 


status  0x1 Transaction mined and execution succeed  
decoded input   {
        "address _to": "0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C",
        "uint256 _value": "50"
    }
decoded output  {
        "0": "bool: false"
    }
2

I think you are misunderstanding the purpose of delegatecall(). It executes the called contract in the context of the calling contract.

In other words, it will use the code from the called contract, but the msg and storage from the calling contract. Since it only has access to the calling contract's storage, it can't look up or modify balances or anything else about the token itself.

Depending on your goals, you may want to use the allowance functionality of the token instead.

  • Right, as I understood it it would preserve the msg object but that's only the case for contract accounts then? Is there no way to preserve the original user address that called the function? I know about the allowance and transferFrom methods but It seemed like a 'dull' workaround. – Nico May 25 '18 at 21:34
  • 1
    It does preserve the user address. The problem is that the storage is preserved, too. So, the token contract tries to look up the balance etc. in the storage of your Test contract, not in the actual token contract. Since those variables simply don't exist in the Test contract, all such lookups will probably result in a 0. – mafrasi2 May 25 '18 at 22:12

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.