2

I know that if I use call from a contract, that I cannot get the return value. I get a true or a false.

Is it possible for me to inspect the blockchain afterwords to get the return value?

For example, if the function that I CALL creates an new contract and returns the address, can I endow the the mined block and find the address of the created contract?

What if it returned a uint?

How would I do this? Web3?

I've created a blog post that shows a bit of what I'm trying to accomplish here: http://catallax.info/news/2017/6/8/calling-future-contracts-from-contracts-in-ethereum-dev-log-6

Austin Fatheree
  • 409
  • 6
  • 11
  • They current way to do this in solidity is to use events, your contract generates an event with the address generated. See https://ethereum.stackexchange.com/q/12950. Another way is to inspect the execution of your contract with debug_traceTransaction but it is way more involved. – Ismael Jun 07 '17 at 02:18
  • That would require the other contract to have implemented an event. Obviously this would be a best practice, but not a surety. – Austin Fatheree Jun 07 '17 at 11:35
  • Were you able to resolve this? Is there a finalized solution posted somewhere? – LampShade Jun 16 '20 at 03:15

2 Answers2

2

Low-level calls are just a tiny bit above inline assembly, so you can use inline assembly to emulate this feature.

Something like this:

function get(address _addr, string _func) public view returns (bytes data) {
    uint len = 32;
    uint ptr;

    bytes4 sig = bytes4(keccak256(_func));
    assembly {
        ptr := mload(0x40)       
        mstore(ptr, sig)

        let result := call(5000, _addr, 0, ptr, 0x4, ptr, add(len, 0x40))

        if eq(result, 0) {
            revert(0, 0)
        }

        ptr := add(ptr, 0x40)
        mstore(0x40, add(ptr, add(len, 0x40)))
    }

    data = toBytes(ptr, len); 
}

function toBytes(uint _addr, uint _len) internal pure returns (bytes memory bts) {
    bts = new bytes(_len);
    uint btsptr;
    assembly {
        btsptr := add(bts, 0x20)
    }
    copy(_addr, btsptr, _len);
}
Aquila
  • 1,812
  • 1
  • 10
  • 23
  • Can you clarify what the copy(_addr, btsptr, _len); line does? copy isn't a real command in solidity. What does that function do exactly? – LampShade Jun 16 '20 at 03:15
0

There is an inline assembly function delegatecall(g, a, in, insize, out, outsize) identical to callcode, which output the return value to mem[out..(out+outsize)), For more details , you can see https://solidity.readthedocs.io/en/v0.4.24/assembly.html.

If you just want to call but not the delegatecall, you can define an interface of your target contract and get the result directly.

pragma solidity ^0.4.24;
contract Remote{
    function A() public returns (uint){
        return uint(12345);
    }
}
/*-------------------local-----------------------*/
interface remote{
    function A() external returns(uint);
}
contract local{
    remote r;
    uint b;
    constructor(address _remote) public {
        r = remote(_remote);
    }
    function cal() public view returns(uint){
        return r.A()+1;
    }
}
Ismael
  • 30,570
  • 21
  • 53
  • 96
tonis
  • 1
  • 1