Gnosis' MultiSig Wallet substract a fixed amount of gas (34710) when calling an external address.
function external_call(address destination, uint value, uint dataLength, bytes data) internal returns (bool) {
bool result;
assembly {
let x := mload(0x40) // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that
result := call(
sub(gas, 34710), // 34710 is the value that solidity is currently emitting
// It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
// callNewAccountGas (25000, in case the destination address does not exist and needs creating)
destination,
value,
d,
dataLength, // Size of the input (in bytes) - this is what fixes the padding problem
x,
0 // Output is ignored, therefore the output size is zero
)
}
return result;
}
It seems to reserve some gas for the worst case scenario. But it causes strange behavior in some circumstances.
- gas available less than 34710:
sub()
will overflow, but EVM fill cap gas to the max available, so the call may succeed. - gas available slightly more to 34710:
sub()
returns a small amount of thas that will make the inner call to fail with out of gas.
Is there any reason for doing that instead of just sending all available gas?
estimateGas
would give you an underestimate on this function (more accurately, since this function isinternal
, on each one of the functions which call it).