@keep-network/tbtc-v2 0.1.1-dev.42 → 0.1.1-dev.45
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.
- package/artifacts/Bank.json +742 -0
- package/artifacts/Bridge.json +2914 -0
- package/artifacts/Deposit.json +117 -0
- package/artifacts/EcdsaDkgValidator.json +532 -0
- package/artifacts/EcdsaInactivity.json +156 -0
- package/artifacts/Fraud.json +153 -0
- package/artifacts/KeepRegistry.json +99 -0
- package/artifacts/KeepStake.json +286 -0
- package/artifacts/KeepToken.json +711 -0
- package/artifacts/KeepTokenStaking.json +483 -0
- package/artifacts/MovingFunds.json +137 -0
- package/artifacts/NuCypherStakingEscrow.json +256 -0
- package/artifacts/NuCypherToken.json +711 -0
- package/artifacts/RandomBeaconStub.json +141 -0
- package/artifacts/Redemption.json +161 -0
- package/artifacts/ReimbursementPool.json +509 -0
- package/artifacts/Relay.json +123 -0
- package/artifacts/SortitionPool.json +944 -0
- package/artifacts/Sweep.json +76 -0
- package/artifacts/T.json +1148 -0
- package/artifacts/TBTC.json +21 -21
- package/artifacts/TBTCToken.json +21 -21
- package/artifacts/TokenStaking.json +2288 -0
- package/artifacts/TokenholderGovernor.json +1795 -0
- package/artifacts/TokenholderTimelock.json +1058 -0
- package/artifacts/VendingMachine.json +24 -24
- package/artifacts/VendingMachineKeep.json +400 -0
- package/artifacts/VendingMachineNuCypher.json +400 -0
- package/artifacts/WalletRegistry.json +2709 -0
- package/artifacts/WalletRegistryGovernance.json +2364 -0
- package/artifacts/Wallets.json +186 -0
- package/artifacts/solcInputs/{002940e9cc8128f6629e90620c66cba5.json → 58ca6018672440f1c9c800806e096f9c.json} +22 -22
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
- package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +2 -2
- package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
- package/build/contracts/bridge/Bridge.sol/Bridge.json +489 -173
- package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
- package/build/contracts/bridge/BridgeState.sol/BridgeState.json +114 -2
- package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +1 -1
- package/build/contracts/bridge/Deposit.sol/Deposit.json +2 -2
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +2 -2
- package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
- package/build/contracts/bridge/Fraud.sol/Fraud.json +5 -57
- package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
- package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
- package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +40 -2
- package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
- package/build/contracts/bridge/{Redeem.sol → Redemption.sol}/OutboundTx.json +3 -3
- package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
- package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
- package/build/contracts/bridge/Sweep.sol/Sweep.dbg.json +1 -1
- package/build/contracts/bridge/Sweep.sol/Sweep.json +2 -2
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
- package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
- package/build/contracts/bridge/Wallets.sol/Wallets.json +21 -2
- package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
- package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
- package/contracts/bridge/BitcoinTx.sol +19 -26
- package/contracts/bridge/Bridge.sol +736 -489
- package/contracts/bridge/BridgeState.sol +271 -24
- package/contracts/bridge/Deposit.sol +24 -2
- package/contracts/bridge/EcdsaLib.sol +15 -0
- package/contracts/bridge/Fraud.sol +64 -31
- package/contracts/bridge/MovingFunds.sol +194 -6
- package/contracts/bridge/{Redeem.sol → Redemption.sol} +20 -18
- package/contracts/bridge/Sweep.sol +13 -8
- package/contracts/bridge/Wallets.sol +53 -35
- package/deploy/00_resolve_relay.ts +28 -0
- package/deploy/04_deploy_bank.ts +25 -0
- package/deploy/05_deploy_bridge.ts +60 -0
- package/deploy/06_bank_update_bridge.ts +19 -0
- package/deploy/07_transfer_ownership.ts +17 -0
- package/export.json +14797 -459
- package/package.json +2 -2
- package/build/contracts/bridge/Redeem.sol/OutboundTx.dbg.json +0 -4
- package/build/contracts/bridge/Redeem.sol/Redeem.dbg.json +0 -4
- package/build/contracts/bridge/Redeem.sol/Redeem.json +0 -92
|
@@ -17,16 +17,13 @@ pragma solidity ^0.8.9;
|
|
|
17
17
|
|
|
18
18
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
19
19
|
|
|
20
|
-
import {BTCUtils} from "@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol";
|
|
21
|
-
import {BytesLib} from "@keep-network/bitcoin-spv-sol/contracts/BytesLib.sol";
|
|
22
|
-
|
|
23
20
|
import {IWalletOwner as EcdsaWalletOwner} from "@keep-network/ecdsa/contracts/api/IWalletOwner.sol";
|
|
24
21
|
|
|
25
22
|
import "./IRelay.sol";
|
|
26
23
|
import "./BridgeState.sol";
|
|
27
24
|
import "./Deposit.sol";
|
|
28
25
|
import "./Sweep.sol";
|
|
29
|
-
import "./
|
|
26
|
+
import "./Redemption.sol";
|
|
30
27
|
import "./BitcoinTx.sol";
|
|
31
28
|
import "./EcdsaLib.sol";
|
|
32
29
|
import "./Wallets.sol";
|
|
@@ -53,72 +50,24 @@ import "../bank/Bank.sol";
|
|
|
53
50
|
/// the sweep operation is confirmed on the Bitcoin network, the ECDSA
|
|
54
51
|
/// wallet informs the Bridge about the sweep increasing appropriate
|
|
55
52
|
/// balances in the Bank.
|
|
56
|
-
/// @dev Bridge is an upgradeable component of the Bank.
|
|
53
|
+
/// @dev Bridge is an upgradeable component of the Bank. The order of
|
|
54
|
+
/// functionalities in this contract is: deposit, sweep, redemption,
|
|
55
|
+
/// moving funds, wallet lifecycle, frauds, parameters.
|
|
57
56
|
///
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// value updates.
|
|
57
|
+
/// TODO: Revisit all events and look which parameters should be indexed.
|
|
58
|
+
/// TODO: Align the convention around `param` and `dev` endings. They should
|
|
59
|
+
/// not have a punctuation mark.
|
|
62
60
|
contract Bridge is Ownable, EcdsaWalletOwner {
|
|
63
61
|
using BridgeState for BridgeState.Storage;
|
|
64
62
|
using Deposit for BridgeState.Storage;
|
|
65
63
|
using Sweep for BridgeState.Storage;
|
|
66
|
-
using
|
|
64
|
+
using Redemption for BridgeState.Storage;
|
|
67
65
|
using MovingFunds for BridgeState.Storage;
|
|
68
|
-
using Fraud for BridgeState.Storage;
|
|
69
66
|
using Wallets for BridgeState.Storage;
|
|
70
|
-
|
|
71
|
-
using BTCUtils for bytes;
|
|
72
|
-
using BTCUtils for uint256;
|
|
73
|
-
using BytesLib for bytes;
|
|
67
|
+
using Fraud for BridgeState.Storage;
|
|
74
68
|
|
|
75
69
|
BridgeState.Storage internal self;
|
|
76
70
|
|
|
77
|
-
event WalletParametersUpdated(
|
|
78
|
-
uint32 walletCreationPeriod,
|
|
79
|
-
uint64 walletMinBtcBalance,
|
|
80
|
-
uint64 walletMaxBtcBalance,
|
|
81
|
-
uint32 walletMaxAge
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
event NewWalletRequested();
|
|
85
|
-
|
|
86
|
-
event NewWalletRegistered(
|
|
87
|
-
bytes32 indexed ecdsaWalletID,
|
|
88
|
-
bytes20 indexed walletPubKeyHash
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
event WalletMovingFunds(
|
|
92
|
-
bytes32 indexed ecdsaWalletID,
|
|
93
|
-
bytes20 indexed walletPubKeyHash
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
event WalletClosed(
|
|
97
|
-
bytes32 indexed ecdsaWalletID,
|
|
98
|
-
bytes20 indexed walletPubKeyHash
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
event WalletTerminated(
|
|
102
|
-
bytes32 indexed ecdsaWalletID,
|
|
103
|
-
bytes20 indexed walletPubKeyHash
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
event VaultStatusUpdated(address indexed vault, bool isTrusted);
|
|
107
|
-
|
|
108
|
-
event FraudSlashingAmountUpdated(uint256 newFraudSlashingAmount);
|
|
109
|
-
|
|
110
|
-
event FraudNotifierRewardMultiplierUpdated(
|
|
111
|
-
uint256 newFraudNotifierRewardMultiplier
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
event FraudChallengeDefeatTimeoutUpdated(
|
|
115
|
-
uint256 newFraudChallengeDefeatTimeout
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
event FraudChallengeDepositAmountUpdated(
|
|
119
|
-
uint256 newFraudChallengeDepositAmount
|
|
120
|
-
);
|
|
121
|
-
|
|
122
71
|
event DepositRevealed(
|
|
123
72
|
bytes32 fundingTxHash,
|
|
124
73
|
uint32 fundingOutputIndex,
|
|
@@ -152,24 +101,94 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
152
101
|
bytes redeemerOutputScript
|
|
153
102
|
);
|
|
154
103
|
|
|
104
|
+
event WalletMovingFunds(
|
|
105
|
+
bytes32 indexed ecdsaWalletID,
|
|
106
|
+
bytes20 indexed walletPubKeyHash
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
event MovingFundsCommitmentSubmitted(
|
|
110
|
+
bytes20 walletPubKeyHash,
|
|
111
|
+
bytes20[] targetWallets,
|
|
112
|
+
address submitter
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
event MovingFundsCompleted(
|
|
116
|
+
bytes20 walletPubKeyHash,
|
|
117
|
+
bytes32 movingFundsTxHash
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
event MovingFundsTimedOut(bytes20 walletPubKeyHash);
|
|
121
|
+
|
|
122
|
+
event NewWalletRequested();
|
|
123
|
+
|
|
124
|
+
event NewWalletRegistered(
|
|
125
|
+
bytes32 indexed ecdsaWalletID,
|
|
126
|
+
bytes20 indexed walletPubKeyHash
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
event WalletClosing(
|
|
130
|
+
bytes32 indexed ecdsaWalletID,
|
|
131
|
+
bytes20 indexed walletPubKeyHash
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
event WalletClosed(
|
|
135
|
+
bytes32 indexed ecdsaWalletID,
|
|
136
|
+
bytes20 indexed walletPubKeyHash
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
event WalletTerminated(
|
|
140
|
+
bytes32 indexed ecdsaWalletID,
|
|
141
|
+
bytes20 indexed walletPubKeyHash
|
|
142
|
+
);
|
|
143
|
+
|
|
155
144
|
event FraudChallengeSubmitted(
|
|
156
|
-
bytes20
|
|
145
|
+
bytes20 walletPubKeyHash,
|
|
157
146
|
bytes32 sighash,
|
|
158
147
|
uint8 v,
|
|
159
148
|
bytes32 r,
|
|
160
149
|
bytes32 s
|
|
161
150
|
);
|
|
162
151
|
|
|
163
|
-
event FraudChallengeDefeated(bytes20
|
|
152
|
+
event FraudChallengeDefeated(bytes20 walletPubKeyHash, bytes32 sighash);
|
|
164
153
|
|
|
165
154
|
event FraudChallengeDefeatTimedOut(
|
|
166
|
-
bytes20
|
|
155
|
+
bytes20 walletPubKeyHash,
|
|
167
156
|
bytes32 sighash
|
|
168
157
|
);
|
|
169
158
|
|
|
170
|
-
event
|
|
171
|
-
|
|
172
|
-
|
|
159
|
+
event VaultStatusUpdated(address indexed vault, bool isTrusted);
|
|
160
|
+
|
|
161
|
+
event DepositParametersUpdated(
|
|
162
|
+
uint64 depositDustThreshold,
|
|
163
|
+
uint64 depositTreasuryFeeDivisor,
|
|
164
|
+
uint64 depositTxMaxFee
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
event RedemptionParametersUpdated(
|
|
168
|
+
uint64 redemptionDustThreshold,
|
|
169
|
+
uint64 redemptionTreasuryFeeDivisor,
|
|
170
|
+
uint64 redemptionTxMaxFee,
|
|
171
|
+
uint256 redemptionTimeout
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
event MovingFundsParametersUpdated(
|
|
175
|
+
uint64 movingFundsTxMaxTotalFee,
|
|
176
|
+
uint32 movingFundsTimeout
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
event WalletParametersUpdated(
|
|
180
|
+
uint32 walletCreationPeriod,
|
|
181
|
+
uint64 walletMinBtcBalance,
|
|
182
|
+
uint64 walletMaxBtcBalance,
|
|
183
|
+
uint32 walletMaxAge,
|
|
184
|
+
uint64 walletMaxBtcTransfer
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
event FraudParametersUpdated(
|
|
188
|
+
uint256 fraudSlashingAmount,
|
|
189
|
+
uint256 fraudNotifierRewardMultiplier,
|
|
190
|
+
uint256 fraudChallengeDefeatTimeout,
|
|
191
|
+
uint256 fraudChallengeDepositAmount
|
|
173
192
|
);
|
|
174
193
|
|
|
175
194
|
constructor(
|
|
@@ -205,6 +224,7 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
205
224
|
self.redemptionTxMaxFee = 10000; // 10000 satoshi
|
|
206
225
|
self.redemptionTimeout = 172800; // 48 hours
|
|
207
226
|
self.movingFundsTxMaxTotalFee = 10000; // 10000 satoshi
|
|
227
|
+
self.movingFundsTimeout = 7 days;
|
|
208
228
|
self.fraudSlashingAmount = 10000 * 1e18; // 10000 T
|
|
209
229
|
self.fraudNotifierRewardMultiplier = 100; // 100%
|
|
210
230
|
self.fraudChallengeDefeatTimeout = 7 days;
|
|
@@ -213,123 +233,7 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
213
233
|
self.walletMinBtcBalance = 1e8; // 1 BTC
|
|
214
234
|
self.walletMaxBtcBalance = 10e8; // 10 BTC
|
|
215
235
|
self.walletMaxAge = 26 weeks; // ~6 months
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
/// @notice Allows the Governance to mark the given vault address as trusted
|
|
219
|
-
/// or no longer trusted. Vaults are not trusted by default.
|
|
220
|
-
/// Trusted vault must meet the following criteria:
|
|
221
|
-
/// - `IVault.receiveBalanceIncrease` must have a known, low gas
|
|
222
|
-
/// cost.
|
|
223
|
-
/// - `IVault.receiveBalanceIncrease` must never revert.
|
|
224
|
-
/// @dev Without restricting reveal only to trusted vaults, malicious
|
|
225
|
-
/// vaults not meeting the criteria would be able to nuke sweep proof
|
|
226
|
-
/// transactions executed by ECDSA wallet with deposits routed to
|
|
227
|
-
/// them.
|
|
228
|
-
/// @param vault The address of the vault
|
|
229
|
-
/// @param isTrusted flag indicating whether the vault is trusted or not
|
|
230
|
-
/// @dev Can only be called by the Governance.
|
|
231
|
-
function setVaultStatus(address vault, bool isTrusted) external onlyOwner {
|
|
232
|
-
self.isVaultTrusted[vault] = isTrusted;
|
|
233
|
-
emit VaultStatusUpdated(vault, isTrusted);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/// @notice Requests creation of a new wallet. This function just
|
|
237
|
-
/// forms a request and the creation process is performed
|
|
238
|
-
/// asynchronously. Once a wallet is created, the ECDSA Wallet
|
|
239
|
-
/// Registry will notify this contract by calling the
|
|
240
|
-
/// `__ecdsaWalletCreatedCallback` function.
|
|
241
|
-
/// @param activeWalletMainUtxo Data of the active wallet's main UTXO, as
|
|
242
|
-
/// currently known on the Ethereum chain.
|
|
243
|
-
/// @dev Requirements:
|
|
244
|
-
/// - `activeWalletMainUtxo` components must point to the recent main
|
|
245
|
-
/// UTXO of the given active wallet, as currently known on the
|
|
246
|
-
/// Ethereum chain. If there is no active wallet at the moment, or
|
|
247
|
-
/// the active wallet has no main UTXO, this parameter can be
|
|
248
|
-
/// empty as it is ignored.
|
|
249
|
-
/// - Wallet creation must not be in progress
|
|
250
|
-
/// - If the active wallet is set, one of the following
|
|
251
|
-
/// conditions must be true:
|
|
252
|
-
/// - The active wallet BTC balance is above the minimum threshold
|
|
253
|
-
/// and the active wallet is old enough, i.e. the creation period
|
|
254
|
-
/// was elapsed since its creation time
|
|
255
|
-
/// - The active wallet BTC balance is above the maximum threshold
|
|
256
|
-
function requestNewWallet(BitcoinTx.UTXO calldata activeWalletMainUtxo)
|
|
257
|
-
external
|
|
258
|
-
{
|
|
259
|
-
self.requestNewWallet(activeWalletMainUtxo);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/// @notice A callback function that is called by the ECDSA Wallet Registry
|
|
263
|
-
/// once a new ECDSA wallet is created.
|
|
264
|
-
/// @param ecdsaWalletID Wallet's unique identifier.
|
|
265
|
-
/// @param publicKeyX Wallet's public key's X coordinate.
|
|
266
|
-
/// @param publicKeyY Wallet's public key's Y coordinate.
|
|
267
|
-
/// @dev Requirements:
|
|
268
|
-
/// - The only caller authorized to call this function is `registry`
|
|
269
|
-
/// - Given wallet data must not belong to an already registered wallet
|
|
270
|
-
function __ecdsaWalletCreatedCallback(
|
|
271
|
-
bytes32 ecdsaWalletID,
|
|
272
|
-
bytes32 publicKeyX,
|
|
273
|
-
bytes32 publicKeyY
|
|
274
|
-
) external override {
|
|
275
|
-
self.registerNewWallet(ecdsaWalletID, publicKeyX, publicKeyY);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/// @notice A callback function that is called by the ECDSA Wallet Registry
|
|
279
|
-
/// once a wallet heartbeat failure is detected.
|
|
280
|
-
/// @param publicKeyX Wallet's public key's X coordinate
|
|
281
|
-
/// @param publicKeyY Wallet's public key's Y coordinate
|
|
282
|
-
/// @dev Requirements:
|
|
283
|
-
/// - The only caller authorized to call this function is `registry`
|
|
284
|
-
/// - Wallet must be in Live state
|
|
285
|
-
function __ecdsaWalletHeartbeatFailedCallback(
|
|
286
|
-
bytes32,
|
|
287
|
-
bytes32 publicKeyX,
|
|
288
|
-
bytes32 publicKeyY
|
|
289
|
-
) external override {
|
|
290
|
-
self.notifyWalletHeartbeatFailed(publicKeyX, publicKeyY);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/// @notice Notifies that the wallet is either old enough or has too few
|
|
294
|
-
/// satoshis left and qualifies to be closed.
|
|
295
|
-
/// @param walletPubKeyHash 20-byte public key hash of the wallet
|
|
296
|
-
/// @param walletMainUtxo Data of the wallet's main UTXO, as currently
|
|
297
|
-
/// known on the Ethereum chain.
|
|
298
|
-
/// @dev Requirements:
|
|
299
|
-
/// - Wallet must not be set as the current active wallet
|
|
300
|
-
/// - Wallet must exceed the wallet maximum age OR the wallet BTC
|
|
301
|
-
/// balance must be lesser than the minimum threshold. If the latter
|
|
302
|
-
/// case is true, the `walletMainUtxo` components must point to the
|
|
303
|
-
/// recent main UTXO of the given wallet, as currently known on the
|
|
304
|
-
/// Ethereum chain. If the wallet has no main UTXO, this parameter
|
|
305
|
-
/// can be empty as it is ignored since the wallet balance is
|
|
306
|
-
/// assumed to be zero.
|
|
307
|
-
/// - Wallet must be in Live state
|
|
308
|
-
function notifyCloseableWallet(
|
|
309
|
-
bytes20 walletPubKeyHash,
|
|
310
|
-
BitcoinTx.UTXO calldata walletMainUtxo
|
|
311
|
-
) external {
|
|
312
|
-
self.notifyCloseableWallet(walletPubKeyHash, walletMainUtxo);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/// @notice Gets details about a registered wallet.
|
|
316
|
-
/// @param walletPubKeyHash The 20-byte wallet public key hash (computed
|
|
317
|
-
/// using Bitcoin HASH160 over the compressed ECDSA public key)
|
|
318
|
-
/// @return Wallet details.
|
|
319
|
-
function getWallet(bytes20 walletPubKeyHash)
|
|
320
|
-
external
|
|
321
|
-
view
|
|
322
|
-
returns (Wallets.Wallet memory)
|
|
323
|
-
{
|
|
324
|
-
return self.registeredWallets[walletPubKeyHash];
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/// @notice Gets the public key hash of the active wallet.
|
|
328
|
-
/// @return The 20-byte public key hash (computed using Bitcoin HASH160
|
|
329
|
-
/// over the compressed ECDSA public key) of the active wallet.
|
|
330
|
-
/// Returns bytes20(0) if there is no active wallet at the moment.
|
|
331
|
-
function getActiveWalletPubKeyHash() external view returns (bytes20) {
|
|
332
|
-
return self.activeWalletPubKeyHash;
|
|
236
|
+
self.walletMaxBtcTransfer = 10e8; // 10 BTC
|
|
333
237
|
}
|
|
334
238
|
|
|
335
239
|
/// @notice Used by the depositor to reveal information about their P2(W)SH
|
|
@@ -417,139 +321,23 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
417
321
|
self.submitSweepProof(sweepTx, sweepProof, mainUtxo);
|
|
418
322
|
}
|
|
419
323
|
|
|
420
|
-
/// @notice
|
|
421
|
-
/// wallet
|
|
422
|
-
///
|
|
423
|
-
///
|
|
424
|
-
///
|
|
425
|
-
///
|
|
426
|
-
///
|
|
427
|
-
///
|
|
428
|
-
///
|
|
429
|
-
///
|
|
430
|
-
///
|
|
431
|
-
///
|
|
432
|
-
///
|
|
433
|
-
///
|
|
434
|
-
///
|
|
435
|
-
|
|
436
|
-
///
|
|
437
|
-
/// @param sighash The hash that was used to produce the ECDSA signature
|
|
438
|
-
/// that is the subject of the fraud claim. This hash is constructed
|
|
439
|
-
/// by applying double SHA-256 over a serialized subset of the
|
|
440
|
-
/// transaction. The exact subset used as hash preimage depends on
|
|
441
|
-
/// the transaction input the signature is produced for. See BIP-143
|
|
442
|
-
/// for reference
|
|
443
|
-
/// @param signature Bitcoin signature in the R/S/V format
|
|
444
|
-
/// @dev Requirements:
|
|
445
|
-
/// - Wallet behind `walletPubKey` must be in `Live` or `MovingFunds`
|
|
446
|
-
/// state
|
|
447
|
-
/// - The challenger must send appropriate amount of ETH used as
|
|
448
|
-
/// fraud challenge deposit
|
|
449
|
-
/// - The signature (represented by r, s and v) must be generated by
|
|
450
|
-
/// the wallet behind `walletPubKey` during signing of `sighash`
|
|
451
|
-
/// - Wallet can be challenged for the given signature only once
|
|
452
|
-
function submitFraudChallenge(
|
|
453
|
-
bytes calldata walletPublicKey,
|
|
454
|
-
bytes32 sighash,
|
|
455
|
-
BitcoinTx.RSVSignature calldata signature
|
|
456
|
-
) external payable {
|
|
457
|
-
self.submitFraudChallenge(walletPublicKey, sighash, signature);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/// @notice Allows to defeat a pending fraud challenge against a wallet if
|
|
461
|
-
/// the transaction that spends the UTXO follows the protocol rules.
|
|
462
|
-
/// In order to defeat the challenge the same `walletPublicKey` and
|
|
463
|
-
/// signature (represented by `r`, `s` and `v`) must be provided as
|
|
464
|
-
/// were used to calculate the sighash during input signing.
|
|
465
|
-
/// The fraud challenge defeat attempt will only succeed if the
|
|
466
|
-
/// inputs in the preimage are considered honestly spent by the
|
|
467
|
-
/// wallet. Therefore the transaction spending the UTXO must be
|
|
468
|
-
/// proven in the Bridge before a challenge defeat is called.
|
|
469
|
-
/// If successfully defeated, the fraud challenge is marked as
|
|
470
|
-
/// resolved and the amount of ether deposited by the challenger is
|
|
471
|
-
/// sent to the treasury.
|
|
472
|
-
/// @param walletPublicKey The public key of the wallet in the uncompressed
|
|
473
|
-
/// and unprefixed format (64 bytes)
|
|
474
|
-
/// @param preimage The preimage which produces sighash used to generate the
|
|
475
|
-
/// ECDSA signature that is the subject of the fraud claim. It is a
|
|
476
|
-
/// serialized subset of the transaction. The exact subset used as
|
|
477
|
-
/// the preimage depends on the transaction input the signature is
|
|
478
|
-
/// produced for. See BIP-143 for reference
|
|
479
|
-
/// @param witness Flag indicating whether the preimage was produced for a
|
|
480
|
-
/// witness input. True for witness, false for non-witness input
|
|
481
|
-
/// @dev Requirements:
|
|
482
|
-
/// - `walletPublicKey` and `sighash` calculated as `hash256(preimage)`
|
|
483
|
-
/// must identify an open fraud challenge
|
|
484
|
-
/// - the preimage must be a valid preimage of a transaction generated
|
|
485
|
-
/// according to the protocol rules and already proved in the Bridge
|
|
486
|
-
/// - before a defeat attempt is made the transaction that spends the
|
|
487
|
-
/// given UTXO must be proven in the Bridge
|
|
488
|
-
function defeatFraudChallenge(
|
|
489
|
-
bytes calldata walletPublicKey,
|
|
490
|
-
bytes calldata preimage,
|
|
491
|
-
bool witness
|
|
492
|
-
) external {
|
|
493
|
-
self.defeatFraudChallenge(walletPublicKey, preimage, witness);
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
/// @notice Notifies about defeat timeout for the given fraud challenge.
|
|
497
|
-
/// Can be called only if there was a fraud challenge identified by
|
|
498
|
-
/// the provided `walletPublicKey` and `sighash` and it was not
|
|
499
|
-
/// defeated on time. The amount of time that needs to pass after
|
|
500
|
-
/// a fraud challenge is reported is indicated by the
|
|
501
|
-
/// `challengeDefeatTimeout`. After a successful fraud challenge
|
|
502
|
-
/// defeat timeout notification the fraud challenge is marked as
|
|
503
|
-
/// resolved, the stake of each operator is slashed, the ether
|
|
504
|
-
/// deposited is returned to the challenger and the challenger is
|
|
505
|
-
/// rewarded.
|
|
506
|
-
/// @param walletPublicKey The public key of the wallet in the uncompressed
|
|
507
|
-
/// and unprefixed format (64 bytes)
|
|
508
|
-
/// @param sighash The hash that was used to produce the ECDSA signature
|
|
509
|
-
/// that is the subject of the fraud claim. This hash is constructed
|
|
510
|
-
/// by applying double SHA-256 over a serialized subset of the
|
|
511
|
-
/// transaction. The exact subset used as hash preimage depends on
|
|
512
|
-
/// the transaction input the signature is produced for. See BIP-143
|
|
513
|
-
/// for reference
|
|
514
|
-
/// @dev Requirements:
|
|
515
|
-
/// - `walletPublicKey`and `sighash` must identify an open fraud
|
|
516
|
-
/// challenge
|
|
517
|
-
/// - the amount of time indicated by `challengeDefeatTimeout` must
|
|
518
|
-
/// pass after the challenge was reported
|
|
519
|
-
function notifyFraudChallengeDefeatTimeout(
|
|
520
|
-
bytes calldata walletPublicKey,
|
|
521
|
-
bytes32 sighash
|
|
522
|
-
) external {
|
|
523
|
-
self.notifyFraudChallengeDefeatTimeout(walletPublicKey, sighash);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/// @notice Returns the fraud challenge identified by the given key built
|
|
527
|
-
/// as keccak256(walletPublicKey|sighash).
|
|
528
|
-
function fraudChallenges(uint256 challengeKey)
|
|
529
|
-
external
|
|
530
|
-
view
|
|
531
|
-
returns (Fraud.FraudChallenge memory)
|
|
532
|
-
{
|
|
533
|
-
return self.fraudChallenges[challengeKey];
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
/// @notice Requests redemption of the given amount from the specified
|
|
537
|
-
/// wallet to the redeemer Bitcoin output script.
|
|
538
|
-
/// @param walletPubKeyHash The 20-byte wallet public key hash (computed
|
|
539
|
-
/// using Bitcoin HASH160 over the compressed ECDSA public key)
|
|
540
|
-
/// @param mainUtxo Data of the wallet's main UTXO, as currently known on
|
|
541
|
-
/// the Ethereum chain
|
|
542
|
-
/// @param redeemerOutputScript The redeemer's length-prefixed output
|
|
543
|
-
/// script (P2PKH, P2WPKH, P2SH or P2WSH) that will be used to lock
|
|
544
|
-
/// redeemed BTC
|
|
545
|
-
/// @param amount Requested amount in satoshi. This is also the TBTC amount
|
|
546
|
-
/// that is taken from redeemer's balance in the Bank upon request.
|
|
547
|
-
/// Once the request is handled, the actual amount of BTC locked
|
|
548
|
-
/// on the redeemer output script will be always lower than this value
|
|
549
|
-
/// since the treasury and Bitcoin transaction fees must be incurred.
|
|
550
|
-
/// The minimal amount satisfying the request can be computed as:
|
|
551
|
-
/// `amount - (amount / redemptionTreasuryFeeDivisor) - redemptionTxMaxFee`.
|
|
552
|
-
/// Fees values are taken at the moment of request creation.
|
|
324
|
+
/// @notice Requests redemption of the given amount from the specified
|
|
325
|
+
/// wallet to the redeemer Bitcoin output script.
|
|
326
|
+
/// @param walletPubKeyHash The 20-byte wallet public key hash (computed
|
|
327
|
+
/// using Bitcoin HASH160 over the compressed ECDSA public key)
|
|
328
|
+
/// @param mainUtxo Data of the wallet's main UTXO, as currently known on
|
|
329
|
+
/// the Ethereum chain
|
|
330
|
+
/// @param redeemerOutputScript The redeemer's length-prefixed output
|
|
331
|
+
/// script (P2PKH, P2WPKH, P2SH or P2WSH) that will be used to lock
|
|
332
|
+
/// redeemed BTC
|
|
333
|
+
/// @param amount Requested amount in satoshi. This is also the TBTC amount
|
|
334
|
+
/// that is taken from redeemer's balance in the Bank upon request.
|
|
335
|
+
/// Once the request is handled, the actual amount of BTC locked
|
|
336
|
+
/// on the redeemer output script will be always lower than this value
|
|
337
|
+
/// since the treasury and Bitcoin transaction fees must be incurred.
|
|
338
|
+
/// The minimal amount satisfying the request can be computed as:
|
|
339
|
+
/// `amount - (amount / redemptionTreasuryFeeDivisor) - redemptionTxMaxFee`.
|
|
340
|
+
/// Fees values are taken at the moment of request creation.
|
|
553
341
|
/// @dev Requirements:
|
|
554
342
|
/// - Wallet behind `walletPubKeyHash` must be live
|
|
555
343
|
/// - `mainUtxo` components must point to the recent main UTXO
|
|
@@ -665,6 +453,61 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
665
453
|
self.notifyRedemptionTimeout(walletPubKeyHash, redeemerOutputScript);
|
|
666
454
|
}
|
|
667
455
|
|
|
456
|
+
/// @notice Submits the moving funds target wallets commitment.
|
|
457
|
+
/// Once all requirements are met, that function registers the
|
|
458
|
+
/// target wallets commitment and opens the way for moving funds
|
|
459
|
+
/// proof submission.
|
|
460
|
+
/// @param walletPubKeyHash 20-byte public key hash of the source wallet
|
|
461
|
+
/// @param walletMainUtxo Data of the source wallet's main UTXO, as
|
|
462
|
+
/// currently known on the Ethereum chain
|
|
463
|
+
/// @param walletMembersIDs Identifiers of the source wallet signing group
|
|
464
|
+
/// members
|
|
465
|
+
/// @param walletMemberIndex Position of the caller in the source wallet
|
|
466
|
+
/// signing group members list
|
|
467
|
+
/// @param targetWallets List of 20-byte public key hashes of the target
|
|
468
|
+
/// wallets that the source wallet commits to move the funds to
|
|
469
|
+
/// @dev Requirements:
|
|
470
|
+
/// - The source wallet must be in the MovingFunds state
|
|
471
|
+
/// - The source wallet must not have pending redemption requests
|
|
472
|
+
/// - The source wallet must not have submitted its commitment already
|
|
473
|
+
/// - The expression `keccak256(abi.encode(walletMembersIDs))` must
|
|
474
|
+
/// be exactly the same as the hash stored under `membersIdsHash`
|
|
475
|
+
/// for the given source wallet in the ECDSA registry. Those IDs are
|
|
476
|
+
/// not directly stored in the contract for gas efficiency purposes
|
|
477
|
+
/// but they can be read from appropriate `DkgResultSubmitted`
|
|
478
|
+
/// and `DkgResultApproved` events.
|
|
479
|
+
/// - The `walletMemberIndex` must be in range [1, walletMembersIDs.length]
|
|
480
|
+
/// - The caller must be the member of the source wallet signing group
|
|
481
|
+
/// at the position indicated by `walletMemberIndex` parameter
|
|
482
|
+
/// - The `walletMainUtxo` components must point to the recent main
|
|
483
|
+
/// UTXO of the source wallet, as currently known on the Ethereum
|
|
484
|
+
/// chain.
|
|
485
|
+
/// - Source wallet BTC balance must be greater than zero
|
|
486
|
+
/// - At least one Live wallet must exist in the system
|
|
487
|
+
/// - Submitted target wallets count must match the expected count
|
|
488
|
+
/// `N = min(liveWalletsCount, ceil(walletBtcBalance / walletMaxBtcTransfer))`
|
|
489
|
+
/// where `N > 0`
|
|
490
|
+
/// - Each target wallet must be not equal to the source wallet
|
|
491
|
+
/// - Each target wallet must follow the expected order i.e. all
|
|
492
|
+
/// target wallets 20-byte public key hashes represented as numbers
|
|
493
|
+
/// must form a strictly increasing sequence without duplicates.
|
|
494
|
+
/// - Each target wallet must be in Live state
|
|
495
|
+
function submitMovingFundsCommitment(
|
|
496
|
+
bytes20 walletPubKeyHash,
|
|
497
|
+
BitcoinTx.UTXO calldata walletMainUtxo,
|
|
498
|
+
uint32[] calldata walletMembersIDs,
|
|
499
|
+
uint256 walletMemberIndex,
|
|
500
|
+
bytes20[] calldata targetWallets
|
|
501
|
+
) external {
|
|
502
|
+
self.submitMovingFundsCommitment(
|
|
503
|
+
walletPubKeyHash,
|
|
504
|
+
walletMainUtxo,
|
|
505
|
+
walletMembersIDs,
|
|
506
|
+
walletMemberIndex,
|
|
507
|
+
targetWallets
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
668
511
|
/// @notice Used by the wallet to prove the BTC moving funds transaction
|
|
669
512
|
/// and to make the necessary state changes. Moving funds is only
|
|
670
513
|
/// accepted if it satisfies SPV proof.
|
|
@@ -724,166 +567,326 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
724
567
|
);
|
|
725
568
|
}
|
|
726
569
|
|
|
727
|
-
/// @notice
|
|
728
|
-
///
|
|
729
|
-
/// @
|
|
730
|
-
///
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
/// @notice Address where the deposit treasury fees will be sent to.
|
|
737
|
-
/// Treasury takes part in the operators rewarding process.
|
|
738
|
-
function treasury() external view returns (address treasury) {
|
|
739
|
-
treasury = self.treasury;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
/// @notice The number of confirmations on the Bitcoin chain required to
|
|
743
|
-
/// successfully evaluate an SPV proof.
|
|
744
|
-
function txProofDifficultyFactor()
|
|
745
|
-
external
|
|
746
|
-
view
|
|
747
|
-
returns (uint256 txProofDifficultyFactor)
|
|
748
|
-
{
|
|
749
|
-
txProofDifficultyFactor = self.txProofDifficultyFactor;
|
|
570
|
+
/// @notice Notifies about a timed out moving funds process. Terminates
|
|
571
|
+
/// the wallet and slashes signing group members as a result.
|
|
572
|
+
/// @param walletPubKeyHash 20-byte public key hash of the wallet
|
|
573
|
+
/// @dev Requirements:
|
|
574
|
+
/// - The wallet must be in the MovingFunds state
|
|
575
|
+
/// - The moving funds timeout must be actually exceeded
|
|
576
|
+
function notifyMovingFundsTimeout(bytes20 walletPubKeyHash) external {
|
|
577
|
+
self.notifyMovingFundsTimeout(walletPubKeyHash);
|
|
750
578
|
}
|
|
751
579
|
|
|
752
|
-
/// @notice
|
|
753
|
-
///
|
|
754
|
-
///
|
|
755
|
-
///
|
|
756
|
-
///
|
|
757
|
-
///
|
|
758
|
-
///
|
|
759
|
-
///
|
|
760
|
-
///
|
|
761
|
-
///
|
|
762
|
-
///
|
|
763
|
-
///
|
|
764
|
-
///
|
|
765
|
-
///
|
|
766
|
-
///
|
|
767
|
-
///
|
|
768
|
-
///
|
|
769
|
-
|
|
580
|
+
/// @notice Requests creation of a new wallet. This function just
|
|
581
|
+
/// forms a request and the creation process is performed
|
|
582
|
+
/// asynchronously. Once a wallet is created, the ECDSA Wallet
|
|
583
|
+
/// Registry will notify this contract by calling the
|
|
584
|
+
/// `__ecdsaWalletCreatedCallback` function.
|
|
585
|
+
/// @param activeWalletMainUtxo Data of the active wallet's main UTXO, as
|
|
586
|
+
/// currently known on the Ethereum chain.
|
|
587
|
+
/// @dev Requirements:
|
|
588
|
+
/// - `activeWalletMainUtxo` components must point to the recent main
|
|
589
|
+
/// UTXO of the given active wallet, as currently known on the
|
|
590
|
+
/// Ethereum chain. If there is no active wallet at the moment, or
|
|
591
|
+
/// the active wallet has no main UTXO, this parameter can be
|
|
592
|
+
/// empty as it is ignored.
|
|
593
|
+
/// - Wallet creation must not be in progress
|
|
594
|
+
/// - If the active wallet is set, one of the following
|
|
595
|
+
/// conditions must be true:
|
|
596
|
+
/// - The active wallet BTC balance is above the minimum threshold
|
|
597
|
+
/// and the active wallet is old enough, i.e. the creation period
|
|
598
|
+
/// was elapsed since its creation time
|
|
599
|
+
/// - The active wallet BTC balance is above the maximum threshold
|
|
600
|
+
function requestNewWallet(BitcoinTx.UTXO calldata activeWalletMainUtxo)
|
|
770
601
|
external
|
|
771
|
-
view
|
|
772
|
-
returns (
|
|
773
|
-
uint64 depositDustThreshold,
|
|
774
|
-
uint64 depositTreasuryFeeDivisor,
|
|
775
|
-
uint64 depositTxMaxFee
|
|
776
|
-
)
|
|
777
602
|
{
|
|
778
|
-
|
|
779
|
-
depositTreasuryFeeDivisor = self.depositTreasuryFeeDivisor;
|
|
780
|
-
depositTxMaxFee = self.depositTxMaxFee;
|
|
603
|
+
self.requestNewWallet(activeWalletMainUtxo);
|
|
781
604
|
}
|
|
782
605
|
|
|
783
|
-
/// @notice
|
|
784
|
-
///
|
|
785
|
-
///
|
|
786
|
-
///
|
|
787
|
-
///
|
|
788
|
-
///
|
|
789
|
-
///
|
|
790
|
-
///
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
/// @return redemptionTxMaxFee Maximum amount of BTC transaction fee that
|
|
798
|
-
/// can be incurred by each redemption request being part of the
|
|
799
|
-
/// given redemption transaction. If the maximum BTC transaction
|
|
800
|
-
/// fee is exceeded, such transaction is considered a fraud.
|
|
801
|
-
/// @return redemptionTimeout Time after which the redemption request can be
|
|
802
|
-
/// reported as timed out. It is counted from the moment when the
|
|
803
|
-
/// redemption request was created via `requestRedemption` call.
|
|
804
|
-
/// Reported timed out requests are cancelled and locked TBTC is
|
|
805
|
-
/// returned to the redeemer in full amount.
|
|
806
|
-
function redemptionParameters()
|
|
807
|
-
external
|
|
808
|
-
view
|
|
809
|
-
returns (
|
|
810
|
-
uint64 redemptionDustThreshold,
|
|
811
|
-
uint64 redemptionTreasuryFeeDivisor,
|
|
812
|
-
uint64 redemptionTxMaxFee,
|
|
813
|
-
uint256 redemptionTimeout,
|
|
814
|
-
address treasury,
|
|
815
|
-
uint256 txProofDifficultyFactor
|
|
816
|
-
)
|
|
817
|
-
{
|
|
818
|
-
redemptionDustThreshold = self.redemptionDustThreshold;
|
|
819
|
-
redemptionTreasuryFeeDivisor = self.redemptionTreasuryFeeDivisor;
|
|
820
|
-
redemptionTxMaxFee = self.redemptionTxMaxFee;
|
|
821
|
-
redemptionTimeout = self.redemptionTimeout;
|
|
606
|
+
/// @notice A callback function that is called by the ECDSA Wallet Registry
|
|
607
|
+
/// once a new ECDSA wallet is created.
|
|
608
|
+
/// @param ecdsaWalletID Wallet's unique identifier.
|
|
609
|
+
/// @param publicKeyX Wallet's public key's X coordinate.
|
|
610
|
+
/// @param publicKeyY Wallet's public key's Y coordinate.
|
|
611
|
+
/// @dev Requirements:
|
|
612
|
+
/// - The only caller authorized to call this function is `registry`
|
|
613
|
+
/// - Given wallet data must not belong to an already registered wallet
|
|
614
|
+
function __ecdsaWalletCreatedCallback(
|
|
615
|
+
bytes32 ecdsaWalletID,
|
|
616
|
+
bytes32 publicKeyX,
|
|
617
|
+
bytes32 publicKeyY
|
|
618
|
+
) external override {
|
|
619
|
+
self.registerNewWallet(ecdsaWalletID, publicKeyX, publicKeyY);
|
|
822
620
|
}
|
|
823
621
|
|
|
824
|
-
/// @notice
|
|
825
|
-
///
|
|
826
|
-
/// @
|
|
827
|
-
///
|
|
828
|
-
///
|
|
829
|
-
///
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
622
|
+
/// @notice A callback function that is called by the ECDSA Wallet Registry
|
|
623
|
+
/// once a wallet heartbeat failure is detected.
|
|
624
|
+
/// @param publicKeyX Wallet's public key's X coordinate
|
|
625
|
+
/// @param publicKeyY Wallet's public key's Y coordinate
|
|
626
|
+
/// @dev Requirements:
|
|
627
|
+
/// - The only caller authorized to call this function is `registry`
|
|
628
|
+
/// - Wallet must be in Live state
|
|
629
|
+
function __ecdsaWalletHeartbeatFailedCallback(
|
|
630
|
+
bytes32,
|
|
631
|
+
bytes32 publicKeyX,
|
|
632
|
+
bytes32 publicKeyY
|
|
633
|
+
) external override {
|
|
634
|
+
self.notifyWalletHeartbeatFailed(publicKeyX, publicKeyY);
|
|
837
635
|
}
|
|
838
636
|
|
|
839
|
-
/// @notice
|
|
840
|
-
///
|
|
841
|
-
///
|
|
842
|
-
/// @
|
|
843
|
-
///
|
|
844
|
-
///
|
|
845
|
-
///
|
|
846
|
-
///
|
|
847
|
-
///
|
|
848
|
-
///
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
fraudSlashingAmount = self.fraudSlashingAmount;
|
|
860
|
-
fraudNotifierRewardMultiplier = self.fraudNotifierRewardMultiplier;
|
|
861
|
-
fraudChallengeDefeatTimeout = self.fraudChallengeDefeatTimeout;
|
|
862
|
-
fraudChallengeDepositAmount = self.fraudChallengeDepositAmount;
|
|
637
|
+
/// @notice Notifies that the wallet is either old enough or has too few
|
|
638
|
+
/// satoshi left and qualifies to be closed.
|
|
639
|
+
/// @param walletPubKeyHash 20-byte public key hash of the wallet
|
|
640
|
+
/// @param walletMainUtxo Data of the wallet's main UTXO, as currently
|
|
641
|
+
/// known on the Ethereum chain.
|
|
642
|
+
/// @dev Requirements:
|
|
643
|
+
/// - Wallet must not be set as the current active wallet
|
|
644
|
+
/// - Wallet must exceed the wallet maximum age OR the wallet BTC
|
|
645
|
+
/// balance must be lesser than the minimum threshold. If the latter
|
|
646
|
+
/// case is true, the `walletMainUtxo` components must point to the
|
|
647
|
+
/// recent main UTXO of the given wallet, as currently known on the
|
|
648
|
+
/// Ethereum chain. If the wallet has no main UTXO, this parameter
|
|
649
|
+
/// can be empty as it is ignored since the wallet balance is
|
|
650
|
+
/// assumed to be zero.
|
|
651
|
+
/// - Wallet must be in Live state
|
|
652
|
+
function notifyCloseableWallet(
|
|
653
|
+
bytes20 walletPubKeyHash,
|
|
654
|
+
BitcoinTx.UTXO calldata walletMainUtxo
|
|
655
|
+
) external {
|
|
656
|
+
self.notifyCloseableWallet(walletPubKeyHash, walletMainUtxo);
|
|
863
657
|
}
|
|
864
658
|
|
|
865
|
-
/// @
|
|
866
|
-
///
|
|
867
|
-
///
|
|
868
|
-
///
|
|
869
|
-
///
|
|
870
|
-
///
|
|
871
|
-
///
|
|
872
|
-
/// the wallet
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
659
|
+
/// @notice Submits a fraud challenge indicating that a UTXO being under
|
|
660
|
+
/// wallet control was unlocked by the wallet but was not used
|
|
661
|
+
/// according to the protocol rules. That means the wallet signed
|
|
662
|
+
/// a transaction input pointing to that UTXO and there is a unique
|
|
663
|
+
/// sighash and signature pair associated with that input. This
|
|
664
|
+
/// function uses those parameters to create a fraud accusation that
|
|
665
|
+
/// proves a given transaction input unlocking the given UTXO was
|
|
666
|
+
/// actually signed by the wallet. This function cannot determine
|
|
667
|
+
/// whether the transaction was actually broadcast and the input was
|
|
668
|
+
/// consumed in a fraudulent way so it just opens a challenge period
|
|
669
|
+
/// during which the wallet can defeat the challenge by submitting
|
|
670
|
+
/// proof of a transaction that consumes the given input according
|
|
671
|
+
/// to protocol rules. To prevent spurious allegations, the caller
|
|
672
|
+
/// must deposit ETH that is returned back upon justified fraud
|
|
673
|
+
/// challenge or confiscated otherwise.
|
|
674
|
+
///@param walletPublicKey The public key of the wallet in the uncompressed
|
|
675
|
+
/// and unprefixed format (64 bytes)
|
|
676
|
+
/// @param sighash The hash that was used to produce the ECDSA signature
|
|
677
|
+
/// that is the subject of the fraud claim. This hash is constructed
|
|
678
|
+
/// by applying double SHA-256 over a serialized subset of the
|
|
679
|
+
/// transaction. The exact subset used as hash preimage depends on
|
|
680
|
+
/// the transaction input the signature is produced for. See BIP-143
|
|
681
|
+
/// for reference
|
|
682
|
+
/// @param signature Bitcoin signature in the R/S/V format
|
|
683
|
+
/// @dev Requirements:
|
|
684
|
+
/// - Wallet behind `walletPublicKey` must be in Live or MovingFunds
|
|
685
|
+
/// or Closing state
|
|
686
|
+
/// - The challenger must send appropriate amount of ETH used as
|
|
687
|
+
/// fraud challenge deposit
|
|
688
|
+
/// - The signature (represented by r, s and v) must be generated by
|
|
689
|
+
/// the wallet behind `walletPubKey` during signing of `sighash`
|
|
690
|
+
/// - Wallet can be challenged for the given signature only once
|
|
691
|
+
function submitFraudChallenge(
|
|
692
|
+
bytes calldata walletPublicKey,
|
|
693
|
+
bytes32 sighash,
|
|
694
|
+
BitcoinTx.RSVSignature calldata signature
|
|
695
|
+
) external payable {
|
|
696
|
+
self.submitFraudChallenge(walletPublicKey, sighash, signature);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/// @notice Allows to defeat a pending fraud challenge against a wallet if
|
|
700
|
+
/// the transaction that spends the UTXO follows the protocol rules.
|
|
701
|
+
/// In order to defeat the challenge the same `walletPublicKey` and
|
|
702
|
+
/// signature (represented by `r`, `s` and `v`) must be provided as
|
|
703
|
+
/// were used to calculate the sighash during input signing.
|
|
704
|
+
/// The fraud challenge defeat attempt will only succeed if the
|
|
705
|
+
/// inputs in the preimage are considered honestly spent by the
|
|
706
|
+
/// wallet. Therefore the transaction spending the UTXO must be
|
|
707
|
+
/// proven in the Bridge before a challenge defeat is called.
|
|
708
|
+
/// If successfully defeated, the fraud challenge is marked as
|
|
709
|
+
/// resolved and the amount of ether deposited by the challenger is
|
|
710
|
+
/// sent to the treasury.
|
|
711
|
+
/// @param walletPublicKey The public key of the wallet in the uncompressed
|
|
712
|
+
/// and unprefixed format (64 bytes)
|
|
713
|
+
/// @param preimage The preimage which produces sighash used to generate the
|
|
714
|
+
/// ECDSA signature that is the subject of the fraud claim. It is a
|
|
715
|
+
/// serialized subset of the transaction. The exact subset used as
|
|
716
|
+
/// the preimage depends on the transaction input the signature is
|
|
717
|
+
/// produced for. See BIP-143 for reference
|
|
718
|
+
/// @param witness Flag indicating whether the preimage was produced for a
|
|
719
|
+
/// witness input. True for witness, false for non-witness input
|
|
720
|
+
/// @dev Requirements:
|
|
721
|
+
/// - `walletPublicKey` and `sighash` calculated as `hash256(preimage)`
|
|
722
|
+
/// must identify an open fraud challenge
|
|
723
|
+
/// - the preimage must be a valid preimage of a transaction generated
|
|
724
|
+
/// according to the protocol rules and already proved in the Bridge
|
|
725
|
+
/// - before a defeat attempt is made the transaction that spends the
|
|
726
|
+
/// given UTXO must be proven in the Bridge
|
|
727
|
+
function defeatFraudChallenge(
|
|
728
|
+
bytes calldata walletPublicKey,
|
|
729
|
+
bytes calldata preimage,
|
|
730
|
+
bool witness
|
|
731
|
+
) external {
|
|
732
|
+
self.defeatFraudChallenge(walletPublicKey, preimage, witness);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/// @notice Notifies about defeat timeout for the given fraud challenge.
|
|
736
|
+
/// Can be called only if there was a fraud challenge identified by
|
|
737
|
+
/// the provided `walletPublicKey` and `sighash` and it was not
|
|
738
|
+
/// defeated on time. The amount of time that needs to pass after
|
|
739
|
+
/// a fraud challenge is reported is indicated by the
|
|
740
|
+
/// `challengeDefeatTimeout`. After a successful fraud challenge
|
|
741
|
+
/// defeat timeout notification the fraud challenge is marked as
|
|
742
|
+
/// resolved, the stake of each operator is slashed, the ether
|
|
743
|
+
/// deposited is returned to the challenger and the challenger is
|
|
744
|
+
/// rewarded.
|
|
745
|
+
/// @param walletPublicKey The public key of the wallet in the uncompressed
|
|
746
|
+
/// and unprefixed format (64 bytes)
|
|
747
|
+
/// @param sighash The hash that was used to produce the ECDSA signature
|
|
748
|
+
/// that is the subject of the fraud claim. This hash is constructed
|
|
749
|
+
/// by applying double SHA-256 over a serialized subset of the
|
|
750
|
+
/// transaction. The exact subset used as hash preimage depends on
|
|
751
|
+
/// the transaction input the signature is produced for. See BIP-143
|
|
752
|
+
/// for reference
|
|
753
|
+
/// @dev Requirements:
|
|
754
|
+
/// - `walletPublicKey`and `sighash` must identify an open fraud
|
|
755
|
+
/// challenge
|
|
756
|
+
/// - the amount of time indicated by `challengeDefeatTimeout` must
|
|
757
|
+
/// pass after the challenge was reported
|
|
758
|
+
function notifyFraudChallengeDefeatTimeout(
|
|
759
|
+
bytes calldata walletPublicKey,
|
|
760
|
+
bytes32 sighash
|
|
761
|
+
) external {
|
|
762
|
+
self.notifyFraudChallengeDefeatTimeout(walletPublicKey, sighash);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/// @notice Allows the Governance to mark the given vault address as trusted
|
|
766
|
+
/// or no longer trusted. Vaults are not trusted by default.
|
|
767
|
+
/// Trusted vault must meet the following criteria:
|
|
768
|
+
/// - `IVault.receiveBalanceIncrease` must have a known, low gas
|
|
769
|
+
/// cost.
|
|
770
|
+
/// - `IVault.receiveBalanceIncrease` must never revert.
|
|
771
|
+
/// @dev Without restricting reveal only to trusted vaults, malicious
|
|
772
|
+
/// vaults not meeting the criteria would be able to nuke sweep proof
|
|
773
|
+
/// transactions executed by ECDSA wallet with deposits routed to
|
|
774
|
+
/// them.
|
|
775
|
+
/// @param vault The address of the vault
|
|
776
|
+
/// @param isTrusted flag indicating whether the vault is trusted or not
|
|
777
|
+
/// @dev Can only be called by the Governance.
|
|
778
|
+
function setVaultStatus(address vault, bool isTrusted) external onlyOwner {
|
|
779
|
+
self.isVaultTrusted[vault] = isTrusted;
|
|
780
|
+
emit VaultStatusUpdated(vault, isTrusted);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
/// @notice Updates parameters of deposits.
|
|
784
|
+
/// @param depositDustThreshold New value of the deposit dust threshold in
|
|
785
|
+
/// satoshis. It is the minimal amount that can be requested to
|
|
786
|
+
//// deposit. Value of this parameter must take into account the value
|
|
787
|
+
/// of `depositTreasuryFeeDivisor` and `depositTxMaxFee` parameters
|
|
788
|
+
/// in order to make requests that can incur the treasury and
|
|
789
|
+
/// transaction fee and still satisfy the depositor
|
|
790
|
+
/// @param depositTreasuryFeeDivisor New value of the treasury fee divisor.
|
|
791
|
+
/// It is the divisor used to compute the treasury fee taken from
|
|
792
|
+
/// each deposit and transferred to the treasury upon sweep proof
|
|
793
|
+
/// submission. That fee is computed as follows:
|
|
794
|
+
/// `treasuryFee = depositedAmount / depositTreasuryFeeDivisor`
|
|
795
|
+
/// For example, if the treasury fee needs to be 2% of each deposit,
|
|
796
|
+
/// the `depositTreasuryFeeDivisor` should be set to `50`
|
|
797
|
+
/// because `1/50 = 0.02 = 2%`
|
|
798
|
+
/// @param depositTxMaxFee New value of the deposit tx max fee in satoshis.
|
|
799
|
+
/// It is the maximum amount of BTC transaction fee that can
|
|
800
|
+
/// be incurred by each swept deposit being part of the given sweep
|
|
801
|
+
/// transaction. If the maximum BTC transaction fee is exceeded,
|
|
802
|
+
/// such transaction is considered a fraud
|
|
803
|
+
/// @dev Requirements:
|
|
804
|
+
/// - Deposit dust threshold must be greater than zero
|
|
805
|
+
/// - Deposit treasury fee divisor must be greater than zero
|
|
806
|
+
/// - Deposit transaction max fee must be greater than zero
|
|
807
|
+
function updateDepositParameters(
|
|
808
|
+
uint64 depositDustThreshold,
|
|
809
|
+
uint64 depositTreasuryFeeDivisor,
|
|
810
|
+
uint64 depositTxMaxFee
|
|
811
|
+
) external onlyOwner {
|
|
812
|
+
self.updateDepositParameters(
|
|
813
|
+
depositDustThreshold,
|
|
814
|
+
depositTreasuryFeeDivisor,
|
|
815
|
+
depositTxMaxFee
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/// @notice Updates parameters of redemptions.
|
|
820
|
+
/// @param redemptionDustThreshold New value of the redemption dust
|
|
821
|
+
/// threshold in satoshis. It is the minimal amount that can be
|
|
822
|
+
/// requested for redemption. Value of this parameter must take into
|
|
823
|
+
/// account the value of `redemptionTreasuryFeeDivisor` and
|
|
824
|
+
/// `redemptionTxMaxFee` parameters in order to make requests that
|
|
825
|
+
/// can incur the treasury and transaction fee and still satisfy the
|
|
826
|
+
/// redeemer.
|
|
827
|
+
/// @param redemptionTreasuryFeeDivisor New value of the redemption
|
|
828
|
+
/// treasury fee divisor. It is the divisor used to compute the
|
|
829
|
+
/// treasury fee taken from each redemption request and transferred
|
|
830
|
+
/// to the treasury upon successful request finalization. That fee is
|
|
831
|
+
/// computed as follows:
|
|
832
|
+
/// `treasuryFee = requestedAmount / redemptionTreasuryFeeDivisor`
|
|
833
|
+
/// For example, if the treasury fee needs to be 2% of each
|
|
834
|
+
/// redemption request, the `redemptionTreasuryFeeDivisor` should
|
|
835
|
+
/// be set to `50` because `1/50 = 0.02 = 2%`.
|
|
836
|
+
/// @param redemptionTxMaxFee New value of the redemption transaction max
|
|
837
|
+
/// fee in satoshis. It is the maximum amount of BTC transaction fee
|
|
838
|
+
/// that can be incurred by each redemption request being part of the
|
|
839
|
+
/// given redemption transaction. If the maximum BTC transaction fee
|
|
840
|
+
/// is exceeded, such transaction is considered a fraud.
|
|
841
|
+
/// This is a per-redemption output max fee for the redemption
|
|
842
|
+
/// transaction.
|
|
843
|
+
/// @param redemptionTimeout New value of the redemption timeout in seconds.
|
|
844
|
+
/// It is the time after which the redemption request can be reported
|
|
845
|
+
/// as timed out. It is counted from the moment when the redemption
|
|
846
|
+
/// request was created via `requestRedemption` call. Reported timed
|
|
847
|
+
/// out requests are cancelled and locked TBTC is returned to the
|
|
848
|
+
/// redeemer in full amount.
|
|
849
|
+
/// @dev Requirements:
|
|
850
|
+
/// - Redemption dust threshold must be greater than zero
|
|
851
|
+
/// - Redemption treasury fee divisor must be greater than zero
|
|
852
|
+
/// - Redemption transaction max fee must be greater than zero
|
|
853
|
+
/// - Redemption timeout must be greater than zero
|
|
854
|
+
function updateRedemptionParameters(
|
|
855
|
+
uint64 redemptionDustThreshold,
|
|
856
|
+
uint64 redemptionTreasuryFeeDivisor,
|
|
857
|
+
uint64 redemptionTxMaxFee,
|
|
858
|
+
uint256 redemptionTimeout
|
|
859
|
+
) external onlyOwner {
|
|
860
|
+
self.updateRedemptionParameters(
|
|
861
|
+
redemptionDustThreshold,
|
|
862
|
+
redemptionTreasuryFeeDivisor,
|
|
863
|
+
redemptionTxMaxFee,
|
|
864
|
+
redemptionTimeout
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/// @notice Updates parameters of moving funds.
|
|
869
|
+
/// @param movingFundsTxMaxTotalFee New value of the moving funds transaction
|
|
870
|
+
/// max total fee in satoshis. It is the maximum amount of the total
|
|
871
|
+
/// BTC transaction fee that is acceptable in a single moving funds
|
|
872
|
+
/// transaction. This is a _total_ max fee for the entire moving
|
|
873
|
+
/// funds transaction.
|
|
874
|
+
/// @param movingFundsTimeout New value of the moving funds timeout in
|
|
875
|
+
/// seconds. It is the time after which the moving funds process can
|
|
876
|
+
/// be reported as timed out. It is counted from the moment when the
|
|
877
|
+
/// wallet was requested to move their funds and switched to the
|
|
878
|
+
/// MovingFunds state.
|
|
879
|
+
/// @dev Requirements:
|
|
880
|
+
/// - Moving funds transaction max total fee must be greater than zero
|
|
881
|
+
/// - Moving funds timeout must be greater than zero
|
|
882
|
+
function updateMovingFundsParameters(
|
|
883
|
+
uint64 movingFundsTxMaxTotalFee,
|
|
884
|
+
uint32 movingFundsTimeout
|
|
885
|
+
) external onlyOwner {
|
|
886
|
+
self.updateMovingFundsParameters(
|
|
887
|
+
movingFundsTxMaxTotalFee,
|
|
888
|
+
movingFundsTimeout
|
|
889
|
+
);
|
|
887
890
|
}
|
|
888
891
|
|
|
889
892
|
/// @notice Updates parameters of wallets.
|
|
@@ -891,39 +894,65 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
891
894
|
/// seconds, determines how frequently a new wallet creation can be
|
|
892
895
|
/// requested
|
|
893
896
|
/// @param walletMinBtcBalance New value of the wallet minimum BTC balance
|
|
894
|
-
/// in
|
|
897
|
+
/// in satoshi, used to decide about wallet creation or closing
|
|
895
898
|
/// @param walletMaxBtcBalance New value of the wallet maximum BTC balance
|
|
896
|
-
/// in
|
|
899
|
+
/// in satoshi, used to decide about wallet creation
|
|
897
900
|
/// @param walletMaxAge New value of the wallet maximum age in seconds,
|
|
898
901
|
/// indicates the maximum age of a wallet in seconds, after which
|
|
899
902
|
/// the wallet moving funds process can be requested
|
|
903
|
+
/// @param walletMaxBtcTransfer New value of the wallet maximum BTC transfer
|
|
904
|
+
/// in satoshi, determines the maximum amount that can be transferred
|
|
905
|
+
// to a single target wallet during the moving funds process
|
|
900
906
|
/// @dev Requirements:
|
|
901
907
|
/// - Wallet minimum BTC balance must be greater than zero
|
|
902
908
|
/// - Wallet maximum BTC balance must be greater than the wallet
|
|
903
909
|
/// minimum BTC balance
|
|
910
|
+
/// - Wallet maximum BTC transfer must be greater than zero
|
|
904
911
|
function updateWalletParameters(
|
|
905
912
|
uint32 walletCreationPeriod,
|
|
906
913
|
uint64 walletMinBtcBalance,
|
|
907
914
|
uint64 walletMaxBtcBalance,
|
|
908
|
-
uint32 walletMaxAge
|
|
915
|
+
uint32 walletMaxAge,
|
|
916
|
+
uint64 walletMaxBtcTransfer
|
|
909
917
|
) external onlyOwner {
|
|
910
918
|
self.updateWalletParameters(
|
|
911
919
|
walletCreationPeriod,
|
|
912
920
|
walletMinBtcBalance,
|
|
913
921
|
walletMaxBtcBalance,
|
|
914
|
-
walletMaxAge
|
|
922
|
+
walletMaxAge,
|
|
923
|
+
walletMaxBtcTransfer
|
|
915
924
|
);
|
|
916
925
|
}
|
|
917
926
|
|
|
918
|
-
/// @notice
|
|
919
|
-
///
|
|
920
|
-
///
|
|
921
|
-
///
|
|
922
|
-
///
|
|
923
|
-
///
|
|
924
|
-
///
|
|
925
|
-
|
|
926
|
-
|
|
927
|
+
/// @notice Updates parameters related to frauds.
|
|
928
|
+
/// @param fraudSlashingAmount New value of the fraud slashing amount in T,
|
|
929
|
+
/// it is the amount slashed from each wallet member for committing
|
|
930
|
+
/// a fraud
|
|
931
|
+
/// @param fraudNotifierRewardMultiplier New value of the fraud notifier
|
|
932
|
+
/// reward multiplier as percentage, it determines the percentage of
|
|
933
|
+
/// the notifier reward from the staking contact the notifier of
|
|
934
|
+
/// a fraud receives. The value must be in the range [0, 100]
|
|
935
|
+
/// @param fraudChallengeDefeatTimeout New value of the challenge defeat
|
|
936
|
+
/// timeout in seconds, it is the amount of time the wallet has to
|
|
937
|
+
/// defeat a fraud challenge. The value must be greater than zero
|
|
938
|
+
/// @param fraudChallengeDepositAmount New value of the fraud challenge
|
|
939
|
+
/// deposit amount in wei, it is the amount of ETH the party
|
|
940
|
+
/// challenging the wallet for fraud needs to deposit
|
|
941
|
+
/// @dev Requirements:
|
|
942
|
+
/// - Fraud notifier reward multiplier must be in the range [0, 100]
|
|
943
|
+
/// - Fraud challenge defeat timeout must be greater than 0
|
|
944
|
+
function updateFraudParameters(
|
|
945
|
+
uint256 fraudSlashingAmount,
|
|
946
|
+
uint256 fraudNotifierRewardMultiplier,
|
|
947
|
+
uint256 fraudChallengeDefeatTimeout,
|
|
948
|
+
uint256 fraudChallengeDepositAmount
|
|
949
|
+
) external onlyOwner {
|
|
950
|
+
self.updateFraudParameters(
|
|
951
|
+
fraudSlashingAmount,
|
|
952
|
+
fraudNotifierRewardMultiplier,
|
|
953
|
+
fraudChallengeDefeatTimeout,
|
|
954
|
+
fraudChallengeDepositAmount
|
|
955
|
+
);
|
|
927
956
|
}
|
|
928
957
|
|
|
929
958
|
/// @notice Collection of all revealed deposits indexed by
|
|
@@ -940,16 +969,6 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
940
969
|
return self.deposits[depositKey];
|
|
941
970
|
}
|
|
942
971
|
|
|
943
|
-
/// @notice Collection of main UTXOs that are honestly spent indexed by
|
|
944
|
-
/// keccak256(fundingTxHash | fundingOutputIndex). The fundingTxHash
|
|
945
|
-
/// is bytes32 (ordered as in Bitcoin internally) and
|
|
946
|
-
/// fundingOutputIndex an uint32. A main UTXO is considered honestly
|
|
947
|
-
/// spent if it was used as an input of a transaction that have been
|
|
948
|
-
/// proven in the Bridge.
|
|
949
|
-
function spentMainUTXOs(uint256 utxoKey) external view returns (bool) {
|
|
950
|
-
return self.spentMainUTXOs[utxoKey];
|
|
951
|
-
}
|
|
952
|
-
|
|
953
972
|
/// @notice Collection of all pending redemption requests indexed by
|
|
954
973
|
/// redemption key built as
|
|
955
974
|
/// keccak256(walletPubKeyHash | redeemerOutputScript). The
|
|
@@ -967,7 +986,7 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
967
986
|
function pendingRedemptions(uint256 redemptionKey)
|
|
968
987
|
external
|
|
969
988
|
view
|
|
970
|
-
returns (
|
|
989
|
+
returns (Redemption.RedemptionRequest memory)
|
|
971
990
|
{
|
|
972
991
|
return self.pendingRedemptions[redemptionKey];
|
|
973
992
|
}
|
|
@@ -988,8 +1007,236 @@ contract Bridge is Ownable, EcdsaWalletOwner {
|
|
|
988
1007
|
function timedOutRedemptions(uint256 redemptionKey)
|
|
989
1008
|
external
|
|
990
1009
|
view
|
|
991
|
-
returns (
|
|
1010
|
+
returns (Redemption.RedemptionRequest memory)
|
|
992
1011
|
{
|
|
993
1012
|
return self.timedOutRedemptions[redemptionKey];
|
|
994
1013
|
}
|
|
1014
|
+
|
|
1015
|
+
/// @notice Collection of main UTXOs that are honestly spent indexed by
|
|
1016
|
+
/// keccak256(fundingTxHash | fundingOutputIndex). The fundingTxHash
|
|
1017
|
+
/// is bytes32 (ordered as in Bitcoin internally) and
|
|
1018
|
+
/// fundingOutputIndex an uint32. A main UTXO is considered honestly
|
|
1019
|
+
/// spent if it was used as an input of a transaction that have been
|
|
1020
|
+
/// proven in the Bridge.
|
|
1021
|
+
function spentMainUTXOs(uint256 utxoKey) external view returns (bool) {
|
|
1022
|
+
return self.spentMainUTXOs[utxoKey];
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/// @notice Gets details about a registered wallet.
|
|
1026
|
+
/// @param walletPubKeyHash The 20-byte wallet public key hash (computed
|
|
1027
|
+
/// using Bitcoin HASH160 over the compressed ECDSA public key)
|
|
1028
|
+
/// @return Wallet details.
|
|
1029
|
+
function wallets(bytes20 walletPubKeyHash)
|
|
1030
|
+
external
|
|
1031
|
+
view
|
|
1032
|
+
returns (Wallets.Wallet memory)
|
|
1033
|
+
{
|
|
1034
|
+
return self.registeredWallets[walletPubKeyHash];
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
/// @notice Gets the public key hash of the active wallet.
|
|
1038
|
+
/// @return The 20-byte public key hash (computed using Bitcoin HASH160
|
|
1039
|
+
/// over the compressed ECDSA public key) of the active wallet.
|
|
1040
|
+
/// Returns bytes20(0) if there is no active wallet at the moment.
|
|
1041
|
+
function activeWalletPubKeyHash() external view returns (bytes20) {
|
|
1042
|
+
return self.activeWalletPubKeyHash;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/// @notice Gets the live wallets count.
|
|
1046
|
+
/// @return The current count of wallets being in the Live state.
|
|
1047
|
+
function liveWalletsCount() external view returns (uint32) {
|
|
1048
|
+
return self.liveWalletsCount;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
/// @notice Returns the fraud challenge identified by the given key built
|
|
1052
|
+
/// as keccak256(walletPublicKey|sighash).
|
|
1053
|
+
function fraudChallenges(uint256 challengeKey)
|
|
1054
|
+
external
|
|
1055
|
+
view
|
|
1056
|
+
returns (Fraud.FraudChallenge memory)
|
|
1057
|
+
{
|
|
1058
|
+
return self.fraudChallenges[challengeKey];
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/// @notice Indicates if the vault with the given address is trusted or not.
|
|
1062
|
+
/// Depositors can route their revealed deposits only to trusted
|
|
1063
|
+
/// vaults and have trusted vaults notified about new deposits as
|
|
1064
|
+
/// soon as these deposits get swept. Vaults not trusted by the
|
|
1065
|
+
/// Bridge can still be used by Bank balance owners on their own
|
|
1066
|
+
/// responsibility - anyone can approve their Bank balance to any
|
|
1067
|
+
/// address.
|
|
1068
|
+
function isVaultTrusted(address vault) external view returns (bool) {
|
|
1069
|
+
return self.isVaultTrusted[vault];
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
/// @notice Returns the current values of Bridge deposit parameters.
|
|
1073
|
+
/// @return depositDustThreshold The minimal amount that can be requested
|
|
1074
|
+
/// to deposit. Value of this parameter must take into account the
|
|
1075
|
+
/// value of `depositTreasuryFeeDivisor` and `depositTxMaxFee`
|
|
1076
|
+
/// parameters in order to make requests that can incur the
|
|
1077
|
+
/// treasury and transaction fee and still satisfy the depositor.
|
|
1078
|
+
/// @return depositTreasuryFeeDivisor Divisor used to compute the treasury
|
|
1079
|
+
/// fee taken from each deposit and transferred to the treasury upon
|
|
1080
|
+
/// sweep proof submission. That fee is computed as follows:
|
|
1081
|
+
/// `treasuryFee = depositedAmount / depositTreasuryFeeDivisor`
|
|
1082
|
+
/// For example, if the treasury fee needs to be 2% of each deposit,
|
|
1083
|
+
/// the `depositTreasuryFeeDivisor` should be set to `50`
|
|
1084
|
+
/// because `1/50 = 0.02 = 2%`.
|
|
1085
|
+
/// @return depositTxMaxFee Maximum amount of BTC transaction fee that can
|
|
1086
|
+
/// be incurred by each swept deposit being part of the given sweep
|
|
1087
|
+
/// transaction. If the maximum BTC transaction fee is exceeded,
|
|
1088
|
+
/// such transaction is considered a fraud.
|
|
1089
|
+
function depositParameters()
|
|
1090
|
+
external
|
|
1091
|
+
view
|
|
1092
|
+
returns (
|
|
1093
|
+
uint64 depositDustThreshold,
|
|
1094
|
+
uint64 depositTreasuryFeeDivisor,
|
|
1095
|
+
uint64 depositTxMaxFee
|
|
1096
|
+
)
|
|
1097
|
+
{
|
|
1098
|
+
depositDustThreshold = self.depositDustThreshold;
|
|
1099
|
+
depositTreasuryFeeDivisor = self.depositTreasuryFeeDivisor;
|
|
1100
|
+
depositTxMaxFee = self.depositTxMaxFee;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
/// @notice Returns the current values of Bridge redemption parameters.
|
|
1104
|
+
/// @return redemptionDustThreshold The minimal amount that can be requested
|
|
1105
|
+
/// for redemption. Value of this parameter must take into account
|
|
1106
|
+
/// the value of `redemptionTreasuryFeeDivisor` and `redemptionTxMaxFee`
|
|
1107
|
+
/// parameters in order to make requests that can incur the
|
|
1108
|
+
/// treasury and transaction fee and still satisfy the redeemer.
|
|
1109
|
+
/// @return redemptionTreasuryFeeDivisor Divisor used to compute the treasury
|
|
1110
|
+
/// fee taken from each redemption request and transferred to the
|
|
1111
|
+
/// treasury upon successful request finalization. That fee is
|
|
1112
|
+
/// computed as follows:
|
|
1113
|
+
/// `treasuryFee = requestedAmount / redemptionTreasuryFeeDivisor`
|
|
1114
|
+
/// For example, if the treasury fee needs to be 2% of each
|
|
1115
|
+
/// redemption request, the `redemptionTreasuryFeeDivisor` should
|
|
1116
|
+
/// be set to `50` because `1/50 = 0.02 = 2%`.
|
|
1117
|
+
/// @return redemptionTxMaxFee Maximum amount of BTC transaction fee that
|
|
1118
|
+
/// can be incurred by each redemption request being part of the
|
|
1119
|
+
/// given redemption transaction. If the maximum BTC transaction
|
|
1120
|
+
/// fee is exceeded, such transaction is considered a fraud.
|
|
1121
|
+
/// This is a per-redemption output max fee for the redemption
|
|
1122
|
+
/// transaction.
|
|
1123
|
+
/// @return redemptionTimeout Time after which the redemption request can be
|
|
1124
|
+
/// reported as timed out. It is counted from the moment when the
|
|
1125
|
+
/// redemption request was created via `requestRedemption` call.
|
|
1126
|
+
/// Reported timed out requests are cancelled and locked TBTC is
|
|
1127
|
+
/// returned to the redeemer in full amount.
|
|
1128
|
+
function redemptionParameters()
|
|
1129
|
+
external
|
|
1130
|
+
view
|
|
1131
|
+
returns (
|
|
1132
|
+
uint64 redemptionDustThreshold,
|
|
1133
|
+
uint64 redemptionTreasuryFeeDivisor,
|
|
1134
|
+
uint64 redemptionTxMaxFee,
|
|
1135
|
+
uint256 redemptionTimeout
|
|
1136
|
+
)
|
|
1137
|
+
{
|
|
1138
|
+
redemptionDustThreshold = self.redemptionDustThreshold;
|
|
1139
|
+
redemptionTreasuryFeeDivisor = self.redemptionTreasuryFeeDivisor;
|
|
1140
|
+
redemptionTxMaxFee = self.redemptionTxMaxFee;
|
|
1141
|
+
redemptionTimeout = self.redemptionTimeout;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/// @notice Returns the current values of Bridge moving funds between
|
|
1145
|
+
/// wallets parameters.
|
|
1146
|
+
/// @return movingFundsTxMaxTotalFee Maximum amount of the total BTC
|
|
1147
|
+
/// transaction fee that is acceptable in a single moving funds
|
|
1148
|
+
/// transaction. This is a _total_ max fee for the entire moving
|
|
1149
|
+
/// funds transaction.
|
|
1150
|
+
/// @return movingFundsTimeout Time after which the moving funds process
|
|
1151
|
+
/// can be reported as timed out. It is counted from the moment
|
|
1152
|
+
/// when the wallet was requested to move their funds and switched
|
|
1153
|
+
/// to the MovingFunds state. Value in seconds.
|
|
1154
|
+
function movingFundsParameters()
|
|
1155
|
+
external
|
|
1156
|
+
view
|
|
1157
|
+
returns (uint64 movingFundsTxMaxTotalFee, uint32 movingFundsTimeout)
|
|
1158
|
+
{
|
|
1159
|
+
movingFundsTxMaxTotalFee = self.movingFundsTxMaxTotalFee;
|
|
1160
|
+
movingFundsTimeout = self.movingFundsTimeout;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
/// @return walletCreationPeriod Determines how frequently a new wallet
|
|
1164
|
+
/// creation can be requested. Value in seconds.
|
|
1165
|
+
/// @return walletMinBtcBalance The minimum BTC threshold in satoshi that is
|
|
1166
|
+
/// used to decide about wallet creation or closing.
|
|
1167
|
+
/// @return walletMaxBtcBalance The maximum BTC threshold in satoshi that is
|
|
1168
|
+
/// used to decide about wallet creation.
|
|
1169
|
+
/// @return walletMaxAge The maximum age of a wallet in seconds, after which
|
|
1170
|
+
/// the wallet moving funds process can be requested.
|
|
1171
|
+
/// @return walletMaxBtcTransfer The maximum BTC amount in satoshi than
|
|
1172
|
+
/// can be transferred to a single target wallet during the moving
|
|
1173
|
+
/// funds process.
|
|
1174
|
+
function walletParameters()
|
|
1175
|
+
external
|
|
1176
|
+
view
|
|
1177
|
+
returns (
|
|
1178
|
+
uint32 walletCreationPeriod,
|
|
1179
|
+
uint64 walletMinBtcBalance,
|
|
1180
|
+
uint64 walletMaxBtcBalance,
|
|
1181
|
+
uint32 walletMaxAge,
|
|
1182
|
+
uint64 walletMaxBtcTransfer
|
|
1183
|
+
)
|
|
1184
|
+
{
|
|
1185
|
+
walletCreationPeriod = self.walletCreationPeriod;
|
|
1186
|
+
walletMinBtcBalance = self.walletMinBtcBalance;
|
|
1187
|
+
walletMaxBtcBalance = self.walletMaxBtcBalance;
|
|
1188
|
+
walletMaxAge = self.walletMaxAge;
|
|
1189
|
+
walletMaxBtcTransfer = self.walletMaxBtcTransfer;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
/// @notice Returns the current values of Bridge fraud parameters.
|
|
1193
|
+
/// @return fraudSlashingAmount The amount slashed from each wallet member
|
|
1194
|
+
/// for committing a fraud.
|
|
1195
|
+
/// @return fraudNotifierRewardMultiplier The percentage of the notifier
|
|
1196
|
+
/// reward from the staking contract the notifier of a fraud
|
|
1197
|
+
/// receives. The value is in the range [0, 100].
|
|
1198
|
+
/// @return fraudChallengeDefeatTimeout The amount of time the wallet has to
|
|
1199
|
+
/// defeat a fraud challenge.
|
|
1200
|
+
/// @return fraudChallengeDepositAmount The amount of ETH in wei the party
|
|
1201
|
+
/// challenging the wallet for fraud needs to deposit.
|
|
1202
|
+
function fraudParameters()
|
|
1203
|
+
external
|
|
1204
|
+
view
|
|
1205
|
+
returns (
|
|
1206
|
+
uint256 fraudSlashingAmount,
|
|
1207
|
+
uint256 fraudNotifierRewardMultiplier,
|
|
1208
|
+
uint256 fraudChallengeDefeatTimeout,
|
|
1209
|
+
uint256 fraudChallengeDepositAmount
|
|
1210
|
+
)
|
|
1211
|
+
{
|
|
1212
|
+
fraudSlashingAmount = self.fraudSlashingAmount;
|
|
1213
|
+
fraudNotifierRewardMultiplier = self.fraudNotifierRewardMultiplier;
|
|
1214
|
+
fraudChallengeDefeatTimeout = self.fraudChallengeDefeatTimeout;
|
|
1215
|
+
fraudChallengeDepositAmount = self.fraudChallengeDepositAmount;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
/// @notice Returns the addresses of contracts Bridge is interacting with.
|
|
1219
|
+
/// @return bank Address of the Bank the Bridge belongs to.
|
|
1220
|
+
/// @return relay Address of the Bitcoin relay providing the current Bitcoin
|
|
1221
|
+
/// network difficulty.
|
|
1222
|
+
function contractReferences()
|
|
1223
|
+
external
|
|
1224
|
+
view
|
|
1225
|
+
returns (Bank bank, IRelay relay)
|
|
1226
|
+
{
|
|
1227
|
+
bank = self.bank;
|
|
1228
|
+
relay = self.relay;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/// @notice Address where the deposit treasury fees will be sent to.
|
|
1232
|
+
/// Treasury takes part in the operators rewarding process.
|
|
1233
|
+
function treasury() external view returns (address) {
|
|
1234
|
+
return self.treasury;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/// @notice The number of confirmations on the Bitcoin chain required to
|
|
1238
|
+
/// successfully evaluate an SPV proof.
|
|
1239
|
+
function txProofDifficultyFactor() external view returns (uint256) {
|
|
1240
|
+
return self.txProofDifficultyFactor;
|
|
1241
|
+
}
|
|
995
1242
|
}
|