@keep-network/tbtc-v2 0.1.1-dev.41 → 0.1.1-dev.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/artifacts/Bank.json +742 -0
- package/artifacts/Bridge.json +2914 -0
- package/artifacts/Deposit.json +117 -0
- package/artifacts/EcdsaDkgValidator.json +532 -0
- package/artifacts/EcdsaInactivity.json +156 -0
- package/artifacts/Fraud.json +153 -0
- package/artifacts/KeepRegistry.json +99 -0
- package/artifacts/KeepStake.json +286 -0
- package/artifacts/KeepToken.json +711 -0
- package/artifacts/KeepTokenStaking.json +483 -0
- package/artifacts/MovingFunds.json +137 -0
- package/artifacts/NuCypherStakingEscrow.json +256 -0
- package/artifacts/NuCypherToken.json +711 -0
- package/artifacts/RandomBeaconStub.json +141 -0
- package/artifacts/Redemption.json +161 -0
- package/artifacts/ReimbursementPool.json +509 -0
- package/artifacts/Relay.json +123 -0
- package/artifacts/SortitionPool.json +944 -0
- package/artifacts/Sweep.json +76 -0
- package/artifacts/T.json +1148 -0
- package/artifacts/TBTC.json +21 -21
- package/artifacts/TBTCToken.json +21 -21
- package/artifacts/TokenStaking.json +2288 -0
- package/artifacts/TokenholderGovernor.json +1795 -0
- package/artifacts/TokenholderTimelock.json +1058 -0
- package/artifacts/VendingMachine.json +24 -24
- package/artifacts/VendingMachineKeep.json +400 -0
- package/artifacts/VendingMachineNuCypher.json +400 -0
- package/artifacts/WalletRegistry.json +2709 -0
- package/artifacts/WalletRegistryGovernance.json +2364 -0
- package/artifacts/Wallets.json +186 -0
- package/artifacts/solcInputs/{e9b173393b9fd7287a0bfaa6d4eb4b71.json → bbe44823ec28554a9429cce5cafee035.json} +34 -34
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
- package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +2 -2
- package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
- package/build/contracts/bridge/Bridge.sol/Bridge.json +535 -273
- package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
- package/build/contracts/bridge/BridgeState.sol/BridgeState.json +147 -3
- package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +1 -1
- package/build/contracts/bridge/Deposit.sol/Deposit.json +2 -2
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +2 -2
- package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
- package/build/contracts/bridge/Fraud.sol/Fraud.json +5 -57
- package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
- package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
- package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +41 -21
- package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
- package/build/contracts/bridge/{Redeem.sol → Redemption.sol}/OutboundTx.json +3 -3
- package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
- package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
- package/build/contracts/bridge/Sweep.sol/Sweep.dbg.json +1 -1
- package/build/contracts/bridge/Sweep.sol/Sweep.json +2 -2
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
- package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
- package/build/contracts/bridge/Wallets.sol/Wallets.json +12 -38
- package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
- package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
- package/contracts/bridge/BitcoinTx.sol +19 -26
- package/contracts/bridge/Bridge.sol +765 -524
- package/contracts/bridge/BridgeState.sol +312 -23
- package/contracts/bridge/Deposit.sol +25 -6
- package/contracts/bridge/EcdsaLib.sol +15 -0
- package/contracts/bridge/Fraud.sol +65 -33
- package/contracts/bridge/MovingFunds.sol +196 -10
- package/contracts/bridge/{Redeem.sol → Redemption.sol} +26 -29
- package/contracts/bridge/Sweep.sol +16 -12
- package/contracts/bridge/Wallets.sol +90 -153
- package/deploy/00_resolve_relay.ts +28 -0
- package/deploy/04_deploy_bank.ts +25 -0
- package/deploy/05_deploy_bridge.ts +60 -0
- package/deploy/06_bank_update_bridge.ts +19 -0
- package/deploy/07_transfer_ownership.ts +17 -0
- package/export.json +14797 -459
- package/package.json +2 -2
- package/build/contracts/bridge/Redeem.sol/OutboundTx.dbg.json +0 -4
- package/build/contracts/bridge/Redeem.sol/Redeem.dbg.json +0 -4
- package/build/contracts/bridge/Redeem.sol/Redeem.json +0 -110
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
pragma solidity ^0.8.9;
|
|
17
17
|
|
|
18
18
|
import {BTCUtils} from "@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol";
|
|
19
|
-
import {IWalletRegistry as EcdsaWalletRegistry} from "@keep-network/ecdsa/contracts/api/IWalletRegistry.sol";
|
|
20
19
|
import {EcdsaDkg} from "@keep-network/ecdsa/contracts/libraries/EcdsaDkg.sol";
|
|
20
|
+
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
|
|
21
21
|
|
|
22
22
|
import "./BitcoinTx.sol";
|
|
23
23
|
import "./EcdsaLib.sol";
|
|
24
|
+
import "./BridgeState.sol";
|
|
24
25
|
|
|
25
26
|
/// @title Wallet library
|
|
26
27
|
/// @notice Library responsible for handling integration between Bridge
|
|
@@ -28,32 +29,6 @@ import "./EcdsaLib.sol";
|
|
|
28
29
|
library Wallets {
|
|
29
30
|
using BTCUtils for bytes;
|
|
30
31
|
|
|
31
|
-
/// @notice Struct that groups the state managed by the library.
|
|
32
|
-
struct Data {
|
|
33
|
-
// ECDSA Wallet Registry contract handle.
|
|
34
|
-
EcdsaWalletRegistry registry;
|
|
35
|
-
// Determines how frequently a new wallet creation can be requested.
|
|
36
|
-
// Value in seconds.
|
|
37
|
-
uint32 creationPeriod;
|
|
38
|
-
// The minimum BTC threshold in satoshi that is used to decide about
|
|
39
|
-
// wallet creation or closing.
|
|
40
|
-
uint64 minBtcBalance;
|
|
41
|
-
// The maximum BTC threshold in satoshi that is used to decide about
|
|
42
|
-
// wallet creation.
|
|
43
|
-
uint64 maxBtcBalance;
|
|
44
|
-
// The maximum age of a wallet in seconds, after which the wallet
|
|
45
|
-
// moving funds process can be requested.
|
|
46
|
-
uint32 maxAge;
|
|
47
|
-
// 20-byte wallet public key hash being reference to the currently
|
|
48
|
-
// active wallet. Can be unset to the zero value under certain
|
|
49
|
-
// circumstances.
|
|
50
|
-
bytes20 activeWalletPubKeyHash;
|
|
51
|
-
// Maps the 20-byte wallet public key hash (computed using Bitcoin
|
|
52
|
-
// HASH160 over the compressed ECDSA public key) to the basic wallet
|
|
53
|
-
// information like state and pending redemptions value.
|
|
54
|
-
mapping(bytes20 => Wallet) registeredWallets;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
32
|
/// @notice Represents wallet state:
|
|
58
33
|
enum WalletState {
|
|
59
34
|
/// @dev The wallet is unknown to the Bridge.
|
|
@@ -65,8 +40,15 @@ library Wallets {
|
|
|
65
40
|
/// fulfill their pending redemption requests although new
|
|
66
41
|
/// redemption requests and new deposit reveals are not accepted.
|
|
67
42
|
MovingFunds,
|
|
68
|
-
/// @dev The wallet moved or redeemed all their funds and
|
|
69
|
-
///
|
|
43
|
+
/// @dev The wallet moved or redeemed all their funds and is in the
|
|
44
|
+
/// closing period where they can be subject of fraud challenges
|
|
45
|
+
/// and must defend against them. This state is needed to protect
|
|
46
|
+
/// against deposit frauds on deposits revealed but not swept.
|
|
47
|
+
/// The closing period must be greater that the deposit refund
|
|
48
|
+
/// time plus some time margin.
|
|
49
|
+
Closing,
|
|
50
|
+
/// @dev The wallet finalized the closing period successfully and
|
|
51
|
+
/// cannot perform any action in the Bridge.
|
|
70
52
|
Closed,
|
|
71
53
|
/// @dev The wallet committed a fraud that was reported. The wallet is
|
|
72
54
|
/// blocked and can not perform any actions in the Bridge.
|
|
@@ -93,6 +75,9 @@ library Wallets {
|
|
|
93
75
|
// UNIX timestamp indicating the moment the wallet was requested to
|
|
94
76
|
// move their funds.
|
|
95
77
|
uint32 movingFundsRequestedAt;
|
|
78
|
+
// UNIX timestamp indicating the moment the wallet's closing period
|
|
79
|
+
// started.
|
|
80
|
+
uint32 closingStartedAt;
|
|
96
81
|
// Current state of the wallet.
|
|
97
82
|
WalletState state;
|
|
98
83
|
// Moving funds target wallet commitment submitted by the wallet. It
|
|
@@ -101,15 +86,6 @@ library Wallets {
|
|
|
101
86
|
bytes32 movingFundsTargetWalletsCommitmentHash;
|
|
102
87
|
}
|
|
103
88
|
|
|
104
|
-
event WalletCreationPeriodUpdated(uint32 newCreationPeriod);
|
|
105
|
-
|
|
106
|
-
event WalletBtcBalanceRangeUpdated(
|
|
107
|
-
uint64 newMinBtcBalance,
|
|
108
|
-
uint64 newMaxBtcBalance
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
event WalletMaxAgeUpdated(uint32 newMaxAge);
|
|
112
|
-
|
|
113
89
|
event NewWalletRequested();
|
|
114
90
|
|
|
115
91
|
event NewWalletRegistered(
|
|
@@ -122,6 +98,11 @@ library Wallets {
|
|
|
122
98
|
bytes20 indexed walletPubKeyHash
|
|
123
99
|
);
|
|
124
100
|
|
|
101
|
+
event WalletClosing(
|
|
102
|
+
bytes32 indexed ecdsaWalletID,
|
|
103
|
+
bytes20 indexed walletPubKeyHash
|
|
104
|
+
);
|
|
105
|
+
|
|
125
106
|
event WalletClosed(
|
|
126
107
|
bytes32 indexed ecdsaWalletID,
|
|
127
108
|
bytes20 indexed walletPubKeyHash
|
|
@@ -132,64 +113,6 @@ library Wallets {
|
|
|
132
113
|
bytes20 indexed walletPubKeyHash
|
|
133
114
|
);
|
|
134
115
|
|
|
135
|
-
/// @notice Initializes state invariants.
|
|
136
|
-
/// @param registry ECDSA Wallet Registry reference
|
|
137
|
-
/// @dev Requirements:
|
|
138
|
-
/// - ECDSA Wallet Registry address must not be initialized
|
|
139
|
-
function init(Data storage self, address registry) external {
|
|
140
|
-
require(
|
|
141
|
-
registry != address(0),
|
|
142
|
-
"ECDSA Wallet Registry address cannot be zero"
|
|
143
|
-
);
|
|
144
|
-
require(
|
|
145
|
-
address(self.registry) == address(0),
|
|
146
|
-
"ECDSA Wallet Registry address already set"
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
self.registry = EcdsaWalletRegistry(registry);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/// @notice Sets the wallet creation period.
|
|
153
|
-
/// @param creationPeriod New value of the wallet creation period
|
|
154
|
-
function setCreationPeriod(Data storage self, uint32 creationPeriod)
|
|
155
|
-
external
|
|
156
|
-
{
|
|
157
|
-
self.creationPeriod = creationPeriod;
|
|
158
|
-
|
|
159
|
-
emit WalletCreationPeriodUpdated(creationPeriod);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/// @notice Sets the minimum and maximum BTC balance parameters.
|
|
163
|
-
/// @param minBtcBalance New value of the minimum BTC balance
|
|
164
|
-
/// @param maxBtcBalance New value of the maximum BTC balance
|
|
165
|
-
/// @dev Requirements:
|
|
166
|
-
/// - Minimum BTC balance must be greater than zero
|
|
167
|
-
/// - Maximum BTC balance must be greater than minimum BTC balance
|
|
168
|
-
function setBtcBalanceRange(
|
|
169
|
-
Data storage self,
|
|
170
|
-
uint64 minBtcBalance,
|
|
171
|
-
uint64 maxBtcBalance
|
|
172
|
-
) external {
|
|
173
|
-
require(minBtcBalance > 0, "Minimum must be greater than zero");
|
|
174
|
-
require(
|
|
175
|
-
maxBtcBalance > minBtcBalance,
|
|
176
|
-
"Maximum must be greater than the minimum"
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
self.minBtcBalance = minBtcBalance;
|
|
180
|
-
self.maxBtcBalance = maxBtcBalance;
|
|
181
|
-
|
|
182
|
-
emit WalletBtcBalanceRangeUpdated(minBtcBalance, maxBtcBalance);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/// @notice Sets the wallet maximum age.
|
|
186
|
-
/// @param maxAge New value of the wallet maximum age
|
|
187
|
-
function setMaxAge(Data storage self, uint32 maxAge) external {
|
|
188
|
-
self.maxAge = maxAge;
|
|
189
|
-
|
|
190
|
-
emit WalletMaxAgeUpdated(maxAge);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
116
|
/// @notice Requests creation of a new wallet. This function just
|
|
194
117
|
/// forms a request and the creation process is performed
|
|
195
118
|
/// asynchronously. Outcome of that process should be delivered
|
|
@@ -210,11 +133,12 @@ library Wallets {
|
|
|
210
133
|
/// was elapsed since its creation time
|
|
211
134
|
/// - The active wallet BTC balance is above the maximum threshold
|
|
212
135
|
function requestNewWallet(
|
|
213
|
-
|
|
136
|
+
BridgeState.Storage storage self,
|
|
214
137
|
BitcoinTx.UTXO calldata activeWalletMainUtxo
|
|
215
138
|
) external {
|
|
216
139
|
require(
|
|
217
|
-
self.
|
|
140
|
+
self.ecdsaWalletRegistry.getWalletCreationState() ==
|
|
141
|
+
EcdsaDkg.State.IDLE,
|
|
218
142
|
"Wallet creation already in progress"
|
|
219
143
|
);
|
|
220
144
|
|
|
@@ -235,19 +159,19 @@ library Wallets {
|
|
|
235
159
|
.createdAt;
|
|
236
160
|
/* solhint-disable-next-line not-rely-on-time */
|
|
237
161
|
bool activeWalletOldEnough = block.timestamp >=
|
|
238
|
-
activeWalletCreatedAt + self.
|
|
162
|
+
activeWalletCreatedAt + self.walletCreationPeriod;
|
|
239
163
|
|
|
240
164
|
require(
|
|
241
165
|
(activeWalletOldEnough &&
|
|
242
|
-
activeWalletBtcBalance >= self.
|
|
243
|
-
activeWalletBtcBalance >= self.
|
|
166
|
+
activeWalletBtcBalance >= self.walletMinBtcBalance) ||
|
|
167
|
+
activeWalletBtcBalance >= self.walletMaxBtcBalance,
|
|
244
168
|
"Wallet creation conditions are not met"
|
|
245
169
|
);
|
|
246
170
|
}
|
|
247
171
|
|
|
248
172
|
emit NewWalletRequested();
|
|
249
173
|
|
|
250
|
-
self.
|
|
174
|
+
self.ecdsaWalletRegistry.requestNewWallet();
|
|
251
175
|
}
|
|
252
176
|
|
|
253
177
|
/// @notice Gets BTC balance for given the wallet.
|
|
@@ -261,7 +185,7 @@ library Wallets {
|
|
|
261
185
|
/// If the wallet has no main UTXO, this parameter can be empty as it
|
|
262
186
|
/// is ignored.
|
|
263
187
|
function getWalletBtcBalance(
|
|
264
|
-
|
|
188
|
+
BridgeState.Storage storage self,
|
|
265
189
|
bytes20 walletPubKeyHash,
|
|
266
190
|
BitcoinTx.UTXO calldata walletMainUtxo
|
|
267
191
|
) internal view returns (uint64 walletBtcBalance) {
|
|
@@ -300,13 +224,13 @@ library Wallets {
|
|
|
300
224
|
/// - The only caller authorized to call this function is `registry`
|
|
301
225
|
/// - Given wallet data must not belong to an already registered wallet
|
|
302
226
|
function registerNewWallet(
|
|
303
|
-
|
|
227
|
+
BridgeState.Storage storage self,
|
|
304
228
|
bytes32 ecdsaWalletID,
|
|
305
229
|
bytes32 publicKeyX,
|
|
306
230
|
bytes32 publicKeyY
|
|
307
231
|
) external {
|
|
308
232
|
require(
|
|
309
|
-
msg.sender == address(self.
|
|
233
|
+
msg.sender == address(self.ecdsaWalletRegistry),
|
|
310
234
|
"Caller is not the ECDSA Wallet Registry"
|
|
311
235
|
);
|
|
312
236
|
|
|
@@ -328,6 +252,8 @@ library Wallets {
|
|
|
328
252
|
// Set the freshly created wallet as the new active wallet.
|
|
329
253
|
self.activeWalletPubKeyHash = walletPubKeyHash;
|
|
330
254
|
|
|
255
|
+
self.liveWalletsCount++;
|
|
256
|
+
|
|
331
257
|
emit NewWalletRegistered(ecdsaWalletID, walletPubKeyHash);
|
|
332
258
|
}
|
|
333
259
|
|
|
@@ -339,12 +265,12 @@ library Wallets {
|
|
|
339
265
|
/// - The only caller authorized to call this function is `registry`
|
|
340
266
|
/// - Wallet must be in Live state
|
|
341
267
|
function notifyWalletHeartbeatFailed(
|
|
342
|
-
|
|
268
|
+
BridgeState.Storage storage self,
|
|
343
269
|
bytes32 publicKeyX,
|
|
344
270
|
bytes32 publicKeyY
|
|
345
271
|
) external {
|
|
346
272
|
require(
|
|
347
|
-
msg.sender == address(self.
|
|
273
|
+
msg.sender == address(self.ecdsaWalletRegistry),
|
|
348
274
|
"Caller is not the ECDSA Wallet Registry"
|
|
349
275
|
);
|
|
350
276
|
|
|
@@ -370,10 +296,10 @@ library Wallets {
|
|
|
370
296
|
/// @param walletPubKeyHash 20-byte public key hash of the wallet
|
|
371
297
|
/// @dev Requirements:
|
|
372
298
|
/// - The wallet must be in the `Live` or `MovingFunds` state
|
|
373
|
-
function
|
|
374
|
-
|
|
299
|
+
function notifyWalletTimedOutRedemption(
|
|
300
|
+
BridgeState.Storage storage self,
|
|
375
301
|
bytes20 walletPubKeyHash
|
|
376
|
-
)
|
|
302
|
+
) internal {
|
|
377
303
|
WalletState walletState = self
|
|
378
304
|
.registeredWallets[walletPubKeyHash]
|
|
379
305
|
.state;
|
|
@@ -408,7 +334,7 @@ library Wallets {
|
|
|
408
334
|
/// assumed to be zero.
|
|
409
335
|
/// - Wallet must be in Live state
|
|
410
336
|
function notifyCloseableWallet(
|
|
411
|
-
|
|
337
|
+
BridgeState.Storage storage self,
|
|
412
338
|
bytes20 walletPubKeyHash,
|
|
413
339
|
BitcoinTx.UTXO calldata walletMainUtxo
|
|
414
340
|
) external {
|
|
@@ -425,12 +351,12 @@ library Wallets {
|
|
|
425
351
|
|
|
426
352
|
/* solhint-disable-next-line not-rely-on-time */
|
|
427
353
|
bool walletOldEnough = block.timestamp >=
|
|
428
|
-
wallet.createdAt + self.
|
|
354
|
+
wallet.createdAt + self.walletMaxAge;
|
|
429
355
|
|
|
430
356
|
require(
|
|
431
357
|
walletOldEnough ||
|
|
432
358
|
getWalletBtcBalance(self, walletPubKeyHash, walletMainUtxo) <
|
|
433
|
-
self.
|
|
359
|
+
self.walletMinBtcBalance,
|
|
434
360
|
"Wallet needs to be old enough or have too few satoshis"
|
|
435
361
|
);
|
|
436
362
|
|
|
@@ -438,21 +364,23 @@ library Wallets {
|
|
|
438
364
|
}
|
|
439
365
|
|
|
440
366
|
/// @notice Requests a wallet to move their funds. If the wallet balance
|
|
441
|
-
/// is zero, the wallet
|
|
442
|
-
///
|
|
443
|
-
/// request refers to the current active wallet, such a wallet
|
|
367
|
+
/// is zero, the wallet closing begins immediately. If the move
|
|
368
|
+
/// funds request refers to the current active wallet, such a wallet
|
|
444
369
|
/// is no longer considered active and the active wallet slot
|
|
445
370
|
/// is unset allowing to trigger a new wallet creation immediately.
|
|
446
371
|
/// @param walletPubKeyHash 20-byte public key hash of the wallet
|
|
447
372
|
/// @dev Requirements:
|
|
448
373
|
/// - The caller must make sure that the wallet is in the Live state
|
|
449
|
-
function moveFunds(
|
|
374
|
+
function moveFunds(
|
|
375
|
+
BridgeState.Storage storage self,
|
|
376
|
+
bytes20 walletPubKeyHash
|
|
377
|
+
) internal {
|
|
450
378
|
Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
|
|
451
379
|
|
|
452
380
|
if (wallet.mainUtxoHash == bytes32(0)) {
|
|
453
381
|
// If the wallet has no main UTXO, that means its BTC balance
|
|
454
|
-
// is zero and
|
|
455
|
-
|
|
382
|
+
// is zero and the wallet closing should begin immediately.
|
|
383
|
+
beginWalletClosing(self, walletPubKeyHash);
|
|
456
384
|
} else {
|
|
457
385
|
// Otherwise, initialize the moving funds process.
|
|
458
386
|
wallet.state = WalletState.MovingFunds;
|
|
@@ -468,45 +396,49 @@ library Wallets {
|
|
|
468
396
|
// possible in order to get a new healthy active wallet.
|
|
469
397
|
delete self.activeWalletPubKeyHash;
|
|
470
398
|
}
|
|
399
|
+
|
|
400
|
+
self.liveWalletsCount--;
|
|
471
401
|
}
|
|
472
402
|
|
|
473
|
-
/// @notice
|
|
474
|
-
/// about this fact.
|
|
403
|
+
/// @notice Begins the closing period of the given wallet.
|
|
475
404
|
/// @param walletPubKeyHash 20-byte public key hash of the wallet
|
|
476
405
|
/// @dev Requirements:
|
|
477
406
|
/// - The caller must make sure that the wallet is in the
|
|
478
|
-
///
|
|
479
|
-
function
|
|
407
|
+
/// MovingFunds state
|
|
408
|
+
function beginWalletClosing(
|
|
409
|
+
BridgeState.Storage storage self,
|
|
410
|
+
bytes20 walletPubKeyHash
|
|
411
|
+
) internal {
|
|
480
412
|
Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
|
|
413
|
+
// Initialize the closing period.
|
|
414
|
+
wallet.state = WalletState.Closing;
|
|
415
|
+
/* solhint-disable-next-line not-rely-on-time */
|
|
416
|
+
wallet.closingStartedAt = uint32(block.timestamp);
|
|
481
417
|
|
|
482
|
-
wallet.
|
|
483
|
-
|
|
484
|
-
emit WalletClosed(wallet.ecdsaWalletID, walletPubKeyHash);
|
|
485
|
-
|
|
486
|
-
self.registry.closeWallet(wallet.ecdsaWalletID);
|
|
418
|
+
emit WalletClosing(wallet.ecdsaWalletID, walletPubKeyHash);
|
|
487
419
|
}
|
|
488
420
|
|
|
489
|
-
/// @notice
|
|
490
|
-
///
|
|
491
|
-
/// to a proven fraud and it should only be called when the fraud
|
|
492
|
-
/// was confirmed.
|
|
421
|
+
/// @notice Finalizes the closing period of the given wallet and notifies
|
|
422
|
+
/// the ECDSA registry about this fact.
|
|
493
423
|
/// @param walletPubKeyHash 20-byte public key hash of the wallet
|
|
494
424
|
/// @dev Requirements:
|
|
495
|
-
/// -
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
425
|
+
/// - The caller must make sure that the wallet is in the Closing state
|
|
426
|
+
///
|
|
427
|
+
/// TODO: Make this function callable from the Bridge contract if
|
|
428
|
+
/// `block.timestamp > wallet.closingStartedAt + self.walletClosingPeriod`.
|
|
429
|
+
///
|
|
430
|
+
// slither-disable-next-line dead-code
|
|
431
|
+
function finalizeWalletClosing(
|
|
432
|
+
BridgeState.Storage storage self,
|
|
433
|
+
bytes20 walletPubKeyHash
|
|
434
|
+
) internal {
|
|
435
|
+
Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
|
|
500
436
|
|
|
501
|
-
|
|
502
|
-
walletState == WalletState.Live ||
|
|
503
|
-
walletState == WalletState.MovingFunds,
|
|
504
|
-
"ECDSA wallet must be in Live or MovingFunds state"
|
|
505
|
-
);
|
|
437
|
+
wallet.state = WalletState.Closed;
|
|
506
438
|
|
|
507
|
-
|
|
439
|
+
emit WalletClosed(wallet.ecdsaWalletID, walletPubKeyHash);
|
|
508
440
|
|
|
509
|
-
|
|
441
|
+
self.ecdsaWalletRegistry.closeWallet(wallet.ecdsaWalletID);
|
|
510
442
|
}
|
|
511
443
|
|
|
512
444
|
/// @notice Terminates the given wallet and notifies the ECDSA registry
|
|
@@ -517,12 +449,17 @@ library Wallets {
|
|
|
517
449
|
/// @param walletPubKeyHash 20-byte public key hash of the wallet
|
|
518
450
|
/// @dev Requirements:
|
|
519
451
|
/// - The caller must make sure that the wallet is in the
|
|
520
|
-
/// Live or MovingFunds state.
|
|
521
|
-
function terminateWallet(
|
|
522
|
-
|
|
523
|
-
|
|
452
|
+
/// Live or MovingFunds or Closing state.
|
|
453
|
+
function terminateWallet(
|
|
454
|
+
BridgeState.Storage storage self,
|
|
455
|
+
bytes20 walletPubKeyHash
|
|
456
|
+
) internal {
|
|
524
457
|
Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
|
|
525
458
|
|
|
459
|
+
if (wallet.state == WalletState.Live) {
|
|
460
|
+
self.liveWalletsCount--;
|
|
461
|
+
}
|
|
462
|
+
|
|
526
463
|
wallet.state = WalletState.Terminated;
|
|
527
464
|
|
|
528
465
|
emit WalletTerminated(wallet.ecdsaWalletID, walletPubKeyHash);
|
|
@@ -534,7 +471,7 @@ library Wallets {
|
|
|
534
471
|
delete self.activeWalletPubKeyHash;
|
|
535
472
|
}
|
|
536
473
|
|
|
537
|
-
self.
|
|
474
|
+
self.ecdsaWalletRegistry.closeWallet(wallet.ecdsaWalletID);
|
|
538
475
|
}
|
|
539
476
|
|
|
540
477
|
/// @notice Notifies that the wallet completed the moving funds process
|
|
@@ -553,11 +490,11 @@ library Wallets {
|
|
|
553
490
|
/// wallet.
|
|
554
491
|
/// - The actual target wallets used in the moving funds transaction
|
|
555
492
|
/// must be exactly the same as the target wallets commitment.
|
|
556
|
-
function
|
|
557
|
-
|
|
493
|
+
function notifyWalletFundsMoved(
|
|
494
|
+
BridgeState.Storage storage self,
|
|
558
495
|
bytes20 walletPubKeyHash,
|
|
559
496
|
bytes32 targetWalletsHash
|
|
560
|
-
)
|
|
497
|
+
) internal {
|
|
561
498
|
Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
|
|
562
499
|
// Check that the wallet is in the MovingFunds state but don't check
|
|
563
500
|
// if the moving funds timeout is exceeded. That should give a
|
|
@@ -586,6 +523,6 @@ library Wallets {
|
|
|
586
523
|
// If funds were moved, the wallet has no longer a main UTXO.
|
|
587
524
|
delete wallet.mainUtxoHash;
|
|
588
525
|
|
|
589
|
-
|
|
526
|
+
beginWalletClosing(self, walletPubKeyHash);
|
|
590
527
|
}
|
|
591
528
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HardhatRuntimeEnvironment } from "hardhat/types"
|
|
2
|
+
import { DeployFunction } from "hardhat-deploy/types"
|
|
3
|
+
|
|
4
|
+
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
|
5
|
+
const { getNamedAccounts, deployments, helpers } = hre
|
|
6
|
+
const { log } = deployments
|
|
7
|
+
const { deployer } = await getNamedAccounts()
|
|
8
|
+
|
|
9
|
+
const Relay = await deployments.getOrNull("Relay")
|
|
10
|
+
|
|
11
|
+
if (Relay && helpers.address.isValid(Relay.address)) {
|
|
12
|
+
log(`using external Relay at ${Relay.address}`)
|
|
13
|
+
} else if (hre.network.name !== "hardhat") {
|
|
14
|
+
throw new Error("deployed Relay contract not found")
|
|
15
|
+
} else {
|
|
16
|
+
log("deploying Relay stub")
|
|
17
|
+
|
|
18
|
+
await deployments.deploy("Relay", {
|
|
19
|
+
contract: "TestRelay",
|
|
20
|
+
from: deployer,
|
|
21
|
+
log: true,
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default func
|
|
27
|
+
|
|
28
|
+
func.tags = ["Relay"]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { HardhatRuntimeEnvironment } from "hardhat/types"
|
|
2
|
+
import { DeployFunction } from "hardhat-deploy/types"
|
|
3
|
+
|
|
4
|
+
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
|
5
|
+
const { deployments, getNamedAccounts } = hre
|
|
6
|
+
const { deploy } = deployments
|
|
7
|
+
const { deployer } = await getNamedAccounts()
|
|
8
|
+
|
|
9
|
+
const Bank = await deploy("Bank", {
|
|
10
|
+
from: deployer,
|
|
11
|
+
args: [],
|
|
12
|
+
log: true,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
if (hre.network.tags.tenderly) {
|
|
16
|
+
await hre.tenderly.verify({
|
|
17
|
+
name: "Bank",
|
|
18
|
+
address: Bank.address,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default func
|
|
24
|
+
|
|
25
|
+
func.tags = ["Bank"]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { HardhatRuntimeEnvironment } from "hardhat/types"
|
|
2
|
+
import { DeployFunction } from "hardhat-deploy/types"
|
|
3
|
+
|
|
4
|
+
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
|
5
|
+
const { deployments, getNamedAccounts } = hre
|
|
6
|
+
const { deploy } = deployments
|
|
7
|
+
const { deployer, treasury } = await getNamedAccounts()
|
|
8
|
+
|
|
9
|
+
const Bank = await deployments.get("Bank")
|
|
10
|
+
const Relay = await deployments.get("Relay")
|
|
11
|
+
|
|
12
|
+
// TODO: Test for mainnet deployment that when `WalletRegistry` is provided
|
|
13
|
+
// in `external/mainnet/` directory it gets resolved correctly, and the deployment
|
|
14
|
+
// script from `@keep-network/ecdsa` is not invoked once again.
|
|
15
|
+
const WalletRegistry = await deployments.get("WalletRegistry")
|
|
16
|
+
|
|
17
|
+
const txProofDifficultyFactor = 6
|
|
18
|
+
|
|
19
|
+
const Deposit = await deploy("Deposit", { from: deployer, log: true })
|
|
20
|
+
const Sweep = await deploy("Sweep", { from: deployer, log: true })
|
|
21
|
+
const Redemption = await deploy("Redemption", { from: deployer, log: true })
|
|
22
|
+
const Wallets = await deploy("Wallets", { from: deployer, log: true })
|
|
23
|
+
const Fraud = await deploy("Fraud", { from: deployer, log: true })
|
|
24
|
+
const MovingFunds = await deploy("MovingFunds", {
|
|
25
|
+
from: deployer,
|
|
26
|
+
log: true,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const Bridge = await deploy("Bridge", {
|
|
30
|
+
from: deployer,
|
|
31
|
+
args: [
|
|
32
|
+
Bank.address,
|
|
33
|
+
Relay.address,
|
|
34
|
+
treasury,
|
|
35
|
+
WalletRegistry.address,
|
|
36
|
+
txProofDifficultyFactor,
|
|
37
|
+
],
|
|
38
|
+
libraries: {
|
|
39
|
+
Deposit: Deposit.address,
|
|
40
|
+
Sweep: Sweep.address,
|
|
41
|
+
Redemption: Redemption.address,
|
|
42
|
+
Wallets: Wallets.address,
|
|
43
|
+
Fraud: Fraud.address,
|
|
44
|
+
MovingFunds: MovingFunds.address,
|
|
45
|
+
},
|
|
46
|
+
log: true,
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
if (hre.network.tags.tenderly) {
|
|
50
|
+
await hre.tenderly.verify({
|
|
51
|
+
name: "Bridge",
|
|
52
|
+
address: Bridge.address,
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default func
|
|
58
|
+
|
|
59
|
+
func.tags = ["Bridge"]
|
|
60
|
+
func.dependencies = ["Bank", "Relay", "Treasury", "WalletRegistry"]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { HardhatRuntimeEnvironment } from "hardhat/types"
|
|
2
|
+
import { DeployFunction } from "hardhat-deploy/types"
|
|
3
|
+
|
|
4
|
+
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
|
5
|
+
const { getNamedAccounts, deployments } = hre
|
|
6
|
+
const { execute, log } = deployments
|
|
7
|
+
const { deployer } = await getNamedAccounts()
|
|
8
|
+
|
|
9
|
+
const Bridge = await deployments.get("Bridge")
|
|
10
|
+
|
|
11
|
+
log("updating Bridge in Bank")
|
|
12
|
+
|
|
13
|
+
await execute("Bank", { from: deployer }, "updateBridge", Bridge.address)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default func
|
|
17
|
+
|
|
18
|
+
func.tags = ["BankUpdateBridge"]
|
|
19
|
+
func.dependencies = ["Bank", "Bridge"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { HardhatRuntimeEnvironment } from "hardhat/types"
|
|
2
|
+
import { DeployFunction } from "hardhat-deploy/types"
|
|
3
|
+
|
|
4
|
+
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
|
5
|
+
const { getNamedAccounts, helpers } = hre
|
|
6
|
+
const { deployer, governance } = await getNamedAccounts()
|
|
7
|
+
|
|
8
|
+
await helpers.ownable.transferOwnership("Bank", governance, deployer)
|
|
9
|
+
|
|
10
|
+
await helpers.ownable.transferOwnership("Bridge", governance, deployer)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default func
|
|
14
|
+
|
|
15
|
+
func.tags = ["TransferOwnership"]
|
|
16
|
+
func.dependencies = ["Bank", "Bridge"]
|
|
17
|
+
func.runAtTheEnd = true
|