@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.
Files changed (81) hide show
  1. package/artifacts/Bank.json +742 -0
  2. package/artifacts/Bridge.json +2914 -0
  3. package/artifacts/Deposit.json +117 -0
  4. package/artifacts/EcdsaDkgValidator.json +532 -0
  5. package/artifacts/EcdsaInactivity.json +156 -0
  6. package/artifacts/Fraud.json +153 -0
  7. package/artifacts/KeepRegistry.json +99 -0
  8. package/artifacts/KeepStake.json +286 -0
  9. package/artifacts/KeepToken.json +711 -0
  10. package/artifacts/KeepTokenStaking.json +483 -0
  11. package/artifacts/MovingFunds.json +137 -0
  12. package/artifacts/NuCypherStakingEscrow.json +256 -0
  13. package/artifacts/NuCypherToken.json +711 -0
  14. package/artifacts/RandomBeaconStub.json +141 -0
  15. package/artifacts/Redemption.json +161 -0
  16. package/artifacts/ReimbursementPool.json +509 -0
  17. package/artifacts/Relay.json +123 -0
  18. package/artifacts/SortitionPool.json +944 -0
  19. package/artifacts/Sweep.json +76 -0
  20. package/artifacts/T.json +1148 -0
  21. package/artifacts/TBTC.json +21 -21
  22. package/artifacts/TBTCToken.json +21 -21
  23. package/artifacts/TokenStaking.json +2288 -0
  24. package/artifacts/TokenholderGovernor.json +1795 -0
  25. package/artifacts/TokenholderTimelock.json +1058 -0
  26. package/artifacts/VendingMachine.json +24 -24
  27. package/artifacts/VendingMachineKeep.json +400 -0
  28. package/artifacts/VendingMachineNuCypher.json +400 -0
  29. package/artifacts/WalletRegistry.json +2709 -0
  30. package/artifacts/WalletRegistryGovernance.json +2364 -0
  31. package/artifacts/Wallets.json +186 -0
  32. package/artifacts/solcInputs/{e9b173393b9fd7287a0bfaa6d4eb4b71.json → bbe44823ec28554a9429cce5cafee035.json} +34 -34
  33. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  34. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  35. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
  36. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +2 -2
  37. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  38. package/build/contracts/bridge/Bridge.sol/Bridge.json +535 -273
  39. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
  40. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +147 -3
  41. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +1 -1
  42. package/build/contracts/bridge/Deposit.sol/Deposit.json +2 -2
  43. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
  44. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +2 -2
  45. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
  46. package/build/contracts/bridge/Fraud.sol/Fraud.json +5 -57
  47. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
  48. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
  49. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +41 -21
  50. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
  51. package/build/contracts/bridge/{Redeem.sol → Redemption.sol}/OutboundTx.json +3 -3
  52. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
  53. package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
  54. package/build/contracts/bridge/Sweep.sol/Sweep.dbg.json +1 -1
  55. package/build/contracts/bridge/Sweep.sol/Sweep.json +2 -2
  56. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  57. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
  58. package/build/contracts/bridge/Wallets.sol/Wallets.json +12 -38
  59. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  60. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  61. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  62. package/contracts/bridge/BitcoinTx.sol +19 -26
  63. package/contracts/bridge/Bridge.sol +765 -524
  64. package/contracts/bridge/BridgeState.sol +312 -23
  65. package/contracts/bridge/Deposit.sol +25 -6
  66. package/contracts/bridge/EcdsaLib.sol +15 -0
  67. package/contracts/bridge/Fraud.sol +65 -33
  68. package/contracts/bridge/MovingFunds.sol +196 -10
  69. package/contracts/bridge/{Redeem.sol → Redemption.sol} +26 -29
  70. package/contracts/bridge/Sweep.sol +16 -12
  71. package/contracts/bridge/Wallets.sol +90 -153
  72. package/deploy/00_resolve_relay.ts +28 -0
  73. package/deploy/04_deploy_bank.ts +25 -0
  74. package/deploy/05_deploy_bridge.ts +60 -0
  75. package/deploy/06_bank_update_bridge.ts +19 -0
  76. package/deploy/07_transfer_ownership.ts +17 -0
  77. package/export.json +14797 -459
  78. package/package.json +2 -2
  79. package/build/contracts/bridge/Redeem.sol/OutboundTx.dbg.json +0 -4
  80. package/build/contracts/bridge/Redeem.sol/Redeem.dbg.json +0 -4
  81. 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 cannot
69
- /// perform any action.
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
- Data storage self,
136
+ BridgeState.Storage storage self,
214
137
  BitcoinTx.UTXO calldata activeWalletMainUtxo
215
138
  ) external {
216
139
  require(
217
- self.registry.getWalletCreationState() == EcdsaDkg.State.IDLE,
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.creationPeriod;
162
+ activeWalletCreatedAt + self.walletCreationPeriod;
239
163
 
240
164
  require(
241
165
  (activeWalletOldEnough &&
242
- activeWalletBtcBalance >= self.minBtcBalance) ||
243
- activeWalletBtcBalance >= self.maxBtcBalance,
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.registry.requestNewWallet();
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
- Data storage self,
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
- Data storage self,
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.registry),
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
- Data storage self,
268
+ BridgeState.Storage storage self,
343
269
  bytes32 publicKeyX,
344
270
  bytes32 publicKeyY
345
271
  ) external {
346
272
  require(
347
- msg.sender == address(self.registry),
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 notifyRedemptionTimedOut(
374
- Data storage self,
299
+ function notifyWalletTimedOutRedemption(
300
+ BridgeState.Storage storage self,
375
301
  bytes20 walletPubKeyHash
376
- ) external {
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
- Data storage self,
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.maxAge;
354
+ wallet.createdAt + self.walletMaxAge;
429
355
 
430
356
  require(
431
357
  walletOldEnough ||
432
358
  getWalletBtcBalance(self, walletPubKeyHash, walletMainUtxo) <
433
- self.minBtcBalance,
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 is closed immediately and the ECDSA
442
- /// registry is notified about this fact. If the move funds
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(Data storage self, bytes20 walletPubKeyHash) internal {
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 it should be closed immediately.
455
- closeWallet(self, walletPubKeyHash);
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 Closes the given wallet and notifies the ECDSA registry
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
- /// Live or MovingFunds state.
479
- function closeWallet(Data storage self, bytes20 walletPubKeyHash) internal {
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.state = WalletState.Closed;
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 Reports about a fraud committed by the given wallet. This
490
- /// function performs slashing and wallet termination in reaction
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
- /// - Wallet must be in Live or MovingFunds state
496
- function notifyFraud(Data storage self, bytes20 walletPubKeyHash) external {
497
- WalletState walletState = self
498
- .registeredWallets[walletPubKeyHash]
499
- .state;
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
- require(
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
- terminateWallet(self, walletPubKeyHash);
439
+ emit WalletClosed(wallet.ecdsaWalletID, walletPubKeyHash);
508
440
 
509
- // TODO: Perform slashing of wallet operators and add unit tests for that.
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(Data storage self, bytes20 walletPubKeyHash)
522
- internal
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.registry.closeWallet(wallet.ecdsaWalletID);
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 notifyFundsMoved(
557
- Data storage self,
493
+ function notifyWalletFundsMoved(
494
+ BridgeState.Storage storage self,
558
495
  bytes20 walletPubKeyHash,
559
496
  bytes32 targetWalletsHash
560
- ) external {
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
- closeWallet(self, walletPubKeyHash);
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