@keep-network/tbtc-v2 0.1.1-dev.14 → 0.1.1-dev.17
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/TBTC.json +11 -11
- package/artifacts/TBTCToken.json +11 -11
- package/artifacts/VendingMachine.json +18 -18
- package/artifacts/solcInputs/{074b94f943fca615dfc6fce3bc4f2e1f.json → 7ba168d4ff7e401eb795fb23fc07b02f.json} +14 -14
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
- package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
- package/build/contracts/bank/Bank.sol/Bank.json +2 -2
- 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 +3 -3
- package/build/contracts/bridge/Bridge.sol/IRelay.dbg.json +1 -1
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
- package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
- package/build/contracts/token/TBTC.sol/TBTC.json +2 -2
- package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +2 -2
- package/contracts/GovernanceUtils.sol +1 -1
- package/contracts/bank/Bank.sol +18 -17
- package/contracts/bridge/BitcoinTx.sol +1 -1
- package/contracts/bridge/Bridge.sol +138 -140
- package/contracts/bridge/VendingMachine.sol +1 -1
- package/contracts/token/TBTC.sol +1 -1
- package/contracts/vault/IVault.sol +1 -1
- package/contracts/vault/TBTCVault.sol +1 -1
- package/package.json +6 -7
|
@@ -13,15 +13,13 @@
|
|
|
13
13
|
// ▐████▌ ▐████▌
|
|
14
14
|
// ▐████▌ ▐████▌
|
|
15
15
|
|
|
16
|
-
pragma solidity 0.8.
|
|
16
|
+
pragma solidity ^0.8.9;
|
|
17
17
|
|
|
18
18
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
19
19
|
|
|
20
20
|
import {BTCUtils} from "@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol";
|
|
21
21
|
import {BytesLib} from "@keep-network/bitcoin-spv-sol/contracts/BytesLib.sol";
|
|
22
|
-
import {
|
|
23
|
-
ValidateSPV
|
|
24
|
-
} from "@keep-network/bitcoin-spv-sol/contracts/ValidateSPV.sol";
|
|
22
|
+
import {ValidateSPV} from "@keep-network/bitcoin-spv-sol/contracts/ValidateSPV.sol";
|
|
25
23
|
|
|
26
24
|
import "../bank/Bank.sol";
|
|
27
25
|
import "./BitcoinTx.sol";
|
|
@@ -191,15 +189,21 @@ contract Bridge is Ownable {
|
|
|
191
189
|
|
|
192
190
|
/// TODO: Make it governable.
|
|
193
191
|
/// @notice The minimal amount that can be requested for redemption.
|
|
194
|
-
/// Value of this parameter
|
|
195
|
-
///
|
|
196
|
-
///
|
|
192
|
+
/// Value of this parameter must take into account the value of
|
|
193
|
+
/// `redemptionTreasuryFeeDivisor` and `redemptionTxMaxFee`
|
|
194
|
+
/// parameters in order to make requests that can incur the
|
|
195
|
+
/// treasury and transaction fee and still satisfy the redeemer.
|
|
197
196
|
uint64 public redemptionDustThreshold;
|
|
198
197
|
|
|
199
198
|
/// TODO: Make it governable.
|
|
200
|
-
/// @notice
|
|
201
|
-
/// transferred to the treasury upon
|
|
202
|
-
|
|
199
|
+
/// @notice Divisor used to compute the treasury fee taken from each
|
|
200
|
+
/// redemption request and transferred to the treasury upon
|
|
201
|
+
/// successful request finalization. That fee is computed as follows:
|
|
202
|
+
/// `treasuryFee = requestedAmount / redemptionTreasuryFeeDivisor`
|
|
203
|
+
/// For example, if the treasury fee needs to be 2% of each
|
|
204
|
+
/// redemption request, the `redemptionTreasuryFeeDivisor` should
|
|
205
|
+
/// be set to `50` because `1/50 = 0.02 = 2%`.
|
|
206
|
+
uint64 public redemptionTreasuryFeeDivisor;
|
|
203
207
|
|
|
204
208
|
/// TODO: Make it governable.
|
|
205
209
|
/// @notice Maximum amount of BTC transaction fee that can be incurred by
|
|
@@ -336,7 +340,7 @@ contract Bridge is Ownable {
|
|
|
336
340
|
|
|
337
341
|
// TODO: Revisit initial values.
|
|
338
342
|
redemptionDustThreshold = 1000000; // 1000000 satoshi = 0.01 BTC
|
|
339
|
-
|
|
343
|
+
redemptionTreasuryFeeDivisor = 2000; // 1/2000 == 5bps == 0.05% == 0.0005
|
|
340
344
|
redemptionTxMaxFee = 1000; // 1000 satoshi
|
|
341
345
|
redemptionTimeout = 172800; // 48 hours
|
|
342
346
|
}
|
|
@@ -407,39 +411,37 @@ contract Bridge is Ownable {
|
|
|
407
411
|
// TODO: Validate if `walletPubKeyHash` is a known and active wallet.
|
|
408
412
|
// TODO: Should we enforce a specific locktime at contract level?
|
|
409
413
|
|
|
410
|
-
bytes memory expectedScript =
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
);
|
|
414
|
+
bytes memory expectedScript = abi.encodePacked(
|
|
415
|
+
hex"14", // Byte length of depositor Ethereum address.
|
|
416
|
+
reveal.depositor,
|
|
417
|
+
hex"75", // OP_DROP
|
|
418
|
+
hex"08", // Byte length of blinding factor value.
|
|
419
|
+
reveal.blindingFactor,
|
|
420
|
+
hex"75", // OP_DROP
|
|
421
|
+
hex"76", // OP_DUP
|
|
422
|
+
hex"a9", // OP_HASH160
|
|
423
|
+
hex"14", // Byte length of a compressed Bitcoin public key hash.
|
|
424
|
+
reveal.walletPubKeyHash,
|
|
425
|
+
hex"87", // OP_EQUAL
|
|
426
|
+
hex"63", // OP_IF
|
|
427
|
+
hex"ac", // OP_CHECKSIG
|
|
428
|
+
hex"67", // OP_ELSE
|
|
429
|
+
hex"76", // OP_DUP
|
|
430
|
+
hex"a9", // OP_HASH160
|
|
431
|
+
hex"14", // Byte length of a compressed Bitcoin public key hash.
|
|
432
|
+
reveal.refundPubKeyHash,
|
|
433
|
+
hex"88", // OP_EQUALVERIFY
|
|
434
|
+
hex"04", // Byte length of refund locktime value.
|
|
435
|
+
reveal.refundLocktime,
|
|
436
|
+
hex"b1", // OP_CHECKLOCKTIMEVERIFY
|
|
437
|
+
hex"75", // OP_DROP
|
|
438
|
+
hex"ac", // OP_CHECKSIG
|
|
439
|
+
hex"68" // OP_ENDIF
|
|
440
|
+
);
|
|
438
441
|
|
|
439
|
-
bytes memory fundingOutput =
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
);
|
|
442
|
+
bytes memory fundingOutput = fundingTx
|
|
443
|
+
.outputVector
|
|
444
|
+
.extractOutputAtIndex(reveal.fundingOutputIndex);
|
|
443
445
|
bytes memory fundingOutputHash = fundingOutput.extractHash();
|
|
444
446
|
|
|
445
447
|
if (fundingOutputHash.length == 20) {
|
|
@@ -467,31 +469,22 @@ contract Bridge is Ownable {
|
|
|
467
469
|
}
|
|
468
470
|
|
|
469
471
|
// Resulting TX hash is in native Bitcoin little-endian format.
|
|
470
|
-
bytes32 fundingTxHash =
|
|
471
|
-
|
|
472
|
-
.
|
|
473
|
-
fundingTx
|
|
474
|
-
|
|
475
|
-
fundingTx
|
|
476
|
-
.inputVector,
|
|
477
|
-
fundingTx
|
|
478
|
-
.outputVector,
|
|
479
|
-
fundingTx
|
|
480
|
-
.locktime
|
|
472
|
+
bytes32 fundingTxHash = abi
|
|
473
|
+
.encodePacked(
|
|
474
|
+
fundingTx.version,
|
|
475
|
+
fundingTx.inputVector,
|
|
476
|
+
fundingTx.outputVector,
|
|
477
|
+
fundingTx.locktime
|
|
481
478
|
)
|
|
482
|
-
|
|
479
|
+
.hash256View();
|
|
483
480
|
|
|
484
|
-
DepositRequest storage deposit =
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
abi.encodePacked(
|
|
489
|
-
fundingTxHash,
|
|
490
|
-
reveal.fundingOutputIndex
|
|
491
|
-
)
|
|
492
|
-
)
|
|
481
|
+
DepositRequest storage deposit = deposits[
|
|
482
|
+
uint256(
|
|
483
|
+
keccak256(
|
|
484
|
+
abi.encodePacked(fundingTxHash, reveal.fundingOutputIndex)
|
|
493
485
|
)
|
|
494
|
-
|
|
486
|
+
)
|
|
487
|
+
];
|
|
495
488
|
require(deposit.revealedAt == 0, "Deposit already revealed");
|
|
496
489
|
|
|
497
490
|
uint64 fundingOutputAmount = fundingOutput.extractValue();
|
|
@@ -569,16 +562,21 @@ contract Bridge is Ownable {
|
|
|
569
562
|
|
|
570
563
|
// Process sweep transaction output and extract its target wallet
|
|
571
564
|
// public key hash and value.
|
|
572
|
-
(
|
|
573
|
-
|
|
565
|
+
(
|
|
566
|
+
bytes20 walletPubKeyHash,
|
|
567
|
+
uint64 sweepTxOutputValue
|
|
568
|
+
) = processSweepTxOutput(sweepTx.outputVector);
|
|
574
569
|
|
|
575
570
|
// TODO: Validate if `walletPubKeyHash` is a known and active wallet.
|
|
576
571
|
|
|
577
572
|
// Check if the main UTXO for given wallet exists. If so, validate
|
|
578
573
|
// passed main UTXO data against the stored hash and use them for
|
|
579
574
|
// further processing. If no main UTXO exists, use empty data.
|
|
580
|
-
BitcoinTx.UTXO memory resolvedMainUtxo =
|
|
581
|
-
|
|
575
|
+
BitcoinTx.UTXO memory resolvedMainUtxo = BitcoinTx.UTXO(
|
|
576
|
+
bytes32(0),
|
|
577
|
+
0,
|
|
578
|
+
0
|
|
579
|
+
);
|
|
582
580
|
bytes32 mainUtxoHash = mainUtxos[walletPubKeyHash];
|
|
583
581
|
if (mainUtxoHash != bytes32(0)) {
|
|
584
582
|
require(
|
|
@@ -655,15 +653,11 @@ contract Bridge is Ownable {
|
|
|
655
653
|
|
|
656
654
|
txHash = abi
|
|
657
655
|
.encodePacked(
|
|
658
|
-
|
|
659
|
-
.
|
|
660
|
-
|
|
661
|
-
.
|
|
662
|
-
|
|
663
|
-
.outputVector,
|
|
664
|
-
txInfo
|
|
665
|
-
.locktime
|
|
666
|
-
)
|
|
656
|
+
txInfo.version,
|
|
657
|
+
txInfo.inputVector,
|
|
658
|
+
txInfo.outputVector,
|
|
659
|
+
txInfo.locktime
|
|
660
|
+
)
|
|
667
661
|
.hash256View();
|
|
668
662
|
|
|
669
663
|
checkProofFromTxHash(txHash, proof);
|
|
@@ -703,8 +697,9 @@ contract Bridge is Ownable {
|
|
|
703
697
|
uint256 requestedDiff = 0;
|
|
704
698
|
uint256 currentDiff = relay.getCurrentEpochDifficulty();
|
|
705
699
|
uint256 previousDiff = relay.getPrevEpochDifficulty();
|
|
706
|
-
uint256 firstHeaderDiff =
|
|
707
|
-
|
|
700
|
+
uint256 firstHeaderDiff = bitcoinHeaders
|
|
701
|
+
.extractTarget()
|
|
702
|
+
.calculateDifficulty();
|
|
708
703
|
|
|
709
704
|
if (firstHeaderDiff == currentDiff) {
|
|
710
705
|
requestedDiff = currentDiff;
|
|
@@ -826,8 +821,10 @@ contract Bridge is Ownable {
|
|
|
826
821
|
// Determining the total number of sweep transaction inputs in the same
|
|
827
822
|
// way as for number of outputs. See `BitcoinTx.inputVector` docs for
|
|
828
823
|
// more details.
|
|
829
|
-
(
|
|
830
|
-
|
|
824
|
+
(
|
|
825
|
+
uint256 inputsCompactSizeUintLength,
|
|
826
|
+
uint256 inputsCount
|
|
827
|
+
) = sweepTxInputVector.parseVarInt();
|
|
831
828
|
|
|
832
829
|
// To determine the first input starting index, we must jump over
|
|
833
830
|
// the compactSize uint which prepends the input vector. One byte
|
|
@@ -865,14 +862,11 @@ contract Bridge is Ownable {
|
|
|
865
862
|
uint256 inputLength
|
|
866
863
|
) = parseTxInputAt(sweepTxInputVector, inputStartingIndex);
|
|
867
864
|
|
|
868
|
-
DepositRequest storage deposit =
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
)
|
|
874
|
-
)
|
|
875
|
-
];
|
|
865
|
+
DepositRequest storage deposit = deposits[
|
|
866
|
+
uint256(
|
|
867
|
+
keccak256(abi.encodePacked(outpointTxHash, outpointIndex))
|
|
868
|
+
)
|
|
869
|
+
];
|
|
876
870
|
|
|
877
871
|
if (deposit.revealedAt != 0) {
|
|
878
872
|
// If we entered here, that means the input was identified as
|
|
@@ -982,7 +976,7 @@ contract Bridge is Ownable {
|
|
|
982
976
|
/// on the redeemer output script will be always lower than this value
|
|
983
977
|
/// since the treasury and Bitcoin transaction fees must be incurred.
|
|
984
978
|
/// The minimal amount satisfying the request can be computed as:
|
|
985
|
-
/// `amount -
|
|
979
|
+
/// `amount - (amount / redemptionTreasuryFeeDivisor) - redemptionTxMaxFee`.
|
|
986
980
|
/// Fees values are taken at the moment of request creation.
|
|
987
981
|
/// @dev Requirements:
|
|
988
982
|
/// - Wallet behind `walletPubKeyHash` must be active
|
|
@@ -1039,8 +1033,9 @@ contract Bridge is Ownable {
|
|
|
1039
1033
|
// is proper. Worth to note `extractHash` ignores the value at all
|
|
1040
1034
|
// so this is why we can use 0 safely. This way of validation is the
|
|
1041
1035
|
// same as in tBTC v1.
|
|
1042
|
-
bytes memory redeemerOutputScriptPayload =
|
|
1043
|
-
|
|
1036
|
+
bytes memory redeemerOutputScriptPayload = abi
|
|
1037
|
+
.encodePacked(bytes8(0), redeemerOutputScript)
|
|
1038
|
+
.extractHash();
|
|
1044
1039
|
require(
|
|
1045
1040
|
redeemerOutputScriptPayload.length > 0,
|
|
1046
1041
|
"Redeemer output script must be a standard type"
|
|
@@ -1062,12 +1057,9 @@ contract Bridge is Ownable {
|
|
|
1062
1057
|
// and redeemer output script pair. That means there can be only one
|
|
1063
1058
|
// request asking for redemption from the given wallet to the given
|
|
1064
1059
|
// BTC script at the same time.
|
|
1065
|
-
uint256 redemptionKey =
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
abi.encodePacked(walletPubKeyHash, redeemerOutputScript)
|
|
1069
|
-
)
|
|
1070
|
-
);
|
|
1060
|
+
uint256 redemptionKey = uint256(
|
|
1061
|
+
keccak256(abi.encodePacked(walletPubKeyHash, redeemerOutputScript))
|
|
1062
|
+
);
|
|
1071
1063
|
|
|
1072
1064
|
// Check if given redemption key is not used by a pending redemption.
|
|
1073
1065
|
// There is no need to check for existence in `timedOutRedemptions`
|
|
@@ -1079,7 +1071,12 @@ contract Bridge is Ownable {
|
|
|
1079
1071
|
"There is a pending redemption request from this wallet to the same address"
|
|
1080
1072
|
);
|
|
1081
1073
|
|
|
1082
|
-
|
|
1074
|
+
// No need to check whether `amount - treasuryFee - txMaxFee > 0`
|
|
1075
|
+
// since the `redemptionDustThreshold` should force that condition
|
|
1076
|
+
// to be always true.
|
|
1077
|
+
uint64 treasuryFee = redemptionTreasuryFeeDivisor > 0
|
|
1078
|
+
? amount / redemptionTreasuryFeeDivisor
|
|
1079
|
+
: 0;
|
|
1083
1080
|
uint64 txMaxFee = redemptionTxMaxFee;
|
|
1084
1081
|
|
|
1085
1082
|
// The main wallet UTXO's value doesn't include all pending redemptions.
|
|
@@ -1175,8 +1172,10 @@ contract Bridge is Ownable {
|
|
|
1175
1172
|
// can assume the transaction happened on Bitcoin chain and has
|
|
1176
1173
|
// a sufficient number of confirmations as determined by
|
|
1177
1174
|
// `txProofDifficultyFactor` constant.
|
|
1178
|
-
bytes32 redemptionTxHash =
|
|
1179
|
-
|
|
1175
|
+
bytes32 redemptionTxHash = validateBitcoinTxProof(
|
|
1176
|
+
redemptionTx,
|
|
1177
|
+
redemptionProof
|
|
1178
|
+
);
|
|
1180
1179
|
|
|
1181
1180
|
// Perform validation of the redemption transaction input. Specifically,
|
|
1182
1181
|
// check if it refers to the expected wallet's main UTXO.
|
|
@@ -1195,11 +1194,10 @@ contract Bridge is Ownable {
|
|
|
1195
1194
|
|
|
1196
1195
|
// Process redemption transaction outputs to extract some info required
|
|
1197
1196
|
// for further processing.
|
|
1198
|
-
RedemptionTxOutputsInfo memory outputsInfo =
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
);
|
|
1197
|
+
RedemptionTxOutputsInfo memory outputsInfo = processRedemptionTxOutputs(
|
|
1198
|
+
redemptionTx.outputVector,
|
|
1199
|
+
walletPubKeyHash
|
|
1200
|
+
);
|
|
1203
1201
|
|
|
1204
1202
|
if (outputsInfo.changeValue > 0) {
|
|
1205
1203
|
// If the change value is grater than zero, it means the change
|
|
@@ -1263,8 +1261,10 @@ contract Bridge is Ownable {
|
|
|
1263
1261
|
|
|
1264
1262
|
// Assert that the single redemption transaction input actually
|
|
1265
1263
|
// refers to the wallet's main UTXO.
|
|
1266
|
-
(
|
|
1267
|
-
|
|
1264
|
+
(
|
|
1265
|
+
bytes32 redemptionTxOutpointTxHash,
|
|
1266
|
+
uint32 redemptionTxOutpointIndex
|
|
1267
|
+
) = processRedemptionTxInput(redemptionTxInputVector);
|
|
1268
1268
|
require(
|
|
1269
1269
|
mainUtxo.txHash == redemptionTxOutpointTxHash &&
|
|
1270
1270
|
mainUtxo.txOutputIndex == redemptionTxOutpointIndex,
|
|
@@ -1339,8 +1339,10 @@ contract Bridge is Ownable {
|
|
|
1339
1339
|
// Determining the total number of redemption transaction outputs in
|
|
1340
1340
|
// the same way as for number of inputs. See `BitcoinTx.outputVector`
|
|
1341
1341
|
// docs for more details.
|
|
1342
|
-
(
|
|
1343
|
-
|
|
1342
|
+
(
|
|
1343
|
+
uint256 outputsCompactSizeUintLength,
|
|
1344
|
+
uint256 outputsCount
|
|
1345
|
+
) = redemptionTxOutputVector.parseVarInt();
|
|
1344
1346
|
|
|
1345
1347
|
// To determine the first output starting index, we must jump over
|
|
1346
1348
|
// the compactSize uint which prepends the output vector. One byte
|
|
@@ -1364,13 +1366,13 @@ contract Bridge is Ownable {
|
|
|
1364
1366
|
// save on gas. Both scripts have a strict format defined by Bitcoin.
|
|
1365
1367
|
//
|
|
1366
1368
|
// The P2PKH script has format <0x1976a914> <20-byte PKH> <0x88ac>.
|
|
1367
|
-
bytes32 walletP2PKHScriptKeccak =
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
);
|
|
1369
|
+
bytes32 walletP2PKHScriptKeccak = keccak256(
|
|
1370
|
+
abi.encodePacked(hex"1976a914", walletPubKeyHash, hex"88ac")
|
|
1371
|
+
);
|
|
1371
1372
|
// The P2WPKH script has format <0x160014> <20-byte PKH>.
|
|
1372
|
-
bytes32 walletP2WPKHScriptKeccak =
|
|
1373
|
-
|
|
1373
|
+
bytes32 walletP2WPKHScriptKeccak = keccak256(
|
|
1374
|
+
abi.encodePacked(hex"160014", walletPubKeyHash)
|
|
1375
|
+
);
|
|
1374
1376
|
|
|
1375
1377
|
// Helper variable that counts the number of processed redemption
|
|
1376
1378
|
// outputs. Redemptions can be either pending or reported as timed out.
|
|
@@ -1383,15 +1385,12 @@ contract Bridge is Ownable {
|
|
|
1383
1385
|
// TODO: Check if we can optimize gas costs by adding
|
|
1384
1386
|
// `extractValueAt` and `extractHashAt` in `bitcoin-spv-sol`
|
|
1385
1387
|
// in order to avoid allocating bytes in memory.
|
|
1386
|
-
uint256 outputLength =
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
outputStartingIndex,
|
|
1393
|
-
outputLength
|
|
1394
|
-
);
|
|
1388
|
+
uint256 outputLength = redemptionTxOutputVector
|
|
1389
|
+
.determineOutputLengthAt(outputStartingIndex);
|
|
1390
|
+
bytes memory output = redemptionTxOutputVector.slice(
|
|
1391
|
+
outputStartingIndex,
|
|
1392
|
+
outputLength
|
|
1393
|
+
);
|
|
1395
1394
|
|
|
1396
1395
|
// Extract the value from given output.
|
|
1397
1396
|
uint64 outputValue = output.extractValue();
|
|
@@ -1414,24 +1413,22 @@ contract Bridge is Ownable {
|
|
|
1414
1413
|
// If we entered here, that the means the given output is
|
|
1415
1414
|
// supposed to represent a redemption. Build the redemption key
|
|
1416
1415
|
// to perform that check.
|
|
1417
|
-
uint256 redemptionKey =
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
abi.encodePacked(walletPubKeyHash, outputScript)
|
|
1421
|
-
)
|
|
1422
|
-
);
|
|
1416
|
+
uint256 redemptionKey = uint256(
|
|
1417
|
+
keccak256(abi.encodePacked(walletPubKeyHash, outputScript))
|
|
1418
|
+
);
|
|
1423
1419
|
|
|
1424
1420
|
if (pendingRedemptions[redemptionKey].requestedAt != 0) {
|
|
1425
1421
|
// If we entered here, that means the output was identified
|
|
1426
1422
|
// as a pending redemption request.
|
|
1427
|
-
RedemptionRequest storage request =
|
|
1428
|
-
|
|
1423
|
+
RedemptionRequest storage request = pendingRedemptions[
|
|
1424
|
+
redemptionKey
|
|
1425
|
+
];
|
|
1429
1426
|
// Compute the request's redeemable amount as the requested
|
|
1430
1427
|
// amount reduced by the treasury fee. The request's
|
|
1431
1428
|
// minimal amount is then the redeemable amount reduced by
|
|
1432
1429
|
// the maximum transaction fee.
|
|
1433
|
-
uint64 redeemableAmount =
|
|
1434
|
-
request.
|
|
1430
|
+
uint64 redeemableAmount = request.requestedAmount -
|
|
1431
|
+
request.treasuryFee;
|
|
1435
1432
|
// Output value must fit between the request's redeemable
|
|
1436
1433
|
// and minimal amounts to be deemed valid.
|
|
1437
1434
|
require(
|
|
@@ -1460,16 +1457,17 @@ contract Bridge is Ownable {
|
|
|
1460
1457
|
// then bypass this output and process the subsequent
|
|
1461
1458
|
// ones. That also means the wallet was already punished
|
|
1462
1459
|
// for the inactivity. Otherwise, just revert.
|
|
1463
|
-
RedemptionRequest storage request =
|
|
1464
|
-
|
|
1460
|
+
RedemptionRequest storage request = timedOutRedemptions[
|
|
1461
|
+
redemptionKey
|
|
1462
|
+
];
|
|
1465
1463
|
|
|
1466
1464
|
require(
|
|
1467
1465
|
request.requestedAt != 0,
|
|
1468
1466
|
"Output is a non-requested redemption"
|
|
1469
1467
|
);
|
|
1470
1468
|
|
|
1471
|
-
uint64 redeemableAmount =
|
|
1472
|
-
request.
|
|
1469
|
+
uint64 redeemableAmount = request.requestedAmount -
|
|
1470
|
+
request.treasuryFee;
|
|
1473
1471
|
|
|
1474
1472
|
require(
|
|
1475
1473
|
redeemableAmount - request.txMaxFee <= outputValue &&
|
package/contracts/token/TBTC.sol
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keep-network/tbtc-v2",
|
|
3
|
-
"version": "0.1.1-dev.
|
|
3
|
+
"version": "0.1.1-dev.17+main.045b8fe8e838ba8ae100b838df4f0558df419754",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"artifacts/",
|
|
@@ -45,17 +45,16 @@
|
|
|
45
45
|
"@types/mocha": "^9.0.0",
|
|
46
46
|
"@types/node": "^16.10.5",
|
|
47
47
|
"chai": "^4.3.4",
|
|
48
|
-
"eslint": "^7.
|
|
49
|
-
"eslint-config-keep": "github:keep-network/eslint-config-keep#0c27ade",
|
|
50
|
-
"eslint-plugin-import": "^2.18.2",
|
|
48
|
+
"eslint": "^7.32.0",
|
|
51
49
|
"ethereum-waffle": "^3.4.0",
|
|
52
50
|
"ethers": "^5.4.7",
|
|
53
51
|
"hardhat": "^2.6.4",
|
|
54
52
|
"hardhat-deploy": "^0.8.11",
|
|
55
53
|
"hardhat-gas-reporter": "^1.0.4",
|
|
56
|
-
"prettier": "^2.
|
|
57
|
-
"prettier-plugin-
|
|
58
|
-
"
|
|
54
|
+
"prettier": "^2.5.1",
|
|
55
|
+
"prettier-plugin-sh": "^0.8.1",
|
|
56
|
+
"prettier-plugin-solidity": "^1.0.0-beta.19",
|
|
57
|
+
"solhint": "^3.3.7",
|
|
59
58
|
"solhint-config-keep": "github:keep-network/solhint-config-keep",
|
|
60
59
|
"ts-node": "^10.2.1",
|
|
61
60
|
"typechain": "^5.2.0",
|