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

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 (72) hide show
  1. package/artifacts/Bank.json +3 -3
  2. package/artifacts/Bridge.json +716 -197
  3. package/artifacts/Deposit.json +9 -9
  4. package/artifacts/DepositSweep.json +76 -0
  5. package/artifacts/EcdsaDkgValidator.json +1 -1
  6. package/artifacts/EcdsaInactivity.json +1 -1
  7. package/artifacts/Fraud.json +9 -9
  8. package/artifacts/KeepRegistry.json +1 -1
  9. package/artifacts/KeepStake.json +2 -2
  10. package/artifacts/KeepToken.json +2 -2
  11. package/artifacts/KeepTokenStaking.json +1 -1
  12. package/artifacts/MovingFunds.json +77 -11
  13. package/artifacts/NuCypherStakingEscrow.json +1 -1
  14. package/artifacts/NuCypherToken.json +2 -2
  15. package/artifacts/RandomBeaconStub.json +1 -1
  16. package/artifacts/Redemption.json +9 -9
  17. package/artifacts/ReimbursementPool.json +2 -2
  18. package/artifacts/Relay.json +9 -9
  19. package/artifacts/SortitionPool.json +2 -2
  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/{6d69fc514efd874ebb1cb86b04981772.json → 452e42f1afe94d8639a5bf98bed9e151.json} +10 -10
  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 +375 -103
  39. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
  40. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +26 -2
  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/DepositSweep.sol/DepositSweep.dbg.json +4 -0
  44. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
  45. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
  46. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
  47. package/build/contracts/bridge/Fraud.sol/Fraud.json +2 -2
  48. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
  49. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
  50. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +46 -2
  51. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
  52. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +2 -2
  53. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
  54. package/build/contracts/bridge/Redemption.sol/Redemption.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/BitcoinTx.sol +69 -0
  62. package/contracts/bridge/Bridge.sol +175 -8
  63. package/contracts/bridge/BridgeState.sol +85 -3
  64. package/contracts/bridge/{Sweep.sol → DepositSweep.sol} +30 -18
  65. package/contracts/bridge/MovingFunds.sol +586 -76
  66. package/contracts/bridge/Wallets.sol +2 -0
  67. package/deploy/05_deploy_bridge.ts +5 -2
  68. package/export.json +479 -56
  69. package/package.json +1 -1
  70. package/artifacts/Sweep.json +0 -76
  71. package/build/contracts/bridge/Sweep.sol/Sweep.dbg.json +0 -4
  72. package/build/contracts/bridge/Sweep.sol/Sweep.json +0 -30
@@ -22,7 +22,7 @@ import {IWalletOwner as EcdsaWalletOwner} from "@keep-network/ecdsa/contracts/ap
22
22
  import "./IRelay.sol";
23
23
  import "./BridgeState.sol";
24
24
  import "./Deposit.sol";
25
- import "./Sweep.sol";
25
+ import "./DepositSweep.sol";
26
26
  import "./Redemption.sol";
27
27
  import "./BitcoinTx.sol";
28
28
  import "./EcdsaLib.sol";
@@ -60,7 +60,7 @@ import "../bank/Bank.sol";
60
60
  contract Bridge is Governable, EcdsaWalletOwner {
61
61
  using BridgeState for BridgeState.Storage;
62
62
  using Deposit for BridgeState.Storage;
63
- using Sweep for BridgeState.Storage;
63
+ using DepositSweep for BridgeState.Storage;
64
64
  using Redemption for BridgeState.Storage;
65
65
  using MovingFunds for BridgeState.Storage;
66
66
  using Wallets for BridgeState.Storage;
@@ -121,6 +121,14 @@ contract Bridge is Governable, EcdsaWalletOwner {
121
121
 
122
122
  event MovingFundsBelowDustReported(bytes20 walletPubKeyHash);
123
123
 
124
+ event MovedFundsSwept(bytes20 walletPubKeyHash, bytes32 sweepTxHash);
125
+
126
+ event MovedFundsSweepTimedOut(
127
+ bytes20 walletPubKeyHash,
128
+ bytes32 movingFundsTxHash,
129
+ uint32 movingFundsTxOutputIndex
130
+ );
131
+
124
132
  event NewWalletRequested();
125
133
 
126
134
  event NewWalletRegistered(
@@ -180,7 +188,11 @@ contract Bridge is Governable, EcdsaWalletOwner {
180
188
  uint64 movingFundsDustThreshold,
181
189
  uint32 movingFundsTimeout,
182
190
  uint96 movingFundsTimeoutSlashingAmount,
183
- uint256 movingFundsTimeoutNotifierRewardMultiplier
191
+ uint256 movingFundsTimeoutNotifierRewardMultiplier,
192
+ uint64 movedFundsSweepTxMaxTotalFee,
193
+ uint32 movedFundsSweepTimeout,
194
+ uint96 movedFundsSweepTimeoutSlashingAmount,
195
+ uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
184
196
  );
185
197
 
186
198
  event WalletParametersUpdated(
@@ -239,6 +251,10 @@ contract Bridge is Governable, EcdsaWalletOwner {
239
251
  self.movingFundsTimeout = 7 days;
240
252
  self.movingFundsTimeoutSlashingAmount = 10000 * 1e18; // 10000 T
241
253
  self.movingFundsTimeoutNotifierRewardMultiplier = 100; //100%
254
+ self.movedFundsSweepTxMaxTotalFee = 10000; // 10000 satoshi
255
+ self.movedFundsSweepTimeout = 7 days;
256
+ self.movedFundsSweepTimeoutSlashingAmount = 10000 * 1e18; // 10000 T
257
+ self.movedFundsSweepTimeoutNotifierRewardMultiplier = 100; //100%
242
258
  self.fraudChallengeDepositAmount = 2 ether;
243
259
  self.fraudChallengeDefeatTimeout = 7 days;
244
260
  self.fraudSlashingAmount = 10000 * 1e18; // 10000 T
@@ -331,12 +347,12 @@ contract Bridge is Governable, EcdsaWalletOwner {
331
347
  /// - `mainUtxo` components must point to the recent main UTXO
332
348
  /// of the given wallet, as currently known on the Ethereum chain.
333
349
  /// If there is no main UTXO, this parameter is ignored.
334
- function submitSweepProof(
350
+ function submitDepositSweepProof(
335
351
  BitcoinTx.Info calldata sweepTx,
336
352
  BitcoinTx.Proof calldata sweepProof,
337
353
  BitcoinTx.UTXO calldata mainUtxo
338
354
  ) external {
339
- self.submitSweepProof(sweepTx, sweepProof, mainUtxo);
355
+ self.submitDepositSweepProof(sweepTx, sweepProof, mainUtxo);
340
356
  }
341
357
 
342
358
  /// @notice Requests redemption of the given amount from the specified
@@ -503,6 +519,7 @@ contract Bridge is Governable, EcdsaWalletOwner {
503
519
  /// @dev Requirements:
504
520
  /// - The source wallet must be in the MovingFunds state
505
521
  /// - The source wallet must not have pending redemption requests
522
+ /// - The source wallet must not have pending moved funds sweep requests
506
523
  /// - The source wallet must not have submitted its commitment already
507
524
  /// - The expression `keccak256(abi.encode(walletMembersIDs))` must
508
525
  /// be exactly the same as the hash stored under `membersIdsHash`
@@ -641,6 +658,85 @@ contract Bridge is Governable, EcdsaWalletOwner {
641
658
  self.notifyMovingFundsBelowDust(walletPubKeyHash, mainUtxo);
642
659
  }
643
660
 
661
+ /// @notice Used by the wallet to prove the BTC moved funds sweep
662
+ /// transaction and to make the necessary state changes. Moved
663
+ /// funds sweep is only accepted if it satisfies SPV proof.
664
+ ///
665
+ /// The function validates the sweep transaction structure by
666
+ /// checking if it actually spends the moved funds UTXO and the
667
+ /// sweeping wallet's main UTXO (optionally), and if it locks the
668
+ /// value on the sweeping wallet's 20-byte public key hash using a
669
+ /// reasonable transaction fee. If all preconditions are
670
+ /// met, this function updates the sweeping wallet main UTXO, thus
671
+ /// their BTC balance.
672
+ ///
673
+ /// It is possible to prove the given sweep transaction only
674
+ /// one time.
675
+ /// @param sweepTx Bitcoin sweep funds transaction data
676
+ /// @param sweepProof Bitcoin sweep funds proof data
677
+ /// @param mainUtxo Data of the sweeping wallet's main UTXO, as currently
678
+ /// known on the Ethereum chain
679
+ /// @dev Requirements:
680
+ /// - `sweepTx` components must match the expected structure. See
681
+ /// `BitcoinTx.Info` docs for reference. Their values must exactly
682
+ /// correspond to appropriate Bitcoin transaction fields to produce
683
+ /// a provable transaction hash.
684
+ /// - The `sweepTx` should represent a Bitcoin transaction with
685
+ /// the first input pointing to a moved funds sweep request targeted
686
+ /// to the wallet, and optionally, the second input pointing to the
687
+ /// wallet's main UTXO, if the sweeping wallet has a main UTXO set.
688
+ /// There should be only one output locking funds on the sweeping
689
+ /// wallet 20-byte public key hash.
690
+ /// - `sweepProof` components must match the expected structure.
691
+ /// See `BitcoinTx.Proof` docs for reference. The `bitcoinHeaders`
692
+ /// field must contain a valid number of block headers, not less
693
+ /// than the `txProofDifficultyFactor` contract constant.
694
+ /// - `mainUtxo` components must point to the recent main UTXO
695
+ /// of the sweeping wallet, as currently known on the Ethereum chain.
696
+ /// If there is no main UTXO, this parameter is ignored.
697
+ /// - The sweeping wallet must be in the Live or MovingFunds state.
698
+ /// - The total Bitcoin transaction fee must be lesser or equal
699
+ /// to `movedFundsSweepTxMaxTotalFee` governable parameter.
700
+ function submitMovedFundsSweepProof(
701
+ BitcoinTx.Info calldata sweepTx,
702
+ BitcoinTx.Proof calldata sweepProof,
703
+ BitcoinTx.UTXO calldata mainUtxo
704
+ ) external {
705
+ self.submitMovedFundsSweepProof(sweepTx, sweepProof, mainUtxo);
706
+ }
707
+
708
+ /// @notice Notifies about a timed out moved funds sweep process. If the
709
+ /// wallet is not terminated yet, that function terminates
710
+ /// the wallet and slashes signing group members as a result.
711
+ /// Marks the given sweep request as TimedOut.
712
+ /// @param movingFundsTxHash 32-byte hash of the moving funds transaction
713
+ /// that caused the sweep request to be created
714
+ /// @param movingFundsTxOutputIndex Index of the moving funds transaction
715
+ /// output that is subject of the sweep request.
716
+ /// @param walletMembersIDs Identifiers of the wallet signing group members
717
+ /// @dev Requirements:
718
+ /// - The moved funds sweep request must be in the Pending state
719
+ /// - The moved funds sweep timeout must be actually exceeded
720
+ /// - The wallet must be either in the Live or MovingFunds or
721
+ /// Terminated state
722
+ /// - The expression `keccak256(abi.encode(walletMembersIDs))` must
723
+ /// be exactly the same as the hash stored under `membersIdsHash`
724
+ /// for the given `walletID`. Those IDs are not directly stored
725
+ /// in the contract for gas efficiency purposes but they can be
726
+ /// read from appropriate `DkgResultSubmitted` and `DkgResultApproved`
727
+ /// events of the `WalletRegistry` contract
728
+ function notifyMovedFundsSweepTimeout(
729
+ bytes32 movingFundsTxHash,
730
+ uint32 movingFundsTxOutputIndex,
731
+ uint32[] calldata walletMembersIDs
732
+ ) external {
733
+ self.notifyMovedFundsSweepTimeout(
734
+ movingFundsTxHash,
735
+ movingFundsTxOutputIndex,
736
+ walletMembersIDs
737
+ );
738
+ }
739
+
644
740
  /// @notice Requests creation of a new wallet. This function just
645
741
  /// forms a request and the creation process is performed
646
742
  /// asynchronously. Once a wallet is created, the ECDSA Wallet
@@ -998,25 +1094,55 @@ contract Bridge is Governable, EcdsaWalletOwner {
998
1094
  /// it determines the percentage of the notifier reward from the
999
1095
  /// staking contact the notifier of a moving funds timeout receives.
1000
1096
  /// The value must be in the range [0, 100]
1097
+ /// @param movedFundsSweepTxMaxTotalFee New value of the moved funds sweep
1098
+ /// transaction max total fee in satoshis. It is the maximum amount
1099
+ /// of the total BTC transaction fee that is acceptable in a single
1100
+ /// moved funds sweep transaction. This is a _total_ max fee for the
1101
+ /// entire moved funds sweep transaction.
1102
+ /// @param movedFundsSweepTimeout New value of the moved funds sweep
1103
+ /// timeout in seconds. It is the time after which the moved funds
1104
+ /// sweep process can be reported as timed out. It is counted from
1105
+ /// the moment when the wallet was requested to sweep the received
1106
+ /// funds.
1107
+ /// @param movedFundsSweepTimeoutSlashingAmount New value of the moved
1108
+ /// funds sweep timeout slashing amount in T, it is the amount
1109
+ /// slashed from each wallet member for moved funds sweep timeout
1110
+ /// @param movedFundsSweepTimeoutNotifierRewardMultiplier New value of
1111
+ /// the moved funds sweep timeout notifier reward multiplier as
1112
+ /// percentage, it determines the percentage of the notifier reward
1113
+ /// from the staking contact the notifier of a moved funds sweep
1114
+ /// timeout receives. The value must be in the range [0, 100]
1001
1115
  /// @dev Requirements:
1002
1116
  /// - Moving funds transaction max total fee must be greater than zero
1003
1117
  /// - Moving funds dust threshold must be greater than zero
1004
1118
  /// - Moving funds timeout must be greater than zero
1005
1119
  /// - Moving funds timeout notifier reward multiplier must be in the
1006
1120
  /// range [0, 100]
1121
+ /// - Moved funds sweep transaction max total fee must be greater than zero
1122
+ /// - Moved funds sweep timeout must be greater than zero
1123
+ /// - Moved funds sweep timeout notifier reward multiplier must be in the
1124
+ /// range [0, 100]
1007
1125
  function updateMovingFundsParameters(
1008
1126
  uint64 movingFundsTxMaxTotalFee,
1009
1127
  uint64 movingFundsDustThreshold,
1010
1128
  uint32 movingFundsTimeout,
1011
1129
  uint96 movingFundsTimeoutSlashingAmount,
1012
- uint256 movingFundsTimeoutNotifierRewardMultiplier
1130
+ uint256 movingFundsTimeoutNotifierRewardMultiplier,
1131
+ uint64 movedFundsSweepTxMaxTotalFee,
1132
+ uint32 movedFundsSweepTimeout,
1133
+ uint96 movedFundsSweepTimeoutSlashingAmount,
1134
+ uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
1013
1135
  ) external onlyGovernance {
1014
1136
  self.updateMovingFundsParameters(
1015
1137
  movingFundsTxMaxTotalFee,
1016
1138
  movingFundsDustThreshold,
1017
1139
  movingFundsTimeout,
1018
1140
  movingFundsTimeoutSlashingAmount,
1019
- movingFundsTimeoutNotifierRewardMultiplier
1141
+ movingFundsTimeoutNotifierRewardMultiplier,
1142
+ movedFundsSweepTxMaxTotalFee,
1143
+ movedFundsSweepTimeout,
1144
+ movedFundsSweepTimeoutSlashingAmount,
1145
+ movedFundsSweepTimeoutNotifierRewardMultiplier
1020
1146
  );
1021
1147
  }
1022
1148
 
@@ -1200,6 +1326,23 @@ contract Bridge is Governable, EcdsaWalletOwner {
1200
1326
  return self.fraudChallenges[challengeKey];
1201
1327
  }
1202
1328
 
1329
+ /// @notice Collection of all moved funds sweep requests indexed by
1330
+ /// `keccak256(movingFundsTxHash | movingFundsOutputIndex)`.
1331
+ /// The `movingFundsTxHash` is `bytes32` (ordered as in Bitcoin
1332
+ /// internally) and `movingFundsOutputIndex` an `uint32`. Each entry
1333
+ /// is actually an UTXO representing the moved funds and is supposed
1334
+ /// to be swept with the current main UTXO of the recipient wallet.
1335
+ /// @param requestKey Request key built as
1336
+ /// `keccak256(movingFundsTxHash | movingFundsOutputIndex)`
1337
+ /// @return Details of the moved funds sweep request.
1338
+ function movedFundsSweepRequests(uint256 requestKey)
1339
+ external
1340
+ view
1341
+ returns (MovingFunds.MovedFundsSweepRequest memory)
1342
+ {
1343
+ return self.movedFundsSweepRequests[requestKey];
1344
+ }
1345
+
1203
1346
  /// @notice Indicates if the vault with the given address is trusted or not.
1204
1347
  /// Depositors can route their revealed deposits only to trusted
1205
1348
  /// vaults and have trusted vaults notified about new deposits as
@@ -1313,6 +1456,20 @@ contract Bridge is Governable, EcdsaWalletOwner {
1313
1456
  /// @return movingFundsTimeoutNotifierRewardMultiplier The percentage of the
1314
1457
  /// notifier reward from the staking contract the notifier of a
1315
1458
  /// moving funds timeout receives. The value is in the range [0, 100].
1459
+ /// @return movedFundsSweepTxMaxTotalFee Maximum amount of the total BTC
1460
+ /// transaction fee that is acceptable in a single moved funds
1461
+ /// sweep transaction. This is a _total_ max fee for the entire
1462
+ /// moved funds sweep transaction.
1463
+ /// @return movedFundsSweepTimeout Time after which the moved funds sweep
1464
+ /// process can be reported as timed out. It is counted from the
1465
+ /// moment when the wallet was requested to sweep the received funds.
1466
+ /// Value in seconds.
1467
+ /// @return movedFundsSweepTimeoutSlashingAmount The amount of stake slashed
1468
+ /// from each member of a wallet for a moved funds sweep timeout.
1469
+ /// @return movedFundsSweepTimeoutNotifierRewardMultiplier The percentage
1470
+ /// of the notifier reward from the staking contract the notifier
1471
+ /// of a moved funds sweep timeout receives. The value is in the
1472
+ /// range [0, 100].
1316
1473
  function movingFundsParameters()
1317
1474
  external
1318
1475
  view
@@ -1321,7 +1478,11 @@ contract Bridge is Governable, EcdsaWalletOwner {
1321
1478
  uint64 movingFundsDustThreshold,
1322
1479
  uint32 movingFundsTimeout,
1323
1480
  uint96 movingFundsTimeoutSlashingAmount,
1324
- uint256 movingFundsTimeoutNotifierRewardMultiplier
1481
+ uint256 movingFundsTimeoutNotifierRewardMultiplier,
1482
+ uint64 movedFundsSweepTxMaxTotalFee,
1483
+ uint32 movedFundsSweepTimeout,
1484
+ uint96 movedFundsSweepTimeoutSlashingAmount,
1485
+ uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
1325
1486
  )
1326
1487
  {
1327
1488
  movingFundsTxMaxTotalFee = self.movingFundsTxMaxTotalFee;
@@ -1331,6 +1492,12 @@ contract Bridge is Governable, EcdsaWalletOwner {
1331
1492
  .movingFundsTimeoutSlashingAmount;
1332
1493
  movingFundsTimeoutNotifierRewardMultiplier = self
1333
1494
  .movingFundsTimeoutNotifierRewardMultiplier;
1495
+ movedFundsSweepTxMaxTotalFee = self.movedFundsSweepTxMaxTotalFee;
1496
+ movedFundsSweepTimeout = self.movedFundsSweepTimeout;
1497
+ movedFundsSweepTimeoutSlashingAmount = self
1498
+ .movedFundsSweepTimeoutSlashingAmount;
1499
+ movedFundsSweepTimeoutNotifierRewardMultiplier = self
1500
+ .movedFundsSweepTimeoutNotifierRewardMultiplier;
1334
1501
  }
1335
1502
 
1336
1503
  /// @return walletCreationPeriod Determines how frequently a new wallet
@@ -22,6 +22,7 @@ import "./Deposit.sol";
22
22
  import "./Redemption.sol";
23
23
  import "./Fraud.sol";
24
24
  import "./Wallets.sol";
25
+ import "./MovingFunds.sol";
25
26
 
26
27
  import "../bank/Bank.sol";
27
28
 
@@ -101,6 +102,32 @@ library BridgeState {
101
102
  // the notifier of a moving funds timeout receives. The value is in the
102
103
  // range [0, 100].
103
104
  uint256 movingFundsTimeoutNotifierRewardMultiplier;
105
+ // Maximum amount of the total BTC transaction fee that is acceptable in
106
+ // a single moved funds sweep transaction.
107
+ //
108
+ // This is a TOTAL max fee for the moved funds sweep transaction. Note
109
+ // that `depositTxMaxFee` is per single deposit and `redemptionTxMaxFee`
110
+ // if per single redemption. `movedFundsSweepTxMaxTotalFee` is a total
111
+ // fee for the entire transaction.
112
+ uint64 movedFundsSweepTxMaxTotalFee;
113
+ // Time after which the moved funds sweep process can be reported as
114
+ // timed out. It is counted from the moment when the recipient wallet
115
+ // was requested to sweep the received funds. Value in seconds.
116
+ uint32 movedFundsSweepTimeout;
117
+ // The amount of stake slashed from each member of a wallet for a moved
118
+ // funds sweep timeout.
119
+ uint96 movedFundsSweepTimeoutSlashingAmount;
120
+ // The percentage of the notifier reward from the staking contract
121
+ // the notifier of a moved funds sweep timeout receives. The value is
122
+ // in the range [0, 100].
123
+ uint256 movedFundsSweepTimeoutNotifierRewardMultiplier;
124
+ // Collection of all moved funds sweep requests indexed by
125
+ // `keccak256(movingFundsTxHash | movingFundsOutputIndex)`.
126
+ // The `movingFundsTxHash` is `bytes32` (ordered as in Bitcoin
127
+ // internally) and `movingFundsOutputIndex` an `uint32`. Each entry
128
+ // is actually an UTXO representing the moved funds and is supposed
129
+ // to be swept with the current main UTXO of the recipient wallet.
130
+ mapping(uint256 => MovingFunds.MovedFundsSweepRequest) movedFundsSweepRequests;
104
131
  // The minimal amount that can be requested for redemption.
105
132
  // Value of this parameter must take into account the value of
106
133
  // `redemptionTreasuryFeeDivisor` and `redemptionTxMaxFee`
@@ -246,7 +273,11 @@ library BridgeState {
246
273
  uint64 movingFundsDustThreshold,
247
274
  uint32 movingFundsTimeout,
248
275
  uint96 movingFundsTimeoutSlashingAmount,
249
- uint256 movingFundsTimeoutNotifierRewardMultiplier
276
+ uint256 movingFundsTimeoutNotifierRewardMultiplier,
277
+ uint64 movedFundsSweepTxMaxTotalFee,
278
+ uint32 movedFundsSweepTimeout,
279
+ uint96 movedFundsSweepTimeoutSlashingAmount,
280
+ uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
250
281
  );
251
282
 
252
283
  event WalletParametersUpdated(
@@ -444,19 +475,45 @@ library BridgeState {
444
475
  /// it determines the percentage of the notifier reward from the
445
476
  /// staking contact the notifier of a moving funds timeout receives.
446
477
  /// The value must be in the range [0, 100]
478
+ /// @param _movedFundsSweepTxMaxTotalFee New value of the moved funds sweep
479
+ /// transaction max total fee in satoshis. It is the maximum amount
480
+ /// of the total BTC transaction fee that is acceptable in a single
481
+ /// moved funds sweep transaction. This is a _total_ max fee for the
482
+ /// entire moved funds sweep transaction.
483
+ /// @param _movedFundsSweepTimeout New value of the moved funds sweep
484
+ /// timeout in seconds. It is the time after which the moved funds
485
+ /// sweep process can be reported as timed out. It is counted from
486
+ /// the moment when the wallet was requested to sweep the received
487
+ /// funds.
488
+ /// @param _movedFundsSweepTimeoutSlashingAmount New value of the moved
489
+ /// funds sweep timeout slashing amount in T, it is the amount
490
+ /// slashed from each wallet member for moved funds sweep timeout
491
+ /// @param _movedFundsSweepTimeoutNotifierRewardMultiplier New value of
492
+ /// the moved funds sweep timeout notifier reward multiplier as
493
+ /// percentage, it determines the percentage of the notifier reward
494
+ /// from the staking contact the notifier of a moved funds sweep
495
+ /// timeout receives. The value must be in the range [0, 100]
447
496
  /// @dev Requirements:
448
497
  /// - Moving funds transaction max total fee must be greater than zero
449
498
  /// - Moving funds dust threshold must be greater than zero
450
499
  /// - Moving funds timeout must be greater than zero
451
500
  /// - Moving funds timeout notifier reward multiplier must be in the
452
501
  /// range [0, 100]
502
+ /// - Moved funds sweep transaction max total fee must be greater than zero
503
+ /// - Moved funds sweep timeout must be greater than zero
504
+ /// - Moved funds sweep timeout notifier reward multiplier must be in the
505
+ /// range [0, 100]
453
506
  function updateMovingFundsParameters(
454
507
  Storage storage self,
455
508
  uint64 _movingFundsTxMaxTotalFee,
456
509
  uint64 _movingFundsDustThreshold,
457
510
  uint32 _movingFundsTimeout,
458
511
  uint96 _movingFundsTimeoutSlashingAmount,
459
- uint256 _movingFundsTimeoutNotifierRewardMultiplier
512
+ uint256 _movingFundsTimeoutNotifierRewardMultiplier,
513
+ uint64 _movedFundsSweepTxMaxTotalFee,
514
+ uint32 _movedFundsSweepTimeout,
515
+ uint96 _movedFundsSweepTimeoutSlashingAmount,
516
+ uint256 _movedFundsSweepTimeoutNotifierRewardMultiplier
460
517
  ) internal {
461
518
  require(
462
519
  _movingFundsTxMaxTotalFee > 0,
@@ -478,6 +535,21 @@ library BridgeState {
478
535
  "Moving funds timeout notifier reward multiplier must be in the range [0, 100]"
479
536
  );
480
537
 
538
+ require(
539
+ _movedFundsSweepTxMaxTotalFee > 0,
540
+ "Moved funds sweep transaction max total fee must be greater than zero"
541
+ );
542
+
543
+ require(
544
+ _movedFundsSweepTimeout > 0,
545
+ "Moved funds sweep timeout must be greater than zero"
546
+ );
547
+
548
+ require(
549
+ _movedFundsSweepTimeoutNotifierRewardMultiplier <= 100,
550
+ "Moved funds sweep timeout notifier reward multiplier must be in the range [0, 100]"
551
+ );
552
+
481
553
  self.movingFundsTxMaxTotalFee = _movingFundsTxMaxTotalFee;
482
554
  self.movingFundsDustThreshold = _movingFundsDustThreshold;
483
555
  self.movingFundsTimeout = _movingFundsTimeout;
@@ -485,13 +557,23 @@ library BridgeState {
485
557
  .movingFundsTimeoutSlashingAmount = _movingFundsTimeoutSlashingAmount;
486
558
  self
487
559
  .movingFundsTimeoutNotifierRewardMultiplier = _movingFundsTimeoutNotifierRewardMultiplier;
560
+ self.movedFundsSweepTxMaxTotalFee = _movedFundsSweepTxMaxTotalFee;
561
+ self.movedFundsSweepTimeout = _movedFundsSweepTimeout;
562
+ self
563
+ .movedFundsSweepTimeoutSlashingAmount = _movedFundsSweepTimeoutSlashingAmount;
564
+ self
565
+ .movedFundsSweepTimeoutNotifierRewardMultiplier = _movedFundsSweepTimeoutNotifierRewardMultiplier;
488
566
 
489
567
  emit MovingFundsParametersUpdated(
490
568
  _movingFundsTxMaxTotalFee,
491
569
  _movingFundsDustThreshold,
492
570
  _movingFundsTimeout,
493
571
  _movingFundsTimeoutSlashingAmount,
494
- _movingFundsTimeoutNotifierRewardMultiplier
572
+ _movingFundsTimeoutNotifierRewardMultiplier,
573
+ _movedFundsSweepTxMaxTotalFee,
574
+ _movedFundsSweepTimeout,
575
+ _movedFundsSweepTimeoutSlashingAmount,
576
+ _movedFundsSweepTimeoutNotifierRewardMultiplier
495
577
  );
496
578
  }
497
579
 
@@ -33,7 +33,7 @@ import "../bank/Bank.sol";
33
33
  /// This has two main effects: it consolidates the UTXO set and it disables
34
34
  /// the refund. Balances of depositors in the Bank are increased when the
35
35
  /// SPV sweep proof is submitted to the Bridge.
36
- library Sweep {
36
+ library DepositSweep {
37
37
  using BridgeState for BridgeState.Storage;
38
38
  using BitcoinTx for BridgeState.Storage;
39
39
 
@@ -41,7 +41,7 @@ library Sweep {
41
41
 
42
42
  /// @notice Represents an outcome of the sweep Bitcoin transaction
43
43
  /// inputs processing.
44
- struct SweepTxInputsInfo {
44
+ struct DepositSweepTxInputsInfo {
45
45
  // Sum of all inputs values i.e. all deposits and main UTXO value,
46
46
  // if present.
47
47
  uint256 inputsTotalValue;
@@ -103,7 +103,7 @@ library Sweep {
103
103
  /// - `mainUtxo` components must point to the recent main UTXO
104
104
  /// of the given wallet, as currently known on the Ethereum chain.
105
105
  /// If there is no main UTXO, this parameter is ignored.
106
- function submitSweepProof(
106
+ function submitDepositSweepProof(
107
107
  BridgeState.Storage storage self,
108
108
  BitcoinTx.Info calldata sweepTx,
109
109
  BitcoinTx.Proof calldata sweepProof,
@@ -120,20 +120,21 @@ library Sweep {
120
120
  (
121
121
  bytes20 walletPubKeyHash,
122
122
  uint64 sweepTxOutputValue
123
- ) = processSweepTxOutput(sweepTx.outputVector);
123
+ ) = processDepositSweepTxOutput(sweepTx.outputVector);
124
124
 
125
125
  (
126
126
  Wallets.Wallet storage wallet,
127
127
  BitcoinTx.UTXO memory resolvedMainUtxo
128
- ) = resolveSweepingWallet(self, walletPubKeyHash, mainUtxo);
128
+ ) = resolveDepositSweepingWallet(self, walletPubKeyHash, mainUtxo);
129
129
 
130
130
  // Process sweep transaction inputs and extract all information needed
131
131
  // to perform deposit bookkeeping.
132
- SweepTxInputsInfo memory inputsInfo = processSweepTxInputs(
133
- self,
134
- sweepTx.inputVector,
135
- resolvedMainUtxo
136
- );
132
+ DepositSweepTxInputsInfo
133
+ memory inputsInfo = processDepositSweepTxInputs(
134
+ self,
135
+ sweepTx.inputVector,
136
+ resolvedMainUtxo
137
+ );
137
138
 
138
139
  // Helper variable that will hold the sum of treasury fees paid by
139
140
  // all deposits.
@@ -145,7 +146,7 @@ library Sweep {
145
146
  (
146
147
  uint256 depositTxFee,
147
148
  uint256 depositTxFeeRemainder
148
- ) = sweepTxFeeDistribution(
149
+ ) = depositSweepTxFeeDistribution(
149
150
  inputsInfo.inputsTotalValue,
150
151
  sweepTxOutputValue,
151
152
  inputsInfo.depositedAmounts.length
@@ -206,11 +207,16 @@ library Sweep {
206
207
  /// @param mainUtxo Data of the wallet's main UTXO, as currently known on
207
208
  /// the Ethereum chain. If no main UTXO exists for the given wallet,
208
209
  /// this parameter is ignored
210
+ /// @return wallet Data of the sweeping wallet.
211
+ /// @return resolvedMainUtxo The actual main UTXO of the sweeping wallet
212
+ /// resolved by cross-checking the `mainUtxo` parameter with
213
+ /// the chain state. If the validation went well, this is the
214
+ /// plain-text main UTXO corresponding to the `wallet.mainUtxoHash`.
209
215
  /// @dev Requirements:
210
216
  /// - Sweeping wallet must be either in Live or MovingFunds state.
211
217
  /// - If the main UTXO of the sweeping wallet exists in the storage,
212
218
  /// the passed `mainUTXO` parameter must be equal to the stored one.
213
- function resolveSweepingWallet(
219
+ function resolveDepositSweepingWallet(
214
220
  BridgeState.Storage storage self,
215
221
  bytes20 walletPubKeyHash,
216
222
  BitcoinTx.UTXO calldata mainUtxo
@@ -261,7 +267,7 @@ library Sweep {
261
267
  /// it is passed here
262
268
  /// @return walletPubKeyHash 20-byte wallet public key hash.
263
269
  /// @return value 8-byte sweep transaction output value.
264
- function processSweepTxOutput(bytes memory sweepTxOutputVector)
270
+ function processDepositSweepTxOutput(bytes memory sweepTxOutputVector)
265
271
  internal
266
272
  pure
267
273
  returns (bytes20 walletPubKeyHash, uint64 value)
@@ -282,6 +288,8 @@ library Sweep {
282
288
 
283
289
  bytes memory output = sweepTxOutputVector.extractOutputAtIndex(0);
284
290
  value = output.extractValue();
291
+ // TODO: Extract `walletPubKeyHash` using `self.extractPubKeyHash`
292
+ // in order to get stronger validation.
285
293
  bytes memory walletPubKeyHashBytes = output.extractHash();
286
294
  // The sweep transaction output should always be P2PKH or P2WPKH.
287
295
  // In both cases, the wallet public key hash should be 20 bytes length.
@@ -311,11 +319,11 @@ library Sweep {
311
319
  /// exists for the given the wallet, this parameter's fields should
312
320
  /// be zeroed to bypass the main UTXO validation
313
321
  /// @return info Outcomes of the processing.
314
- function processSweepTxInputs(
322
+ function processDepositSweepTxInputs(
315
323
  BridgeState.Storage storage self,
316
324
  bytes memory sweepTxInputVector,
317
325
  BitcoinTx.UTXO memory mainUtxo
318
- ) internal returns (SweepTxInputsInfo memory info) {
326
+ ) internal returns (DepositSweepTxInputsInfo memory info) {
319
327
  // If the passed `mainUtxo` parameter's values are zeroed, the main UTXO
320
328
  // for the given wallet doesn't exist and it is not expected to be
321
329
  // included in the sweep transaction input vector.
@@ -365,7 +373,10 @@ library Sweep {
365
373
  bytes32 outpointTxHash,
366
374
  uint32 outpointIndex,
367
375
  uint256 inputLength
368
- ) = parseTxInputAt(sweepTxInputVector, inputStartingIndex);
376
+ ) = parseDepositSweepTxInputAt(
377
+ sweepTxInputVector,
378
+ inputStartingIndex
379
+ );
369
380
 
370
381
  Deposit.DepositRequest storage deposit = self.deposits[
371
382
  uint256(
@@ -402,6 +413,7 @@ library Sweep {
402
413
  } else if (
403
414
  mainUtxoExpected != mainUtxoFound &&
404
415
  mainUtxo.txHash == outpointTxHash
416
+ // TODO: We probably need to check `mainUtxo.txOutputIndex == outpointIndex` as well.
405
417
  ) {
406
418
  // If we entered here, that means the input was identified as
407
419
  // the expected main UTXO.
@@ -455,7 +467,7 @@ library Sweep {
455
467
  /// @dev This function assumes vector's structure is valid so it must be
456
468
  /// validated using e.g. `BTCUtils.validateVin` function before it
457
469
  /// is passed here.
458
- function parseTxInputAt(
470
+ function parseDepositSweepTxInputAt(
459
471
  bytes memory inputVector,
460
472
  uint256 inputStartingIndex
461
473
  )
@@ -490,7 +502,7 @@ library Sweep {
490
502
  /// transaction fee than cannot be distributed over all deposits.
491
503
  /// @dev It is up to the caller to decide how the remainder should be
492
504
  /// counted in. This function only computes its value.
493
- function sweepTxFeeDistribution(
505
+ function depositSweepTxFeeDistribution(
494
506
  uint256 sweepTxInputsTotalValue,
495
507
  uint256 sweepTxOutputValue,
496
508
  uint256 depositsCount