-
Notifications
You must be signed in to change notification settings - Fork 29
Out of gas in implementation will not "propagate" to proxy #51
Comments
I pushed a potential solution to https://github.com/zeppelinos/zos-lib/tree/feature/out-of-gas-errors. The idea would be to change the delegate code in the proxy to the following: function _delegate(address implementation) internal {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize)
// Store how much gas we have available
let availablegas := gas
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
// Assume we are out of gas if we have under 1/64 of gas remaining
// TODO: Fine-tune this formula to account for additional cost of delegatecall itself
let outofgas := lt(gas, div(availablegas, 64))
// Copy the returned data.
returndatacopy(0, 0, returndatasize)
switch result
// delegatecall returns 0 on error.
case 0 {
switch outofgas
case 0 { revert(0, returndatasize) }
case 1 { for { } 1 { } { } }
}
default {
return(0, returndatasize)
}
}
} The idea is that, if the That said, I'd suggest against implementing this feature. Returning out-of-gas from a call is an added feature from the node, not part of the EVM itself, and is lost among regular calls. For instance, given this code: contract Gassy {
uint256 i;
function gassy() public {
while(true) { i = i + 1; }
}
function throws() public {
i = 10;
assert(false);
}
}
contract ManualProxy {
Gassy gassy;
function ManualProxy() {
gassy = new Gassy();
}
function callGassy() {
gassy.gassy();
}
function callThrow() {
gassy.throws();
}
} Given an instance
This means that regular calls completely miss the out of gas or invalid opcode errors, since Solidity itself only checks the return value of a As such, I recommend not trying to add a feature not even present in Solidity, and keep the same behaviour of just The only argument for implementing this would be to make the proxy as transparent as possible, from the point of view of a client interacting with it. I'd appreciate any comments here @frangio @facuspagnuolo. |
Great analysis, @spalladino. Unless someone shows a realistic example where it's a problem, I think I'm almost convinced that we should not implement this. Some remaining questions I'd like to see answered:
|
Thanks for the job @spalladino! I do agree with your conclusion, I don't see the point to simulate OOG errors when even Solidity is not doing it. Nit comment regarding the solution, I'd try to perform the |
I wanted to avoid the gas from |
Closing as discussed. Will keep the code here though for future reference. |
The Proxy contract calls
delegatecall
to some other implementation which may run out of gas. In that case, the proxy willrevert
. It will probably still have gas left because thedelegatecall
(like normalcall
) only forwards a fraction of the gas left to the callee (see EIP-150). Therefore, there is some information lost for the caller of the proxy: they cannot see that the call ran out of gas.I think this is part of a bigger problem of the platform which is that there is no way of knowing whether a transaction failed because of running out of gas or some other reason.
We want to consider making the proxy "run out of gas" if the
delegatecall
failed and it consumed all available gas, so as to propagate this information upwards the call chain. It's not clear if or how this could be done.The text was updated successfully, but these errors were encountered: