-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmultiSign.sol
415 lines (380 loc) · 17.3 KB
/
multiSign.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
/**
* @title MultiSign contract
* @author Autonomint
* @notice Contract that is used for MultiSign feature
* - Owners can:
* # Pause specific function in Borrow or CDS
* # Pause entire Borrowing or CDS contract
* # Approve setter functions to set addresses, ltv etc.
* @dev All admin functions are callable by the admin address only
* @dev Checks whether the function or contract is paused or not.
*/
contract MultiSign is Initializable, OwnableUpgradeable, UUPSUpgradeable {
address[] private owners; // Owners array
uint8 private maxOwners; // Maximum number of owners approval required
uint8 private noOfOwners; // Total number of owners
mapping(address => bool) public isOwner; // To check the address is owner
uint64 private requiredApprovals; // Required number of approvals to execute the function
enum SetterFunctions {
SetLTV, // To set LTV of the protocol
SetAPR, // To set APR of the protocol
SetWithdrawTimeLimitCDS, // To set withdraw time limit in CDS
SetAdminBorrow, // To set ADMIN in borrow
SetAdminCDS, // TO set ADMIN in CDS
SetTreasuryBorrow, // To set treasury contract address in borrow
SetTreasuryCDS, // To set treasury contract address in CDS
SetBondRatio, // To set ABOND-USDa ratio in Borrow
SetUSDaLimit, // To set minimum percentage of USDa to deposit in CDS
SetUsdtLimit // To set minimum percentage of USDT to deposit in CDS
}
enum Functions {
BorrowingDeposit, // Deposit function in borrow
BorrowingWithdraw, // Withdraw function in borrow
Liquidation, // Liquidation function
SetAPR, // Set APR function in borrow
CDSDeposit, // Deposit function in CDS
CDSWithdraw, // Withdraw function in CDS
RedeemUSDT // Redeem USDT function in CDS
}
mapping(SetterFunctions => mapping(address owner => bool approved)) public approvedToUpdate; // Check which owners were approved
mapping(Functions => mapping(address owner => bool paused)) public pauseApproved; // Store what functions are approved for pause by owners
mapping(Functions => mapping(address owner => bool unpaused)) public unpauseApproved; // Store what functions are approved for unpause by owners
mapping(Functions => bool paused) public functionState; // Returns true if function is in pause state
/**
* @dev Initialize function to initialize the contract
* @param _owners owners address in array
* @param _requiredApprovals number of owners approvals required
*/
function initialize(
address[] memory _owners,
uint64 _requiredApprovals
) public initializer {
// initialize the owner
__Ownable_init(msg.sender);
//Initialize the proxy
__UUPSUpgradeable_init();
uint8 _noOfOwners = uint8(_owners.length);
// Check whether the number of owners is not a zero
require(_noOfOwners > 0, "Owners required");
maxOwners = 10;
// Check whether the owners reached maximum limit
require( _noOfOwners <= maxOwners,"Number of owners should be below maximum owners limit");
// Check whether the required approvals are lessthan or equal to the number of owners
require(_requiredApprovals > 0 && _requiredApprovals <= _noOfOwners,"Invalid number of required approvals");
for (uint64 i; i < _noOfOwners; i++) {
address _owner = _owners[i];
// Check the owner address is non zero
require(_owner != address(0), "Invalid owner");
// Check, the same owner address is not repeated
require(!isOwner[_owner], "Duplicate owner");
isOwner[_owner] = true;
owners.push(_owner);
}
requiredApprovals = _requiredApprovals;
noOfOwners = _noOfOwners;
}
function _authorizeUpgrade(
address newImplementation
) internal override onlyOwner {}
/**
* @dev modifier to check whether the caller is owner or not
*/
modifier onlyOwners() {
require(isOwner[msg.sender], "Not an owner");
_;
}
/**
* @dev Function to approve pause functions
* @param functions Which functions needs to pause
*/
function approvePause(uint8[] memory functions) external onlyOwners {
uint8 noOfFunctions = uint8(functions.length);
// Check, the given functions are not empty
require(noOfFunctions > 0, "Empty array");
// Loop through the functions to approve pause functions
for (uint8 i = 0; i < noOfFunctions; i++) {
// Check, the caller(owner) has already approved to pause given function
require(!pauseApproved[Functions(functions[i])][msg.sender],"Already approved");
// Change the mapping to true
pauseApproved[Functions(functions[i])][msg.sender] = true;
}
}
/**
* @dev Function to approve setter functions
* @param functions Which functions needs to set
*/
function approveSetterFunction(
uint8[] memory functions
) external onlyOwners {
uint8 noOfFunctions = uint8(functions.length);
// Check, the given functions are not empty
require(noOfFunctions > 0, "Empty array");
// Loop through the functions to approve setter functions
for (uint8 i = 0; i < noOfFunctions; i++) {
// Check, the caller(owner) has already approved to set given function
require(!approvedToUpdate[SetterFunctions(functions[i])][msg.sender],"Already approved");
// Change the mapping to true
approvedToUpdate[SetterFunctions(functions[i])][msg.sender] = true;
}
}
/**
* @dev Function to approve unpause functions
* @param functions Which functions needs to pause
*/
function approveUnPause(uint8[] memory functions) external onlyOwners {
uint8 noOfFunctions = uint8(functions.length);
// Check, the given functions are not empty
require(noOfFunctions > 0, "Empty array");
// Loop through the functions to approve unpause functions
for (uint8 i = 0; i < noOfFunctions; i++) {
// Check, the caller(owner) has already approved to unpause given function
require(!unpauseApproved[Functions(functions[i])][msg.sender],"Already approved");
// Change the mapping to true
unpauseApproved[Functions(functions[i])][msg.sender] = true;
}
}
/**
* @dev Function to approve ,pause borrowing contracts
*/
function approveBorrowingPause() external onlyOwners {
// Check, the caller(owner) has already approved to pause borrowing contract functions
require(!pauseApproved[Functions.BorrowingDeposit][msg.sender],"BorrowingDeposit Already approved");
require(!pauseApproved[Functions.BorrowingWithdraw][msg.sender],"BorrowingWithdraw Already approved");
require(!pauseApproved[Functions.Liquidation][msg.sender],"Liquidation Already approved");
require(!pauseApproved[Functions.SetAPR][msg.sender],"SetAPR Already approved");
// Change the mapping to true
pauseApproved[Functions.BorrowingDeposit][msg.sender] = true;
pauseApproved[Functions.BorrowingWithdraw][msg.sender] = true;
pauseApproved[Functions.Liquidation][msg.sender] = true;
pauseApproved[Functions.SetAPR][msg.sender] = true;
}
/**
* @dev Function to approve ,pause CDS contracts
*/
function approveCDSPause() external onlyOwners {
// Check, the caller(owner) has already approved to pause cds contract function
require(!pauseApproved[Functions.CDSDeposit][msg.sender],"CDSDeposit Already approved");
require(!pauseApproved[Functions.CDSWithdraw][msg.sender],"CDSWithdraw Already approved");
require(!pauseApproved[Functions.RedeemUSDT][msg.sender],"RedeemUSDT Already approved");
// Change the mapping to true
pauseApproved[Functions.CDSDeposit][msg.sender] = true;
pauseApproved[Functions.CDSWithdraw][msg.sender] = true;
pauseApproved[Functions.RedeemUSDT][msg.sender] = true;
}
/**
* @dev Function to approve ,unpause borrowing contracts
*/
function approveBorrowingUnPause() external onlyOwners {
// Check, the caller(owner) has already approved to unpause borrowing contract function
require(!unpauseApproved[Functions.BorrowingDeposit][msg.sender],"BorrowingDeposit Already approved");
require(!unpauseApproved[Functions.BorrowingWithdraw][msg.sender],"BorrowingWithdraw Already approved");
require(!unpauseApproved[Functions.Liquidation][msg.sender],"Liquidation Already approved");
require(!unpauseApproved[Functions.SetAPR][msg.sender],"SetAPR Already approved");
// Change the mapping to true
unpauseApproved[Functions.BorrowingDeposit][msg.sender] = true;
unpauseApproved[Functions.BorrowingWithdraw][msg.sender] = true;
unpauseApproved[Functions.Liquidation][msg.sender] = true;
unpauseApproved[Functions.SetAPR][msg.sender] = true;
}
/**
* @dev Function to approve ,unpause cds contracts
*/
function approveCDSUnPause() external onlyOwners {
// Check, the caller(owner) has already approved to unpause cds contract function
require(!unpauseApproved[Functions.CDSDeposit][msg.sender],"CDSDeposit Already approved");
require(!unpauseApproved[Functions.CDSWithdraw][msg.sender],"CDSWithdraw Already approved");
require(!unpauseApproved[Functions.RedeemUSDT][msg.sender],"RedeemUSDT Already approved");
// Change the mapping to true
unpauseApproved[Functions.CDSDeposit][msg.sender] = true;
unpauseApproved[Functions.CDSWithdraw][msg.sender] = true;
unpauseApproved[Functions.RedeemUSDT][msg.sender] = true;
}
/**
* @dev Gets the pause approval count for the specfic function
*/
function getApprovalPauseCount(
Functions _function
) private view returns (uint64) {
uint64 count;
// Loop through the approved functions with owners mapping and get the approval count
for (uint64 i; i < noOfOwners; i++) {
// Check the owner has approved function to pause
if (pauseApproved[_function][owners[i]]) {
count += 1;
}
}
return count;
}
/**
* @dev Gets the unpause approval count for the specfic function
*/
function getApprovalUnPauseCount(
Functions _function
) private view returns (uint64) {
uint64 count;
// Loop through the approved functions with owners mapping and get the approval count
for (uint64 i; i < noOfOwners; i++) {
// Check the owner has approved function to unpause
if (unpauseApproved[_function][owners[i]]) {
count += 1;
}
}
return count;
}
/**
* @dev Gets the setter approval count for the specfic function
*/
function getSetterFunctionApproval(
SetterFunctions _function
) private view returns (uint64) {
uint64 count;
// Loop through the approved functions with owners mapping and get the approval count
for (uint64 i; i < noOfOwners; i++) {
// Check the owner has approved function to set
if (approvedToUpdate[_function][owners[i]]) {
count += 1;
}
}
return count;
}
/**
* @dev Pause the function, If reqired approvals from the owners met
* @param _function Fucntion to execute pause
*/
function executePause(Functions _function) private returns (bool) {
// Get the number of approvals
require(getApprovalPauseCount(_function) >= requiredApprovals,"Required approvals not met");
// Loop through the approved functions with owners mapping and change to false
for (uint64 i; i < noOfOwners; i++) {
pauseApproved[_function][owners[i]] = false;
}
return true;
}
/**
* @dev UnPause the function, If reqired approvals from the owners met
* @param _function Fucntion to execute unpause
*/
function executeUnPause(Functions _function) private returns (bool) {
// Get the number of approvals
require(getApprovalUnPauseCount(_function) >= requiredApprovals,"Required approvals not met");
// Loop through the approved functions with owners mapping and change to false
for (uint64 i; i < noOfOwners; i++) {
unpauseApproved[_function][owners[i]] = false;
}
return true;
}
/**
* @dev Set the function, If reqired approvals from the owners met
* @param _function Fucntion to execute setter
*/
function executeSetterFunction(
SetterFunctions _function
) external returns (bool) {
// Get the number of approvals
require(getSetterFunctionApproval(_function) >= requiredApprovals,"Required approvals not met");
// Loop through the approved functions with owners mapping and change to false
for (uint64 i; i < noOfOwners; i++) {
approvedToUpdate[_function][owners[i]] = false;
}
return true;
}
/**
* @dev Pause the functions, If reqired approvals from the owners met
* @param functions Fucntions to execute pause
*/
function pauseFunction(uint8[] memory functions) external onlyOwners {
uint8 noOfFunctions = uint8(functions.length);
// Check, the given functions are not empty
require(noOfFunctions > 0, "Empty array");
// Loop through the approved functions with owners mapping and change to true
for (uint8 i = 0; i < noOfFunctions; i++) {
// Execute the pause for given functions, check if returned true
require(executePause(Functions(functions[i])));
functionState[Functions(functions[i])] = true;
}
}
/**
* @dev UnPause the functions, If reqired approvals from the owners met
* @param functions Fucntions to execute unpause
*/
function unpauseFunction(uint8[] memory functions) external onlyOwners {
uint8 noOfFunctions = uint8(functions.length);
// Check, the given functions are not empty
require(noOfFunctions > 0, "Empty array");
// Loop through the approved functions with owners mapping and change to false
for (uint8 i = 0; i < noOfFunctions; i++) {
// Execute the unpause for given functions, check if returned true
require(executeUnPause(Functions(functions[i])));
functionState[Functions(functions[i])] = false;
}
}
/**
* @dev Pause the borrowing contract functions, If reqired approvals from the owners met
*/
function pauseBorrowing() external onlyOwners {
// Execute the pause for all borrowing functions, check if returned true
require(
executePause(Functions(0)) &&
executePause(Functions(1)) &&
executePause(Functions(2)) &&
executePause(Functions(3))
);
// Change the mapping to true
functionState[Functions.BorrowingDeposit] = true;
functionState[Functions.BorrowingWithdraw] = true;
functionState[Functions.Liquidation] = true;
functionState[Functions.SetAPR] = true;
}
/**
* @dev Pause the cds contract functions, If reqired approvals from the owners met
*/
function pauseCDS() external onlyOwners {
// Execute the pause for all cds functions, check if returned true
require(
executePause(Functions(4)) &&
executePause(Functions(5)) &&
executePause(Functions(6))
);
// Change the mapping to true
functionState[Functions.CDSDeposit] = true;
functionState[Functions.CDSWithdraw] = true;
functionState[Functions.RedeemUSDT] = true;
}
/**
* @dev UnPause the borrowing contract functions, If reqired approvals from the owners met
*/
function unpauseBorrowing() external onlyOwners {
// Execute the unpause for all borrowing functions, check if returned true
require(
executeUnPause(Functions(0)) &&
executeUnPause(Functions(1)) &&
executeUnPause(Functions(2)) &&
executeUnPause(Functions(3))
);
// Change the mapping to false
functionState[Functions.BorrowingDeposit] = false;
functionState[Functions.BorrowingWithdraw] = false;
functionState[Functions.Liquidation] = false;
functionState[Functions.SetAPR] = false;
}
/**
* @dev UnPause the cds contract functions, If reqired approvals from the owners met
*/
function unpauseCDS() external onlyOwners {
// Execute the unpause for all cds functions, check if returned true
require(
executeUnPause(Functions(4)) &&
executeUnPause(Functions(5)) &&
executeUnPause(Functions(6))
);
// Change the mapping to false
functionState[Functions.CDSDeposit] = false;
functionState[Functions.CDSWithdraw] = false;
functionState[Functions.RedeemUSDT] = false;
}
}