From db159946bb324bfead3885ff861bedc04c01e63e Mon Sep 17 00:00:00 2001 From: derpy-duck <115193320+derpy-duck@users.noreply.github.com> Date: Fri, 6 Jan 2023 22:27:03 +0000 Subject: [PATCH] Redelivery Error Testing - Errors 1, 9-17 --- .../contracts/coreRelayer/CoreRelayer.sol | 4 - .../coreRelayer/CoreRelayerMessages.sol | 57 +--- ethereum/forge-test/CoreRelayer.t.sol | 280 +++++++++++++++--- 3 files changed, 248 insertions(+), 93 deletions(-) diff --git a/ethereum/contracts/coreRelayer/CoreRelayer.sol b/ethereum/contracts/coreRelayer/CoreRelayer.sol index e2d204f..cc4c3a8 100644 --- a/ethereum/contracts/coreRelayer/CoreRelayer.sol +++ b/ethereum/contracts/coreRelayer/CoreRelayer.sol @@ -8,8 +8,6 @@ import "../libraries/external/BytesLib.sol"; import "./CoreRelayerGovernance.sol"; import "./CoreRelayerStructs.sol"; -import "forge-std/console.sol"; - contract CoreRelayer is CoreRelayerGovernance { using BytesLib for bytes; @@ -255,8 +253,6 @@ contract CoreRelayer is CoreRelayerGovernance { } totalFees = totalFees + requestFee; - console.log(funds); - console.log(totalFees); if (funds < totalFees) { return (0, false, "25"); //"Insufficient funds were provided to cover the delivery fees."); } diff --git a/ethereum/contracts/coreRelayer/CoreRelayerMessages.sol b/ethereum/contracts/coreRelayer/CoreRelayerMessages.sol index cb2222d..2c8b673 100644 --- a/ethereum/contracts/coreRelayer/CoreRelayerMessages.sol +++ b/ethereum/contracts/coreRelayer/CoreRelayerMessages.sol @@ -11,18 +11,6 @@ import "./CoreRelayerStructs.sol"; contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters { using BytesLib for bytes; - // function encodeDeliveryStatus(DeliveryStatus memory ds) internal pure returns (bytes memory) { - // require(ds.payloadID == 2, "invalid DeliveryStatus"); - // return abi.encodePacked( - // uint8(2), // payloadID = 2 - // ds.batchHash, - // ds.emitterAddress, - // ds.sequence, - // ds.deliveryCount, - // ds.deliverySuccess ? uint8(1) : uint8(0) - // ); - // } - function decodeRedeliveryByTxHashInstruction(bytes memory encoded) internal pure @@ -61,7 +49,6 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters { index += 32; } - /// @dev `decodeDeliveryInstructionsContainer` parses encoded delivery instructions into the DeliveryInstructions struct function decodeDeliveryInstructionsContainer(bytes memory encoded) internal pure @@ -117,35 +104,9 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters { return DeliveryInstructionsContainer(payloadId, sufficientlyFunded, instructionArray); } - // function parseDeliveryStatus(bytes memory encoded) internal pure returns (DeliveryStatus memory ds) { - // uint256 index = 0; - - // ds.payloadID = encoded.toUint8(index); - // index += 1; - - // require(ds.payloadID == 2, "invalid DeliveryStatus"); - - // ds.batchHash = encoded.toBytes32(index); - // index += 32; - - // ds.emitterAddress = encoded.toBytes32(index); - // index += 32; - - // ds.sequence = encoded.toUint64(index); - // index += 8; - - // ds.deliveryCount = encoded.toUint16(index); - // index += 2; - - // ds.deliverySuccess = encoded.toUint8(index) != 0; - // index += 1; - - // require(encoded.length == index, "invalid DeliveryStatus"); - // } - function encodeDeliveryRequestsContainer(DeliveryRequestsContainer memory container) internal - view + pure returns (bytes memory encoded) { encoded = abi.encodePacked( @@ -165,17 +126,15 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters { request.refundAddress, request.computeBudget, request.applicationBudget, - request.relayParameters.length > 0 ? request.relayParameters.toUint8(0) : uint8(0), - request.relayParameters.length > 0 - ? request.relayParameters.toBytes32(1) - : bytes32(uint256(uint160(address(0x0)))) + uint8(request.relayParameters.length), + request.relayParameters ); } } function decodeDeliveryRequestsContainer(bytes memory encoded) internal - view + pure returns (DeliveryRequestsContainer memory) { uint256 index = 0; @@ -211,9 +170,13 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters { request.applicationBudget = encoded.toUint256(index); index += 32; - request.relayParameters = encoded.slice(index, 33); + uint8 relayParametersLength = encoded.toUint8(index); - index += 33; + index += 1; + + request.relayParameters = encoded.slice(index, relayParametersLength); + + index += relayParametersLength; requestArray[i] = request; } diff --git a/ethereum/forge-test/CoreRelayer.t.sol b/ethereum/forge-test/CoreRelayer.t.sol index 88ee6a2..8226f42 100644 --- a/ethereum/forge-test/CoreRelayer.t.sol +++ b/ethereum/forge-test/CoreRelayer.t.sol @@ -423,46 +423,6 @@ contract TestCoreRelayer is Test { assertTrue(keccak256(target.integration.getMessage()) == keccak256(secondMessage)); } - function testRevertRequestRedeliveryNotEnoughFunds(GasParameters memory gasParams, bytes memory message) public { - (uint16 SOURCE_CHAIN_ID, uint16 TARGET_CHAIN_ID, Contracts memory source, Contracts memory target) = - standardAssumeAndSetupTwoChains(gasParams, 1000000); - - vm.recordLogs(); - - // estimate the cost based on the intialized values - uint256 payment = source.coreRelayer.quoteGasRedeliveryFee( - TARGET_CHAIN_ID, gasParams.targetGasLimit, source.relayProvider - ) + source.wormhole.messageFee(); - uint256 paymentNotEnough = source.coreRelayer.quoteGasDeliveryFee(TARGET_CHAIN_ID, 10, source.relayProvider) - + source.wormhole.messageFee(); - - source.integration.sendMessage{value: paymentNotEnough}( - message, TARGET_CHAIN_ID, address(target.integration), address(target.refundAddress) - ); - - genericRelayer(SOURCE_CHAIN_ID, 2); - - assertTrue( - (keccak256(target.integration.getMessage()) != keccak256(message)) - || (keccak256(message) == keccak256(bytes(""))) - ); - - bytes32 deliveryVaaHash = vm.getRecordedLogs()[0].data.toBytes32(0); - - ICoreRelayer.RedeliveryByTxHashRequest memory redeliveryRequest = ICoreRelayer.RedeliveryByTxHashRequest( - SOURCE_CHAIN_ID, - deliveryVaaHash, - 1, - TARGET_CHAIN_ID, - payment - source.wormhole.messageFee(), - 0, - source.coreRelayer.getDefaultRelayParams() - ); - - vm.expectRevert(bytes("1")); - source.coreRelayer.requestRedelivery{value: payment - 1}(redeliveryRequest, 1, source.relayProvider); - } - function testRevertNonceZero(GasParameters memory gasParams, bytes memory message) public { (uint16 SOURCE_CHAIN_ID, uint16 TARGET_CHAIN_ID, Contracts memory source, Contracts memory target) = standardAssumeAndSetupTwoChains(gasParams, 1000000); @@ -486,16 +446,252 @@ contract TestCoreRelayer is Test { } /** - * Forwarding tests 3-7.. need to think about how to test this.. some sort of way to control the forwarding request? Or maybe make a different relayerintegration for testing? + * Forwarding tests 2, 3-7.. need to think about how to test this.. some sort of way to control the forwarding request? Or maybe make a different relayerintegration for testing? */ /** - * Reentrnecy test for execute delivery 8 + * Reentrancy test for execute delivery 8 */ /** * Redelivery 9-17 */ + struct RedeliveryStackTooDeep { + bytes32 deliveryVaaHash; + uint256 payment; + Vm.Log[] entries; + bytes redeliveryVM; + IWormhole.VM parsed; + uint256 budget; + ICoreRelayer.RedeliveryByTxHashRequest redeliveryRequest; + ICoreRelayer.TargetDeliveryParametersSingle originalDelivery; + ICoreRelayer.TargetRedeliveryByTxHashParamsSingle package; + ICoreRelayer.RedeliveryByTxHashInstruction instruction; + } + + function change(bytes memory message, uint256 index) internal { + if (message[index] == 0x02) { + message[index] = 0x04; + } else { + message[index] = 0x02; + } + } + + function testRevertRedeliveryErrors_1_9_10_11_12_13_14_15_16_17( + GasParameters memory gasParams, + bytes memory message + ) public { + (uint16 SOURCE_CHAIN_ID, uint16 TARGET_CHAIN_ID, Contracts memory source, Contracts memory target) = + standardAssumeAndSetupTwoChains(gasParams, 1000000); + + vm.recordLogs(); + + RedeliveryStackTooDeep memory stack; + + source.integration.sendMessage{ + value: source.coreRelayer.quoteGasDeliveryFee(TARGET_CHAIN_ID, 21000, source.relayProvider) + + source.wormhole.messageFee() + }(message, TARGET_CHAIN_ID, address(target.integration), address(target.refundAddress)); + + genericRelayer(SOURCE_CHAIN_ID, 2); + + assertTrue( + (keccak256(target.integration.getMessage()) != keccak256(message)) + || (keccak256(message) == keccak256(bytes(""))) + ); + + stack.deliveryVaaHash = vm.getRecordedLogs()[0].data.toBytes32(0); + + stack.payment = + source.coreRelayer.quoteGasDeliveryFee(TARGET_CHAIN_ID, gasParams.targetGasLimit, source.relayProvider); + + stack.redeliveryRequest = ICoreRelayer.RedeliveryByTxHashRequest( + SOURCE_CHAIN_ID, + stack.deliveryVaaHash, + 1, + TARGET_CHAIN_ID, + stack.payment - source.wormhole.messageFee(), + 0, + source.coreRelayer.getDefaultRelayParams() + ); + + vm.expectRevert(bytes("1")); + source.coreRelayer.requestRedelivery{value: stack.payment - 1}(stack.redeliveryRequest, 1, source.relayProvider); + + source.coreRelayer.requestRedelivery{value: stack.payment}(stack.redeliveryRequest, 1, source.relayProvider); + + stack.entries = vm.getRecordedLogs(); + + stack.redeliveryVM = relayerWormholeSimulator.fetchSignedMessageFromLogs( + stack.entries[0], SOURCE_CHAIN_ID, address(source.coreRelayer) + ); + + stack.originalDelivery = pastDeliveries[stack.deliveryVaaHash]; + + bytes memory fakeVM = abi.encodePacked(stack.originalDelivery.encodedVMs[1]); + bytes memory correctVM = abi.encodePacked(stack.originalDelivery.encodedVMs[1]); + change(fakeVM, fakeVM.length - 1); + stack.originalDelivery.encodedVMs[1] = fakeVM; + + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + stack.redeliveryVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + stack.parsed = relayerWormhole.parseVM(stack.redeliveryVM); + stack.instruction = target.coreRelayer.getRedeliveryByTxHashInstruction(stack.parsed.payload); + + stack.budget = stack.instruction.newMaximumRefundTarget + stack.instruction.newApplicationBudgetTarget; + + vm.prank(target.relayer); + vm.expectRevert(bytes("9")); + target.coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + + stack.originalDelivery.encodedVMs[1] = stack.originalDelivery.encodedVMs[0]; + + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + stack.redeliveryVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + vm.prank(target.relayer); + vm.expectRevert(bytes("10")); + target.coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + + stack.originalDelivery.encodedVMs[1] = correctVM; + + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + stack.redeliveryVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + correctVM = abi.encodePacked(stack.redeliveryVM); + fakeVM = abi.encodePacked(correctVM); + change(fakeVM, fakeVM.length - 1); + + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + fakeVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + vm.prank(target.relayer); + vm.expectRevert(bytes("11")); + target.coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + + fakeVM = relayerWormholeSimulator.fetchSignedMessageFromLogs( + stack.entries[0], SOURCE_CHAIN_ID, address(source.integration) + ); + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + fakeVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + vm.prank(target.relayer); + vm.expectRevert(bytes("12")); + target.coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + + source.relayProvider.updateDeliveryAddress(TARGET_CHAIN_ID, bytes32(uint256(uint160(address(this))))); + vm.getRecordedLogs(); + source.coreRelayer.requestRedelivery{value: stack.payment}(stack.redeliveryRequest, 1, source.relayProvider); + stack.entries = vm.getRecordedLogs(); + source.relayProvider.updateDeliveryAddress(TARGET_CHAIN_ID, bytes32(uint256(uint160(address(target.relayer))))); + + fakeVM = relayerWormholeSimulator.fetchSignedMessageFromLogs( + stack.entries[0], SOURCE_CHAIN_ID, address(source.coreRelayer) + ); + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + fakeVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + vm.prank(target.relayer); + vm.expectRevert(bytes("13")); + target.coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + stack.redeliveryVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + vm.expectRevert(bytes("14")); + target.coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + + uint16 differentChainId = 2; + if (TARGET_CHAIN_ID == 2) { + differentChainId = 3; + } + + vm.deal(map[differentChainId].relayer, stack.budget); + vm.expectRevert(bytes("15")); + vm.prank(target.relayer); + map[differentChainId].coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + + stack.redeliveryRequest = ICoreRelayer.RedeliveryByTxHashRequest( + SOURCE_CHAIN_ID, + stack.deliveryVaaHash, + 1, + differentChainId, + stack.payment - source.wormhole.messageFee(), + 0, + source.coreRelayer.getDefaultRelayParams() + ); + source.relayProvider.updatePrice(differentChainId, gasParams.targetGasPrice, gasParams.targetNativePrice); + source.relayProvider.updatePrice(differentChainId, gasParams.sourceGasPrice, gasParams.sourceNativePrice); + source.relayProvider.updateDeliveryAddress(differentChainId, bytes32(uint256(uint160(address(target.relayer))))); + vm.getRecordedLogs(); + source.coreRelayer.requestRedelivery{value: stack.payment}(stack.redeliveryRequest, 1, source.relayProvider); + stack.entries = vm.getRecordedLogs(); + source.relayProvider.updateDeliveryAddress( + differentChainId, bytes32(uint256(uint160(address(map[differentChainId].relayer)))) + ); + + fakeVM = relayerWormholeSimulator.fetchSignedMessageFromLogs( + stack.entries[0], SOURCE_CHAIN_ID, address(source.coreRelayer) + ); + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + fakeVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + vm.expectRevert(bytes("16")); + vm.prank(target.relayer); + map[differentChainId].coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + + stack.package = ICoreRelayer.TargetRedeliveryByTxHashParamsSingle( + correctVM, + stack.originalDelivery.encodedVMs, + stack.originalDelivery.deliveryIndex, + stack.originalDelivery.multisendIndex + ); + + vm.expectRevert(bytes("17")); + vm.prank(target.relayer); + target.coreRelayer.redeliverSingle{value: stack.budget - 1}(stack.package); + + assertTrue( + (keccak256(target.integration.getMessage()) != keccak256(message)) + || (keccak256(message) == keccak256(bytes(""))) + ); + vm.prank(target.relayer); + target.coreRelayer.redeliverSingle{value: stack.budget}(stack.package); + assertTrue(keccak256(target.integration.getMessage()) == keccak256(message)); + } /** * Delivery 18-24