← CTF

Ethernaut

EthernautJune 2025GitHub ↗

Ethernaut is OpenZeppelin’s smart-contract wargame. Each level hands you a vulnerable contract and you have to break it. I played through it for fun, and my attack contracts for each level I solved, up to and including GatekeeperOne, are in the repo.

Levels

LevelWhat I exploited
Coin FlipThe “randomness” comes from blockhash, so a contract calling in the same block can predict it
TelephoneThe contract checks tx.origin when it should check msg.sender
TokenUnchecked integer underflow (pre-0.8 arithmetic)
Delegationdelegatecall runs my code inside the victim’s storage
Forceselfdestruct pushes ETH into a contract that has no receive
Vault“Private” storage can still be read on-chain
KingA receiver that reverts, so nobody can ever take the throne back
Re-entrancyThe contract makes the external call before it updates balances
ElevatorAn interface that gives different answers to the same call
GatekeeperOneBrute-forcing gasleft() % 8191 and building a key out of type-casting rules

GatekeeperOne

This was the last level I did. The third gate wants a bytes8 key whose uint32, uint16 and uint64 truncations satisfy a chain of equalities tied to tx.origin. Masking my own address gives the key:

bytes8 key = bytes8(uint64(uint160(address(msg.sender)))) & 0xFFFFFFFF0000FFFF;
(bool success,) = gatekeeper.call{gas: gas}(abi.encodeWithSignature("enter(bytes8)", key));

The second gate needs gasleft() to be a multiple of 8191 at the moment it’s checked, so I swept the gas argument until a call went through.