@keep-network/tbtc-v2 0.1.1-dev.52 → 0.1.1-dev.55

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 (68) hide show
  1. package/artifacts/Bank.json +3 -3
  2. package/artifacts/Bridge.json +293 -187
  3. package/artifacts/Deposit.json +7 -7
  4. package/artifacts/EcdsaDkgValidator.json +1 -1
  5. package/artifacts/EcdsaInactivity.json +1 -1
  6. package/artifacts/Fraud.json +10 -10
  7. package/artifacts/KeepRegistry.json +1 -1
  8. package/artifacts/KeepStake.json +2 -2
  9. package/artifacts/KeepToken.json +2 -2
  10. package/artifacts/KeepTokenStaking.json +1 -1
  11. package/artifacts/MovingFunds.json +13 -12
  12. package/artifacts/NuCypherStakingEscrow.json +1 -1
  13. package/artifacts/NuCypherToken.json +2 -2
  14. package/artifacts/RandomBeaconStub.json +1 -1
  15. package/artifacts/Redemption.json +14 -13
  16. package/artifacts/ReimbursementPool.json +2 -2
  17. package/artifacts/Relay.json +9 -9
  18. package/artifacts/SortitionPool.json +2 -2
  19. package/artifacts/Sweep.json +7 -7
  20. package/artifacts/T.json +2 -2
  21. package/artifacts/TBTC.json +3 -3
  22. package/artifacts/TBTCToken.json +3 -3
  23. package/artifacts/TokenStaking.json +1 -1
  24. package/artifacts/TokenholderGovernor.json +9 -9
  25. package/artifacts/TokenholderTimelock.json +8 -8
  26. package/artifacts/VendingMachine.json +10 -10
  27. package/artifacts/VendingMachineKeep.json +1 -1
  28. package/artifacts/VendingMachineNuCypher.json +1 -1
  29. package/artifacts/WalletRegistry.json +2 -2
  30. package/artifacts/WalletRegistryGovernance.json +2 -2
  31. package/artifacts/Wallets.json +9 -9
  32. package/artifacts/solcInputs/{dcf2fc19e497270603c798faeb0a9ba9.json → 6d69fc514efd874ebb1cb86b04981772.json} +7 -7
  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 +139 -65
  39. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
  40. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +37 -13
  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/Fraud.sol/Fraud.dbg.json +1 -1
  45. package/build/contracts/bridge/Fraud.sol/Fraud.json +2 -2
  46. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
  47. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
  48. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +2 -2
  49. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
  50. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +2 -2
  51. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
  52. package/build/contracts/bridge/Redemption.sol/Redemption.json +2 -2
  53. package/build/contracts/bridge/Sweep.sol/Sweep.dbg.json +1 -1
  54. package/build/contracts/bridge/Sweep.sol/Sweep.json +2 -2
  55. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  56. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
  57. package/build/contracts/bridge/Wallets.sol/Wallets.json +2 -2
  58. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  59. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  60. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  61. package/contracts/bridge/Bridge.sol +147 -64
  62. package/contracts/bridge/BridgeState.sol +110 -47
  63. package/contracts/bridge/Fraud.sol +1 -1
  64. package/contracts/bridge/MovingFunds.sol +16 -3
  65. package/contracts/bridge/Redemption.sol +34 -12
  66. package/contracts/bridge/Wallets.sol +5 -9
  67. package/export.json +105 -44
  68. package/package.json +1 -1
@@ -83,17 +83,24 @@ library BridgeState {
83
83
  // if per single redemption. `movingFundsTxMaxTotalFee` is a total
84
84
  // fee for the entire transaction.
85
85
  uint64 movingFundsTxMaxTotalFee;
86
- // Time after which the moving funds process can be reported as
87
- // timed out. It is counted from the moment when the wallet
88
- // was requested to move their funds and switched to the MovingFunds
89
- // state. Value in seconds.
90
- uint32 movingFundsTimeout;
91
86
  // The minimal satoshi amount that makes sense to be transferred during
92
87
  // the moving funds process. Moving funds wallets having their BTC
93
88
  // balance below that value can begin closing immediately as
94
89
  // transferring such a low value may not be possible due to
95
90
  // BTC network fees.
96
91
  uint64 movingFundsDustThreshold;
92
+ // Time after which the moving funds process can be reported as
93
+ // timed out. It is counted from the moment when the wallet
94
+ // was requested to move their funds and switched to the MovingFunds
95
+ // state. Value in seconds.
96
+ uint32 movingFundsTimeout;
97
+ // The amount of stake slashed from each member of a wallet for a moving
98
+ // funds timeout.
99
+ uint96 movingFundsTimeoutSlashingAmount;
100
+ // The percentage of the notifier reward from the staking contract
101
+ // the notifier of a moving funds timeout receives. The value is in the
102
+ // range [0, 100].
103
+ uint256 movingFundsTimeoutNotifierRewardMultiplier;
97
104
  // The minimal amount that can be requested for redemption.
98
105
  // Value of this parameter must take into account the value of
99
106
  // `redemptionTreasuryFeeDivisor` and `redemptionTxMaxFee`
@@ -122,6 +129,13 @@ library BridgeState {
122
129
  // timed out requests are cancelled and locked TBTC is returned
123
130
  // to the redeemer in full amount.
124
131
  uint256 redemptionTimeout;
132
+ // The amount of stake slashed from each member of a wallet for a
133
+ // redemption timeout.
134
+ uint96 redemptionTimeoutSlashingAmount;
135
+ // The percentage of the notifier reward from the staking contract
136
+ // the notifier of a redemption timeout receives. The value is in the
137
+ // range [0, 100].
138
+ uint256 redemptionTimeoutNotifierRewardMultiplier;
125
139
  // Collection of all pending redemption requests indexed by
126
140
  // redemption key built as
127
141
  // `keccak256(walletPubKeyHash | redeemerOutputScript)`.
@@ -151,16 +165,16 @@ library BridgeState {
151
165
  // mapping basing on a timed out request stored previously in
152
166
  // `pendingRedemptions` mapping.
153
167
  mapping(uint256 => Redemption.RedemptionRequest) timedOutRedemptions;
168
+ // The amount of ETH in wei the party challenging the wallet for fraud
169
+ // needs to deposit.
170
+ uint256 fraudChallengeDepositAmount;
171
+ // The amount of time the wallet has to defeat a fraud challenge.
172
+ uint256 fraudChallengeDefeatTimeout;
154
173
  // The amount of stake slashed from each member of a wallet for a fraud.
155
174
  uint96 fraudSlashingAmount;
156
175
  // The percentage of the notifier reward from the staking contract
157
176
  // the notifier of a fraud receives. The value is in the range [0, 100].
158
177
  uint256 fraudNotifierRewardMultiplier;
159
- // The amount of time the wallet has to defeat a fraud challenge.
160
- uint256 fraudChallengeDefeatTimeout;
161
- // The amount of ETH in wei the party challenging the wallet for fraud
162
- // needs to deposit.
163
- uint256 fraudChallengeDepositAmount;
164
178
  // Collection of all submitted fraud challenges indexed by challenge
165
179
  // key built as `keccak256(walletPublicKey|sighash)`.
166
180
  mapping(uint256 => Fraud.FraudChallenge) fraudChallenges;
@@ -222,13 +236,17 @@ library BridgeState {
222
236
  uint64 redemptionDustThreshold,
223
237
  uint64 redemptionTreasuryFeeDivisor,
224
238
  uint64 redemptionTxMaxFee,
225
- uint256 redemptionTimeout
239
+ uint256 redemptionTimeout,
240
+ uint96 redemptionTimeoutSlashingAmount,
241
+ uint256 redemptionTimeoutNotifierRewardMultiplier
226
242
  );
227
243
 
228
244
  event MovingFundsParametersUpdated(
229
245
  uint64 movingFundsTxMaxTotalFee,
246
+ uint64 movingFundsDustThreshold,
230
247
  uint32 movingFundsTimeout,
231
- uint64 movingFundsDustThreshold
248
+ uint96 movingFundsTimeoutSlashingAmount,
249
+ uint256 movingFundsTimeoutNotifierRewardMultiplier
232
250
  );
233
251
 
234
252
  event WalletParametersUpdated(
@@ -242,10 +260,10 @@ library BridgeState {
242
260
  );
243
261
 
244
262
  event FraudParametersUpdated(
245
- uint96 fraudSlashingAmount,
246
- uint256 fraudNotifierRewardMultiplier,
263
+ uint256 fraudChallengeDepositAmount,
247
264
  uint256 fraudChallengeDefeatTimeout,
248
- uint256 fraudChallengeDepositAmount
265
+ uint96 fraudSlashingAmount,
266
+ uint256 fraudNotifierRewardMultiplier
249
267
  );
250
268
 
251
269
  /// @notice Updates parameters of deposits.
@@ -334,17 +352,29 @@ library BridgeState {
334
352
  /// request was created via `requestRedemption` call. Reported timed
335
353
  /// out requests are cancelled and locked TBTC is returned to the
336
354
  /// redeemer in full amount.
355
+ /// @param _redemptionTimeoutSlashingAmount New value of the redemption
356
+ /// timeout slashing amount in T, it is the amount slashed from each
357
+ /// wallet member for redemption timeout
358
+ /// @param _redemptionTimeoutNotifierRewardMultiplier New value of the
359
+ /// redemption timeout notifier reward multiplier as percentage,
360
+ /// it determines the percentage of the notifier reward from the
361
+ /// staking contact the notifier of a redemption timeout receives.
362
+ /// The value must be in the range [0, 100]
337
363
  /// @dev Requirements:
338
364
  /// - Redemption dust threshold must be greater than zero
339
365
  /// - Redemption treasury fee divisor must be greater than zero
340
366
  /// - Redemption transaction max fee must be greater than zero
341
367
  /// - Redemption timeout must be greater than zero
368
+ /// - Redemption timeout notifier reward multiplier must be in the
369
+ /// range [0, 100]
342
370
  function updateRedemptionParameters(
343
371
  Storage storage self,
344
372
  uint64 _redemptionDustThreshold,
345
373
  uint64 _redemptionTreasuryFeeDivisor,
346
374
  uint64 _redemptionTxMaxFee,
347
- uint256 _redemptionTimeout
375
+ uint256 _redemptionTimeout,
376
+ uint96 _redemptionTimeoutSlashingAmount,
377
+ uint256 _redemptionTimeoutNotifierRewardMultiplier
348
378
  ) internal {
349
379
  require(
350
380
  _redemptionDustThreshold > 0,
@@ -366,16 +396,26 @@ library BridgeState {
366
396
  "Redemption timeout must be greater than zero"
367
397
  );
368
398
 
399
+ require(
400
+ _redemptionTimeoutNotifierRewardMultiplier <= 100,
401
+ "Redemption timeout notifier reward multiplier must be in the range [0, 100]"
402
+ );
403
+
369
404
  self.redemptionDustThreshold = _redemptionDustThreshold;
370
405
  self.redemptionTreasuryFeeDivisor = _redemptionTreasuryFeeDivisor;
371
406
  self.redemptionTxMaxFee = _redemptionTxMaxFee;
372
407
  self.redemptionTimeout = _redemptionTimeout;
408
+ self.redemptionTimeoutSlashingAmount = _redemptionTimeoutSlashingAmount;
409
+ self
410
+ .redemptionTimeoutNotifierRewardMultiplier = _redemptionTimeoutNotifierRewardMultiplier;
373
411
 
374
412
  emit RedemptionParametersUpdated(
375
413
  _redemptionDustThreshold,
376
414
  _redemptionTreasuryFeeDivisor,
377
415
  _redemptionTxMaxFee,
378
- _redemptionTimeout
416
+ _redemptionTimeout,
417
+ _redemptionTimeoutSlashingAmount,
418
+ _redemptionTimeoutNotifierRewardMultiplier
379
419
  );
380
420
  }
381
421
 
@@ -385,50 +425,73 @@ library BridgeState {
385
425
  /// BTC transaction fee that is acceptable in a single moving funds
386
426
  /// transaction. This is a _total_ max fee for the entire moving
387
427
  /// funds transaction.
388
- /// @param _movingFundsTimeout New value of the moving funds timeout in
389
- /// seconds. It is the time after which the moving funds process can
390
- /// be reported as timed out. It is counted from the moment when the
391
- /// wallet was requested to move their funds and switched to the
392
- /// MovingFunds state.
393
428
  /// @param _movingFundsDustThreshold New value of the moving funds dust
394
429
  /// threshold. It is the minimal satoshi amount that makes sense to
395
430
  // be transferred during the moving funds process. Moving funds
396
431
  // wallets having their BTC balance below that value can begin
397
432
  // closing immediately as transferring such a low value may not be
398
433
  // possible due to BTC network fees.
434
+ /// @param _movingFundsTimeout New value of the moving funds timeout in
435
+ /// seconds. It is the time after which the moving funds process can
436
+ /// be reported as timed out. It is counted from the moment when the
437
+ /// wallet was requested to move their funds and switched to the
438
+ /// MovingFunds state.
439
+ /// @param _movingFundsTimeoutSlashingAmount New value of the moving funds
440
+ /// timeout slashing amount in T, it is the amount slashed from each
441
+ /// wallet member for moving funds timeout
442
+ /// @param _movingFundsTimeoutNotifierRewardMultiplier New value of the
443
+ /// moving funds timeout notifier reward multiplier as percentage,
444
+ /// it determines the percentage of the notifier reward from the
445
+ /// staking contact the notifier of a moving funds timeout receives.
446
+ /// The value must be in the range [0, 100]
399
447
  /// @dev Requirements:
400
448
  /// - Moving funds transaction max total fee must be greater than zero
401
- /// - Moving funds timeout must be greater than zero
402
449
  /// - Moving funds dust threshold must be greater than zero
450
+ /// - Moving funds timeout must be greater than zero
451
+ /// - Moving funds timeout notifier reward multiplier must be in the
452
+ /// range [0, 100]
403
453
  function updateMovingFundsParameters(
404
454
  Storage storage self,
405
455
  uint64 _movingFundsTxMaxTotalFee,
456
+ uint64 _movingFundsDustThreshold,
406
457
  uint32 _movingFundsTimeout,
407
- uint64 _movingFundsDustThreshold
458
+ uint96 _movingFundsTimeoutSlashingAmount,
459
+ uint256 _movingFundsTimeoutNotifierRewardMultiplier
408
460
  ) internal {
409
461
  require(
410
462
  _movingFundsTxMaxTotalFee > 0,
411
463
  "Moving funds transaction max total fee must be greater than zero"
412
464
  );
413
465
 
466
+ require(
467
+ _movingFundsDustThreshold > 0,
468
+ "Moving funds dust threshold must be greater than zero"
469
+ );
470
+
414
471
  require(
415
472
  _movingFundsTimeout > 0,
416
473
  "Moving funds timeout must be greater than zero"
417
474
  );
418
475
 
419
476
  require(
420
- _movingFundsDustThreshold > 0,
421
- "Moving funds dust threshold must be greater than zero"
477
+ _movingFundsTimeoutNotifierRewardMultiplier <= 100,
478
+ "Moving funds timeout notifier reward multiplier must be in the range [0, 100]"
422
479
  );
423
480
 
424
481
  self.movingFundsTxMaxTotalFee = _movingFundsTxMaxTotalFee;
425
- self.movingFundsTimeout = _movingFundsTimeout;
426
482
  self.movingFundsDustThreshold = _movingFundsDustThreshold;
483
+ self.movingFundsTimeout = _movingFundsTimeout;
484
+ self
485
+ .movingFundsTimeoutSlashingAmount = _movingFundsTimeoutSlashingAmount;
486
+ self
487
+ .movingFundsTimeoutNotifierRewardMultiplier = _movingFundsTimeoutNotifierRewardMultiplier;
427
488
 
428
489
  emit MovingFundsParametersUpdated(
429
490
  _movingFundsTxMaxTotalFee,
491
+ _movingFundsDustThreshold,
430
492
  _movingFundsTimeout,
431
- _movingFundsDustThreshold
493
+ _movingFundsTimeoutSlashingAmount,
494
+ _movingFundsTimeoutNotifierRewardMultiplier
432
495
  );
433
496
  }
434
497
 
@@ -505,6 +568,12 @@ library BridgeState {
505
568
  }
506
569
 
507
570
  /// @notice Updates parameters related to frauds.
571
+ /// @param _fraudChallengeDepositAmount New value of the fraud challenge
572
+ /// deposit amount in wei, it is the amount of ETH the party
573
+ /// challenging the wallet for fraud needs to deposit
574
+ /// @param _fraudChallengeDefeatTimeout New value of the challenge defeat
575
+ /// timeout in seconds, it is the amount of time the wallet has to
576
+ /// defeat a fraud challenge. The value must be greater than zero
508
577
  /// @param _fraudSlashingAmount New value of the fraud slashing amount in T,
509
578
  /// it is the amount slashed from each wallet member for committing
510
579
  /// a fraud
@@ -512,42 +581,36 @@ library BridgeState {
512
581
  /// reward multiplier as percentage, it determines the percentage of
513
582
  /// the notifier reward from the staking contact the notifier of
514
583
  /// a fraud receives. The value must be in the range [0, 100]
515
- /// @param _fraudChallengeDefeatTimeout New value of the challenge defeat
516
- /// timeout in seconds, it is the amount of time the wallet has to
517
- /// defeat a fraud challenge. The value must be greater than zero
518
- /// @param _fraudChallengeDepositAmount New value of the fraud challenge
519
- /// deposit amount in wei, it is the amount of ETH the party
520
- /// challenging the wallet for fraud needs to deposit
521
584
  /// @dev Requirements:
522
- /// - Fraud notifier reward multiplier must be in the range [0, 100]
523
585
  /// - Fraud challenge defeat timeout must be greater than 0
586
+ /// - Fraud notifier reward multiplier must be in the range [0, 100]
524
587
  function updateFraudParameters(
525
588
  Storage storage self,
526
- uint96 _fraudSlashingAmount,
527
- uint256 _fraudNotifierRewardMultiplier,
589
+ uint256 _fraudChallengeDepositAmount,
528
590
  uint256 _fraudChallengeDefeatTimeout,
529
- uint256 _fraudChallengeDepositAmount
591
+ uint96 _fraudSlashingAmount,
592
+ uint256 _fraudNotifierRewardMultiplier
530
593
  ) internal {
531
594
  require(
532
- _fraudNotifierRewardMultiplier <= 100,
533
- "Fraud notifier reward multiplier must be in the range [0, 100]"
595
+ _fraudChallengeDefeatTimeout > 0,
596
+ "Fraud challenge defeat timeout must be greater than zero"
534
597
  );
535
598
 
536
599
  require(
537
- _fraudChallengeDefeatTimeout > 0,
538
- "Fraud challenge defeat timeout must be greater than zero"
600
+ _fraudNotifierRewardMultiplier <= 100,
601
+ "Fraud notifier reward multiplier must be in the range [0, 100]"
539
602
  );
540
603
 
604
+ self.fraudChallengeDepositAmount = _fraudChallengeDepositAmount;
605
+ self.fraudChallengeDefeatTimeout = _fraudChallengeDefeatTimeout;
541
606
  self.fraudSlashingAmount = _fraudSlashingAmount;
542
607
  self.fraudNotifierRewardMultiplier = _fraudNotifierRewardMultiplier;
543
- self.fraudChallengeDefeatTimeout = _fraudChallengeDefeatTimeout;
544
- self.fraudChallengeDepositAmount = _fraudChallengeDepositAmount;
545
608
 
546
609
  emit FraudParametersUpdated(
547
- _fraudSlashingAmount,
548
- _fraudNotifierRewardMultiplier,
610
+ _fraudChallengeDepositAmount,
549
611
  _fraudChallengeDefeatTimeout,
550
- _fraudChallengeDepositAmount
612
+ _fraudSlashingAmount,
613
+ _fraudNotifierRewardMultiplier
551
614
  );
552
615
  }
553
616
  }
@@ -277,7 +277,7 @@ library Fraud {
277
277
  /// for the given `walletID`. Those IDs are not directly stored
278
278
  /// in the contract for gas efficiency purposes but they can be
279
279
  /// read from appropriate `DkgResultSubmitted` and `DkgResultApproved`
280
- /// events.
280
+ /// events of the `WalletRegistry` contract
281
281
  /// - The amount of time indicated by `challengeDefeatTimeout` must pass
282
282
  /// after the challenge was reported
283
283
  function notifyFraudChallengeDefeatTimeout(
@@ -434,12 +434,20 @@ library MovingFunds {
434
434
  /// @notice Notifies about a timed out moving funds process. Terminates
435
435
  /// the wallet and slashes signing group members as a result.
436
436
  /// @param walletPubKeyHash 20-byte public key hash of the wallet
437
+ /// @param walletMembersIDs Identifiers of the wallet signing group members
437
438
  /// @dev Requirements:
438
439
  /// - The wallet must be in the MovingFunds state
439
440
  /// - The moving funds timeout must be actually exceeded
441
+ /// - The expression `keccak256(abi.encode(walletMembersIDs))` must
442
+ /// be exactly the same as the hash stored under `membersIdsHash`
443
+ /// for the given `walletID`. Those IDs are not directly stored
444
+ /// in the contract for gas efficiency purposes but they can be
445
+ /// read from appropriate `DkgResultSubmitted` and `DkgResultApproved`
446
+ /// events of the `WalletRegistry` contract
440
447
  function notifyMovingFundsTimeout(
441
448
  BridgeState.Storage storage self,
442
- bytes20 walletPubKeyHash
449
+ bytes20 walletPubKeyHash,
450
+ uint32[] calldata walletMembersIDs
443
451
  ) external {
444
452
  Wallets.Wallet storage wallet = self.registeredWallets[
445
453
  walletPubKeyHash
@@ -459,8 +467,13 @@ library MovingFunds {
459
467
 
460
468
  self.terminateWallet(walletPubKeyHash);
461
469
 
462
- // TODO: Perform slashing of wallet operators, reward the notifier
463
- // using seized amount, and add unit tests for that.
470
+ self.ecdsaWalletRegistry.seize(
471
+ self.movingFundsTimeoutSlashingAmount,
472
+ self.movingFundsTimeoutNotifierRewardMultiplier,
473
+ msg.sender,
474
+ wallet.ecdsaWalletID,
475
+ walletMembersIDs
476
+ );
464
477
 
465
478
  // slither-disable-next-line reentrancy-events
466
479
  emit MovingFundsTimedOut(walletPubKeyHash);
@@ -765,29 +765,41 @@ library Redemption {
765
765
  /// with the given wallet, that has timed out. The redemption
766
766
  /// request is identified by the key built as
767
767
  /// `keccak256(walletPubKeyHash | redeemerOutputScript)`.
768
- /// The results of calling this function: the pending redemptions
769
- /// value for the wallet will be decreased by the requested amount
770
- /// (minus treasury fee), the tokens taken from the redeemer on
771
- /// redemption request will be returned to the redeemer, the request
772
- /// will be moved from pending redemptions to timed-out redemptions.
773
- /// If the state of the wallet is `Live` or `MovingFunds`, the
774
- /// wallet operators will be slashed.
775
- /// Additionally, if the state of wallet is `Live`, the wallet will
776
- /// be closed or marked as `MovingFunds` (depending on the presence
777
- /// or absence of the wallet's main UTXO) and the wallet will no
778
- /// longer be marked as the active wallet (if it was marked as such).
768
+ /// The results of calling this function:
769
+ /// - the pending redemptions value for the wallet will be decreased
770
+ /// by the requested amount (minus treasury fee),
771
+ /// - the tokens taken from the redeemer on redemption request will
772
+ /// be returned to the redeemer,
773
+ /// - the request will be moved from pending redemptions to
774
+ /// timed-out redemptions,
775
+ /// - if the state of the wallet is `Live` or `MovingFunds`, the
776
+ /// wallet operators will be slashed and the notifier will be
777
+ /// rewarded,
778
+ /// - if the state of wallet is `Live`, the wallet will be closed or
779
+ /// marked as `MovingFunds` (depending on the presence or absence
780
+ /// of the wallet's main UTXO) and the wallet will no longer be
781
+ /// marked as the active wallet (if it was marked as such).
779
782
  /// @param walletPubKeyHash 20-byte public key hash of the wallet
783
+ /// @param walletMembersIDs Identifiers of the wallet signing group members
780
784
  /// @param redeemerOutputScript The redeemer's length-prefixed output
781
785
  /// script (P2PKH, P2WPKH, P2SH or P2WSH)
782
786
  /// @dev Requirements:
787
+ /// - The wallet must be in the Live or MovingFunds or Terminated state
783
788
  /// - The redemption request identified by `walletPubKeyHash` and
784
789
  /// `redeemerOutputScript` must exist
790
+ /// - The expression `keccak256(abi.encode(walletMembersIDs))` must
791
+ /// be exactly the same as the hash stored under `membersIdsHash`
792
+ /// for the given `walletID`. Those IDs are not directly stored
793
+ /// in the contract for gas efficiency purposes but they can be
794
+ /// read from appropriate `DkgResultSubmitted` and `DkgResultApproved`
795
+ /// events of the `WalletRegistry` contract
785
796
  /// - The amount of time defined by `redemptionTimeout` must have
786
797
  /// passed since the redemption was requested (the request must be
787
- /// timed-out).
798
+ /// timed-out)
788
799
  function notifyRedemptionTimeout(
789
800
  BridgeState.Storage storage self,
790
801
  bytes20 walletPubKeyHash,
802
+ uint32[] calldata walletMembersIDs,
791
803
  bytes calldata redeemerOutputScript
792
804
  ) external {
793
805
  uint256 redemptionKey = uint256(
@@ -836,7 +848,17 @@ library Redemption {
836
848
  ) {
837
849
  // Propagate timeout consequences to the wallet
838
850
  self.notifyWalletTimedOutRedemption(walletPubKeyHash);
851
+
852
+ // Slash the wallet operators and reward the notifier
853
+ self.ecdsaWalletRegistry.seize(
854
+ self.redemptionTimeoutSlashingAmount,
855
+ self.redemptionTimeoutNotifierRewardMultiplier,
856
+ msg.sender,
857
+ wallet.ecdsaWalletID,
858
+ walletMembersIDs
859
+ );
839
860
  }
861
+
840
862
  // slither-disable-next-line reentrancy-events
841
863
  emit RedemptionTimedOut(walletPubKeyHash, redeemerOutputScript);
842
864
 
@@ -288,12 +288,11 @@ library Wallets {
288
288
  moveFunds(self, walletPubKeyHash);
289
289
  }
290
290
 
291
- /// @notice Handles a notification about a wallet redemption timeout
292
- /// and requests slashing of the wallet operators. Triggers the
293
- /// wallet moving funds process only if the wallet is still in the
294
- /// Live state. That means multiple action timeouts can be reported
295
- /// for the same wallet but only the first report requests the
296
- /// wallet to move their funds.
291
+ /// @notice Handles a notification about a wallet redemption timeout.
292
+ /// Triggers the wallet moving funds process only if the wallet is
293
+ /// still in the Live state. That means multiple action timeouts can
294
+ /// be reported for the same wallet but only the first report
295
+ /// requests the wallet to move their funds.
297
296
  /// @param walletPubKeyHash 20-byte public key hash of the wallet
298
297
  /// @dev Requirements:
299
298
  /// - The wallet must be in the `Live` or `MovingFunds` state
@@ -314,9 +313,6 @@ library Wallets {
314
313
  if (walletState == WalletState.Live) {
315
314
  moveFunds(self, walletPubKeyHash);
316
315
  }
317
-
318
- // TODO: Perform slashing of wallet operators and transfer some of the
319
- // slashed tokens to the caller of this function.
320
316
  }
321
317
 
322
318
  /// @notice Notifies that the wallet is either old enough or has too few