Let's suppose I have a simple delegatecall based relay contract. It looks up the contract implementation from a registry and passes the call to the upgradeable implementation:
contract Relay {
address public registrarAddr;
string public name;
function Relay(address _registrarAddr, string _name) {
registrarAddr = _registrarAddr;
name = _name;
}
function getImplAddr() constant returns (address) {
Registrar registrar = Registrar(registrarAddr);
return registrar.addr(name);
}
function() {
address currentVersion = this.getImplAddr();
if(!currentVersion.delegatecall(msg.data)) throw;
}
}
As you see the current function() {}
has a special check for delegatecall
return values, as this is based on an example code.
The question is, how delegatecall
handle return values? Can I modify this delegatecall
hook to perform normal web3 contract.call().balanceOf(addr)
style functions for reading public values from the implementation contract? Or if I set up a relay contract do I need to have special logic in place to read the data from the contract what I would normally do with call()
? Are there any examples of such arrangements?
Best Answer
delegatecall
is not supposed to handle return values as it cannot be aware of the length of the other side (unless there would be a dedicated parameter passed to it). Currently, thedelegatecall
Solidity built-in method does not support supplying the return value size, nor getting the return value out after the call.According to the documentation it should always return a boolean signaling the execution outcome. It seems the compiler may currently have a problem, see https://github.com/ethereum/solidity/issues/2678.
To get the result out, you will need to know the return value size and use inline assembly: