@keep-network/tbtc-v2 0.1.1-dev.6 → 0.1.1-dev.60

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 (95) hide show
  1. package/README.adoc +12 -0
  2. package/artifacts/Bank.json +752 -0
  3. package/artifacts/Bridge.json +3962 -0
  4. package/artifacts/Deposit.json +117 -0
  5. package/artifacts/DepositSweep.json +76 -0
  6. package/artifacts/EcdsaDkgValidator.json +532 -0
  7. package/artifacts/EcdsaInactivity.json +156 -0
  8. package/artifacts/Fraud.json +154 -0
  9. package/artifacts/KeepRegistry.json +99 -0
  10. package/artifacts/KeepStake.json +286 -0
  11. package/artifacts/KeepToken.json +711 -0
  12. package/artifacts/KeepTokenStaking.json +483 -0
  13. package/artifacts/MovingFunds.json +227 -0
  14. package/artifacts/NuCypherStakingEscrow.json +256 -0
  15. package/artifacts/NuCypherToken.json +711 -0
  16. package/artifacts/RandomBeaconStub.json +141 -0
  17. package/artifacts/Redemption.json +162 -0
  18. package/artifacts/ReimbursementPool.json +509 -0
  19. package/artifacts/Relay.json +123 -0
  20. package/artifacts/SortitionPool.json +944 -0
  21. package/artifacts/T.json +1148 -0
  22. package/artifacts/TBTC.json +27 -26
  23. package/artifacts/TBTCToken.json +27 -26
  24. package/artifacts/TokenStaking.json +2288 -0
  25. package/artifacts/TokenholderGovernor.json +1795 -0
  26. package/artifacts/TokenholderTimelock.json +1058 -0
  27. package/artifacts/VendingMachine.json +30 -29
  28. package/artifacts/VendingMachineKeep.json +400 -0
  29. package/artifacts/VendingMachineNuCypher.json +400 -0
  30. package/artifacts/WalletRegistry.json +2709 -0
  31. package/artifacts/WalletRegistryGovernance.json +2364 -0
  32. package/artifacts/Wallets.json +186 -0
  33. package/artifacts/solcInputs/59994c0eff9c9c3b454733a65b82146c.json +218 -0
  34. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  35. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
  36. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  37. package/build/contracts/bank/Bank.sol/Bank.json +20 -2
  38. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +4 -0
  39. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +10 -0
  40. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  41. package/build/contracts/bridge/Bridge.sol/Bridge.json +2470 -132
  42. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
  43. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +220 -0
  44. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
  45. package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
  46. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +4 -0
  47. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
  48. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +4 -0
  49. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +10 -0
  50. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +4 -0
  51. package/build/contracts/bridge/Fraud.sol/Fraud.json +86 -0
  52. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
  53. package/build/contracts/bridge/IRelay.sol/IRelay.json +37 -0
  54. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +4 -0
  55. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +125 -0
  56. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
  57. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +10 -0
  58. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
  59. package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
  60. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  61. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
  62. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +4 -0
  63. package/build/contracts/bridge/Wallets.sol/Wallets.json +112 -0
  64. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  65. package/build/contracts/token/TBTC.sol/TBTC.json +2 -2
  66. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  67. package/build/contracts/vault/IVault.sol/IVault.json +19 -1
  68. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  69. package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +36 -18
  70. package/contracts/GovernanceUtils.sol +1 -1
  71. package/contracts/bank/Bank.sol +34 -18
  72. package/contracts/bridge/BitcoinTx.sol +303 -0
  73. package/contracts/bridge/Bridge.sol +1527 -247
  74. package/contracts/bridge/BridgeState.sol +698 -0
  75. package/contracts/bridge/Deposit.sol +266 -0
  76. package/contracts/bridge/DepositSweep.sol +514 -0
  77. package/contracts/bridge/EcdsaLib.sol +45 -0
  78. package/contracts/bridge/Fraud.sol +508 -0
  79. package/contracts/bridge/IRelay.sol +28 -0
  80. package/contracts/bridge/MovingFunds.sol +1034 -0
  81. package/contracts/bridge/Redemption.sol +868 -0
  82. package/contracts/bridge/VendingMachine.sol +1 -1
  83. package/contracts/bridge/Wallets.sol +550 -0
  84. package/contracts/token/TBTC.sol +1 -1
  85. package/contracts/vault/IVault.sol +32 -10
  86. package/contracts/vault/TBTCVault.sol +20 -2
  87. package/deploy/00_resolve_relay.ts +28 -0
  88. package/deploy/04_deploy_bank.ts +27 -0
  89. package/deploy/05_deploy_bridge.ts +67 -0
  90. package/deploy/06_bank_update_bridge.ts +19 -0
  91. package/deploy/07_transfer_ownership.ts +15 -0
  92. package/deploy/08_transfer_governance.ts +20 -0
  93. package/export.json +15711 -475
  94. package/package.json +27 -24
  95. package/artifacts/solcInputs/c4fd2c31cc58f5fe0cc586dd84a84b60.json +0 -125
@@ -13,123 +13,279 @@
13
13
  // ▐████▌ ▐████▌
14
14
  // ▐████▌ ▐████▌
15
15
 
16
- pragma solidity 0.8.4;
16
+ pragma solidity ^0.8.9;
17
17
 
18
- import {BTCUtils} from "@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol";
19
- import {BytesLib} from "@keep-network/bitcoin-spv-sol/contracts/BytesLib.sol";
18
+ import "@keep-network/random-beacon/contracts/Governable.sol";
20
19
 
21
- /// @title BTC Bridge
22
- /// @notice Bridge manages BTC deposit and redemption and is increasing and
20
+ import {IWalletOwner as EcdsaWalletOwner} from "@keep-network/ecdsa/contracts/api/IWalletOwner.sol";
21
+
22
+ import "./IRelay.sol";
23
+ import "./BridgeState.sol";
24
+ import "./Deposit.sol";
25
+ import "./DepositSweep.sol";
26
+ import "./Redemption.sol";
27
+ import "./BitcoinTx.sol";
28
+ import "./EcdsaLib.sol";
29
+ import "./Wallets.sol";
30
+ import "./Fraud.sol";
31
+ import "./MovingFunds.sol";
32
+
33
+ import "../bank/Bank.sol";
34
+
35
+ /// @title Bitcoin Bridge
36
+ /// @notice Bridge manages BTC deposit and redemption flow and is increasing and
23
37
  /// decreasing balances in the Bank as a result of BTC deposit and
24
- /// redemption operations.
38
+ /// redemption operations performed by depositors and redeemers.
25
39
  ///
26
- /// Depositors send BTC funds to the most-recently-created-wallet of the
27
- /// bridge using pay-to-script-hash (P2SH) or
28
- /// pay-to-witness-script-hash (P2WSH) which contains hashed
29
- /// information about the depositor’s minting Ethereum address. Then,
30
- /// the depositor reveals their desired Ethereum minting address to the
31
- /// Ethereum chain. The Bridge listens for these sorts of messages and
32
- /// when it gets one, it checks the Bitcoin network to make sure the
33
- /// funds line up. If they do, the off-chain wallet may decide to pick
34
- /// this transaction for sweeping, and when the sweep operation is
35
- /// confirmed on the Bitcoin network, the wallet informs the Bridge
36
- /// about the sweep increasing appropriate balances in the Bank.
37
- /// @dev Bridge is an upgradeable component of the Bank.
38
- contract Bridge {
39
- using BTCUtils for bytes;
40
- using BytesLib for bytes;
41
-
42
- /// @notice Represents Bitcoin transaction data as described in:
43
- /// https://developer.bitcoin.org/reference/transactions.html#raw-transaction-format
44
- struct TxInfo {
45
- // Transaction version number (4-byte LE).
46
- bytes4 version;
47
- // All transaction inputs prepended by the number of inputs encoded
48
- // as a compactSize uint. Single vector item looks as follows:
49
- // https://developer.bitcoin.org/reference/transactions.html#txin-a-transaction-input-non-coinbase
50
- // though SegWit inputs don't contain the signature script (scriptSig).
51
- // All encoded input transaction hashes are little-endian.
52
- bytes inputVector;
53
- // All transaction outputs prepended by the number of outputs encoded
54
- // as a compactSize uint. Single vector item looks as follows:
55
- // https://developer.bitcoin.org/reference/transactions.html#txout-a-transaction-output
56
- bytes outputVector;
57
- // Transaction locktime (4-byte LE).
58
- bytes4 locktime;
59
- }
60
-
61
- /// @notice Represents data which must be revealed by the depositor during
62
- /// deposit reveal.
63
- struct RevealInfo {
64
- // Index of the funding output belonging to the funding transaction.
65
- uint8 fundingOutputIndex;
66
- // Ethereum depositor address.
67
- address depositor;
68
- // The blinding factor as 8 bytes. Byte endianness doesn't matter
69
- // as this factor is not interpreted as uint.
70
- bytes8 blindingFactor;
71
- // The compressed Bitcoin public key (33 bytes and 02 or 03 prefix)
72
- // of the deposit's wallet hashed in the HASH160 Bitcoin opcode style.
73
- bytes20 walletPubKeyHash;
74
- // The compressed Bitcoin public key (33 bytes and 02 or 03 prefix)
75
- // that can be used to make the deposit refund after the refund
76
- // locktime passes. Hashed in the HASH160 Bitcoin opcode style.
77
- bytes20 refundPubKeyHash;
78
- // The refund locktime (4-byte LE). Interpreted according to locktime
79
- // parsing rules described in:
80
- // https://developer.bitcoin.org/devguide/transactions.html#locktime-and-sequence-number
81
- // and used with OP_CHECKLOCKTIMEVERIFY opcode as described in:
82
- // https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
83
- bytes4 refundLocktime;
84
- // Address of the tBTC vault.
85
- address vault;
86
- }
87
-
88
- /// @notice Represents tBTC deposit data.
89
- struct DepositInfo {
90
- // Ethereum depositor address.
91
- address depositor;
92
- // Deposit amount in satoshi (8-byte LE). For example:
93
- // 0.0001 BTC = 10000 satoshi = 0x1027000000000000
94
- bytes8 amount;
95
- // UNIX timestamp the deposit was revealed at.
96
- uint32 revealedAt;
97
- // Address of the tBTC vault.
98
- address vault;
99
- }
100
-
101
- /// @notice Collection of all unswept deposits indexed by
102
- /// keccak256(fundingTxHash | fundingOutputIndex).
103
- /// The fundingTxHash is LE bytes32 and fundingOutputIndex an uint8.
104
- /// This mapping may contain valid and invalid deposits and the
105
- /// wallet is responsible for validating them before attempting to
106
- /// execute a sweep.
107
- ///
108
- /// TODO: Explore the possibility of storing just a hash of DepositInfo.
109
- mapping(uint256 => DepositInfo) public unswept;
40
+ /// Depositors send BTC funds to the most recently created off-chain
41
+ /// ECDSA wallet of the bridge using pay-to-script-hash (P2SH) or
42
+ /// pay-to-witness-script-hash (P2WSH) containing hashed information
43
+ /// about the depositor’s Ethereum address. Then, the depositor reveals
44
+ /// their Ethereum address along with their deposit blinding factor,
45
+ /// refund public key hash and refund locktime to the Bridge on Ethereum
46
+ /// chain. The off-chain ECDSA wallet listens for these sorts of
47
+ /// messages and when it gets one, it checks the Bitcoin network to make
48
+ /// sure the deposit lines up. If it does, the off-chain ECDSA wallet
49
+ /// may decide to pick the deposit transaction for sweeping, and when
50
+ /// the sweep operation is confirmed on the Bitcoin network, the ECDSA
51
+ /// wallet informs the Bridge about the sweep increasing appropriate
52
+ /// balances in the Bank.
53
+ /// @dev Bridge is an upgradeable component of the Bank. The order of
54
+ /// functionalities in this contract is: deposit, sweep, redemption,
55
+ /// moving funds, wallet lifecycle, frauds, parameters.
56
+ ///
57
+ /// TODO: Revisit all events and look which parameters should be indexed.
58
+ /// TODO: Align the convention around `param` and `dev` endings. They should
59
+ /// not have a punctuation mark.
60
+ contract Bridge is Governable, EcdsaWalletOwner {
61
+ using BridgeState for BridgeState.Storage;
62
+ using Deposit for BridgeState.Storage;
63
+ using DepositSweep for BridgeState.Storage;
64
+ using Redemption for BridgeState.Storage;
65
+ using MovingFunds for BridgeState.Storage;
66
+ using Wallets for BridgeState.Storage;
67
+ using Fraud for BridgeState.Storage;
68
+
69
+ BridgeState.Storage internal self;
110
70
 
111
71
  event DepositRevealed(
112
72
  bytes32 fundingTxHash,
113
- uint8 fundingOutputIndex,
73
+ uint32 fundingOutputIndex,
114
74
  address depositor,
75
+ uint64 amount,
115
76
  bytes8 blindingFactor,
116
77
  bytes20 walletPubKeyHash,
117
78
  bytes20 refundPubKeyHash,
118
- bytes4 refundLocktime
79
+ bytes4 refundLocktime,
80
+ address vault
81
+ );
82
+
83
+ event DepositsSwept(bytes20 walletPubKeyHash, bytes32 sweepTxHash);
84
+
85
+ event RedemptionRequested(
86
+ bytes20 walletPubKeyHash,
87
+ bytes redeemerOutputScript,
88
+ address redeemer,
89
+ uint64 requestedAmount,
90
+ uint64 treasuryFee,
91
+ uint64 txMaxFee
92
+ );
93
+
94
+ event RedemptionsCompleted(
95
+ bytes20 walletPubKeyHash,
96
+ bytes32 redemptionTxHash
97
+ );
98
+
99
+ event RedemptionTimedOut(
100
+ bytes20 walletPubKeyHash,
101
+ bytes redeemerOutputScript
102
+ );
103
+
104
+ event WalletMovingFunds(
105
+ bytes32 indexed ecdsaWalletID,
106
+ bytes20 indexed walletPubKeyHash
107
+ );
108
+
109
+ event MovingFundsCommitmentSubmitted(
110
+ bytes20 walletPubKeyHash,
111
+ bytes20[] targetWallets,
112
+ address submitter
113
+ );
114
+
115
+ event MovingFundsCompleted(
116
+ bytes20 walletPubKeyHash,
117
+ bytes32 movingFundsTxHash
118
+ );
119
+
120
+ event MovingFundsTimedOut(bytes20 walletPubKeyHash);
121
+
122
+ event MovingFundsBelowDustReported(bytes20 walletPubKeyHash);
123
+
124
+ event MovedFundsSwept(bytes20 walletPubKeyHash, bytes32 sweepTxHash);
125
+
126
+ event MovedFundsSweepTimedOut(
127
+ bytes20 walletPubKeyHash,
128
+ bytes32 movingFundsTxHash,
129
+ uint32 movingFundsTxOutputIndex
130
+ );
131
+
132
+ event NewWalletRequested();
133
+
134
+ event NewWalletRegistered(
135
+ bytes32 indexed ecdsaWalletID,
136
+ bytes20 indexed walletPubKeyHash
137
+ );
138
+
139
+ event WalletClosing(
140
+ bytes32 indexed ecdsaWalletID,
141
+ bytes20 indexed walletPubKeyHash
142
+ );
143
+
144
+ event WalletClosed(
145
+ bytes32 indexed ecdsaWalletID,
146
+ bytes20 indexed walletPubKeyHash
147
+ );
148
+
149
+ event WalletTerminated(
150
+ bytes32 indexed ecdsaWalletID,
151
+ bytes20 indexed walletPubKeyHash
152
+ );
153
+
154
+ event FraudChallengeSubmitted(
155
+ bytes20 walletPubKeyHash,
156
+ bytes32 sighash,
157
+ uint8 v,
158
+ bytes32 r,
159
+ bytes32 s
160
+ );
161
+
162
+ event FraudChallengeDefeated(bytes20 walletPubKeyHash, bytes32 sighash);
163
+
164
+ event FraudChallengeDefeatTimedOut(
165
+ bytes20 walletPubKeyHash,
166
+ bytes32 sighash
167
+ );
168
+
169
+ event VaultStatusUpdated(address indexed vault, bool isTrusted);
170
+
171
+ event DepositParametersUpdated(
172
+ uint64 depositDustThreshold,
173
+ uint64 depositTreasuryFeeDivisor,
174
+ uint64 depositTxMaxFee
175
+ );
176
+
177
+ event RedemptionParametersUpdated(
178
+ uint64 redemptionDustThreshold,
179
+ uint64 redemptionTreasuryFeeDivisor,
180
+ uint64 redemptionTxMaxFee,
181
+ uint256 redemptionTimeout,
182
+ uint96 redemptionTimeoutSlashingAmount,
183
+ uint256 redemptionTimeoutNotifierRewardMultiplier
184
+ );
185
+
186
+ event MovingFundsParametersUpdated(
187
+ uint64 movingFundsTxMaxTotalFee,
188
+ uint64 movingFundsDustThreshold,
189
+ uint32 movingFundsTimeout,
190
+ uint96 movingFundsTimeoutSlashingAmount,
191
+ uint256 movingFundsTimeoutNotifierRewardMultiplier,
192
+ uint64 movedFundsSweepTxMaxTotalFee,
193
+ uint32 movedFundsSweepTimeout,
194
+ uint96 movedFundsSweepTimeoutSlashingAmount,
195
+ uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
196
+ );
197
+
198
+ event WalletParametersUpdated(
199
+ uint32 walletCreationPeriod,
200
+ uint64 walletCreationMinBtcBalance,
201
+ uint64 walletCreationMaxBtcBalance,
202
+ uint64 walletClosureMinBtcBalance,
203
+ uint32 walletMaxAge,
204
+ uint64 walletMaxBtcTransfer,
205
+ uint32 walletClosingPeriod
119
206
  );
120
207
 
208
+ event FraudParametersUpdated(
209
+ uint256 fraudChallengeDepositAmount,
210
+ uint256 fraudChallengeDefeatTimeout,
211
+ uint96 fraudSlashingAmount,
212
+ uint256 fraudNotifierRewardMultiplier
213
+ );
214
+
215
+ constructor(
216
+ address _bank,
217
+ address _relay,
218
+ address _treasury,
219
+ address _ecdsaWalletRegistry,
220
+ uint256 _txProofDifficultyFactor
221
+ ) {
222
+ require(_bank != address(0), "Bank address cannot be zero");
223
+ self.bank = Bank(_bank);
224
+
225
+ require(_relay != address(0), "Relay address cannot be zero");
226
+ self.relay = IRelay(_relay);
227
+
228
+ require(
229
+ _ecdsaWalletRegistry != address(0),
230
+ "ECDSA Wallet Registry address cannot be zero"
231
+ );
232
+ self.ecdsaWalletRegistry = EcdsaWalletRegistry(_ecdsaWalletRegistry);
233
+
234
+ require(_treasury != address(0), "Treasury address cannot be zero");
235
+ self.treasury = _treasury;
236
+
237
+ self.txProofDifficultyFactor = _txProofDifficultyFactor;
238
+
239
+ // TODO: Revisit initial values.
240
+ self.depositDustThreshold = 1000000; // 1000000 satoshi = 0.01 BTC
241
+ self.depositTxMaxFee = 10000; // 10000 satoshi
242
+ self.depositTreasuryFeeDivisor = 2000; // 1/2000 == 5bps == 0.05% == 0.0005
243
+ self.redemptionDustThreshold = 1000000; // 1000000 satoshi = 0.01 BTC
244
+ self.redemptionTreasuryFeeDivisor = 2000; // 1/2000 == 5bps == 0.05% == 0.0005
245
+ self.redemptionTxMaxFee = 10000; // 10000 satoshi
246
+ self.redemptionTimeout = 172800; // 48 hours
247
+ self.redemptionTimeoutSlashingAmount = 10000 * 1e18; // 10000 T
248
+ self.redemptionTimeoutNotifierRewardMultiplier = 100; // 100%
249
+ self.movingFundsTxMaxTotalFee = 10000; // 10000 satoshi
250
+ self.movingFundsDustThreshold = 20000; // 20000 satoshi
251
+ self.movingFundsTimeout = 7 days;
252
+ self.movingFundsTimeoutSlashingAmount = 10000 * 1e18; // 10000 T
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%
258
+ self.fraudChallengeDepositAmount = 2 ether;
259
+ self.fraudChallengeDefeatTimeout = 7 days;
260
+ self.fraudSlashingAmount = 10000 * 1e18; // 10000 T
261
+ self.fraudNotifierRewardMultiplier = 100; // 100%
262
+ self.walletCreationPeriod = 1 weeks;
263
+ self.walletCreationMinBtcBalance = 1e8; // 1 BTC
264
+ self.walletCreationMaxBtcBalance = 100e8; // 100 BTC
265
+ self.walletClosureMinBtcBalance = 5 * 1e7; // 0.5 BTC
266
+ self.walletMaxAge = 26 weeks; // ~6 months
267
+ self.walletMaxBtcTransfer = 10e8; // 10 BTC
268
+ self.walletClosingPeriod = 40 days;
269
+
270
+ _transferGovernance(msg.sender);
271
+ }
272
+
121
273
  /// @notice Used by the depositor to reveal information about their P2(W)SH
122
274
  /// Bitcoin deposit to the Bridge on Ethereum chain. The off-chain
123
275
  /// wallet listens for revealed deposit events and may decide to
124
276
  /// include the revealed deposit in the next executed sweep.
125
277
  /// Information about the Bitcoin deposit can be revealed before or
126
278
  /// after the Bitcoin transaction with P2(W)SH deposit is mined on
127
- /// the Bitcoin chain. Worth noting the gas cost of this function
279
+ /// the Bitcoin chain. Worth noting, the gas cost of this function
128
280
  /// scales with the number of P2(W)SH transaction inputs and
129
- /// outputs.
130
- /// @param fundingTx Bitcoin funding transaction data.
131
- /// @param reveal Deposit reveal data.
281
+ /// outputs. The deposit may be routed to one of the trusted vaults.
282
+ /// When a deposit is routed to a vault, vault gets notified when
283
+ /// the deposit gets swept and it may execute the appropriate action.
284
+ /// @param fundingTx Bitcoin funding transaction data, see `BitcoinTx.Info`
285
+ /// @param reveal Deposit reveal data, see `RevealInfo struct
132
286
  /// @dev Requirements:
287
+ /// - `reveal.walletPubKeyHash` must identify a `Live` wallet
288
+ /// - `reveal.vault` must be 0x0 or point to a trusted vault
133
289
  /// - `reveal.fundingOutputIndex` must point to the actual P2(W)SH
134
290
  /// output of the BTC deposit transaction
135
291
  /// - `reveal.depositor` must be the Ethereum address used in the
@@ -149,122 +305,10 @@ contract Bridge {
149
305
  /// to sweep the deposit and the depositor has to wait until the
150
306
  /// deposit script unlocks to receive their BTC back.
151
307
  function revealDeposit(
152
- TxInfo calldata fundingTx,
153
- RevealInfo calldata reveal
308
+ BitcoinTx.Info calldata fundingTx,
309
+ Deposit.DepositRevealInfo calldata reveal
154
310
  ) external {
155
- bytes memory expectedScript =
156
- abi.encodePacked(
157
- hex"14", // Byte length of depositor Ethereum address.
158
- reveal.depositor,
159
- hex"75", // OP_DROP
160
- hex"08", // Byte length of blinding factor value.
161
- reveal.blindingFactor,
162
- hex"75", // OP_DROP
163
- hex"76", // OP_DUP
164
- hex"a9", // OP_HASH160
165
- hex"14", // Byte length of a compressed Bitcoin public key hash.
166
- reveal.walletPubKeyHash,
167
- hex"87", // OP_EQUAL
168
- hex"63", // OP_IF
169
- hex"ac", // OP_CHECKSIG
170
- hex"67", // OP_ELSE
171
- hex"76", // OP_DUP
172
- hex"a9", // OP_HASH160
173
- hex"14", // Byte length of a compressed Bitcoin public key hash.
174
- reveal.refundPubKeyHash,
175
- hex"88", // OP_EQUALVERIFY
176
- hex"04", // Byte length of refund locktime value.
177
- reveal.refundLocktime,
178
- hex"b1", // OP_CHECKLOCKTIMEVERIFY
179
- hex"75", // OP_DROP
180
- hex"ac", // OP_CHECKSIG
181
- hex"68" // OP_ENDIF
182
- );
183
-
184
- bytes memory fundingOutput =
185
- fundingTx.outputVector.extractOutputAtIndex(
186
- reveal.fundingOutputIndex
187
- );
188
- bytes memory fundingOutputHash = fundingOutput.extractHash();
189
-
190
- if (fundingOutputHash.length == 20) {
191
- // A 20-byte output hash is used by P2SH. That hash is constructed
192
- // by applying OP_HASH160 on the locking script. A 20-byte output
193
- // hash is used as well by P2PKH and P2WPKH (OP_HASH160 on the
194
- // public key). However, since we compare the actual output hash
195
- // with an expected locking script hash, this check will succeed only
196
- // for P2SH transaction type with expected script hash value. For
197
- // P2PKH and P2WPKH, it will fail on the output hash comparison with
198
- // the expected locking script hash.
199
- require(
200
- keccak256(fundingOutputHash) ==
201
- keccak256(expectedScript.hash160()),
202
- "Wrong 20-byte script hash"
203
- );
204
- } else if (fundingOutputHash.length == 32) {
205
- // A 32-byte output hash is used by P2WSH. That hash is constructed
206
- // by applying OP_HASH256 on the locking script.
207
- require(
208
- fundingOutputHash.toBytes32() == expectedScript.hash256(),
209
- "Wrong 32-byte script hash"
210
- );
211
- } else {
212
- revert("Wrong script hash length");
213
- }
214
-
215
- // Resulting TX hash is in native Bitcoin little-endian format.
216
- bytes32 fundingTxHash =
217
- abi
218
- .encodePacked(
219
- fundingTx
220
- .version,
221
- fundingTx
222
- .inputVector,
223
- fundingTx
224
- .outputVector,
225
- fundingTx
226
- .locktime
227
- )
228
- .hash256();
229
-
230
- DepositInfo storage deposit =
231
- unswept[
232
- uint256(
233
- keccak256(
234
- abi.encodePacked(
235
- fundingTxHash,
236
- reveal.fundingOutputIndex
237
- )
238
- )
239
- )
240
- ];
241
- require(deposit.revealedAt == 0, "Deposit already revealed");
242
-
243
- bytes8 fundingOutputAmount;
244
- /* solhint-disable-next-line no-inline-assembly */
245
- assembly {
246
- // First 8 bytes (little-endian) of the funding output represents
247
- // its value. To take the value, we need to jump over the first
248
- // word determining the array length, load the array, and trim it
249
- // by putting it to a bytes8.
250
- fundingOutputAmount := mload(add(fundingOutput, 32))
251
- }
252
-
253
- deposit.amount = fundingOutputAmount;
254
- deposit.depositor = reveal.depositor;
255
- /* solhint-disable-next-line not-rely-on-time */
256
- deposit.revealedAt = uint32(block.timestamp);
257
- deposit.vault = reveal.vault;
258
-
259
- emit DepositRevealed(
260
- fundingTxHash,
261
- reveal.fundingOutputIndex,
262
- reveal.depositor,
263
- reveal.blindingFactor,
264
- reveal.walletPubKeyHash,
265
- reveal.refundPubKeyHash,
266
- reveal.refundLocktime
267
- );
311
+ self.revealDeposit(fundingTx, reveal);
268
312
  }
269
313
 
270
314
  /// @notice Used by the wallet to prove the BTC deposit sweep transaction
@@ -278,41 +322,1277 @@ contract Bridge {
278
322
  /// during the reveal transaction, minus their fee share.
279
323
  ///
280
324
  /// It is possible to prove the given sweep only one time.
281
- /// @param sweepTx Bitcoin sweep transaction data.
282
- /// @param merkleProof The merkle proof of transaction inclusion in a block.
283
- /// @param txIndexInBlock Transaction index in the block (0-indexed).
284
- /// @param bitcoinHeaders Single bytestring of 80-byte bitcoin headers,
285
- /// lowest height first.
286
- function sweep(
287
- TxInfo calldata sweepTx,
288
- bytes memory merkleProof,
289
- uint256 txIndexInBlock,
290
- bytes memory bitcoinHeaders
325
+ /// @param sweepTx Bitcoin sweep transaction data
326
+ /// @param sweepProof Bitcoin sweep proof data
327
+ /// @param mainUtxo Data of the wallet's main UTXO, as currently known on
328
+ /// the Ethereum chain. If no main UTXO exists for the given wallet,
329
+ /// this parameter is ignored
330
+ /// @dev Requirements:
331
+ /// - `sweepTx` components must match the expected structure. See
332
+ /// `BitcoinTx.Info` docs for reference. Their values must exactly
333
+ /// correspond to appropriate Bitcoin transaction fields to produce
334
+ /// a provable transaction hash.
335
+ /// - The `sweepTx` should represent a Bitcoin transaction with 1..n
336
+ /// inputs. If the wallet has no main UTXO, all n inputs should
337
+ /// correspond to P2(W)SH revealed deposits UTXOs. If the wallet has
338
+ /// an existing main UTXO, one of the n inputs must point to that
339
+ /// main UTXO and remaining n-1 inputs should correspond to P2(W)SH
340
+ /// revealed deposits UTXOs. That transaction must have only
341
+ /// one P2(W)PKH output locking funds on the 20-byte wallet public
342
+ /// key hash.
343
+ /// - `sweepProof` components must match the expected structure. See
344
+ /// `BitcoinTx.Proof` docs for reference. The `bitcoinHeaders`
345
+ /// field must contain a valid number of block headers, not less
346
+ /// than the `txProofDifficultyFactor` contract constant.
347
+ /// - `mainUtxo` components must point to the recent main UTXO
348
+ /// of the given wallet, as currently known on the Ethereum chain.
349
+ /// If there is no main UTXO, this parameter is ignored.
350
+ function submitDepositSweepProof(
351
+ BitcoinTx.Info calldata sweepTx,
352
+ BitcoinTx.Proof calldata sweepProof,
353
+ BitcoinTx.UTXO calldata mainUtxo
354
+ ) external {
355
+ self.submitDepositSweepProof(sweepTx, sweepProof, mainUtxo);
356
+ }
357
+
358
+ /// @notice Requests redemption of the given amount from the specified
359
+ /// wallet to the redeemer Bitcoin output script.
360
+ /// @param walletPubKeyHash The 20-byte wallet public key hash (computed
361
+ /// using Bitcoin HASH160 over the compressed ECDSA public key)
362
+ /// @param mainUtxo Data of the wallet's main UTXO, as currently known on
363
+ /// the Ethereum chain
364
+ /// @param redeemerOutputScript The redeemer's length-prefixed output
365
+ /// script (P2PKH, P2WPKH, P2SH or P2WSH) that will be used to lock
366
+ /// redeemed BTC
367
+ /// @param amount Requested amount in satoshi. This is also the TBTC amount
368
+ /// that is taken from redeemer's balance in the Bank upon request.
369
+ /// Once the request is handled, the actual amount of BTC locked
370
+ /// on the redeemer output script will be always lower than this value
371
+ /// since the treasury and Bitcoin transaction fees must be incurred.
372
+ /// The minimal amount satisfying the request can be computed as:
373
+ /// `amount - (amount / redemptionTreasuryFeeDivisor) - redemptionTxMaxFee`.
374
+ /// Fees values are taken at the moment of request creation.
375
+ /// @dev Requirements:
376
+ /// - Wallet behind `walletPubKeyHash` must be live
377
+ /// - `mainUtxo` components must point to the recent main UTXO
378
+ /// of the given wallet, as currently known on the Ethereum chain.
379
+ /// - `redeemerOutputScript` must be a proper Bitcoin script
380
+ /// - `redeemerOutputScript` cannot have wallet PKH as payload
381
+ /// - `amount` must be above or equal the `redemptionDustThreshold`
382
+ /// - Given `walletPubKeyHash` and `redeemerOutputScript` pair can be
383
+ /// used for only one pending request at the same time
384
+ /// - Wallet must have enough Bitcoin balance to proceed the request
385
+ /// - Redeemer must make an allowance in the Bank that the Bridge
386
+ /// contract can spend the given `amount`.
387
+ function requestRedemption(
388
+ bytes20 walletPubKeyHash,
389
+ BitcoinTx.UTXO calldata mainUtxo,
390
+ bytes calldata redeemerOutputScript,
391
+ uint64 amount
392
+ ) external {
393
+ self.requestRedemption(
394
+ walletPubKeyHash,
395
+ mainUtxo,
396
+ redeemerOutputScript,
397
+ amount
398
+ );
399
+ }
400
+
401
+ /// @notice Used by the wallet to prove the BTC redemption transaction
402
+ /// and to make the necessary bookkeeping. Redemption is only
403
+ /// accepted if it satisfies SPV proof.
404
+ ///
405
+ /// The function is performing Bank balance updates by burning
406
+ /// the total redeemed Bitcoin amount from Bridge balance and
407
+ /// transferring the treasury fee sum to the treasury address.
408
+ ///
409
+ /// It is possible to prove the given redemption only one time.
410
+ /// @param redemptionTx Bitcoin redemption transaction data
411
+ /// @param redemptionProof Bitcoin redemption proof data
412
+ /// @param mainUtxo Data of the wallet's main UTXO, as currently known on
413
+ /// the Ethereum chain
414
+ /// @param walletPubKeyHash 20-byte public key hash (computed using Bitcoin
415
+ /// HASH160 over the compressed ECDSA public key) of the wallet which
416
+ /// performed the redemption transaction
417
+ /// @dev Requirements:
418
+ /// - `redemptionTx` components must match the expected structure. See
419
+ /// `BitcoinTx.Info` docs for reference. Their values must exactly
420
+ /// correspond to appropriate Bitcoin transaction fields to produce
421
+ /// a provable transaction hash.
422
+ /// - The `redemptionTx` should represent a Bitcoin transaction with
423
+ /// exactly 1 input that refers to the wallet's main UTXO. That
424
+ /// transaction should have 1..n outputs handling existing pending
425
+ /// redemption requests or pointing to reported timed out requests.
426
+ /// There can be also 1 optional output representing the
427
+ /// change and pointing back to the 20-byte wallet public key hash.
428
+ /// The change should be always present if the redeemed value sum
429
+ /// is lower than the total wallet's BTC balance.
430
+ /// - `redemptionProof` components must match the expected structure.
431
+ /// See `BitcoinTx.Proof` docs for reference. The `bitcoinHeaders`
432
+ /// field must contain a valid number of block headers, not less
433
+ /// than the `txProofDifficultyFactor` contract constant.
434
+ /// - `mainUtxo` components must point to the recent main UTXO
435
+ /// of the given wallet, as currently known on the Ethereum chain.
436
+ /// Additionally, the recent main UTXO on Ethereum must be set.
437
+ /// - `walletPubKeyHash` must be connected with the main UTXO used
438
+ /// as transaction single input.
439
+ /// Other remarks:
440
+ /// - Putting the change output as the first transaction output can
441
+ /// save some gas because the output processing loop begins each
442
+ /// iteration by checking whether the given output is the change
443
+ /// thus uses some gas for making the comparison. Once the change
444
+ /// is identified, that check is omitted in further iterations.
445
+ function submitRedemptionProof(
446
+ BitcoinTx.Info calldata redemptionTx,
447
+ BitcoinTx.Proof calldata redemptionProof,
448
+ BitcoinTx.UTXO calldata mainUtxo,
449
+ bytes20 walletPubKeyHash
450
+ ) external {
451
+ self.submitRedemptionProof(
452
+ redemptionTx,
453
+ redemptionProof,
454
+ mainUtxo,
455
+ walletPubKeyHash
456
+ );
457
+ }
458
+
459
+ /// @notice Notifies that there is a pending redemption request associated
460
+ /// with the given wallet, that has timed out. The redemption
461
+ /// request is identified by the key built as
462
+ /// `keccak256(walletPubKeyHash | redeemerOutputScript)`.
463
+ /// The results of calling this function:
464
+ /// - the pending redemptions value for the wallet will be decreased
465
+ /// by the requested amount (minus treasury fee),
466
+ /// - the tokens taken from the redeemer on redemption request will
467
+ /// be returned to the redeemer,
468
+ /// - the request will be moved from pending redemptions to
469
+ /// timed-out redemptions,
470
+ /// - if the state of the wallet is `Live` or `MovingFunds`, the
471
+ /// wallet operators will be slashed and the notifier will be
472
+ /// rewarded,
473
+ /// - if the state of wallet is `Live`, the wallet will be closed or
474
+ /// marked as `MovingFunds` (depending on the presence or absence
475
+ /// of the wallet's main UTXO) and the wallet will no longer be
476
+ /// marked as the active wallet (if it was marked as such).
477
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet
478
+ /// @param walletMembersIDs Identifiers of the wallet signing group members
479
+ /// @param redeemerOutputScript The redeemer's length-prefixed output
480
+ /// script (P2PKH, P2WPKH, P2SH or P2WSH)
481
+ /// @dev Requirements:
482
+ /// - The wallet must be in the Live or MovingFunds or Terminated state
483
+ /// - The redemption request identified by `walletPubKeyHash` and
484
+ /// `redeemerOutputScript` must exist
485
+ /// - The expression `keccak256(abi.encode(walletMembersIDs))` must
486
+ /// be exactly the same as the hash stored under `membersIdsHash`
487
+ /// for the given `walletID`. Those IDs are not directly stored
488
+ /// in the contract for gas efficiency purposes but they can be
489
+ /// read from appropriate `DkgResultSubmitted` and `DkgResultApproved`
490
+ /// events of the `WalletRegistry` contract
491
+ /// - The amount of time defined by `redemptionTimeout` must have
492
+ /// passed since the redemption was requested (the request must be
493
+ /// timed-out)
494
+ function notifyRedemptionTimeout(
495
+ bytes20 walletPubKeyHash,
496
+ uint32[] calldata walletMembersIDs,
497
+ bytes calldata redeemerOutputScript
498
+ ) external {
499
+ self.notifyRedemptionTimeout(
500
+ walletPubKeyHash,
501
+ walletMembersIDs,
502
+ redeemerOutputScript
503
+ );
504
+ }
505
+
506
+ /// @notice Submits the moving funds target wallets commitment.
507
+ /// Once all requirements are met, that function registers the
508
+ /// target wallets commitment and opens the way for moving funds
509
+ /// proof submission.
510
+ /// @param walletPubKeyHash 20-byte public key hash of the source wallet
511
+ /// @param walletMainUtxo Data of the source wallet's main UTXO, as
512
+ /// currently known on the Ethereum chain
513
+ /// @param walletMembersIDs Identifiers of the source wallet signing group
514
+ /// members
515
+ /// @param walletMemberIndex Position of the caller in the source wallet
516
+ /// signing group members list
517
+ /// @param targetWallets List of 20-byte public key hashes of the target
518
+ /// wallets that the source wallet commits to move the funds to
519
+ /// @dev Requirements:
520
+ /// - The source wallet must be in the MovingFunds state
521
+ /// - The source wallet must not have pending redemption requests
522
+ /// - The source wallet must not have pending moved funds sweep requests
523
+ /// - The source wallet must not have submitted its commitment already
524
+ /// - The expression `keccak256(abi.encode(walletMembersIDs))` must
525
+ /// be exactly the same as the hash stored under `membersIdsHash`
526
+ /// for the given source wallet in the ECDSA registry. Those IDs are
527
+ /// not directly stored in the contract for gas efficiency purposes
528
+ /// but they can be read from appropriate `DkgResultSubmitted`
529
+ /// and `DkgResultApproved` events.
530
+ /// - The `walletMemberIndex` must be in range [1, walletMembersIDs.length]
531
+ /// - The caller must be the member of the source wallet signing group
532
+ /// at the position indicated by `walletMemberIndex` parameter
533
+ /// - The `walletMainUtxo` components must point to the recent main
534
+ /// UTXO of the source wallet, as currently known on the Ethereum
535
+ /// chain.
536
+ /// - Source wallet BTC balance must be greater than zero
537
+ /// - At least one Live wallet must exist in the system
538
+ /// - Submitted target wallets count must match the expected count
539
+ /// `N = min(liveWalletsCount, ceil(walletBtcBalance / walletMaxBtcTransfer))`
540
+ /// where `N > 0`
541
+ /// - Each target wallet must be not equal to the source wallet
542
+ /// - Each target wallet must follow the expected order i.e. all
543
+ /// target wallets 20-byte public key hashes represented as numbers
544
+ /// must form a strictly increasing sequence without duplicates.
545
+ /// - Each target wallet must be in Live state
546
+ function submitMovingFundsCommitment(
547
+ bytes20 walletPubKeyHash,
548
+ BitcoinTx.UTXO calldata walletMainUtxo,
549
+ uint32[] calldata walletMembersIDs,
550
+ uint256 walletMemberIndex,
551
+ bytes20[] calldata targetWallets
552
+ ) external {
553
+ self.submitMovingFundsCommitment(
554
+ walletPubKeyHash,
555
+ walletMainUtxo,
556
+ walletMembersIDs,
557
+ walletMemberIndex,
558
+ targetWallets
559
+ );
560
+ }
561
+
562
+ /// @notice Used by the wallet to prove the BTC moving funds transaction
563
+ /// and to make the necessary state changes. Moving funds is only
564
+ /// accepted if it satisfies SPV proof.
565
+ ///
566
+ /// The function validates the moving funds transaction structure
567
+ /// by checking if it actually spends the main UTXO of the declared
568
+ /// wallet and locks the value on the pre-committed target wallets
569
+ /// using a reasonable transaction fee. If all preconditions are
570
+ /// met, this functions closes the source wallet.
571
+ ///
572
+ /// It is possible to prove the given moving funds transaction only
573
+ /// one time.
574
+ /// @param movingFundsTx Bitcoin moving funds transaction data
575
+ /// @param movingFundsProof Bitcoin moving funds proof data
576
+ /// @param mainUtxo Data of the wallet's main UTXO, as currently known on
577
+ /// the Ethereum chain
578
+ /// @param walletPubKeyHash 20-byte public key hash (computed using Bitcoin
579
+ /// HASH160 over the compressed ECDSA public key) of the wallet
580
+ /// which performed the moving funds transaction
581
+ /// @dev Requirements:
582
+ /// - `movingFundsTx` components must match the expected structure. See
583
+ /// `BitcoinTx.Info` docs for reference. Their values must exactly
584
+ /// correspond to appropriate Bitcoin transaction fields to produce
585
+ /// a provable transaction hash.
586
+ /// - The `movingFundsTx` should represent a Bitcoin transaction with
587
+ /// exactly 1 input that refers to the wallet's main UTXO. That
588
+ /// transaction should have 1..n outputs corresponding to the
589
+ /// pre-committed target wallets. Outputs must be ordered in the
590
+ /// same way as their corresponding target wallets are ordered
591
+ /// within the target wallets commitment.
592
+ /// - `movingFundsProof` components must match the expected structure.
593
+ /// See `BitcoinTx.Proof` docs for reference. The `bitcoinHeaders`
594
+ /// field must contain a valid number of block headers, not less
595
+ /// than the `txProofDifficultyFactor` contract constant.
596
+ /// - `mainUtxo` components must point to the recent main UTXO
597
+ /// of the given wallet, as currently known on the Ethereum chain.
598
+ /// Additionally, the recent main UTXO on Ethereum must be set.
599
+ /// - `walletPubKeyHash` must be connected with the main UTXO used
600
+ /// as transaction single input.
601
+ /// - The wallet that `walletPubKeyHash` points to must be in the
602
+ /// MovingFunds state.
603
+ /// - The target wallets commitment must be submitted by the wallet
604
+ /// that `walletPubKeyHash` points to.
605
+ /// - The total Bitcoin transaction fee must be lesser or equal
606
+ /// to `movingFundsTxMaxTotalFee` governable parameter.
607
+ function submitMovingFundsProof(
608
+ BitcoinTx.Info calldata movingFundsTx,
609
+ BitcoinTx.Proof calldata movingFundsProof,
610
+ BitcoinTx.UTXO calldata mainUtxo,
611
+ bytes20 walletPubKeyHash
612
+ ) external {
613
+ self.submitMovingFundsProof(
614
+ movingFundsTx,
615
+ movingFundsProof,
616
+ mainUtxo,
617
+ walletPubKeyHash
618
+ );
619
+ }
620
+
621
+ /// @notice Notifies about a timed out moving funds process. Terminates
622
+ /// the wallet and slashes signing group members as a result.
623
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet
624
+ /// @param walletMembersIDs Identifiers of the wallet signing group members
625
+ /// @dev Requirements:
626
+ /// - The wallet must be in the MovingFunds state
627
+ /// - The moving funds timeout must be actually exceeded
628
+ /// - The expression `keccak256(abi.encode(walletMembersIDs))` must
629
+ /// be exactly the same as the hash stored under `membersIdsHash`
630
+ /// for the given `walletID`. Those IDs are not directly stored
631
+ /// in the contract for gas efficiency purposes but they can be
632
+ /// read from appropriate `DkgResultSubmitted` and `DkgResultApproved`
633
+ /// events of the `WalletRegistry` contract
634
+ function notifyMovingFundsTimeout(
635
+ bytes20 walletPubKeyHash,
636
+ uint32[] calldata walletMembersIDs
291
637
  ) external {
292
- // TODO We need to read `fundingTxHash`, `fundingOutputIndex` from
293
- // `sweepTx.inputVector`. We then hash them to obtain deposit
294
- // identifier and read DepositInfo. From DepositInfo we know what
295
- // amount was inferred during deposit reveal transaction and we
296
- // use that amount to update their Bank balance, minus fee.
297
- //
298
- // TODO We need to validate if the sum in the output minus the
299
- // amount from the previous wallet balance input minus fees is
300
- // equal to the amount by which Bank balances were increased.
301
- //
302
- // TODO We need to validate `sweepTx.outputVector` to see if the balance
303
- // was not transferred away from the wallet before increasing
304
- // balances in the bank.
305
- //
306
- // TODO Delete deposit from unswept mapping or mark it as swept
307
- // depending on the gas costs. Alternatively, do not allow to
308
- // use the same TX input vector twice. Sweep should be provable
309
- // only one time.
310
- }
311
-
312
- // TODO It is possible a malicious wallet can sweep deposits that can not
313
- // be later proved on Ethereum. For example, a deposit with
314
- // an incorrect amount revealed. We need to provide a function for honest
315
- // depositors, next to sweep, to prove their swept balances on Ethereum
316
- // selectively, based on deposits they have earlier received.
317
- // (UPDATE PR #90: Is it still the case since amounts are inferred?)
638
+ self.notifyMovingFundsTimeout(walletPubKeyHash, walletMembersIDs);
639
+ }
640
+
641
+ /// @notice Notifies about a moving funds wallet whose BTC balance is
642
+ /// below the moving funds dust threshold. Ends the moving funds
643
+ /// process and begins wallet closing immediately.
644
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet
645
+ /// @param mainUtxo Data of the wallet's main UTXO, as currently known
646
+ /// on the Ethereum chain.
647
+ /// @dev Requirements:
648
+ /// - The wallet must be in the MovingFunds state
649
+ /// - The `mainUtxo` components must point to the recent main UTXO
650
+ /// of the given wallet, as currently known on the Ethereum chain.
651
+ /// If the wallet has no main UTXO, this parameter can be empty as it
652
+ /// is ignored.
653
+ /// - The wallet BTC balance must be below the moving funds threshold
654
+ function notifyMovingFundsBelowDust(
655
+ bytes20 walletPubKeyHash,
656
+ BitcoinTx.UTXO calldata mainUtxo
657
+ ) external {
658
+ self.notifyMovingFundsBelowDust(walletPubKeyHash, mainUtxo);
659
+ }
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
+
740
+ /// @notice Requests creation of a new wallet. This function just
741
+ /// forms a request and the creation process is performed
742
+ /// asynchronously. Once a wallet is created, the ECDSA Wallet
743
+ /// Registry will notify this contract by calling the
744
+ /// `__ecdsaWalletCreatedCallback` function.
745
+ /// @param activeWalletMainUtxo Data of the active wallet's main UTXO, as
746
+ /// currently known on the Ethereum chain.
747
+ /// @dev Requirements:
748
+ /// - `activeWalletMainUtxo` components must point to the recent main
749
+ /// UTXO of the given active wallet, as currently known on the
750
+ /// Ethereum chain. If there is no active wallet at the moment, or
751
+ /// the active wallet has no main UTXO, this parameter can be
752
+ /// empty as it is ignored.
753
+ /// - Wallet creation must not be in progress
754
+ /// - If the active wallet is set, one of the following
755
+ /// conditions must be true:
756
+ /// - The active wallet BTC balance is above the minimum threshold
757
+ /// and the active wallet is old enough, i.e. the creation period
758
+ /// was elapsed since its creation time
759
+ /// - The active wallet BTC balance is above the maximum threshold
760
+ function requestNewWallet(BitcoinTx.UTXO calldata activeWalletMainUtxo)
761
+ external
762
+ {
763
+ self.requestNewWallet(activeWalletMainUtxo);
764
+ }
765
+
766
+ /// @notice A callback function that is called by the ECDSA Wallet Registry
767
+ /// once a new ECDSA wallet is created.
768
+ /// @param ecdsaWalletID Wallet's unique identifier.
769
+ /// @param publicKeyX Wallet's public key's X coordinate.
770
+ /// @param publicKeyY Wallet's public key's Y coordinate.
771
+ /// @dev Requirements:
772
+ /// - The only caller authorized to call this function is `registry`
773
+ /// - Given wallet data must not belong to an already registered wallet
774
+ function __ecdsaWalletCreatedCallback(
775
+ bytes32 ecdsaWalletID,
776
+ bytes32 publicKeyX,
777
+ bytes32 publicKeyY
778
+ ) external override {
779
+ self.registerNewWallet(ecdsaWalletID, publicKeyX, publicKeyY);
780
+ }
781
+
782
+ /// @notice A callback function that is called by the ECDSA Wallet Registry
783
+ /// once a wallet heartbeat failure is detected.
784
+ /// @param publicKeyX Wallet's public key's X coordinate
785
+ /// @param publicKeyY Wallet's public key's Y coordinate
786
+ /// @dev Requirements:
787
+ /// - The only caller authorized to call this function is `registry`
788
+ /// - Wallet must be in Live state
789
+ function __ecdsaWalletHeartbeatFailedCallback(
790
+ bytes32,
791
+ bytes32 publicKeyX,
792
+ bytes32 publicKeyY
793
+ ) external override {
794
+ self.notifyWalletHeartbeatFailed(publicKeyX, publicKeyY);
795
+ }
796
+
797
+ /// @notice Notifies that the wallet is either old enough or has too few
798
+ /// satoshi left and qualifies to be closed.
799
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet
800
+ /// @param walletMainUtxo Data of the wallet's main UTXO, as currently
801
+ /// known on the Ethereum chain.
802
+ /// @dev Requirements:
803
+ /// - Wallet must not be set as the current active wallet
804
+ /// - Wallet must exceed the wallet maximum age OR the wallet BTC
805
+ /// balance must be lesser than the minimum threshold. If the latter
806
+ /// case is true, the `walletMainUtxo` components must point to the
807
+ /// recent main UTXO of the given wallet, as currently known on the
808
+ /// Ethereum chain. If the wallet has no main UTXO, this parameter
809
+ /// can be empty as it is ignored since the wallet balance is
810
+ /// assumed to be zero.
811
+ /// - Wallet must be in Live state
812
+ function notifyCloseableWallet(
813
+ bytes20 walletPubKeyHash,
814
+ BitcoinTx.UTXO calldata walletMainUtxo
815
+ ) external {
816
+ self.notifyCloseableWallet(walletPubKeyHash, walletMainUtxo);
817
+ }
818
+
819
+ /// @notice Notifies about the end of the closing period for the given wallet.
820
+ /// Closes the wallet ultimately and notifies the ECDSA registry
821
+ /// about this fact.
822
+ /// @param walletPubKeyHash 20-byte public key hash of the wallet
823
+ /// @dev Requirements:
824
+ /// - The wallet must be in the Closing state
825
+ /// - The wallet closing period must have elapsed
826
+ function notifyWalletClosingPeriodElapsed(bytes20 walletPubKeyHash)
827
+ external
828
+ {
829
+ self.notifyWalletClosingPeriodElapsed(walletPubKeyHash);
830
+ }
831
+
832
+ /// @notice Submits a fraud challenge indicating that a UTXO being under
833
+ /// wallet control was unlocked by the wallet but was not used
834
+ /// according to the protocol rules. That means the wallet signed
835
+ /// a transaction input pointing to that UTXO and there is a unique
836
+ /// sighash and signature pair associated with that input. This
837
+ /// function uses those parameters to create a fraud accusation that
838
+ /// proves a given transaction input unlocking the given UTXO was
839
+ /// actually signed by the wallet. This function cannot determine
840
+ /// whether the transaction was actually broadcast and the input was
841
+ /// consumed in a fraudulent way so it just opens a challenge period
842
+ /// during which the wallet can defeat the challenge by submitting
843
+ /// proof of a transaction that consumes the given input according
844
+ /// to protocol rules. To prevent spurious allegations, the caller
845
+ /// must deposit ETH that is returned back upon justified fraud
846
+ /// challenge or confiscated otherwise.
847
+ ///@param walletPublicKey The public key of the wallet in the uncompressed
848
+ /// and unprefixed format (64 bytes)
849
+ /// @param sighash The hash that was used to produce the ECDSA signature
850
+ /// that is the subject of the fraud claim. This hash is constructed
851
+ /// by applying double SHA-256 over a serialized subset of the
852
+ /// transaction. The exact subset used as hash preimage depends on
853
+ /// the transaction input the signature is produced for. See BIP-143
854
+ /// for reference
855
+ /// @param signature Bitcoin signature in the R/S/V format
856
+ /// @dev Requirements:
857
+ /// - Wallet behind `walletPublicKey` must be in Live or MovingFunds
858
+ /// or Closing state
859
+ /// - The challenger must send appropriate amount of ETH used as
860
+ /// fraud challenge deposit
861
+ /// - The signature (represented by r, s and v) must be generated by
862
+ /// the wallet behind `walletPubKey` during signing of `sighash`
863
+ /// - Wallet can be challenged for the given signature only once
864
+ function submitFraudChallenge(
865
+ bytes calldata walletPublicKey,
866
+ bytes32 sighash,
867
+ BitcoinTx.RSVSignature calldata signature
868
+ ) external payable {
869
+ self.submitFraudChallenge(walletPublicKey, sighash, signature);
870
+ }
871
+
872
+ /// @notice Allows to defeat a pending fraud challenge against a wallet if
873
+ /// the transaction that spends the UTXO follows the protocol rules.
874
+ /// In order to defeat the challenge the same `walletPublicKey` and
875
+ /// signature (represented by `r`, `s` and `v`) must be provided as
876
+ /// were used to calculate the sighash during input signing.
877
+ /// The fraud challenge defeat attempt will only succeed if the
878
+ /// inputs in the preimage are considered honestly spent by the
879
+ /// wallet. Therefore the transaction spending the UTXO must be
880
+ /// proven in the Bridge before a challenge defeat is called.
881
+ /// If successfully defeated, the fraud challenge is marked as
882
+ /// resolved and the amount of ether deposited by the challenger is
883
+ /// sent to the treasury.
884
+ /// @param walletPublicKey The public key of the wallet in the uncompressed
885
+ /// and unprefixed format (64 bytes)
886
+ /// @param preimage The preimage which produces sighash used to generate the
887
+ /// ECDSA signature that is the subject of the fraud claim. It is a
888
+ /// serialized subset of the transaction. The exact subset used as
889
+ /// the preimage depends on the transaction input the signature is
890
+ /// produced for. See BIP-143 for reference
891
+ /// @param witness Flag indicating whether the preimage was produced for a
892
+ /// witness input. True for witness, false for non-witness input
893
+ /// @dev Requirements:
894
+ /// - `walletPublicKey` and `sighash` calculated as `hash256(preimage)`
895
+ /// must identify an open fraud challenge
896
+ /// - the preimage must be a valid preimage of a transaction generated
897
+ /// according to the protocol rules and already proved in the Bridge
898
+ /// - before a defeat attempt is made the transaction that spends the
899
+ /// given UTXO must be proven in the Bridge
900
+ function defeatFraudChallenge(
901
+ bytes calldata walletPublicKey,
902
+ bytes calldata preimage,
903
+ bool witness
904
+ ) external {
905
+ self.defeatFraudChallenge(walletPublicKey, preimage, witness);
906
+ }
907
+
908
+ /// @notice Notifies about defeat timeout for the given fraud challenge.
909
+ /// Can be called only if there was a fraud challenge identified by
910
+ /// the provided `walletPublicKey` and `sighash` and it was not
911
+ /// defeated on time. The amount of time that needs to pass after
912
+ /// a fraud challenge is reported is indicated by the
913
+ /// `challengeDefeatTimeout`. After a successful fraud challenge
914
+ /// defeat timeout notification the fraud challenge is marked as
915
+ /// resolved, the stake of each operator is slashed, the ether
916
+ /// deposited is returned to the challenger and the challenger is
917
+ /// rewarded.
918
+ /// @param walletPublicKey The public key of the wallet in the uncompressed
919
+ /// and unprefixed format (64 bytes)
920
+ /// @param walletMembersIDs Identifiers of the wallet signing group members
921
+ /// @param sighash The hash that was used to produce the ECDSA signature
922
+ /// that is the subject of the fraud claim. This hash is constructed
923
+ /// by applying double SHA-256 over a serialized subset of the
924
+ /// transaction. The exact subset used as hash preimage depends on
925
+ /// the transaction input the signature is produced for. See BIP-143
926
+ /// for reference
927
+ /// @dev Requirements:
928
+ /// - The wallet must be in the Live or MovingFunds or Closing or
929
+ /// Terminated state
930
+ /// - The `walletPublicKey` and `sighash` must identify an open fraud
931
+ /// challenge
932
+ /// - The expression `keccak256(abi.encode(walletMembersIDs))` must
933
+ /// be exactly the same as the hash stored under `membersIdsHash`
934
+ /// for the given `walletID`. Those IDs are not directly stored
935
+ /// in the contract for gas efficiency purposes but they can be
936
+ /// read from appropriate `DkgResultSubmitted` and `DkgResultApproved`
937
+ /// events of the `WalletRegistry` contract
938
+ /// - The amount of time indicated by `challengeDefeatTimeout` must pass
939
+ /// after the challenge was reported
940
+ function notifyFraudChallengeDefeatTimeout(
941
+ bytes calldata walletPublicKey,
942
+ uint32[] calldata walletMembersIDs,
943
+ bytes32 sighash
944
+ ) external {
945
+ self.notifyFraudChallengeDefeatTimeout(
946
+ walletPublicKey,
947
+ walletMembersIDs,
948
+ sighash
949
+ );
950
+ }
951
+
952
+ /// @notice Allows the Governance to mark the given vault address as trusted
953
+ /// or no longer trusted. Vaults are not trusted by default.
954
+ /// Trusted vault must meet the following criteria:
955
+ /// - `IVault.receiveBalanceIncrease` must have a known, low gas
956
+ /// cost.
957
+ /// - `IVault.receiveBalanceIncrease` must never revert.
958
+ /// @dev Without restricting reveal only to trusted vaults, malicious
959
+ /// vaults not meeting the criteria would be able to nuke sweep proof
960
+ /// transactions executed by ECDSA wallet with deposits routed to
961
+ /// them.
962
+ /// @param vault The address of the vault
963
+ /// @param isTrusted flag indicating whether the vault is trusted or not
964
+ /// @dev Can only be called by the Governance.
965
+ function setVaultStatus(address vault, bool isTrusted)
966
+ external
967
+ onlyGovernance
968
+ {
969
+ self.isVaultTrusted[vault] = isTrusted;
970
+ emit VaultStatusUpdated(vault, isTrusted);
971
+ }
972
+
973
+ /// @notice Updates parameters of deposits.
974
+ /// @param depositDustThreshold New value of the deposit dust threshold in
975
+ /// satoshis. It is the minimal amount that can be requested to
976
+ //// deposit. Value of this parameter must take into account the value
977
+ /// of `depositTreasuryFeeDivisor` and `depositTxMaxFee` parameters
978
+ /// in order to make requests that can incur the treasury and
979
+ /// transaction fee and still satisfy the depositor
980
+ /// @param depositTreasuryFeeDivisor New value of the treasury fee divisor.
981
+ /// It is the divisor used to compute the treasury fee taken from
982
+ /// each deposit and transferred to the treasury upon sweep proof
983
+ /// submission. That fee is computed as follows:
984
+ /// `treasuryFee = depositedAmount / depositTreasuryFeeDivisor`
985
+ /// For example, if the treasury fee needs to be 2% of each deposit,
986
+ /// the `depositTreasuryFeeDivisor` should be set to `50`
987
+ /// because `1/50 = 0.02 = 2%`
988
+ /// @param depositTxMaxFee New value of the deposit tx max fee in satoshis.
989
+ /// It is the maximum amount of BTC transaction fee that can
990
+ /// be incurred by each swept deposit being part of the given sweep
991
+ /// transaction. If the maximum BTC transaction fee is exceeded,
992
+ /// such transaction is considered a fraud
993
+ /// @dev Requirements:
994
+ /// - Deposit dust threshold must be greater than zero
995
+ /// - Deposit treasury fee divisor must be greater than zero
996
+ /// - Deposit transaction max fee must be greater than zero
997
+ function updateDepositParameters(
998
+ uint64 depositDustThreshold,
999
+ uint64 depositTreasuryFeeDivisor,
1000
+ uint64 depositTxMaxFee
1001
+ ) external onlyGovernance {
1002
+ self.updateDepositParameters(
1003
+ depositDustThreshold,
1004
+ depositTreasuryFeeDivisor,
1005
+ depositTxMaxFee
1006
+ );
1007
+ }
1008
+
1009
+ /// @notice Updates parameters of redemptions.
1010
+ /// @param redemptionDustThreshold New value of the redemption dust
1011
+ /// threshold in satoshis. It is the minimal amount that can be
1012
+ /// requested for redemption. Value of this parameter must take into
1013
+ /// account the value of `redemptionTreasuryFeeDivisor` and
1014
+ /// `redemptionTxMaxFee` parameters in order to make requests that
1015
+ /// can incur the treasury and transaction fee and still satisfy the
1016
+ /// redeemer.
1017
+ /// @param redemptionTreasuryFeeDivisor New value of the redemption
1018
+ /// treasury fee divisor. It is the divisor used to compute the
1019
+ /// treasury fee taken from each redemption request and transferred
1020
+ /// to the treasury upon successful request finalization. That fee is
1021
+ /// computed as follows:
1022
+ /// `treasuryFee = requestedAmount / redemptionTreasuryFeeDivisor`
1023
+ /// For example, if the treasury fee needs to be 2% of each
1024
+ /// redemption request, the `redemptionTreasuryFeeDivisor` should
1025
+ /// be set to `50` because `1/50 = 0.02 = 2%`.
1026
+ /// @param redemptionTxMaxFee New value of the redemption transaction max
1027
+ /// fee in satoshis. It is the maximum amount of BTC transaction fee
1028
+ /// that can be incurred by each redemption request being part of the
1029
+ /// given redemption transaction. If the maximum BTC transaction fee
1030
+ /// is exceeded, such transaction is considered a fraud.
1031
+ /// This is a per-redemption output max fee for the redemption
1032
+ /// transaction.
1033
+ /// @param redemptionTimeout New value of the redemption timeout in seconds.
1034
+ /// It is the time after which the redemption request can be reported
1035
+ /// as timed out. It is counted from the moment when the redemption
1036
+ /// request was created via `requestRedemption` call. Reported timed
1037
+ /// out requests are cancelled and locked TBTC is returned to the
1038
+ /// redeemer in full amount.
1039
+ /// @param redemptionTimeoutSlashingAmount New value of the redemption
1040
+ /// timeout slashing amount in T, it is the amount slashed from each
1041
+ /// wallet member for redemption timeout
1042
+ /// @param redemptionTimeoutNotifierRewardMultiplier New value of the
1043
+ /// redemption timeout notifier reward multiplier as percentage,
1044
+ /// it determines the percentage of the notifier reward from the
1045
+ /// staking contact the notifier of a redemption timeout receives.
1046
+ /// The value must be in the range [0, 100]
1047
+ /// @dev Requirements:
1048
+ /// - Redemption dust threshold must be greater than zero
1049
+ /// - Redemption treasury fee divisor must be greater than zero
1050
+ /// - Redemption transaction max fee must be greater than zero
1051
+ /// - Redemption timeout must be greater than zero
1052
+ /// - Redemption timeout notifier reward multiplier must be in the
1053
+ /// range [0, 100]
1054
+ function updateRedemptionParameters(
1055
+ uint64 redemptionDustThreshold,
1056
+ uint64 redemptionTreasuryFeeDivisor,
1057
+ uint64 redemptionTxMaxFee,
1058
+ uint256 redemptionTimeout,
1059
+ uint96 redemptionTimeoutSlashingAmount,
1060
+ uint256 redemptionTimeoutNotifierRewardMultiplier
1061
+ ) external onlyGovernance {
1062
+ self.updateRedemptionParameters(
1063
+ redemptionDustThreshold,
1064
+ redemptionTreasuryFeeDivisor,
1065
+ redemptionTxMaxFee,
1066
+ redemptionTimeout,
1067
+ redemptionTimeoutSlashingAmount,
1068
+ redemptionTimeoutNotifierRewardMultiplier
1069
+ );
1070
+ }
1071
+
1072
+ /// @notice Updates parameters of moving funds.
1073
+ /// @param movingFundsTxMaxTotalFee New value of the moving funds transaction
1074
+ /// max total fee in satoshis. It is the maximum amount of the total
1075
+ /// BTC transaction fee that is acceptable in a single moving funds
1076
+ /// transaction. This is a _total_ max fee for the entire moving
1077
+ /// funds transaction.
1078
+ /// @param movingFundsDustThreshold New value of the moving funds dust
1079
+ /// threshold. It is the minimal satoshi amount that makes sense to
1080
+ // be transferred during the moving funds process. Moving funds
1081
+ // wallets having their BTC balance below that value can begin
1082
+ // closing immediately as transferring such a low value may not be
1083
+ // possible due to BTC network fees.
1084
+ /// @param movingFundsTimeout New value of the moving funds timeout in
1085
+ /// seconds. It is the time after which the moving funds process can
1086
+ /// be reported as timed out. It is counted from the moment when the
1087
+ /// wallet was requested to move their funds and switched to the
1088
+ /// MovingFunds state.
1089
+ /// @param movingFundsTimeoutSlashingAmount New value of the moving funds
1090
+ /// timeout slashing amount in T, it is the amount slashed from each
1091
+ /// wallet member for moving funds timeout
1092
+ /// @param movingFundsTimeoutNotifierRewardMultiplier New value of the
1093
+ /// moving funds timeout notifier reward multiplier as percentage,
1094
+ /// it determines the percentage of the notifier reward from the
1095
+ /// staking contact the notifier of a moving funds timeout receives.
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]
1115
+ /// @dev Requirements:
1116
+ /// - Moving funds transaction max total fee must be greater than zero
1117
+ /// - Moving funds dust threshold must be greater than zero
1118
+ /// - Moving funds timeout must be greater than zero
1119
+ /// - Moving funds timeout notifier reward multiplier must be in the
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]
1125
+ function updateMovingFundsParameters(
1126
+ uint64 movingFundsTxMaxTotalFee,
1127
+ uint64 movingFundsDustThreshold,
1128
+ uint32 movingFundsTimeout,
1129
+ uint96 movingFundsTimeoutSlashingAmount,
1130
+ uint256 movingFundsTimeoutNotifierRewardMultiplier,
1131
+ uint64 movedFundsSweepTxMaxTotalFee,
1132
+ uint32 movedFundsSweepTimeout,
1133
+ uint96 movedFundsSweepTimeoutSlashingAmount,
1134
+ uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
1135
+ ) external onlyGovernance {
1136
+ self.updateMovingFundsParameters(
1137
+ movingFundsTxMaxTotalFee,
1138
+ movingFundsDustThreshold,
1139
+ movingFundsTimeout,
1140
+ movingFundsTimeoutSlashingAmount,
1141
+ movingFundsTimeoutNotifierRewardMultiplier,
1142
+ movedFundsSweepTxMaxTotalFee,
1143
+ movedFundsSweepTimeout,
1144
+ movedFundsSweepTimeoutSlashingAmount,
1145
+ movedFundsSweepTimeoutNotifierRewardMultiplier
1146
+ );
1147
+ }
1148
+
1149
+ /// @notice Updates parameters of wallets.
1150
+ /// @param walletCreationPeriod New value of the wallet creation period in
1151
+ /// seconds, determines how frequently a new wallet creation can be
1152
+ /// requested
1153
+ /// @param walletCreationMinBtcBalance New value of the wallet minimum BTC
1154
+ /// balance in satoshi, used to decide about wallet creation
1155
+ /// @param walletCreationMaxBtcBalance New value of the wallet maximum BTC
1156
+ /// balance in satoshi, used to decide about wallet creation
1157
+ /// @param walletClosureMinBtcBalance New value of the wallet minimum BTC
1158
+ /// balance in satoshi, used to decide about wallet closure
1159
+ /// @param walletMaxAge New value of the wallet maximum age in seconds,
1160
+ /// indicates the maximum age of a wallet in seconds, after which
1161
+ /// the wallet moving funds process can be requested
1162
+ /// @param walletMaxBtcTransfer New value of the wallet maximum BTC transfer
1163
+ /// in satoshi, determines the maximum amount that can be transferred
1164
+ // to a single target wallet during the moving funds process
1165
+ /// @param walletClosingPeriod New value of the wallet closing period in
1166
+ /// seconds, determines the length of the wallet closing period,
1167
+ // i.e. the period when the wallet remains in the Closing state
1168
+ // and can be subject of deposit fraud challenges
1169
+ /// @dev Requirements:
1170
+ /// - Wallet minimum BTC balance must be greater than zero
1171
+ /// - Wallet maximum BTC balance must be greater than the wallet
1172
+ /// minimum BTC balance
1173
+ /// - Wallet maximum BTC transfer must be greater than zero
1174
+ /// - Wallet closing period must be greater than zero
1175
+ function updateWalletParameters(
1176
+ uint32 walletCreationPeriod,
1177
+ uint64 walletCreationMinBtcBalance,
1178
+ uint64 walletCreationMaxBtcBalance,
1179
+ uint64 walletClosureMinBtcBalance,
1180
+ uint32 walletMaxAge,
1181
+ uint64 walletMaxBtcTransfer,
1182
+ uint32 walletClosingPeriod
1183
+ ) external onlyGovernance {
1184
+ self.updateWalletParameters(
1185
+ walletCreationPeriod,
1186
+ walletCreationMinBtcBalance,
1187
+ walletCreationMaxBtcBalance,
1188
+ walletClosureMinBtcBalance,
1189
+ walletMaxAge,
1190
+ walletMaxBtcTransfer,
1191
+ walletClosingPeriod
1192
+ );
1193
+ }
1194
+
1195
+ /// @notice Updates parameters related to frauds.
1196
+ /// @param fraudChallengeDepositAmount New value of the fraud challenge
1197
+ /// deposit amount in wei, it is the amount of ETH the party
1198
+ /// challenging the wallet for fraud needs to deposit
1199
+ /// @param fraudChallengeDefeatTimeout New value of the challenge defeat
1200
+ /// timeout in seconds, it is the amount of time the wallet has to
1201
+ /// defeat a fraud challenge. The value must be greater than zero
1202
+ /// @param fraudSlashingAmount New value of the fraud slashing amount in T,
1203
+ /// it is the amount slashed from each wallet member for committing
1204
+ /// a fraud
1205
+ /// @param fraudNotifierRewardMultiplier New value of the fraud notifier
1206
+ /// reward multiplier as percentage, it determines the percentage of
1207
+ /// the notifier reward from the staking contact the notifier of
1208
+ /// a fraud receives. The value must be in the range [0, 100]
1209
+ /// @dev Requirements:
1210
+ /// - Fraud challenge defeat timeout must be greater than 0
1211
+ /// - Fraud notifier reward multiplier must be in the range [0, 100]
1212
+ function updateFraudParameters(
1213
+ uint256 fraudChallengeDepositAmount,
1214
+ uint256 fraudChallengeDefeatTimeout,
1215
+ uint96 fraudSlashingAmount,
1216
+ uint256 fraudNotifierRewardMultiplier
1217
+ ) external onlyGovernance {
1218
+ self.updateFraudParameters(
1219
+ fraudChallengeDepositAmount,
1220
+ fraudChallengeDefeatTimeout,
1221
+ fraudSlashingAmount,
1222
+ fraudNotifierRewardMultiplier
1223
+ );
1224
+ }
1225
+
1226
+ /// @notice Collection of all revealed deposits indexed by
1227
+ /// keccak256(fundingTxHash | fundingOutputIndex).
1228
+ /// The fundingTxHash is bytes32 (ordered as in Bitcoin internally)
1229
+ /// and fundingOutputIndex an uint32. This mapping may contain valid
1230
+ /// and invalid deposits and the wallet is responsible for
1231
+ /// validating them before attempting to execute a sweep.
1232
+ function deposits(uint256 depositKey)
1233
+ external
1234
+ view
1235
+ returns (Deposit.DepositRequest memory)
1236
+ {
1237
+ return self.deposits[depositKey];
1238
+ }
1239
+
1240
+ /// @notice Collection of all pending redemption requests indexed by
1241
+ /// redemption key built as
1242
+ /// keccak256(walletPubKeyHash | redeemerOutputScript). The
1243
+ /// walletPubKeyHash is the 20-byte wallet's public key hash
1244
+ /// (computed using Bitcoin HASH160 over the compressed ECDSA
1245
+ /// public key) and redeemerOutputScript is a Bitcoin script
1246
+ /// (P2PKH, P2WPKH, P2SH or P2WSH) that will be used to lock
1247
+ /// redeemed BTC as requested by the redeemer. Requests are added
1248
+ /// to this mapping by the `requestRedemption` method (duplicates
1249
+ /// not allowed) and are removed by one of the following methods:
1250
+ /// - `submitRedemptionProof` in case the request was handled
1251
+ /// successfully
1252
+ /// - `notifyRedemptionTimeout` in case the request was reported
1253
+ /// to be timed out
1254
+ function pendingRedemptions(uint256 redemptionKey)
1255
+ external
1256
+ view
1257
+ returns (Redemption.RedemptionRequest memory)
1258
+ {
1259
+ return self.pendingRedemptions[redemptionKey];
1260
+ }
1261
+
1262
+ /// @notice Collection of all timed out redemptions requests indexed by
1263
+ /// redemption key built as
1264
+ /// keccak256(walletPubKeyHash | redeemerOutputScript). The
1265
+ /// walletPubKeyHash is the 20-byte wallet's public key hash
1266
+ /// (computed using Bitcoin HASH160 over the compressed ECDSA
1267
+ /// public key) and redeemerOutputScript is the Bitcoin script
1268
+ /// (P2PKH, P2WPKH, P2SH or P2WSH) that is involved in the timed
1269
+ /// out request. Timed out requests are stored in this mapping to
1270
+ /// avoid slashing the wallets multiple times for the same timeout.
1271
+ /// Only one method can add to this mapping:
1272
+ /// - `notifyRedemptionTimeout` which puts the redemption key
1273
+ /// to this mapping basing on a timed out request stored
1274
+ /// previously in `pendingRedemptions` mapping.
1275
+ function timedOutRedemptions(uint256 redemptionKey)
1276
+ external
1277
+ view
1278
+ returns (Redemption.RedemptionRequest memory)
1279
+ {
1280
+ return self.timedOutRedemptions[redemptionKey];
1281
+ }
1282
+
1283
+ /// @notice Collection of main UTXOs that are honestly spent indexed by
1284
+ /// keccak256(fundingTxHash | fundingOutputIndex). The fundingTxHash
1285
+ /// is bytes32 (ordered as in Bitcoin internally) and
1286
+ /// fundingOutputIndex an uint32. A main UTXO is considered honestly
1287
+ /// spent if it was used as an input of a transaction that have been
1288
+ /// proven in the Bridge.
1289
+ function spentMainUTXOs(uint256 utxoKey) external view returns (bool) {
1290
+ return self.spentMainUTXOs[utxoKey];
1291
+ }
1292
+
1293
+ /// @notice Gets details about a registered wallet.
1294
+ /// @param walletPubKeyHash The 20-byte wallet public key hash (computed
1295
+ /// using Bitcoin HASH160 over the compressed ECDSA public key)
1296
+ /// @return Wallet details.
1297
+ function wallets(bytes20 walletPubKeyHash)
1298
+ external
1299
+ view
1300
+ returns (Wallets.Wallet memory)
1301
+ {
1302
+ return self.registeredWallets[walletPubKeyHash];
1303
+ }
1304
+
1305
+ /// @notice Gets the public key hash of the active wallet.
1306
+ /// @return The 20-byte public key hash (computed using Bitcoin HASH160
1307
+ /// over the compressed ECDSA public key) of the active wallet.
1308
+ /// Returns bytes20(0) if there is no active wallet at the moment.
1309
+ function activeWalletPubKeyHash() external view returns (bytes20) {
1310
+ return self.activeWalletPubKeyHash;
1311
+ }
1312
+
1313
+ /// @notice Gets the live wallets count.
1314
+ /// @return The current count of wallets being in the Live state.
1315
+ function liveWalletsCount() external view returns (uint32) {
1316
+ return self.liveWalletsCount;
1317
+ }
1318
+
1319
+ /// @notice Returns the fraud challenge identified by the given key built
1320
+ /// as keccak256(walletPublicKey|sighash).
1321
+ function fraudChallenges(uint256 challengeKey)
1322
+ external
1323
+ view
1324
+ returns (Fraud.FraudChallenge memory)
1325
+ {
1326
+ return self.fraudChallenges[challengeKey];
1327
+ }
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
+
1346
+ /// @notice Indicates if the vault with the given address is trusted or not.
1347
+ /// Depositors can route their revealed deposits only to trusted
1348
+ /// vaults and have trusted vaults notified about new deposits as
1349
+ /// soon as these deposits get swept. Vaults not trusted by the
1350
+ /// Bridge can still be used by Bank balance owners on their own
1351
+ /// responsibility - anyone can approve their Bank balance to any
1352
+ /// address.
1353
+ function isVaultTrusted(address vault) external view returns (bool) {
1354
+ return self.isVaultTrusted[vault];
1355
+ }
1356
+
1357
+ /// @notice Returns the current values of Bridge deposit parameters.
1358
+ /// @return depositDustThreshold The minimal amount that can be requested
1359
+ /// to deposit. Value of this parameter must take into account the
1360
+ /// value of `depositTreasuryFeeDivisor` and `depositTxMaxFee`
1361
+ /// parameters in order to make requests that can incur the
1362
+ /// treasury and transaction fee and still satisfy the depositor.
1363
+ /// @return depositTreasuryFeeDivisor Divisor used to compute the treasury
1364
+ /// fee taken from each deposit and transferred to the treasury upon
1365
+ /// sweep proof submission. That fee is computed as follows:
1366
+ /// `treasuryFee = depositedAmount / depositTreasuryFeeDivisor`
1367
+ /// For example, if the treasury fee needs to be 2% of each deposit,
1368
+ /// the `depositTreasuryFeeDivisor` should be set to `50`
1369
+ /// because `1/50 = 0.02 = 2%`.
1370
+ /// @return depositTxMaxFee Maximum amount of BTC transaction fee that can
1371
+ /// be incurred by each swept deposit being part of the given sweep
1372
+ /// transaction. If the maximum BTC transaction fee is exceeded,
1373
+ /// such transaction is considered a fraud.
1374
+ function depositParameters()
1375
+ external
1376
+ view
1377
+ returns (
1378
+ uint64 depositDustThreshold,
1379
+ uint64 depositTreasuryFeeDivisor,
1380
+ uint64 depositTxMaxFee
1381
+ )
1382
+ {
1383
+ depositDustThreshold = self.depositDustThreshold;
1384
+ depositTreasuryFeeDivisor = self.depositTreasuryFeeDivisor;
1385
+ depositTxMaxFee = self.depositTxMaxFee;
1386
+ }
1387
+
1388
+ /// @notice Returns the current values of Bridge redemption parameters.
1389
+ /// @return redemptionDustThreshold The minimal amount that can be requested
1390
+ /// for redemption. Value of this parameter must take into account
1391
+ /// the value of `redemptionTreasuryFeeDivisor` and `redemptionTxMaxFee`
1392
+ /// parameters in order to make requests that can incur the
1393
+ /// treasury and transaction fee and still satisfy the redeemer.
1394
+ /// @return redemptionTreasuryFeeDivisor Divisor used to compute the treasury
1395
+ /// fee taken from each redemption request and transferred to the
1396
+ /// treasury upon successful request finalization. That fee is
1397
+ /// computed as follows:
1398
+ /// `treasuryFee = requestedAmount / redemptionTreasuryFeeDivisor`
1399
+ /// For example, if the treasury fee needs to be 2% of each
1400
+ /// redemption request, the `redemptionTreasuryFeeDivisor` should
1401
+ /// be set to `50` because `1/50 = 0.02 = 2%`.
1402
+ /// @return redemptionTxMaxFee Maximum amount of BTC transaction fee that
1403
+ /// can be incurred by each redemption request being part of the
1404
+ /// given redemption transaction. If the maximum BTC transaction
1405
+ /// fee is exceeded, such transaction is considered a fraud.
1406
+ /// This is a per-redemption output max fee for the redemption
1407
+ /// transaction.
1408
+ /// @return redemptionTimeout Time after which the redemption request can be
1409
+ /// reported as timed out. It is counted from the moment when the
1410
+ /// redemption request was created via `requestRedemption` call.
1411
+ /// Reported timed out requests are cancelled and locked TBTC is
1412
+ /// returned to the redeemer in full amount.
1413
+ /// @return redemptionTimeoutSlashingAmount The amount of stake slashed
1414
+ /// from each member of a wallet for a redemption timeout.
1415
+ /// @return redemptionTimeoutNotifierRewardMultiplier The percentage of the
1416
+ /// notifier reward from the staking contract the notifier of a
1417
+ /// redemption timeout receives. The value is in the range [0, 100].
1418
+ function redemptionParameters()
1419
+ external
1420
+ view
1421
+ returns (
1422
+ uint64 redemptionDustThreshold,
1423
+ uint64 redemptionTreasuryFeeDivisor,
1424
+ uint64 redemptionTxMaxFee,
1425
+ uint256 redemptionTimeout,
1426
+ uint96 redemptionTimeoutSlashingAmount,
1427
+ uint256 redemptionTimeoutNotifierRewardMultiplier
1428
+ )
1429
+ {
1430
+ redemptionDustThreshold = self.redemptionDustThreshold;
1431
+ redemptionTreasuryFeeDivisor = self.redemptionTreasuryFeeDivisor;
1432
+ redemptionTxMaxFee = self.redemptionTxMaxFee;
1433
+ redemptionTimeout = self.redemptionTimeout;
1434
+ redemptionTimeoutSlashingAmount = self.redemptionTimeoutSlashingAmount;
1435
+ redemptionTimeoutNotifierRewardMultiplier = self
1436
+ .redemptionTimeoutNotifierRewardMultiplier;
1437
+ }
1438
+
1439
+ /// @notice Returns the current values of Bridge moving funds between
1440
+ /// wallets parameters.
1441
+ /// @return movingFundsTxMaxTotalFee Maximum amount of the total BTC
1442
+ /// transaction fee that is acceptable in a single moving funds
1443
+ /// transaction. This is a _total_ max fee for the entire moving
1444
+ /// funds transaction.
1445
+ /// @return movingFundsDustThreshold The minimal satoshi amount that makes
1446
+ /// sense to be transferred during the moving funds process. Moving
1447
+ /// funds wallets having their BTC balance below that value can
1448
+ /// begin closing immediately as transferring such a low value may
1449
+ /// not be possible due to BTC network fees.
1450
+ /// @return movingFundsTimeout Time after which the moving funds process
1451
+ /// can be reported as timed out. It is counted from the moment
1452
+ /// when the wallet was requested to move their funds and switched
1453
+ /// to the MovingFunds state. Value in seconds.
1454
+ /// @return movingFundsTimeoutSlashingAmount The amount of stake slashed
1455
+ /// from each member of a wallet for a moving funds timeout.
1456
+ /// @return movingFundsTimeoutNotifierRewardMultiplier The percentage of the
1457
+ /// notifier reward from the staking contract the notifier of a
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].
1473
+ function movingFundsParameters()
1474
+ external
1475
+ view
1476
+ returns (
1477
+ uint64 movingFundsTxMaxTotalFee,
1478
+ uint64 movingFundsDustThreshold,
1479
+ uint32 movingFundsTimeout,
1480
+ uint96 movingFundsTimeoutSlashingAmount,
1481
+ uint256 movingFundsTimeoutNotifierRewardMultiplier,
1482
+ uint64 movedFundsSweepTxMaxTotalFee,
1483
+ uint32 movedFundsSweepTimeout,
1484
+ uint96 movedFundsSweepTimeoutSlashingAmount,
1485
+ uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
1486
+ )
1487
+ {
1488
+ movingFundsTxMaxTotalFee = self.movingFundsTxMaxTotalFee;
1489
+ movingFundsDustThreshold = self.movingFundsDustThreshold;
1490
+ movingFundsTimeout = self.movingFundsTimeout;
1491
+ movingFundsTimeoutSlashingAmount = self
1492
+ .movingFundsTimeoutSlashingAmount;
1493
+ movingFundsTimeoutNotifierRewardMultiplier = self
1494
+ .movingFundsTimeoutNotifierRewardMultiplier;
1495
+ movedFundsSweepTxMaxTotalFee = self.movedFundsSweepTxMaxTotalFee;
1496
+ movedFundsSweepTimeout = self.movedFundsSweepTimeout;
1497
+ movedFundsSweepTimeoutSlashingAmount = self
1498
+ .movedFundsSweepTimeoutSlashingAmount;
1499
+ movedFundsSweepTimeoutNotifierRewardMultiplier = self
1500
+ .movedFundsSweepTimeoutNotifierRewardMultiplier;
1501
+ }
1502
+
1503
+ /// @return walletCreationPeriod Determines how frequently a new wallet
1504
+ /// creation can be requested. Value in seconds.
1505
+ /// @return walletCreationMinBtcBalance The minimum BTC threshold in satoshi
1506
+ /// that is used to decide about wallet creation.
1507
+ /// @return walletCreationMaxBtcBalance The maximum BTC threshold in satoshi
1508
+ /// that is used to decide about wallet creation.
1509
+ /// @return walletClosureMinBtcBalance The minimum BTC threshold in satoshi
1510
+ /// that is used to decide about wallet closure.
1511
+ /// @return walletMaxAge The maximum age of a wallet in seconds, after which
1512
+ /// the wallet moving funds process can be requested.
1513
+ /// @return walletMaxBtcTransfer The maximum BTC amount in satoshi than
1514
+ /// can be transferred to a single target wallet during the moving
1515
+ /// funds process.
1516
+ /// @return walletClosingPeriod Determines the length of the wallet closing
1517
+ /// period, i.e. the period when the wallet remains in the Closing
1518
+ /// state and can be subject of deposit fraud challenges. Value
1519
+ /// in seconds.
1520
+ function walletParameters()
1521
+ external
1522
+ view
1523
+ returns (
1524
+ uint32 walletCreationPeriod,
1525
+ uint64 walletCreationMinBtcBalance,
1526
+ uint64 walletCreationMaxBtcBalance,
1527
+ uint64 walletClosureMinBtcBalance,
1528
+ uint32 walletMaxAge,
1529
+ uint64 walletMaxBtcTransfer,
1530
+ uint32 walletClosingPeriod
1531
+ )
1532
+ {
1533
+ walletCreationPeriod = self.walletCreationPeriod;
1534
+ walletCreationMinBtcBalance = self.walletCreationMinBtcBalance;
1535
+ walletCreationMaxBtcBalance = self.walletCreationMaxBtcBalance;
1536
+ walletClosureMinBtcBalance = self.walletClosureMinBtcBalance;
1537
+ walletMaxAge = self.walletMaxAge;
1538
+ walletMaxBtcTransfer = self.walletMaxBtcTransfer;
1539
+ walletClosingPeriod = self.walletClosingPeriod;
1540
+ }
1541
+
1542
+ /// @notice Returns the current values of Bridge fraud parameters.
1543
+ /// @return fraudChallengeDepositAmount The amount of ETH in wei the party
1544
+ /// challenging the wallet for fraud needs to deposit.
1545
+ /// @return fraudChallengeDefeatTimeout The amount of time the wallet has to
1546
+ /// defeat a fraud challenge.
1547
+ /// @return fraudSlashingAmount The amount slashed from each wallet member
1548
+ /// for committing a fraud.
1549
+ /// @return fraudNotifierRewardMultiplier The percentage of the notifier
1550
+ /// reward from the staking contract the notifier of a fraud
1551
+ /// receives. The value is in the range [0, 100].
1552
+ function fraudParameters()
1553
+ external
1554
+ view
1555
+ returns (
1556
+ uint256 fraudChallengeDepositAmount,
1557
+ uint256 fraudChallengeDefeatTimeout,
1558
+ uint96 fraudSlashingAmount,
1559
+ uint256 fraudNotifierRewardMultiplier
1560
+ )
1561
+ {
1562
+ fraudChallengeDepositAmount = self.fraudChallengeDepositAmount;
1563
+ fraudChallengeDefeatTimeout = self.fraudChallengeDefeatTimeout;
1564
+ fraudSlashingAmount = self.fraudSlashingAmount;
1565
+ fraudNotifierRewardMultiplier = self.fraudNotifierRewardMultiplier;
1566
+ }
1567
+
1568
+ /// @notice Returns the addresses of contracts Bridge is interacting with.
1569
+ /// @return bank Address of the Bank the Bridge belongs to.
1570
+ /// @return relay Address of the Bitcoin relay providing the current Bitcoin
1571
+ /// network difficulty.
1572
+ /// @return ecdsaWalletRegistry Address of the ECDSA Wallet Registry.
1573
+ function contractReferences()
1574
+ external
1575
+ view
1576
+ returns (
1577
+ Bank bank,
1578
+ IRelay relay,
1579
+ EcdsaWalletRegistry ecdsaWalletRegistry
1580
+ )
1581
+ {
1582
+ bank = self.bank;
1583
+ relay = self.relay;
1584
+ ecdsaWalletRegistry = self.ecdsaWalletRegistry;
1585
+ }
1586
+
1587
+ /// @notice Address where the deposit treasury fees will be sent to.
1588
+ /// Treasury takes part in the operators rewarding process.
1589
+ function treasury() external view returns (address) {
1590
+ return self.treasury;
1591
+ }
1592
+
1593
+ /// @notice The number of confirmations on the Bitcoin chain required to
1594
+ /// successfully evaluate an SPV proof.
1595
+ function txProofDifficultyFactor() external view returns (uint256) {
1596
+ return self.txProofDifficultyFactor;
1597
+ }
318
1598
  }