@keep-network/tbtc-v2 0.1.1-dev.55 → 0.1.1-dev.56
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 +3 -3
- package/artifacts/Bridge.json +515 -191
- package/artifacts/Deposit.json +7 -7
- package/artifacts/DepositSweep.json +76 -0
- package/artifacts/EcdsaDkgValidator.json +1 -1
- package/artifacts/EcdsaInactivity.json +1 -1
- package/artifacts/Fraud.json +7 -7
- package/artifacts/KeepRegistry.json +1 -1
- package/artifacts/KeepStake.json +2 -2
- package/artifacts/KeepToken.json +2 -2
- package/artifacts/KeepTokenStaking.json +1 -1
- package/artifacts/MovingFunds.json +40 -10
- package/artifacts/NuCypherStakingEscrow.json +1 -1
- package/artifacts/NuCypherToken.json +2 -2
- package/artifacts/RandomBeaconStub.json +1 -1
- package/artifacts/Redemption.json +9 -9
- package/artifacts/ReimbursementPool.json +2 -2
- package/artifacts/Relay.json +9 -9
- package/artifacts/SortitionPool.json +2 -2
- package/artifacts/T.json +2 -2
- package/artifacts/TBTC.json +3 -3
- package/artifacts/TBTCToken.json +3 -3
- package/artifacts/TokenStaking.json +1 -1
- package/artifacts/TokenholderGovernor.json +9 -9
- package/artifacts/TokenholderTimelock.json +8 -8
- package/artifacts/VendingMachine.json +10 -10
- package/artifacts/VendingMachineKeep.json +1 -1
- package/artifacts/VendingMachineNuCypher.json +1 -1
- package/artifacts/WalletRegistry.json +2 -2
- package/artifacts/WalletRegistryGovernance.json +2 -2
- package/artifacts/Wallets.json +9 -9
- package/artifacts/solcInputs/{6d69fc514efd874ebb1cb86b04981772.json → 5dd2a7c685770548b7ea9ce25e179326.json} +9 -9
- 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 +266 -103
- package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
- package/build/contracts/bridge/BridgeState.sol/BridgeState.json +8 -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/DepositSweep.sol/DepositSweep.dbg.json +4 -0
- package/build/contracts/bridge/{Sweep.sol/Sweep.json → DepositSweep.sol/DepositSweep.json} +4 -4
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
- package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
- package/build/contracts/bridge/Fraud.sol/Fraud.json +2 -2
- 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 +21 -2
- package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
- package/build/contracts/bridge/Redemption.sol/OutboundTx.json +2 -2
- package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
- package/build/contracts/bridge/Redemption.sol/Redemption.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 +2 -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 +69 -0
- package/contracts/bridge/Bridge.sol +90 -8
- package/contracts/bridge/BridgeState.sol +34 -3
- package/contracts/bridge/{Sweep.sol → DepositSweep.sol} +30 -18
- package/contracts/bridge/MovingFunds.sol +469 -76
- package/deploy/05_deploy_bridge.ts +5 -2
- package/export.json +313 -56
- package/package.json +1 -1
- package/artifacts/Sweep.json +0 -76
- package/build/contracts/bridge/Sweep.sol/Sweep.dbg.json +0 -4
|
@@ -22,7 +22,7 @@ import {IWalletOwner as EcdsaWalletOwner} from "@keep-network/ecdsa/contracts/ap
|
|
|
22
22
|
import "./IRelay.sol";
|
|
23
23
|
import "./BridgeState.sol";
|
|
24
24
|
import "./Deposit.sol";
|
|
25
|
-
import "./
|
|
25
|
+
import "./DepositSweep.sol";
|
|
26
26
|
import "./Redemption.sol";
|
|
27
27
|
import "./BitcoinTx.sol";
|
|
28
28
|
import "./EcdsaLib.sol";
|
|
@@ -60,7 +60,7 @@ import "../bank/Bank.sol";
|
|
|
60
60
|
contract Bridge is Governable, EcdsaWalletOwner {
|
|
61
61
|
using BridgeState for BridgeState.Storage;
|
|
62
62
|
using Deposit for BridgeState.Storage;
|
|
63
|
-
using
|
|
63
|
+
using DepositSweep for BridgeState.Storage;
|
|
64
64
|
using Redemption for BridgeState.Storage;
|
|
65
65
|
using MovingFunds for BridgeState.Storage;
|
|
66
66
|
using Wallets for BridgeState.Storage;
|
|
@@ -121,6 +121,8 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
121
121
|
|
|
122
122
|
event MovingFundsBelowDustReported(bytes20 walletPubKeyHash);
|
|
123
123
|
|
|
124
|
+
event MovedFundsSwept(bytes20 walletPubKeyHash, bytes32 sweepTxHash);
|
|
125
|
+
|
|
124
126
|
event NewWalletRequested();
|
|
125
127
|
|
|
126
128
|
event NewWalletRegistered(
|
|
@@ -180,7 +182,8 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
180
182
|
uint64 movingFundsDustThreshold,
|
|
181
183
|
uint32 movingFundsTimeout,
|
|
182
184
|
uint96 movingFundsTimeoutSlashingAmount,
|
|
183
|
-
uint256 movingFundsTimeoutNotifierRewardMultiplier
|
|
185
|
+
uint256 movingFundsTimeoutNotifierRewardMultiplier,
|
|
186
|
+
uint64 movedFundsSweepTxMaxTotalFee
|
|
184
187
|
);
|
|
185
188
|
|
|
186
189
|
event WalletParametersUpdated(
|
|
@@ -239,6 +242,7 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
239
242
|
self.movingFundsTimeout = 7 days;
|
|
240
243
|
self.movingFundsTimeoutSlashingAmount = 10000 * 1e18; // 10000 T
|
|
241
244
|
self.movingFundsTimeoutNotifierRewardMultiplier = 100; //100%
|
|
245
|
+
self.movedFundsSweepTxMaxTotalFee = 10000; // 10000 satoshi
|
|
242
246
|
self.fraudChallengeDepositAmount = 2 ether;
|
|
243
247
|
self.fraudChallengeDefeatTimeout = 7 days;
|
|
244
248
|
self.fraudSlashingAmount = 10000 * 1e18; // 10000 T
|
|
@@ -331,12 +335,12 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
331
335
|
/// - `mainUtxo` components must point to the recent main UTXO
|
|
332
336
|
/// of the given wallet, as currently known on the Ethereum chain.
|
|
333
337
|
/// If there is no main UTXO, this parameter is ignored.
|
|
334
|
-
function
|
|
338
|
+
function submitDepositSweepProof(
|
|
335
339
|
BitcoinTx.Info calldata sweepTx,
|
|
336
340
|
BitcoinTx.Proof calldata sweepProof,
|
|
337
341
|
BitcoinTx.UTXO calldata mainUtxo
|
|
338
342
|
) external {
|
|
339
|
-
self.
|
|
343
|
+
self.submitDepositSweepProof(sweepTx, sweepProof, mainUtxo);
|
|
340
344
|
}
|
|
341
345
|
|
|
342
346
|
/// @notice Requests redemption of the given amount from the specified
|
|
@@ -641,6 +645,53 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
641
645
|
self.notifyMovingFundsBelowDust(walletPubKeyHash, mainUtxo);
|
|
642
646
|
}
|
|
643
647
|
|
|
648
|
+
/// @notice Used by the wallet to prove the BTC moved funds sweep
|
|
649
|
+
/// transaction and to make the necessary state changes. Moved
|
|
650
|
+
/// funds sweep is only accepted if it satisfies SPV proof.
|
|
651
|
+
///
|
|
652
|
+
/// The function validates the sweep transaction structure by
|
|
653
|
+
/// checking if it actually spends the moved funds UTXO and the
|
|
654
|
+
/// sweeping wallet's main UTXO (optionally), and if it locks the
|
|
655
|
+
/// value on the sweeping wallet's 20-byte public key hash using a
|
|
656
|
+
/// reasonable transaction fee. If all preconditions are
|
|
657
|
+
/// met, this function updates the sweeping wallet main UTXO, thus
|
|
658
|
+
/// their BTC balance.
|
|
659
|
+
///
|
|
660
|
+
/// It is possible to prove the given sweep transaction only
|
|
661
|
+
/// one time.
|
|
662
|
+
/// @param sweepTx Bitcoin sweep funds transaction data
|
|
663
|
+
/// @param sweepProof Bitcoin sweep funds proof data
|
|
664
|
+
/// @param mainUtxo Data of the sweeping wallet's main UTXO, as currently
|
|
665
|
+
/// known on the Ethereum chain
|
|
666
|
+
/// @dev Requirements:
|
|
667
|
+
/// - `sweepTx` components must match the expected structure. See
|
|
668
|
+
/// `BitcoinTx.Info` docs for reference. Their values must exactly
|
|
669
|
+
/// correspond to appropriate Bitcoin transaction fields to produce
|
|
670
|
+
/// a provable transaction hash.
|
|
671
|
+
/// - The `sweepTx` should represent a Bitcoin transaction with
|
|
672
|
+
/// the first input pointing to a moved funds sweep request targeted
|
|
673
|
+
/// to the wallet, and optionally, the second input pointing to the
|
|
674
|
+
/// wallet's main UTXO, if the sweeping wallet has a main UTXO set.
|
|
675
|
+
/// There should be only one output locking funds on the sweeping
|
|
676
|
+
/// wallet 20-byte public key hash.
|
|
677
|
+
/// - `sweepProof` components must match the expected structure.
|
|
678
|
+
/// See `BitcoinTx.Proof` docs for reference. The `bitcoinHeaders`
|
|
679
|
+
/// field must contain a valid number of block headers, not less
|
|
680
|
+
/// than the `txProofDifficultyFactor` contract constant.
|
|
681
|
+
/// - `mainUtxo` components must point to the recent main UTXO
|
|
682
|
+
/// of the sweeping wallet, as currently known on the Ethereum chain.
|
|
683
|
+
/// If there is no main UTXO, this parameter is ignored.
|
|
684
|
+
/// - The sweeping wallet must be in the Live or MovingFunds state.
|
|
685
|
+
/// - The total Bitcoin transaction fee must be lesser or equal
|
|
686
|
+
/// to `movedFundsSweepTxMaxTotalFee` governable parameter.
|
|
687
|
+
function submitMovedFundsSweepProof(
|
|
688
|
+
BitcoinTx.Info calldata sweepTx,
|
|
689
|
+
BitcoinTx.Proof calldata sweepProof,
|
|
690
|
+
BitcoinTx.UTXO calldata mainUtxo
|
|
691
|
+
) external {
|
|
692
|
+
self.submitMovedFundsSweepProof(sweepTx, sweepProof, mainUtxo);
|
|
693
|
+
}
|
|
694
|
+
|
|
644
695
|
/// @notice Requests creation of a new wallet. This function just
|
|
645
696
|
/// forms a request and the creation process is performed
|
|
646
697
|
/// asynchronously. Once a wallet is created, the ECDSA Wallet
|
|
@@ -998,25 +1049,33 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
998
1049
|
/// it determines the percentage of the notifier reward from the
|
|
999
1050
|
/// staking contact the notifier of a moving funds timeout receives.
|
|
1000
1051
|
/// The value must be in the range [0, 100]
|
|
1052
|
+
/// @param movedFundsSweepTxMaxTotalFee New value of the moved funds sweep
|
|
1053
|
+
/// transaction max total fee in satoshis. It is the maximum amount
|
|
1054
|
+
/// of the total BTC transaction fee that is acceptable in a single
|
|
1055
|
+
/// moved funds sweep transaction. This is a _total_ max fee for the
|
|
1056
|
+
/// entire moved funds sweep transaction.
|
|
1001
1057
|
/// @dev Requirements:
|
|
1002
1058
|
/// - Moving funds transaction max total fee must be greater than zero
|
|
1003
1059
|
/// - Moving funds dust threshold must be greater than zero
|
|
1004
1060
|
/// - Moving funds timeout must be greater than zero
|
|
1005
1061
|
/// - Moving funds timeout notifier reward multiplier must be in the
|
|
1006
1062
|
/// range [0, 100]
|
|
1063
|
+
/// - Moved funds sweep transaction max total fee must be greater than zero
|
|
1007
1064
|
function updateMovingFundsParameters(
|
|
1008
1065
|
uint64 movingFundsTxMaxTotalFee,
|
|
1009
1066
|
uint64 movingFundsDustThreshold,
|
|
1010
1067
|
uint32 movingFundsTimeout,
|
|
1011
1068
|
uint96 movingFundsTimeoutSlashingAmount,
|
|
1012
|
-
uint256 movingFundsTimeoutNotifierRewardMultiplier
|
|
1069
|
+
uint256 movingFundsTimeoutNotifierRewardMultiplier,
|
|
1070
|
+
uint64 movedFundsSweepTxMaxTotalFee
|
|
1013
1071
|
) external onlyGovernance {
|
|
1014
1072
|
self.updateMovingFundsParameters(
|
|
1015
1073
|
movingFundsTxMaxTotalFee,
|
|
1016
1074
|
movingFundsDustThreshold,
|
|
1017
1075
|
movingFundsTimeout,
|
|
1018
1076
|
movingFundsTimeoutSlashingAmount,
|
|
1019
|
-
movingFundsTimeoutNotifierRewardMultiplier
|
|
1077
|
+
movingFundsTimeoutNotifierRewardMultiplier,
|
|
1078
|
+
movedFundsSweepTxMaxTotalFee
|
|
1020
1079
|
);
|
|
1021
1080
|
}
|
|
1022
1081
|
|
|
@@ -1200,6 +1259,23 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
1200
1259
|
return self.fraudChallenges[challengeKey];
|
|
1201
1260
|
}
|
|
1202
1261
|
|
|
1262
|
+
/// @notice Collection of all moved funds sweep requests indexed by
|
|
1263
|
+
/// `keccak256(movingFundsTxHash | movingFundsOutputIndex)`.
|
|
1264
|
+
/// The `movingFundsTxHash` is `bytes32` (ordered as in Bitcoin
|
|
1265
|
+
/// internally) and `movingFundsOutputIndex` an `uint32`. Each entry
|
|
1266
|
+
/// is actually an UTXO representing the moved funds and is supposed
|
|
1267
|
+
/// to be swept with the current main UTXO of the recipient wallet.
|
|
1268
|
+
/// @param requestKey Request key built as
|
|
1269
|
+
/// `keccak256(movingFundsTxHash | movingFundsOutputIndex)`
|
|
1270
|
+
/// @return Details of the moved funds sweep request.
|
|
1271
|
+
function movedFundsSweepRequests(uint256 requestKey)
|
|
1272
|
+
external
|
|
1273
|
+
view
|
|
1274
|
+
returns (MovingFunds.MovedFundsSweepRequest memory)
|
|
1275
|
+
{
|
|
1276
|
+
return self.movedFundsSweepRequests[requestKey];
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1203
1279
|
/// @notice Indicates if the vault with the given address is trusted or not.
|
|
1204
1280
|
/// Depositors can route their revealed deposits only to trusted
|
|
1205
1281
|
/// vaults and have trusted vaults notified about new deposits as
|
|
@@ -1313,6 +1389,10 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
1313
1389
|
/// @return movingFundsTimeoutNotifierRewardMultiplier The percentage of the
|
|
1314
1390
|
/// notifier reward from the staking contract the notifier of a
|
|
1315
1391
|
/// moving funds timeout receives. The value is in the range [0, 100].
|
|
1392
|
+
/// @return movedFundsSweepTxMaxTotalFee Maximum amount of the total BTC
|
|
1393
|
+
/// transaction fee that is acceptable in a single moved funds
|
|
1394
|
+
/// sweep transaction. This is a _total_ max fee for the entire
|
|
1395
|
+
/// moved funds sweep transaction.
|
|
1316
1396
|
function movingFundsParameters()
|
|
1317
1397
|
external
|
|
1318
1398
|
view
|
|
@@ -1321,7 +1401,8 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
1321
1401
|
uint64 movingFundsDustThreshold,
|
|
1322
1402
|
uint32 movingFundsTimeout,
|
|
1323
1403
|
uint96 movingFundsTimeoutSlashingAmount,
|
|
1324
|
-
uint256 movingFundsTimeoutNotifierRewardMultiplier
|
|
1404
|
+
uint256 movingFundsTimeoutNotifierRewardMultiplier,
|
|
1405
|
+
uint64 movedFundsSweepTxMaxTotalFee
|
|
1325
1406
|
)
|
|
1326
1407
|
{
|
|
1327
1408
|
movingFundsTxMaxTotalFee = self.movingFundsTxMaxTotalFee;
|
|
@@ -1331,6 +1412,7 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
1331
1412
|
.movingFundsTimeoutSlashingAmount;
|
|
1332
1413
|
movingFundsTimeoutNotifierRewardMultiplier = self
|
|
1333
1414
|
.movingFundsTimeoutNotifierRewardMultiplier;
|
|
1415
|
+
movedFundsSweepTxMaxTotalFee = self.movedFundsSweepTxMaxTotalFee;
|
|
1334
1416
|
}
|
|
1335
1417
|
|
|
1336
1418
|
/// @return walletCreationPeriod Determines how frequently a new wallet
|
|
@@ -22,6 +22,7 @@ import "./Deposit.sol";
|
|
|
22
22
|
import "./Redemption.sol";
|
|
23
23
|
import "./Fraud.sol";
|
|
24
24
|
import "./Wallets.sol";
|
|
25
|
+
import "./MovingFunds.sol";
|
|
25
26
|
|
|
26
27
|
import "../bank/Bank.sol";
|
|
27
28
|
|
|
@@ -101,6 +102,21 @@ library BridgeState {
|
|
|
101
102
|
// the notifier of a moving funds timeout receives. The value is in the
|
|
102
103
|
// range [0, 100].
|
|
103
104
|
uint256 movingFundsTimeoutNotifierRewardMultiplier;
|
|
105
|
+
// Maximum amount of the total BTC transaction fee that is acceptable in
|
|
106
|
+
// a single moved funds sweep transaction.
|
|
107
|
+
//
|
|
108
|
+
// This is a TOTAL max fee for the moved funds sweep transaction. Note
|
|
109
|
+
// that `depositTxMaxFee` is per single deposit and `redemptionTxMaxFee`
|
|
110
|
+
// if per single redemption. `movedFundsSweepTxMaxTotalFee` is a total
|
|
111
|
+
// fee for the entire transaction.
|
|
112
|
+
uint64 movedFundsSweepTxMaxTotalFee;
|
|
113
|
+
// Collection of all moved funds sweep requests indexed by
|
|
114
|
+
// `keccak256(movingFundsTxHash | movingFundsOutputIndex)`.
|
|
115
|
+
// The `movingFundsTxHash` is `bytes32` (ordered as in Bitcoin
|
|
116
|
+
// internally) and `movingFundsOutputIndex` an `uint32`. Each entry
|
|
117
|
+
// is actually an UTXO representing the moved funds and is supposed
|
|
118
|
+
// to be swept with the current main UTXO of the recipient wallet.
|
|
119
|
+
mapping(uint256 => MovingFunds.MovedFundsSweepRequest) movedFundsSweepRequests;
|
|
104
120
|
// The minimal amount that can be requested for redemption.
|
|
105
121
|
// Value of this parameter must take into account the value of
|
|
106
122
|
// `redemptionTreasuryFeeDivisor` and `redemptionTxMaxFee`
|
|
@@ -246,7 +262,8 @@ library BridgeState {
|
|
|
246
262
|
uint64 movingFundsDustThreshold,
|
|
247
263
|
uint32 movingFundsTimeout,
|
|
248
264
|
uint96 movingFundsTimeoutSlashingAmount,
|
|
249
|
-
uint256 movingFundsTimeoutNotifierRewardMultiplier
|
|
265
|
+
uint256 movingFundsTimeoutNotifierRewardMultiplier,
|
|
266
|
+
uint64 movedFundsSweepTxMaxTotalFee
|
|
250
267
|
);
|
|
251
268
|
|
|
252
269
|
event WalletParametersUpdated(
|
|
@@ -444,19 +461,26 @@ library BridgeState {
|
|
|
444
461
|
/// it determines the percentage of the notifier reward from the
|
|
445
462
|
/// staking contact the notifier of a moving funds timeout receives.
|
|
446
463
|
/// The value must be in the range [0, 100]
|
|
464
|
+
/// @param _movedFundsSweepTxMaxTotalFee New value of the moved funds sweep
|
|
465
|
+
/// transaction max total fee in satoshis. It is the maximum amount
|
|
466
|
+
/// of the total BTC transaction fee that is acceptable in a single
|
|
467
|
+
/// moved funds sweep transaction. This is a _total_ max fee for the
|
|
468
|
+
/// entire moved funds sweep transaction.
|
|
447
469
|
/// @dev Requirements:
|
|
448
470
|
/// - Moving funds transaction max total fee must be greater than zero
|
|
449
471
|
/// - Moving funds dust threshold must be greater than zero
|
|
450
472
|
/// - Moving funds timeout must be greater than zero
|
|
451
473
|
/// - Moving funds timeout notifier reward multiplier must be in the
|
|
452
474
|
/// range [0, 100]
|
|
475
|
+
/// - Moved funds sweep transaction max total fee must be greater than zero
|
|
453
476
|
function updateMovingFundsParameters(
|
|
454
477
|
Storage storage self,
|
|
455
478
|
uint64 _movingFundsTxMaxTotalFee,
|
|
456
479
|
uint64 _movingFundsDustThreshold,
|
|
457
480
|
uint32 _movingFundsTimeout,
|
|
458
481
|
uint96 _movingFundsTimeoutSlashingAmount,
|
|
459
|
-
uint256 _movingFundsTimeoutNotifierRewardMultiplier
|
|
482
|
+
uint256 _movingFundsTimeoutNotifierRewardMultiplier,
|
|
483
|
+
uint64 _movedFundsSweepTxMaxTotalFee
|
|
460
484
|
) internal {
|
|
461
485
|
require(
|
|
462
486
|
_movingFundsTxMaxTotalFee > 0,
|
|
@@ -478,6 +502,11 @@ library BridgeState {
|
|
|
478
502
|
"Moving funds timeout notifier reward multiplier must be in the range [0, 100]"
|
|
479
503
|
);
|
|
480
504
|
|
|
505
|
+
require(
|
|
506
|
+
_movedFundsSweepTxMaxTotalFee > 0,
|
|
507
|
+
"Moved funds sweep transaction max total fee must be greater than zero"
|
|
508
|
+
);
|
|
509
|
+
|
|
481
510
|
self.movingFundsTxMaxTotalFee = _movingFundsTxMaxTotalFee;
|
|
482
511
|
self.movingFundsDustThreshold = _movingFundsDustThreshold;
|
|
483
512
|
self.movingFundsTimeout = _movingFundsTimeout;
|
|
@@ -485,13 +514,15 @@ library BridgeState {
|
|
|
485
514
|
.movingFundsTimeoutSlashingAmount = _movingFundsTimeoutSlashingAmount;
|
|
486
515
|
self
|
|
487
516
|
.movingFundsTimeoutNotifierRewardMultiplier = _movingFundsTimeoutNotifierRewardMultiplier;
|
|
517
|
+
self.movedFundsSweepTxMaxTotalFee = _movedFundsSweepTxMaxTotalFee;
|
|
488
518
|
|
|
489
519
|
emit MovingFundsParametersUpdated(
|
|
490
520
|
_movingFundsTxMaxTotalFee,
|
|
491
521
|
_movingFundsDustThreshold,
|
|
492
522
|
_movingFundsTimeout,
|
|
493
523
|
_movingFundsTimeoutSlashingAmount,
|
|
494
|
-
_movingFundsTimeoutNotifierRewardMultiplier
|
|
524
|
+
_movingFundsTimeoutNotifierRewardMultiplier,
|
|
525
|
+
_movedFundsSweepTxMaxTotalFee
|
|
495
526
|
);
|
|
496
527
|
}
|
|
497
528
|
|
|
@@ -33,7 +33,7 @@ import "../bank/Bank.sol";
|
|
|
33
33
|
/// This has two main effects: it consolidates the UTXO set and it disables
|
|
34
34
|
/// the refund. Balances of depositors in the Bank are increased when the
|
|
35
35
|
/// SPV sweep proof is submitted to the Bridge.
|
|
36
|
-
library
|
|
36
|
+
library DepositSweep {
|
|
37
37
|
using BridgeState for BridgeState.Storage;
|
|
38
38
|
using BitcoinTx for BridgeState.Storage;
|
|
39
39
|
|
|
@@ -41,7 +41,7 @@ library Sweep {
|
|
|
41
41
|
|
|
42
42
|
/// @notice Represents an outcome of the sweep Bitcoin transaction
|
|
43
43
|
/// inputs processing.
|
|
44
|
-
struct
|
|
44
|
+
struct DepositSweepTxInputsInfo {
|
|
45
45
|
// Sum of all inputs values i.e. all deposits and main UTXO value,
|
|
46
46
|
// if present.
|
|
47
47
|
uint256 inputsTotalValue;
|
|
@@ -103,7 +103,7 @@ library Sweep {
|
|
|
103
103
|
/// - `mainUtxo` components must point to the recent main UTXO
|
|
104
104
|
/// of the given wallet, as currently known on the Ethereum chain.
|
|
105
105
|
/// If there is no main UTXO, this parameter is ignored.
|
|
106
|
-
function
|
|
106
|
+
function submitDepositSweepProof(
|
|
107
107
|
BridgeState.Storage storage self,
|
|
108
108
|
BitcoinTx.Info calldata sweepTx,
|
|
109
109
|
BitcoinTx.Proof calldata sweepProof,
|
|
@@ -120,20 +120,21 @@ library Sweep {
|
|
|
120
120
|
(
|
|
121
121
|
bytes20 walletPubKeyHash,
|
|
122
122
|
uint64 sweepTxOutputValue
|
|
123
|
-
) =
|
|
123
|
+
) = processDepositSweepTxOutput(sweepTx.outputVector);
|
|
124
124
|
|
|
125
125
|
(
|
|
126
126
|
Wallets.Wallet storage wallet,
|
|
127
127
|
BitcoinTx.UTXO memory resolvedMainUtxo
|
|
128
|
-
) =
|
|
128
|
+
) = resolveDepositSweepingWallet(self, walletPubKeyHash, mainUtxo);
|
|
129
129
|
|
|
130
130
|
// Process sweep transaction inputs and extract all information needed
|
|
131
131
|
// to perform deposit bookkeeping.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
DepositSweepTxInputsInfo
|
|
133
|
+
memory inputsInfo = processDepositSweepTxInputs(
|
|
134
|
+
self,
|
|
135
|
+
sweepTx.inputVector,
|
|
136
|
+
resolvedMainUtxo
|
|
137
|
+
);
|
|
137
138
|
|
|
138
139
|
// Helper variable that will hold the sum of treasury fees paid by
|
|
139
140
|
// all deposits.
|
|
@@ -145,7 +146,7 @@ library Sweep {
|
|
|
145
146
|
(
|
|
146
147
|
uint256 depositTxFee,
|
|
147
148
|
uint256 depositTxFeeRemainder
|
|
148
|
-
) =
|
|
149
|
+
) = depositSweepTxFeeDistribution(
|
|
149
150
|
inputsInfo.inputsTotalValue,
|
|
150
151
|
sweepTxOutputValue,
|
|
151
152
|
inputsInfo.depositedAmounts.length
|
|
@@ -206,11 +207,16 @@ library Sweep {
|
|
|
206
207
|
/// @param mainUtxo Data of the wallet's main UTXO, as currently known on
|
|
207
208
|
/// the Ethereum chain. If no main UTXO exists for the given wallet,
|
|
208
209
|
/// this parameter is ignored
|
|
210
|
+
/// @return wallet Data of the sweeping wallet.
|
|
211
|
+
/// @return resolvedMainUtxo The actual main UTXO of the sweeping wallet
|
|
212
|
+
/// resolved by cross-checking the `mainUtxo` parameter with
|
|
213
|
+
/// the chain state. If the validation went well, this is the
|
|
214
|
+
/// plain-text main UTXO corresponding to the `wallet.mainUtxoHash`.
|
|
209
215
|
/// @dev Requirements:
|
|
210
216
|
/// - Sweeping wallet must be either in Live or MovingFunds state.
|
|
211
217
|
/// - If the main UTXO of the sweeping wallet exists in the storage,
|
|
212
218
|
/// the passed `mainUTXO` parameter must be equal to the stored one.
|
|
213
|
-
function
|
|
219
|
+
function resolveDepositSweepingWallet(
|
|
214
220
|
BridgeState.Storage storage self,
|
|
215
221
|
bytes20 walletPubKeyHash,
|
|
216
222
|
BitcoinTx.UTXO calldata mainUtxo
|
|
@@ -261,7 +267,7 @@ library Sweep {
|
|
|
261
267
|
/// it is passed here
|
|
262
268
|
/// @return walletPubKeyHash 20-byte wallet public key hash.
|
|
263
269
|
/// @return value 8-byte sweep transaction output value.
|
|
264
|
-
function
|
|
270
|
+
function processDepositSweepTxOutput(bytes memory sweepTxOutputVector)
|
|
265
271
|
internal
|
|
266
272
|
pure
|
|
267
273
|
returns (bytes20 walletPubKeyHash, uint64 value)
|
|
@@ -282,6 +288,8 @@ library Sweep {
|
|
|
282
288
|
|
|
283
289
|
bytes memory output = sweepTxOutputVector.extractOutputAtIndex(0);
|
|
284
290
|
value = output.extractValue();
|
|
291
|
+
// TODO: Extract `walletPubKeyHash` using `self.extractPubKeyHash`
|
|
292
|
+
// in order to get stronger validation.
|
|
285
293
|
bytes memory walletPubKeyHashBytes = output.extractHash();
|
|
286
294
|
// The sweep transaction output should always be P2PKH or P2WPKH.
|
|
287
295
|
// In both cases, the wallet public key hash should be 20 bytes length.
|
|
@@ -311,11 +319,11 @@ library Sweep {
|
|
|
311
319
|
/// exists for the given the wallet, this parameter's fields should
|
|
312
320
|
/// be zeroed to bypass the main UTXO validation
|
|
313
321
|
/// @return info Outcomes of the processing.
|
|
314
|
-
function
|
|
322
|
+
function processDepositSweepTxInputs(
|
|
315
323
|
BridgeState.Storage storage self,
|
|
316
324
|
bytes memory sweepTxInputVector,
|
|
317
325
|
BitcoinTx.UTXO memory mainUtxo
|
|
318
|
-
) internal returns (
|
|
326
|
+
) internal returns (DepositSweepTxInputsInfo memory info) {
|
|
319
327
|
// If the passed `mainUtxo` parameter's values are zeroed, the main UTXO
|
|
320
328
|
// for the given wallet doesn't exist and it is not expected to be
|
|
321
329
|
// included in the sweep transaction input vector.
|
|
@@ -365,7 +373,10 @@ library Sweep {
|
|
|
365
373
|
bytes32 outpointTxHash,
|
|
366
374
|
uint32 outpointIndex,
|
|
367
375
|
uint256 inputLength
|
|
368
|
-
) =
|
|
376
|
+
) = parseDepositSweepTxInputAt(
|
|
377
|
+
sweepTxInputVector,
|
|
378
|
+
inputStartingIndex
|
|
379
|
+
);
|
|
369
380
|
|
|
370
381
|
Deposit.DepositRequest storage deposit = self.deposits[
|
|
371
382
|
uint256(
|
|
@@ -402,6 +413,7 @@ library Sweep {
|
|
|
402
413
|
} else if (
|
|
403
414
|
mainUtxoExpected != mainUtxoFound &&
|
|
404
415
|
mainUtxo.txHash == outpointTxHash
|
|
416
|
+
// TODO: We probably need to check `mainUtxo.txOutputIndex == outpointIndex` as well.
|
|
405
417
|
) {
|
|
406
418
|
// If we entered here, that means the input was identified as
|
|
407
419
|
// the expected main UTXO.
|
|
@@ -455,7 +467,7 @@ library Sweep {
|
|
|
455
467
|
/// @dev This function assumes vector's structure is valid so it must be
|
|
456
468
|
/// validated using e.g. `BTCUtils.validateVin` function before it
|
|
457
469
|
/// is passed here.
|
|
458
|
-
function
|
|
470
|
+
function parseDepositSweepTxInputAt(
|
|
459
471
|
bytes memory inputVector,
|
|
460
472
|
uint256 inputStartingIndex
|
|
461
473
|
)
|
|
@@ -490,7 +502,7 @@ library Sweep {
|
|
|
490
502
|
/// transaction fee than cannot be distributed over all deposits.
|
|
491
503
|
/// @dev It is up to the caller to decide how the remainder should be
|
|
492
504
|
/// counted in. This function only computes its value.
|
|
493
|
-
function
|
|
505
|
+
function depositSweepTxFeeDistribution(
|
|
494
506
|
uint256 sweepTxInputsTotalValue,
|
|
495
507
|
uint256 sweepTxOutputValue,
|
|
496
508
|
uint256 depositsCount
|