@keep-network/tbtc-v2 0.1.1-dev.63 → 0.1.1-dev.66

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 (69) hide show
  1. package/artifacts/Bank.json +6 -6
  2. package/artifacts/Bridge.json +159 -118
  3. package/artifacts/Deposit.json +7 -7
  4. package/artifacts/DepositSweep.json +14 -13
  5. package/artifacts/EcdsaDkgValidator.json +1 -1
  6. package/artifacts/EcdsaInactivity.json +1 -1
  7. package/artifacts/Fraud.json +7 -7
  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 +31 -9
  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 +11 -11
  19. package/artifacts/SortitionPool.json +2 -2
  20. package/artifacts/T.json +2 -2
  21. package/artifacts/TBTC.json +6 -6
  22. package/artifacts/TBTCToken.json +6 -6
  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 +13 -13
  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 +7 -7
  32. package/artifacts/solcInputs/{888980850d09abe497842d2096dd7e11.json → 496e626b61d332140d7f8662b25cbc03.json} +5 -5
  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 +79 -40
  39. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
  40. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +2 -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 +1 -1
  44. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +2 -2
  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/Heartbeat.sol/Heartbeat.dbg.json +1 -1
  49. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
  50. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
  51. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +15 -2
  52. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
  53. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +2 -2
  54. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
  55. package/build/contracts/bridge/Redemption.sol/Redemption.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 +2 -2
  59. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  60. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +1 -1
  61. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  62. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  63. package/contracts/bridge/Bridge.sol +34 -4
  64. package/contracts/bridge/BridgeState.sol +15 -7
  65. package/contracts/bridge/DepositSweep.sol +93 -40
  66. package/contracts/bridge/MovingFunds.sol +42 -4
  67. package/contracts/bridge/Redemption.sol +0 -1
  68. package/export.json +44 -0
  69. package/package.json +1 -1
@@ -39,6 +39,29 @@ library DepositSweep {
39
39
 
40
40
  using BTCUtils for bytes;
41
41
 
42
+ /// @notice Represents temporary information needed during the processing
43
+ /// of the deposit sweep Bitcoin transaction inputs. This structure
44
+ /// is an internal one and should not be exported outside of the
45
+ /// deposit sweep transaction processing code.
46
+ /// @dev Allows to mitigate "stack too deep" errors on EVM.
47
+ struct DepositSweepTxInputsProcessingInfo {
48
+ // Input vector of the deposit sweep Bitcoin transaction. It is
49
+ // assumed the vector's structure is valid so it must be validated
50
+ // using e.g. `BTCUtils.validateVin` function before being used
51
+ // during the processing. The validation is usually done as part
52
+ // of the `BitcoinTx.validateProof` call that checks the SPV proof.
53
+ bytes sweepTxInputVector;
54
+ // Data of the wallet's main UTXO. If no main UTXO exists for the given
55
+ // sweeping wallet, this parameter's fields should be zeroed to bypass
56
+ // the main UTXO validation
57
+ BitcoinTx.UTXO mainUtxo;
58
+ // Address of the vault where all swept deposits should be routed to.
59
+ // It is used to validate whether all swept deposits have been revealed
60
+ // with the same `vault` parameter. It is an optional parameter.
61
+ // Set to zero address if deposits are not routed to a vault.
62
+ address vault;
63
+ }
64
+
42
65
  /// @notice Represents an outcome of the sweep Bitcoin transaction
43
66
  /// inputs processing.
44
67
  struct DepositSweepTxInputsInfo {
@@ -83,6 +106,15 @@ library DepositSweep {
83
106
  /// @param mainUtxo Data of the wallet's main UTXO, as currently known on
84
107
  /// the Ethereum chain. If no main UTXO exists for the given wallet,
85
108
  /// this parameter is ignored
109
+ /// @param vault Optional address of the vault where all swept deposits
110
+ /// should be routed to. All deposits swept as part of the transaction
111
+ /// must have their `vault` parameters set to the same address.
112
+ /// If this parameter is set to an address of a trusted vault, swept
113
+ /// deposits are routed to that vault.
114
+ /// If this parameter is set to the zero address or to an address
115
+ /// of a non-trusted vault, swept deposits are not routed to a
116
+ /// vault but depositors' balances are increased in the Bank
117
+ /// individually.
86
118
  /// @dev Requirements:
87
119
  /// - `sweepTx` components must match the expected structure. See
88
120
  /// `BitcoinTx.Info` docs for reference. Their values must exactly
@@ -96,6 +128,9 @@ library DepositSweep {
96
128
  /// revealed deposits UTXOs. That transaction must have only
97
129
  /// one P2(W)PKH output locking funds on the 20-byte wallet public
98
130
  /// key hash.
131
+ /// - All revealed deposits that are swept by `sweepTx` must have
132
+ /// their `vault` parameters set to the same address as the address
133
+ /// passed in the `vault` function parameter.
99
134
  /// - `sweepProof` components must match the expected structure. See
100
135
  /// `BitcoinTx.Proof` docs for reference. The `bitcoinHeaders`
101
136
  /// field must contain a valid number of block headers, not less
@@ -107,7 +142,8 @@ library DepositSweep {
107
142
  BridgeState.Storage storage self,
108
143
  BitcoinTx.Info calldata sweepTx,
109
144
  BitcoinTx.Proof calldata sweepProof,
110
- BitcoinTx.UTXO calldata mainUtxo
145
+ BitcoinTx.UTXO calldata mainUtxo,
146
+ address vault
111
147
  ) external {
112
148
  // The actual transaction proof is performed here. After that point, we
113
149
  // can assume the transaction happened on Bitcoin chain and has
@@ -132,8 +168,11 @@ library DepositSweep {
132
168
  DepositSweepTxInputsInfo
133
169
  memory inputsInfo = processDepositSweepTxInputs(
134
170
  self,
135
- sweepTx.inputVector,
136
- resolvedMainUtxo
171
+ DepositSweepTxInputsProcessingInfo(
172
+ sweepTx.inputVector,
173
+ resolvedMainUtxo,
174
+ vault
175
+ )
137
176
  );
138
177
 
139
178
  // Helper variable that will hold the sum of treasury fees paid by
@@ -189,15 +228,26 @@ library DepositSweep {
189
228
  // slither-disable-next-line reentrancy-events
190
229
  emit DepositsSwept(walletPubKeyHash, sweepTxHash);
191
230
 
192
- // Update depositors balances in the Bank.
193
- self.bank.increaseBalances(
194
- inputsInfo.depositors,
195
- inputsInfo.depositedAmounts
196
- );
231
+ if (vault != address(0) && self.isVaultTrusted[vault]) {
232
+ // If the `vault` address is not zero and belongs to a trusted
233
+ // vault, route the deposits to that vault.
234
+ self.bank.increaseBalanceAndCall(
235
+ vault,
236
+ inputsInfo.depositors,
237
+ inputsInfo.depositedAmounts
238
+ );
239
+ } else {
240
+ // If the `vault` address is zero or belongs to a non-trusted
241
+ // vault, increase balances in the Bank individually for each
242
+ // depositor.
243
+ self.bank.increaseBalances(
244
+ inputsInfo.depositors,
245
+ inputsInfo.depositedAmounts
246
+ );
247
+ }
248
+
197
249
  // Pass the treasury fee to the treasury address.
198
250
  self.bank.increaseBalance(self.treasury, totalTreasuryFee);
199
-
200
- // TODO: Handle deposits having `vault` set.
201
251
  }
202
252
 
203
253
  /// @notice Resolves sweeping wallet based on the provided wallet public key
@@ -299,32 +349,23 @@ library DepositSweep {
299
349
  /// if one of the inputs cannot be recognized as a pointer to a
300
350
  /// revealed deposit or expected main UTXO.
301
351
  /// This function also marks each processed deposit as swept.
302
- /// @param sweepTxInputVector Bitcoin sweep transaction input vector.
303
- /// This function assumes vector's structure is valid so it must be
304
- /// validated using e.g. `BTCUtils.validateVin` function before
305
- /// it is passed here
306
- /// @param mainUtxo Data of the wallet's main UTXO. If no main UTXO
307
- /// exists for the given the wallet, this parameter's fields should
308
- /// be zeroed to bypass the main UTXO validation
309
- /// @return info Outcomes of the processing.
352
+ /// @return resultInfo Outcomes of the processing.
310
353
  function processDepositSweepTxInputs(
311
354
  BridgeState.Storage storage self,
312
- bytes memory sweepTxInputVector,
313
- BitcoinTx.UTXO memory mainUtxo
314
- ) internal returns (DepositSweepTxInputsInfo memory info) {
355
+ DepositSweepTxInputsProcessingInfo memory processInfo
356
+ ) internal returns (DepositSweepTxInputsInfo memory resultInfo) {
315
357
  // If the passed `mainUtxo` parameter's values are zeroed, the main UTXO
316
358
  // for the given wallet doesn't exist and it is not expected to be
317
359
  // included in the sweep transaction input vector.
318
- bool mainUtxoExpected = mainUtxo.txHash != bytes32(0);
360
+ bool mainUtxoExpected = processInfo.mainUtxo.txHash != bytes32(0);
319
361
  bool mainUtxoFound = false;
320
362
 
321
363
  // Determining the total number of sweep transaction inputs in the same
322
364
  // way as for number of outputs. See `BitcoinTx.inputVector` docs for
323
365
  // more details.
324
- (
325
- uint256 inputsCompactSizeUintLength,
326
- uint256 inputsCount
327
- ) = sweepTxInputVector.parseVarInt();
366
+ (uint256 inputsCompactSizeUintLength, uint256 inputsCount) = processInfo
367
+ .sweepTxInputVector
368
+ .parseVarInt();
328
369
 
329
370
  // To determine the first input starting index, we must jump over
330
371
  // the compactSize uint which prepends the input vector. One byte
@@ -346,11 +387,13 @@ library DepositSweep {
346
387
  // Determine the swept deposits count. If main UTXO is NOT expected,
347
388
  // all inputs should be deposits. If main UTXO is expected, one input
348
389
  // should point to that main UTXO.
349
- info.depositors = new address[](
390
+ resultInfo.depositors = new address[](
350
391
  !mainUtxoExpected ? inputsCount : inputsCount - 1
351
392
  );
352
- info.depositedAmounts = new uint256[](info.depositors.length);
353
- info.treasuryFees = new uint256[](info.depositors.length);
393
+ resultInfo.depositedAmounts = new uint256[](
394
+ resultInfo.depositors.length
395
+ );
396
+ resultInfo.treasuryFees = new uint256[](resultInfo.depositors.length);
354
397
 
355
398
  // Initialize helper variables.
356
399
  uint256 processedDepositsCount = 0;
@@ -362,7 +405,7 @@ library DepositSweep {
362
405
  uint32 outpointIndex,
363
406
  uint256 inputLength
364
407
  ) = parseDepositSweepTxInputAt(
365
- sweepTxInputVector,
408
+ processInfo.sweepTxInputVector,
366
409
  inputStartingIndex
367
410
  );
368
411
 
@@ -377,7 +420,12 @@ library DepositSweep {
377
420
  // a revealed deposit.
378
421
  require(deposit.sweptAt == 0, "Deposit already swept");
379
422
 
380
- if (processedDepositsCount == info.depositors.length) {
423
+ require(
424
+ deposit.vault == processInfo.vault,
425
+ "Deposit should be routed to another vault"
426
+ );
427
+
428
+ if (processedDepositsCount == resultInfo.depositors.length) {
381
429
  // If this condition is true, that means a deposit input
382
430
  // took place of an expected main UTXO input.
383
431
  // In other words, there is no expected main UTXO
@@ -390,22 +438,27 @@ library DepositSweep {
390
438
  /* solhint-disable-next-line not-rely-on-time */
391
439
  deposit.sweptAt = uint32(block.timestamp);
392
440
 
393
- info.depositors[processedDepositsCount] = deposit.depositor;
394
- info.depositedAmounts[processedDepositsCount] = deposit.amount;
395
- info.inputsTotalValue += info.depositedAmounts[
441
+ resultInfo.depositors[processedDepositsCount] = deposit
442
+ .depositor;
443
+ resultInfo.depositedAmounts[processedDepositsCount] = deposit
444
+ .amount;
445
+ resultInfo.inputsTotalValue += resultInfo.depositedAmounts[
396
446
  processedDepositsCount
397
447
  ];
398
- info.treasuryFees[processedDepositsCount] = deposit.treasuryFee;
448
+ resultInfo.treasuryFees[processedDepositsCount] = deposit
449
+ .treasuryFee;
399
450
 
400
451
  processedDepositsCount++;
401
452
  } else if (
402
453
  mainUtxoExpected != mainUtxoFound &&
403
- mainUtxo.txHash == outpointTxHash &&
404
- mainUtxo.txOutputIndex == outpointIndex
454
+ processInfo.mainUtxo.txHash == outpointTxHash &&
455
+ processInfo.mainUtxo.txOutputIndex == outpointIndex
405
456
  ) {
406
457
  // If we entered here, that means the input was identified as
407
458
  // the expected main UTXO.
408
- info.inputsTotalValue += mainUtxo.txOutputValue;
459
+ resultInfo.inputsTotalValue += processInfo
460
+ .mainUtxo
461
+ .txOutputValue;
409
462
  mainUtxoFound = true;
410
463
 
411
464
  // Main UTXO used as an input, mark it as spent.
@@ -426,7 +479,7 @@ library DepositSweep {
426
479
  }
427
480
 
428
481
  // Construction of the input processing loop guarantees that:
429
- // `processedDepositsCount == info.depositors.length == info.depositedAmounts.length`
482
+ // `processedDepositsCount == resultInfo.depositors.length == resultInfo.depositedAmounts.length`
430
483
  // is always true at this point. We just use the first variable
431
484
  // to assert the total count of swept deposit is bigger than zero.
432
485
  require(
@@ -441,7 +494,7 @@ library DepositSweep {
441
494
  "Expected main UTXO not present in sweep transaction inputs"
442
495
  );
443
496
 
444
- return info;
497
+ return resultInfo;
445
498
  }
446
499
 
447
500
  /// @notice Parses a Bitcoin transaction input starting at the given index.
@@ -93,6 +93,8 @@ library MovingFunds {
93
93
  address submitter
94
94
  );
95
95
 
96
+ event MovingFundsTimeoutReset(bytes20 walletPubKeyHash);
97
+
96
98
  event MovingFundsCompleted(
97
99
  bytes20 walletPubKeyHash,
98
100
  bytes32 movingFundsTxHash
@@ -206,10 +208,8 @@ library MovingFunds {
206
208
 
207
209
  // This requirement fails only when `liveWalletsCount` is zero. In
208
210
  // that case, the system cannot accept the commitment and must provide
209
- // new wallets first.
210
- //
211
- // TODO: Expose separate function to reset the moving funds timeout
212
- // if no Live wallets exist in the system.
211
+ // new wallets first. However, the wallet supposed to submit the
212
+ // commitment can keep resetting the moving funds timeout until then.
213
213
  require(expectedTargetWalletsCount > 0, "No target wallets available");
214
214
 
215
215
  require(
@@ -252,6 +252,44 @@ library MovingFunds {
252
252
  );
253
253
  }
254
254
 
255
+ /// @notice Resets the moving funds timeout for the given wallet if the
256
+ /// target wallet commitment cannot be submitted due to a lack
257
+ /// of live wallets in the system.
258
+ /// @param walletPubKeyHash 20-byte public key hash of the moving funds wallet
259
+ /// @dev Requirements:
260
+ /// - The wallet must be in the MovingFunds state
261
+ /// - The target wallets commitment must not be already submitted for
262
+ /// the given moving funds wallet
263
+ /// - Live wallets count must be zero
264
+ function resetMovingFundsTimeout(
265
+ BridgeState.Storage storage self,
266
+ bytes20 walletPubKeyHash
267
+ ) external {
268
+ Wallets.Wallet storage wallet = self.registeredWallets[
269
+ walletPubKeyHash
270
+ ];
271
+
272
+ require(
273
+ wallet.state == Wallets.WalletState.MovingFunds,
274
+ "ECDSA wallet must be in MovingFunds state"
275
+ );
276
+
277
+ // If the moving funds wallet already submitted their target wallets
278
+ // commitment, there is no point to reset the timeout since the
279
+ // wallet can make the BTC transaction and submit the proof.
280
+ require(
281
+ wallet.movingFundsTargetWalletsCommitmentHash == bytes32(0),
282
+ "Target wallets commitment already submitted"
283
+ );
284
+
285
+ require(self.liveWalletsCount == 0, "Live wallets count must be zero");
286
+
287
+ /* solhint-disable-next-line not-rely-on-time */
288
+ wallet.movingFundsRequestedAt = uint32(block.timestamp);
289
+
290
+ emit MovingFundsTimeoutReset(walletPubKeyHash);
291
+ }
292
+
255
293
  /// @notice Used by the wallet to prove the BTC moving funds transaction
256
294
  /// and to make the necessary state changes. Moving funds is only
257
295
  /// accepted if it satisfies SPV proof.
@@ -825,7 +825,6 @@ library Redemption {
825
825
  request.treasuryFee;
826
826
 
827
827
  require(
828
- // TODO: Allow the wallets in `Closing` state when the state is added
829
828
  wallet.state == Wallets.WalletState.Live ||
830
829
  wallet.state == Wallets.WalletState.MovingFunds ||
831
830
  wallet.state == Wallets.WalletState.Terminated,
package/export.json CHANGED
@@ -14031,6 +14031,19 @@
14031
14031
  ],
14032
14032
  "name": "MovingFundsTimedOut",
14033
14033
  "type": "event"
14034
+ },
14035
+ {
14036
+ "anonymous": false,
14037
+ "inputs": [
14038
+ {
14039
+ "indexed": false,
14040
+ "internalType": "bytes20",
14041
+ "name": "walletPubKeyHash",
14042
+ "type": "bytes20"
14043
+ }
14044
+ ],
14045
+ "name": "MovingFundsTimeoutReset",
14046
+ "type": "event"
14034
14047
  }
14035
14048
  ]
14036
14049
  },
@@ -14473,6 +14486,19 @@
14473
14486
  "name": "MovingFundsTimedOut",
14474
14487
  "type": "event"
14475
14488
  },
14489
+ {
14490
+ "anonymous": false,
14491
+ "inputs": [
14492
+ {
14493
+ "indexed": false,
14494
+ "internalType": "bytes20",
14495
+ "name": "walletPubKeyHash",
14496
+ "type": "bytes20"
14497
+ }
14498
+ ],
14499
+ "name": "MovingFundsTimeoutReset",
14500
+ "type": "event"
14501
+ },
14476
14502
  {
14477
14503
  "anonymous": false,
14478
14504
  "inputs": [
@@ -15535,6 +15561,19 @@
15535
15561
  "stateMutability": "nonpayable",
15536
15562
  "type": "function"
15537
15563
  },
15564
+ {
15565
+ "inputs": [
15566
+ {
15567
+ "internalType": "bytes20",
15568
+ "name": "walletPubKeyHash",
15569
+ "type": "bytes20"
15570
+ }
15571
+ ],
15572
+ "name": "resetMovingFundsTimeout",
15573
+ "outputs": [],
15574
+ "stateMutability": "nonpayable",
15575
+ "type": "function"
15576
+ },
15538
15577
  {
15539
15578
  "inputs": [
15540
15579
  {
@@ -16037,6 +16076,11 @@
16037
16076
  "internalType": "struct BitcoinTx.UTXO",
16038
16077
  "name": "mainUtxo",
16039
16078
  "type": "tuple"
16079
+ },
16080
+ {
16081
+ "internalType": "address",
16082
+ "name": "vault",
16083
+ "type": "address"
16040
16084
  }
16041
16085
  ],
16042
16086
  "name": "submitDepositSweepProof",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keep-network/tbtc-v2",
3
- "version": "0.1.1-dev.63+main.68e692f8fe53043af3c81bd88afd16954759ad5d",
3
+ "version": "0.1.1-dev.66+main.194aaf49b16b3d5ef27df189fbc4a71cf3b779d0",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "artifacts/",