Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/interfaces/ICustomConsistencyLevel.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;

//from https://github.com/wormhole-foundation/wormhole/blob/39081fa2936badf178f8b7e5eb63074d3308bf7d/ethereum/contracts/custom_consistency_level/interfaces/ICustomConsistencyLevel.sol
interface ICustomConsistencyLevel {
//topic0 0xa37f0112e03d41de27266c1680238ff1548c0441ad1e73c82917c000eefdd5ea.
event ConfigSet(address emitterAddress, bytes32 config);

function configure(bytes32 config) external;

function getConfiguration(address emitterAddress) external returns (bytes32);
}
34 changes: 34 additions & 0 deletions src/interfaces/executor/IExecutor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/src/interfaces/IExecutor.sol
interface IExecutor {
struct SignedQuoteHeader {
bytes4 prefix;
address quoterAddress;
bytes32 payeeAddress;
uint16 srcChain;
uint16 dstChain;
uint64 expiryTime;
}

event RequestForExecution(
address indexed quoterAddress,
uint256 amtPaid,
uint16 dstChain,
bytes32 dstAddr,
address refundAddr,
bytes signedQuote,
bytes requestBytes,
bytes relayInstructions
);

function requestExecution(
uint16 dstChain,
bytes32 dstAddr,
address refundAddr,
bytes calldata signedQuote,
bytes calldata requestBytes,
bytes calldata relayInstructions
) external payable;
}
8 changes: 8 additions & 0 deletions src/interfaces/executor/IVaaV1Receiver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/src/interfaces/IVaaV1Receiver.sol
//any contract that wishes to receive V1 VAAs from the executor needs to implement `IVaaV1Receiver`.
interface IVaaV1Receiver {
function executeVAAv1(bytes memory msg) external payable;
}
20 changes: 20 additions & 0 deletions src/libraries/ConsistencyConfigMaker.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

//from https://github.com/wormhole-foundation/wormhole/blob/39081fa2936badf178f8b7e5eb63074d3308bf7d/ethereum/contracts/custom_consistency_level/libraries/ConfigMakers.sol
library ConsistencyConfigMaker {
uint8 public constant TYPE_ADDITIONAL_BLOCKS = 1;

//blocksToWait specifies the number of additional blocks to wait after the consistency level is reached.
function makeAdditionalBlocksConfig(uint8 consistencyLevel, uint16 blocksToWait)
internal
pure
returns (bytes32)
{
return bytes32((((
uint256(TYPE_ADDITIONAL_BLOCKS)
<< 8) | uint256(consistencyLevel))
<< 16) | uint256(blocksToWait))
<< 224;
}
}
40 changes: 40 additions & 0 deletions src/libraries/executor/ExecutorMessages.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/src/libraries/ExecutorMessages.sol
library ExecutorMessages {
bytes4 private constant REQ_VAA_V1 = "ERV1";
bytes4 private constant REQ_NTT_V1 = "ERN1";
bytes4 private constant REQ_CCTP_V1 = "ERC1";
bytes4 private constant REQ_CCTP_V2 = "ERC2";

//selector 492f620d.
error PayloadTooLarge();

function makeVAAv1Request(uint16 emitterChain, bytes32 emitterAddress, uint64 sequence)
internal
pure
returns (bytes memory)
{
return abi.encodePacked(REQ_VAA_V1, emitterChain, emitterAddress, sequence);
}

//messageId specifies the manager message id for the NTT transfer.
function makeNTTv1Request(uint16 srcChain, bytes32 srcManager, bytes32 messageId)
internal
pure
returns (bytes memory)
{
return abi.encodePacked(REQ_NTT_V1, srcChain, srcManager, messageId);
}

function makeCCTPv1Request(uint32 sourceDomain, uint64 nonce) internal pure returns (bytes memory) {
return abi.encodePacked(REQ_CCTP_V1, sourceDomain, nonce);
}

//this request currently assumes the Executor will auto detect the event off chain.
//that may change in the future, in which case this interface would change.
function makeCCTPv2Request() internal pure returns (bytes memory) {
return abi.encodePacked(REQ_CCTP_V2, uint8(1));
}
}
17 changes: 17 additions & 0 deletions src/libraries/executor/RelayInstructions.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/src/libraries/RelayInstructions.sol
library RelayInstructions {
uint8 private constant RECV_INST_TYPE_GAS = uint8(1);
uint8 private constant RECV_INST_TYPE_DROP_OFF = uint8(2);

//this instruction may be specified more than once. If so, the relayer should sum the values.
function encodeGas(uint128 gasLimit, uint128 msgVal) internal pure returns (bytes memory) {
return abi.encodePacked(RECV_INST_TYPE_GAS, gasLimit, msgVal);
}

function encodeGasDropOffInstructions(uint128 dropOff, bytes32 recipient) internal pure returns (bytes memory) {
return abi.encodePacked(RECV_INST_TYPE_DROP_OFF, dropOff, recipient);
}
}
15 changes: 15 additions & 0 deletions test/CustomConsistencyLevel.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import {Test, console} from "forge-std/Test.sol";
import {CONSISTENCY_LEVEL_SAFE} from "../src/constants/ConsistencyLevel.sol";
import {ConsistencyConfigMaker} from "../src/libraries/ConsistencyConfigMaker.sol";

//from https://github.com/wormhole-foundation/wormhole/blob/39081fa2936badf178f8b7e5eb63074d3308bf7d/ethereum/forge-test/CustomConsistencyLevel.t.sol
contract CustomConsistencyLevelTest is Test {
function test_makeAdditionalBlocksConfig() public {
bytes32 expected = 0x01c9002a00000000000000000000000000000000000000000000000000000000;
bytes32 result = ConsistencyConfigMaker.makeAdditionalBlocksConfig(CONSISTENCY_LEVEL_SAFE, 42);
assertEq(expected, result);
}
}
39 changes: 39 additions & 0 deletions test/executor/ExecutorMessages.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.13;

import {Test, console} from "forge-std/Test.sol";
import {ExecutorMessages} from "../../src/libraries/executor/ExecutorMessages.sol";

//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/test/ExecutorMessages.t.sol
contract ExecutorMessagesTest is Test {
function test_makeVAAv1Request() public {
uint16 emitterChain = 7;
bytes32 emitterAddress = bytes32(uint256(uint160(0xdeadbeef)));
bytes memory expected = abi.encodePacked("ERV1", emitterChain, emitterAddress, uint64(42));
bytes memory buf = ExecutorMessages.makeVAAv1Request(emitterChain, emitterAddress, 42);
assertEq(expected, buf);
}

function test_makeNTTv1Request() public {
uint16 srcChain = 7;
bytes32 srcManager = bytes32(uint256(uint160(0xdeadbeef)));
bytes32 messageId = bytes32(uint256(42));
bytes memory expected = abi.encodePacked("ERN1", srcChain, srcManager, messageId);
bytes memory buf = ExecutorMessages.makeNTTv1Request(srcChain, srcManager, messageId);
assertEq(expected, buf);
}

function test_makeCCTPv1Request() public {
uint32 srcDomain = 7;
uint64 nonce = 42;
bytes memory expected = abi.encodePacked("ERC1", srcDomain, nonce);
bytes memory buf = ExecutorMessages.makeCCTPv1Request(srcDomain, nonce);
assertEq(expected, buf);
}

function test_makeCCTPv2Request() public {
bytes memory expected = abi.encodePacked("ERC2", uint8(1));
bytes memory buf = ExecutorMessages.makeCCTPv2Request();
assertEq(expected, buf);
}
}
37 changes: 37 additions & 0 deletions test/executor/RelayInstructions.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.13;

import {Test, console} from "forge-std/Test.sol";
import {RelayInstructions} from "../../src/libraries/executor/RelayInstructions.sol";

//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/test/RelayInstructions.t.sol
contract RelayInstructionsTest is Test {
function test_encodeGas() public {
uint128 gasLimit = 123456000;
uint128 msgVal = 42000;
bytes memory expected = abi.encodePacked(uint8(1), gasLimit, msgVal);
bytes memory buf = RelayInstructions.encodeGas(gasLimit, msgVal);
assertEq(expected, buf);
}

function test_encodeGasDropOffInstructions() public {
uint128 dropOff = 123456000;
bytes32 recipient = bytes32(uint256(uint160(0xdeadbeef)));
bytes memory expected = abi.encodePacked(uint8(2), dropOff, recipient);
bytes memory buf = RelayInstructions.encodeGasDropOffInstructions(dropOff, recipient);
assertEq(expected, buf);
}

function test_multipleInstructions() public {
uint128 gasLimit = 123456000;
uint128 msgVal = 42000;
uint128 dropOff = 123456000;
bytes32 recipient = bytes32(uint256(uint160(0xdeadbeef)));
bytes memory expected = abi.encodePacked(uint8(1), gasLimit, msgVal, uint8(2), dropOff, recipient);
bytes memory buf = abi.encodePacked(
RelayInstructions.encodeGas(gasLimit, msgVal),
RelayInstructions.encodeGasDropOffInstructions(dropOff, recipient)
);
assertEq(expected, buf);
}
}