1
pragma solidity ^0.5.3;

contract SimpleFallback{
    event FallbackCalledEvent(bytes data);
    event AddEvent(uint a, uint b, uint result);
    event DoubleEvent(uint a, uint b);
    event GetNameEvent(string);

    function() external{
        emit FallbackCalledEvent(msg.data);
    }

    function add(uint a, uint b) public returns(uint){
        // assert(a >= 0);
        // assert(b >= 0);
        // assert(a + b > a && a + b > b);

        uint _result = a + b;
        emit AddEvent(a, b, _result);

        return _result;
    }

    function double(uint a) public returns(uint){
        // assert(a >= 0);
        // assert(2*a >= 0 && 2*a >= a);
        uint _result = 2*a;

        emit DoubleEvent(a, _result);

        return _result;
    }

    function getName(string memory name) public returns(string memory){
        emit GetNameEvent(name);

        return name;
    }
}


contract RunTest{


    function callAddlTest(address other) public {
        // bytes4 messageId = bytes4(keccak256("add(uint, uint)"));
        // other.call(messageId, 5, 60);
        other.call(abi.encodeWithSignature("add(uint,uint)", 85, 60));
    }

    function callDoublelTest(address other) public {
        // bytes4 messageId = bytes4(keccak256("add(uint, uint)"));
        // other.call(messageId, 5, 60);
        other.call(abi.encodeWithSignature("double(uint)", 100));
    }

    function callgetNameTest(address other) public{
        other.call(abi.encodeWithSignature("getName(string)", "hello"));
    }
}

Operation as below.

  • Step 1. deploy 2 contracts;
  • Step 2. call callAddlTest whit contract SimpleFallback's address, event log is as below, which showed that called add() failed, the fallback function was triggered.
[
    {
        "from": "0x038f160ad632409bfb18582241d9fd88c1a072ba",
        "topic": "0x5cd57a899be814fb3a40e18f9d1ba77420bbd22073d35165511f750aa70538b6",
        "event": "FallbackCalledEvent",
        "args": {
            "0": "0xb89663520000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000003c",
            "data": "0xb89663520000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000003c",
            "length": 1
        }
    }
]
  • Step 3. call callDoubleTest whit contract SimpleFallback's address, event log is as below, which showed that called double() failed, the fallback function was triggered.
[
    {
        "from": "0x038f160ad632409bfb18582241d9fd88c1a072ba",
        "topic": "0x5cd57a899be814fb3a40e18f9d1ba77420bbd22073d35165511f750aa70538b6",
        "event": "FallbackCalledEvent",
        "args": {
            "0": "0xd524bc570000000000000000000000000000000000000000000000000000000000000064",
            "data": "0xd524bc570000000000000000000000000000000000000000000000000000000000000064",
            "length": 1
        }
    }
]
  • Step 4. call callgetNameTest whit contract SimpleFallback's address, event log is as below, which showed that called getName() successfully.

    {
        "from": "0x038f160ad632409bfb18582241d9fd88c1a072ba",
        "topic": "0x26c73f7f14382f5db0b9f94dd29ff8938f2e4be69fb13e0825ece287e8e538d5",
        "event": "GetNameEvent",
        "args": {
            "0": "hello",
            "length": 1
        }
    }
]

Question:

for call(abi.encodeWithSignature()), why: - 1)other.call(abi.encodeWithSignature("add(uint,uint)", 85, 60)); did not work? - 2)other.call(abi.encodeWithSignature("double(uint)", 100)); did not work? - 3)other.call(abi.encodeWithSignature("getName(string)", "hello")); did work? - 4) does encodeWithSignature not support multiple parameters, compared 1) and 3)? and does encodeWithSignature not support a uint parameters, compared 2) and 3)?

1

I already found out the root cause. It should use the full names of the types, not their aliases, so it should be uint256 instead of uint.

  • OMG, thank you for this. I just spent ~3 hours trying to understand why my staticcall is always failing. – TripleSpeeder Apr 9 '19 at 6:36
  • I think encodeWithSignature shuold provide better friendly interface, fox example, abi.encodeWithSignature("add(uint,uint)") and abi.encodeWithSignature("add(uint, uint)") are two different function signature, just because of spaces. – Yannick Apr 9 '19 at 6:42

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.