From 9eb076d391aed0c65a37f72d43f1c9a2c0cb85c6 Mon Sep 17 00:00:00 2001 From: Luisfc68 <60527258+Luisfc68@users.noreply.github.com> Date: Fri, 16 Feb 2024 12:50:11 -0300 Subject: [PATCH] Feature/GBI-1652 - Null script size verification (#208) * chore: change method of setting github token in workflow * feat: add null script content validation * test: add test to null script content validation --- .github/workflows/ci.yml | 2 +- contracts/LiquidityBridgeContractV2.sol | 1 + errorCodes.json | 3 +- test/basic.tests.js | 62 +++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fafe853..c5a262c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: node-version: '19.6.0' - name: NPM Login - run: echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrc + run: npm config set //npm.pkg.github.com/:_authToken ${{ secrets.GITHUB_TOKEN }} - name: Install truffle run: npm install -g truffle diff --git a/contracts/LiquidityBridgeContractV2.sol b/contracts/LiquidityBridgeContractV2.sol index 2b11b72..32a8f86 100644 --- a/contracts/LiquidityBridgeContractV2.sol +++ b/contracts/LiquidityBridgeContractV2.sol @@ -703,6 +703,7 @@ contract LiquidityBridgeContractV2 is Initializable, OwnableUpgradeable, Reentra require(quote.lbcAddress != address(0), "LBC042"); BtcUtils.TxRawOutput[] memory outputs = BtcUtils.getOutputs(btcTx); bytes memory scriptContent = BtcUtils.parseNullDataScript(outputs[QUOTE_HASH_OUTPUT].pkScript); + require(scriptContent.length == 33 && scriptContent[0] == 0x20, "LBC075"); // shift the array to remove the first byte (the size) for (uint8 i = 0 ; i < scriptContent.length - 1; i++) { scriptContent[i] = scriptContent[i + 1]; diff --git a/errorCodes.json b/errorCodes.json index 8d94300..0eb1472 100644 --- a/errorCodes.json +++ b/errorCodes.json @@ -67,5 +67,6 @@ "LBC071": "Intentional overflow on quote values", "LBC072": "Minimum collateral for registration can't be lower than 0.6 RBTC", "LBC073": "Resign delay blocks lower than minimal", - "LBC074": "Error sending fee to DAO" + "LBC074": "Error sending fee to DAO", + "LBC075": "Malformed BTC transaction output" } diff --git a/test/basic.tests.js b/test/basic.tests.js index 23f52c9..f872669 100644 --- a/test/basic.tests.js +++ b/test/basic.tests.js @@ -1540,6 +1540,68 @@ contract("LiquidityBridgeContractV2.sol", async (accounts) => { ); }); + it("Should fail on refundPegout if btc tx null data script has wrong format", async () => { + const blockHeaderHash = + "0x02327049330a25d4d17e53e79f478cbb79c53a509679b1d8a1505c5697afb326"; + const partialMerkleTree = + "0x02327049330a25d4d17e53e79f478cbb79c53a509679b1d8a1505c5697afb426"; + const merkleBranchHashes = [ + "0x02327049330a25d4d17e53e79f478cbb79c53a509679b1d8a1505c5697afb326", + ]; + let quote = utils.getTestPegOutQuote( + instance.address, //lbc address + liquidityProviderRskAddress, + accounts[2], + web3.utils.toBN(1) + ); + quote.transferConfirmations = 0; + + // configure mocked block on mockBridge + const firstConfirmationTime = utils.reverseHexBytes( + web3.utils.toHex(quote.agreementTimestamp + 300).substring(2) + ); + const firstHeader = + "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + firstConfirmationTime + + "0000000000000000"; + await bridgeMockInstance.setHeaderByHash(blockHeaderHash, firstHeader); + + const msgValue = quote.value.add(quote.callFee).add(quote.productFeeAmount).add(quote.gasFee); + const quoteHash = await instance.hashPegoutQuote(utils.asArray(quote)); + const signature = await web3.eth.sign(quoteHash, liquidityProviderRskAddress); + const pegOut = await instance.depositPegout(utils.asArray(quote), signature, { + value: msgValue.toNumber() + }); + await truffleAssertions.eventEmitted(pegOut, "PegOutDeposit"); + + let incorrectSizeByteTx = await utils.generateRawTx(instance, quote); + incorrectSizeByteTx = web3.utils.bytesToHex(incorrectSizeByteTx).replace("6a20", "6a40"); + await truffleAssertions.reverts( + instance.refundPegOut( + quoteHash, + incorrectSizeByteTx, + blockHeaderHash, + partialMerkleTree, + merkleBranchHashes + ), + "LBC075" + ); + + let incorrectHashSizeTx = await utils.generateRawTx(instance, quote); + incorrectHashSizeTx = web3.utils.bytesToHex(incorrectHashSizeTx) + .replace("226a20"+quoteHash.slice(2), "216a19"+quoteHash.slice(2, -2)); + await truffleAssertions.reverts( + instance.refundPegOut( + quoteHash, + incorrectHashSizeTx, + blockHeaderHash, + partialMerkleTree, + merkleBranchHashes + ), + "LBC075" + ); + }); + it("Should fail on refundPegout if btc tx doesn't have correct amount", async () => { const blockHeaderHash = "0x02327049330a25d4d17e53e79f478cbb79c53a509679b1d8a1505c5697afb326"; const partialMerkleTree = "0x02327049330a25d4d17e53e79f478cbb79c53a509679b1d8a1505c5697afb426";