@keep-network/tbtc-v2 0.1.1-dev.7 → 0.1.1-dev.70

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