@keep-network/tbtc-v2 0.1.1-dev.8 → 0.1.1-dev.82

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