{"id":16517849,"url":"https://github.com/erhant/ethernaut-evm-challenges","last_synced_at":"2026-05-12T17:40:44.097Z","repository":{"id":214643771,"uuid":"711314781","full_name":"erhant/ethernaut-evm-challenges","owner":"erhant","description":"Solutions to Ethernaut, EVM Puzzles and More EVM Puzzles; using Foundry.","archived":false,"fork":false,"pushed_at":"2024-01-08T12:32:45.000Z","size":257,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-13T06:43:19.811Z","etag":null,"topics":["ctf","ethereum","ethernaut","evm","evm-puzzles","foundry","puzzle","security"],"latest_commit_sha":null,"homepage":"https://ethernaut.openzeppelin.com","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/erhant.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-28T21:27:00.000Z","updated_at":"2024-01-08T15:21:07.000Z","dependencies_parsed_at":"2023-12-29T16:25:53.589Z","dependency_job_id":"d0ebc837-9dac-408a-8f60-2cf772ab513c","html_url":"https://github.com/erhant/ethernaut-evm-challenges","commit_stats":null,"previous_names":["erhant/ethernaut-evm-challenges"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erhant%2Fethernaut-evm-challenges","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erhant%2Fethernaut-evm-challenges/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erhant%2Fethernaut-evm-challenges/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erhant%2Fethernaut-evm-challenges/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erhant","download_url":"https://codeload.github.com/erhant/ethernaut-evm-challenges/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241564432,"owners_count":19982958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ctf","ethereum","ethernaut","evm","evm-puzzles","foundry","puzzle","security"],"created_at":"2024-10-11T16:33:59.685Z","updated_at":"2026-05-12T17:40:44.067Z","avatar_url":"https://github.com/erhant.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ethernaut \u0026 EVM Puzzles Solutions\n\nSolutions to Ethernaut, EVM puzzles and More EVM Puzzles in [Foundry](https://book.getfoundry.sh/), migrated \u0026 improved from my previous [solutions with Hardhat](https://github.com/erhant/solidity-ctfs).\n\nTo get started:\n\n```sh\nforge install\n```\n\nThen, see the solutions in action via:\n\n```sh\nforge test\n```\n\n\u003e [!NOTE]\n\u003e\n\u003e We are making use of the following libraries for Ethernaut, shown via their installation commands:\n\u003e\n\u003e ```sh\n\u003e forge install OpenZeppelin/ethernaut\n\u003e forge install openzeppelin-contracts-08=OpenZeppelin/openzeppelin-contracts@v4.7.3\n\u003e ```\n\n## [Ethernaut](https://ethernaut.openzeppelin.com/)\n\nWe use the original Ethernaut levels whenever possible, but there are a few exceptions as noted below. We also provide scripts to automatically solve \u0026 submit each problem, see [scripts](#scripts) section below.\n\n- [x] [Hello Ethernaut](./script/HelloEthernaut.s.sol)\n- [x] [Fallback](./script/Fallback.s.sol)\n- [x] [Fallout](./script/Fallout.s.sol)\u003csup\u003e\\* uses v0.8 instead of v0.6\u003c/sup\u003e\n- [x] [CoinFlip](./script/CoinFlip.s.sol)\n- [x] [Telephone](./script/Telephone.s.sol)\n- [x] [Token](./script/Token.s.sol)\u003csup\u003e\\* using v0.8 instead of v0.6\u003c/sup\u003e\n- [x] [Delegation](./script/Delegation.s.sol)\n- [x] [Force](./script/Force.s.sol)\n- [x] [Vault](./script/Vault.s.sol)\n- [x] [King](./script/King.s.sol)\n- [x] [Reentrance](./script/Reentrance.s.sol)\u003csup\u003e\\* using v0.8 instead of v0.6\u003c/sup\u003e\n- [x] [Elevator](./script/Elevator.s.sol)\n- [x] [Privacy](./script/Privacy.s.sol)\n- [x] [Gatekeeper One](./script/GatekeeperOne.s.sol)\n- [x] [Gatekeeper Two](./script/GatekeeperTwo.s.sol)\n- [x] [Naught Coin](./script/NaughtCoin.s.sol)\n- [x] [Preservation](./script/Preservation.s.sol)\n- [x] [Recovery](./script/Recovery.s.sol)\n- [x] [Magic Number](./script/MagicNum.s.sol)\n- [x] [Alien Codex](./script/AlienCodex.s.sol)\u003csup\u003e\\* requires v0.5, so we deploy bytecode via \u003ccode\u003eCREATE\u003c/code\u003e\u003c/sup\u003e\n- [x] [Denial](./script/Denial.s.sol)\n- [x] [Shop](./script/Shop.s.sol)\n- [x] [Dex](./script/Dex.s.sol)\n- [x] [Dex Two](./script/DexTwo.s.sol)\n- [x] [Puzzle Wallet](./script/PuzzleWallet.s.sol)\n- [x] [Motorbike](./script/Motorbike.s.sol)\u003csup\u003e\\* using v0.8 instead of v0.7 or below\u003c/sup\u003e\n- [x] [Double Entry Point](./script/DoubleEntryPoint.s.sol)\n- [x] [Good Samaritan](./script/GoodSamaritan.s.sol)\n- [x] [Gatekeeper Three](./script/GatekeeperThree.s.sol)\n- [x] [Switch](./script/Switch.s.sol)\n\n\u003e [!TIP]\n\u003e\n\u003e For my old write-ups using Hardhat, see [here](https://dev.to/erhant/series/18918).\n\n### Scripts\n\nWe have a script for each Ethernaut level that can check if it is solved, or actually solve \u0026 submit it given an instance.\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e We do not encourage running these scripts without even looking at the questions \u0026 trying them yourself. We only want these to be used so that you don't write everything from the console from scratch in the website!\n\u003e\n\u003e So please, try \u0026 solve the questions yourself before running these scripts!\n\n#### Running a Script\n\nFirst, write your credentials within an `.env` file, as shown in the `.env.example`. Then, on the Ethernaut website for some challenge, get a new instance and keep note of the level \u0026 instance address.\n\nYou can run scripts as shown below, with `\u003cLevel\u003e` corresponding to the level name as it appears in the file name. These scripts will run the attack on actual contracts on the blockchain.\n\n```sh\n# Check if the instance is solved\nsource .env \u0026\u0026 forge script ./scripts/\u003cLevel\u003e.s.sol:Check -f=$RPC_URL\n\n# Solve \u0026 submit instance\nsource .env \u0026\u0026 forge script ./scripts/\u003cLevel\u003e.s.sol:Solve -f=$RPC_URL --private-key=$PRIVATE_KEY\n```\n\n\u003e [!TIP]\n\u003e\n\u003e To actually do the transactions on-chain, just add `--broadcast` flag to the command.\n\u003e\n\u003e If things go right, you should see a tick-mark on Ethernaut website with the same wallet, meaning that your submitted solution was accepted!\n\n#### Edge Case: CoinFlip\n\nIn the CoinFlip level, we must deploy an attacker contract first and then call `flip()` on it on 10 different blocks. Foundry does not support this kind of behavior in a single script, as discussed in [this issue](https://github.com/foundry-rs/foundry/issues/1902).\n\nFor this reason, we must run the scripts for this level as follows:\n\n```sh\n# (1) deploy attacker\nsource .env \u0026\u0026 forge script ./scripts/CoinFlip.s.sol:Solve -f=$RPC_URL --private-key=$PRIVATE_KEY -s=\"deploy()\" --broadcast\n\n# (2) save attacker address to .env as:\nATKR_COINFLIP=\u003cattacker-address-here\u003e\n\n# (3) attack (do this 10 times)\nsource .env \u0026\u0026 forge script ./scripts/CoinFlip.s.sol:Solve -f=$RPC_URL --private-key=$PRIVATE_KEY -s=\"flip()\" --broadcast\n\n# (4) run the script as usual to submit the instance\nsource .env \u0026\u0026 forge script ./scripts/CoinFlip.s.sol:Solve -f=$RPC_URL --private-key=$PRIVATE_KEY --broadcast\n```\n\n#### Edge Case: Motorbike\n\nIn the Motorbike level, we use `selfdestruct` and the instance verification checks for the contract size of the self-destructed contract to see if it is 0. Due to how `selfdestruct` works, the contract size is only made 0 after the block is mined for that transaction, so in a single Foundry script we will not be able to see that effect, as per the [issue here](https://github.com/foundry-rs/foundry/issues/1902).\n\nFor this reason, the attack is in two steps:\n\n```sh\n# (1) deploy attacker\nsource .env \u0026\u0026 forge script ./scripts/Motorbike.s.sol:Solve -f=$RPC_URL --private-key=$PRIVATE_KEY -s=\"pwn()\" --broadcast\n\n# (2) run the script as usual to submit the instance\nsource .env \u0026\u0026 forge script ./scripts/Motorbike.s.sol:Solve -f=$RPC_URL --private-key=$PRIVATE_KEY --broadcast\n```\n\n#### Writing a Script\n\nHere is what a script looks like for some challenge called `LevelName`:\n\n```solidity\n// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {CheckScript} from \"./common/Check.sol\";\nimport {SolveScript} from \"./common/Solve.sol\";\nimport {LevelName} from \"ethernaut/levels/LevelName.sol\";\n\ncontract Check is CheckScript(\"LEVEL_NAME\") {}\n\ncontract Solve is SolveScript(\"LEVEL_NAME\") {\n    LevelName target;\n\n    constructor() {\n        target = LevelName(instance);\n    }\n\n    function attack() public override {\n        // the attack code within the test can be copy-pasted here!\n    }\n}\n```\n\nHere, you just have to write the attack within `attack` function, and it should \"just work\". The `SolveScript` also exposes a variable called `player` that holds your address as well.\n\n## [EVM Puzzles](https://github.com/fvictorio/evm-puzzles/)\n\n- [x] [Puzzle 1](./test/evm/MoreEVMPuzzles.t.sol#L7)\n- [x] [Puzzle 2](./test/evm/MoreEVMPuzzles.t.sol#L15)\n- [x] [Puzzle 3](./test/evm/MoreEVMPuzzles.t.sol#L23)\n- [x] [Puzzle 4](./test/evm/MoreEVMPuzzles.t.sol#L31)\n- [x] [Puzzle 5](./test/evm/MoreEVMPuzzles.t.sol#L39)\n- [x] [Puzzle 6](./test/evm/MoreEVMPuzzles.t.sol#L47)\n- [x] [Puzzle 7](./test/evm/MoreEVMPuzzles.t.sol#L53)\n- [x] [Puzzle 8](./test/evm/MoreEVMPuzzles.t.sol#L57)\n- [x] [Puzzle 9](./test/evm/MoreEVMPuzzles.t.sol#L65)\n- [x] [Puzzle 10](./test/evm/MoreEVMPuzzles.t.sol#L69)\n\n\u003e [!TIP]\n\u003e\n\u003e For my write-ups see [here](https://dev.to/erhant/evm-puzzles-walkthrough-471a).\n\n## [More EVM Puzzles](https://github.com/daltyboy11/more-evm-puzzles)\n\n- [x] [Puzzle 1](./test/evm/EVMPuzzles.t.sol#L7)\n- [x] [Puzzle 2](./test/evm/EVMPuzzles.t.sol#L11)\n- [x] [Puzzle 3](./test/evm/EVMPuzzles.t.sol#L15)\n- [x] [Puzzle 4](./test/evm/EVMPuzzles.t.sol#L20)\n- [x] [Puzzle 5](./test/evm/EVMPuzzles.t.sol#L24)\n- [x] [Puzzle 6](./test/evm/EVMPuzzles.t.sol#L28)\n- [x] [Puzzle 7](./test/evm/EVMPuzzles.t.sol#L33)\n- [x] [Puzzle 8](./test/evm/EVMPuzzles.t.sol#L37)\n- [x] [Puzzle 9](./test/evm/EVMPuzzles.t.sol#L43)\n- [x] [Puzzle 10](./test/evm/EVMPuzzles.t.sol#L47)\n\n\u003e [!TIP]\n\u003e\n\u003e For my write-ups see [here](https://dev.to/erhant/more-evm-puzzles-walkthrough-4lil).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferhant%2Fethernaut-evm-challenges","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferhant%2Fethernaut-evm-challenges","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferhant%2Fethernaut-evm-challenges/lists"}