@keep-network/tbtc-v2 1.6.0-dev.7 → 1.6.0-dev.9

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 (106) hide show
  1. package/artifacts/BLS.json +1 -1
  2. package/artifacts/Bank.json +3 -3
  3. package/artifacts/BeaconAuthorization.json +1 -1
  4. package/artifacts/BeaconDkg.json +1 -1
  5. package/artifacts/BeaconDkgValidator.json +1 -1
  6. package/artifacts/BeaconInactivity.json +1 -1
  7. package/artifacts/BeaconSortitionPool.json +3 -3
  8. package/artifacts/Bridge.json +5 -5
  9. package/artifacts/BridgeGovernance.json +2 -2
  10. package/artifacts/BridgeGovernanceParameters.json +2 -2
  11. package/artifacts/Deposit.json +2 -2
  12. package/artifacts/DepositSweep.json +2 -2
  13. package/artifacts/DonationVault.json +3 -3
  14. package/artifacts/EcdsaDkgValidator.json +1 -1
  15. package/artifacts/EcdsaInactivity.json +1 -1
  16. package/artifacts/EcdsaSortitionPool.json +3 -3
  17. package/artifacts/Fraud.json +2 -2
  18. package/artifacts/LightRelay.json +18 -18
  19. package/artifacts/LightRelayMaintainerProxy.json +8 -8
  20. package/artifacts/MaintainerProxy.json +19 -19
  21. package/artifacts/MovingFunds.json +2 -2
  22. package/artifacts/NuCypherToken.json +2 -2
  23. package/artifacts/RandomBeacon.json +2 -2
  24. package/artifacts/RandomBeaconChaosnet.json +2 -2
  25. package/artifacts/RandomBeaconGovernance.json +2 -2
  26. package/artifacts/Redemption.json +2 -2
  27. package/artifacts/ReimbursementPool.json +2 -2
  28. package/artifacts/T.json +2 -2
  29. package/artifacts/TBTC.json +3 -3
  30. package/artifacts/TBTCToken.json +3 -3
  31. package/artifacts/TBTCVault.json +23 -23
  32. package/artifacts/TokenStaking.json +1 -1
  33. package/artifacts/TokenholderGovernor.json +9 -9
  34. package/artifacts/TokenholderTimelock.json +8 -8
  35. package/artifacts/VendingMachine.json +3 -3
  36. package/artifacts/VendingMachineNuCypher.json +1 -1
  37. package/artifacts/VendingMachineV2.json +3 -3
  38. package/artifacts/VendingMachineV3.json +3 -3
  39. package/artifacts/WalletProposalValidator.json +89 -13
  40. package/artifacts/WalletRegistry.json +5 -5
  41. package/artifacts/WalletRegistryGovernance.json +2 -2
  42. package/artifacts/Wallets.json +2 -2
  43. package/artifacts/solcInputs/{b4e1c442421284b256fcad9f86102ecc.json → 3090118554664301f434ca00232869b0.json} +1 -1
  44. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  45. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  46. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +1 -1
  47. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
  48. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  49. package/build/contracts/bridge/BridgeGovernanceParameters.sol/BridgeGovernanceParameters.dbg.json +1 -1
  50. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
  51. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +1 -1
  52. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +1 -1
  53. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
  54. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
  55. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +1 -1
  56. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
  57. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
  58. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
  59. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
  60. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  61. package/build/contracts/bridge/VendingMachineV2.sol/VendingMachineV2.dbg.json +1 -1
  62. package/build/contracts/bridge/VendingMachineV3.sol/VendingMachineV3.dbg.json +1 -1
  63. package/build/contracts/bridge/WalletProposalValidator.sol/WalletProposalValidator.dbg.json +1 -1
  64. package/build/contracts/bridge/WalletProposalValidator.sol/WalletProposalValidator.json +65 -2
  65. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
  66. package/build/contracts/l2/L2TBTC.sol/L2TBTC.dbg.json +1 -1
  67. package/build/contracts/l2/L2WormholeGateway.sol/IWormholeTokenBridge.dbg.json +1 -1
  68. package/build/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.dbg.json +1 -1
  69. package/build/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.dbg.json +1 -1
  70. package/build/contracts/relay/LightRelay.sol/ILightRelay.dbg.json +1 -1
  71. package/build/contracts/relay/LightRelay.sol/LightRelay.dbg.json +1 -1
  72. package/build/contracts/relay/LightRelay.sol/RelayUtils.dbg.json +1 -1
  73. package/build/contracts/relay/LightRelayMaintainerProxy.sol/LightRelayMaintainerProxy.dbg.json +1 -1
  74. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  75. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +1 -1
  76. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  77. package/build/contracts/vault/TBTCOptimisticMinting.sol/TBTCOptimisticMinting.dbg.json +1 -1
  78. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  79. package/contracts/bridge/WalletProposalValidator.sol +151 -8
  80. package/export/artifacts/contracts/bridge/Bridge.sol/Bridge.json +22 -22
  81. package/export/artifacts/contracts/bridge/VendingMachine.sol/VendingMachine.json +6 -6
  82. package/export/artifacts/contracts/bridge/VendingMachineV2.sol/VendingMachineV2.json +6 -6
  83. package/export/artifacts/contracts/bridge/VendingMachineV3.sol/VendingMachineV3.json +6 -6
  84. package/export/artifacts/contracts/bridge/WalletProposalValidator.sol/WalletProposalValidator.json +14904 -11318
  85. package/export/artifacts/contracts/l2/L2TBTC.sol/L2TBTC.json +40 -40
  86. package/export/artifacts/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.json +47 -47
  87. package/export/artifacts/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.json +88 -88
  88. package/export/artifacts/contracts/relay/LightRelay.sol/LightRelay.json +57 -57
  89. package/export/artifacts/contracts/relay/LightRelayMaintainerProxy.sol/LightRelayMaintainerProxy.json +31 -31
  90. package/export/artifacts/contracts/test/BankStub.sol/BankStub.json +2 -2
  91. package/export/artifacts/contracts/test/BridgeStub.sol/BridgeStub.json +58 -58
  92. package/export/artifacts/contracts/test/GoerliLightRelay.sol/GoerliLightRelay.json +59 -59
  93. package/export/artifacts/contracts/test/HeartbeatStub.sol/HeartbeatStub.json +2 -2
  94. package/export/artifacts/contracts/test/LightRelayStub.sol/LightRelayStub.json +59 -59
  95. package/export/artifacts/contracts/test/ReceiveApprovalStub.sol/ReceiveApprovalStub.json +7 -7
  96. package/export/artifacts/contracts/test/SepoliaLightRelay.sol/SepoliaLightRelay.json +59 -59
  97. package/export/artifacts/contracts/test/SystemTestRelay.sol/SystemTestRelay.json +14 -14
  98. package/export/artifacts/contracts/test/TestERC20.sol/TestERC20.json +6 -6
  99. package/export/artifacts/contracts/test/TestERC721.sol/TestERC721.json +8 -8
  100. package/export/artifacts/contracts/test/TestEcdsaLib.sol/TestEcdsaLib.json +2 -2
  101. package/export/artifacts/contracts/test/WormholeBridgeStub.sol/WormholeBridgeStub.json +37 -37
  102. package/export/artifacts/contracts/token/TBTC.sol/TBTC.json +2 -2
  103. package/export/artifacts/contracts/vault/DonationVault.sol/DonationVault.json +11 -11
  104. package/export/artifacts/contracts/vault/TBTCVault.sol/TBTCVault.json +135 -135
  105. package/export/typechain/factories/WalletProposalValidator__factory.js +64 -1
  106. package/package.json +1 -1
@@ -22,6 +22,7 @@ import "./BitcoinTx.sol";
22
22
  import "./Bridge.sol";
23
23
  import "./Deposit.sol";
24
24
  import "./Redemption.sol";
25
+ import "./MovingFunds.sol";
25
26
  import "./Wallets.sol";
26
27
 
27
28
  /// @title Wallet proposal validator.
@@ -104,6 +105,20 @@ contract WalletProposalValidator {
104
105
  uint256 movingFundsTxFee;
105
106
  }
106
107
 
108
+ /// @notice Helper structure representing a moved funds sweep proposal.
109
+ struct MovedFundsSweepProposal {
110
+ // 20-byte public key hash of the wallet.
111
+ bytes20 walletPubKeyHash;
112
+ // 32-byte hash of the moving funds transaction that caused the sweep
113
+ // request to be created.
114
+ bytes32 movingFundsTxHash;
115
+ // Index of the moving funds transaction output that is subject of the
116
+ // sweep request.
117
+ uint32 movingFundsTxOutputIndex;
118
+ // Proposed BTC fee for the entire transaction.
119
+ uint256 movedFundsSweepTxFee;
120
+ }
121
+
107
122
  /// @notice Helper structure representing a heartbeat proposal.
108
123
  struct HeartbeatProposal {
109
124
  // 20-byte public key hash of the target wallet.
@@ -603,6 +618,7 @@ contract WalletProposalValidator {
603
618
  /// most of the work can be done using a single readonly contract
604
619
  /// call.
605
620
  /// @param proposal The moving funds proposal to validate.
621
+ /// @param walletMainUtxo The main UTXO of the source wallet.
606
622
  /// @return True if the proposal is valid. Reverts otherwise.
607
623
  /// @dev Notice that this function is meant to be invoked after the moving
608
624
  /// funds commitment has already been submitted. This function skips
@@ -613,15 +629,16 @@ contract WalletProposalValidator {
613
629
  /// - The target wallets commitment must be submitted,
614
630
  /// - The target wallets commitment hash must match the target wallets
615
631
  /// from the proposal,
632
+ /// - The source wallet BTC balance must be equal to or greater than
633
+ /// `movingFundsDustThreshold`,
616
634
  /// - The proposed moving funds transaction fee must be greater than
617
635
  /// zero,
618
636
  /// - The proposed moving funds transaction fee must not exceed the
619
637
  /// maximum total fee allowed for moving funds.
620
- function validateMovingFundsProposal(MovingFundsProposal calldata proposal)
621
- external
622
- view
623
- returns (bool)
624
- {
638
+ function validateMovingFundsProposal(
639
+ MovingFundsProposal calldata proposal,
640
+ BitcoinTx.UTXO calldata walletMainUtxo
641
+ ) external view returns (bool) {
625
642
  Wallets.Wallet memory sourceWallet = bridge.wallets(
626
643
  proposal.walletPubKeyHash
627
644
  );
@@ -645,10 +662,32 @@ contract WalletProposalValidator {
645
662
  "Target wallets do not match target wallets commitment hash"
646
663
  );
647
664
 
648
- // Make sure the proposed fee is valid.
649
- (uint64 movingFundsTxMaxTotalFee, , , , , , , , , , ) = bridge
650
- .movingFundsParameters();
665
+ (
666
+ uint64 movingFundsTxMaxTotalFee,
667
+ uint64 movingFundsDustThreshold,
668
+ ,
669
+ ,
670
+ ,
671
+ ,
672
+ ,
673
+ ,
674
+ ,
675
+ ,
676
+
677
+ ) = bridge.movingFundsParameters();
678
+
679
+ // Make sure the source wallet balance is correct.
680
+ uint64 sourceWalletBtcBalance = getWalletBtcBalance(
681
+ sourceWallet.mainUtxoHash,
682
+ walletMainUtxo
683
+ );
651
684
 
685
+ require(
686
+ sourceWalletBtcBalance >= movingFundsDustThreshold,
687
+ "Source wallet BTC balance is below the moving funds dust threshold"
688
+ );
689
+
690
+ // Make sure the proposed fee is valid.
652
691
  require(
653
692
  proposal.movingFundsTxFee > 0,
654
693
  "Proposed transaction fee cannot be zero"
@@ -662,6 +701,110 @@ contract WalletProposalValidator {
662
701
  return true;
663
702
  }
664
703
 
704
+ /// @notice Calculates the Bitcoin balance of a wallet based on its main
705
+ /// UTXO.
706
+ /// @param walletMainUtxoHash The hash of the wallet's main UTXO.
707
+ /// @param walletMainUtxo The detailed data of the wallet's main UTXO.
708
+ /// @return walletBtcBalance The calculated Bitcoin balance of the wallet.
709
+ function getWalletBtcBalance(
710
+ bytes32 walletMainUtxoHash,
711
+ BitcoinTx.UTXO calldata walletMainUtxo
712
+ ) internal view returns (uint64 walletBtcBalance) {
713
+ // If the wallet has a main UTXO hash set, cross-check it with the
714
+ // provided plain-text parameter and get the transaction output value
715
+ // as BTC balance. Otherwise, the BTC balance is just zero.
716
+ if (walletMainUtxoHash != bytes32(0)) {
717
+ require(
718
+ keccak256(
719
+ abi.encodePacked(
720
+ walletMainUtxo.txHash,
721
+ walletMainUtxo.txOutputIndex,
722
+ walletMainUtxo.txOutputValue
723
+ )
724
+ ) == walletMainUtxoHash,
725
+ "Invalid wallet main UTXO data"
726
+ );
727
+
728
+ walletBtcBalance = walletMainUtxo.txOutputValue;
729
+ }
730
+
731
+ return walletBtcBalance;
732
+ }
733
+
734
+ /// @notice View function encapsulating the main rules of a valid moved
735
+ /// funds sweep proposal. This function is meant to facilitate the
736
+ /// off-chain validation of the incoming proposals. Thanks to it,
737
+ /// most of the work can be done using a single readonly contract
738
+ /// call.
739
+ /// @param proposal The moved funds sweep proposal to validate.
740
+ /// @return True if the proposal is valid. Reverts otherwise.
741
+ /// @dev Requirements:
742
+ /// - The source wallet must be in the Live or MovingFunds state,
743
+ /// - The moved funds sweep request identified by the proposed
744
+ /// transaction hash and output index must be in the Pending state,
745
+ /// - The transaction hash and output index from the proposal must
746
+ /// identify a moved funds sweep request in the Pending state,
747
+ /// - The transaction hash and output index from the proposal must
748
+ /// identify a moved funds sweep request that belongs to the wallet,
749
+ /// - The proposed moved funds sweep transaction fee must be greater
750
+ /// than zero,
751
+ /// - The proposed moved funds sweep transaction fee must not exceed
752
+ /// the maximum total fee allowed for moved funds sweep.
753
+ function validateMovedFundsSweepProposal(
754
+ MovedFundsSweepProposal calldata proposal
755
+ ) external view returns (bool) {
756
+ Wallets.Wallet memory wallet = bridge.wallets(
757
+ proposal.walletPubKeyHash
758
+ );
759
+
760
+ // Make sure the wallet is in Live or MovingFunds state.
761
+ require(
762
+ wallet.state == Wallets.WalletState.Live ||
763
+ wallet.state == Wallets.WalletState.MovingFunds,
764
+ "Source wallet is not in Live or MovingFunds state"
765
+ );
766
+
767
+ // Make sure the moved funds sweep request is valid.
768
+ uint256 sweepRequestKeyUint = uint256(
769
+ keccak256(
770
+ abi.encodePacked(
771
+ proposal.movingFundsTxHash,
772
+ proposal.movingFundsTxOutputIndex
773
+ )
774
+ )
775
+ );
776
+
777
+ MovingFunds.MovedFundsSweepRequest memory sweepRequest = bridge
778
+ .movedFundsSweepRequests(sweepRequestKeyUint);
779
+
780
+ require(
781
+ sweepRequest.state ==
782
+ MovingFunds.MovedFundsSweepRequestState.Pending,
783
+ "Sweep request is not in Pending state"
784
+ );
785
+
786
+ require(
787
+ sweepRequest.walletPubKeyHash == proposal.walletPubKeyHash,
788
+ "Sweep request does not belong to the wallet"
789
+ );
790
+
791
+ // Make sure the proposed fee is valid.
792
+ (, , , , , , , uint64 movedFundsSweepTxMaxTotalFee, , , ) = bridge
793
+ .movingFundsParameters();
794
+
795
+ require(
796
+ proposal.movedFundsSweepTxFee > 0,
797
+ "Proposed transaction fee cannot be zero"
798
+ );
799
+
800
+ require(
801
+ proposal.movedFundsSweepTxFee <= movedFundsSweepTxMaxTotalFee,
802
+ "Proposed transaction fee is too high"
803
+ );
804
+
805
+ return true;
806
+ }
807
+
665
808
  /// @notice View function encapsulating the main rules of a valid heartbeat
666
809
  /// proposal. This function is meant to facilitate the off-chain
667
810
  /// validation of the incoming proposals. Thanks to it, most