6

How does one specify gas or value making a call this way:

contract AbstractB {
    function getX() returns(uint);
}

contract A {
    function makeCall(address addressB){
         AbstractB(addressB).getX();
    }
}

The following doesn't work(Error: Member "gas" not found...):

AbstractB(addressB).gas(0).getX();
4

EDIT: I upvoted and recommend @Xavier's answer (@BokkyPooBah's answer is missing () at the end).

It's more type-safe and here's an example showing the return value of getX. You do need to provide non-zero gas:

contract AbstractB {
    function getX() returns(uint) {
        return 3;
    }
}

contract A {
    function makeCall(address addressB) returns(uint) {
        return AbstractB(addressB).getX.gas(1000)();
    }
}

OLD: Use call.gas(g).value(v)(methodId, args) syntax. Not recommended because not type-safe and you don't get the return value of getX.

Example: addressB.call.gas(0).value(1 ether)(bytes4(sha3("getX()")));

Complete example, which should always checks the return value of call:

contract AbstractB {
    function getX() returns(uint);
}

contract A {
    function makeCall(address addressB){
         if (!addressB.call.gas(0).value(1 ether)(bytes4(sha3("getX()")))) {
             throw;
         }
    }
}
  • thank you very much, good sir!!! I guess, it also means that there's no point in having AbstractB contract at all there? – manidos Aug 22 '16 at 9:34
  • 2
    Yes, but actually the other answers that use AbstractB are safer for type-safety. – eth Aug 22 '16 at 9:36
4

AbstractB(addressB).getX.gas(0)();

Notice the many parentheses: (0)()

2

Try the following:

contract AbstractB {
    function getX() returns(uint);
}

contract A {
    function makeCall(address addressB) {
        AbstractB(addressB).getX.value(1 ether).gas(0);
    }
}

EDIT: As noted by the other answers to this question, the code AbstractB(addressB).getX.value(1 ether).gas(0); above is incorrect and should be replaced by:

        AbstractB(addressB).getX.value(1 ether).gas(0)();
1

I've compiled these two contracts using solidity online compiler. I've changed only one line.

  • AbstractB(addressB).getX.gas(0); @BokkyPooBah solution

  • AbstractB(addressB).getX.gas(0)(); @xavier-leprêtre solution

And got massively different bytecodes:

6060604052601e8060106000396000f3606060405260e060020a60003504637ff76d728114601a575b005b601856

vs

606060405260848060106000396000f3606060405260e060020a60003504637ff76d728114601a575b005b60186004357f5197c7aa00000000000000000000000000000000000000000000000000000000606090815273ffffffffffffffffffffffffffffffffffffffff821690635197c7aa906000906064906020906004818588803b1560025787f115600257505050505056


contract AbstractB {
    function getX() returns(uint);
}

contract A {
    function makeCall(address addressB){
         AbstractB(addressB).getX.gas(0);
    }
}

contract AbstractB {
    function getX() returns(uint);
}

contract A {
    function makeCall(address addressB){
         AbstractB(addressB).getX.gas(0)();
    }
}

I don't mind the difference in bytecode size, what's scary is that these contracts might have some behaviour differences. What's going on there?

  • 2
    The extra () is needed to make the actual call and obtain return a value. (Example in my edited answer.) – eth Aug 22 '16 at 10:01

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.