0

I am reading the source code of EVM. And want to imitate a contract remote call.

I made two contracts as below:

callee:

contract Called{
    uint public myuint;

    function set(uint _var) {
        myuint = _var;
    }

    function get() view returns (uint){
        return myuint;
    }
}

caller:

interface Called{
    function set(uint);
    function get() view returns (uint);
}

contract Caller {

    Called public called_address;

    function set_address(address _addy) {
        called_address = Called(_addy);
    }

    function set(uint256 _var) {
        called_address.set(_var);
    } 

    function set_call(address _called, uint256 _var) {
        require(_called.call(bytes4(sha3("set(uint256)")), _var));
    }
}

Then, my test code is as below :

...
contractCode, contractAddr, gasLeftover, vmerr := evm.Create(contractRef, data, total, big.NewInt(0))
...
// metaContractAddr is the contract address of callee. I got it after I called evm.Create(callee.bytecode).
input, err := abiObj.Pack("set_address", metaContractAddr)
must(err)
outputs, gasLeftover, vmerr := evm.Call(contractRef, contractAddr, input, statedb.GetBalance(fromAddress).Uint64(), big.NewInt(0))
must(vmerr)
fmt.Printf("output = %x\n", outputs)

input, err = abiObj.Pack("set", big.NewInt(100000))
must(err)
outputs, gasLeftover, vmerr = evm.Call(contractRef, contractAddr, input, statedb.GetBalance(fromAddress).Uint64(), big.NewInt(0))
must(vmerr)
fmt.Printf("output = %x\n", outputs)

The first call set_address went well, cause I can get it by calling called_address's getter method. But when calling input, err = abiObj.Pack("set", big.NewInt(100000)), error occured as below:

op = GAS, operation=vm.operation{execute:(vm.executionFunc)(0x4229840), gasCost:(vm.gasFunc)(0x4234140), validateStack:(vm.stackValidationFunc)(0x4234f20), memorySize:(vm.memorySizeFunc)(nil), halts:false, jumps:false, writes:false, valid:true, reverts:false, returns:false}
op = CALL, operation=vm.operation{execute:(vm.executionFunc)(0x422a220), gasCost:(vm.gasFunc)(0x4220e10), validateStack:(vm.stackValidationFunc)(0x4234f20), memorySize:(vm.memorySizeFunc)(0x4233310), halts:false, jumps:false, writes:false, valid:true, reverts:false, returns:true}
panic: out of gas

goroutine 1 [running]:
main.must(0x434ec20, 0xc420086ca0)
    main_icc.go:46 +0x4a
main.main()
    main_icc.go:132 +0x1581
exit status 2

From this error, I am sure that the caller's balance is definitely enough, which be assigned to 1e18.

Anyone helps? thanks in advance!

  • Out of gas is not really out of. the bytecode is wrong as far as I can conclude. It seems I can not use the callee's contract address from evm.Create. – Duan Bing Jun 4 '18 at 9:55
  • I modified the contract's method, add gas() method like this: function set(uint256 _var) { called_address.set.gas(300000)(_var); }, it seems work, but the _var doesn't persist after my test process quit. – Duan Bing Jun 4 '18 at 22:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.