My solutions of Ethernaut CTFs.
curl -L https://foundry.paradigm.xyz | bash
foundryup
git clone https://github.com/hammadghazi/Foundry-X-Ethernaut.git
forge install
forge build
forge test -vv
# example forge test --match-contract TestCoinFlip
forge test --match-contract NAME_OF_THE_TEST
Create a new test CHALLENGE.t.sol
in the test/
directory and inherit from BaseTest.sol
.
BaseTest.sol will automate all these things:
- The constructor will set up some basic parameters like the number of users to create, how many ethers give them (5 ether) as initial balance and the labels for each user (for better debugging with forge)
- Set up the
Ethernaut
contract - Register the level that you have specified in your
CHALLENGE.t.sol
constructor - Run the test automatically calling two callbacks inside your
CHALLENGE.t.sol
contractsetupLevel
is the function you must override and implement all the logic needed to set up the challenge. Usually is always the same (callcreateLevelInstance
and initialize thelevel
variable)exploitLevel
is the function you must override and implement all the logic to solve the challenge
- Run automatically the
checkSuccess
function that will check if the solution you have provided has solved the challenge
Here's an example of a test
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.6.0;
pragma experimental ABIEncoderV2;
import './utils/BaseTest.sol';
import 'src/levels/CHALLENGE.sol';
import 'src/levels/CHALLENGEFactory.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';
contract TestCHALLENGE is BaseTest {
CoinFlip private level;
constructor() public {
// SETUP LEVEL FACTORY
levelFactory = new CHALLENGEFactory();
}
function setUp() public override {
// Call the BaseTest setUp() function that will also create testsing accounts
super.setUp();
}
function testRunLevel() public {
runLevel();
}
function setupLevel() internal override {
/** CODE YOUR SETUP HERE */
levelAddress = payable(this.createLevelInstance(true));
level = CHALLENGE(levelAddress);
}
function exploitLevel() internal override {
/** CODE YOUR EXPLOIT HERE */
vm.startPrank(player);
// SOLVE THE CHALLENGE!
vm.stopPrank();
}
}
What you need to do is to
- Replace
CHALLENGE
with the name of the Ethernaut challenge you are solving - Modify
setupLevel
if needed - Implement the logic to solve the challenge inside
exploitLevel
betweenstartPrank
andstopPrank
- Run the test!
- Alien Codex is not part of this repository.
- Motorbike challenge test case can't be validated because of the way foundry test works.
- MagicNumber is not part of this repository.