From bfead33eb5124d5aa2604656c8dfb15df5d3aa56 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 28 Aug 2023 20:57:03 +0530 Subject: [PATCH 1/4] feat: wormhole vaa init --- .../WormholeHelper.sol | 87 +++-------- .../lib/BytesParsing.sol | 0 .../lib/InternalStructs.sol | 0 .../lib/PayloadDecoder.sol | 0 .../lib/TypedUnits.sol | 0 .../specialized-relayer/WormholeHelper.sol | 97 ++++++++++++ .../specialized-relayer/lib/IWormhole.sol | 146 ++++++++++++++++++ ....t.sol => Wormhole.AutomaticRelayer.t.sol} | 73 ++------- test/Wormhole.SpecializedRelayer.t.sol | 85 ++++++++++ 9 files changed, 366 insertions(+), 122 deletions(-) rename src/wormhole/{ => automatic-relayer}/WormholeHelper.sol (72%) rename src/wormhole/{ => automatic-relayer}/lib/BytesParsing.sol (100%) rename src/wormhole/{ => automatic-relayer}/lib/InternalStructs.sol (100%) rename src/wormhole/{ => automatic-relayer}/lib/PayloadDecoder.sol (100%) rename src/wormhole/{ => automatic-relayer}/lib/TypedUnits.sol (100%) create mode 100644 src/wormhole/specialized-relayer/WormholeHelper.sol create mode 100644 src/wormhole/specialized-relayer/lib/IWormhole.sol rename test/{Wormhole.t.sol => Wormhole.AutomaticRelayer.t.sol} (79%) create mode 100644 test/Wormhole.SpecializedRelayer.t.sol diff --git a/src/wormhole/WormholeHelper.sol b/src/wormhole/automatic-relayer/WormholeHelper.sol similarity index 72% rename from src/wormhole/WormholeHelper.sol rename to src/wormhole/automatic-relayer/WormholeHelper.sol index 25ff2c0..93cba6e 100644 --- a/src/wormhole/WormholeHelper.sol +++ b/src/wormhole/automatic-relayer/WormholeHelper.sol @@ -8,7 +8,7 @@ import "forge-std/Test.sol"; import "./lib/PayloadDecoder.sol"; import "./lib/InternalStructs.sol"; -import {TypeCasts} from "../libraries/TypeCasts.sol"; +import {TypeCasts} from "../../libraries/TypeCasts.sol"; /// @dev interface that every wormhole receiver should implement /// @notice the helper will try to deliver the message to this interface @@ -33,8 +33,7 @@ contract WormholeHelper is Test { //////////////////////////////////////////////////////////////*/ /// @dev LogMessagePublished (index_topic_1 address sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel) - bytes32 constant MESSAGE_EVENT_SELECTOR = - 0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2; + bytes32 constant MESSAGE_EVENT_SELECTOR = 0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2; /*/////////////////////////////////////////////////////////////// EXTERNAL FUNCTIONS @@ -45,20 +44,8 @@ contract WormholeHelper is Test { /// @param dstForkId is the dst fork id to deliver the message /// @param dstRelayer is wormhole's dst chain relayer /// @param logs is the logs after message dispatch on src chain - function help( - uint16 srcChainId, - uint256 dstForkId, - address dstRelayer, - Vm.Log[] calldata logs - ) external { - _help( - srcChainId, - dstForkId, - address(0), - dstRelayer, - MESSAGE_EVENT_SELECTOR, - logs - ); + function help(uint16 srcChainId, uint256 dstForkId, address dstRelayer, Vm.Log[] calldata logs) external { + _help(srcChainId, dstForkId, address(0), dstRelayer, MESSAGE_EVENT_SELECTOR, logs); } /// @dev single dst x user-specific event selector @@ -73,14 +60,7 @@ contract WormholeHelper is Test { bytes32 msgEventSelector, Vm.Log[] calldata logs ) external { - _help( - srcChainId, - dstForkId, - address(0), - dstRelayer, - msgEventSelector, - logs - ); + _help(srcChainId, dstForkId, address(0), dstRelayer, msgEventSelector, logs); } /// @dev multi dst x default event selector @@ -95,15 +75,8 @@ contract WormholeHelper is Test { address[] calldata dstRelayer, Vm.Log[] calldata logs ) external { - for (uint256 i; i < dstForkId.length; ) { - _help( - srcChainId, - dstForkId[i], - expDstAddress[i], - dstRelayer[i], - MESSAGE_EVENT_SELECTOR, - logs - ); + for (uint256 i; i < dstForkId.length;) { + _help(srcChainId, dstForkId[i], expDstAddress[i], dstRelayer[i], MESSAGE_EVENT_SELECTOR, logs); unchecked { ++i; @@ -124,15 +97,8 @@ contract WormholeHelper is Test { bytes32 msgEventSelector, Vm.Log[] calldata logs ) external { - for (uint256 i; i < dstForkId.length; ) { - _help( - srcChainId, - dstForkId[i], - expDstAddress[i], - dstRelayer[i], - msgEventSelector, - logs - ); + for (uint256 i; i < dstForkId.length;) { + _help(srcChainId, dstForkId[i], expDstAddress[i], dstRelayer[i], msgEventSelector, logs); unchecked { ++i; @@ -141,10 +107,7 @@ contract WormholeHelper is Test { } /// @dev helps find logs of `length` for default event selector - function findLogs( - Vm.Log[] calldata logs, - uint256 length - ) external pure returns (Vm.Log[] memory HLLogs) { + function findLogs(Vm.Log[] calldata logs, uint256 length) external pure returns (Vm.Log[] memory HLLogs) { return _findLogs(logs, MESSAGE_EVENT_SELECTOR, length); } @@ -179,28 +142,22 @@ contract WormholeHelper is Test { Vm.Log memory log = logs[i]; if (log.topics[0] == eventSelector) { - (v.sequence, v.nonce, v.payload, ) = abi.decode( - log.data, - (uint64, uint32, bytes, uint8) - ); + (v.sequence, v.nonce, v.payload,) = abi.decode(log.data, (uint64, uint32, bytes, uint8)); - DeliveryInstruction memory instruction = PayloadDecoder - .decodeDeliveryInstruction(v.payload); + DeliveryInstruction memory instruction = PayloadDecoder.decodeDeliveryInstruction(v.payload); - v.dstAddress = TypeCasts.bytes32ToAddress( - instruction.targetAddress - ); + v.dstAddress = TypeCasts.bytes32ToAddress(instruction.targetAddress); - if ( - expDstAddress == address(0) || expDstAddress == v.dstAddress - ) + if (expDstAddress == address(0) || expDstAddress == v.dstAddress) { IWormholeReceiver(v.dstAddress).receiveWormholeMessages( instruction.payload, new bytes[](0), instruction.senderAddress, srcChainId, - keccak256(abi.encodePacked(v.sequence, v.nonce)) /// @dev generating some random hash + keccak256(abi.encodePacked(v.sequence, v.nonce)) ); + /// @dev generating some random hash + } } } @@ -209,11 +166,11 @@ contract WormholeHelper is Test { } /// @dev helper to get logs - function _findLogs( - Vm.Log[] memory logs, - bytes32 dispatchSelector, - uint256 length - ) internal pure returns (Vm.Log[] memory WormholeLogs) { + function _findLogs(Vm.Log[] memory logs, bytes32 dispatchSelector, uint256 length) + internal + pure + returns (Vm.Log[] memory WormholeLogs) + { WormholeLogs = new Vm.Log[](length); uint256 currentIndex = 0; diff --git a/src/wormhole/lib/BytesParsing.sol b/src/wormhole/automatic-relayer/lib/BytesParsing.sol similarity index 100% rename from src/wormhole/lib/BytesParsing.sol rename to src/wormhole/automatic-relayer/lib/BytesParsing.sol diff --git a/src/wormhole/lib/InternalStructs.sol b/src/wormhole/automatic-relayer/lib/InternalStructs.sol similarity index 100% rename from src/wormhole/lib/InternalStructs.sol rename to src/wormhole/automatic-relayer/lib/InternalStructs.sol diff --git a/src/wormhole/lib/PayloadDecoder.sol b/src/wormhole/automatic-relayer/lib/PayloadDecoder.sol similarity index 100% rename from src/wormhole/lib/PayloadDecoder.sol rename to src/wormhole/automatic-relayer/lib/PayloadDecoder.sol diff --git a/src/wormhole/lib/TypedUnits.sol b/src/wormhole/automatic-relayer/lib/TypedUnits.sol similarity index 100% rename from src/wormhole/lib/TypedUnits.sol rename to src/wormhole/automatic-relayer/lib/TypedUnits.sol diff --git a/src/wormhole/specialized-relayer/WormholeHelper.sol b/src/wormhole/specialized-relayer/WormholeHelper.sol new file mode 100644 index 0000000..c174424 --- /dev/null +++ b/src/wormhole/specialized-relayer/WormholeHelper.sol @@ -0,0 +1,97 @@ +/// SPDX-License-Identifier: MIT +pragma solidity >= 0.8.0; + +/// library imports +import "forge-std/Test.sol"; + +/// local imports +import "./lib/IWormhole.sol"; +import {TypeCasts} from "../../libraries/TypeCasts.sol"; + +interface IWormholeReceiver { + function receiveMessage(bytes memory encodedMessage) external; +} + +/// @title WormholeHelper +/// @author Sujith Somraaj +/// @dev wormhole helper that uses VAA to deliver messages +/// @notice supports specialized relayers (for automatic relayer use WormholeHelper) +/// @notice in real-world scenario the off-chain infra will just sign the VAAs but this helpers mocks both signing and relaying +/// MORE INFO: https://docs.wormhole.com/wormhole/quick-start/cross-chain-dev/specialized-relayer +contract WormholeHelper is Test { + function help( + uint16 srcChainId, + uint16 dstChainId, + uint256 dstForkId, + address dstWormhole, + address dstTarget, + Vm.Log[] calldata srcLogs + ) external { + vm.selectFork(dstForkId); + + IWormhole wormhole = IWormhole(dstWormhole); + + bytes32 lastSlot = 0x2fc7941cecc943bf2000c5d7068f2b8c8e9a29be62acd583fe9e6e90489a8c82; + uint256 lastKey = 420; + + /// @dev updates the storage slot to update the guardian set + for (uint256 i; i < 19; i++) { + vm.store(address(wormhole), bytes32(lastSlot), TypeCasts.addressToBytes32(vm.addr(lastKey))); + lastSlot = bytes32(uint256(lastSlot) + 1); + ++lastKey; + } + + /// @dev generates vaa hash + IWormhole.VM memory vaa = IWormhole.VM( + uint8(1), + uint32(block.timestamp), + uint32(0), + srcChainId, + TypeCasts.addressToBytes32(vm.addr(419)), + uint64(0), + uint8(0), + abi.encode(type(uint256).max), + wormhole.getCurrentGuardianSetIndex(), + new IWormhole.Signature[](19), + bytes32(0) + ); + + bytes memory body = abi.encodePacked( + vaa.timestamp, + vaa.nonce, + vaa.emitterChainId, + vaa.emitterAddress, + vaa.sequence, + vaa.consistencyLevel, + vaa.payload + ); + + console.logBytes(vaa.payload); + + vaa.hash = keccak256(abi.encodePacked(keccak256(body))); + lastKey = 420; + + for (uint256 i; i < 19; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(lastKey, vaa.hash); + vaa.signatures[i] = IWormhole.Signature(r, s, v, uint8(i)); + console.log(vm.addr(lastKey)); + ++lastKey; + } + + bytes memory encodedVaa = abi.encodePacked(vaa.version, vaa.guardianSetIndex, uint8(19)); + for (uint256 i; i < 19; i++) { + encodedVaa = abi.encodePacked( + encodedVaa, + vaa.signatures[i].guardianIndex, + vaa.signatures[i].r, + vaa.signatures[i].s, + vaa.signatures[i].v - 27 + ); + } + + encodedVaa = abi.encodePacked(encodedVaa, body); + + /// call the target with the vaa + IWormholeReceiver(dstTarget).receiveMessage(encodedVaa); + } +} diff --git a/src/wormhole/specialized-relayer/lib/IWormhole.sol b/src/wormhole/specialized-relayer/lib/IWormhole.sol new file mode 100644 index 0000000..c826555 --- /dev/null +++ b/src/wormhole/specialized-relayer/lib/IWormhole.sol @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +interface IWormhole { + struct GuardianSet { + address[] keys; + uint32 expirationTime; + } + + struct Signature { + bytes32 r; + bytes32 s; + uint8 v; + uint8 guardianIndex; + } + + struct VM { + uint8 version; + uint32 timestamp; + uint32 nonce; + uint16 emitterChainId; + bytes32 emitterAddress; + uint64 sequence; + uint8 consistencyLevel; + bytes payload; + uint32 guardianSetIndex; + Signature[] signatures; + bytes32 hash; + } + + struct ContractUpgrade { + bytes32 module; + uint8 action; + uint16 chain; + address newContract; + } + + struct GuardianSetUpgrade { + bytes32 module; + uint8 action; + uint16 chain; + GuardianSet newGuardianSet; + uint32 newGuardianSetIndex; + } + + struct SetMessageFee { + bytes32 module; + uint8 action; + uint16 chain; + uint256 messageFee; + } + + struct TransferFees { + bytes32 module; + uint8 action; + uint16 chain; + uint256 amount; + bytes32 recipient; + } + + struct RecoverChainId { + bytes32 module; + uint8 action; + uint256 evmChainId; + uint16 newChainId; + } + + event LogMessagePublished( + address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel + ); + event ContractUpgraded(address indexed oldContract, address indexed newContract); + event GuardianSetAdded(uint32 indexed index); + + function publishMessage(uint32 nonce, bytes memory payload, uint8 consistencyLevel) + external + payable + returns (uint64 sequence); + + function initialize() external; + + function parseAndVerifyVM(bytes calldata encodedVM) + external + view + returns (VM memory vm, bool valid, string memory reason); + + function verifyVM(VM memory vm) external view returns (bool valid, string memory reason); + + function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) + external + pure + returns (bool valid, string memory reason); + + function parseVM(bytes memory encodedVM) external pure returns (VM memory vm); + + function quorum(uint256 numGuardians) external pure returns (uint256 numSignaturesRequiredForQuorum); + + function getGuardianSet(uint32 index) external view returns (GuardianSet memory); + + function getCurrentGuardianSetIndex() external view returns (uint32); + + function getGuardianSetExpiry() external view returns (uint32); + + function governanceActionIsConsumed(bytes32 hash) external view returns (bool); + + function isInitialized(address impl) external view returns (bool); + + function chainId() external view returns (uint16); + + function isFork() external view returns (bool); + + function governanceChainId() external view returns (uint16); + + function governanceContract() external view returns (bytes32); + + function messageFee() external view returns (uint256); + + function evmChainId() external view returns (uint256); + + function nextSequence(address emitter) external view returns (uint64); + + function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu); + + function parseGuardianSetUpgrade(bytes memory encodedUpgrade) + external + pure + returns (GuardianSetUpgrade memory gsu); + + function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf); + + function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf); + + function parseRecoverChainId(bytes memory encodedRecoverChainId) + external + pure + returns (RecoverChainId memory rci); + + function submitContractUpgrade(bytes memory _vm) external; + + function submitSetMessageFee(bytes memory _vm) external; + + function submitNewGuardianSet(bytes memory _vm) external; + + function submitTransferFees(bytes memory _vm) external; + + function submitRecoverChainId(bytes memory _vm) external; +} diff --git a/test/Wormhole.t.sol b/test/Wormhole.AutomaticRelayer.t.sol similarity index 79% rename from test/Wormhole.t.sol rename to test/Wormhole.AutomaticRelayer.t.sol index 2dcd56b..d93e0ec 100644 --- a/test/Wormhole.t.sol +++ b/test/Wormhole.AutomaticRelayer.t.sol @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; +/// library imports import "forge-std/Test.sol"; -import "src/wormhole/WormholeHelper.sol"; + +/// local imports +import "src/wormhole/automatic-relayer/WormholeHelper.sol"; interface IWormholeRelayerSend { function sendPayloadToEvm( @@ -23,17 +26,10 @@ interface IWormholeRelayerSend { address refundAddress ) external payable returns (uint64 sequence); - function quoteEVMDeliveryPrice( - uint16 targetChain, - uint256 receiverValue, - uint256 gasLimit - ) + function quoteEVMDeliveryPrice(uint16 targetChain, uint256 receiverValue, uint256 gasLimit) external view - returns ( - uint256 nativePriceQuote, - uint256 targetChainRefundPerGasUnused - ); + returns (uint256 nativePriceQuote, uint256 targetChainRefundPerGasUnused); } interface IWormholeRelayer is IWormholeRelayerSend {} @@ -75,7 +71,7 @@ contract AnotherTarget { } } -contract WormholeHelperTest is Test { +contract WormholeAutomaticRelayerHelperTest is Test { WormholeHelper wormholeHelper; Target target; Target altTarget; @@ -153,10 +149,7 @@ contract WormholeHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _aMoreFancyCrossChainFunctionInYourContract( - L2_1_CHAIN_ID, - address(anotherTarget) - ); + _aMoreFancyCrossChainFunctionInYourContract(L2_1_CHAIN_ID, address(anotherTarget)); Vm.Log[] memory logs = vm.getRecordedLogs(); wormholeHelper.help(L1_CHAIN_ID, POLYGON_FORK_ID, L2_2_RELAYER, logs); @@ -183,12 +176,7 @@ contract WormholeHelperTest is Test { reorderedLogs[0] = WormholeLogs[1]; reorderedLogs[1] = WormholeLogs[0]; - wormholeHelper.help( - L1_CHAIN_ID, - POLYGON_FORK_ID, - L2_1_RELAYER, - reorderedLogs - ); + wormholeHelper.help(L1_CHAIN_ID, POLYGON_FORK_ID, L2_1_RELAYER, reorderedLogs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), CROSS_CHAIN_MESSAGE); @@ -200,20 +188,11 @@ contract WormholeHelperTest is Test { vm.recordLogs(); _someCrossChainFunctionInYourContract(L2_1_CHAIN_ID, address(target)); - _someCrossChainFunctionInYourContract( - L2_2_CHAIN_ID, - address(altTarget) - ); + _someCrossChainFunctionInYourContract(L2_2_CHAIN_ID, address(altTarget)); Vm.Log[] memory logs = vm.getRecordedLogs(); - wormholeHelper.help( - L1_CHAIN_ID, - allDstForks, - allDstTargets, - allDstRelayers, - logs - ); + wormholeHelper.help(L1_CHAIN_ID, allDstForks, allDstTargets, allDstRelayers, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), CROSS_CHAIN_MESSAGE); @@ -222,17 +201,10 @@ contract WormholeHelperTest is Test { assertEq(altTarget.value(), CROSS_CHAIN_MESSAGE); } - function _aMoreFancyCrossChainFunctionInYourContract( - uint16 dstChainId, - address receiver - ) internal { + function _aMoreFancyCrossChainFunctionInYourContract(uint16 dstChainId, address receiver) internal { IWormholeRelayer relayer = IWormholeRelayer(L1_RELAYER); - (uint256 msgValue, ) = relayer.quoteEVMDeliveryPrice( - dstChainId, - 0, - 500000 - ); + (uint256 msgValue,) = relayer.quoteEVMDeliveryPrice(dstChainId, 0, 500000); relayer.sendPayloadToEvm{value: msgValue}( dstChainId, @@ -245,26 +217,13 @@ contract WormholeHelperTest is Test { ); } - function _someCrossChainFunctionInYourContract( - uint16 dstChainId, - address receiver - ) internal { + function _someCrossChainFunctionInYourContract(uint16 dstChainId, address receiver) internal { IWormholeRelayer relayer = IWormholeRelayer(L1_RELAYER); - (uint256 msgValue, ) = relayer.quoteEVMDeliveryPrice( - dstChainId, - 0, - 500000 - ); + (uint256 msgValue,) = relayer.quoteEVMDeliveryPrice(dstChainId, 0, 500000); relayer.sendPayloadToEvm{value: msgValue}( - dstChainId, - receiver, - abi.encode(CROSS_CHAIN_MESSAGE), - 0, - 500000, - L1_CHAIN_ID, - address(this) + dstChainId, receiver, abi.encode(CROSS_CHAIN_MESSAGE), 0, 500000, L1_CHAIN_ID, address(this) ); } } diff --git a/test/Wormhole.SpecializedRelayer.t.sol b/test/Wormhole.SpecializedRelayer.t.sol new file mode 100644 index 0000000..4ee0d22 --- /dev/null +++ b/test/Wormhole.SpecializedRelayer.t.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/// library imports +import "forge-std/Test.sol"; + +/// local imports +import "src/wormhole/specialized-relayer/lib/IWormhole.sol"; +import "src/wormhole/specialized-relayer/WormholeHelper.sol"; + +contract Target { + uint256 public value; + IWormhole public wormhole; + + constructor(IWormhole _wormhole) { + wormhole = _wormhole; + } + + function receiveMessage(bytes memory encodedMessage) public { + // call the Wormhole core contract to parse and verify the encodedMessage + (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = + wormhole.parseAndVerifyVM(encodedMessage); + // do security checks and set value + require(valid); + value = abi.decode(wormholeMessage.payload, (uint256)); + } +} + +contract WormholeSpecializedRelayerHelperTest is Test { + WormholeHelper wormholeHelper; + Target target; + + uint32 nonce; + + uint256 L1_FORK_ID; + uint256 POLYGON_FORK_ID; + + uint256 CROSS_CHAIN_MESSAGE = UINT256_MAX; + + uint16 L1_CHAIN_ID = 2; + uint16 L2_1_CHAIN_ID = 5; + + address constant L1_CORE = 0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B; + address constant L2_1_CORE = 0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7; + + string RPC_ETH_MAINNET = vm.envString("ETH_MAINNET_RPC_URL"); + string RPC_POLYGON_MAINNET = vm.envString("POLYGON_MAINNET_RPC_URL"); + + receive() external payable {} + + function setUp() external { + L1_FORK_ID = vm.createSelectFork(RPC_ETH_MAINNET); + wormholeHelper = new WormholeHelper(); + + POLYGON_FORK_ID = vm.createSelectFork(RPC_POLYGON_MAINNET); + target = new Target(IWormhole(L2_1_CORE)); + } + + /// @dev is a simple cross-chain message + function testSimpleWormhole() external { + vm.selectFork(L1_FORK_ID); + + vm.recordLogs(); + _someCrossChainFunctionInYourContract(); + + wormholeHelper.help( + L1_CHAIN_ID, L2_1_CHAIN_ID, POLYGON_FORK_ID, L2_1_CORE, address(target), vm.getRecordedLogs() + ); + + vm.selectFork(POLYGON_FORK_ID); + assertEq(target.value(), CROSS_CHAIN_MESSAGE); + } + + /// @dev is a simple cross-chain message to be published by wormhole + function _someCrossChainFunctionInYourContract() internal { + IWormhole wormhole = IWormhole(L1_CORE); + + /// @dev publish a new message + ++nonce; + + /// @dev by sending `0` in the last argument, we get instant finality + /// @notice should use your optimal finality in development + wormhole.publishMessage{value: wormhole.messageFee()}(nonce, abi.encode(CROSS_CHAIN_MESSAGE), 0); + } +} From 621accc88b119299a2b6cbc92d639083fd446037 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 28 Aug 2023 22:21:56 +0530 Subject: [PATCH 2/4] feat: add tests for wormhole specialized relayers --- .gas-snapshot | 20 +- src/axelar/AxelarHelper.sol | 79 +- src/axelar/lib/AddressHelper.sol | 19 +- src/celer/CelerHelper.sol | 121 +- src/hyperlane/HyperlaneHelper.sol | 132 +-- src/layerzero/LayerZeroHelper.sol | 161 +-- src/layerzero/lib/LZPacket.sol | 59 +- .../automatic-relayer/lib/BytesParsing.sol | 1030 ++++++----------- .../automatic-relayer/lib/PayloadDecoder.sol | 130 +-- .../automatic-relayer/lib/TypedUnits.sol | 29 +- .../specialized-relayer/WormholeHelper.sol | 184 ++- test/Axelar.t.sol | 120 +- test/Celer.t.sol | 115 +- test/Hyperlane.t.sol | 184 +-- test/LayerZero.t.sol | 92 +- test/Stargate.t.sol | 51 +- test/Wormhole.SpecializedRelayer.t.sol | 123 +- 17 files changed, 1018 insertions(+), 1631 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index a91928d..dcc8863 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -3,10 +3,10 @@ AxelarHelperTest:testFancyAxelar() (gas: 234946) AxelarHelperTest:testMultiDstAxelar() (gas: 390512) AxelarHelperTest:testSimpleAxelar() (gas: 189522) CelerHelperTest:testCustomOrderingCeler() (gas: 108322) -CelerHelperTest:testFancyCeler() (gas: 117841) +CelerHelperTest:testFancyCeler() (gas: 122514) CelerHelperTest:testMultiDstCeler() (gas: 151149) CelerHelperTest:testSimpleCeler() (gas: 71938) -CelerHelperTest:testSimpleCelerWithEstimates() (gas: 72328) +CelerHelperTest:testSimpleCelerWithEstimates() (gas: 76856) HyperlaneHelperTest:testCustomOrderingHL() (gas: 145179) HyperlaneHelperTest:testFancyHL() (gas: 146237) HyperlaneHelperTest:testMultiDstHL() (gas: 193359) @@ -16,12 +16,16 @@ LayerZeroHelperTest:testCustomOrderingLZ() (gas: 339820) LayerZeroHelperTest:testFancyLZ() (gas: 295097) LayerZeroHelperTest:testMultiDstLZ() (gas: 475776) LayerZeroHelperTest:testSimpleLZ() (gas: 245549) -LayerZeroHelperTest:testSimpleLZWithEstimates() (gas: 246017) +LayerZeroHelperTest:testSimpleLZWithEstimates() (gas: 309922) StargateHelperTest:testCustomOrderingSG() (gas: 797976) StargateHelperTest:testFancySG() (gas: 589535) StargateHelperTest:testSimpleSG() (gas: 537570) -StargateHelperTest:testSimpleSGWithEstimates() (gas: 538082) -WormholeHelperTest:testCustomOrderingWormhole() (gas: 287323) -WormholeHelperTest:testFancyWormhole() (gas: 226022) -WormholeHelperTest:testMultiDstWormhole() (gas: 349780) -WormholeHelperTest:testSimpleWormhole() (gas: 179638) \ No newline at end of file +StargateHelperTest:testSimpleSGWithEstimates() (gas: 603229) +WormholeAutomaticRelayerHelperTest:testCustomOrderingWormhole() (gas: 287323) +WormholeAutomaticRelayerHelperTest:testFancyWormhole() (gas: 226022) +WormholeAutomaticRelayerHelperTest:testMultiDstWormhole() (gas: 349780) +WormholeAutomaticRelayerHelperTest:testSimpleWormhole() (gas: 179638) +WormholeSpecializedRelayerHelperTest:testCustomOrderingWormhole() (gas: 591017) +WormholeSpecializedRelayerHelperTest:testFancyWormhole() (gas: 327851) +WormholeSpecializedRelayerHelperTest:testMultiDstWormhole() (gas: 626734) +WormholeSpecializedRelayerHelperTest:testSimpleWormhole() (gas: 330643) \ No newline at end of file diff --git a/src/axelar/AxelarHelper.sol b/src/axelar/AxelarHelper.sol index 4a6f4b0..ca29cb7 100644 --- a/src/axelar/AxelarHelper.sol +++ b/src/axelar/AxelarHelper.sol @@ -14,23 +14,16 @@ interface IAxelarExecutable { } interface IAxelarGateway { - function approveContractCall( - bytes calldata params, - bytes32 commandId - ) external; + function approveContractCall(bytes calldata params, bytes32 commandId) external; - function callContract( - string calldata destinationChain, - string calldata contractAddress, - bytes calldata payload - ) external; + function callContract(string calldata destinationChain, string calldata contractAddress, bytes calldata payload) + external; } /// @title Axelar Helper /// @notice helps mock the message transfer using axelar bridge contract AxelarHelper is Test { - bytes32 constant MESSAGE_EVENT_SELECTOR = - 0x30ae6cc78c27e651745bf2ad08a11de83910ac1e347a52f7ac898c0fbef94dae; + bytes32 constant MESSAGE_EVENT_SELECTOR = 0x30ae6cc78c27e651745bf2ad08a11de83910ac1e347a52f7ac898c0fbef94dae; function help( string memory fromChain, @@ -40,14 +33,7 @@ contract AxelarHelper is Test { Vm.Log[] calldata logs ) external { for (uint256 i; i < toGateway.length; i++) { - _help( - fromChain, - toGateway[i], - expDstChain[i], - forkId[i], - MESSAGE_EVENT_SELECTOR, - logs - ); + _help(fromChain, toGateway[i], expDstChain[i], forkId[i], MESSAGE_EVENT_SELECTOR, logs); } } @@ -69,20 +55,10 @@ contract AxelarHelper is Test { uint256 forkId, Vm.Log[] calldata logs ) external { - _help( - fromChain, - toGateway, - expDstChain, - forkId, - MESSAGE_EVENT_SELECTOR, - logs - ); + _help(fromChain, toGateway, expDstChain, forkId, MESSAGE_EVENT_SELECTOR, logs); } - function findLogs( - Vm.Log[] calldata logs, - uint256 length - ) external pure returns (Vm.Log[] memory HLLogs) { + function findLogs(Vm.Log[] calldata logs, uint256 length) external pure returns (Vm.Log[] memory HLLogs) { return _findLogs(logs, MESSAGE_EVENT_SELECTOR, length); } @@ -112,32 +88,21 @@ contract AxelarHelper is Test { v.log = logs[i]; if (v.log.topics[0] == eventSelector) { - (v.destinationChain, v.destinationContract, v.payload) = abi - .decode(v.log.data, (string, string, bytes)); + (v.destinationChain, v.destinationContract, v.payload) = abi.decode(v.log.data, (string, string, bytes)); /// FIXME: length based checks aren't sufficient if (isStringsEqual(expDstChain, v.destinationChain)) { - string memory srcAddress = AddressHelper.toString( - address(uint160(uint256(v.log.topics[1]))) - ); - address dstContract = AddressHelper.fromString( - v.destinationContract - ); + string memory srcAddress = AddressHelper.toString(address(uint160(uint256(v.log.topics[1])))); + address dstContract = AddressHelper.fromString(v.destinationContract); IAxelarGateway(toGateway).approveContractCall( - abi.encode( - fromChain, - srcAddress, - dstContract, - keccak256(v.payload), - bytes32(0), - i - ), + abi.encode(fromChain, srcAddress, dstContract, keccak256(v.payload), bytes32(0), i), v.log.topics[2] ); IAxelarExecutable(dstContract).execute( - v.log.topics[2], /// payloadHash + v.log.topics[2], + /// payloadHash fromChain, srcAddress, v.payload @@ -150,19 +115,15 @@ contract AxelarHelper is Test { vm.selectFork(v.prevForkId); } - function isStringsEqual( - string memory a, - string memory b - ) public pure returns (bool) { - return (keccak256(abi.encodePacked((a))) == - keccak256(abi.encodePacked((b)))); + function isStringsEqual(string memory a, string memory b) public pure returns (bool) { + return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)))); } - function _findLogs( - Vm.Log[] memory logs, - bytes32 dispatchSelector, - uint256 length - ) internal pure returns (Vm.Log[] memory AxelarLogs) { + function _findLogs(Vm.Log[] memory logs, bytes32 dispatchSelector, uint256 length) + internal + pure + returns (Vm.Log[] memory AxelarLogs) + { AxelarLogs = new Vm.Log[](length); uint256 currentIndex = 0; diff --git a/src/axelar/lib/AddressHelper.sol b/src/axelar/lib/AddressHelper.sol index 135fcad..bb03d77 100644 --- a/src/axelar/lib/AddressHelper.sol +++ b/src/axelar/lib/AddressHelper.sol @@ -8,22 +8,17 @@ library AddressHelper { return address(_addressBytes); } - function remove0xPrefix( - string memory _hexString - ) internal pure returns (string memory) { + function remove0xPrefix(string memory _hexString) internal pure returns (string memory) { if ( - bytes(_hexString).length >= 2 && - bytes(_hexString)[0] == "0" && - (bytes(_hexString)[1] == "x" || bytes(_hexString)[1] == "X") + bytes(_hexString).length >= 2 && bytes(_hexString)[0] == "0" + && (bytes(_hexString)[1] == "x" || bytes(_hexString)[1] == "X") ) { return substring(_hexString, 2, bytes(_hexString).length); } return _hexString; } - function parseHexStringToBytes20( - string memory _hexString - ) internal pure returns (bytes20) { + function parseHexStringToBytes20(string memory _hexString) internal pure returns (bytes20) { bytes memory _bytesString = bytes(_hexString); uint160 _parsedBytes = 0; for (uint256 i = 0; i < _bytesString.length; i += 2) { @@ -48,11 +43,7 @@ library AddressHelper { } } - function substring( - string memory _str, - uint256 _start, - uint256 _end - ) internal pure returns (string memory) { + function substring(string memory _str, uint256 _start, uint256 _end) internal pure returns (string memory) { bytes memory _strBytes = bytes(_str); bytes memory _result = new bytes(_end - _start); for (uint256 i = _start; i < _end; i++) { diff --git a/src/celer/CelerHelper.sol b/src/celer/CelerHelper.sol index 4351153..6360c09 100644 --- a/src/celer/CelerHelper.sol +++ b/src/celer/CelerHelper.sol @@ -18,11 +18,7 @@ interface IMessageBus { * @param _dstChainId The destination chain ID. * @param _message Arbitrary message bytes to be decoded by the destination app contract. */ - function sendMessage( - address _receiver, - uint256 _dstChainId, - bytes calldata _message - ) external payable; + function sendMessage(address _receiver, uint256 _dstChainId, bytes calldata _message) external payable; function calcFee(bytes calldata _message) external view returns (uint256); } @@ -41,12 +37,10 @@ interface IMessageReceiverApp { * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _executor Address who called the MessageBus execution function */ - function executeMessage( - address _sender, - uint64 _srcChainId, - bytes calldata _message, - address _executor - ) external payable returns (ExecutionStatus); + function executeMessage(address _sender, uint64 _srcChainId, bytes calldata _message, address _executor) + external + payable + returns (ExecutionStatus); } /// @title Celer IM Cross-Chain Helper @@ -54,12 +48,12 @@ interface IMessageReceiverApp { /// @notice will help developers test celer im using forked mainnets (Near mainnet execution) /// @notice supports only EVM chains at this moment & single transfers contract CelerHelper is Test { - bytes32 constant MESSAGE_EVENT_SELECTOR = - 0xce3972bfffe49d317e1d128047a97a3d86b25c94f6f04409f988ef854d25e0e4; + bytes32 constant MESSAGE_EVENT_SELECTOR = 0xce3972bfffe49d317e1d128047a97a3d86b25c94f6f04409f988ef854d25e0e4; /// @dev to process multi destination payloads function help( - uint64 fromChainId, /// @dev is inevitable, cannot fetch form logs + uint64 fromChainId, + /// @dev is inevitable, cannot fetch form logs address fromMessageBus, address[] memory toMessageBus, uint64[] memory expDstChainId, @@ -81,27 +75,20 @@ contract CelerHelper is Test { } function help( - uint64 fromChainId, /// @dev is inevitable, cannot fetch form logs + uint64 fromChainId, + /// @dev is inevitable, cannot fetch form logs address fromMessageBus, address toMessageBus, uint64 expDstChainId, uint256 forkId, Vm.Log[] calldata logs ) external { - _help( - fromChainId, - fromMessageBus, - toMessageBus, - expDstChainId, - MESSAGE_EVENT_SELECTOR, - forkId, - logs, - false - ); + _help(fromChainId, fromMessageBus, toMessageBus, expDstChainId, MESSAGE_EVENT_SELECTOR, forkId, logs, false); } function help( - uint64 fromChainId, /// @dev is inevitable, cannot fetch form logs + uint64 fromChainId, + /// @dev is inevitable, cannot fetch form logs address fromMessageBus, address toMessageBus, uint64 expDstChainId, @@ -109,20 +96,12 @@ contract CelerHelper is Test { uint256 forkId, Vm.Log[] calldata logs ) external { - _help( - fromChainId, - fromMessageBus, - toMessageBus, - expDstChainId, - eventSelector, - forkId, - logs, - false - ); + _help(fromChainId, fromMessageBus, toMessageBus, expDstChainId, eventSelector, forkId, logs, false); } function helpWithEstimates( - uint64 fromChainId, /// @dev is inevitable, cannot fetch form logs + uint64 fromChainId, + /// @dev is inevitable, cannot fetch form logs address fromMessageBus, address toMessageBus, uint64 expDstChainId, @@ -143,7 +122,8 @@ contract CelerHelper is Test { } function helpWithEstimates( - uint64 fromChainId, /// @dev is inevitable, cannot fetch form logs + uint64 fromChainId, + /// @dev is inevitable, cannot fetch form logs address fromMessageBus, address toMessageBus, uint64 expDstChainId, @@ -152,20 +132,12 @@ contract CelerHelper is Test { Vm.Log[] calldata logs ) external { bool enableEstimates = vm.envOr("ENABLE_CELER_ESTIMATES", false); - _help( - fromChainId, - fromMessageBus, - toMessageBus, - expDstChainId, - eventSelector, - forkId, - logs, - enableEstimates - ); + _help(fromChainId, fromMessageBus, toMessageBus, expDstChainId, eventSelector, forkId, logs, enableEstimates); } function helpWithEstimates( - uint64 fromChainId, /// @dev is inevitable, cannot fetch form logs + uint64 fromChainId, + /// @dev is inevitable, cannot fetch form logs address fromMessageBus, address[] memory toMessageBus, uint64[] memory expDstChainId, @@ -187,18 +159,15 @@ contract CelerHelper is Test { } } - function findLogs( - Vm.Log[] calldata logs, - uint256 length - ) external pure returns (Vm.Log[] memory HLLogs) { + function findLogs(Vm.Log[] calldata logs, uint256 length) external pure returns (Vm.Log[] memory HLLogs) { return _findLogs(logs, MESSAGE_EVENT_SELECTOR, length); } - function findLogs( - Vm.Log[] calldata logs, - bytes32 eventSelector, - uint256 length - ) external pure returns (Vm.Log[] memory HLLogs) { + function findLogs(Vm.Log[] calldata logs, bytes32 eventSelector, uint256 length) + external + pure + returns (Vm.Log[] memory HLLogs) + { return _findLogs(logs, eventSelector, length); } @@ -219,9 +188,7 @@ contract CelerHelper is Test { for (uint256 i; i < logs.length; i++) { Vm.Log memory log = logs[i]; - if ( - log.topics[0] == eventSelector && log.emitter == fromMessageBus - ) { + if (log.topics[0] == eventSelector && log.emitter == fromMessageBus) { bytes memory data = log.data; address sender = TypeCasts.bytes32ToAddress(log.topics[1]); @@ -230,10 +197,7 @@ contract CelerHelper is Test { vm.stopBroadcast(); vm.selectFork(prevForkId); if (enableEstimates) { - emit log_named_uint( - "gasEstimate", - _estimateGas(fromMessageBus, data) - ); + emit log_named_uint("gasEstimate", _estimateGas(fromMessageBus, data)); } vm.selectFork(forkId); vm.startBroadcast(toMessageBus); @@ -244,12 +208,7 @@ contract CelerHelper is Test { vm.selectFork(prevForkId); } - function _handle( - uint64 fromChainId, - address sender, - bytes memory data, - uint64 expDstChainId - ) internal { + function _handle(uint64 fromChainId, address sender, bytes memory data, uint64 expDstChainId) internal { bytes32 receiver; uint256 dstChainId; @@ -261,15 +220,13 @@ contract CelerHelper is Test { } if (uint64(dstChainId) == expDstChainId) { - IMessageReceiverApp(TypeCasts.bytes32ToAddress(receiver)) - .executeMessage(sender, fromChainId, message, address(this)); + IMessageReceiverApp(TypeCasts.bytes32ToAddress(receiver)).executeMessage( + sender, fromChainId, message, address(this) + ); } } - function _estimateGas( - address fromMessageBus, - bytes memory message - ) internal returns (uint256 gasEstimate) { + function _estimateGas(address fromMessageBus, bytes memory message) internal returns (uint256 gasEstimate) { /// NOTE: In celer two fees are involved, but only the 1st one is /// estimated here /// 1: Sync, Sign and Store Cost [Source Fees] @@ -277,11 +234,11 @@ contract CelerHelper is Test { gasEstimate = IMessageBus(fromMessageBus).calcFee(message); } - function _findLogs( - Vm.Log[] memory logs, - bytes32 dispatchSelector, - uint256 length - ) internal pure returns (Vm.Log[] memory CelerLogs) { + function _findLogs(Vm.Log[] memory logs, bytes32 dispatchSelector, uint256 length) + internal + pure + returns (Vm.Log[] memory CelerLogs) + { CelerLogs = new Vm.Log[](length); uint256 currentIndex = 0; diff --git a/src/hyperlane/HyperlaneHelper.sol b/src/hyperlane/HyperlaneHelper.sol index 6908e9c..1d936b9 100644 --- a/src/hyperlane/HyperlaneHelper.sol +++ b/src/hyperlane/HyperlaneHelper.sol @@ -7,53 +7,27 @@ import "solady/src/utils/LibString.sol"; import {TypeCasts} from "../libraries/TypeCasts.sol"; interface IMessageRecipient { - function handle( - uint32 _origin, - bytes32 _sender, - bytes calldata _message - ) external; + function handle(uint32 _origin, bytes32 _sender, bytes calldata _message) external; } contract HyperlaneHelper is Test { - bytes32 constant DISPATCH_SELECTOR = - 0x769f711d20c679153d382254f59892613b58a97cc876b249134ac25c80f9c814; + bytes32 constant DISPATCH_SELECTOR = 0x769f711d20c679153d382254f59892613b58a97cc876b249134ac25c80f9c814; function help( address fromMailbox, address[] memory toMailbox, - uint32[] memory expDstDomains, /// expected destination domain + uint32[] memory expDstDomains, + /// expected destination domain uint256[] memory forkId, Vm.Log[] calldata logs ) external { for (uint256 i = 0; i < expDstDomains.length; i++) { - _help( - fromMailbox, - toMailbox[i], - expDstDomains[i], - DISPATCH_SELECTOR, - forkId[i], - logs, - false - ); + _help(fromMailbox, toMailbox[i], expDstDomains[i], DISPATCH_SELECTOR, forkId[i], logs, false); } } - function help( - address fromMailbox, - address toMailbox, - uint256 forkId, - Vm.Log[] calldata logs - ) external { - return - _help( - fromMailbox, - toMailbox, - 0, - DISPATCH_SELECTOR, - forkId, - logs, - false - ); + function help(address fromMailbox, address toMailbox, uint256 forkId, Vm.Log[] calldata logs) external { + return _help(fromMailbox, toMailbox, 0, DISPATCH_SELECTOR, forkId, logs, false); } function help( @@ -69,40 +43,22 @@ contract HyperlaneHelper is Test { function helpWithEstimates( address fromMailbox, address[] memory toMailbox, - uint32[] memory expDstDomains, /// expected destination domains + uint32[] memory expDstDomains, + /// expected destination domains uint256[] memory forkId, Vm.Log[] calldata logs ) external { bool enableEstimates = vm.envOr("ENABLE_HYPERLANE_ESTIMATES", false); for (uint256 i = 0; i < expDstDomains.length; i++) { - _help( - fromMailbox, - toMailbox[i], - expDstDomains[i], - DISPATCH_SELECTOR, - forkId[i], - logs, - enableEstimates - ); + _help(fromMailbox, toMailbox[i], expDstDomains[i], DISPATCH_SELECTOR, forkId[i], logs, enableEstimates); } } - function helpWithEstimates( - address fromMailbox, - address toMailbox, - uint256 forkId, - Vm.Log[] calldata logs - ) external { + function helpWithEstimates(address fromMailbox, address toMailbox, uint256 forkId, Vm.Log[] calldata logs) + external + { bool enableEstimates = vm.envOr("ENABLE_HYPERLANE_ESTIMATES", false); - _help( - fromMailbox, - toMailbox, - 0, - DISPATCH_SELECTOR, - forkId, - logs, - enableEstimates - ); + _help(fromMailbox, toMailbox, 0, DISPATCH_SELECTOR, forkId, logs, enableEstimates); } function helpWithEstimates( @@ -113,29 +69,18 @@ contract HyperlaneHelper is Test { Vm.Log[] calldata logs ) external { bool enableEstimates = vm.envOr("ENABLE_HYPERLANE_ESTIMATES", false); - _help( - fromMailbox, - toMailbox, - 0, - dispatchSelector, - forkId, - logs, - enableEstimates - ); + _help(fromMailbox, toMailbox, 0, dispatchSelector, forkId, logs, enableEstimates); } - function findLogs( - Vm.Log[] calldata logs, - uint256 length - ) external pure returns (Vm.Log[] memory HLLogs) { + function findLogs(Vm.Log[] calldata logs, uint256 length) external pure returns (Vm.Log[] memory HLLogs) { return _findLogs(logs, DISPATCH_SELECTOR, length); } - function findLogs( - Vm.Log[] calldata logs, - bytes32 dispatchSelector, - uint256 length - ) external pure returns (Vm.Log[] memory HLLogs) { + function findLogs(Vm.Log[] calldata logs, bytes32 dispatchSelector, uint256 length) + external + pure + returns (Vm.Log[] memory HLLogs) + { return _findLogs(logs, dispatchSelector, length); } @@ -153,9 +98,7 @@ contract HyperlaneHelper is Test { vm.startBroadcast(toMailbox); for (uint256 i; i < logs.length; i++) { Vm.Log memory log = logs[i]; - if ( - log.emitter == fromMailbox && log.topics[0] == dispatchSelector - ) { + if (log.emitter == fromMailbox && log.topics[0] == dispatchSelector) { uint32 destinationDomain = uint32(uint256(log.topics[2])); bytes memory message = abi.decode(log.data, (bytes)); @@ -168,11 +111,10 @@ contract HyperlaneHelper is Test { vm.selectFork(prevForkId); } - function _estimateGas( - uint32 originDomain, - uint32 destinationDomain, - uint256 handleGas - ) internal returns (uint256 gasEstimate) { + function _estimateGas(uint32 originDomain, uint32 destinationDomain, uint256 handleGas) + internal + returns (uint256 gasEstimate) + { string[] memory cmds = new string[](9); // Build ffi command string @@ -190,11 +132,7 @@ contract HyperlaneHelper is Test { gasEstimate = abi.decode(result, (uint256)); } - function _handle( - bytes memory message, - uint32 destinationDomain, - bool enableEstimates - ) internal { + function _handle(bytes memory message, uint32 destinationDomain, bool enableEstimates) internal { bytes32 _recipient; uint256 _originDomain; bytes32 _sender; @@ -213,20 +151,16 @@ contract HyperlaneHelper is Test { handleGas -= gasleft(); if (enableEstimates) { - uint256 gasEstimate = _estimateGas( - originDomain, - destinationDomain, - handleGas - ); + uint256 gasEstimate = _estimateGas(originDomain, destinationDomain, handleGas); emit log_named_uint("gasEstimate", gasEstimate); } } - function _findLogs( - Vm.Log[] memory logs, - bytes32 dispatchSelector, - uint256 length - ) internal pure returns (Vm.Log[] memory HLLogs) { + function _findLogs(Vm.Log[] memory logs, bytes32 dispatchSelector, uint256 length) + internal + pure + returns (Vm.Log[] memory HLLogs) + { HLLogs = new Vm.Log[](length); uint256 currentIndex = 0; diff --git a/src/layerzero/LayerZeroHelper.sol b/src/layerzero/LayerZeroHelper.sol index d189b51..2f61e51 100644 --- a/src/layerzero/LayerZeroHelper.sol +++ b/src/layerzero/LayerZeroHelper.sol @@ -26,50 +26,26 @@ interface ILayerZeroEndpoint { } contract LayerZeroHelper is Test { - bytes32 constant PACKET_SELECTOR = - 0xe9bded5f24a4168e4f3bf44e00298c993b22376aad8c58c7dda9718a54cbea82; - address constant DEFAULT_LIBRARY = - 0x4D73AdB72bC3DD368966edD0f0b2148401A178E2; + bytes32 constant PACKET_SELECTOR = 0xe9bded5f24a4168e4f3bf44e00298c993b22376aad8c58c7dda9718a54cbea82; + address constant DEFAULT_LIBRARY = 0x4D73AdB72bC3DD368966edD0f0b2148401A178E2; // handle atomic multi destination packets function help( address[] memory endpoints, - uint16[] memory expChainIds, /// expected chain ids + uint16[] memory expChainIds, + /// expected chain ids uint256 gasToSend, uint256[] memory forkId, Vm.Log[] calldata logs ) external { for (uint256 i = 0; i < expChainIds.length; i++) { - _help( - endpoints[i], - expChainIds[i], - DEFAULT_LIBRARY, - gasToSend, - PACKET_SELECTOR, - forkId[i], - logs, - false - ); + _help(endpoints[i], expChainIds[i], DEFAULT_LIBRARY, gasToSend, PACKET_SELECTOR, forkId[i], logs, false); } } // hardcoded defaultLibrary on ETH and Packet event selector - function help( - address endpoint, - uint256 gasToSend, - uint256 forkId, - Vm.Log[] calldata logs - ) external { - _help( - endpoint, - 0, - DEFAULT_LIBRARY, - gasToSend, - PACKET_SELECTOR, - forkId, - logs, - false - ); + function help(address endpoint, uint256 gasToSend, uint256 forkId, Vm.Log[] calldata logs) external { + _help(endpoint, 0, DEFAULT_LIBRARY, gasToSend, PACKET_SELECTOR, forkId, logs, false); } function help( @@ -80,22 +56,14 @@ contract LayerZeroHelper is Test { uint256 forkId, Vm.Log[] calldata logs ) external { - _help( - endpoint, - 0, - defaultLibrary, - gasToSend, - eventSelector, - forkId, - logs, - false - ); + _help(endpoint, 0, defaultLibrary, gasToSend, eventSelector, forkId, logs, false); } // process multi destination payloads function helpWithEstimates( address[] memory endpoints, - uint16[] memory expChainIds, /// expected chain ids + uint16[] memory expChainIds, + /// expected chain ids uint256 gasToSend, uint256[] memory forkId, Vm.Log[] calldata logs @@ -116,23 +84,9 @@ contract LayerZeroHelper is Test { } // hardcoded defaultLibrary on ETH and Packet event selector - function helpWithEstimates( - address endpoint, - uint256 gasToSend, - uint256 forkId, - Vm.Log[] calldata logs - ) external { + function helpWithEstimates(address endpoint, uint256 gasToSend, uint256 forkId, Vm.Log[] calldata logs) external { bool enableEstimates = vm.envOr("ENABLE_LZ_ESTIMATES", false); - _help( - endpoint, - 0, - DEFAULT_LIBRARY, - gasToSend, - PACKET_SELECTOR, - forkId, - logs, - enableEstimates - ); + _help(endpoint, 0, DEFAULT_LIBRARY, gasToSend, PACKET_SELECTOR, forkId, logs, enableEstimates); } function helpWithEstimates( @@ -144,30 +98,18 @@ contract LayerZeroHelper is Test { Vm.Log[] calldata logs ) external { bool enableEstimates = vm.envOr("ENABLE_LZ_ESTIMATES", false); - _help( - endpoint, - 0, - defaultLibrary, - gasToSend, - eventSelector, - forkId, - logs, - enableEstimates - ); + _help(endpoint, 0, defaultLibrary, gasToSend, eventSelector, forkId, logs, enableEstimates); } - function findLogs( - Vm.Log[] calldata logs, - uint256 length - ) external pure returns (Vm.Log[] memory lzLogs) { + function findLogs(Vm.Log[] calldata logs, uint256 length) external pure returns (Vm.Log[] memory lzLogs) { return _findLogs(logs, PACKET_SELECTOR, length); } - function findLogs( - Vm.Log[] calldata logs, - bytes32 eventSelector, - uint256 length - ) external pure returns (Vm.Log[] memory lzLogs) { + function findLogs(Vm.Log[] calldata logs, bytes32 eventSelector, uint256 length) + external + pure + returns (Vm.Log[] memory lzLogs) + { return _findLogs(logs, eventSelector, length); } @@ -189,19 +131,14 @@ contract LayerZeroHelper is Test { Vm.Log memory log = logs[i]; // unsure if the default library always emits the event if ( - /*log.emitter == defaultLibrary &&*/ log.topics[0] == - eventSelector + log + /*log.emitter == defaultLibrary &&*/ + .topics[0] == eventSelector ) { bytes memory payload = abi.decode(log.data, (bytes)); - LayerZeroPacket.Packet memory packet = LayerZeroPacket - .getPacket(payload); + LayerZeroPacket.Packet memory packet = LayerZeroPacket.getPacket(payload); if (packet.dstChainId == expChainId || expChainId == 0) { - _receivePayload( - endpoint, - packet, - gasToSend, - enableEstimates - ); + _receivePayload(endpoint, packet, gasToSend, enableEstimates); } } } @@ -217,13 +154,8 @@ contract LayerZeroHelper is Test { bool payInZRO, bytes memory adapterParam ) internal returns (uint256 gasEstimate) { - (uint256 nativeGas, ) = ILayerZeroEndpoint(endpoint).estimateFees( - destination, - userApplication, - payload, - payInZRO, - adapterParam - ); + (uint256 nativeGas,) = + ILayerZeroEndpoint(endpoint).estimateFees(destination, userApplication, payload, payInZRO, adapterParam); return nativeGas; } @@ -233,50 +165,29 @@ contract LayerZeroHelper is Test { uint256 gasToSend, bool enableEstimates ) internal { - bytes memory path = abi.encodePacked( - packet.srcAddress, - packet.dstAddress - ); + bytes memory path = abi.encodePacked(packet.srcAddress, packet.dstAddress); vm.store( address(endpoint), - keccak256( - abi.encodePacked( - path, - keccak256( - abi.encodePacked(uint256(packet.srcChainId), uint256(5)) - ) - ) - ), + keccak256(abi.encodePacked(path, keccak256(abi.encodePacked(uint256(packet.srcChainId), uint256(5))))), bytes32(uint256(packet.nonce)) ); ILayerZeroEndpoint(endpoint).receivePayload( - packet.srcChainId, - path, - packet.dstAddress, - packet.nonce + 1, - gasToSend, - packet.payload + packet.srcChainId, path, packet.dstAddress, packet.nonce + 1, gasToSend, packet.payload ); if (enableEstimates) { - uint256 gasEstimate = _estimateGas( - endpoint, - packet.dstChainId, - packet.dstAddress, - packet.payload, - false, - "" - ); + uint256 gasEstimate = + _estimateGas(endpoint, packet.dstChainId, packet.dstAddress, packet.payload, false, ""); emit log_named_uint("gasEstimate", gasEstimate); } } - function _findLogs( - Vm.Log[] memory logs, - bytes32 eventSelector, - uint256 length - ) internal pure returns (Vm.Log[] memory lzLogs) { + function _findLogs(Vm.Log[] memory logs, bytes32 eventSelector, uint256 length) + internal + pure + returns (Vm.Log[] memory lzLogs) + { lzLogs = new Vm.Log[](length); uint256 currentIndex = 0; diff --git a/src/layerzero/lib/LZPacket.sol b/src/layerzero/lib/LZPacket.sol index 9fea54e..df8eeb6 100644 --- a/src/layerzero/lib/LZPacket.sol +++ b/src/layerzero/lib/LZPacket.sol @@ -19,9 +19,7 @@ library LayerZeroPacket { bytes payload; } - function getPacket( - bytes memory data - ) internal pure returns (Packet memory) { + function getPacket(bytes memory data) internal pure returns (Packet memory) { Packet memory packet; uint256 realSize; uint64 nonce; @@ -42,7 +40,7 @@ library LayerZeroPacket { DynamicBufferLib.DynamicBuffer memory payloadBuffer; uint256 start = 84; // 32 + 52 bytes uint256 size = realSize + 32 - 84; // 64 bytes - for (uint256 i = start; i < start + size; ) { + for (uint256 i = start; i < start + size;) { bytes32 toAdd; assembly { toAdd := mload(add(data, i)) @@ -59,11 +57,11 @@ library LayerZeroPacket { return packet; } - function getPacketV2( - bytes memory data, - uint256 sizeOfSrcAddress, - bytes32 ulnAddress - ) internal pure returns (LayerZeroPacket.Packet memory) { + function getPacketV2(bytes memory data, uint256 sizeOfSrcAddress, bytes32 ulnAddress) + internal + pure + returns (LayerZeroPacket.Packet memory) + { // packet def: abi.encodePacked(nonce, srcChain, srcAddress, dstChain, dstAddress, payload); // data def: abi.encode(packet) = offset(32) + length(32) + packet // if from EVM @@ -101,23 +99,16 @@ library LayerZeroPacket { // payloadBuffer.init(payloadSize); // payloadBuffer.writeRawBytes(0, data, nonPayloadSize + 96, payloadSize); - return - LayerZeroPacket.Packet( - srcChain, - dstChain, - nonce, - dstAddress, - srcAddressBuffer.buf, - ulnAddress, - payloadBuffer.buf - ); + return LayerZeroPacket.Packet( + srcChain, dstChain, nonce, dstAddress, srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf + ); } - function getPacketV3( - bytes memory data, - uint256 sizeOfSrcAddress, - bytes32 ulnAddress - ) internal pure returns (LayerZeroPacket.Packet memory) { + function getPacketV3(bytes memory data, uint256 sizeOfSrcAddress, bytes32 ulnAddress) + internal + pure + returns (LayerZeroPacket.Packet memory) + { // data def: abi.encodePacked(nonce, srcChain, srcAddress, dstChain, dstAddress, payload); // if from EVM // 0 - 31 0 - 31 | total bytes size @@ -154,23 +145,11 @@ library LayerZeroPacket { Buffer.buffer memory payloadBuffer; if (payloadSize > 0) { payloadBuffer.init(payloadSize); - payloadBuffer.writeRawBytes( - 0, - data, - nonPayloadSize + 32, - payloadSize - ); + payloadBuffer.writeRawBytes(0, data, nonPayloadSize + 32, payloadSize); } - return - LayerZeroPacket.Packet( - srcChain, - dstChain, - nonce, - dstAddress, - srcAddressBuffer.buf, - ulnAddress, - payloadBuffer.buf - ); + return LayerZeroPacket.Packet( + srcChain, dstChain, nonce, dstAddress, srcAddressBuffer.buf, ulnAddress, payloadBuffer.buf + ); } } diff --git a/src/wormhole/automatic-relayer/lib/BytesParsing.sol b/src/wormhole/automatic-relayer/lib/BytesParsing.sol index a7dba26..93c1fd4 100644 --- a/src/wormhole/automatic-relayer/lib/BytesParsing.sol +++ b/src/wormhole/automatic-relayer/lib/BytesParsing.sol @@ -7,15 +7,15 @@ library BytesParsing { error OutOfBounds(uint256 offset, uint256 length); - function checkBound(uint offset, uint length) internal pure { + function checkBound(uint256 offset, uint256 length) internal pure { if (offset > length) revert OutOfBounds(offset, length); } - function sliceUnchecked( - bytes memory encoded, - uint offset, - uint length - ) internal pure returns (bytes memory ret, uint nextOffset) { + function sliceUnchecked(bytes memory encoded, uint256 offset, uint256 length) + internal + pure + returns (bytes memory ret, uint256 nextOffset) + { //bail early for degenerate case if (length == 0) return (new bytes(0), offset); @@ -36,20 +36,14 @@ library BytesParsing { // We remedy this issue by writing the length of our `ret` slice at the end, thus // overwritting those garbage bytes. let shift := and(length, 31) //equivalent to `mod(length, 32)` but 2 gas cheaper - if iszero(shift) { - shift := wordSize - } + if iszero(shift) { shift := wordSize } let dest := add(ret, shift) let end := add(dest, length) - for { - let src := add(add(encoded, shift), offset) - } lt(dest, end) { + for { let src := add(add(encoded, shift), offset) } lt(dest, end) { src := add(src, wordSize) dest := add(dest, wordSize) - } { - mstore(dest, mload(src)) - } + } { mstore(dest, mload(src)) } mstore(ret, length) //When compiling with --via-ir then normally allocated memory (i.e. via new) will have 32 byte @@ -58,96 +52,85 @@ library BytesParsing { } } - function slice( - bytes memory encoded, - uint offset, - uint length - ) internal pure returns (bytes memory ret, uint nextOffset) { + function slice(bytes memory encoded, uint256 offset, uint256 length) + internal + pure + returns (bytes memory ret, uint256 nextOffset) + { (ret, nextOffset) = sliceUnchecked(encoded, offset, length); checkBound(nextOffset, encoded.length); } - function asAddressUnchecked( - bytes memory encoded, - uint offset - ) internal pure returns (address, uint) { - (uint160 ret, uint nextOffset) = asUint160(encoded, offset); + function asAddressUnchecked(bytes memory encoded, uint256 offset) internal pure returns (address, uint256) { + (uint160 ret, uint256 nextOffset) = asUint160(encoded, offset); return (address(ret), nextOffset); } - function asAddress( - bytes memory encoded, - uint offset - ) internal pure returns (address ret, uint nextOffset) { + function asAddress(bytes memory encoded, uint256 offset) internal pure returns (address ret, uint256 nextOffset) { (ret, nextOffset) = asAddressUnchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBoolUnckecked( - bytes memory encoded, - uint offset - ) internal pure returns (bool, uint) { - (uint8 ret, uint nextOffset) = asUint8(encoded, offset); + function asBoolUnckecked(bytes memory encoded, uint256 offset) internal pure returns (bool, uint256) { + (uint8 ret, uint256 nextOffset) = asUint8(encoded, offset); return (ret != 0, nextOffset); } - function asBool( - bytes memory encoded, - uint offset - ) internal pure returns (bool ret, uint nextOffset) { + function asBool(bytes memory encoded, uint256 offset) internal pure returns (bool ret, uint256 nextOffset) { (ret, nextOffset) = asBoolUnckecked(encoded, offset); checkBound(nextOffset, encoded.length); } /* ------------------------------------------------------------------------------------------------- -Remaining library code below was auto-generated by via the following js/node code: - -for (let bytes = 1; bytes <= 32; ++bytes) { - const bits = bytes*8; - console.log( -`function asUint${bits}Unchecked( - bytes memory encoded, - uint offset -) internal pure returns (uint${bits} ret, uint nextOffset) { - assembly ("memory-safe") { + Remaining library code below was auto-generated by via the following js/node code: + + for (let bytes = 1; bytes <= 32; ++bytes) { + const bits = bytes*8; + console.log( + `function asUint${bits}Unchecked( + bytes memory encoded, + uint offset + ) internal pure returns (uint${bits} ret, uint nextOffset) { + assembly ("memory-safe") { nextOffset := add(offset, ${bytes}) ret := mload(add(encoded, nextOffset)) - } - return (ret, nextOffset); -} + } + return (ret, nextOffset); + } -function asUint${bits}( - bytes memory encoded, - uint offset -) internal pure returns (uint${bits} ret, uint nextOffset) { - (ret, nextOffset) = asUint${bits}Unchecked(encoded, offset); - checkBound(nextOffset, encoded.length); -} + function asUint${bits}( + bytes memory encoded, + uint offset + ) internal pure returns (uint${bits} ret, uint nextOffset) { + (ret, nextOffset) = asUint${bits}Unchecked(encoded, offset); + checkBound(nextOffset, encoded.length); + } -function asBytes${bytes}Unchecked( - bytes memory encoded, - uint offset -) internal pure returns (bytes${bytes}, uint) { - (uint${bits} ret, uint nextOffset) = asUint${bits}Unchecked(encoded, offset); - return (bytes${bytes}(ret), nextOffset); -} + function asBytes${bytes}Unchecked( + bytes memory encoded, + uint offset + ) internal pure returns (bytes${bytes}, uint) { + (uint${bits} ret, uint nextOffset) = asUint${bits}Unchecked(encoded, offset); + return (bytes${bytes}(ret), nextOffset); + } -function asBytes${bytes}( - bytes memory encoded, - uint offset -) internal pure returns (bytes${bytes}, uint) { - (uint${bits} ret, uint nextOffset) = asUint${bits}(encoded, offset); - return (bytes${bytes}(ret), nextOffset); -} -` - ); -} -------------------------------------------------------------------------------------------------- */ + function asBytes${bytes}( + bytes memory encoded, + uint offset + ) internal pure returns (bytes${bytes}, uint) { + (uint${bits} ret, uint nextOffset) = asUint${bits}(encoded, offset); + return (bytes${bytes}(ret), nextOffset); + } + ` + ); + } + ------------------------------------------------------------------------------------------------- */ - function asUint8Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint8 ret, uint nextOffset) { + function asUint8Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint8 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 1) ret := mload(add(encoded, nextOffset)) @@ -155,34 +138,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint8( - bytes memory encoded, - uint offset - ) internal pure returns (uint8 ret, uint nextOffset) { + function asUint8(bytes memory encoded, uint256 offset) internal pure returns (uint8 ret, uint256 nextOffset) { (ret, nextOffset) = asUint8Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes1Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes1, uint) { - (uint8 ret, uint nextOffset) = asUint8Unchecked(encoded, offset); + function asBytes1Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes1, uint256) { + (uint8 ret, uint256 nextOffset) = asUint8Unchecked(encoded, offset); return (bytes1(ret), nextOffset); } - function asBytes1( - bytes memory encoded, - uint offset - ) internal pure returns (bytes1, uint) { - (uint8 ret, uint nextOffset) = asUint8(encoded, offset); + function asBytes1(bytes memory encoded, uint256 offset) internal pure returns (bytes1, uint256) { + (uint8 ret, uint256 nextOffset) = asUint8(encoded, offset); return (bytes1(ret), nextOffset); } - function asUint16Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint16 ret, uint nextOffset) { + function asUint16Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint16 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 2) ret := mload(add(encoded, nextOffset)) @@ -190,34 +165,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint16( - bytes memory encoded, - uint offset - ) internal pure returns (uint16 ret, uint nextOffset) { + function asUint16(bytes memory encoded, uint256 offset) internal pure returns (uint16 ret, uint256 nextOffset) { (ret, nextOffset) = asUint16Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes2Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes2, uint) { - (uint16 ret, uint nextOffset) = asUint16Unchecked(encoded, offset); + function asBytes2Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes2, uint256) { + (uint16 ret, uint256 nextOffset) = asUint16Unchecked(encoded, offset); return (bytes2(ret), nextOffset); } - function asBytes2( - bytes memory encoded, - uint offset - ) internal pure returns (bytes2, uint) { - (uint16 ret, uint nextOffset) = asUint16(encoded, offset); + function asBytes2(bytes memory encoded, uint256 offset) internal pure returns (bytes2, uint256) { + (uint16 ret, uint256 nextOffset) = asUint16(encoded, offset); return (bytes2(ret), nextOffset); } - function asUint24Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint24 ret, uint nextOffset) { + function asUint24Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint24 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 3) ret := mload(add(encoded, nextOffset)) @@ -225,34 +192,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint24( - bytes memory encoded, - uint offset - ) internal pure returns (uint24 ret, uint nextOffset) { + function asUint24(bytes memory encoded, uint256 offset) internal pure returns (uint24 ret, uint256 nextOffset) { (ret, nextOffset) = asUint24Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes3Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes3, uint) { - (uint24 ret, uint nextOffset) = asUint24Unchecked(encoded, offset); + function asBytes3Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes3, uint256) { + (uint24 ret, uint256 nextOffset) = asUint24Unchecked(encoded, offset); return (bytes3(ret), nextOffset); } - function asBytes3( - bytes memory encoded, - uint offset - ) internal pure returns (bytes3, uint) { - (uint24 ret, uint nextOffset) = asUint24(encoded, offset); + function asBytes3(bytes memory encoded, uint256 offset) internal pure returns (bytes3, uint256) { + (uint24 ret, uint256 nextOffset) = asUint24(encoded, offset); return (bytes3(ret), nextOffset); } - function asUint32Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint32 ret, uint nextOffset) { + function asUint32Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint32 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 4) ret := mload(add(encoded, nextOffset)) @@ -260,34 +219,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint32( - bytes memory encoded, - uint offset - ) internal pure returns (uint32 ret, uint nextOffset) { + function asUint32(bytes memory encoded, uint256 offset) internal pure returns (uint32 ret, uint256 nextOffset) { (ret, nextOffset) = asUint32Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes4Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes4, uint) { - (uint32 ret, uint nextOffset) = asUint32Unchecked(encoded, offset); + function asBytes4Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes4, uint256) { + (uint32 ret, uint256 nextOffset) = asUint32Unchecked(encoded, offset); return (bytes4(ret), nextOffset); } - function asBytes4( - bytes memory encoded, - uint offset - ) internal pure returns (bytes4, uint) { - (uint32 ret, uint nextOffset) = asUint32(encoded, offset); + function asBytes4(bytes memory encoded, uint256 offset) internal pure returns (bytes4, uint256) { + (uint32 ret, uint256 nextOffset) = asUint32(encoded, offset); return (bytes4(ret), nextOffset); } - function asUint40Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint40 ret, uint nextOffset) { + function asUint40Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint40 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 5) ret := mload(add(encoded, nextOffset)) @@ -295,34 +246,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint40( - bytes memory encoded, - uint offset - ) internal pure returns (uint40 ret, uint nextOffset) { + function asUint40(bytes memory encoded, uint256 offset) internal pure returns (uint40 ret, uint256 nextOffset) { (ret, nextOffset) = asUint40Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes5Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes5, uint) { - (uint40 ret, uint nextOffset) = asUint40Unchecked(encoded, offset); + function asBytes5Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes5, uint256) { + (uint40 ret, uint256 nextOffset) = asUint40Unchecked(encoded, offset); return (bytes5(ret), nextOffset); } - function asBytes5( - bytes memory encoded, - uint offset - ) internal pure returns (bytes5, uint) { - (uint40 ret, uint nextOffset) = asUint40(encoded, offset); + function asBytes5(bytes memory encoded, uint256 offset) internal pure returns (bytes5, uint256) { + (uint40 ret, uint256 nextOffset) = asUint40(encoded, offset); return (bytes5(ret), nextOffset); } - function asUint48Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint48 ret, uint nextOffset) { + function asUint48Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint48 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 6) ret := mload(add(encoded, nextOffset)) @@ -330,34 +273,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint48( - bytes memory encoded, - uint offset - ) internal pure returns (uint48 ret, uint nextOffset) { + function asUint48(bytes memory encoded, uint256 offset) internal pure returns (uint48 ret, uint256 nextOffset) { (ret, nextOffset) = asUint48Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes6Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes6, uint) { - (uint48 ret, uint nextOffset) = asUint48Unchecked(encoded, offset); + function asBytes6Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes6, uint256) { + (uint48 ret, uint256 nextOffset) = asUint48Unchecked(encoded, offset); return (bytes6(ret), nextOffset); } - function asBytes6( - bytes memory encoded, - uint offset - ) internal pure returns (bytes6, uint) { - (uint48 ret, uint nextOffset) = asUint48(encoded, offset); + function asBytes6(bytes memory encoded, uint256 offset) internal pure returns (bytes6, uint256) { + (uint48 ret, uint256 nextOffset) = asUint48(encoded, offset); return (bytes6(ret), nextOffset); } - function asUint56Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint56 ret, uint nextOffset) { + function asUint56Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint56 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 7) ret := mload(add(encoded, nextOffset)) @@ -365,34 +300,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint56( - bytes memory encoded, - uint offset - ) internal pure returns (uint56 ret, uint nextOffset) { + function asUint56(bytes memory encoded, uint256 offset) internal pure returns (uint56 ret, uint256 nextOffset) { (ret, nextOffset) = asUint56Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes7Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes7, uint) { - (uint56 ret, uint nextOffset) = asUint56Unchecked(encoded, offset); + function asBytes7Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes7, uint256) { + (uint56 ret, uint256 nextOffset) = asUint56Unchecked(encoded, offset); return (bytes7(ret), nextOffset); } - function asBytes7( - bytes memory encoded, - uint offset - ) internal pure returns (bytes7, uint) { - (uint56 ret, uint nextOffset) = asUint56(encoded, offset); + function asBytes7(bytes memory encoded, uint256 offset) internal pure returns (bytes7, uint256) { + (uint56 ret, uint256 nextOffset) = asUint56(encoded, offset); return (bytes7(ret), nextOffset); } - function asUint64Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint64 ret, uint nextOffset) { + function asUint64Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint64 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 8) ret := mload(add(encoded, nextOffset)) @@ -400,34 +327,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint64( - bytes memory encoded, - uint offset - ) internal pure returns (uint64 ret, uint nextOffset) { + function asUint64(bytes memory encoded, uint256 offset) internal pure returns (uint64 ret, uint256 nextOffset) { (ret, nextOffset) = asUint64Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes8Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes8, uint) { - (uint64 ret, uint nextOffset) = asUint64Unchecked(encoded, offset); + function asBytes8Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes8, uint256) { + (uint64 ret, uint256 nextOffset) = asUint64Unchecked(encoded, offset); return (bytes8(ret), nextOffset); } - function asBytes8( - bytes memory encoded, - uint offset - ) internal pure returns (bytes8, uint) { - (uint64 ret, uint nextOffset) = asUint64(encoded, offset); + function asBytes8(bytes memory encoded, uint256 offset) internal pure returns (bytes8, uint256) { + (uint64 ret, uint256 nextOffset) = asUint64(encoded, offset); return (bytes8(ret), nextOffset); } - function asUint72Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint72 ret, uint nextOffset) { + function asUint72Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint72 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 9) ret := mload(add(encoded, nextOffset)) @@ -435,34 +354,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint72( - bytes memory encoded, - uint offset - ) internal pure returns (uint72 ret, uint nextOffset) { + function asUint72(bytes memory encoded, uint256 offset) internal pure returns (uint72 ret, uint256 nextOffset) { (ret, nextOffset) = asUint72Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes9Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes9, uint) { - (uint72 ret, uint nextOffset) = asUint72Unchecked(encoded, offset); + function asBytes9Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes9, uint256) { + (uint72 ret, uint256 nextOffset) = asUint72Unchecked(encoded, offset); return (bytes9(ret), nextOffset); } - function asBytes9( - bytes memory encoded, - uint offset - ) internal pure returns (bytes9, uint) { - (uint72 ret, uint nextOffset) = asUint72(encoded, offset); + function asBytes9(bytes memory encoded, uint256 offset) internal pure returns (bytes9, uint256) { + (uint72 ret, uint256 nextOffset) = asUint72(encoded, offset); return (bytes9(ret), nextOffset); } - function asUint80Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint80 ret, uint nextOffset) { + function asUint80Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint80 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 10) ret := mload(add(encoded, nextOffset)) @@ -470,34 +381,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint80( - bytes memory encoded, - uint offset - ) internal pure returns (uint80 ret, uint nextOffset) { + function asUint80(bytes memory encoded, uint256 offset) internal pure returns (uint80 ret, uint256 nextOffset) { (ret, nextOffset) = asUint80Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes10Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes10, uint) { - (uint80 ret, uint nextOffset) = asUint80Unchecked(encoded, offset); + function asBytes10Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes10, uint256) { + (uint80 ret, uint256 nextOffset) = asUint80Unchecked(encoded, offset); return (bytes10(ret), nextOffset); } - function asBytes10( - bytes memory encoded, - uint offset - ) internal pure returns (bytes10, uint) { - (uint80 ret, uint nextOffset) = asUint80(encoded, offset); + function asBytes10(bytes memory encoded, uint256 offset) internal pure returns (bytes10, uint256) { + (uint80 ret, uint256 nextOffset) = asUint80(encoded, offset); return (bytes10(ret), nextOffset); } - function asUint88Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint88 ret, uint nextOffset) { + function asUint88Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint88 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 11) ret := mload(add(encoded, nextOffset)) @@ -505,34 +408,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint88( - bytes memory encoded, - uint offset - ) internal pure returns (uint88 ret, uint nextOffset) { + function asUint88(bytes memory encoded, uint256 offset) internal pure returns (uint88 ret, uint256 nextOffset) { (ret, nextOffset) = asUint88Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes11Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes11, uint) { - (uint88 ret, uint nextOffset) = asUint88Unchecked(encoded, offset); + function asBytes11Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes11, uint256) { + (uint88 ret, uint256 nextOffset) = asUint88Unchecked(encoded, offset); return (bytes11(ret), nextOffset); } - function asBytes11( - bytes memory encoded, - uint offset - ) internal pure returns (bytes11, uint) { - (uint88 ret, uint nextOffset) = asUint88(encoded, offset); + function asBytes11(bytes memory encoded, uint256 offset) internal pure returns (bytes11, uint256) { + (uint88 ret, uint256 nextOffset) = asUint88(encoded, offset); return (bytes11(ret), nextOffset); } - function asUint96Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint96 ret, uint nextOffset) { + function asUint96Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint96 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 12) ret := mload(add(encoded, nextOffset)) @@ -540,34 +435,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint96( - bytes memory encoded, - uint offset - ) internal pure returns (uint96 ret, uint nextOffset) { + function asUint96(bytes memory encoded, uint256 offset) internal pure returns (uint96 ret, uint256 nextOffset) { (ret, nextOffset) = asUint96Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes12Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes12, uint) { - (uint96 ret, uint nextOffset) = asUint96Unchecked(encoded, offset); + function asBytes12Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes12, uint256) { + (uint96 ret, uint256 nextOffset) = asUint96Unchecked(encoded, offset); return (bytes12(ret), nextOffset); } - function asBytes12( - bytes memory encoded, - uint offset - ) internal pure returns (bytes12, uint) { - (uint96 ret, uint nextOffset) = asUint96(encoded, offset); + function asBytes12(bytes memory encoded, uint256 offset) internal pure returns (bytes12, uint256) { + (uint96 ret, uint256 nextOffset) = asUint96(encoded, offset); return (bytes12(ret), nextOffset); } - function asUint104Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint104 ret, uint nextOffset) { + function asUint104Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint104 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 13) ret := mload(add(encoded, nextOffset)) @@ -575,34 +462,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint104( - bytes memory encoded, - uint offset - ) internal pure returns (uint104 ret, uint nextOffset) { + function asUint104(bytes memory encoded, uint256 offset) internal pure returns (uint104 ret, uint256 nextOffset) { (ret, nextOffset) = asUint104Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes13Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes13, uint) { - (uint104 ret, uint nextOffset) = asUint104Unchecked(encoded, offset); + function asBytes13Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes13, uint256) { + (uint104 ret, uint256 nextOffset) = asUint104Unchecked(encoded, offset); return (bytes13(ret), nextOffset); } - function asBytes13( - bytes memory encoded, - uint offset - ) internal pure returns (bytes13, uint) { - (uint104 ret, uint nextOffset) = asUint104(encoded, offset); + function asBytes13(bytes memory encoded, uint256 offset) internal pure returns (bytes13, uint256) { + (uint104 ret, uint256 nextOffset) = asUint104(encoded, offset); return (bytes13(ret), nextOffset); } - function asUint112Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint112 ret, uint nextOffset) { + function asUint112Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint112 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 14) ret := mload(add(encoded, nextOffset)) @@ -610,34 +489,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint112( - bytes memory encoded, - uint offset - ) internal pure returns (uint112 ret, uint nextOffset) { + function asUint112(bytes memory encoded, uint256 offset) internal pure returns (uint112 ret, uint256 nextOffset) { (ret, nextOffset) = asUint112Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes14Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes14, uint) { - (uint112 ret, uint nextOffset) = asUint112Unchecked(encoded, offset); + function asBytes14Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes14, uint256) { + (uint112 ret, uint256 nextOffset) = asUint112Unchecked(encoded, offset); return (bytes14(ret), nextOffset); } - function asBytes14( - bytes memory encoded, - uint offset - ) internal pure returns (bytes14, uint) { - (uint112 ret, uint nextOffset) = asUint112(encoded, offset); + function asBytes14(bytes memory encoded, uint256 offset) internal pure returns (bytes14, uint256) { + (uint112 ret, uint256 nextOffset) = asUint112(encoded, offset); return (bytes14(ret), nextOffset); } - function asUint120Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint120 ret, uint nextOffset) { + function asUint120Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint120 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 15) ret := mload(add(encoded, nextOffset)) @@ -645,34 +516,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint120( - bytes memory encoded, - uint offset - ) internal pure returns (uint120 ret, uint nextOffset) { + function asUint120(bytes memory encoded, uint256 offset) internal pure returns (uint120 ret, uint256 nextOffset) { (ret, nextOffset) = asUint120Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes15Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes15, uint) { - (uint120 ret, uint nextOffset) = asUint120Unchecked(encoded, offset); + function asBytes15Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes15, uint256) { + (uint120 ret, uint256 nextOffset) = asUint120Unchecked(encoded, offset); return (bytes15(ret), nextOffset); } - function asBytes15( - bytes memory encoded, - uint offset - ) internal pure returns (bytes15, uint) { - (uint120 ret, uint nextOffset) = asUint120(encoded, offset); + function asBytes15(bytes memory encoded, uint256 offset) internal pure returns (bytes15, uint256) { + (uint120 ret, uint256 nextOffset) = asUint120(encoded, offset); return (bytes15(ret), nextOffset); } - function asUint128Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint128 ret, uint nextOffset) { + function asUint128Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint128 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 16) ret := mload(add(encoded, nextOffset)) @@ -680,34 +543,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint128( - bytes memory encoded, - uint offset - ) internal pure returns (uint128 ret, uint nextOffset) { + function asUint128(bytes memory encoded, uint256 offset) internal pure returns (uint128 ret, uint256 nextOffset) { (ret, nextOffset) = asUint128Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes16Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes16, uint) { - (uint128 ret, uint nextOffset) = asUint128Unchecked(encoded, offset); + function asBytes16Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes16, uint256) { + (uint128 ret, uint256 nextOffset) = asUint128Unchecked(encoded, offset); return (bytes16(ret), nextOffset); } - function asBytes16( - bytes memory encoded, - uint offset - ) internal pure returns (bytes16, uint) { - (uint128 ret, uint nextOffset) = asUint128(encoded, offset); + function asBytes16(bytes memory encoded, uint256 offset) internal pure returns (bytes16, uint256) { + (uint128 ret, uint256 nextOffset) = asUint128(encoded, offset); return (bytes16(ret), nextOffset); } - function asUint136Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint136 ret, uint nextOffset) { + function asUint136Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint136 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 17) ret := mload(add(encoded, nextOffset)) @@ -715,34 +570,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint136( - bytes memory encoded, - uint offset - ) internal pure returns (uint136 ret, uint nextOffset) { + function asUint136(bytes memory encoded, uint256 offset) internal pure returns (uint136 ret, uint256 nextOffset) { (ret, nextOffset) = asUint136Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes17Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes17, uint) { - (uint136 ret, uint nextOffset) = asUint136Unchecked(encoded, offset); + function asBytes17Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes17, uint256) { + (uint136 ret, uint256 nextOffset) = asUint136Unchecked(encoded, offset); return (bytes17(ret), nextOffset); } - function asBytes17( - bytes memory encoded, - uint offset - ) internal pure returns (bytes17, uint) { - (uint136 ret, uint nextOffset) = asUint136(encoded, offset); + function asBytes17(bytes memory encoded, uint256 offset) internal pure returns (bytes17, uint256) { + (uint136 ret, uint256 nextOffset) = asUint136(encoded, offset); return (bytes17(ret), nextOffset); } - function asUint144Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint144 ret, uint nextOffset) { + function asUint144Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint144 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 18) ret := mload(add(encoded, nextOffset)) @@ -750,34 +597,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint144( - bytes memory encoded, - uint offset - ) internal pure returns (uint144 ret, uint nextOffset) { + function asUint144(bytes memory encoded, uint256 offset) internal pure returns (uint144 ret, uint256 nextOffset) { (ret, nextOffset) = asUint144Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes18Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes18, uint) { - (uint144 ret, uint nextOffset) = asUint144Unchecked(encoded, offset); + function asBytes18Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes18, uint256) { + (uint144 ret, uint256 nextOffset) = asUint144Unchecked(encoded, offset); return (bytes18(ret), nextOffset); } - function asBytes18( - bytes memory encoded, - uint offset - ) internal pure returns (bytes18, uint) { - (uint144 ret, uint nextOffset) = asUint144(encoded, offset); + function asBytes18(bytes memory encoded, uint256 offset) internal pure returns (bytes18, uint256) { + (uint144 ret, uint256 nextOffset) = asUint144(encoded, offset); return (bytes18(ret), nextOffset); } - function asUint152Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint152 ret, uint nextOffset) { + function asUint152Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint152 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 19) ret := mload(add(encoded, nextOffset)) @@ -785,34 +624,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint152( - bytes memory encoded, - uint offset - ) internal pure returns (uint152 ret, uint nextOffset) { + function asUint152(bytes memory encoded, uint256 offset) internal pure returns (uint152 ret, uint256 nextOffset) { (ret, nextOffset) = asUint152Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes19Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes19, uint) { - (uint152 ret, uint nextOffset) = asUint152Unchecked(encoded, offset); + function asBytes19Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes19, uint256) { + (uint152 ret, uint256 nextOffset) = asUint152Unchecked(encoded, offset); return (bytes19(ret), nextOffset); } - function asBytes19( - bytes memory encoded, - uint offset - ) internal pure returns (bytes19, uint) { - (uint152 ret, uint nextOffset) = asUint152(encoded, offset); + function asBytes19(bytes memory encoded, uint256 offset) internal pure returns (bytes19, uint256) { + (uint152 ret, uint256 nextOffset) = asUint152(encoded, offset); return (bytes19(ret), nextOffset); } - function asUint160Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint160 ret, uint nextOffset) { + function asUint160Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint160 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 20) ret := mload(add(encoded, nextOffset)) @@ -820,34 +651,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint160( - bytes memory encoded, - uint offset - ) internal pure returns (uint160 ret, uint nextOffset) { + function asUint160(bytes memory encoded, uint256 offset) internal pure returns (uint160 ret, uint256 nextOffset) { (ret, nextOffset) = asUint160Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes20Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes20, uint) { - (uint160 ret, uint nextOffset) = asUint160Unchecked(encoded, offset); + function asBytes20Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes20, uint256) { + (uint160 ret, uint256 nextOffset) = asUint160Unchecked(encoded, offset); return (bytes20(ret), nextOffset); } - function asBytes20( - bytes memory encoded, - uint offset - ) internal pure returns (bytes20, uint) { - (uint160 ret, uint nextOffset) = asUint160(encoded, offset); + function asBytes20(bytes memory encoded, uint256 offset) internal pure returns (bytes20, uint256) { + (uint160 ret, uint256 nextOffset) = asUint160(encoded, offset); return (bytes20(ret), nextOffset); } - function asUint168Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint168 ret, uint nextOffset) { + function asUint168Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint168 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 21) ret := mload(add(encoded, nextOffset)) @@ -855,34 +678,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint168( - bytes memory encoded, - uint offset - ) internal pure returns (uint168 ret, uint nextOffset) { + function asUint168(bytes memory encoded, uint256 offset) internal pure returns (uint168 ret, uint256 nextOffset) { (ret, nextOffset) = asUint168Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes21Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes21, uint) { - (uint168 ret, uint nextOffset) = asUint168Unchecked(encoded, offset); + function asBytes21Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes21, uint256) { + (uint168 ret, uint256 nextOffset) = asUint168Unchecked(encoded, offset); return (bytes21(ret), nextOffset); } - function asBytes21( - bytes memory encoded, - uint offset - ) internal pure returns (bytes21, uint) { - (uint168 ret, uint nextOffset) = asUint168(encoded, offset); + function asBytes21(bytes memory encoded, uint256 offset) internal pure returns (bytes21, uint256) { + (uint168 ret, uint256 nextOffset) = asUint168(encoded, offset); return (bytes21(ret), nextOffset); } - function asUint176Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint176 ret, uint nextOffset) { + function asUint176Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint176 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 22) ret := mload(add(encoded, nextOffset)) @@ -890,34 +705,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint176( - bytes memory encoded, - uint offset - ) internal pure returns (uint176 ret, uint nextOffset) { + function asUint176(bytes memory encoded, uint256 offset) internal pure returns (uint176 ret, uint256 nextOffset) { (ret, nextOffset) = asUint176Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes22Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes22, uint) { - (uint176 ret, uint nextOffset) = asUint176Unchecked(encoded, offset); + function asBytes22Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes22, uint256) { + (uint176 ret, uint256 nextOffset) = asUint176Unchecked(encoded, offset); return (bytes22(ret), nextOffset); } - function asBytes22( - bytes memory encoded, - uint offset - ) internal pure returns (bytes22, uint) { - (uint176 ret, uint nextOffset) = asUint176(encoded, offset); + function asBytes22(bytes memory encoded, uint256 offset) internal pure returns (bytes22, uint256) { + (uint176 ret, uint256 nextOffset) = asUint176(encoded, offset); return (bytes22(ret), nextOffset); } - function asUint184Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint184 ret, uint nextOffset) { + function asUint184Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint184 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 23) ret := mload(add(encoded, nextOffset)) @@ -925,34 +732,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint184( - bytes memory encoded, - uint offset - ) internal pure returns (uint184 ret, uint nextOffset) { + function asUint184(bytes memory encoded, uint256 offset) internal pure returns (uint184 ret, uint256 nextOffset) { (ret, nextOffset) = asUint184Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes23Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes23, uint) { - (uint184 ret, uint nextOffset) = asUint184Unchecked(encoded, offset); + function asBytes23Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes23, uint256) { + (uint184 ret, uint256 nextOffset) = asUint184Unchecked(encoded, offset); return (bytes23(ret), nextOffset); } - function asBytes23( - bytes memory encoded, - uint offset - ) internal pure returns (bytes23, uint) { - (uint184 ret, uint nextOffset) = asUint184(encoded, offset); + function asBytes23(bytes memory encoded, uint256 offset) internal pure returns (bytes23, uint256) { + (uint184 ret, uint256 nextOffset) = asUint184(encoded, offset); return (bytes23(ret), nextOffset); } - function asUint192Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint192 ret, uint nextOffset) { + function asUint192Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint192 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 24) ret := mload(add(encoded, nextOffset)) @@ -960,34 +759,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint192( - bytes memory encoded, - uint offset - ) internal pure returns (uint192 ret, uint nextOffset) { + function asUint192(bytes memory encoded, uint256 offset) internal pure returns (uint192 ret, uint256 nextOffset) { (ret, nextOffset) = asUint192Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes24Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes24, uint) { - (uint192 ret, uint nextOffset) = asUint192Unchecked(encoded, offset); + function asBytes24Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes24, uint256) { + (uint192 ret, uint256 nextOffset) = asUint192Unchecked(encoded, offset); return (bytes24(ret), nextOffset); } - function asBytes24( - bytes memory encoded, - uint offset - ) internal pure returns (bytes24, uint) { - (uint192 ret, uint nextOffset) = asUint192(encoded, offset); + function asBytes24(bytes memory encoded, uint256 offset) internal pure returns (bytes24, uint256) { + (uint192 ret, uint256 nextOffset) = asUint192(encoded, offset); return (bytes24(ret), nextOffset); } - function asUint200Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint200 ret, uint nextOffset) { + function asUint200Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint200 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 25) ret := mload(add(encoded, nextOffset)) @@ -995,34 +786,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint200( - bytes memory encoded, - uint offset - ) internal pure returns (uint200 ret, uint nextOffset) { + function asUint200(bytes memory encoded, uint256 offset) internal pure returns (uint200 ret, uint256 nextOffset) { (ret, nextOffset) = asUint200Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes25Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes25, uint) { - (uint200 ret, uint nextOffset) = asUint200Unchecked(encoded, offset); + function asBytes25Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes25, uint256) { + (uint200 ret, uint256 nextOffset) = asUint200Unchecked(encoded, offset); return (bytes25(ret), nextOffset); } - function asBytes25( - bytes memory encoded, - uint offset - ) internal pure returns (bytes25, uint) { - (uint200 ret, uint nextOffset) = asUint200(encoded, offset); + function asBytes25(bytes memory encoded, uint256 offset) internal pure returns (bytes25, uint256) { + (uint200 ret, uint256 nextOffset) = asUint200(encoded, offset); return (bytes25(ret), nextOffset); } - function asUint208Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint208 ret, uint nextOffset) { + function asUint208Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint208 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 26) ret := mload(add(encoded, nextOffset)) @@ -1030,34 +813,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint208( - bytes memory encoded, - uint offset - ) internal pure returns (uint208 ret, uint nextOffset) { + function asUint208(bytes memory encoded, uint256 offset) internal pure returns (uint208 ret, uint256 nextOffset) { (ret, nextOffset) = asUint208Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes26Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes26, uint) { - (uint208 ret, uint nextOffset) = asUint208Unchecked(encoded, offset); + function asBytes26Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes26, uint256) { + (uint208 ret, uint256 nextOffset) = asUint208Unchecked(encoded, offset); return (bytes26(ret), nextOffset); } - function asBytes26( - bytes memory encoded, - uint offset - ) internal pure returns (bytes26, uint) { - (uint208 ret, uint nextOffset) = asUint208(encoded, offset); + function asBytes26(bytes memory encoded, uint256 offset) internal pure returns (bytes26, uint256) { + (uint208 ret, uint256 nextOffset) = asUint208(encoded, offset); return (bytes26(ret), nextOffset); } - function asUint216Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint216 ret, uint nextOffset) { + function asUint216Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint216 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 27) ret := mload(add(encoded, nextOffset)) @@ -1065,34 +840,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint216( - bytes memory encoded, - uint offset - ) internal pure returns (uint216 ret, uint nextOffset) { + function asUint216(bytes memory encoded, uint256 offset) internal pure returns (uint216 ret, uint256 nextOffset) { (ret, nextOffset) = asUint216Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes27Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes27, uint) { - (uint216 ret, uint nextOffset) = asUint216Unchecked(encoded, offset); + function asBytes27Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes27, uint256) { + (uint216 ret, uint256 nextOffset) = asUint216Unchecked(encoded, offset); return (bytes27(ret), nextOffset); } - function asBytes27( - bytes memory encoded, - uint offset - ) internal pure returns (bytes27, uint) { - (uint216 ret, uint nextOffset) = asUint216(encoded, offset); + function asBytes27(bytes memory encoded, uint256 offset) internal pure returns (bytes27, uint256) { + (uint216 ret, uint256 nextOffset) = asUint216(encoded, offset); return (bytes27(ret), nextOffset); } - function asUint224Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint224 ret, uint nextOffset) { + function asUint224Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint224 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 28) ret := mload(add(encoded, nextOffset)) @@ -1100,34 +867,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint224( - bytes memory encoded, - uint offset - ) internal pure returns (uint224 ret, uint nextOffset) { + function asUint224(bytes memory encoded, uint256 offset) internal pure returns (uint224 ret, uint256 nextOffset) { (ret, nextOffset) = asUint224Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes28Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes28, uint) { - (uint224 ret, uint nextOffset) = asUint224Unchecked(encoded, offset); + function asBytes28Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes28, uint256) { + (uint224 ret, uint256 nextOffset) = asUint224Unchecked(encoded, offset); return (bytes28(ret), nextOffset); } - function asBytes28( - bytes memory encoded, - uint offset - ) internal pure returns (bytes28, uint) { - (uint224 ret, uint nextOffset) = asUint224(encoded, offset); + function asBytes28(bytes memory encoded, uint256 offset) internal pure returns (bytes28, uint256) { + (uint224 ret, uint256 nextOffset) = asUint224(encoded, offset); return (bytes28(ret), nextOffset); } - function asUint232Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint232 ret, uint nextOffset) { + function asUint232Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint232 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 29) ret := mload(add(encoded, nextOffset)) @@ -1135,34 +894,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint232( - bytes memory encoded, - uint offset - ) internal pure returns (uint232 ret, uint nextOffset) { + function asUint232(bytes memory encoded, uint256 offset) internal pure returns (uint232 ret, uint256 nextOffset) { (ret, nextOffset) = asUint232Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes29Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes29, uint) { - (uint232 ret, uint nextOffset) = asUint232Unchecked(encoded, offset); + function asBytes29Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes29, uint256) { + (uint232 ret, uint256 nextOffset) = asUint232Unchecked(encoded, offset); return (bytes29(ret), nextOffset); } - function asBytes29( - bytes memory encoded, - uint offset - ) internal pure returns (bytes29, uint) { - (uint232 ret, uint nextOffset) = asUint232(encoded, offset); + function asBytes29(bytes memory encoded, uint256 offset) internal pure returns (bytes29, uint256) { + (uint232 ret, uint256 nextOffset) = asUint232(encoded, offset); return (bytes29(ret), nextOffset); } - function asUint240Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint240 ret, uint nextOffset) { + function asUint240Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint240 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 30) ret := mload(add(encoded, nextOffset)) @@ -1170,34 +921,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint240( - bytes memory encoded, - uint offset - ) internal pure returns (uint240 ret, uint nextOffset) { + function asUint240(bytes memory encoded, uint256 offset) internal pure returns (uint240 ret, uint256 nextOffset) { (ret, nextOffset) = asUint240Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes30Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes30, uint) { - (uint240 ret, uint nextOffset) = asUint240Unchecked(encoded, offset); + function asBytes30Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes30, uint256) { + (uint240 ret, uint256 nextOffset) = asUint240Unchecked(encoded, offset); return (bytes30(ret), nextOffset); } - function asBytes30( - bytes memory encoded, - uint offset - ) internal pure returns (bytes30, uint) { - (uint240 ret, uint nextOffset) = asUint240(encoded, offset); + function asBytes30(bytes memory encoded, uint256 offset) internal pure returns (bytes30, uint256) { + (uint240 ret, uint256 nextOffset) = asUint240(encoded, offset); return (bytes30(ret), nextOffset); } - function asUint248Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint248 ret, uint nextOffset) { + function asUint248Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint248 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 31) ret := mload(add(encoded, nextOffset)) @@ -1205,34 +948,26 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint248( - bytes memory encoded, - uint offset - ) internal pure returns (uint248 ret, uint nextOffset) { + function asUint248(bytes memory encoded, uint256 offset) internal pure returns (uint248 ret, uint256 nextOffset) { (ret, nextOffset) = asUint248Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes31Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes31, uint) { - (uint248 ret, uint nextOffset) = asUint248Unchecked(encoded, offset); + function asBytes31Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes31, uint256) { + (uint248 ret, uint256 nextOffset) = asUint248Unchecked(encoded, offset); return (bytes31(ret), nextOffset); } - function asBytes31( - bytes memory encoded, - uint offset - ) internal pure returns (bytes31, uint) { - (uint248 ret, uint nextOffset) = asUint248(encoded, offset); + function asBytes31(bytes memory encoded, uint256 offset) internal pure returns (bytes31, uint256) { + (uint248 ret, uint256 nextOffset) = asUint248(encoded, offset); return (bytes31(ret), nextOffset); } - function asUint256Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (uint256 ret, uint nextOffset) { + function asUint256Unchecked(bytes memory encoded, uint256 offset) + internal + pure + returns (uint256 ret, uint256 nextOffset) + { assembly ("memory-safe") { nextOffset := add(offset, 32) ret := mload(add(encoded, nextOffset)) @@ -1240,27 +975,18 @@ function asBytes${bytes}( return (ret, nextOffset); } - function asUint256( - bytes memory encoded, - uint offset - ) internal pure returns (uint256 ret, uint nextOffset) { + function asUint256(bytes memory encoded, uint256 offset) internal pure returns (uint256 ret, uint256 nextOffset) { (ret, nextOffset) = asUint256Unchecked(encoded, offset); checkBound(nextOffset, encoded.length); } - function asBytes32Unchecked( - bytes memory encoded, - uint offset - ) internal pure returns (bytes32, uint) { - (uint256 ret, uint nextOffset) = asUint256Unchecked(encoded, offset); + function asBytes32Unchecked(bytes memory encoded, uint256 offset) internal pure returns (bytes32, uint256) { + (uint256 ret, uint256 nextOffset) = asUint256Unchecked(encoded, offset); return (bytes32(ret), nextOffset); } - function asBytes32( - bytes memory encoded, - uint offset - ) internal pure returns (bytes32, uint) { - (uint256 ret, uint nextOffset) = asUint256(encoded, offset); + function asBytes32(bytes memory encoded, uint256 offset) internal pure returns (bytes32, uint256) { + (uint256 ret, uint256 nextOffset) = asUint256(encoded, offset); return (bytes32(ret), nextOffset); } } diff --git a/src/wormhole/automatic-relayer/lib/PayloadDecoder.sol b/src/wormhole/automatic-relayer/lib/PayloadDecoder.sol index 1eb7443..918da55 100644 --- a/src/wormhole/automatic-relayer/lib/PayloadDecoder.sol +++ b/src/wormhole/automatic-relayer/lib/PayloadDecoder.sol @@ -26,9 +26,7 @@ library PayloadDecoder { // inefficient (unless the optimizer is smart enough to just concatenate them tail-recursion // style which seems highly unlikely) - function encode( - DeliveryInstruction memory strct - ) internal pure returns (bytes memory encoded) { + function encode(DeliveryInstruction memory strct) internal pure returns (bytes memory encoded) { encoded = abi.encodePacked( PAYLOAD_ID_DELIVERY_INSTRUCTION, strct.targetChain, @@ -49,14 +47,8 @@ library PayloadDecoder { ); } - function decodeDeliveryInstruction( - bytes memory encoded - ) internal pure returns (DeliveryInstruction memory strct) { - uint256 offset = checkUint8( - encoded, - 0, - PAYLOAD_ID_DELIVERY_INSTRUCTION - ); + function decodeDeliveryInstruction(bytes memory encoded) internal pure returns (DeliveryInstruction memory strct) { + uint256 offset = checkUint8(encoded, 0, PAYLOAD_ID_DELIVERY_INSTRUCTION); uint256 requestedReceiverValue; uint256 extraReceiverValue; @@ -69,26 +61,18 @@ library PayloadDecoder { (strct.encodedExecutionInfo, offset) = decodeBytes(encoded, offset); (strct.refundChain, offset) = encoded.asUint16Unchecked(offset); (strct.refundAddress, offset) = encoded.asBytes32Unchecked(offset); - (strct.refundDeliveryProvider, offset) = encoded.asBytes32Unchecked( - offset - ); - (strct.sourceDeliveryProvider, offset) = encoded.asBytes32Unchecked( - offset - ); + (strct.refundDeliveryProvider, offset) = encoded.asBytes32Unchecked(offset); + (strct.sourceDeliveryProvider, offset) = encoded.asBytes32Unchecked(offset); (strct.senderAddress, offset) = encoded.asBytes32Unchecked(offset); (strct.vaaKeys, offset) = decodeVaaKeyArray(encoded, offset); - strct.requestedReceiverValue = TargetNative.wrap( - requestedReceiverValue - ); + strct.requestedReceiverValue = TargetNative.wrap(requestedReceiverValue); strct.extraReceiverValue = TargetNative.wrap(extraReceiverValue); checkLength(encoded, offset); } - function encode( - RedeliveryInstruction memory strct - ) internal pure returns (bytes memory encoded) { + function encode(RedeliveryInstruction memory strct) internal pure returns (bytes memory encoded) { bytes memory vaaKey = encodeVaaKey(strct.deliveryVaaKey); encoded = abi.encodePacked( PAYLOAD_ID_REDELIVERY_INSTRUCTION, @@ -101,49 +85,34 @@ library PayloadDecoder { ); } - function decodeRedeliveryInstruction( - bytes memory encoded - ) internal pure returns (RedeliveryInstruction memory strct) { - uint256 offset = checkUint8( - encoded, - 0, - PAYLOAD_ID_REDELIVERY_INSTRUCTION - ); + function decodeRedeliveryInstruction(bytes memory encoded) + internal + pure + returns (RedeliveryInstruction memory strct) + { + uint256 offset = checkUint8(encoded, 0, PAYLOAD_ID_REDELIVERY_INSTRUCTION); uint256 newRequestedReceiverValue; (strct.deliveryVaaKey, offset) = decodeVaaKey(encoded, offset); (strct.targetChain, offset) = encoded.asUint16Unchecked(offset); - (newRequestedReceiverValue, offset) = encoded.asUint256Unchecked( - offset - ); + (newRequestedReceiverValue, offset) = encoded.asUint256Unchecked(offset); (strct.newEncodedExecutionInfo, offset) = decodeBytes(encoded, offset); - (strct.newSourceDeliveryProvider, offset) = encoded.asBytes32Unchecked( - offset - ); + (strct.newSourceDeliveryProvider, offset) = encoded.asBytes32Unchecked(offset); (strct.newSenderAddress, offset) = encoded.asBytes32Unchecked(offset); - strct.newRequestedReceiverValue = TargetNative.wrap( - newRequestedReceiverValue - ); + strct.newRequestedReceiverValue = TargetNative.wrap(newRequestedReceiverValue); checkLength(encoded, offset); } - function encode( - DeliveryOverride memory strct - ) internal pure returns (bytes memory encoded) { + function encode(DeliveryOverride memory strct) internal pure returns (bytes memory encoded) { encoded = abi.encodePacked( - VERSION_DELIVERY_OVERRIDE, - strct.newReceiverValue, - encodeBytes(strct.newExecutionInfo), - strct.redeliveryHash + VERSION_DELIVERY_OVERRIDE, strct.newReceiverValue, encodeBytes(strct.newExecutionInfo), strct.redeliveryHash ); } - function decodeDeliveryOverride( - bytes memory encoded - ) internal pure returns (DeliveryOverride memory strct) { + function decodeDeliveryOverride(bytes memory encoded) internal pure returns (DeliveryOverride memory strct) { uint256 offset = checkUint8(encoded, 0, VERSION_DELIVERY_OVERRIDE); uint256 receiverValue; @@ -159,12 +128,10 @@ library PayloadDecoder { // ------------------------------------------ private -------------------------------------------- - function encodeVaaKeyArray( - VaaKey[] memory vaaKeys - ) private pure returns (bytes memory encoded) { + function encodeVaaKeyArray(VaaKey[] memory vaaKeys) private pure returns (bytes memory encoded) { assert(vaaKeys.length < type(uint8).max); encoded = abi.encodePacked(uint8(vaaKeys.length)); - for (uint256 i = 0; i < vaaKeys.length; ) { + for (uint256 i = 0; i < vaaKeys.length;) { encoded = abi.encodePacked(encoded, encodeVaaKey(vaaKeys[i])); unchecked { ++i; @@ -172,14 +139,15 @@ library PayloadDecoder { } } - function decodeVaaKeyArray( - bytes memory encoded, - uint256 startOffset - ) private pure returns (VaaKey[] memory vaaKeys, uint256 offset) { + function decodeVaaKeyArray(bytes memory encoded, uint256 startOffset) + private + pure + returns (VaaKey[] memory vaaKeys, uint256 offset) + { uint8 vaaKeysLength; (vaaKeysLength, offset) = encoded.asUint8Unchecked(startOffset); vaaKeys = new VaaKey[](vaaKeysLength); - for (uint256 i = 0; i < vaaKeys.length; ) { + for (uint256 i = 0; i < vaaKeys.length;) { (vaaKeys[i], offset) = decodeVaaKey(encoded, offset); unchecked { ++i; @@ -187,50 +155,42 @@ library PayloadDecoder { } } - function encodeVaaKey( - VaaKey memory vaaKey - ) private pure returns (bytes memory encoded) { - encoded = abi.encodePacked( - encoded, - VERSION_VAAKEY, - vaaKey.chainId, - vaaKey.emitterAddress, - vaaKey.sequence - ); + function encodeVaaKey(VaaKey memory vaaKey) private pure returns (bytes memory encoded) { + encoded = abi.encodePacked(encoded, VERSION_VAAKEY, vaaKey.chainId, vaaKey.emitterAddress, vaaKey.sequence); } - function decodeVaaKey( - bytes memory encoded, - uint256 startOffset - ) private pure returns (VaaKey memory vaaKey, uint256 offset) { + function decodeVaaKey(bytes memory encoded, uint256 startOffset) + private + pure + returns (VaaKey memory vaaKey, uint256 offset) + { offset = checkUint8(encoded, startOffset, VERSION_VAAKEY); (vaaKey.chainId, offset) = encoded.asUint16Unchecked(offset); (vaaKey.emitterAddress, offset) = encoded.asBytes32Unchecked(offset); (vaaKey.sequence, offset) = encoded.asUint64Unchecked(offset); } - function encodeBytes( - bytes memory payload - ) private pure returns (bytes memory encoded) { + function encodeBytes(bytes memory payload) private pure returns (bytes memory encoded) { //casting payload.length to uint32 is safe because you'll be hard-pressed to allocate 4 GB of // EVM memory in a single transaction encoded = abi.encodePacked(uint32(payload.length), payload); } - function decodeBytes( - bytes memory encoded, - uint256 startOffset - ) private pure returns (bytes memory payload, uint256 offset) { + function decodeBytes(bytes memory encoded, uint256 startOffset) + private + pure + returns (bytes memory payload, uint256 offset) + { uint32 payloadLength; (payloadLength, offset) = encoded.asUint32Unchecked(startOffset); (payload, offset) = encoded.sliceUnchecked(offset, payloadLength); } - function checkUint8( - bytes memory encoded, - uint256 startOffset, - uint8 expectedPayloadId - ) private pure returns (uint256 offset) { + function checkUint8(bytes memory encoded, uint256 startOffset, uint8 expectedPayloadId) + private + pure + returns (uint256 offset) + { uint8 parsedPayloadId; (parsedPayloadId, offset) = encoded.asUint8Unchecked(startOffset); if (parsedPayloadId != expectedPayloadId) {} diff --git a/src/wormhole/automatic-relayer/lib/TypedUnits.sol b/src/wormhole/automatic-relayer/lib/TypedUnits.sol index 4eb5306..9fe7874 100644 --- a/src/wormhole/automatic-relayer/lib/TypedUnits.sol +++ b/src/wormhole/automatic-relayer/lib/TypedUnits.sol @@ -15,15 +15,7 @@ type LocalNative is uint256; type TargetNative is uint256; -using { - addWei as +, - subWei as -, - lteWei as <=, - ltWei as <, - gtWei as >, - eqWei as ==, - neqWei as != -} for Wei global; +using {addWei as +, subWei as -, lteWei as <=, ltWei as <, gtWei as >, eqWei as ==, neqWei as !=} for Wei global; using {addTargetNative as +, subTargetNative as -} for TargetNative global; using { leLocalNative as <, @@ -32,11 +24,7 @@ using { addLocalNative as +, subLocalNative as - } for LocalNative global; -using { - ltGas as <, - lteGas as <=, - subGas as - -} for Gas global; +using {ltGas as <, lteGas as <=, subGas as -} for Gas global; using WeiLib for Wei; using GasLib for Gas; @@ -114,16 +102,7 @@ function leqLocalNative(LocalNative a, LocalNative b) pure returns (bool) { library WeiLib { using { - toDollars, - toGas, - convertAsset, - min, - max, - scale, - unwrap, - asGasPrice, - asTargetNative, - asLocalNative + toDollars, toGas, convertAsset, min, max, scale, unwrap, asGasPrice, asTargetNative, asLocalNative } for Wei; function min(Wei x, Wei maxVal) internal pure returns (Wei) { @@ -259,4 +238,4 @@ library LocalNativeLib { function asNative(LocalNative w) internal pure returns (Wei) { return Wei.wrap(LocalNative.unwrap(w)); } -} \ No newline at end of file +} diff --git a/src/wormhole/specialized-relayer/WormholeHelper.sol b/src/wormhole/specialized-relayer/WormholeHelper.sol index c174424..6ebfe7f 100644 --- a/src/wormhole/specialized-relayer/WormholeHelper.sol +++ b/src/wormhole/specialized-relayer/WormholeHelper.sol @@ -19,18 +19,144 @@ interface IWormholeReceiver { /// @notice in real-world scenario the off-chain infra will just sign the VAAs but this helpers mocks both signing and relaying /// MORE INFO: https://docs.wormhole.com/wormhole/quick-start/cross-chain-dev/specialized-relayer contract WormholeHelper is Test { + /*/////////////////////////////////////////////////////////////// + CONSTANTS + //////////////////////////////////////////////////////////////*/ + + /// @dev LogMessagePublished (index_topic_1 address sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel) + bytes32 constant MESSAGE_EVENT_SELECTOR = 0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2; + + /*/////////////////////////////////////////////////////////////// + EXTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /// @dev single dst x default event selector + /// @param srcChainId is the wormhole identifier of the source chain + /// @param dstForkId is the dst fork id to deliver the message + /// @param dstWormhole is the wormhole core contract on dst chain + /// @param dstTarget is the final receiver of the message + /// @param srcLogs is the logs after message dispatch on src chain + function help( + uint16 srcChainId, + uint256 dstForkId, + address dstWormhole, + address dstTarget, + Vm.Log[] calldata srcLogs + ) external { + _help(srcChainId, dstForkId, dstWormhole, dstTarget, MESSAGE_EVENT_SELECTOR, srcLogs); + } + + /// @dev single dst x user-specified event selector function help( uint16 srcChainId, - uint16 dstChainId, uint256 dstForkId, address dstWormhole, address dstTarget, + bytes32 msgEventSelector, Vm.Log[] calldata srcLogs ) external { + _help(srcChainId, dstForkId, dstWormhole, dstTarget, msgEventSelector, srcLogs); + } + + /// @dev multi dst x default event selector + function help( + uint16 srcChainId, + uint256[] memory dstForkId, + address[] memory dstWormhole, + address[] memory dstTarget, + Vm.Log[] calldata srcLogs + ) external { + for (uint256 i; i < dstForkId.length;) { + _help(srcChainId, dstForkId[i], dstWormhole[i], dstTarget[i], MESSAGE_EVENT_SELECTOR, srcLogs); + + unchecked { + ++i; + } + } + } + + /// @dev multi dst x user-specified event selector + function help( + uint16 srcChainId, + uint256[] memory dstForkId, + address[] memory dstWormhole, + address[] memory dstTarget, + bytes32 msgEventSelector, + Vm.Log[] calldata srcLogs + ) external { + for (uint256 i; i < dstForkId.length;) { + _help(srcChainId, dstForkId[i], dstWormhole[i], dstTarget[i], msgEventSelector, srcLogs); + + unchecked { + ++i; + } + } + } + + /// @dev helps find logs of `length` for default event selector + function findLogs(Vm.Log[] calldata logs, uint256 length) external pure returns (Vm.Log[] memory HLLogs) { + return _findLogs(logs, MESSAGE_EVENT_SELECTOR, length); + } + + /*/////////////////////////////////////////////////////////////// + INTERNAL HELPER FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + struct LocalVars { + uint256 prevForkId; + uint64 sequence; + uint32 nonce; + bytes payload; + uint8 consistencyLevel; + address dstAddress; + } + + function _help( + uint16 srcChainId, + uint256 dstForkId, + address dstWormhole, + address dstTarget, + bytes32 eventSelector, + Vm.Log[] calldata srcLogs + ) internal { + LocalVars memory v; + + v.prevForkId = vm.activeFork(); vm.selectFork(dstForkId); - IWormhole wormhole = IWormhole(dstWormhole); + for (uint256 i; i < srcLogs.length; i++) { + Vm.Log memory log = srcLogs[i]; + + if (log.topics[0] == eventSelector) { + (v.sequence, v.nonce, v.payload, v.consistencyLevel) = + abi.decode(log.data, (uint64, uint32, bytes, uint8)); + + /// @dev overrides wormhole guardian set to a preferred set + _prepareWormhole(dstWormhole); + + /// @dev generates the VAA using our overriden guardian set + bytes memory encodedVAA = _generateVAA( + srcChainId, + v.nonce, + TypeCasts.bytes32ToAddress(log.topics[1]), + v.sequence, + v.consistencyLevel, + v.payload, + dstWormhole + ); + + /// @dev delivers the message by passing the new guardian set to receiver + IWormholeReceiver(dstTarget).receiveMessage(encodedVAA); + } + } + + vm.selectFork(v.prevForkId); + } + /// @dev overrides the guardian set by choosing slot + /// TODO: slot works till the guardianSetIndex is 3 + function _prepareWormhole(address dstWormhole) internal { + IWormhole wormhole = IWormhole(dstWormhole); bytes32 lastSlot = 0x2fc7941cecc943bf2000c5d7068f2b8c8e9a29be62acd583fe9e6e90489a8c82; uint256 lastKey = 420; @@ -40,17 +166,31 @@ contract WormholeHelper is Test { lastSlot = bytes32(uint256(lastSlot) + 1); ++lastKey; } + } + + /// @dev generates the encoded vaa + function _generateVAA( + uint16 srcChainId, + uint32 nonce, + address emitterAddress, + uint64 sequence, + uint8 consistencyLevel, + bytes memory payload, + address dstWormhole + ) internal view returns (bytes memory) { + IWormhole wormhole = IWormhole(dstWormhole); /// @dev generates vaa hash IWormhole.VM memory vaa = IWormhole.VM( uint8(1), + /// version = 1 uint32(block.timestamp), - uint32(0), + nonce, srcChainId, - TypeCasts.addressToBytes32(vm.addr(419)), - uint64(0), - uint8(0), - abi.encode(type(uint256).max), + TypeCasts.addressToBytes32(emitterAddress), + sequence, + consistencyLevel, + payload, wormhole.getCurrentGuardianSetIndex(), new IWormhole.Signature[](19), bytes32(0) @@ -66,15 +206,12 @@ contract WormholeHelper is Test { vaa.payload ); - console.logBytes(vaa.payload); - vaa.hash = keccak256(abi.encodePacked(keccak256(body))); - lastKey = 420; + uint256 lastKey = 420; for (uint256 i; i < 19; i++) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(lastKey, vaa.hash); vaa.signatures[i] = IWormhole.Signature(r, s, v, uint8(i)); - console.log(vm.addr(lastKey)); ++lastKey; } @@ -89,9 +226,28 @@ contract WormholeHelper is Test { ); } - encodedVaa = abi.encodePacked(encodedVaa, body); + return abi.encodePacked(encodedVaa, body); + } + + /// @dev helper to get logs + function _findLogs(Vm.Log[] memory logs, bytes32 dispatchSelector, uint256 length) + internal + pure + returns (Vm.Log[] memory WormholeLogs) + { + WormholeLogs = new Vm.Log[](length); - /// call the target with the vaa - IWormholeReceiver(dstTarget).receiveMessage(encodedVaa); + uint256 currentIndex = 0; + + for (uint256 i = 0; i < logs.length; i++) { + if (logs[i].topics[0] == dispatchSelector) { + WormholeLogs[currentIndex] = logs[i]; + currentIndex++; + + if (currentIndex == length) { + break; + } + } + } } } diff --git a/test/Axelar.t.sol b/test/Axelar.t.sol index a056602..d9f8319 100644 --- a/test/Axelar.t.sol +++ b/test/Axelar.t.sol @@ -9,9 +9,12 @@ contract Target { uint256 public value; function execute( - bytes32, /// commandId - string calldata, /// sourceChain - string calldata, /// sourceAddress + bytes32, + /// commandId + string calldata, + /// sourceChain + string calldata, + /// sourceAddress bytes calldata payload ) external { value = abi.decode(payload, (uint256)); @@ -36,9 +39,7 @@ contract AnotherTarget { bytes calldata payload ) external { require( - keccak256(abi.encodePacked(sourceChain)) == - keccak256(abi.encodePacked(expectedChain)), - "Unexpected origin" + keccak256(abi.encodePacked(sourceChain)) == keccak256(abi.encodePacked(expectedChain)), "Unexpected origin" ); (value, kevin, bob) = abi.decode(payload, (uint256, address, bytes32)); } @@ -63,10 +64,8 @@ contract AxelarHelperTest is Test { string constant L2_2_CHAIN_ID = "arbitrum"; address constant L1_GATEWAY = 0x4F4495243837681061C4743b74B3eEdf548D56A5; - address constant POLYGON_GATEWAY = - 0x6f015F16De9fC8791b234eF68D486d2bF203FBA8; - address constant ARBITRUM_GATEWAY = - 0xe432150cce91c13a887f7D836923d5597adD8E31; + address constant POLYGON_GATEWAY = 0x6f015F16De9fC8791b234eF68D486d2bF203FBA8; + address constant ARBITRUM_GATEWAY = 0xe432150cce91c13a887f7D836923d5597adD8E31; address[] public allDstTargets; address[] public allDstGateways; @@ -105,19 +104,10 @@ contract AxelarHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _someCrossChainFunctionInYourContract( - L2_1_CHAIN_ID, - AddressHelper.toString(address(target)) - ); + _someCrossChainFunctionInYourContract(L2_1_CHAIN_ID, AddressHelper.toString(address(target))); Vm.Log[] memory logs = vm.getRecordedLogs(); - axelarHelper.help( - L1_CHAIN_ID, - POLYGON_GATEWAY, - L2_1_CHAIN_ID, - POLYGON_FORK_ID, - logs - ); + axelarHelper.help(L1_CHAIN_ID, POLYGON_GATEWAY, L2_1_CHAIN_ID, POLYGON_FORK_ID, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), CROSS_CHAIN_MESSAGE); @@ -127,19 +117,10 @@ contract AxelarHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _aMoreFancyCrossChainFunctionInYourContract( - L2_1_CHAIN_ID, - AddressHelper.toString(address(anotherTarget)) - ); + _aMoreFancyCrossChainFunctionInYourContract(L2_1_CHAIN_ID, AddressHelper.toString(address(anotherTarget))); Vm.Log[] memory logs = vm.getRecordedLogs(); - axelarHelper.help( - L1_CHAIN_ID, - POLYGON_GATEWAY, - L2_1_CHAIN_ID, - POLYGON_FORK_ID, - logs - ); + axelarHelper.help(L1_CHAIN_ID, POLYGON_GATEWAY, L2_1_CHAIN_ID, POLYGON_FORK_ID, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(anotherTarget.value(), 12); @@ -151,14 +132,8 @@ contract AxelarHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _someSecondCrossChainFunctionInYourContract( - L2_1_CHAIN_ID, - AddressHelper.toString(address(target)) - ); - _someCrossChainFunctionInYourContract( - L2_1_CHAIN_ID, - AddressHelper.toString(address(target)) - ); + _someSecondCrossChainFunctionInYourContract(L2_1_CHAIN_ID, AddressHelper.toString(address(target))); + _someCrossChainFunctionInYourContract(L2_1_CHAIN_ID, AddressHelper.toString(address(target))); Vm.Log[] memory logs = vm.getRecordedLogs(); Vm.Log[] memory AxelarLogs = axelarHelper.findLogs(logs, 2); @@ -167,13 +142,7 @@ contract AxelarHelperTest is Test { reorderedLogs[0] = AxelarLogs[1]; reorderedLogs[1] = AxelarLogs[0]; - axelarHelper.help( - L1_CHAIN_ID, - POLYGON_GATEWAY, - L2_1_CHAIN_ID, - POLYGON_FORK_ID, - reorderedLogs - ); + axelarHelper.help(L1_CHAIN_ID, POLYGON_GATEWAY, L2_1_CHAIN_ID, POLYGON_FORK_ID, reorderedLogs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), SECOND_CROSS_CHAIN_MESSAGE); @@ -185,21 +154,12 @@ contract AxelarHelperTest is Test { _manyCrossChainFunctionInYourContract( [L2_1_CHAIN_ID, L2_2_CHAIN_ID], - [ - AddressHelper.toString(address(target)), - AddressHelper.toString(address(altTarget)) - ] + [AddressHelper.toString(address(target)), AddressHelper.toString(address(altTarget))] ); Vm.Log[] memory logs = vm.getRecordedLogs(); - axelarHelper.help( - L1_CHAIN_ID, - allDstGateways, - allDstChainIds, - allDstForks, - logs - ); + axelarHelper.help(L1_CHAIN_ID, allDstGateways, allDstChainIds, allDstForks, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), CROSS_CHAIN_MESSAGE); @@ -208,57 +168,29 @@ contract AxelarHelperTest is Test { assertEq(altTarget.value(), CROSS_CHAIN_MESSAGE); } - function _manyCrossChainFunctionInYourContract( - string[2] memory dstChainIds, - string[2] memory receivers - ) internal { + function _manyCrossChainFunctionInYourContract(string[2] memory dstChainIds, string[2] memory receivers) internal { IAxelarGateway gateway = IAxelarGateway(L1_GATEWAY); for (uint256 i = 0; i < dstChainIds.length; i++) { - gateway.callContract( - dstChainIds[i], - receivers[i], - abi.encode(CROSS_CHAIN_MESSAGE) - ); + gateway.callContract(dstChainIds[i], receivers[i], abi.encode(CROSS_CHAIN_MESSAGE)); } } - function _someCrossChainFunctionInYourContract( - string memory dstChain, - string memory receiver - ) internal { + function _someCrossChainFunctionInYourContract(string memory dstChain, string memory receiver) internal { IAxelarGateway gateway = IAxelarGateway(L1_GATEWAY); - gateway.callContract( - dstChain, - receiver, - abi.encode(CROSS_CHAIN_MESSAGE) - ); + gateway.callContract(dstChain, receiver, abi.encode(CROSS_CHAIN_MESSAGE)); } - function _someSecondCrossChainFunctionInYourContract( - string memory dstChain, - string memory receiver - ) internal { + function _someSecondCrossChainFunctionInYourContract(string memory dstChain, string memory receiver) internal { IAxelarGateway gateway = IAxelarGateway(L1_GATEWAY); - gateway.callContract( - dstChain, - receiver, - abi.encode(SECOND_CROSS_CHAIN_MESSAGE) - ); + gateway.callContract(dstChain, receiver, abi.encode(SECOND_CROSS_CHAIN_MESSAGE)); } - function _aMoreFancyCrossChainFunctionInYourContract( - string memory dstChain, - string memory receiver - ) internal { + function _aMoreFancyCrossChainFunctionInYourContract(string memory dstChain, string memory receiver) internal { IAxelarGateway gateway = IAxelarGateway(L1_GATEWAY); - gateway.callContract( - dstChain, - receiver, - abi.encode(uint256(12), msg.sender, keccak256("bob")) - ); + gateway.callContract(dstChain, receiver, abi.encode(uint256(12), msg.sender, keccak256("bob"))); } } diff --git a/test/Celer.t.sol b/test/Celer.t.sol index 299485e..0864d34 100644 --- a/test/Celer.t.sol +++ b/test/Celer.t.sol @@ -13,12 +13,11 @@ contract Target { Retry // execution rejected, can retry later } - function executeMessage( - address _sender, - uint64 _srcChainId, - bytes calldata _message, - address _executor - ) external payable returns (ExecutionStatus) { + function executeMessage(address _sender, uint64 _srcChainId, bytes calldata _message, address _executor) + external + payable + returns (ExecutionStatus) + { value = abi.decode(_message, (uint256)); return ExecutionStatus.Success; @@ -42,12 +41,11 @@ contract AnotherTarget { expectedChainId = _expectedChainId; } - function executeMessage( - address _sender, - uint64 _srcChainId, - bytes calldata _message, - address _executor - ) external payable returns (ExecutionStatus) { + function executeMessage(address _sender, uint64 _srcChainId, bytes calldata _message, address _executor) + external + payable + returns (ExecutionStatus) + { require(_srcChainId == expectedChainId, "Unexpected origin"); (value, kevin, bob) = abi.decode(_message, (uint256, address, bytes32)); @@ -72,12 +70,9 @@ contract CelerHelperTest is Test { uint64 constant L2_1_CHAIN_ID = 137; uint64 constant L2_2_CHAIN_ID = 42161; - address constant L1_CelerMessageBus = - 0x4066D196A423b2b3B8B054f4F40efB47a74E200C; - address constant POLYGON_CelerMessageBus = - 0x95714818fdd7a5454F73Da9c777B3ee6EbAEEa6B; - address constant ARBITRUM_CelerMessageBus = - 0x3Ad9d0648CDAA2426331e894e980D0a5Ed16257f; + address constant L1_CelerMessageBus = 0x4066D196A423b2b3B8B054f4F40efB47a74E200C; + address constant POLYGON_CelerMessageBus = 0x95714818fdd7a5454F73Da9c777B3ee6EbAEEa6B; + address constant ARBITRUM_CelerMessageBus = 0x3Ad9d0648CDAA2426331e894e980D0a5Ed16257f; address[] public allDstTargets; address[] public allDstMessageBus; @@ -119,14 +114,7 @@ contract CelerHelperTest is Test { _someCrossChainFunctionInYourContract(L2_1_CHAIN_ID, address(target)); Vm.Log[] memory logs = vm.getRecordedLogs(); - celerHelper.help( - L1_CHAIN_ID, - L1_CelerMessageBus, - POLYGON_CelerMessageBus, - L2_1_CHAIN_ID, - POLYGON_FORK_ID, - logs - ); + celerHelper.help(L1_CHAIN_ID, L1_CelerMessageBus, POLYGON_CelerMessageBus, L2_1_CHAIN_ID, POLYGON_FORK_ID, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), CROSS_CHAIN_MESSAGE); @@ -140,12 +128,7 @@ contract CelerHelperTest is Test { Vm.Log[] memory logs = vm.getRecordedLogs(); celerHelper.helpWithEstimates( - L1_CHAIN_ID, - L1_CelerMessageBus, - POLYGON_CelerMessageBus, - L2_1_CHAIN_ID, - POLYGON_FORK_ID, - logs + L1_CHAIN_ID, L1_CelerMessageBus, POLYGON_CelerMessageBus, L2_1_CHAIN_ID, POLYGON_FORK_ID, logs ); vm.selectFork(POLYGON_FORK_ID); @@ -156,19 +139,11 @@ contract CelerHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _aMoreFancyCrossChainFunctionInYourContract( - L2_1_CHAIN_ID, - address(anotherTarget) - ); + _aMoreFancyCrossChainFunctionInYourContract(L2_1_CHAIN_ID, address(anotherTarget)); Vm.Log[] memory logs = vm.getRecordedLogs(); celerHelper.helpWithEstimates( - L1_CHAIN_ID, - L1_CelerMessageBus, - POLYGON_CelerMessageBus, - L2_1_CHAIN_ID, - POLYGON_FORK_ID, - logs + L1_CHAIN_ID, L1_CelerMessageBus, POLYGON_CelerMessageBus, L2_1_CHAIN_ID, POLYGON_FORK_ID, logs ); vm.selectFork(POLYGON_FORK_ID); @@ -193,12 +168,7 @@ contract CelerHelperTest is Test { reorderedLogs[1] = CelerLogs[0]; celerHelper.help( - L1_CHAIN_ID, - L1_CelerMessageBus, - POLYGON_CelerMessageBus, - L2_1_CHAIN_ID, - POLYGON_FORK_ID, - reorderedLogs + L1_CHAIN_ID, L1_CelerMessageBus, POLYGON_CelerMessageBus, L2_1_CHAIN_ID, POLYGON_FORK_ID, reorderedLogs ); vm.selectFork(POLYGON_FORK_ID); @@ -209,21 +179,11 @@ contract CelerHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _manyCrossChainFunctionInYourContract( - [L2_1_CHAIN_ID, L2_2_CHAIN_ID], - [address(target), address(altTarget)] - ); + _manyCrossChainFunctionInYourContract([L2_1_CHAIN_ID, L2_2_CHAIN_ID], [address(target), address(altTarget)]); Vm.Log[] memory logs = vm.getRecordedLogs(); - celerHelper.help( - L1_CHAIN_ID, - L1_CelerMessageBus, - allDstMessageBus, - allDstChainIds, - allDstForks, - logs - ); + celerHelper.help(L1_CHAIN_ID, L1_CelerMessageBus, allDstMessageBus, allDstChainIds, allDstForks, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), CROSS_CHAIN_MESSAGE); @@ -232,42 +192,23 @@ contract CelerHelperTest is Test { assertEq(altTarget.value(), CROSS_CHAIN_MESSAGE); } - function _manyCrossChainFunctionInYourContract( - uint64[2] memory dstChainIds, - address[2] memory receivers - ) internal { + function _manyCrossChainFunctionInYourContract(uint64[2] memory dstChainIds, address[2] memory receivers) + internal + { IMessageBus bus = IMessageBus(L1_CelerMessageBus); for (uint256 i = 0; i < dstChainIds.length; i++) { - bus.sendMessage{value: 2 ether}( - receivers[i], - dstChainIds[i], - abi.encode(CROSS_CHAIN_MESSAGE) - ); + bus.sendMessage{value: 2 ether}(receivers[i], dstChainIds[i], abi.encode(CROSS_CHAIN_MESSAGE)); } } - function _someCrossChainFunctionInYourContract( - uint64 dstChainId, - address receiver - ) internal { + function _someCrossChainFunctionInYourContract(uint64 dstChainId, address receiver) internal { IMessageBus bus = IMessageBus(L1_CelerMessageBus); - bus.sendMessage{value: 2 ether}( - receiver, - dstChainId, - abi.encode(CROSS_CHAIN_MESSAGE) - ); + bus.sendMessage{value: 2 ether}(receiver, dstChainId, abi.encode(CROSS_CHAIN_MESSAGE)); } - function _aMoreFancyCrossChainFunctionInYourContract( - uint64 dstChainId, - address receiver - ) internal { + function _aMoreFancyCrossChainFunctionInYourContract(uint64 dstChainId, address receiver) internal { IMessageBus bus = IMessageBus(L1_CelerMessageBus); - bus.sendMessage{value: 2 ether}( - receiver, - dstChainId, - abi.encode(uint256(12), msg.sender, keccak256("bob")) - ); + bus.sendMessage{value: 2 ether}(receiver, dstChainId, abi.encode(uint256(12), msg.sender, keccak256("bob"))); } } diff --git a/test/Hyperlane.t.sol b/test/Hyperlane.t.sol index 5fe321d..c2c3db7 100644 --- a/test/Hyperlane.t.sol +++ b/test/Hyperlane.t.sol @@ -6,37 +6,23 @@ import "forge-std/Test.sol"; import "src/hyperlane/HyperlaneHelper.sol"; interface IMailbox { - event Dispatch( - address indexed sender, - uint32 indexed destination, - bytes32 indexed recipient, - bytes message - ); - - function dispatch( - uint32 _destinationDomain, - bytes32 _recipientAddress, - bytes calldata _messageBody - ) external returns (bytes32); + event Dispatch(address indexed sender, uint32 indexed destination, bytes32 indexed recipient, bytes message); + + function dispatch(uint32 _destinationDomain, bytes32 _recipientAddress, bytes calldata _messageBody) + external + returns (bytes32); } interface IInterchainGasPaymaster { - function payForGas( - bytes32 _messageId, - uint32 _destinationDomain, - uint256 _gasAmount, - address _refundAddress - ) external payable; + function payForGas(bytes32 _messageId, uint32 _destinationDomain, uint256 _gasAmount, address _refundAddress) + external + payable; } contract Target { uint256 public value; - function handle( - uint32 _origin, - bytes32 _sender, - bytes calldata _message - ) external { + function handle(uint32 _origin, bytes32 _sender, bytes calldata _message) external { value = abi.decode(_message, (uint256)); } } @@ -52,11 +38,7 @@ contract AnotherTarget { expectedOrigin = _expectedOrigin; } - function handle( - uint32 _origin, - bytes32 _sender, - bytes calldata _message - ) external { + function handle(uint32 _origin, bytes32 _sender, bytes calldata _message) external { require(_origin == expectedOrigin, "Unexpected origin"); (value, kevin, bob) = abi.decode(_message, (uint256, address, bytes32)); } @@ -65,7 +47,8 @@ contract AnotherTarget { contract HyperlaneHelperTest is Test { HyperlaneHelper hyperlaneHelper; Target target; - Target altTarget; /// @dev is alternative target on arbitrum + Target altTarget; + /// @dev is alternative target on arbitrum AnotherTarget anotherTarget; @@ -78,16 +61,11 @@ contract HyperlaneHelperTest is Test { uint32 constant L2_2_DOMAIN = 42161; address constant L1_HLMailbox = 0x35231d4c2D8B8ADcB5617A638A0c4548684c7C70; - address constant L1_HLPaymaster = - 0xdE86327fBFD04C4eA11dC0F270DA6083534c2582; - address constant POLYGON_HLMailbox = - 0x35231d4c2D8B8ADcB5617A638A0c4548684c7C70; - address constant POLYGON_HLPaymaster = - 0xdE86327fBFD04C4eA11dC0F270DA6083534c2582; - address constant ARBITRUM_HLMailbox = - 0x35231d4c2D8B8ADcB5617A638A0c4548684c7C70; - address constant ARBITRUM_HLPaymaster = - 0xdE86327fBFD04C4eA11dC0F270DA6083534c2582; + address constant L1_HLPaymaster = 0xdE86327fBFD04C4eA11dC0F270DA6083534c2582; + address constant POLYGON_HLMailbox = 0x35231d4c2D8B8ADcB5617A638A0c4548684c7C70; + address constant POLYGON_HLPaymaster = 0xdE86327fBFD04C4eA11dC0F270DA6083534c2582; + address constant ARBITRUM_HLMailbox = 0x35231d4c2D8B8ADcB5617A638A0c4548684c7C70; + address constant ARBITRUM_HLPaymaster = 0xdE86327fBFD04C4eA11dC0F270DA6083534c2582; address[] public allDstTargets; address[] public allDstMailbox; @@ -130,17 +108,9 @@ contract HyperlaneHelperTest is Test { // \/ This is the part of the code you could copy to use the HyperlaneHelper // in your own tests. vm.recordLogs(); - _someCrossChainFunctionInYourContract( - L2_1_DOMAIN, - TypeCasts.addressToBytes32(address(target)) - ); + _someCrossChainFunctionInYourContract(L2_1_DOMAIN, TypeCasts.addressToBytes32(address(target))); Vm.Log[] memory logs = vm.getRecordedLogs(); - hyperlaneHelper.help( - L1_HLMailbox, - POLYGON_HLMailbox, - POLYGON_FORK_ID, - logs - ); + hyperlaneHelper.help(L1_HLMailbox, POLYGON_HLMailbox, POLYGON_FORK_ID, logs); // /\ // || // || @@ -153,17 +123,9 @@ contract HyperlaneHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _someCrossChainFunctionInYourContract( - L2_1_DOMAIN, - TypeCasts.addressToBytes32(address(target)) - ); + _someCrossChainFunctionInYourContract(L2_1_DOMAIN, TypeCasts.addressToBytes32(address(target))); Vm.Log[] memory logs = vm.getRecordedLogs(); - hyperlaneHelper.helpWithEstimates( - L1_HLMailbox, - POLYGON_HLMailbox, - POLYGON_FORK_ID, - logs - ); + hyperlaneHelper.helpWithEstimates(L1_HLMailbox, POLYGON_HLMailbox, POLYGON_FORK_ID, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), 12); @@ -173,17 +135,9 @@ contract HyperlaneHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _aMoreFancyCrossChainFunctionInYourContract( - L2_1_DOMAIN, - TypeCasts.addressToBytes32(address(anotherTarget)) - ); + _aMoreFancyCrossChainFunctionInYourContract(L2_1_DOMAIN, TypeCasts.addressToBytes32(address(anotherTarget))); Vm.Log[] memory logs = vm.getRecordedLogs(); - hyperlaneHelper.help( - L1_HLMailbox, - POLYGON_HLMailbox, - POLYGON_FORK_ID, - logs - ); + hyperlaneHelper.help(L1_HLMailbox, POLYGON_HLMailbox, POLYGON_FORK_ID, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(anotherTarget.value(), 12); @@ -195,25 +149,14 @@ contract HyperlaneHelperTest is Test { vm.selectFork(L1_FORK_ID); vm.recordLogs(); - _someCrossChainFunctionInYourContract( - L2_1_DOMAIN, - TypeCasts.addressToBytes32(address(target)) - ); - _someOtherCrossChainFunctionInYourContract( - L2_1_DOMAIN, - TypeCasts.addressToBytes32(address(target)) - ); + _someCrossChainFunctionInYourContract(L2_1_DOMAIN, TypeCasts.addressToBytes32(address(target))); + _someOtherCrossChainFunctionInYourContract(L2_1_DOMAIN, TypeCasts.addressToBytes32(address(target))); Vm.Log[] memory logs = vm.getRecordedLogs(); Vm.Log[] memory HLLogs = hyperlaneHelper.findLogs(logs, 2); Vm.Log[] memory reorderedLogs = new Vm.Log[](2); reorderedLogs[0] = HLLogs[1]; reorderedLogs[1] = HLLogs[0]; - hyperlaneHelper.help( - L1_HLMailbox, - POLYGON_HLMailbox, - POLYGON_FORK_ID, - reorderedLogs - ); + hyperlaneHelper.help(L1_HLMailbox, POLYGON_HLMailbox, POLYGON_FORK_ID, reorderedLogs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), 12); @@ -225,20 +168,11 @@ contract HyperlaneHelperTest is Test { _manyCrossChainFunctionInYourContract( [L2_1_DOMAIN, L2_2_DOMAIN], - [ - TypeCasts.addressToBytes32(address(target)), - TypeCasts.addressToBytes32(address(altTarget)) - ] + [TypeCasts.addressToBytes32(address(target)), TypeCasts.addressToBytes32(address(altTarget))] ); Vm.Log[] memory logs = vm.getRecordedLogs(); - hyperlaneHelper.help( - L1_HLMailbox, - allDstMailbox, - allDstDomains, - allDstForks, - logs - ); + hyperlaneHelper.help(L1_HLMailbox, allDstMailbox, allDstDomains, allDstForks, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), 21); @@ -247,70 +181,36 @@ contract HyperlaneHelperTest is Test { assertEq(altTarget.value(), 21); } - function _manyCrossChainFunctionInYourContract( - uint32[2] memory targetDomain, - bytes32[2] memory L2Target - ) internal { + function _manyCrossChainFunctionInYourContract(uint32[2] memory targetDomain, bytes32[2] memory L2Target) + internal + { IMailbox mailbox = IMailbox(L1_HLMailbox); for (uint256 i = 0; i < targetDomain.length; i++) { - bytes32 id = mailbox.dispatch( - targetDomain[i], - L2Target[i], - abi.encode(uint256(21)) - ); - IInterchainGasPaymaster paymaster = IInterchainGasPaymaster( - L1_HLPaymaster - ); + bytes32 id = mailbox.dispatch(targetDomain[i], L2Target[i], abi.encode(uint256(21))); + IInterchainGasPaymaster paymaster = IInterchainGasPaymaster(L1_HLPaymaster); paymaster.payForGas(id, targetDomain[i], 100000, msg.sender); } } - function _someCrossChainFunctionInYourContract( - uint32 targetDomain, - bytes32 L2Target - ) internal { + function _someCrossChainFunctionInYourContract(uint32 targetDomain, bytes32 L2Target) internal { IMailbox mailbox = IMailbox(L1_HLMailbox); - bytes32 id = mailbox.dispatch( - targetDomain, - L2Target, - abi.encode(uint256(12)) - ); - IInterchainGasPaymaster paymaster = IInterchainGasPaymaster( - L1_HLPaymaster - ); + bytes32 id = mailbox.dispatch(targetDomain, L2Target, abi.encode(uint256(12))); + IInterchainGasPaymaster paymaster = IInterchainGasPaymaster(L1_HLPaymaster); paymaster.payForGas(id, targetDomain, 100000, msg.sender); } - function _someOtherCrossChainFunctionInYourContract( - uint32 targetDomain, - bytes32 L2Target - ) internal { + function _someOtherCrossChainFunctionInYourContract(uint32 targetDomain, bytes32 L2Target) internal { IMailbox mailbox = IMailbox(L1_HLMailbox); - bytes32 id = mailbox.dispatch( - targetDomain, - L2Target, - abi.encode(uint256(6)) - ); - IInterchainGasPaymaster paymaster = IInterchainGasPaymaster( - L1_HLPaymaster - ); + bytes32 id = mailbox.dispatch(targetDomain, L2Target, abi.encode(uint256(6))); + IInterchainGasPaymaster paymaster = IInterchainGasPaymaster(L1_HLPaymaster); paymaster.payForGas(id, targetDomain, 100000, msg.sender); } - function _aMoreFancyCrossChainFunctionInYourContract( - uint32 targetDomain, - bytes32 L2Target - ) internal { + function _aMoreFancyCrossChainFunctionInYourContract(uint32 targetDomain, bytes32 L2Target) internal { IMailbox mailbox = IMailbox(L1_HLMailbox); - bytes32 id = mailbox.dispatch( - targetDomain, - L2Target, - abi.encode(uint256(12), msg.sender, keccak256("bob")) - ); - IInterchainGasPaymaster paymaster = IInterchainGasPaymaster( - L1_HLPaymaster - ); + bytes32 id = mailbox.dispatch(targetDomain, L2Target, abi.encode(uint256(12), msg.sender, keccak256("bob"))); + IInterchainGasPaymaster paymaster = IInterchainGasPaymaster(L1_HLPaymaster); paymaster.payForGas(id, targetDomain, 100000, msg.sender); } } diff --git a/test/LayerZero.t.sol b/test/LayerZero.t.sol index 70e2c37..f284464 100644 --- a/test/LayerZero.t.sol +++ b/test/LayerZero.t.sol @@ -19,12 +19,9 @@ interface ILayerZeroEndpoint { contract Target { uint256 public value; - function lzReceive( - uint16 _srcChainId, - bytes calldata _srcAddress, - uint64 _nonce, - bytes calldata _payload - ) external { + function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) + external + { value = abi.decode(_payload, (uint256)); } } @@ -40,12 +37,9 @@ contract AnotherTarget { expectedId = _expectedId; } - function lzReceive( - uint16 _srcChainId, - bytes calldata _srcAddress, - uint64 _nonce, - bytes calldata _payload - ) external { + function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) + external + { require(_srcChainId == expectedId, "Unexpected id"); (value, kevin, bob) = abi.decode(_payload, (uint256, address, bytes32)); } @@ -66,10 +60,8 @@ contract LayerZeroHelperTest is Test { uint16 constant ARBITRUM_ID = 110; address constant L1_lzEndpoint = 0x66A71Dcef29A0fFBDBE3c6a460a3B5BC225Cd675; - address constant polygonEndpoint = - 0x3c2269811836af69497E5F486A85D7316753cf62; - address constant arbitrumEndpoint = - 0x3c2269811836af69497E5F486A85D7316753cf62; + address constant polygonEndpoint = 0x3c2269811836af69497E5F486A85D7316753cf62; + address constant arbitrumEndpoint = 0x3c2269811836af69497E5F486A85D7316753cf62; address[] public allDstTargets; address[] public allDstEndpoints; @@ -129,12 +121,7 @@ contract LayerZeroHelperTest is Test { vm.recordLogs(); _someCrossChainFunctionInYourContract(); Vm.Log[] memory logs = vm.getRecordedLogs(); - lzHelper.helpWithEstimates( - polygonEndpoint, - 100000, - POLYGON_FORK_ID, - logs - ); + lzHelper.helpWithEstimates(polygonEndpoint, 100000, POLYGON_FORK_ID, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), 12); @@ -178,13 +165,7 @@ contract LayerZeroHelperTest is Test { _manyCrossChainFunctionInYourContract(); Vm.Log[] memory logs = vm.getRecordedLogs(); - lzHelper.help( - allDstEndpoints, - allDstChainIds, - 100000, - allDstForks, - logs - ); + lzHelper.help(allDstEndpoints, allDstChainIds, 100000, allDstForks, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), 12); @@ -196,72 +177,37 @@ contract LayerZeroHelperTest is Test { function _manyCrossChainFunctionInYourContract() internal { ILayerZeroEndpoint endpoint = ILayerZeroEndpoint(L1_lzEndpoint); - bytes memory remoteAndLocalAddresses_1 = abi.encodePacked( - address(target), - address(this) - ); - bytes memory remoteAndLocalAddresses_2 = abi.encodePacked( - address(altTarget), - address(this) - ); + bytes memory remoteAndLocalAddresses_1 = abi.encodePacked(address(target), address(this)); + bytes memory remoteAndLocalAddresses_2 = abi.encodePacked(address(altTarget), address(this)); endpoint.send{value: 1 ether}( - POLYGON_ID, - remoteAndLocalAddresses_1, - abi.encode(uint256(12)), - payable(msg.sender), - address(0), - "" + POLYGON_ID, remoteAndLocalAddresses_1, abi.encode(uint256(12)), payable(msg.sender), address(0), "" ); endpoint.send{value: 1 ether}( - ARBITRUM_ID, - remoteAndLocalAddresses_2, - abi.encode(uint256(21)), - payable(msg.sender), - address(0), - "" + ARBITRUM_ID, remoteAndLocalAddresses_2, abi.encode(uint256(21)), payable(msg.sender), address(0), "" ); } function _someCrossChainFunctionInYourContract() internal { ILayerZeroEndpoint endpoint = ILayerZeroEndpoint(L1_lzEndpoint); - bytes memory remoteAndLocalAddresses = abi.encodePacked( - address(target), - address(this) - ); + bytes memory remoteAndLocalAddresses = abi.encodePacked(address(target), address(this)); endpoint.send{value: 1 ether}( - POLYGON_ID, - remoteAndLocalAddresses, - abi.encode(uint256(12)), - payable(msg.sender), - address(0), - "" + POLYGON_ID, remoteAndLocalAddresses, abi.encode(uint256(12)), payable(msg.sender), address(0), "" ); } function _someOtherCrossChainFunctionInYourContract() internal { ILayerZeroEndpoint endpoint = ILayerZeroEndpoint(L1_lzEndpoint); - bytes memory remoteAndLocalAddresses = abi.encodePacked( - address(target), - address(this) - ); + bytes memory remoteAndLocalAddresses = abi.encodePacked(address(target), address(this)); endpoint.send{value: 1 ether}( - POLYGON_ID, - remoteAndLocalAddresses, - abi.encode(uint256(6)), - payable(msg.sender), - address(0), - "" + POLYGON_ID, remoteAndLocalAddresses, abi.encode(uint256(6)), payable(msg.sender), address(0), "" ); } function _aMoreFancyCrossChainFunctionInYourContract() internal { ILayerZeroEndpoint endpoint = ILayerZeroEndpoint(L1_lzEndpoint); - bytes memory remoteAndLocalAddresses = abi.encodePacked( - address(anotherTarget), - address(this) - ); + bytes memory remoteAndLocalAddresses = abi.encodePacked(address(anotherTarget), address(this)); endpoint.send{value: 1 ether}( POLYGON_ID, remoteAndLocalAddresses, diff --git a/test/Stargate.t.sol b/test/Stargate.t.sol index 39d4ff2..c48ab97 100644 --- a/test/Stargate.t.sol +++ b/test/Stargate.t.sol @@ -37,11 +37,16 @@ contract Target { uint256 public value; function sgReceive( - uint16, /// _srcChainId - bytes memory, /// _srcAddress - uint256, /// _nonce - address, /// _token - uint256, /// amountLD + uint16, + /// _srcChainId + bytes memory, + /// _srcAddress + uint256, + /// _nonce + address, + /// _token + uint256, + /// amountLD bytes memory payload ) external { value = abi.decode(payload, (uint256)); @@ -61,10 +66,14 @@ contract AnotherTarget { function sgReceive( uint16 _srcChainId, - bytes memory, /// _srcAddress - uint256, /// _nonce - address, /// _token - uint256, /// _amount + bytes memory, + /// _srcAddress + uint256, + /// _nonce + address, + /// _token + uint256, + /// _amount bytes memory payload ) external { require(_srcChainId == expectedId, "Unexpected id"); @@ -120,11 +129,7 @@ contract StargateHelperTest is Test { vm.selectFork(L2_FORK_ID); assertEq(target.value(), 12); // tolerated margin of $2 - assertApproxEqAbs( - L2token.balanceOf(address(target)), - 10 ** 9, - 2 * 10 ** 6 - ); + assertApproxEqAbs(L2token.balanceOf(address(target)), 10 ** 9, 2 * 10 ** 6); } function testSimpleSGWithEstimates() external { @@ -138,11 +143,7 @@ contract StargateHelperTest is Test { vm.selectFork(L2_FORK_ID); assertEq(target.value(), 12); // tolerated margin of $2 - assertApproxEqAbs( - L2token.balanceOf(address(target)), - 10 ** 9, - 2 * 10 ** 6 - ); + assertApproxEqAbs(L2token.balanceOf(address(target)), 10 ** 9, 2 * 10 ** 6); } function testFancySG() external { @@ -157,11 +158,7 @@ contract StargateHelperTest is Test { assertEq(anotherTarget.value(), 12); assertEq(anotherTarget.kevin(), msg.sender); assertEq(anotherTarget.bob(), keccak256("bob")); - assertApproxEqAbs( - L2token.balanceOf(address(anotherTarget)), - 10 ** 9, - 2 * 10 ** 6 - ); + assertApproxEqAbs(L2token.balanceOf(address(anotherTarget)), 10 ** 9, 2 * 10 ** 6); } function testCustomOrderingSG() external { @@ -183,11 +180,7 @@ contract StargateHelperTest is Test { vm.selectFork(L2_FORK_ID); assertEq(target.value(), 12); - assertApproxEqAbs( - L2token.balanceOf(address(target)), - 2 * 10 ** 9, - 2 * 10 ** 6 - ); + assertApproxEqAbs(L2token.balanceOf(address(target)), 2 * 10 ** 9, 2 * 10 ** 6); } function _someCrossChainFunctionInYourContract() internal { diff --git a/test/Wormhole.SpecializedRelayer.t.sol b/test/Wormhole.SpecializedRelayer.t.sol index 4ee0d22..fd0f275 100644 --- a/test/Wormhole.SpecializedRelayer.t.sol +++ b/test/Wormhole.SpecializedRelayer.t.sol @@ -12,6 +12,8 @@ contract Target { uint256 public value; IWormhole public wormhole; + event ValueAdded(uint256 value); + constructor(IWormhole _wormhole) { wormhole = _wormhole; } @@ -23,28 +25,65 @@ contract Target { // do security checks and set value require(valid); value = abi.decode(wormholeMessage.payload, (uint256)); + + emit ValueAdded(value); + } +} + +contract AnotherTarget { + uint256 public value; + IWormhole public wormhole; + address expEmitter; + + constructor(IWormhole _wormhole, address _expEmitter) { + wormhole = _wormhole; + expEmitter = _expEmitter; + } + + function receiveMessage(bytes memory encodedMessage) public { + // call the Wormhole core contract to parse and verify the encodedMessage + (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = + wormhole.parseAndVerifyVM(encodedMessage); + // do security checks and set value + require(valid); + require(wormholeMessage.emitterChainId == 2); + require(TypeCasts.bytes32ToAddress(wormholeMessage.emitterAddress) == expEmitter); + + value = abi.decode(wormholeMessage.payload, (uint256)); } } contract WormholeSpecializedRelayerHelperTest is Test { WormholeHelper wormholeHelper; Target target; + Target altTarget; + + AnotherTarget anotherTarget; uint32 nonce; uint256 L1_FORK_ID; uint256 POLYGON_FORK_ID; + uint256 ARBITRUM_FORK_ID; uint256 CROSS_CHAIN_MESSAGE = UINT256_MAX; uint16 L1_CHAIN_ID = 2; uint16 L2_1_CHAIN_ID = 5; + uint16 constant L2_2_CHAIN_ID = 23; address constant L1_CORE = 0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B; address constant L2_1_CORE = 0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7; + address constant L2_2_CORE = 0xa5f208e072434bC67592E4C49C1B991BA79BCA46; + + address[] public allDstCore; + uint16[] public allDstChainIds; + uint256[] public allDstForks; + address[] public allDstTargets; string RPC_ETH_MAINNET = vm.envString("ETH_MAINNET_RPC_URL"); string RPC_POLYGON_MAINNET = vm.envString("POLYGON_MAINNET_RPC_URL"); + string RPC_ARBITRUM_MAINNET = vm.envString("ARBITRUM_MAINNET_RPC_URL"); receive() external payable {} @@ -54,6 +93,22 @@ contract WormholeSpecializedRelayerHelperTest is Test { POLYGON_FORK_ID = vm.createSelectFork(RPC_POLYGON_MAINNET); target = new Target(IWormhole(L2_1_CORE)); + anotherTarget = new AnotherTarget(IWormhole(L2_1_CORE),address(this)); + + ARBITRUM_FORK_ID = vm.createSelectFork(RPC_ARBITRUM_MAINNET); + altTarget = new Target(IWormhole(L2_2_CORE)); + + allDstChainIds.push(L2_1_CHAIN_ID); + allDstChainIds.push(L2_2_CHAIN_ID); + + allDstForks.push(POLYGON_FORK_ID); + allDstForks.push(ARBITRUM_FORK_ID); + + allDstCore.push(L2_1_CORE); + allDstCore.push(L2_2_CORE); + + allDstTargets.push(address(target)); + allDstTargets.push(address(altTarget)); } /// @dev is a simple cross-chain message @@ -63,12 +118,62 @@ contract WormholeSpecializedRelayerHelperTest is Test { vm.recordLogs(); _someCrossChainFunctionInYourContract(); - wormholeHelper.help( - L1_CHAIN_ID, L2_1_CHAIN_ID, POLYGON_FORK_ID, L2_1_CORE, address(target), vm.getRecordedLogs() - ); + wormholeHelper.help(L1_CHAIN_ID, POLYGON_FORK_ID, L2_1_CORE, address(target), vm.getRecordedLogs()); + + vm.selectFork(POLYGON_FORK_ID); + assertEq(target.value(), CROSS_CHAIN_MESSAGE); + } + + /// @dev is a fancy cross-chain message with more validatins on target + function testFancyWormhole() external { + vm.selectFork(L1_FORK_ID); + + vm.recordLogs(); + _someCrossChainFunctionInYourContract(); + wormholeHelper.help(L1_CHAIN_ID, POLYGON_FORK_ID, L2_1_CORE, address(anotherTarget), vm.getRecordedLogs()); + + vm.selectFork(POLYGON_FORK_ID); + assertEq(anotherTarget.value(), CROSS_CHAIN_MESSAGE); + } + + /// @dev test event log re-ordering + function testCustomOrderingWormhole() external { + vm.selectFork(L1_FORK_ID); + + vm.recordLogs(); + + _someCrossChainFunctionInYourContract(abi.encode(type(uint32).max)); + _someCrossChainFunctionInYourContract(); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + Vm.Log[] memory WormholeLogs = wormholeHelper.findLogs(logs, 2); + Vm.Log[] memory reorderedLogs = new Vm.Log[](2); + + reorderedLogs[0] = WormholeLogs[1]; + reorderedLogs[1] = WormholeLogs[0]; + + wormholeHelper.help(L1_CHAIN_ID, POLYGON_FORK_ID, L2_1_CORE, address(target), reorderedLogs); + + vm.selectFork(POLYGON_FORK_ID); + assertEq(target.value(), type(uint32).max); + } + + /// @dev test multi-dst wormhole helper + function testMultiDstWormhole() external { + vm.selectFork(L1_FORK_ID); + vm.recordLogs(); + + _someCrossChainFunctionInYourContract(); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + wormholeHelper.help(L1_CHAIN_ID, allDstForks, allDstCore, allDstTargets, logs); vm.selectFork(POLYGON_FORK_ID); assertEq(target.value(), CROSS_CHAIN_MESSAGE); + + vm.selectFork(ARBITRUM_FORK_ID); + assertEq(altTarget.value(), CROSS_CHAIN_MESSAGE); } /// @dev is a simple cross-chain message to be published by wormhole @@ -82,4 +187,16 @@ contract WormholeSpecializedRelayerHelperTest is Test { /// @notice should use your optimal finality in development wormhole.publishMessage{value: wormhole.messageFee()}(nonce, abi.encode(CROSS_CHAIN_MESSAGE), 0); } + + /// @dev is a simple cross-chain message to be published by wormhole + function _someCrossChainFunctionInYourContract(bytes memory message) internal { + IWormhole wormhole = IWormhole(L1_CORE); + + /// @dev publish a new message + ++nonce; + + /// @dev by sending `0` in the last argument, we get instant finality + /// @notice should use your optimal finality in development + wormhole.publishMessage{value: wormhole.messageFee()}(nonce, message, 0); + } } From f6f61f4a2a7ccdf52b745d468904e0e5b422ada6 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 28 Aug 2023 22:24:15 +0530 Subject: [PATCH 3/4] fix: gas snapshot --- .gas-snapshot | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index dcc8863..8370844 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -3,10 +3,10 @@ AxelarHelperTest:testFancyAxelar() (gas: 234946) AxelarHelperTest:testMultiDstAxelar() (gas: 390512) AxelarHelperTest:testSimpleAxelar() (gas: 189522) CelerHelperTest:testCustomOrderingCeler() (gas: 108322) -CelerHelperTest:testFancyCeler() (gas: 122514) +CelerHelperTest:testFancyCeler() (gas: 117841) CelerHelperTest:testMultiDstCeler() (gas: 151149) CelerHelperTest:testSimpleCeler() (gas: 71938) -CelerHelperTest:testSimpleCelerWithEstimates() (gas: 76856) +CelerHelperTest:testSimpleCelerWithEstimates() (gas: 72328) HyperlaneHelperTest:testCustomOrderingHL() (gas: 145179) HyperlaneHelperTest:testFancyHL() (gas: 146237) HyperlaneHelperTest:testMultiDstHL() (gas: 193359) @@ -16,11 +16,11 @@ LayerZeroHelperTest:testCustomOrderingLZ() (gas: 339820) LayerZeroHelperTest:testFancyLZ() (gas: 295097) LayerZeroHelperTest:testMultiDstLZ() (gas: 475776) LayerZeroHelperTest:testSimpleLZ() (gas: 245549) -LayerZeroHelperTest:testSimpleLZWithEstimates() (gas: 309922) +LayerZeroHelperTest:testSimpleLZWithEstimates() (gas: 246017) StargateHelperTest:testCustomOrderingSG() (gas: 797976) StargateHelperTest:testFancySG() (gas: 589535) StargateHelperTest:testSimpleSG() (gas: 537570) -StargateHelperTest:testSimpleSGWithEstimates() (gas: 603229) +StargateHelperTest:testSimpleSGWithEstimates() (gas: 538082) WormholeAutomaticRelayerHelperTest:testCustomOrderingWormhole() (gas: 287323) WormholeAutomaticRelayerHelperTest:testFancyWormhole() (gas: 226022) WormholeAutomaticRelayerHelperTest:testMultiDstWormhole() (gas: 349780) From dd357e7d3c0f6c6560fe0bd848055216296984a0 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Tue, 29 Aug 2023 15:56:15 +0530 Subject: [PATCH 4/4] chore: remove unwanted comments --- src/axelar/AxelarHelper.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/axelar/AxelarHelper.sol b/src/axelar/AxelarHelper.sol index ca29cb7..b79bf57 100644 --- a/src/axelar/AxelarHelper.sol +++ b/src/axelar/AxelarHelper.sol @@ -90,7 +90,6 @@ contract AxelarHelper is Test { if (v.log.topics[0] == eventSelector) { (v.destinationChain, v.destinationContract, v.payload) = abi.decode(v.log.data, (string, string, bytes)); - /// FIXME: length based checks aren't sufficient if (isStringsEqual(expDstChain, v.destinationChain)) { string memory srcAddress = AddressHelper.toString(address(uint160(uint256(v.log.topics[1])))); address dstContract = AddressHelper.fromString(v.destinationContract);