This is re ‘Gatekeeper One’ challenge on Ethernaut: https://ethernaut.openzeppelin.com/level/0x9b261b23cE149422DE75907C6ac0C30cEc4e652A
The enter
function has a modifier that requires gasleft
to be a multiple of 8191 at that point:
modifier gateTwo() {
require(gasleft().mod(8191) == 0);
_;
}
The sample solution loops through a range of likely gas values and uses those as an argument to call.gas:
bytes memory encodedParams = abi.encodeWithSignature(("enter(bytes8)"),
key
);
// gas offset usually comes in around 210, give a buffer of 60 on each side
for (uint256 i = 0; i < 120; i++) {
(bool result, bytes memory data) = address(GatekeeperOneContractAddress).call.gas(
i + 150 + 8191 * 3
)(
encodedParams
);
if(result)
{
break;
}
}
}
Now, that works. But if I try to call enter
using a different syntax:
GatekeeperOne gatekeeper = GatekeeperOne(GatekeeperOneContractAddress);
for (uint256 i = 0; i < 120; i++) {
bool result = gatekeeper.enter{gas:i + 150 + 8191 * 3}(key);
if(result)
{
break;
}
}
It fails. Meaning the execution is reverted because (I suppose) one of the requirements is not passed. How is this way of calling different? I am specifying the same amount of gas, am I not?