5

I have read a number of posts about making calls between contracts, but I can't get this simple example to work that involves two contracts that are already deployed on my private Ethereum blockchain.

The pattern I'm trying to create is:
i- 'Caller' receives call to 'proxyRequest' function
ii- Caller uses the the _target parameter and calls the 'registrationRequest' function at the supplied address.
iii- 'UserRegistered' event in 'CallMe' should fire.

But the problem is that the 'call' function in 'Caller' always returns false. Any pointers would be appreciated.

If I use Web3 and create a transaction that calls the 'registrationRequest' function directly in 'CallMe', then it works fine.

contract Caller
{
    event SendingTransaction(address indexed _requestor, uint8 indexed action);     

    address public minter;
    bytes public email;      // hash of the email address

    modifier onlyOwner {
    if (msg.sender != minter)
        throw;
       _;
    }

    function() {
        throw;
    }

    function Caller(bytes _email) {

        // constructor
        minter= msg.sender;
        email= _email;
    }

    function proxyRequest(address _target, string _payload) onlyOwner public {

        SendingTransaction(_target, 1);
        // Event fires OK when I subscribe to it via Web3 code.

        if (!_target.call("registrationRequest",_target, _payload))
        {
            SendingTransaction(_target, 2);
            // Event fires OK when I subscribe to it via Web3 code.
        }
        else
        {
            SendingTransaction(_target, 3);
            // Event NEVER fires
        }


    }

}

Second contract.

pragma solidity ^0.4.7;

contract CallMe
{
    event UserRegistered(address indexed _from, string _attr);

    address public minter;     // keep track of the entity that created the contract

    modifier onlyOwner {
        if (msg.sender != minter)
            throw;
        _;
    }

    function CallMe() {
        minter = msg.sender;
    }

    function() { 
        throw;
    }

    function registrationRequest(address _toAdd, string _code) {

        // this event fires ok if I invoke it via web3
        // this event DOES NOT fire ok if function invoked by 'Caller'
        UserRegistered(_toAdd, _code);
    }


    function getMinter() constant returns (address) {
        return minter;
    }
}

1 Answer 1

3

To call function from another contract you need to provide sha3 hash of function's signature (see solidity docs and this excellent answer):

_target.call(bytes4(sha3("registrationRequest(address,string)")), _target, _payload);

Another option is to explicitly convert address to CallMe:

CallMe cm = CallMe(_target);
cm.registrationRequest(_target, _payload);

Please note the difference: _target.call(..) returns false if call was not successful, while cm.registrationRequest(..) throws an exception.


Here is a script to run a test with node.js and testrpc. You can see that UserRegistered is fired and SendingTransaction(_target, 3) is fired too.

$ node test.js 
callme 0xf29c07da3e712ccda8fac94a9af499774bdbeeaa
caller 0x56157bb7ee83e749b5368f4c47ffc406fc653e5a
SendingTransaction { _requestor: '0xf29c07da3e712ccda8fac94a9af499774bdbeeaa',
  action: { [String: '1'] s: 1, e: 0, c: [ 1 ] } }
SendingTransaction { _requestor: '0xf29c07da3e712ccda8fac94a9af499774bdbeeaa',
  action: { [String: '3'] s: 1, e: 0, c: [ 3 ] } }
UserRegistered { _from: '0xf29c07da3e712ccda8fac94a9af499774bdbeeaa',
  _attr: '' }

But there is a problem with _attr argument not showing in UserRegistered event. This is due to Solidity's limitation on passing variable-sized arguments.

4
  • I tried out the _target.call(bytes4(sha3("registrationRequest(address,string)")), _target, _payload); but could not get it to work. I also tried using bytes32 instead of string but could also not get it to work. Jan 11, 2017 at 5:18
  • This may be the case, I have not tried to compile/run the code (and is not able to do this right now). Can you please give me more details on what actually does not work? UserRegistered is not fired? Jan 11, 2017 at 5:36
  • Yup. UserRegistered is not fired. I tried call, callcode and delegatecall - see ethereum.stackexchange.com/questions/3667/… . Jan 11, 2017 at 5:39
  • 1
    Just tested and it's ok. Please see updated answer. Jan 11, 2017 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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