@keep-network/tbtc-v2 0.1.1-dev.95 → 0.1.1-dev.98
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 +8 -8
- package/artifacts/Bridge.json +57 -57
- package/artifacts/Deposit.json +9 -9
- package/artifacts/DepositSweep.json +9 -9
- package/artifacts/EcdsaDkgValidator.json +1 -1
- package/artifacts/EcdsaInactivity.json +1 -1
- package/artifacts/EcdsaSortitionPool.json +2 -2
- 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 +9 -9
- 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/T.json +2 -2
- package/artifacts/TBTC.json +10 -10
- package/artifacts/TBTCToken.json +10 -10
- package/artifacts/TBTCVault.json +15 -15
- package/artifacts/TokenStaking.json +1 -1
- package/artifacts/TokenholderGovernor.json +9 -9
- package/artifacts/TokenholderTimelock.json +8 -8
- package/artifacts/VendingMachine.json +11 -11
- package/artifacts/VendingMachineKeep.json +1 -1
- package/artifacts/VendingMachineNuCypher.json +1 -1
- package/artifacts/WalletRegistry.json +5 -5
- package/artifacts/WalletRegistryGovernance.json +2 -2
- package/artifacts/Wallets.json +9 -9
- package/artifacts/solcInputs/{b1eed895af5ae97fee0102eb17dac6e6.json → becdd5668a2170e95004d124119e4fcb.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/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.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 +103 -103
- package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
- package/build/contracts/bridge/BridgeState.sol/BridgeState.json +2 -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 +1 -1
- package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +2 -2
- 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/Heartbeat.sol/Heartbeat.dbg.json +1 -1
- 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 +2 -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/DonationVault.sol/DonationVault.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 +72 -39
- package/contracts/bridge/Bridge.sol +14 -14
- package/contracts/bridge/BridgeState.sol +83 -75
- package/contracts/bridge/DepositSweep.sol +3 -0
- package/contracts/bridge/Fraud.sol +7 -32
- package/contracts/bridge/MovingFunds.sol +41 -53
- package/contracts/bridge/Redemption.sol +143 -108
- package/contracts/bridge/Wallets.sol +309 -143
- package/export.json +44 -44
- package/package.json +2 -2
|
@@ -42,34 +42,11 @@ library OutboundTx {
|
|
|
42
42
|
/// before it is passed here.
|
|
43
43
|
/// @param mainUtxo Data of the wallet's main UTXO, as currently known on
|
|
44
44
|
/// the Ethereum chain.
|
|
45
|
-
/// @param walletPubKeyHash 20-byte public key hash (computed using Bitcoin
|
|
46
|
-
// HASH160 over the compressed ECDSA public key) of the wallet which
|
|
47
|
-
/// performed the outbound transaction.
|
|
48
45
|
function processWalletOutboundTxInput(
|
|
49
46
|
BridgeState.Storage storage self,
|
|
50
47
|
bytes memory walletOutboundTxInputVector,
|
|
51
|
-
BitcoinTx.UTXO calldata mainUtxo
|
|
52
|
-
bytes20 walletPubKeyHash
|
|
48
|
+
BitcoinTx.UTXO calldata mainUtxo
|
|
53
49
|
) internal {
|
|
54
|
-
// Assert that main UTXO for passed wallet exists in storage.
|
|
55
|
-
bytes32 mainUtxoHash = self
|
|
56
|
-
.registeredWallets[walletPubKeyHash]
|
|
57
|
-
.mainUtxoHash;
|
|
58
|
-
require(mainUtxoHash != bytes32(0), "No main UTXO for given wallet");
|
|
59
|
-
|
|
60
|
-
// Assert that passed main UTXO parameter is the same as in storage and
|
|
61
|
-
// can be used for further processing.
|
|
62
|
-
require(
|
|
63
|
-
keccak256(
|
|
64
|
-
abi.encodePacked(
|
|
65
|
-
mainUtxo.txHash,
|
|
66
|
-
mainUtxo.txOutputIndex,
|
|
67
|
-
mainUtxo.txOutputValue
|
|
68
|
-
)
|
|
69
|
-
) == mainUtxoHash,
|
|
70
|
-
"Invalid main UTXO data"
|
|
71
|
-
);
|
|
72
|
-
|
|
73
50
|
// Assert that the single outbound transaction input actually
|
|
74
51
|
// refers to the wallet's main UTXO.
|
|
75
52
|
(
|
|
@@ -447,16 +424,14 @@ library Redemption {
|
|
|
447
424
|
);
|
|
448
425
|
|
|
449
426
|
// Validate if redeemer output script is a correct standard type
|
|
450
|
-
// (P2PKH, P2WPKH, P2SH or P2WSH). This is done by
|
|
451
|
-
//
|
|
452
|
-
//
|
|
453
|
-
//
|
|
454
|
-
//
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
.encodePacked(bytes8(0), redeemerOutputScript)
|
|
459
|
-
.extractHash();
|
|
427
|
+
// (P2PKH, P2WPKH, P2SH or P2WSH). This is done by using
|
|
428
|
+
// `BTCUtils.extractHashAt` on it. Such a function extracts the payload
|
|
429
|
+
// properly only from standard outputs so if it succeeds, we have a
|
|
430
|
+
// guarantee the redeemer output script is proper. The underlying way
|
|
431
|
+
// of validation is the same as in tBTC v1.
|
|
432
|
+
bytes memory redeemerOutputScriptPayload = redeemerOutputScript
|
|
433
|
+
.extractHashAt(0, redeemerOutputScript.length);
|
|
434
|
+
|
|
460
435
|
require(
|
|
461
436
|
redeemerOutputScriptPayload.length > 0,
|
|
462
437
|
"Redeemer output script must be a standard type"
|
|
@@ -464,8 +439,8 @@ library Redemption {
|
|
|
464
439
|
// Check if the redeemer output script payload does not point to the
|
|
465
440
|
// wallet public key hash.
|
|
466
441
|
require(
|
|
467
|
-
|
|
468
|
-
|
|
442
|
+
redeemerOutputScriptPayload.length != 20 ||
|
|
443
|
+
walletPubKeyHash != redeemerOutputScriptPayload.slice20(0),
|
|
469
444
|
"Redeemer output script must not point to the wallet PKH"
|
|
470
445
|
);
|
|
471
446
|
|
|
@@ -478,8 +453,9 @@ library Redemption {
|
|
|
478
453
|
// and redeemer output script pair. That means there can be only one
|
|
479
454
|
// request asking for redemption from the given wallet to the given
|
|
480
455
|
// BTC script at the same time.
|
|
481
|
-
uint256 redemptionKey =
|
|
482
|
-
|
|
456
|
+
uint256 redemptionKey = getRedemptionKey(
|
|
457
|
+
walletPubKeyHash,
|
|
458
|
+
redeemerOutputScript
|
|
483
459
|
);
|
|
484
460
|
|
|
485
461
|
// Check if given redemption key is not used by a pending redemption.
|
|
@@ -520,6 +496,7 @@ library Redemption {
|
|
|
520
496
|
uint32(block.timestamp)
|
|
521
497
|
);
|
|
522
498
|
|
|
499
|
+
// slither-disable-next-line reentrancy-events
|
|
523
500
|
emit RedemptionRequested(
|
|
524
501
|
walletPubKeyHash,
|
|
525
502
|
redeemerOutputScript,
|
|
@@ -583,6 +560,9 @@ library Redemption {
|
|
|
583
560
|
BitcoinTx.UTXO calldata mainUtxo,
|
|
584
561
|
bytes20 walletPubKeyHash
|
|
585
562
|
) external {
|
|
563
|
+
// Wallet state validation is performed in the `resolveRedeemingWallet`
|
|
564
|
+
// function.
|
|
565
|
+
|
|
586
566
|
// The actual transaction proof is performed here. After that point, we
|
|
587
567
|
// can assume the transaction happened on Bitcoin chain and has
|
|
588
568
|
// a sufficient number of confirmations as determined by
|
|
@@ -592,24 +572,18 @@ library Redemption {
|
|
|
592
572
|
redemptionProof
|
|
593
573
|
);
|
|
594
574
|
|
|
575
|
+
Wallets.Wallet storage wallet = resolveRedeemingWallet(
|
|
576
|
+
self,
|
|
577
|
+
walletPubKeyHash,
|
|
578
|
+
mainUtxo
|
|
579
|
+
);
|
|
580
|
+
|
|
595
581
|
// Process the redemption transaction input. Specifically, check if it
|
|
596
582
|
// refers to the expected wallet's main UTXO.
|
|
597
583
|
OutboundTx.processWalletOutboundTxInput(
|
|
598
584
|
self,
|
|
599
585
|
redemptionTx.inputVector,
|
|
600
|
-
mainUtxo
|
|
601
|
-
walletPubKeyHash
|
|
602
|
-
);
|
|
603
|
-
|
|
604
|
-
Wallets.Wallet storage wallet = self.registeredWallets[
|
|
605
|
-
walletPubKeyHash
|
|
606
|
-
];
|
|
607
|
-
|
|
608
|
-
Wallets.WalletState walletState = wallet.state;
|
|
609
|
-
require(
|
|
610
|
-
walletState == Wallets.WalletState.Live ||
|
|
611
|
-
walletState == Wallets.WalletState.MovingFunds,
|
|
612
|
-
"Wallet must be in Live or MovingFunds state"
|
|
586
|
+
mainUtxo
|
|
613
587
|
);
|
|
614
588
|
|
|
615
589
|
// Process redemption transaction outputs to extract some info required
|
|
@@ -645,6 +619,50 @@ library Redemption {
|
|
|
645
619
|
self.bank.transferBalance(self.treasury, outputsInfo.totalTreasuryFee);
|
|
646
620
|
}
|
|
647
621
|
|
|
622
|
+
/// @notice Resolves redeeming wallet based on the provided wallet public
|
|
623
|
+
/// key hash. Validates the wallet state and current main UTXO, as
|
|
624
|
+
/// currently known on the Ethereum chain.
|
|
625
|
+
/// @param walletPubKeyHash public key hash of the wallet proving the sweep
|
|
626
|
+
/// Bitcoin transaction.
|
|
627
|
+
/// @param mainUtxo Data of the wallet's main UTXO, as currently known on
|
|
628
|
+
/// the Ethereum chain.
|
|
629
|
+
/// @return wallet Data of the sweeping wallet.
|
|
630
|
+
/// @dev Requirements:
|
|
631
|
+
/// - Sweeping wallet must be either in Live or MovingFunds state,
|
|
632
|
+
/// - Main UTXO of the redeeming wallet must exists in the storage,
|
|
633
|
+
/// - The passed `mainUTXO` parameter must be equal to the stored one.
|
|
634
|
+
function resolveRedeemingWallet(
|
|
635
|
+
BridgeState.Storage storage self,
|
|
636
|
+
bytes20 walletPubKeyHash,
|
|
637
|
+
BitcoinTx.UTXO calldata mainUtxo
|
|
638
|
+
) internal view returns (Wallets.Wallet storage wallet) {
|
|
639
|
+
wallet = self.registeredWallets[walletPubKeyHash];
|
|
640
|
+
|
|
641
|
+
// Assert that main UTXO for passed wallet exists in storage.
|
|
642
|
+
bytes32 mainUtxoHash = wallet.mainUtxoHash;
|
|
643
|
+
require(mainUtxoHash != bytes32(0), "No main UTXO for given wallet");
|
|
644
|
+
|
|
645
|
+
// Assert that passed main UTXO parameter is the same as in storage and
|
|
646
|
+
// can be used for further processing.
|
|
647
|
+
require(
|
|
648
|
+
keccak256(
|
|
649
|
+
abi.encodePacked(
|
|
650
|
+
mainUtxo.txHash,
|
|
651
|
+
mainUtxo.txOutputIndex,
|
|
652
|
+
mainUtxo.txOutputValue
|
|
653
|
+
)
|
|
654
|
+
) == mainUtxoHash,
|
|
655
|
+
"Invalid main UTXO data"
|
|
656
|
+
);
|
|
657
|
+
|
|
658
|
+
Wallets.WalletState walletState = wallet.state;
|
|
659
|
+
require(
|
|
660
|
+
walletState == Wallets.WalletState.Live ||
|
|
661
|
+
walletState == Wallets.WalletState.MovingFunds,
|
|
662
|
+
"Wallet must be in Live or MovingFunds state"
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
|
|
648
666
|
/// @notice Processes the Bitcoin redemption transaction output vector.
|
|
649
667
|
/// It extracts each output and tries to identify it as a pending
|
|
650
668
|
/// redemption request, reported timed out request, or change.
|
|
@@ -656,7 +674,7 @@ library Redemption {
|
|
|
656
674
|
/// must be validated using e.g. `BTCUtils.validateVout` function
|
|
657
675
|
/// before it is passed here.
|
|
658
676
|
/// @param walletPubKeyHash 20-byte public key hash (computed using Bitcoin
|
|
659
|
-
|
|
677
|
+
/// HASH160 over the compressed ECDSA public key) of the wallet which
|
|
660
678
|
/// performed the redemption transaction.
|
|
661
679
|
/// @return info Outcomes of the processing.
|
|
662
680
|
function processRedemptionTxOutputs(
|
|
@@ -704,7 +722,7 @@ library Redemption {
|
|
|
704
722
|
// which matches the P2PKH structure as per:
|
|
705
723
|
// https://en.bitcoin.it/wiki/Transaction#Pay-to-PubkeyHash
|
|
706
724
|
bytes32 walletP2PKHScriptKeccak = keccak256(
|
|
707
|
-
abi.encodePacked(
|
|
725
|
+
abi.encodePacked(BitcoinTx.makeP2PKHScript(walletPubKeyHash))
|
|
708
726
|
);
|
|
709
727
|
// The P2WPKH script has the byte format: <0x160014> <20-byte PKH>.
|
|
710
728
|
// According to https://en.bitcoin.it/wiki/Script#Opcodes this translates to:
|
|
@@ -714,7 +732,7 @@ library Redemption {
|
|
|
714
732
|
// which matches the P2WPKH structure as per:
|
|
715
733
|
// https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#P2WPKH
|
|
716
734
|
bytes32 walletP2WPKHScriptKeccak = keccak256(
|
|
717
|
-
abi.encodePacked(
|
|
735
|
+
abi.encodePacked(BitcoinTx.makeP2WPKHScript(walletPubKeyHash))
|
|
718
736
|
);
|
|
719
737
|
|
|
720
738
|
return
|
|
@@ -733,7 +751,7 @@ library Redemption {
|
|
|
733
751
|
|
|
734
752
|
/// @notice Processes all outputs from the redemption transaction. Tries to
|
|
735
753
|
/// identify output as a change output, pending redemption request
|
|
736
|
-
|
|
754
|
+
/// or reported redemption. Reverts if one of the outputs cannot be
|
|
737
755
|
/// recognized properly. Marks each request as processed by removing
|
|
738
756
|
/// them from `pendingRedemptions` mapping.
|
|
739
757
|
/// @param redemptionTxOutputVector Bitcoin redemption transaction output
|
|
@@ -741,7 +759,7 @@ library Redemption {
|
|
|
741
759
|
/// must be validated using e.g. `BTCUtils.validateVout` function
|
|
742
760
|
/// before it is passed here.
|
|
743
761
|
/// @param walletPubKeyHash 20-byte public key hash (computed using Bitcoin
|
|
744
|
-
|
|
762
|
+
/// HASH160 over the compressed ECDSA public key) of the wallet which
|
|
745
763
|
/// performed the redemption transaction.
|
|
746
764
|
/// @param processInfo RedemptionTxOutputsProcessingInfo identifying output
|
|
747
765
|
/// starting index, the number of outputs and possible wallet change
|
|
@@ -765,24 +783,33 @@ library Redemption {
|
|
|
765
783
|
// https://github.com/keep-network/tbtc-v2/issues/257
|
|
766
784
|
uint256 outputLength = redemptionTxOutputVector
|
|
767
785
|
.determineOutputLengthAt(processInfo.outputStartingIndex);
|
|
768
|
-
bytes memory output = redemptionTxOutputVector.slice(
|
|
769
|
-
processInfo.outputStartingIndex,
|
|
770
|
-
outputLength
|
|
771
|
-
);
|
|
772
786
|
|
|
773
787
|
// Extract the value from given output.
|
|
774
|
-
uint64 outputValue =
|
|
788
|
+
uint64 outputValue = redemptionTxOutputVector.extractValueAt(
|
|
789
|
+
processInfo.outputStartingIndex
|
|
790
|
+
);
|
|
791
|
+
|
|
792
|
+
uint256 scriptLength = outputLength - 8;
|
|
793
|
+
|
|
775
794
|
// The output consists of an 8-byte value and a variable length
|
|
776
|
-
// script. To
|
|
795
|
+
// script. To hash that script we slice the output starting from
|
|
777
796
|
// 9th byte until the end.
|
|
778
|
-
|
|
797
|
+
|
|
798
|
+
uint256 outputScriptStart = processInfo.outputStartingIndex + 8;
|
|
799
|
+
|
|
800
|
+
bytes32 outputScriptHash;
|
|
801
|
+
/* solhint-disable-next-line no-inline-assembly */
|
|
802
|
+
assembly {
|
|
803
|
+
outputScriptHash := keccak256(
|
|
804
|
+
add(redemptionTxOutputVector, add(outputScriptStart, 32)),
|
|
805
|
+
scriptLength
|
|
806
|
+
)
|
|
807
|
+
}
|
|
779
808
|
|
|
780
809
|
if (
|
|
781
810
|
resultInfo.changeValue == 0 &&
|
|
782
|
-
(
|
|
783
|
-
processInfo.
|
|
784
|
-
keccak256(outputScript) ==
|
|
785
|
-
processInfo.walletP2WPKHScriptKeccak) &&
|
|
811
|
+
(outputScriptHash == processInfo.walletP2PKHScriptKeccak ||
|
|
812
|
+
outputScriptHash == processInfo.walletP2WPKHScriptKeccak) &&
|
|
786
813
|
outputValue > 0
|
|
787
814
|
) {
|
|
788
815
|
// If we entered here, that means the change output with a
|
|
@@ -797,8 +824,7 @@ library Redemption {
|
|
|
797
824
|
uint64 treasuryFee
|
|
798
825
|
) = processNonChangeRedemptionTxOutput(
|
|
799
826
|
self,
|
|
800
|
-
walletPubKeyHash,
|
|
801
|
-
outputScript,
|
|
827
|
+
_getRedemptionKey(walletPubKeyHash, outputScriptHash),
|
|
802
828
|
outputValue
|
|
803
829
|
);
|
|
804
830
|
resultInfo.totalBurnableValue += burnableValue;
|
|
@@ -829,10 +855,7 @@ library Redemption {
|
|
|
829
855
|
/// requested and reported timed-out redemption.
|
|
830
856
|
/// This function also marks each pending request as processed by
|
|
831
857
|
/// removing them from `pendingRedemptions` mapping.
|
|
832
|
-
/// @param
|
|
833
|
-
// HASH160 over the compressed ECDSA public key) of the wallet which
|
|
834
|
-
/// performed the redemption transaction.
|
|
835
|
-
/// @param outputScript Non-change output script to be processed.
|
|
858
|
+
/// @param redemptionKey Redemption key of the output being processed.
|
|
836
859
|
/// @param outputValue Value of the output being processed.
|
|
837
860
|
/// @return burnableValue The value burnable as a result of processing this
|
|
838
861
|
/// single redemption output. This value needs to be summed up with
|
|
@@ -846,17 +869,9 @@ library Redemption {
|
|
|
846
869
|
/// redemption request.
|
|
847
870
|
function processNonChangeRedemptionTxOutput(
|
|
848
871
|
BridgeState.Storage storage self,
|
|
849
|
-
|
|
850
|
-
bytes memory outputScript,
|
|
872
|
+
uint256 redemptionKey,
|
|
851
873
|
uint64 outputValue
|
|
852
874
|
) internal returns (uint64 burnableValue, uint64 treasuryFee) {
|
|
853
|
-
// This function should be called only if the given output is
|
|
854
|
-
// supposed to represent a redemption. Build the redemption key
|
|
855
|
-
// to perform that check.
|
|
856
|
-
uint256 redemptionKey = uint256(
|
|
857
|
-
keccak256(abi.encodePacked(walletPubKeyHash, outputScript))
|
|
858
|
-
);
|
|
859
|
-
|
|
860
875
|
if (self.pendingRedemptions[redemptionKey].requestedAt != 0) {
|
|
861
876
|
// If we entered here, that means the output was identified
|
|
862
877
|
// as a pending redemption request.
|
|
@@ -956,8 +971,10 @@ library Redemption {
|
|
|
956
971
|
uint32[] calldata walletMembersIDs,
|
|
957
972
|
bytes calldata redeemerOutputScript
|
|
958
973
|
) external {
|
|
959
|
-
|
|
960
|
-
|
|
974
|
+
// Wallet state is validated in `notifyWalletRedemptionTimeout`.
|
|
975
|
+
uint256 redemptionKey = getRedemptionKey(
|
|
976
|
+
walletPubKeyHash,
|
|
977
|
+
redeemerOutputScript
|
|
961
978
|
);
|
|
962
979
|
Redemption.RedemptionRequest memory request = self.pendingRedemptions[
|
|
963
980
|
redemptionKey
|
|
@@ -978,44 +995,62 @@ library Redemption {
|
|
|
978
995
|
request.requestedAmount -
|
|
979
996
|
request.treasuryFee;
|
|
980
997
|
|
|
981
|
-
require(
|
|
982
|
-
wallet.state == Wallets.WalletState.Live ||
|
|
983
|
-
wallet.state == Wallets.WalletState.MovingFunds ||
|
|
984
|
-
wallet.state == Wallets.WalletState.Terminated,
|
|
985
|
-
"Wallet must be in Live, MovingFunds or Terminated state"
|
|
986
|
-
);
|
|
987
|
-
|
|
988
998
|
// It is worth noting that there is no need to check if
|
|
989
999
|
// `timedOutRedemption` mapping already contains the given redemption
|
|
990
1000
|
// key. There is no possibility to re-use a key of a reported timed-out
|
|
991
1001
|
// redemption because the wallet responsible for causing the timeout is
|
|
992
1002
|
// moved to a state that prevents it to receive new redemption requests.
|
|
993
1003
|
|
|
1004
|
+
// Propagate timeout consequences to the wallet
|
|
1005
|
+
self.notifyWalletRedemptionTimeout(walletPubKeyHash, walletMembersIDs);
|
|
1006
|
+
|
|
994
1007
|
// Move the redemption from pending redemptions to timed-out redemptions
|
|
995
1008
|
self.timedOutRedemptions[redemptionKey] = request;
|
|
996
1009
|
delete self.pendingRedemptions[redemptionKey];
|
|
997
1010
|
|
|
998
|
-
if (
|
|
999
|
-
wallet.state == Wallets.WalletState.Live ||
|
|
1000
|
-
wallet.state == Wallets.WalletState.MovingFunds
|
|
1001
|
-
) {
|
|
1002
|
-
// Slash the wallet operators and reward the notifier
|
|
1003
|
-
self.ecdsaWalletRegistry.seize(
|
|
1004
|
-
self.redemptionTimeoutSlashingAmount,
|
|
1005
|
-
self.redemptionTimeoutNotifierRewardMultiplier,
|
|
1006
|
-
msg.sender,
|
|
1007
|
-
wallet.ecdsaWalletID,
|
|
1008
|
-
walletMembersIDs
|
|
1009
|
-
);
|
|
1010
|
-
|
|
1011
|
-
// Propagate timeout consequences to the wallet
|
|
1012
|
-
self.notifyWalletTimedOutRedemption(walletPubKeyHash);
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
1011
|
// slither-disable-next-line reentrancy-events
|
|
1016
1012
|
emit RedemptionTimedOut(walletPubKeyHash, redeemerOutputScript);
|
|
1017
1013
|
|
|
1018
1014
|
// Return the requested amount of tokens to the redeemer
|
|
1019
1015
|
self.bank.transferBalance(request.redeemer, request.requestedAmount);
|
|
1020
1016
|
}
|
|
1017
|
+
|
|
1018
|
+
/// @notice Calculate redemption key without allocations.
|
|
1019
|
+
/// @param walletPubKeyHash the pubkey hash of the wallet.
|
|
1020
|
+
/// @param script the output script of the redemption.
|
|
1021
|
+
/// @return The key = keccak256(keccak256(script), walletPubKeyHash).
|
|
1022
|
+
function getRedemptionKey(bytes20 walletPubKeyHash, bytes memory script)
|
|
1023
|
+
internal
|
|
1024
|
+
pure
|
|
1025
|
+
returns (uint256)
|
|
1026
|
+
{
|
|
1027
|
+
bytes32 scriptHash = keccak256(script);
|
|
1028
|
+
uint256 key;
|
|
1029
|
+
/* solhint-disable-next-line no-inline-assembly */
|
|
1030
|
+
assembly {
|
|
1031
|
+
mstore(0, scriptHash)
|
|
1032
|
+
mstore(32, walletPubKeyHash)
|
|
1033
|
+
key := keccak256(0, 52)
|
|
1034
|
+
}
|
|
1035
|
+
return key;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
/// @notice Finish calculating redemption key without allocations.
|
|
1039
|
+
/// @param walletPubKeyHash the pubkey hash of the wallet.
|
|
1040
|
+
/// @param scriptHash the output script hash of the redemption.
|
|
1041
|
+
/// @return The key = keccak256(scriptHash, walletPubKeyHash).
|
|
1042
|
+
function _getRedemptionKey(bytes20 walletPubKeyHash, bytes32 scriptHash)
|
|
1043
|
+
internal
|
|
1044
|
+
pure
|
|
1045
|
+
returns (uint256)
|
|
1046
|
+
{
|
|
1047
|
+
uint256 key;
|
|
1048
|
+
/* solhint-disable-next-line no-inline-assembly */
|
|
1049
|
+
assembly {
|
|
1050
|
+
mstore(0, scriptHash)
|
|
1051
|
+
mstore(32, walletPubKeyHash)
|
|
1052
|
+
key := keccak256(0, 52)
|
|
1053
|
+
}
|
|
1054
|
+
return key;
|
|
1055
|
+
}
|
|
1021
1056
|
}
|