This repo is intended for beginners to play OpenZeppelin's Ethernaut and write PoC (proof-of-concept) exploit codes with Foundry.
- Level01 Fallback
- Level02 Fallout
- Level03 Coin Flip
- Level04 Telephone
- Level05 Token
- Level06 Delegation
- Level07 Force
- Level08 Vault
- Level09 King
- Level10 Re-entrancy
- Level11 Elevator
- Level12 Privacy
- Level13 Gatekeeper One
- Level14 Gatekeeper Two
- Level15 Naught Coin
- Level16 Preservation
- Level17 Recovery
- Level18 MagicNumber
- Level19 Alien Codex
- Level20 Denial
- Level21 Shop
- Level22 Dex
- Level23 Dex Two
- Level24 Puzzle Wallet
- Level25 Motorbike
- Level26 DoubleEntryPoint
- Level27 Good Samaritan
- Level28 Gatekeeper Three
- Level29 Switch
The following challenges are not part of this repo:
Those challenges rely on old version of solidity to showcase bugs/exploits. Therefore, we'll remove them to prevent compilation errors.
curl -L https://foundry.paradigm.xyz | bash
foundryup
[email protected]:alex0207s/ethernaut-foundry-boilerplate.git
cd ethernaut-foundry-boilerplate
forge install
create a new test file XX-<LevelName>.t.sol
in the test/
directory.
Here's an example of a test contract for challenge 1 Fallback
pragma solidity ^0.8.10;
import "ds-test/test.sol";
import "forge-std/Vm.sol";
import "src/core/Ethernaut.sol";
import "src/levels/01-Fallback/FallbackFactory.sol";
contract FallbackTest is DSTest {
Vm vm = Vm(address(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D));
Ethernaut ethernaut;
address hacker = vm.addr(1); // generate the random address with given private key
function setUp() public {
ethernaut = new Ethernaut();
// set hacker's balance to 1 Ether, use it when you need!
// vm.deal(hacker, 1 ether);
}
function testFallbackHack() public {
/////////////////
// LEVEL SETUP //
/////////////////
FallbackFactory fallbackFactory = new FallbackFactory();
ethernaut.registerLevel(fallbackFactory);
vm.startPrank(hacker);
address levelAddress = ethernaut.createLevelInstance(fallbackFactory);
Fallback ethernautFallback = Fallback(payable(levelAddress));
//////////////////
// LEVEL ATTACK //
//////////////////
// implement your solution here
//////////////////////
// LEVEL SUBMISSION //
//////////////////////
bool levelSuccessfullyPassed = ethernaut.submitLevelInstance(
payable(levelAddress)
);
vm.stopPrank();
assert(levelSuccessfullyPassed);
}
}
setup()
function for initiating the main Ethernaut contracttest<LevelName>Hack()
function for- Creating a level instance
- Executing the attack logic to solve challenge
- Submitting the solution and validating your result
All you need to do is to implement your own PoC to solve the challenge in the LEVEL ATTACK block of test<LevelName>Hack()
function. You are allowed to create a malicious contract to exploit vulnerable contracts if you need to.
forge test --match-contract <LevelName>Test -v
You can obtain more detailed information on the summary of passing and failing tests by using the -v flag to increase verbosity.
- Level 2 (
-vv
): Logs emitted during tests are also displayed. That includes assertion errors from tests, showing information such as expected vs actual. - Level 3 (
-vvv
): Stack traces for failing tests are also displayed. - Level 4 (
-vvvv
): Stack traces for all tests are displayed, and setup traces for failing tests are displayed. - Level 5 (
-vvvvv
): Stack traces and setup traces are always displayed.
I have placed the solutions of each challenge in the solution branch. You can access them with the following command:
git checkout -b solution origin/solution
forge init ethernaut-foundry-boilerplate
forge install OpenZeppelin/openzeppelin-contracts
forge install openzeppelin-contracts-06=OpenZeppelin/[email protected]
Edit the foundry.toml
file,
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']
remappings = [
'ds-test/=lib/forge-std/lib/ds-test/src/',
'forge-std/=lib/forge-std/src/',
'openzeppelin-contracts-06/=lib/openzeppelin-contracts-06/contracts/',
'openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/',
]
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
Then run
forge remappings > remappings.txt
Create core
and levels
folders under the src/
to put the main logic contract and the challenge of Ethernaut
We add Ethernaut-05.sol
, Level-05.sol
, Ethernaut-06.sol
, Level-06.sol
for challenge 19 Alien Codex and challenge 25 Motorbike
└── src
├── core
│ ├── Ethernaut-05.sol
│ │
│ ├── Level-05.sol
│ │
│ ├── Ethernaut-06.sol
│ │
│ ├── Level-06.sol
│ │
│ ├── Ethernaut.sol
│ │
│ └── Level.sol
│
└── levels
└── XX-<LevelName>
├── <LevelName>.sol
│
└── <LevelName>Factory.sol
/core
: it contains the six main logic contracts of the EthernautEthernaut.sol
token from here. But we add return value for each function ofEthernaut.sol
Level.sol
token from here.Ethernaut-05.sol
same fromEthernaut.sol
but for supporting the challenge 19 Alien CodexLevel-05.sol
same fromLevel.sol
but for supporting the challenge 19 Alien CodexEthernaut-06.sol
same fromEthernaut.sol
but for supporting the challenge 25 MotorbikeLevel-06.sol
same fromLevel.sol
but for supporting the challenge 25 Motorbike
/levels
: it contains the all levels of the Ethernaut. For each level is composed of two contracts and can be found from here:<LevelName>.sol
<LevelName>Factory.sol