@keep-network/tbtc-v2 0.1.1-dev.55 → 0.1.1-dev.58
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 +716 -197
- package/artifacts/Deposit.json +9 -9
- package/artifacts/DepositSweep.json +76 -0
- package/artifacts/EcdsaDkgValidator.json +1 -1
- package/artifacts/EcdsaInactivity.json +1 -1
- package/artifacts/Fraud.json +9 -9
- 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 +77 -11
- 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 → 452e42f1afe94d8639a5bf98bed9e151.json} +10 -10
- 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 +375 -103
- package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
- package/build/contracts/bridge/BridgeState.sol/BridgeState.json +26 -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/DepositSweep.sol/DepositSweep.json +30 -0
- 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 +46 -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 +175 -8
- package/contracts/bridge/BridgeState.sol +85 -3
- package/contracts/bridge/{Sweep.sol → DepositSweep.sol} +30 -18
- package/contracts/bridge/MovingFunds.sol +586 -76
- package/contracts/bridge/Wallets.sol +2 -0
- package/deploy/05_deploy_bridge.ts +5 -2
- package/export.json +479 -56
- package/package.json +1 -1
- package/artifacts/Sweep.json +0 -76
- package/build/contracts/bridge/Sweep.sol/Sweep.dbg.json +0 -4
- package/build/contracts/bridge/Sweep.sol/Sweep.json +0 -30
|
@@ -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,14 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
121
121
|
|
|
122
122
|
event MovingFundsBelowDustReported(bytes20 walletPubKeyHash);
|
|
123
123
|
|
|
124
|
+
event MovedFundsSwept(bytes20 walletPubKeyHash, bytes32 sweepTxHash);
|
|
125
|
+
|
|
126
|
+
event MovedFundsSweepTimedOut(
|
|
127
|
+
bytes20 walletPubKeyHash,
|
|
128
|
+
bytes32 movingFundsTxHash,
|
|
129
|
+
uint32 movingFundsTxOutputIndex
|
|
130
|
+
);
|
|
131
|
+
|
|
124
132
|
event NewWalletRequested();
|
|
125
133
|
|
|
126
134
|
event NewWalletRegistered(
|
|
@@ -180,7 +188,11 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
180
188
|
uint64 movingFundsDustThreshold,
|
|
181
189
|
uint32 movingFundsTimeout,
|
|
182
190
|
uint96 movingFundsTimeoutSlashingAmount,
|
|
183
|
-
uint256 movingFundsTimeoutNotifierRewardMultiplier
|
|
191
|
+
uint256 movingFundsTimeoutNotifierRewardMultiplier,
|
|
192
|
+
uint64 movedFundsSweepTxMaxTotalFee,
|
|
193
|
+
uint32 movedFundsSweepTimeout,
|
|
194
|
+
uint96 movedFundsSweepTimeoutSlashingAmount,
|
|
195
|
+
uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
|
|
184
196
|
);
|
|
185
197
|
|
|
186
198
|
event WalletParametersUpdated(
|
|
@@ -239,6 +251,10 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
239
251
|
self.movingFundsTimeout = 7 days;
|
|
240
252
|
self.movingFundsTimeoutSlashingAmount = 10000 * 1e18; // 10000 T
|
|
241
253
|
self.movingFundsTimeoutNotifierRewardMultiplier = 100; //100%
|
|
254
|
+
self.movedFundsSweepTxMaxTotalFee = 10000; // 10000 satoshi
|
|
255
|
+
self.movedFundsSweepTimeout = 7 days;
|
|
256
|
+
self.movedFundsSweepTimeoutSlashingAmount = 10000 * 1e18; // 10000 T
|
|
257
|
+
self.movedFundsSweepTimeoutNotifierRewardMultiplier = 100; //100%
|
|
242
258
|
self.fraudChallengeDepositAmount = 2 ether;
|
|
243
259
|
self.fraudChallengeDefeatTimeout = 7 days;
|
|
244
260
|
self.fraudSlashingAmount = 10000 * 1e18; // 10000 T
|
|
@@ -331,12 +347,12 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
331
347
|
/// - `mainUtxo` components must point to the recent main UTXO
|
|
332
348
|
/// of the given wallet, as currently known on the Ethereum chain.
|
|
333
349
|
/// If there is no main UTXO, this parameter is ignored.
|
|
334
|
-
function
|
|
350
|
+
function submitDepositSweepProof(
|
|
335
351
|
BitcoinTx.Info calldata sweepTx,
|
|
336
352
|
BitcoinTx.Proof calldata sweepProof,
|
|
337
353
|
BitcoinTx.UTXO calldata mainUtxo
|
|
338
354
|
) external {
|
|
339
|
-
self.
|
|
355
|
+
self.submitDepositSweepProof(sweepTx, sweepProof, mainUtxo);
|
|
340
356
|
}
|
|
341
357
|
|
|
342
358
|
/// @notice Requests redemption of the given amount from the specified
|
|
@@ -503,6 +519,7 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
503
519
|
/// @dev Requirements:
|
|
504
520
|
/// - The source wallet must be in the MovingFunds state
|
|
505
521
|
/// - The source wallet must not have pending redemption requests
|
|
522
|
+
/// - The source wallet must not have pending moved funds sweep requests
|
|
506
523
|
/// - The source wallet must not have submitted its commitment already
|
|
507
524
|
/// - The expression `keccak256(abi.encode(walletMembersIDs))` must
|
|
508
525
|
/// be exactly the same as the hash stored under `membersIdsHash`
|
|
@@ -641,6 +658,85 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
641
658
|
self.notifyMovingFundsBelowDust(walletPubKeyHash, mainUtxo);
|
|
642
659
|
}
|
|
643
660
|
|
|
661
|
+
/// @notice Used by the wallet to prove the BTC moved funds sweep
|
|
662
|
+
/// transaction and to make the necessary state changes. Moved
|
|
663
|
+
/// funds sweep is only accepted if it satisfies SPV proof.
|
|
664
|
+
///
|
|
665
|
+
/// The function validates the sweep transaction structure by
|
|
666
|
+
/// checking if it actually spends the moved funds UTXO and the
|
|
667
|
+
/// sweeping wallet's main UTXO (optionally), and if it locks the
|
|
668
|
+
/// value on the sweeping wallet's 20-byte public key hash using a
|
|
669
|
+
/// reasonable transaction fee. If all preconditions are
|
|
670
|
+
/// met, this function updates the sweeping wallet main UTXO, thus
|
|
671
|
+
/// their BTC balance.
|
|
672
|
+
///
|
|
673
|
+
/// It is possible to prove the given sweep transaction only
|
|
674
|
+
/// one time.
|
|
675
|
+
/// @param sweepTx Bitcoin sweep funds transaction data
|
|
676
|
+
/// @param sweepProof Bitcoin sweep funds proof data
|
|
677
|
+
/// @param mainUtxo Data of the sweeping wallet's main UTXO, as currently
|
|
678
|
+
/// known on the Ethereum chain
|
|
679
|
+
/// @dev Requirements:
|
|
680
|
+
/// - `sweepTx` components must match the expected structure. See
|
|
681
|
+
/// `BitcoinTx.Info` docs for reference. Their values must exactly
|
|
682
|
+
/// correspond to appropriate Bitcoin transaction fields to produce
|
|
683
|
+
/// a provable transaction hash.
|
|
684
|
+
/// - The `sweepTx` should represent a Bitcoin transaction with
|
|
685
|
+
/// the first input pointing to a moved funds sweep request targeted
|
|
686
|
+
/// to the wallet, and optionally, the second input pointing to the
|
|
687
|
+
/// wallet's main UTXO, if the sweeping wallet has a main UTXO set.
|
|
688
|
+
/// There should be only one output locking funds on the sweeping
|
|
689
|
+
/// wallet 20-byte public key hash.
|
|
690
|
+
/// - `sweepProof` components must match the expected structure.
|
|
691
|
+
/// See `BitcoinTx.Proof` docs for reference. The `bitcoinHeaders`
|
|
692
|
+
/// field must contain a valid number of block headers, not less
|
|
693
|
+
/// than the `txProofDifficultyFactor` contract constant.
|
|
694
|
+
/// - `mainUtxo` components must point to the recent main UTXO
|
|
695
|
+
/// of the sweeping wallet, as currently known on the Ethereum chain.
|
|
696
|
+
/// If there is no main UTXO, this parameter is ignored.
|
|
697
|
+
/// - The sweeping wallet must be in the Live or MovingFunds state.
|
|
698
|
+
/// - The total Bitcoin transaction fee must be lesser or equal
|
|
699
|
+
/// to `movedFundsSweepTxMaxTotalFee` governable parameter.
|
|
700
|
+
function submitMovedFundsSweepProof(
|
|
701
|
+
BitcoinTx.Info calldata sweepTx,
|
|
702
|
+
BitcoinTx.Proof calldata sweepProof,
|
|
703
|
+
BitcoinTx.UTXO calldata mainUtxo
|
|
704
|
+
) external {
|
|
705
|
+
self.submitMovedFundsSweepProof(sweepTx, sweepProof, mainUtxo);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/// @notice Notifies about a timed out moved funds sweep process. If the
|
|
709
|
+
/// wallet is not terminated yet, that function terminates
|
|
710
|
+
/// the wallet and slashes signing group members as a result.
|
|
711
|
+
/// Marks the given sweep request as TimedOut.
|
|
712
|
+
/// @param movingFundsTxHash 32-byte hash of the moving funds transaction
|
|
713
|
+
/// that caused the sweep request to be created
|
|
714
|
+
/// @param movingFundsTxOutputIndex Index of the moving funds transaction
|
|
715
|
+
/// output that is subject of the sweep request.
|
|
716
|
+
/// @param walletMembersIDs Identifiers of the wallet signing group members
|
|
717
|
+
/// @dev Requirements:
|
|
718
|
+
/// - The moved funds sweep request must be in the Pending state
|
|
719
|
+
/// - The moved funds sweep timeout must be actually exceeded
|
|
720
|
+
/// - The wallet must be either in the Live or MovingFunds or
|
|
721
|
+
/// Terminated state
|
|
722
|
+
/// - The expression `keccak256(abi.encode(walletMembersIDs))` must
|
|
723
|
+
/// be exactly the same as the hash stored under `membersIdsHash`
|
|
724
|
+
/// for the given `walletID`. Those IDs are not directly stored
|
|
725
|
+
/// in the contract for gas efficiency purposes but they can be
|
|
726
|
+
/// read from appropriate `DkgResultSubmitted` and `DkgResultApproved`
|
|
727
|
+
/// events of the `WalletRegistry` contract
|
|
728
|
+
function notifyMovedFundsSweepTimeout(
|
|
729
|
+
bytes32 movingFundsTxHash,
|
|
730
|
+
uint32 movingFundsTxOutputIndex,
|
|
731
|
+
uint32[] calldata walletMembersIDs
|
|
732
|
+
) external {
|
|
733
|
+
self.notifyMovedFundsSweepTimeout(
|
|
734
|
+
movingFundsTxHash,
|
|
735
|
+
movingFundsTxOutputIndex,
|
|
736
|
+
walletMembersIDs
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
|
|
644
740
|
/// @notice Requests creation of a new wallet. This function just
|
|
645
741
|
/// forms a request and the creation process is performed
|
|
646
742
|
/// asynchronously. Once a wallet is created, the ECDSA Wallet
|
|
@@ -998,25 +1094,55 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
998
1094
|
/// it determines the percentage of the notifier reward from the
|
|
999
1095
|
/// staking contact the notifier of a moving funds timeout receives.
|
|
1000
1096
|
/// The value must be in the range [0, 100]
|
|
1097
|
+
/// @param movedFundsSweepTxMaxTotalFee New value of the moved funds sweep
|
|
1098
|
+
/// transaction max total fee in satoshis. It is the maximum amount
|
|
1099
|
+
/// of the total BTC transaction fee that is acceptable in a single
|
|
1100
|
+
/// moved funds sweep transaction. This is a _total_ max fee for the
|
|
1101
|
+
/// entire moved funds sweep transaction.
|
|
1102
|
+
/// @param movedFundsSweepTimeout New value of the moved funds sweep
|
|
1103
|
+
/// timeout in seconds. It is the time after which the moved funds
|
|
1104
|
+
/// sweep process can be reported as timed out. It is counted from
|
|
1105
|
+
/// the moment when the wallet was requested to sweep the received
|
|
1106
|
+
/// funds.
|
|
1107
|
+
/// @param movedFundsSweepTimeoutSlashingAmount New value of the moved
|
|
1108
|
+
/// funds sweep timeout slashing amount in T, it is the amount
|
|
1109
|
+
/// slashed from each wallet member for moved funds sweep timeout
|
|
1110
|
+
/// @param movedFundsSweepTimeoutNotifierRewardMultiplier New value of
|
|
1111
|
+
/// the moved funds sweep timeout notifier reward multiplier as
|
|
1112
|
+
/// percentage, it determines the percentage of the notifier reward
|
|
1113
|
+
/// from the staking contact the notifier of a moved funds sweep
|
|
1114
|
+
/// timeout receives. The value must be in the range [0, 100]
|
|
1001
1115
|
/// @dev Requirements:
|
|
1002
1116
|
/// - Moving funds transaction max total fee must be greater than zero
|
|
1003
1117
|
/// - Moving funds dust threshold must be greater than zero
|
|
1004
1118
|
/// - Moving funds timeout must be greater than zero
|
|
1005
1119
|
/// - Moving funds timeout notifier reward multiplier must be in the
|
|
1006
1120
|
/// range [0, 100]
|
|
1121
|
+
/// - Moved funds sweep transaction max total fee must be greater than zero
|
|
1122
|
+
/// - Moved funds sweep timeout must be greater than zero
|
|
1123
|
+
/// - Moved funds sweep timeout notifier reward multiplier must be in the
|
|
1124
|
+
/// range [0, 100]
|
|
1007
1125
|
function updateMovingFundsParameters(
|
|
1008
1126
|
uint64 movingFundsTxMaxTotalFee,
|
|
1009
1127
|
uint64 movingFundsDustThreshold,
|
|
1010
1128
|
uint32 movingFundsTimeout,
|
|
1011
1129
|
uint96 movingFundsTimeoutSlashingAmount,
|
|
1012
|
-
uint256 movingFundsTimeoutNotifierRewardMultiplier
|
|
1130
|
+
uint256 movingFundsTimeoutNotifierRewardMultiplier,
|
|
1131
|
+
uint64 movedFundsSweepTxMaxTotalFee,
|
|
1132
|
+
uint32 movedFundsSweepTimeout,
|
|
1133
|
+
uint96 movedFundsSweepTimeoutSlashingAmount,
|
|
1134
|
+
uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
|
|
1013
1135
|
) external onlyGovernance {
|
|
1014
1136
|
self.updateMovingFundsParameters(
|
|
1015
1137
|
movingFundsTxMaxTotalFee,
|
|
1016
1138
|
movingFundsDustThreshold,
|
|
1017
1139
|
movingFundsTimeout,
|
|
1018
1140
|
movingFundsTimeoutSlashingAmount,
|
|
1019
|
-
movingFundsTimeoutNotifierRewardMultiplier
|
|
1141
|
+
movingFundsTimeoutNotifierRewardMultiplier,
|
|
1142
|
+
movedFundsSweepTxMaxTotalFee,
|
|
1143
|
+
movedFundsSweepTimeout,
|
|
1144
|
+
movedFundsSweepTimeoutSlashingAmount,
|
|
1145
|
+
movedFundsSweepTimeoutNotifierRewardMultiplier
|
|
1020
1146
|
);
|
|
1021
1147
|
}
|
|
1022
1148
|
|
|
@@ -1200,6 +1326,23 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
1200
1326
|
return self.fraudChallenges[challengeKey];
|
|
1201
1327
|
}
|
|
1202
1328
|
|
|
1329
|
+
/// @notice Collection of all moved funds sweep requests indexed by
|
|
1330
|
+
/// `keccak256(movingFundsTxHash | movingFundsOutputIndex)`.
|
|
1331
|
+
/// The `movingFundsTxHash` is `bytes32` (ordered as in Bitcoin
|
|
1332
|
+
/// internally) and `movingFundsOutputIndex` an `uint32`. Each entry
|
|
1333
|
+
/// is actually an UTXO representing the moved funds and is supposed
|
|
1334
|
+
/// to be swept with the current main UTXO of the recipient wallet.
|
|
1335
|
+
/// @param requestKey Request key built as
|
|
1336
|
+
/// `keccak256(movingFundsTxHash | movingFundsOutputIndex)`
|
|
1337
|
+
/// @return Details of the moved funds sweep request.
|
|
1338
|
+
function movedFundsSweepRequests(uint256 requestKey)
|
|
1339
|
+
external
|
|
1340
|
+
view
|
|
1341
|
+
returns (MovingFunds.MovedFundsSweepRequest memory)
|
|
1342
|
+
{
|
|
1343
|
+
return self.movedFundsSweepRequests[requestKey];
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1203
1346
|
/// @notice Indicates if the vault with the given address is trusted or not.
|
|
1204
1347
|
/// Depositors can route their revealed deposits only to trusted
|
|
1205
1348
|
/// vaults and have trusted vaults notified about new deposits as
|
|
@@ -1313,6 +1456,20 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
1313
1456
|
/// @return movingFundsTimeoutNotifierRewardMultiplier The percentage of the
|
|
1314
1457
|
/// notifier reward from the staking contract the notifier of a
|
|
1315
1458
|
/// moving funds timeout receives. The value is in the range [0, 100].
|
|
1459
|
+
/// @return movedFundsSweepTxMaxTotalFee Maximum amount of the total BTC
|
|
1460
|
+
/// transaction fee that is acceptable in a single moved funds
|
|
1461
|
+
/// sweep transaction. This is a _total_ max fee for the entire
|
|
1462
|
+
/// moved funds sweep transaction.
|
|
1463
|
+
/// @return movedFundsSweepTimeout Time after which the moved funds sweep
|
|
1464
|
+
/// process can be reported as timed out. It is counted from the
|
|
1465
|
+
/// moment when the wallet was requested to sweep the received funds.
|
|
1466
|
+
/// Value in seconds.
|
|
1467
|
+
/// @return movedFundsSweepTimeoutSlashingAmount The amount of stake slashed
|
|
1468
|
+
/// from each member of a wallet for a moved funds sweep timeout.
|
|
1469
|
+
/// @return movedFundsSweepTimeoutNotifierRewardMultiplier The percentage
|
|
1470
|
+
/// of the notifier reward from the staking contract the notifier
|
|
1471
|
+
/// of a moved funds sweep timeout receives. The value is in the
|
|
1472
|
+
/// range [0, 100].
|
|
1316
1473
|
function movingFundsParameters()
|
|
1317
1474
|
external
|
|
1318
1475
|
view
|
|
@@ -1321,7 +1478,11 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
1321
1478
|
uint64 movingFundsDustThreshold,
|
|
1322
1479
|
uint32 movingFundsTimeout,
|
|
1323
1480
|
uint96 movingFundsTimeoutSlashingAmount,
|
|
1324
|
-
uint256 movingFundsTimeoutNotifierRewardMultiplier
|
|
1481
|
+
uint256 movingFundsTimeoutNotifierRewardMultiplier,
|
|
1482
|
+
uint64 movedFundsSweepTxMaxTotalFee,
|
|
1483
|
+
uint32 movedFundsSweepTimeout,
|
|
1484
|
+
uint96 movedFundsSweepTimeoutSlashingAmount,
|
|
1485
|
+
uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
|
|
1325
1486
|
)
|
|
1326
1487
|
{
|
|
1327
1488
|
movingFundsTxMaxTotalFee = self.movingFundsTxMaxTotalFee;
|
|
@@ -1331,6 +1492,12 @@ contract Bridge is Governable, EcdsaWalletOwner {
|
|
|
1331
1492
|
.movingFundsTimeoutSlashingAmount;
|
|
1332
1493
|
movingFundsTimeoutNotifierRewardMultiplier = self
|
|
1333
1494
|
.movingFundsTimeoutNotifierRewardMultiplier;
|
|
1495
|
+
movedFundsSweepTxMaxTotalFee = self.movedFundsSweepTxMaxTotalFee;
|
|
1496
|
+
movedFundsSweepTimeout = self.movedFundsSweepTimeout;
|
|
1497
|
+
movedFundsSweepTimeoutSlashingAmount = self
|
|
1498
|
+
.movedFundsSweepTimeoutSlashingAmount;
|
|
1499
|
+
movedFundsSweepTimeoutNotifierRewardMultiplier = self
|
|
1500
|
+
.movedFundsSweepTimeoutNotifierRewardMultiplier;
|
|
1334
1501
|
}
|
|
1335
1502
|
|
|
1336
1503
|
/// @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,32 @@ 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
|
+
// Time after which the moved funds sweep process can be reported as
|
|
114
|
+
// timed out. It is counted from the moment when the recipient wallet
|
|
115
|
+
// was requested to sweep the received funds. Value in seconds.
|
|
116
|
+
uint32 movedFundsSweepTimeout;
|
|
117
|
+
// The amount of stake slashed from each member of a wallet for a moved
|
|
118
|
+
// funds sweep timeout.
|
|
119
|
+
uint96 movedFundsSweepTimeoutSlashingAmount;
|
|
120
|
+
// The percentage of the notifier reward from the staking contract
|
|
121
|
+
// the notifier of a moved funds sweep timeout receives. The value is
|
|
122
|
+
// in the range [0, 100].
|
|
123
|
+
uint256 movedFundsSweepTimeoutNotifierRewardMultiplier;
|
|
124
|
+
// Collection of all moved funds sweep requests indexed by
|
|
125
|
+
// `keccak256(movingFundsTxHash | movingFundsOutputIndex)`.
|
|
126
|
+
// The `movingFundsTxHash` is `bytes32` (ordered as in Bitcoin
|
|
127
|
+
// internally) and `movingFundsOutputIndex` an `uint32`. Each entry
|
|
128
|
+
// is actually an UTXO representing the moved funds and is supposed
|
|
129
|
+
// to be swept with the current main UTXO of the recipient wallet.
|
|
130
|
+
mapping(uint256 => MovingFunds.MovedFundsSweepRequest) movedFundsSweepRequests;
|
|
104
131
|
// The minimal amount that can be requested for redemption.
|
|
105
132
|
// Value of this parameter must take into account the value of
|
|
106
133
|
// `redemptionTreasuryFeeDivisor` and `redemptionTxMaxFee`
|
|
@@ -246,7 +273,11 @@ library BridgeState {
|
|
|
246
273
|
uint64 movingFundsDustThreshold,
|
|
247
274
|
uint32 movingFundsTimeout,
|
|
248
275
|
uint96 movingFundsTimeoutSlashingAmount,
|
|
249
|
-
uint256 movingFundsTimeoutNotifierRewardMultiplier
|
|
276
|
+
uint256 movingFundsTimeoutNotifierRewardMultiplier,
|
|
277
|
+
uint64 movedFundsSweepTxMaxTotalFee,
|
|
278
|
+
uint32 movedFundsSweepTimeout,
|
|
279
|
+
uint96 movedFundsSweepTimeoutSlashingAmount,
|
|
280
|
+
uint256 movedFundsSweepTimeoutNotifierRewardMultiplier
|
|
250
281
|
);
|
|
251
282
|
|
|
252
283
|
event WalletParametersUpdated(
|
|
@@ -444,19 +475,45 @@ library BridgeState {
|
|
|
444
475
|
/// it determines the percentage of the notifier reward from the
|
|
445
476
|
/// staking contact the notifier of a moving funds timeout receives.
|
|
446
477
|
/// The value must be in the range [0, 100]
|
|
478
|
+
/// @param _movedFundsSweepTxMaxTotalFee New value of the moved funds sweep
|
|
479
|
+
/// transaction max total fee in satoshis. It is the maximum amount
|
|
480
|
+
/// of the total BTC transaction fee that is acceptable in a single
|
|
481
|
+
/// moved funds sweep transaction. This is a _total_ max fee for the
|
|
482
|
+
/// entire moved funds sweep transaction.
|
|
483
|
+
/// @param _movedFundsSweepTimeout New value of the moved funds sweep
|
|
484
|
+
/// timeout in seconds. It is the time after which the moved funds
|
|
485
|
+
/// sweep process can be reported as timed out. It is counted from
|
|
486
|
+
/// the moment when the wallet was requested to sweep the received
|
|
487
|
+
/// funds.
|
|
488
|
+
/// @param _movedFundsSweepTimeoutSlashingAmount New value of the moved
|
|
489
|
+
/// funds sweep timeout slashing amount in T, it is the amount
|
|
490
|
+
/// slashed from each wallet member for moved funds sweep timeout
|
|
491
|
+
/// @param _movedFundsSweepTimeoutNotifierRewardMultiplier New value of
|
|
492
|
+
/// the moved funds sweep timeout notifier reward multiplier as
|
|
493
|
+
/// percentage, it determines the percentage of the notifier reward
|
|
494
|
+
/// from the staking contact the notifier of a moved funds sweep
|
|
495
|
+
/// timeout receives. The value must be in the range [0, 100]
|
|
447
496
|
/// @dev Requirements:
|
|
448
497
|
/// - Moving funds transaction max total fee must be greater than zero
|
|
449
498
|
/// - Moving funds dust threshold must be greater than zero
|
|
450
499
|
/// - Moving funds timeout must be greater than zero
|
|
451
500
|
/// - Moving funds timeout notifier reward multiplier must be in the
|
|
452
501
|
/// range [0, 100]
|
|
502
|
+
/// - Moved funds sweep transaction max total fee must be greater than zero
|
|
503
|
+
/// - Moved funds sweep timeout must be greater than zero
|
|
504
|
+
/// - Moved funds sweep timeout notifier reward multiplier must be in the
|
|
505
|
+
/// range [0, 100]
|
|
453
506
|
function updateMovingFundsParameters(
|
|
454
507
|
Storage storage self,
|
|
455
508
|
uint64 _movingFundsTxMaxTotalFee,
|
|
456
509
|
uint64 _movingFundsDustThreshold,
|
|
457
510
|
uint32 _movingFundsTimeout,
|
|
458
511
|
uint96 _movingFundsTimeoutSlashingAmount,
|
|
459
|
-
uint256 _movingFundsTimeoutNotifierRewardMultiplier
|
|
512
|
+
uint256 _movingFundsTimeoutNotifierRewardMultiplier,
|
|
513
|
+
uint64 _movedFundsSweepTxMaxTotalFee,
|
|
514
|
+
uint32 _movedFundsSweepTimeout,
|
|
515
|
+
uint96 _movedFundsSweepTimeoutSlashingAmount,
|
|
516
|
+
uint256 _movedFundsSweepTimeoutNotifierRewardMultiplier
|
|
460
517
|
) internal {
|
|
461
518
|
require(
|
|
462
519
|
_movingFundsTxMaxTotalFee > 0,
|
|
@@ -478,6 +535,21 @@ library BridgeState {
|
|
|
478
535
|
"Moving funds timeout notifier reward multiplier must be in the range [0, 100]"
|
|
479
536
|
);
|
|
480
537
|
|
|
538
|
+
require(
|
|
539
|
+
_movedFundsSweepTxMaxTotalFee > 0,
|
|
540
|
+
"Moved funds sweep transaction max total fee must be greater than zero"
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
require(
|
|
544
|
+
_movedFundsSweepTimeout > 0,
|
|
545
|
+
"Moved funds sweep timeout must be greater than zero"
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
require(
|
|
549
|
+
_movedFundsSweepTimeoutNotifierRewardMultiplier <= 100,
|
|
550
|
+
"Moved funds sweep timeout notifier reward multiplier must be in the range [0, 100]"
|
|
551
|
+
);
|
|
552
|
+
|
|
481
553
|
self.movingFundsTxMaxTotalFee = _movingFundsTxMaxTotalFee;
|
|
482
554
|
self.movingFundsDustThreshold = _movingFundsDustThreshold;
|
|
483
555
|
self.movingFundsTimeout = _movingFundsTimeout;
|
|
@@ -485,13 +557,23 @@ library BridgeState {
|
|
|
485
557
|
.movingFundsTimeoutSlashingAmount = _movingFundsTimeoutSlashingAmount;
|
|
486
558
|
self
|
|
487
559
|
.movingFundsTimeoutNotifierRewardMultiplier = _movingFundsTimeoutNotifierRewardMultiplier;
|
|
560
|
+
self.movedFundsSweepTxMaxTotalFee = _movedFundsSweepTxMaxTotalFee;
|
|
561
|
+
self.movedFundsSweepTimeout = _movedFundsSweepTimeout;
|
|
562
|
+
self
|
|
563
|
+
.movedFundsSweepTimeoutSlashingAmount = _movedFundsSweepTimeoutSlashingAmount;
|
|
564
|
+
self
|
|
565
|
+
.movedFundsSweepTimeoutNotifierRewardMultiplier = _movedFundsSweepTimeoutNotifierRewardMultiplier;
|
|
488
566
|
|
|
489
567
|
emit MovingFundsParametersUpdated(
|
|
490
568
|
_movingFundsTxMaxTotalFee,
|
|
491
569
|
_movingFundsDustThreshold,
|
|
492
570
|
_movingFundsTimeout,
|
|
493
571
|
_movingFundsTimeoutSlashingAmount,
|
|
494
|
-
_movingFundsTimeoutNotifierRewardMultiplier
|
|
572
|
+
_movingFundsTimeoutNotifierRewardMultiplier,
|
|
573
|
+
_movedFundsSweepTxMaxTotalFee,
|
|
574
|
+
_movedFundsSweepTimeout,
|
|
575
|
+
_movedFundsSweepTimeoutSlashingAmount,
|
|
576
|
+
_movedFundsSweepTimeoutNotifierRewardMultiplier
|
|
495
577
|
);
|
|
496
578
|
}
|
|
497
579
|
|
|
@@ -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
|