forked from balancer/balancer-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TBPoolJoinExitPool.sol
61 lines (46 loc) · 2.17 KB
/
TBPoolJoinExitPool.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
import "./BNum.sol";
// This test is similar to TBPoolJoin but with an exit fee
contract TBPoolJoinExit is BNum {
// joinPool models the BPool.joinPool behavior for one token
function joinPool(uint poolAmountOut, uint poolTotal, uint _records_t_balance)
internal pure returns(uint)
{
uint ratio = bdiv(poolAmountOut, poolTotal);
require(ratio != 0);
uint bal = _records_t_balance;
uint tokenAmountIn = bmul(ratio, bal);
return tokenAmountIn;
}
// exitPool models the BPool.exitPool behavior for one token
function exitPool(uint poolAmountIn, uint poolTotal, uint _records_t_balance)
internal pure returns(uint)
{
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
uint pAiAfterExitFee = bsub(poolAmountIn, exitFee);
uint ratio = bdiv(pAiAfterExitFee, poolTotal);
require(ratio != 0);
uint bal = _records_t_balance;
uint tokenAmountOut = bmul(ratio, bal);
return tokenAmountOut;
}
// This function model an attacker calling joinPool - exitPool and taking advantage of potential rounding
// issues to generate free pool token
function joinAndExitPool(uint poolAmountOut, uint poolAmountIn, uint poolTotal, uint _records_t_balance) public pure {
uint tokenAmountIn = joinPool(poolAmountOut, poolTotal, _records_t_balance);
// We constraint poolTotal and _records_t_balance
// To have "realistic" values
require(poolTotal <= 100 ether);
require(poolTotal >= 1 ether);
require(_records_t_balance <= 10 ether);
require(_records_t_balance >= 10**6);
poolTotal = badd(poolTotal, poolAmountOut);
_records_t_balance = badd(_records_t_balance, tokenAmountIn);
require(tokenAmountIn > 0); // prevent triggering the free token generation from joinPool
require(poolTotal >= poolAmountIn);
uint tokenAmountOut = exitPool(poolAmountIn, poolTotal, _records_t_balance);
require(_records_t_balance >= tokenAmountOut);
// We try to generate free pool share
require(poolAmountOut > poolAmountIn);
require(tokenAmountOut == tokenAmountIn);
}
}