@keep-network/tbtc-v2 0.1.1-dev.15 → 0.1.1-dev.16
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 +3 -3
- package/artifacts/TBTCToken.json +3 -3
- package/artifacts/VendingMachine.json +3 -3
- package/artifacts/solcInputs/{a76c1776cec417d8640e42239e23ea4b.json → 3d68045732e072924745a5b701f4ad2a.json} +2 -2
- 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/Bank.sol/Bank.json +2 -2
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
- package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
- package/build/contracts/bridge/Bridge.sol/Bridge.json +2 -2
- 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/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/build/contracts/vault/TBTCVault.sol/TBTCVault.json +2 -2
- package/contracts/bank/Bank.sol +17 -16
- package/contracts/bridge/Bridge.sol +117 -130
- package/package.json +6 -7
|
@@ -174,8 +174,8 @@
|
|
|
174
174
|
"type": "function"
|
|
175
175
|
}
|
|
176
176
|
],
|
|
177
|
-
"bytecode": "
|
|
178
|
-
"deployedBytecode": "
|
|
177
|
+
"bytecode": "0x608060405234801561001057600080fd5b50604051610b62380380610b6283398101604081905261002f91610138565b6001600160a01b03821661008a5760405162461bcd60e51b815260206004820181905260248201527f42616e6b2063616e206e6f7420626520746865207a65726f206164647265737360448201526064015b60405180910390fd5b6001600160a01b0381166100ef5760405162461bcd60e51b815260206004820152602660248201527f5442544320746f6b656e2063616e206e6f7420626520746865207a65726f206160448201526564647265737360d01b6064820152608401610081565b600080546001600160a01b039384166001600160a01b03199182161790915560018054929093169116179055610172565b6001600160a01b038116811461013557600080fd5b50565b6000806040838503121561014b57600080fd5b825161015681610120565b602084015190925061016781610120565b809150509250929050565b6109e1806101816000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80638f4ffcb11161005b5780638f4ffcb1146100d9578063a0712d68146100ec578063db006a75146100ff578063e5d3d7141461011257600080fd5b8063461c637314610082578063537941371461009757806376cdb03b146100aa575b600080fd5b6100956100903660046107cb565b610125565b005b6100956100a5366004610853565b61023d565b6000546100bd906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6100956100e736600461087d565b6103e8565b6100956100fa366004610918565b6104a7565b61009561010d366004610918565b6105c9565b6001546100bd906001600160a01b031681565b6000546001600160a01b031633146101845760405162461bcd60e51b815260206004820152601660248201527f43616c6c6572206973206e6f74207468652042616e6b0000000000000000000060448201526064015b60405180910390fd5b826101d15760405162461bcd60e51b815260206004820152601760248201527f4e6f206465706f7369746f727320737065636966696564000000000000000000604482015260640161017b565b60005b83811015610236576102248585838181106101f1576101f1610931565b90506020020160208101906102069190610947565b84848481811061021857610218610931565b905060200201356105d6565b8061022e81610969565b9150506101d4565b5050505050565b6000546001600160a01b031633146102975760405162461bcd60e51b815260206004820152601660248201527f43616c6c6572206973206e6f74207468652042616e6b00000000000000000000604482015260640161017b565b6000546040516370a0823160e01b81526001600160a01b038481166004830152839216906370a082319060240160206040518083038186803b1580156102dc57600080fd5b505afa1580156102f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103149190610992565b101561036d5760405162461bcd60e51b815260206004820152602260248201527f416d6f756e7420657863656564732062616c616e636520696e207468652062616044820152616e6b60f01b606482015260840161017b565b61037782826105d6565b600054604051631f1b6d2760e21b81526001600160a01b0384811660048301523060248301526044820184905290911690637c6db49c906064015b600060405180830381600087803b1580156103cc57600080fd5b505af11580156103e0573d6000803e3d6000fd5b505050505050565b6001546001600160a01b038481169116146104455760405162461bcd60e51b815260206004820152601160248201527f546f6b656e206973206e6f742054425443000000000000000000000000000000604482015260640161017b565b336001600160a01b0384161461049d5760405162461bcd60e51b815260206004820152601860248201527f4f6e6c7920544254432063616c6c657220616c6c6f7765640000000000000000604482015260640161017b565b610236858561066b565b6000546040516370a0823160e01b815233600482018190529183916001600160a01b03909116906370a082319060240160206040518083038186803b1580156104ef57600080fd5b505afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610992565b10156105805760405162461bcd60e51b815260206004820152602260248201527f416d6f756e7420657863656564732062616c616e636520696e207468652062616044820152616e6b60f01b606482015260840161017b565b61058a81836105d6565b600054604051631f1b6d2760e21b81526001600160a01b0383811660048301523060248301526044820185905290911690637c6db49c906064016103b2565b6105d3338261066b565b50565b816001600160a01b03167f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe8260405161061191815260200190565b60405180910390a26001546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015260248201849052909116906340c10f19906044016103b2565b816001600160a01b03167f4896181ff8f4543cc00db9fe9b6fb7e6f032b7eb772c72ab1ec1b4d2e03b9369826040516106a691815260200190565b60405180910390a26001546040517f79cc67900000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015260248201849052909116906379cc679090604401600060405180830381600087803b15801561071557600080fd5b505af1158015610729573d6000803e3d6000fd5b50506000546040517f56a6d9ef0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301526024820186905290911692506356a6d9ef91506044016103b2565b60008083601f84011261079157600080fd5b50813567ffffffffffffffff8111156107a957600080fd5b6020830191508360208260051b85010111156107c457600080fd5b9250929050565b600080600080604085870312156107e157600080fd5b843567ffffffffffffffff808211156107f957600080fd5b6108058883890161077f565b9096509450602087013591508082111561081e57600080fd5b5061082b8782880161077f565b95989497509550505050565b80356001600160a01b038116811461084e57600080fd5b919050565b6000806040838503121561086657600080fd5b61086f83610837565b946020939093013593505050565b60008060008060006080868803121561089557600080fd5b61089e86610837565b9450602086013593506108b360408701610837565b9250606086013567ffffffffffffffff808211156108d057600080fd5b818801915088601f8301126108e457600080fd5b8135818111156108f357600080fd5b89602082850101111561090557600080fd5b9699959850939650602001949392505050565b60006020828403121561092a57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561095957600080fd5b61096282610837565b9392505050565b600060001982141561098b57634e487b7160e01b600052601160045260246000fd5b5060010190565b6000602082840312156109a457600080fd5b505191905056fea264697066735822122034d347dae8b0cb7669cfc1db70694636766f5fdc5f5a1be8ba243f64fcb4915964736f6c63430008090033",
|
|
178
|
+
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80638f4ffcb11161005b5780638f4ffcb1146100d9578063a0712d68146100ec578063db006a75146100ff578063e5d3d7141461011257600080fd5b8063461c637314610082578063537941371461009757806376cdb03b146100aa575b600080fd5b6100956100903660046107cb565b610125565b005b6100956100a5366004610853565b61023d565b6000546100bd906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6100956100e736600461087d565b6103e8565b6100956100fa366004610918565b6104a7565b61009561010d366004610918565b6105c9565b6001546100bd906001600160a01b031681565b6000546001600160a01b031633146101845760405162461bcd60e51b815260206004820152601660248201527f43616c6c6572206973206e6f74207468652042616e6b0000000000000000000060448201526064015b60405180910390fd5b826101d15760405162461bcd60e51b815260206004820152601760248201527f4e6f206465706f7369746f727320737065636966696564000000000000000000604482015260640161017b565b60005b83811015610236576102248585838181106101f1576101f1610931565b90506020020160208101906102069190610947565b84848481811061021857610218610931565b905060200201356105d6565b8061022e81610969565b9150506101d4565b5050505050565b6000546001600160a01b031633146102975760405162461bcd60e51b815260206004820152601660248201527f43616c6c6572206973206e6f74207468652042616e6b00000000000000000000604482015260640161017b565b6000546040516370a0823160e01b81526001600160a01b038481166004830152839216906370a082319060240160206040518083038186803b1580156102dc57600080fd5b505afa1580156102f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103149190610992565b101561036d5760405162461bcd60e51b815260206004820152602260248201527f416d6f756e7420657863656564732062616c616e636520696e207468652062616044820152616e6b60f01b606482015260840161017b565b61037782826105d6565b600054604051631f1b6d2760e21b81526001600160a01b0384811660048301523060248301526044820184905290911690637c6db49c906064015b600060405180830381600087803b1580156103cc57600080fd5b505af11580156103e0573d6000803e3d6000fd5b505050505050565b6001546001600160a01b038481169116146104455760405162461bcd60e51b815260206004820152601160248201527f546f6b656e206973206e6f742054425443000000000000000000000000000000604482015260640161017b565b336001600160a01b0384161461049d5760405162461bcd60e51b815260206004820152601860248201527f4f6e6c7920544254432063616c6c657220616c6c6f7765640000000000000000604482015260640161017b565b610236858561066b565b6000546040516370a0823160e01b815233600482018190529183916001600160a01b03909116906370a082319060240160206040518083038186803b1580156104ef57600080fd5b505afa158015610503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105279190610992565b10156105805760405162461bcd60e51b815260206004820152602260248201527f416d6f756e7420657863656564732062616c616e636520696e207468652062616044820152616e6b60f01b606482015260840161017b565b61058a81836105d6565b600054604051631f1b6d2760e21b81526001600160a01b0383811660048301523060248301526044820185905290911690637c6db49c906064016103b2565b6105d3338261066b565b50565b816001600160a01b03167f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe8260405161061191815260200190565b60405180910390a26001546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015260248201849052909116906340c10f19906044016103b2565b816001600160a01b03167f4896181ff8f4543cc00db9fe9b6fb7e6f032b7eb772c72ab1ec1b4d2e03b9369826040516106a691815260200190565b60405180910390a26001546040517f79cc67900000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015260248201849052909116906379cc679090604401600060405180830381600087803b15801561071557600080fd5b505af1158015610729573d6000803e3d6000fd5b50506000546040517f56a6d9ef0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301526024820186905290911692506356a6d9ef91506044016103b2565b60008083601f84011261079157600080fd5b50813567ffffffffffffffff8111156107a957600080fd5b6020830191508360208260051b85010111156107c457600080fd5b9250929050565b600080600080604085870312156107e157600080fd5b843567ffffffffffffffff808211156107f957600080fd5b6108058883890161077f565b9096509450602087013591508082111561081e57600080fd5b5061082b8782880161077f565b95989497509550505050565b80356001600160a01b038116811461084e57600080fd5b919050565b6000806040838503121561086657600080fd5b61086f83610837565b946020939093013593505050565b60008060008060006080868803121561089557600080fd5b61089e86610837565b9450602086013593506108b360408701610837565b9250606086013567ffffffffffffffff808211156108d057600080fd5b818801915088601f8301126108e457600080fd5b8135818111156108f357600080fd5b89602082850101111561090557600080fd5b9699959850939650602001949392505050565b60006020828403121561092a57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561095957600080fd5b61096282610837565b9392505050565b600060001982141561098b57634e487b7160e01b600052601160045260246000fd5b5060010190565b6000602082840312156109a457600080fd5b505191905056fea264697066735822122034d347dae8b0cb7669cfc1db70694636766f5fdc5f5a1be8ba243f64fcb4915964736f6c63430008090033",
|
|
179
179
|
"linkReferences": {},
|
|
180
180
|
"deployedLinkReferences": {}
|
|
181
181
|
}
|
package/contracts/bank/Bank.sol
CHANGED
|
@@ -222,23 +222,22 @@ contract Bank is Ownable {
|
|
|
222
222
|
);
|
|
223
223
|
require(v == 27 || v == 28, "Invalid signature 'v' value");
|
|
224
224
|
|
|
225
|
-
bytes32 digest =
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
deadline
|
|
238
|
-
)
|
|
225
|
+
bytes32 digest = keccak256(
|
|
226
|
+
abi.encodePacked(
|
|
227
|
+
"\x19\x01",
|
|
228
|
+
DOMAIN_SEPARATOR(),
|
|
229
|
+
keccak256(
|
|
230
|
+
abi.encode(
|
|
231
|
+
PERMIT_TYPEHASH,
|
|
232
|
+
owner,
|
|
233
|
+
spender,
|
|
234
|
+
amount,
|
|
235
|
+
nonce[owner]++,
|
|
236
|
+
deadline
|
|
239
237
|
)
|
|
240
238
|
)
|
|
241
|
-
)
|
|
239
|
+
)
|
|
240
|
+
);
|
|
242
241
|
address recoveredAddress = ecrecover(digest, v, r, s);
|
|
243
242
|
require(
|
|
244
243
|
recoveredAddress != address(0) && recoveredAddress == owner,
|
|
@@ -357,7 +356,9 @@ contract Bank is Ownable {
|
|
|
357
356
|
|
|
358
357
|
uint256 spenderBalance = balanceOf[spender];
|
|
359
358
|
require(spenderBalance >= amount, "Transfer amount exceeds balance");
|
|
360
|
-
unchecked {
|
|
359
|
+
unchecked {
|
|
360
|
+
balanceOf[spender] = spenderBalance - amount;
|
|
361
|
+
}
|
|
361
362
|
balanceOf[recipient] += amount;
|
|
362
363
|
emit BalanceTransferred(spender, recipient, amount);
|
|
363
364
|
}
|
|
@@ -19,9 +19,7 @@ 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";
|
|
@@ -407,39 +405,37 @@ contract Bridge is Ownable {
|
|
|
407
405
|
// TODO: Validate if `walletPubKeyHash` is a known and active wallet.
|
|
408
406
|
// TODO: Should we enforce a specific locktime at contract level?
|
|
409
407
|
|
|
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
|
-
);
|
|
408
|
+
bytes memory expectedScript = abi.encodePacked(
|
|
409
|
+
hex"14", // Byte length of depositor Ethereum address.
|
|
410
|
+
reveal.depositor,
|
|
411
|
+
hex"75", // OP_DROP
|
|
412
|
+
hex"08", // Byte length of blinding factor value.
|
|
413
|
+
reveal.blindingFactor,
|
|
414
|
+
hex"75", // OP_DROP
|
|
415
|
+
hex"76", // OP_DUP
|
|
416
|
+
hex"a9", // OP_HASH160
|
|
417
|
+
hex"14", // Byte length of a compressed Bitcoin public key hash.
|
|
418
|
+
reveal.walletPubKeyHash,
|
|
419
|
+
hex"87", // OP_EQUAL
|
|
420
|
+
hex"63", // OP_IF
|
|
421
|
+
hex"ac", // OP_CHECKSIG
|
|
422
|
+
hex"67", // OP_ELSE
|
|
423
|
+
hex"76", // OP_DUP
|
|
424
|
+
hex"a9", // OP_HASH160
|
|
425
|
+
hex"14", // Byte length of a compressed Bitcoin public key hash.
|
|
426
|
+
reveal.refundPubKeyHash,
|
|
427
|
+
hex"88", // OP_EQUALVERIFY
|
|
428
|
+
hex"04", // Byte length of refund locktime value.
|
|
429
|
+
reveal.refundLocktime,
|
|
430
|
+
hex"b1", // OP_CHECKLOCKTIMEVERIFY
|
|
431
|
+
hex"75", // OP_DROP
|
|
432
|
+
hex"ac", // OP_CHECKSIG
|
|
433
|
+
hex"68" // OP_ENDIF
|
|
434
|
+
);
|
|
438
435
|
|
|
439
|
-
bytes memory fundingOutput =
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
);
|
|
436
|
+
bytes memory fundingOutput = fundingTx
|
|
437
|
+
.outputVector
|
|
438
|
+
.extractOutputAtIndex(reveal.fundingOutputIndex);
|
|
443
439
|
bytes memory fundingOutputHash = fundingOutput.extractHash();
|
|
444
440
|
|
|
445
441
|
if (fundingOutputHash.length == 20) {
|
|
@@ -467,31 +463,22 @@ contract Bridge is Ownable {
|
|
|
467
463
|
}
|
|
468
464
|
|
|
469
465
|
// 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
|
|
466
|
+
bytes32 fundingTxHash = abi
|
|
467
|
+
.encodePacked(
|
|
468
|
+
fundingTx.version,
|
|
469
|
+
fundingTx.inputVector,
|
|
470
|
+
fundingTx.outputVector,
|
|
471
|
+
fundingTx.locktime
|
|
481
472
|
)
|
|
482
|
-
|
|
473
|
+
.hash256View();
|
|
483
474
|
|
|
484
|
-
DepositRequest storage deposit =
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
abi.encodePacked(
|
|
489
|
-
fundingTxHash,
|
|
490
|
-
reveal.fundingOutputIndex
|
|
491
|
-
)
|
|
492
|
-
)
|
|
475
|
+
DepositRequest storage deposit = deposits[
|
|
476
|
+
uint256(
|
|
477
|
+
keccak256(
|
|
478
|
+
abi.encodePacked(fundingTxHash, reveal.fundingOutputIndex)
|
|
493
479
|
)
|
|
494
|
-
|
|
480
|
+
)
|
|
481
|
+
];
|
|
495
482
|
require(deposit.revealedAt == 0, "Deposit already revealed");
|
|
496
483
|
|
|
497
484
|
uint64 fundingOutputAmount = fundingOutput.extractValue();
|
|
@@ -569,16 +556,21 @@ contract Bridge is Ownable {
|
|
|
569
556
|
|
|
570
557
|
// Process sweep transaction output and extract its target wallet
|
|
571
558
|
// public key hash and value.
|
|
572
|
-
(
|
|
573
|
-
|
|
559
|
+
(
|
|
560
|
+
bytes20 walletPubKeyHash,
|
|
561
|
+
uint64 sweepTxOutputValue
|
|
562
|
+
) = processSweepTxOutput(sweepTx.outputVector);
|
|
574
563
|
|
|
575
564
|
// TODO: Validate if `walletPubKeyHash` is a known and active wallet.
|
|
576
565
|
|
|
577
566
|
// Check if the main UTXO for given wallet exists. If so, validate
|
|
578
567
|
// passed main UTXO data against the stored hash and use them for
|
|
579
568
|
// further processing. If no main UTXO exists, use empty data.
|
|
580
|
-
BitcoinTx.UTXO memory resolvedMainUtxo =
|
|
581
|
-
|
|
569
|
+
BitcoinTx.UTXO memory resolvedMainUtxo = BitcoinTx.UTXO(
|
|
570
|
+
bytes32(0),
|
|
571
|
+
0,
|
|
572
|
+
0
|
|
573
|
+
);
|
|
582
574
|
bytes32 mainUtxoHash = mainUtxos[walletPubKeyHash];
|
|
583
575
|
if (mainUtxoHash != bytes32(0)) {
|
|
584
576
|
require(
|
|
@@ -655,15 +647,11 @@ contract Bridge is Ownable {
|
|
|
655
647
|
|
|
656
648
|
txHash = abi
|
|
657
649
|
.encodePacked(
|
|
658
|
-
|
|
659
|
-
.
|
|
660
|
-
|
|
661
|
-
.
|
|
662
|
-
|
|
663
|
-
.outputVector,
|
|
664
|
-
txInfo
|
|
665
|
-
.locktime
|
|
666
|
-
)
|
|
650
|
+
txInfo.version,
|
|
651
|
+
txInfo.inputVector,
|
|
652
|
+
txInfo.outputVector,
|
|
653
|
+
txInfo.locktime
|
|
654
|
+
)
|
|
667
655
|
.hash256View();
|
|
668
656
|
|
|
669
657
|
checkProofFromTxHash(txHash, proof);
|
|
@@ -703,8 +691,9 @@ contract Bridge is Ownable {
|
|
|
703
691
|
uint256 requestedDiff = 0;
|
|
704
692
|
uint256 currentDiff = relay.getCurrentEpochDifficulty();
|
|
705
693
|
uint256 previousDiff = relay.getPrevEpochDifficulty();
|
|
706
|
-
uint256 firstHeaderDiff =
|
|
707
|
-
|
|
694
|
+
uint256 firstHeaderDiff = bitcoinHeaders
|
|
695
|
+
.extractTarget()
|
|
696
|
+
.calculateDifficulty();
|
|
708
697
|
|
|
709
698
|
if (firstHeaderDiff == currentDiff) {
|
|
710
699
|
requestedDiff = currentDiff;
|
|
@@ -826,8 +815,10 @@ contract Bridge is Ownable {
|
|
|
826
815
|
// Determining the total number of sweep transaction inputs in the same
|
|
827
816
|
// way as for number of outputs. See `BitcoinTx.inputVector` docs for
|
|
828
817
|
// more details.
|
|
829
|
-
(
|
|
830
|
-
|
|
818
|
+
(
|
|
819
|
+
uint256 inputsCompactSizeUintLength,
|
|
820
|
+
uint256 inputsCount
|
|
821
|
+
) = sweepTxInputVector.parseVarInt();
|
|
831
822
|
|
|
832
823
|
// To determine the first input starting index, we must jump over
|
|
833
824
|
// the compactSize uint which prepends the input vector. One byte
|
|
@@ -865,14 +856,11 @@ contract Bridge is Ownable {
|
|
|
865
856
|
uint256 inputLength
|
|
866
857
|
) = parseTxInputAt(sweepTxInputVector, inputStartingIndex);
|
|
867
858
|
|
|
868
|
-
DepositRequest storage deposit =
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
)
|
|
874
|
-
)
|
|
875
|
-
];
|
|
859
|
+
DepositRequest storage deposit = deposits[
|
|
860
|
+
uint256(
|
|
861
|
+
keccak256(abi.encodePacked(outpointTxHash, outpointIndex))
|
|
862
|
+
)
|
|
863
|
+
];
|
|
876
864
|
|
|
877
865
|
if (deposit.revealedAt != 0) {
|
|
878
866
|
// If we entered here, that means the input was identified as
|
|
@@ -1039,8 +1027,9 @@ contract Bridge is Ownable {
|
|
|
1039
1027
|
// is proper. Worth to note `extractHash` ignores the value at all
|
|
1040
1028
|
// so this is why we can use 0 safely. This way of validation is the
|
|
1041
1029
|
// same as in tBTC v1.
|
|
1042
|
-
bytes memory redeemerOutputScriptPayload =
|
|
1043
|
-
|
|
1030
|
+
bytes memory redeemerOutputScriptPayload = abi
|
|
1031
|
+
.encodePacked(bytes8(0), redeemerOutputScript)
|
|
1032
|
+
.extractHash();
|
|
1044
1033
|
require(
|
|
1045
1034
|
redeemerOutputScriptPayload.length > 0,
|
|
1046
1035
|
"Redeemer output script must be a standard type"
|
|
@@ -1062,12 +1051,9 @@ contract Bridge is Ownable {
|
|
|
1062
1051
|
// and redeemer output script pair. That means there can be only one
|
|
1063
1052
|
// request asking for redemption from the given wallet to the given
|
|
1064
1053
|
// BTC script at the same time.
|
|
1065
|
-
uint256 redemptionKey =
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
abi.encodePacked(walletPubKeyHash, redeemerOutputScript)
|
|
1069
|
-
)
|
|
1070
|
-
);
|
|
1054
|
+
uint256 redemptionKey = uint256(
|
|
1055
|
+
keccak256(abi.encodePacked(walletPubKeyHash, redeemerOutputScript))
|
|
1056
|
+
);
|
|
1071
1057
|
|
|
1072
1058
|
// Check if given redemption key is not used by a pending redemption.
|
|
1073
1059
|
// There is no need to check for existence in `timedOutRedemptions`
|
|
@@ -1175,8 +1161,10 @@ contract Bridge is Ownable {
|
|
|
1175
1161
|
// can assume the transaction happened on Bitcoin chain and has
|
|
1176
1162
|
// a sufficient number of confirmations as determined by
|
|
1177
1163
|
// `txProofDifficultyFactor` constant.
|
|
1178
|
-
bytes32 redemptionTxHash =
|
|
1179
|
-
|
|
1164
|
+
bytes32 redemptionTxHash = validateBitcoinTxProof(
|
|
1165
|
+
redemptionTx,
|
|
1166
|
+
redemptionProof
|
|
1167
|
+
);
|
|
1180
1168
|
|
|
1181
1169
|
// Perform validation of the redemption transaction input. Specifically,
|
|
1182
1170
|
// check if it refers to the expected wallet's main UTXO.
|
|
@@ -1195,11 +1183,10 @@ contract Bridge is Ownable {
|
|
|
1195
1183
|
|
|
1196
1184
|
// Process redemption transaction outputs to extract some info required
|
|
1197
1185
|
// for further processing.
|
|
1198
|
-
RedemptionTxOutputsInfo memory outputsInfo =
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
);
|
|
1186
|
+
RedemptionTxOutputsInfo memory outputsInfo = processRedemptionTxOutputs(
|
|
1187
|
+
redemptionTx.outputVector,
|
|
1188
|
+
walletPubKeyHash
|
|
1189
|
+
);
|
|
1203
1190
|
|
|
1204
1191
|
if (outputsInfo.changeValue > 0) {
|
|
1205
1192
|
// If the change value is grater than zero, it means the change
|
|
@@ -1263,8 +1250,10 @@ contract Bridge is Ownable {
|
|
|
1263
1250
|
|
|
1264
1251
|
// Assert that the single redemption transaction input actually
|
|
1265
1252
|
// refers to the wallet's main UTXO.
|
|
1266
|
-
(
|
|
1267
|
-
|
|
1253
|
+
(
|
|
1254
|
+
bytes32 redemptionTxOutpointTxHash,
|
|
1255
|
+
uint32 redemptionTxOutpointIndex
|
|
1256
|
+
) = processRedemptionTxInput(redemptionTxInputVector);
|
|
1268
1257
|
require(
|
|
1269
1258
|
mainUtxo.txHash == redemptionTxOutpointTxHash &&
|
|
1270
1259
|
mainUtxo.txOutputIndex == redemptionTxOutpointIndex,
|
|
@@ -1339,8 +1328,10 @@ contract Bridge is Ownable {
|
|
|
1339
1328
|
// Determining the total number of redemption transaction outputs in
|
|
1340
1329
|
// the same way as for number of inputs. See `BitcoinTx.outputVector`
|
|
1341
1330
|
// docs for more details.
|
|
1342
|
-
(
|
|
1343
|
-
|
|
1331
|
+
(
|
|
1332
|
+
uint256 outputsCompactSizeUintLength,
|
|
1333
|
+
uint256 outputsCount
|
|
1334
|
+
) = redemptionTxOutputVector.parseVarInt();
|
|
1344
1335
|
|
|
1345
1336
|
// To determine the first output starting index, we must jump over
|
|
1346
1337
|
// the compactSize uint which prepends the output vector. One byte
|
|
@@ -1364,13 +1355,13 @@ contract Bridge is Ownable {
|
|
|
1364
1355
|
// save on gas. Both scripts have a strict format defined by Bitcoin.
|
|
1365
1356
|
//
|
|
1366
1357
|
// The P2PKH script has format <0x1976a914> <20-byte PKH> <0x88ac>.
|
|
1367
|
-
bytes32 walletP2PKHScriptKeccak =
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
);
|
|
1358
|
+
bytes32 walletP2PKHScriptKeccak = keccak256(
|
|
1359
|
+
abi.encodePacked(hex"1976a914", walletPubKeyHash, hex"88ac")
|
|
1360
|
+
);
|
|
1371
1361
|
// The P2WPKH script has format <0x160014> <20-byte PKH>.
|
|
1372
|
-
bytes32 walletP2WPKHScriptKeccak =
|
|
1373
|
-
|
|
1362
|
+
bytes32 walletP2WPKHScriptKeccak = keccak256(
|
|
1363
|
+
abi.encodePacked(hex"160014", walletPubKeyHash)
|
|
1364
|
+
);
|
|
1374
1365
|
|
|
1375
1366
|
// Helper variable that counts the number of processed redemption
|
|
1376
1367
|
// outputs. Redemptions can be either pending or reported as timed out.
|
|
@@ -1383,15 +1374,12 @@ contract Bridge is Ownable {
|
|
|
1383
1374
|
// TODO: Check if we can optimize gas costs by adding
|
|
1384
1375
|
// `extractValueAt` and `extractHashAt` in `bitcoin-spv-sol`
|
|
1385
1376
|
// in order to avoid allocating bytes in memory.
|
|
1386
|
-
uint256 outputLength =
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
outputStartingIndex,
|
|
1393
|
-
outputLength
|
|
1394
|
-
);
|
|
1377
|
+
uint256 outputLength = redemptionTxOutputVector
|
|
1378
|
+
.determineOutputLengthAt(outputStartingIndex);
|
|
1379
|
+
bytes memory output = redemptionTxOutputVector.slice(
|
|
1380
|
+
outputStartingIndex,
|
|
1381
|
+
outputLength
|
|
1382
|
+
);
|
|
1395
1383
|
|
|
1396
1384
|
// Extract the value from given output.
|
|
1397
1385
|
uint64 outputValue = output.extractValue();
|
|
@@ -1414,24 +1402,22 @@ contract Bridge is Ownable {
|
|
|
1414
1402
|
// If we entered here, that the means the given output is
|
|
1415
1403
|
// supposed to represent a redemption. Build the redemption key
|
|
1416
1404
|
// to perform that check.
|
|
1417
|
-
uint256 redemptionKey =
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
abi.encodePacked(walletPubKeyHash, outputScript)
|
|
1421
|
-
)
|
|
1422
|
-
);
|
|
1405
|
+
uint256 redemptionKey = uint256(
|
|
1406
|
+
keccak256(abi.encodePacked(walletPubKeyHash, outputScript))
|
|
1407
|
+
);
|
|
1423
1408
|
|
|
1424
1409
|
if (pendingRedemptions[redemptionKey].requestedAt != 0) {
|
|
1425
1410
|
// If we entered here, that means the output was identified
|
|
1426
1411
|
// as a pending redemption request.
|
|
1427
|
-
RedemptionRequest storage request =
|
|
1428
|
-
|
|
1412
|
+
RedemptionRequest storage request = pendingRedemptions[
|
|
1413
|
+
redemptionKey
|
|
1414
|
+
];
|
|
1429
1415
|
// Compute the request's redeemable amount as the requested
|
|
1430
1416
|
// amount reduced by the treasury fee. The request's
|
|
1431
1417
|
// minimal amount is then the redeemable amount reduced by
|
|
1432
1418
|
// the maximum transaction fee.
|
|
1433
|
-
uint64 redeemableAmount =
|
|
1434
|
-
request.
|
|
1419
|
+
uint64 redeemableAmount = request.requestedAmount -
|
|
1420
|
+
request.treasuryFee;
|
|
1435
1421
|
// Output value must fit between the request's redeemable
|
|
1436
1422
|
// and minimal amounts to be deemed valid.
|
|
1437
1423
|
require(
|
|
@@ -1460,16 +1446,17 @@ contract Bridge is Ownable {
|
|
|
1460
1446
|
// then bypass this output and process the subsequent
|
|
1461
1447
|
// ones. That also means the wallet was already punished
|
|
1462
1448
|
// for the inactivity. Otherwise, just revert.
|
|
1463
|
-
RedemptionRequest storage request =
|
|
1464
|
-
|
|
1449
|
+
RedemptionRequest storage request = timedOutRedemptions[
|
|
1450
|
+
redemptionKey
|
|
1451
|
+
];
|
|
1465
1452
|
|
|
1466
1453
|
require(
|
|
1467
1454
|
request.requestedAt != 0,
|
|
1468
1455
|
"Output is a non-requested redemption"
|
|
1469
1456
|
);
|
|
1470
1457
|
|
|
1471
|
-
uint64 redeemableAmount =
|
|
1472
|
-
request.
|
|
1458
|
+
uint64 redeemableAmount = request.requestedAmount -
|
|
1459
|
+
request.treasuryFee;
|
|
1473
1460
|
|
|
1474
1461
|
require(
|
|
1475
1462
|
redeemableAmount - request.txMaxFee <= outputValue &&
|
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.16+main.d05213ad4dbd8982d3731c67f312ed445462aa4d",
|
|
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",
|