-
Notifications
You must be signed in to change notification settings - Fork 167
/
TBPoolBind.sol
169 lines (148 loc) · 7.52 KB
/
TBPoolBind.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
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import "../crytic-export/flattening/BPool.sol";
import "./MyToken.sol";
import "./CryticInterface.sol";
contract TBPoolBindPrivileged is CryticInterface, BPool {
constructor() public {
// Create a new token with initial_token_balance as total supply.
// After the token is created, each user defined in CryticInterface
// (crytic_owner, crytic_user and crytic_attacker) receives 1/3 of
// the initial balance
MyToken t;
t = new MyToken(initial_token_balance, address(this));
bind(address(t), MIN_BALANCE, MIN_WEIGHT);
}
// initial token balances is the max amount for uint256
uint internal initial_token_balance = uint(-1);
// these two variables are used to save valid balances and denorm parameters
uint internal valid_balance_to_bind = MIN_BALANCE;
uint internal valid_denorm_to_bind = MIN_WEIGHT;
// this function allows to create as many tokens as needed
function create_and_bind(uint balance, uint denorm) public returns (address) {
// Create a new token with initial_token_balance as total supply.
// After the token is created, each user defined in CryticInterface
// (crytic_owner, crytic_user and crytic_attacker) receives 1/3 of
// the initial balance
MyToken bt = new MyToken(initial_token_balance, address(this));
bt.approve(address(this), initial_token_balance);
// Bind the token with the provided parameters
bind(address(bt), balance, denorm);
// Save the balance and denorm values used. These are used in the rebind checks
valid_balance_to_bind = balance;
valid_denorm_to_bind = denorm;
return address(bt);
}
function echidna_getNumTokens_less_or_equal_MAX_BOUND_TOKENS() public returns (bool) {
// it is not possible to bind more than `MAX_BOUND_TOKENS`
return this.getNumTokens() <= MAX_BOUND_TOKENS;
}
function echidna_revert_bind_twice() public returns (bool) {
if (this.getCurrentTokens().length > 0 && this.getController() == crytic_owner && !this.isFinalized()) {
// binding the first token should be enough, if we have this property to always revert
bind(this.getCurrentTokens()[0], valid_balance_to_bind, valid_denorm_to_bind);
// This return will make this property to fail
return true;
}
// If there are no tokens or if the controller was changed or if the pool was finalized, just revert.
revert();
}
function echidna_revert_unbind_twice() public returns (bool) {
if (this.getCurrentTokens().length > 0 && this.getController() == crytic_owner && !this.isFinalized()) {
address[] memory current_tokens = this.getCurrentTokens();
// unbinding the first token twice should be enough, if we want this property to always revert
unbind(current_tokens[0]);
unbind(current_tokens[0]);
return true;
}
// if there are no tokens or if the controller was changed or if the pool was finalized, just revert
revert();
}
function echidna_all_tokens_are_unbindable() public returns (bool) {
if (this.getController() == crytic_owner && !this.isFinalized()) {
address[] memory current_tokens = this.getCurrentTokens();
// unbind all the tokens, one by one
for (uint i = 0; i < current_tokens.length; i++) {
unbind(current_tokens[i]);
}
// at the end, the list of current tokens should be empty
return (this.getCurrentTokens().length == 0);
}
// if the controller was changed or if the pool was finalized, just return true
return true;
}
function echidna_all_tokens_are_rebindable_with_valid_parameters() public returns (bool) {
if (this.getController() == crytic_owner && !this.isFinalized()) {
address[] memory current_tokens = this.getCurrentTokens();
for (uint i = 0; i < current_tokens.length; i++) {
// rebind all the tokens, one by one, using valid parameters
rebind(current_tokens[i], valid_balance_to_bind, valid_denorm_to_bind);
}
// at the end, the list of current tokens should have not change in size
return current_tokens.length == this.getCurrentTokens().length;
}
// if the controller was changed or if the pool was finalized, just return true
return true;
}
function echidna_revert_rebind_unbinded() public returns (bool) {
if (this.getCurrentTokens().length > 0 && this.getController() == crytic_owner && !this.isFinalized()) {
address[] memory current_tokens = this.getCurrentTokens();
// unbinding and rebinding the first token should be enough, if we want this property to always revert
unbind(current_tokens[0]);
rebind(current_tokens[0], valid_balance_to_bind, valid_denorm_to_bind);
return true;
}
// if the controller was changed or if the pool was finalized, just return true
revert();
}
}
contract TBPoolBindUnprivileged is CryticInterface, BPool {
MyToken t1;
MyToken t2;
// initial token balances is the max amount for uint256
uint internal initial_token_balance = uint(-1);
constructor() public {
// two tokens with minimal balances and weights are created by the controller
t1 = new MyToken(initial_token_balance, address(this));
bind(address(t1), MIN_BALANCE, MIN_WEIGHT);
t2 = new MyToken(initial_token_balance, address(this));
bind(address(t2), MIN_BALANCE, MIN_WEIGHT);
}
// these two variables are used to save valid balances and denorm parameters
uint internal valid_balance_to_bind = MIN_BALANCE;
uint internal valid_denorm_to_bind = MIN_WEIGHT;
// this function allows to create as many tokens as needed
function create_and_bind(uint balance, uint denorm) public returns (address) {
// Create a new token with initial_token_balance as total supply.
// After the token is created, each user defined in CryticInterface
// (crytic_owner, crytic_user and crytic_attacker) receives 1/3 of
// the initial balance
MyToken bt = new MyToken(initial_token_balance, address(this));
bt.approve(address(this), initial_token_balance);
// Bind the token with the provided parameters
bind(address(bt), balance, denorm);
// Save the balance and denorm values used. These are used in the rebind checks
valid_balance_to_bind = balance;
valid_denorm_to_bind = denorm;
return address(bt);
}
function echidna_only_controller_can_bind() public returns (bool) {
// the number of tokens cannot be changed
return this.getNumTokens() == 2;
}
function echidna_revert_when_bind() public returns (bool) {
// calling bind will revert
create_and_bind(valid_balance_to_bind, valid_denorm_to_bind);
return true;
}
function echidna_revert_when_rebind() public returns (bool) {
// calling rebind on binded tokens will revert
rebind(address(t1), valid_balance_to_bind, valid_denorm_to_bind);
rebind(address(t2), valid_balance_to_bind, valid_denorm_to_bind);
return true;
}
function echidna_revert_when_unbind() public returns (bool) {
// calling unbind on binded tokens will revert
unbind(address(t1));
unbind(address(t2));
return true;
}
}