@keep-network/tbtc-v2 0.1.1-dev.96 → 0.1.1-dev.97

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 (71) hide show
  1. package/artifacts/Bank.json +3 -3
  2. package/artifacts/Bridge.json +43 -43
  3. package/artifacts/Deposit.json +7 -7
  4. package/artifacts/DepositSweep.json +7 -7
  5. package/artifacts/EcdsaDkgValidator.json +1 -1
  6. package/artifacts/EcdsaInactivity.json +1 -1
  7. package/artifacts/EcdsaSortitionPool.json +2 -2
  8. package/artifacts/Fraud.json +9 -9
  9. package/artifacts/KeepRegistry.json +1 -1
  10. package/artifacts/KeepStake.json +2 -2
  11. package/artifacts/KeepToken.json +2 -2
  12. package/artifacts/KeepTokenStaking.json +1 -1
  13. package/artifacts/MovingFunds.json +9 -9
  14. package/artifacts/NuCypherStakingEscrow.json +1 -1
  15. package/artifacts/NuCypherToken.json +2 -2
  16. package/artifacts/RandomBeaconStub.json +1 -1
  17. package/artifacts/Redemption.json +9 -9
  18. package/artifacts/ReimbursementPool.json +2 -2
  19. package/artifacts/Relay.json +9 -9
  20. package/artifacts/T.json +2 -2
  21. package/artifacts/TBTC.json +3 -3
  22. package/artifacts/TBTCToken.json +3 -3
  23. package/artifacts/TBTCVault.json +12 -12
  24. package/artifacts/TokenStaking.json +1 -1
  25. package/artifacts/TokenholderGovernor.json +9 -9
  26. package/artifacts/TokenholderTimelock.json +8 -8
  27. package/artifacts/VendingMachine.json +10 -10
  28. package/artifacts/VendingMachineKeep.json +1 -1
  29. package/artifacts/VendingMachineNuCypher.json +1 -1
  30. package/artifacts/WalletRegistry.json +5 -5
  31. package/artifacts/WalletRegistryGovernance.json +2 -2
  32. package/artifacts/Wallets.json +9 -9
  33. package/artifacts/solcInputs/{3cf46a7694ce157f71d9dbf4db692b09.json → 5e62cff1ead0900b07facca4b559e818.json} +5 -5
  34. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  35. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  36. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +1 -1
  37. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
  38. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +2 -2
  39. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  40. package/build/contracts/bridge/Bridge.sol/Bridge.json +61 -61
  41. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
  42. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +2 -2
  43. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +1 -1
  44. package/build/contracts/bridge/Deposit.sol/Deposit.json +2 -2
  45. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +1 -1
  46. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +2 -2
  47. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
  48. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
  49. package/build/contracts/bridge/Fraud.sol/Fraud.json +2 -2
  50. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +1 -1
  51. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
  52. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
  53. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +2 -2
  54. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
  55. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +2 -2
  56. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
  57. package/build/contracts/bridge/Redemption.sol/Redemption.json +2 -2
  58. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  59. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
  60. package/build/contracts/bridge/Wallets.sol/Wallets.json +2 -2
  61. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  62. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +1 -1
  63. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  64. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  65. package/contracts/bridge/Bridge.sol +2 -2
  66. package/contracts/bridge/Fraud.sol +7 -32
  67. package/contracts/bridge/MovingFunds.sol +18 -51
  68. package/contracts/bridge/Redemption.sol +5 -24
  69. package/contracts/bridge/Wallets.sol +309 -143
  70. package/export.json +32 -32
  71. package/package.json +1 -1
@@ -41,17 +41,19 @@ library Wallets {
41
41
  /// redemption requests and new deposit reveals are not accepted.
42
42
  MovingFunds,
43
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
44
+ /// closing period where it is still a subject of fraud challenges
45
45
  /// and must defend against them. This state is needed to protect
46
46
  /// against deposit frauds on deposits revealed but not swept.
47
47
  /// The closing period must be greater that the deposit refund
48
48
  /// time plus some time margin.
49
49
  Closing,
50
50
  /// @dev The wallet finalized the closing period successfully and
51
- /// cannot perform any action in the Bridge.
51
+ /// can no longer perform any action in the Bridge.
52
52
  Closed,
53
- /// @dev The wallet committed a fraud that was reported. The wallet is
54
- /// blocked and can not perform any actions in the Bridge.
53
+ /// @dev The wallet committed a fraud that was reported, did not move
54
+ /// funds to another wallet before a timeout, or did not sweep
55
+ /// funds moved to if from another wallet before a timeout. The
56
+ /// wallet is blocked and can not perform any actions in the Bridge.
55
57
  /// Off-chain coordination with the wallet operators is needed to
56
58
  /// recover funds.
57
59
  Terminated
@@ -180,46 +182,6 @@ library Wallets {
180
182
  self.ecdsaWalletRegistry.requestNewWallet();
181
183
  }
182
184
 
183
- /// @notice Gets BTC balance for given the wallet.
184
- /// @param walletPubKeyHash 20-byte public key hash of the wallet.
185
- /// @param walletMainUtxo Data of the wallet's main UTXO, as currently
186
- /// known on the Ethereum chain.
187
- /// @return walletBtcBalance Current BTC balance for the given wallet.
188
- /// @dev Requirements:
189
- /// - `walletMainUtxo` components must point to the recent main UTXO
190
- /// of the given wallet, as currently known on the Ethereum chain.
191
- /// If the wallet has no main UTXO, this parameter can be empty as it
192
- /// is ignored.
193
- function getWalletBtcBalance(
194
- BridgeState.Storage storage self,
195
- bytes20 walletPubKeyHash,
196
- BitcoinTx.UTXO calldata walletMainUtxo
197
- ) internal view returns (uint64 walletBtcBalance) {
198
- bytes32 walletMainUtxoHash = self
199
- .registeredWallets[walletPubKeyHash]
200
- .mainUtxoHash;
201
-
202
- // If the wallet has a main UTXO hash set, cross-check it with the
203
- // provided plain-text parameter and get the transaction output value
204
- // as BTC balance. Otherwise, the BTC balance is just zero.
205
- if (walletMainUtxoHash != bytes32(0)) {
206
- require(
207
- keccak256(
208
- abi.encodePacked(
209
- walletMainUtxo.txHash,
210
- walletMainUtxo.txOutputIndex,
211
- walletMainUtxo.txOutputValue
212
- )
213
- ) == walletMainUtxoHash,
214
- "Invalid wallet main UTXO data"
215
- );
216
-
217
- walletBtcBalance = walletMainUtxo.txOutputValue;
218
- }
219
-
220
- return walletBtcBalance;
221
- }
222
-
223
185
  /// @notice Registers a new wallet. This function should be called
224
186
  /// after the wallet creation process initiated using
225
187
  /// `requestNewWallet` completes and brings the outcomes.
@@ -263,6 +225,53 @@ library Wallets {
263
225
  emit NewWalletRegistered(ecdsaWalletID, walletPubKeyHash);
264
226
  }
265
227
 
228
+ /// @notice Handles a notification about a wallet redemption timeout.
229
+ /// Triggers the wallet moving funds process only if the wallet is
230
+ /// still in the Live state. That means multiple action timeouts can
231
+ /// be reported for the same wallet but only the first report
232
+ /// requests the wallet to move their funds. Executes slashing if
233
+ /// the wallet is in Live or MovingFunds state. Allows to notify
234
+ /// redemption timeout also for a Terminated wallet in case the
235
+ /// redemption was requested before the wallet got terminated.
236
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet.
237
+ /// @param walletMembersIDs Identifiers of the wallet signing group members.
238
+ /// @dev Requirements:
239
+ /// - The wallet must be in the `Live`, `MovingFunds`,
240
+ /// or `Terminated` state.
241
+ function notifyWalletRedemptionTimeout(
242
+ BridgeState.Storage storage self,
243
+ bytes20 walletPubKeyHash,
244
+ uint32[] calldata walletMembersIDs
245
+ ) internal {
246
+ Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
247
+ WalletState walletState = wallet.state;
248
+
249
+ require(
250
+ walletState == WalletState.Live ||
251
+ walletState == WalletState.MovingFunds ||
252
+ walletState == WalletState.Terminated,
253
+ "Wallet must be in Live or MovingFunds or Terminated state"
254
+ );
255
+
256
+ if (
257
+ walletState == Wallets.WalletState.Live ||
258
+ walletState == Wallets.WalletState.MovingFunds
259
+ ) {
260
+ // Slash the wallet operators and reward the notifier
261
+ self.ecdsaWalletRegistry.seize(
262
+ self.redemptionTimeoutSlashingAmount,
263
+ self.redemptionTimeoutNotifierRewardMultiplier,
264
+ msg.sender,
265
+ wallet.ecdsaWalletID,
266
+ walletMembersIDs
267
+ );
268
+ }
269
+
270
+ if (walletState == WalletState.Live) {
271
+ moveFunds(self, walletPubKeyHash);
272
+ }
273
+ }
274
+
266
275
  /// @notice Handles a notification about a wallet heartbeat failure and
267
276
  /// triggers the wallet moving funds process.
268
277
  /// @param publicKeyX Wallet's public key's X coordinate.
@@ -293,33 +302,6 @@ library Wallets {
293
302
  moveFunds(self, walletPubKeyHash);
294
303
  }
295
304
 
296
- /// @notice Handles a notification about a wallet redemption timeout.
297
- /// Triggers the wallet moving funds process only if the wallet is
298
- /// still in the Live state. That means multiple action timeouts can
299
- /// be reported for the same wallet but only the first report
300
- /// requests the wallet to move their funds.
301
- /// @param walletPubKeyHash 20-byte public key hash of the wallet.
302
- /// @dev Requirements:
303
- /// - The wallet must be in the `Live` or `MovingFunds` state.
304
- function notifyWalletTimedOutRedemption(
305
- BridgeState.Storage storage self,
306
- bytes20 walletPubKeyHash
307
- ) internal {
308
- WalletState walletState = self
309
- .registeredWallets[walletPubKeyHash]
310
- .state;
311
-
312
- require(
313
- walletState == WalletState.Live ||
314
- walletState == WalletState.MovingFunds,
315
- "Wallet must be in Live or MovingFunds state"
316
- );
317
-
318
- if (walletState == WalletState.Live) {
319
- moveFunds(self, walletPubKeyHash);
320
- }
321
- }
322
-
323
305
  /// @notice Notifies that the wallet is either old enough or has too few
324
306
  /// satoshis left and qualifies to be closed.
325
307
  /// @param walletPubKeyHash 20-byte public key hash of the wallet.
@@ -335,7 +317,7 @@ library Wallets {
335
317
  /// can be empty as it is ignored since the wallet balance is
336
318
  /// assumed to be zero,
337
319
  /// - Wallet must be in Live state.
338
- function notifyCloseableWallet(
320
+ function notifyWalletCloseable(
339
321
  BridgeState.Storage storage self,
340
322
  bytes20 walletPubKeyHash,
341
323
  BitcoinTx.UTXO calldata walletMainUtxo
@@ -365,6 +347,227 @@ library Wallets {
365
347
  moveFunds(self, walletPubKeyHash);
366
348
  }
367
349
 
350
+ /// @notice Notifies about the end of the closing period for the given wallet.
351
+ /// Closes the wallet ultimately and notifies the ECDSA registry
352
+ /// about this fact.
353
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet.
354
+ /// @dev Requirements:
355
+ /// - The wallet must be in the Closing state,
356
+ /// - The wallet closing period must have elapsed.
357
+ function notifyWalletClosingPeriodElapsed(
358
+ BridgeState.Storage storage self,
359
+ bytes20 walletPubKeyHash
360
+ ) internal {
361
+ Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
362
+
363
+ require(
364
+ wallet.state == WalletState.Closing,
365
+ "Wallet must be in Closing state"
366
+ );
367
+
368
+ require(
369
+ /* solhint-disable-next-line not-rely-on-time */
370
+ block.timestamp >
371
+ wallet.closingStartedAt + self.walletClosingPeriod,
372
+ "Closing period has not elapsed yet"
373
+ );
374
+
375
+ finalizeWalletClosing(self, walletPubKeyHash);
376
+ }
377
+
378
+ /// @notice Notifies that the wallet completed the moving funds process
379
+ /// successfully. Checks if the funds were moved to the expected
380
+ /// target wallets. Closes the source wallet if everything went
381
+ /// good and reverts otherwise.
382
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet.
383
+ /// @param targetWalletsHash 32-byte keccak256 hash over the list of
384
+ /// 20-byte public key hashes of the target wallets actually used
385
+ /// within the moving funds transactions.
386
+ /// @dev Requirements:
387
+ /// - The caller must make sure the moving funds transaction actually
388
+ /// happened on Bitcoin chain and fits the protocol requirements,
389
+ /// - The source wallet must be in the MovingFunds state,
390
+ /// - The target wallets commitment must be submitted by the source
391
+ /// wallet,
392
+ /// - The actual target wallets used in the moving funds transaction
393
+ /// must be exactly the same as the target wallets commitment.
394
+ function notifyWalletFundsMoved(
395
+ BridgeState.Storage storage self,
396
+ bytes20 walletPubKeyHash,
397
+ bytes32 targetWalletsHash
398
+ ) internal {
399
+ Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
400
+ // Check that the wallet is in the MovingFunds state but don't check
401
+ // if the moving funds timeout is exceeded. That should give a
402
+ // possibility to move funds in case when timeout was hit but was
403
+ // not reported yet.
404
+ require(
405
+ wallet.state == WalletState.MovingFunds,
406
+ "Wallet must be in MovingFunds state"
407
+ );
408
+
409
+ bytes32 targetWalletsCommitmentHash = wallet
410
+ .movingFundsTargetWalletsCommitmentHash;
411
+
412
+ require(
413
+ targetWalletsCommitmentHash != bytes32(0),
414
+ "Target wallets commitment not submitted yet"
415
+ );
416
+
417
+ // Make sure that the target wallets where funds were moved to are
418
+ // exactly the same as the ones the source wallet committed to.
419
+ require(
420
+ targetWalletsCommitmentHash == targetWalletsHash,
421
+ "Target wallets don't correspond to the commitment"
422
+ );
423
+
424
+ // If funds were moved, the wallet has no longer a main UTXO.
425
+ delete wallet.mainUtxoHash;
426
+
427
+ beginWalletClosing(self, walletPubKeyHash);
428
+ }
429
+
430
+ /// @notice Called when a MovingFunds wallet has a balance below the dust
431
+ /// threshold. Begins the wallet closing.
432
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet.
433
+ /// @dev Requirements:
434
+ /// - The wallet must be in the MovingFunds state.
435
+ function notifyWalletMovingFundsBelowDust(
436
+ BridgeState.Storage storage self,
437
+ bytes20 walletPubKeyHash
438
+ ) internal {
439
+ WalletState walletState = self
440
+ .registeredWallets[walletPubKeyHash]
441
+ .state;
442
+
443
+ require(
444
+ walletState == Wallets.WalletState.MovingFunds,
445
+ "Wallet must be in MovingFunds state"
446
+ );
447
+
448
+ beginWalletClosing(self, walletPubKeyHash);
449
+ }
450
+
451
+ /// @notice Called when the timeout for MovingFunds for the wallet elapsed.
452
+ /// Slashes wallet members and terminates the wallet.
453
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet.
454
+ /// @param walletMembersIDs Identifiers of the wallet signing group members.
455
+ /// @dev Requirements:
456
+ /// - The wallet must be in the MovingFunds state.
457
+ function notifyWalletMovingFundsTimeout(
458
+ BridgeState.Storage storage self,
459
+ bytes20 walletPubKeyHash,
460
+ uint32[] calldata walletMembersIDs
461
+ ) internal {
462
+ Wallets.Wallet storage wallet = self.registeredWallets[
463
+ walletPubKeyHash
464
+ ];
465
+
466
+ require(
467
+ wallet.state == Wallets.WalletState.MovingFunds,
468
+ "Wallet must be in MovingFunds state"
469
+ );
470
+
471
+ self.ecdsaWalletRegistry.seize(
472
+ self.movingFundsTimeoutSlashingAmount,
473
+ self.movingFundsTimeoutNotifierRewardMultiplier,
474
+ msg.sender,
475
+ wallet.ecdsaWalletID,
476
+ walletMembersIDs
477
+ );
478
+
479
+ terminateWallet(self, walletPubKeyHash);
480
+ }
481
+
482
+ /// @notice Called when a wallet which was asked to sweep funds moved from
483
+ /// another wallet did not provide a sweeping proof before a timeout.
484
+ /// Slashes and terminates the wallet who failed to provide a proof.
485
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet which was
486
+ /// supposed to sweep funds.
487
+ /// @param walletMembersIDs Identifiers of the wallet signing group members.
488
+ /// @dev Requirements:
489
+ /// - The wallet must be in the `Live`, `MovingFunds`,
490
+ /// or `Terminated` state.
491
+ function notifyWalletMovedFundsSweepTimeout(
492
+ BridgeState.Storage storage self,
493
+ bytes20 walletPubKeyHash,
494
+ uint32[] calldata walletMembersIDs
495
+ ) internal {
496
+ Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
497
+ WalletState walletState = wallet.state;
498
+
499
+ require(
500
+ walletState == WalletState.Live ||
501
+ walletState == WalletState.MovingFunds ||
502
+ walletState == WalletState.Terminated,
503
+ "Wallet must be in Live or MovingFunds or Terminated state"
504
+ );
505
+
506
+ if (
507
+ walletState == Wallets.WalletState.Live ||
508
+ walletState == Wallets.WalletState.MovingFunds
509
+ ) {
510
+ self.ecdsaWalletRegistry.seize(
511
+ self.movedFundsSweepTimeoutSlashingAmount,
512
+ self.movedFundsSweepTimeoutNotifierRewardMultiplier,
513
+ msg.sender,
514
+ wallet.ecdsaWalletID,
515
+ walletMembersIDs
516
+ );
517
+
518
+ terminateWallet(self, walletPubKeyHash);
519
+ }
520
+ }
521
+
522
+ /// @notice Called when a wallet which was challenged for a fraud did not
523
+ /// defeat the challenge before the timeout. Slashes and terminates
524
+ /// the wallet who failed to defeat the challenge. If the wallet is
525
+ /// already terminated, it does nothing.
526
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet which was
527
+ /// supposed to sweep funds.
528
+ /// @param walletMembersIDs Identifiers of the wallet signing group members.
529
+ /// @param challenger Address of the party which submitted the fraud
530
+ /// challenge.
531
+ /// @dev Requirements:
532
+ /// - The wallet must be in the `Live`, `MovingFunds`, `Closing`
533
+ /// or `Terminated` state.
534
+ function notifyWalletFraudChallengeDefeatTimeout(
535
+ BridgeState.Storage storage self,
536
+ bytes20 walletPubKeyHash,
537
+ uint32[] calldata walletMembersIDs,
538
+ address challenger
539
+ ) internal {
540
+ Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
541
+ WalletState walletState = wallet.state;
542
+
543
+ if (
544
+ walletState == Wallets.WalletState.Live ||
545
+ walletState == Wallets.WalletState.MovingFunds ||
546
+ walletState == Wallets.WalletState.Closing
547
+ ) {
548
+ self.ecdsaWalletRegistry.seize(
549
+ self.fraudSlashingAmount,
550
+ self.fraudNotifierRewardMultiplier,
551
+ challenger,
552
+ wallet.ecdsaWalletID,
553
+ walletMembersIDs
554
+ );
555
+
556
+ terminateWallet(self, walletPubKeyHash);
557
+ } else if (walletState == Wallets.WalletState.Terminated) {
558
+ // This is a special case when the wallet was already terminated
559
+ // due to a previous deliberate protocol violation. In that
560
+ // case, this function should be still callable for other fraud
561
+ // challenges timeouts in order to let the challenger unlock its
562
+ // ETH deposit back. However, the wallet termination logic is
563
+ // not called and the challenger is not rewarded.
564
+ } else {
565
+ revert(
566
+ "Wallet must be in Live or MovingFunds or Closing or Terminated state"
567
+ );
568
+ }
569
+ }
570
+
368
571
  /// @notice Requests a wallet to move their funds. If the wallet balance
369
572
  /// is zero, the wallet closing begins immediately. If the move
370
573
  /// funds request refers to the current active wallet, such a wallet
@@ -389,6 +592,7 @@ library Wallets {
389
592
  /* solhint-disable-next-line not-rely-on-time */
390
593
  wallet.movingFundsRequestedAt = uint32(block.timestamp);
391
594
 
595
+ // slither-disable-next-line reentrancy-events
392
596
  emit WalletMovingFunds(wallet.ecdsaWalletID, walletPubKeyHash);
393
597
  }
394
598
 
@@ -417,37 +621,10 @@ library Wallets {
417
621
  /* solhint-disable-next-line not-rely-on-time */
418
622
  wallet.closingStartedAt = uint32(block.timestamp);
419
623
 
624
+ // slither-disable-next-line reentrancy-events
420
625
  emit WalletClosing(wallet.ecdsaWalletID, walletPubKeyHash);
421
626
  }
422
627
 
423
- /// @notice Notifies about the end of the closing period for the given wallet.
424
- /// Closes the wallet ultimately and notifies the ECDSA registry
425
- /// about this fact.
426
- /// @param walletPubKeyHash 20-byte public key hash of the wallet.
427
- /// @dev Requirements:
428
- /// - The wallet must be in the Closing state,
429
- /// - The wallet closing period must have elapsed.
430
- function notifyWalletClosingPeriodElapsed(
431
- BridgeState.Storage storage self,
432
- bytes20 walletPubKeyHash
433
- ) internal {
434
- Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
435
-
436
- require(
437
- wallet.state == WalletState.Closing,
438
- "Wallet must be in Closing state"
439
- );
440
-
441
- require(
442
- /* solhint-disable-next-line not-rely-on-time */
443
- block.timestamp >
444
- wallet.closingStartedAt + self.walletClosingPeriod,
445
- "Closing period has not elapsed yet"
446
- );
447
-
448
- finalizeWalletClosing(self, walletPubKeyHash);
449
- }
450
-
451
628
  /// @notice Finalizes the closing period of the given wallet and notifies
452
629
  /// the ECDSA registry about this fact.
453
630
  /// @param walletPubKeyHash 20-byte public key hash of the wallet.
@@ -487,6 +664,7 @@ library Wallets {
487
664
 
488
665
  wallet.state = WalletState.Terminated;
489
666
 
667
+ // slither-disable-next-line reentrancy-events
490
668
  emit WalletTerminated(wallet.ecdsaWalletID, walletPubKeyHash);
491
669
 
492
670
  if (self.activeWalletPubKeyHash == walletPubKeyHash) {
@@ -499,55 +677,43 @@ library Wallets {
499
677
  self.ecdsaWalletRegistry.closeWallet(wallet.ecdsaWalletID);
500
678
  }
501
679
 
502
- /// @notice Notifies that the wallet completed the moving funds process
503
- /// successfully. Checks if the funds were moved to the expected
504
- /// target wallets. Closes the source wallet if everything went
505
- /// good and reverts otherwise.
680
+ /// @notice Gets BTC balance for given the wallet.
506
681
  /// @param walletPubKeyHash 20-byte public key hash of the wallet.
507
- /// @param targetWalletsHash 32-byte keccak256 hash over the list of
508
- /// 20-byte public key hashes of the target wallets actually used
509
- /// within the moving funds transactions.
682
+ /// @param walletMainUtxo Data of the wallet's main UTXO, as currently
683
+ /// known on the Ethereum chain.
684
+ /// @return walletBtcBalance Current BTC balance for the given wallet.
510
685
  /// @dev Requirements:
511
- /// - The caller must make sure the moving funds transaction actually
512
- /// happened on Bitcoin chain and fits the protocol requirements,
513
- /// - The source wallet must be in the MovingFunds state,
514
- /// - The target wallets commitment must be submitted by the source
515
- /// wallet,
516
- /// - The actual target wallets used in the moving funds transaction
517
- /// must be exactly the same as the target wallets commitment.
518
- function notifyWalletFundsMoved(
686
+ /// - `walletMainUtxo` components must point to the recent main UTXO
687
+ /// of the given wallet, as currently known on the Ethereum chain.
688
+ /// If the wallet has no main UTXO, this parameter can be empty as it
689
+ /// is ignored.
690
+ function getWalletBtcBalance(
519
691
  BridgeState.Storage storage self,
520
692
  bytes20 walletPubKeyHash,
521
- bytes32 targetWalletsHash
522
- ) internal {
523
- Wallet storage wallet = self.registeredWallets[walletPubKeyHash];
524
- // Check that the wallet is in the MovingFunds state but don't check
525
- // if the moving funds timeout is exceeded. That should give a
526
- // possibility to move funds in case when timeout was hit but was
527
- // not reported yet.
528
- require(
529
- wallet.state == WalletState.MovingFunds,
530
- "Wallet must be in MovingFunds state"
531
- );
532
-
533
- bytes32 targetWalletsCommitmentHash = wallet
534
- .movingFundsTargetWalletsCommitmentHash;
535
-
536
- require(
537
- targetWalletsCommitmentHash != bytes32(0),
538
- "Target wallets commitment not submitted yet"
539
- );
693
+ BitcoinTx.UTXO calldata walletMainUtxo
694
+ ) internal view returns (uint64 walletBtcBalance) {
695
+ bytes32 walletMainUtxoHash = self
696
+ .registeredWallets[walletPubKeyHash]
697
+ .mainUtxoHash;
540
698
 
541
- // Make sure that the target wallets where funds were moved to are
542
- // exactly the same as the ones the source wallet committed to.
543
- require(
544
- targetWalletsCommitmentHash == targetWalletsHash,
545
- "Target wallets don't correspond to the commitment"
546
- );
699
+ // If the wallet has a main UTXO hash set, cross-check it with the
700
+ // provided plain-text parameter and get the transaction output value
701
+ // as BTC balance. Otherwise, the BTC balance is just zero.
702
+ if (walletMainUtxoHash != bytes32(0)) {
703
+ require(
704
+ keccak256(
705
+ abi.encodePacked(
706
+ walletMainUtxo.txHash,
707
+ walletMainUtxo.txOutputIndex,
708
+ walletMainUtxo.txOutputValue
709
+ )
710
+ ) == walletMainUtxoHash,
711
+ "Invalid wallet main UTXO data"
712
+ );
547
713
 
548
- // If funds were moved, the wallet has no longer a main UTXO.
549
- delete wallet.mainUtxoHash;
714
+ walletBtcBalance = walletMainUtxo.txOutputValue;
715
+ }
550
716
 
551
- beginWalletClosing(self, walletPubKeyHash);
717
+ return walletBtcBalance;
552
718
  }
553
719
  }
package/export.json CHANGED
@@ -15267,38 +15267,6 @@
15267
15267
  }
15268
15268
  ]
15269
15269
  },
15270
- {
15271
- "type": "function",
15272
- "name": "notifyCloseableWallet",
15273
- "constant": false,
15274
- "payable": false,
15275
- "gas": 29000000,
15276
- "inputs": [
15277
- {
15278
- "type": "bytes20",
15279
- "name": "walletPubKeyHash"
15280
- },
15281
- {
15282
- "type": "tuple",
15283
- "name": "walletMainUtxo",
15284
- "components": [
15285
- {
15286
- "type": "bytes32",
15287
- "name": "txHash"
15288
- },
15289
- {
15290
- "type": "uint32",
15291
- "name": "txOutputIndex"
15292
- },
15293
- {
15294
- "type": "uint64",
15295
- "name": "txOutputValue"
15296
- }
15297
- ]
15298
- }
15299
- ],
15300
- "outputs": []
15301
- },
15302
15270
  {
15303
15271
  "type": "function",
15304
15272
  "name": "notifyFraudChallengeDefeatTimeout",
@@ -15415,6 +15383,38 @@
15415
15383
  ],
15416
15384
  "outputs": []
15417
15385
  },
15386
+ {
15387
+ "type": "function",
15388
+ "name": "notifyWalletCloseable",
15389
+ "constant": false,
15390
+ "payable": false,
15391
+ "gas": 29000000,
15392
+ "inputs": [
15393
+ {
15394
+ "type": "bytes20",
15395
+ "name": "walletPubKeyHash"
15396
+ },
15397
+ {
15398
+ "type": "tuple",
15399
+ "name": "walletMainUtxo",
15400
+ "components": [
15401
+ {
15402
+ "type": "bytes32",
15403
+ "name": "txHash"
15404
+ },
15405
+ {
15406
+ "type": "uint32",
15407
+ "name": "txOutputIndex"
15408
+ },
15409
+ {
15410
+ "type": "uint64",
15411
+ "name": "txOutputValue"
15412
+ }
15413
+ ]
15414
+ }
15415
+ ],
15416
+ "outputs": []
15417
+ },
15418
15418
  {
15419
15419
  "type": "function",
15420
15420
  "name": "notifyWalletClosingPeriodElapsed",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keep-network/tbtc-v2",
3
- "version": "0.1.1-dev.96+main.5131d26731c4fd456a3943a2d889d7356624a67d",
3
+ "version": "0.1.1-dev.97+main.a22deeca0ba51d31473ab19c2cfd708912cd27e8",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "artifacts/",