Skip to content

Commit 6ec17ec

Browse files
committed
add custom consistency level and executor
1 parent 75feab1 commit 6ec17ec

File tree

9 files changed

+223
-0
lines changed

9 files changed

+223
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: Apache 2
2+
pragma solidity ^0.8.0;
3+
4+
//from https://github.com/wormhole-foundation/wormhole/blob/39081fa2936badf178f8b7e5eb63074d3308bf7d/ethereum/contracts/custom_consistency_level/interfaces/ICustomConsistencyLevel.sol
5+
interface ICustomConsistencyLevel {
6+
//topic0 0xa37f0112e03d41de27266c1680238ff1548c0441ad1e73c82917c000eefdd5ea.
7+
event ConfigSet(address emitterAddress, bytes32 config);
8+
9+
function configure(bytes32 config) external;
10+
11+
function getConfiguration(address emitterAddress) external returns (bytes32);
12+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/src/interfaces/IExecutor.sol
5+
interface IExecutor {
6+
struct SignedQuoteHeader {
7+
bytes4 prefix;
8+
address quoterAddress;
9+
bytes32 payeeAddress;
10+
uint16 srcChain;
11+
uint16 dstChain;
12+
uint64 expiryTime;
13+
}
14+
15+
event RequestForExecution(
16+
address indexed quoterAddress,
17+
uint256 amtPaid,
18+
uint16 dstChain,
19+
bytes32 dstAddr,
20+
address refundAddr,
21+
bytes signedQuote,
22+
bytes requestBytes,
23+
bytes relayInstructions
24+
);
25+
26+
function requestExecution(
27+
uint16 dstChain,
28+
bytes32 dstAddr,
29+
address refundAddr,
30+
bytes calldata signedQuote,
31+
bytes calldata requestBytes,
32+
bytes calldata relayInstructions
33+
) external payable;
34+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/src/interfaces/IVaaV1Receiver.sol
5+
//any contract that wishes to receive V1 VAAs from the executor needs to implement `IVaaV1Receiver`.
6+
interface IVaaV1Receiver {
7+
function executeVAAv1(bytes memory msg) external payable;
8+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
import {BytesParsing} from "wormhole-sdk/libraries/BytesParsing.sol";
5+
6+
//from https://github.com/wormhole-foundation/wormhole/blob/39081fa2936badf178f8b7e5eb63074d3308bf7d/ethereum/contracts/custom_consistency_level/libraries/ConfigMakers.sol
7+
library ConsistencyConfigMaker {
8+
uint8 public constant TYPE_ADDITIONAL_BLOCKS = 1;
9+
10+
//blocksToWait specifies the number of additional blocks to wait after the consistency level is reached.
11+
function makeAdditionalBlocksConfig(uint8 consistencyLevel, uint16 blocksToWait)
12+
internal
13+
pure
14+
returns (bytes32 ret)
15+
{
16+
bytes28 padding;
17+
(ret,) = BytesParsing.asBytes32MemUnchecked(
18+
abi.encodePacked(TYPE_ADDITIONAL_BLOCKS, consistencyLevel, blocksToWait, padding), 0
19+
);
20+
}
21+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.19;
3+
4+
//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/src/libraries/ExecutorMessages.sol
5+
library ExecutorMessages {
6+
bytes4 private constant REQ_VAA_V1 = "ERV1";
7+
bytes4 private constant REQ_NTT_V1 = "ERN1";
8+
bytes4 private constant REQ_CCTP_V1 = "ERC1";
9+
bytes4 private constant REQ_CCTP_V2 = "ERC2";
10+
11+
//selector 492f620d.
12+
error PayloadTooLarge();
13+
14+
function makeVAAv1Request(uint16 emitterChain, bytes32 emitterAddress, uint64 sequence)
15+
internal
16+
pure
17+
returns (bytes memory)
18+
{
19+
return abi.encodePacked(REQ_VAA_V1, emitterChain, emitterAddress, sequence);
20+
}
21+
22+
//messageId specifies the manager message id for the NTT transfer.
23+
function makeNTTv1Request(uint16 srcChain, bytes32 srcManager, bytes32 messageId)
24+
internal
25+
pure
26+
returns (bytes memory)
27+
{
28+
return abi.encodePacked(REQ_NTT_V1, srcChain, srcManager, messageId);
29+
}
30+
31+
function makeCCTPv1Request(uint32 sourceDomain, uint64 nonce) internal pure returns (bytes memory) {
32+
return abi.encodePacked(REQ_CCTP_V1, sourceDomain, nonce);
33+
}
34+
35+
//this request currently assumes the Executor will auto detect the event off chain.
36+
//that may change in the future, in which case this interface would change.
37+
function makeCCTPv2Request() internal pure returns (bytes memory) {
38+
return abi.encodePacked(REQ_CCTP_V2, uint8(1));
39+
}
40+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.19;
3+
4+
//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/src/libraries/RelayInstructions.sol
5+
library RelayInstructions {
6+
uint8 private constant RECV_INST_TYPE_GAS = uint8(1);
7+
uint8 private constant RECV_INST_TYPE_DROP_OFF = uint8(2);
8+
9+
//this instruction may be specified more than once. If so, the relayer should sum the values.
10+
function encodeGas(uint128 gasLimit, uint128 msgVal) internal pure returns (bytes memory) {
11+
return abi.encodePacked(RECV_INST_TYPE_GAS, gasLimit, msgVal);
12+
}
13+
14+
function encodeGasDropOffInstructions(uint128 dropOff, bytes32 recipient) internal pure returns (bytes memory) {
15+
return abi.encodePacked(RECV_INST_TYPE_DROP_OFF, dropOff, recipient);
16+
}
17+
}

test/CustomConsistencyLevel.t.sol

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
import {Test, console} from "forge-std/Test.sol";
5+
import {CONSISTENCY_LEVEL_SAFE} from "../src/constants/ConsistencyLevel.sol";
6+
import {ConsistencyConfigMaker} from "../src/libraries/ConsistencyConfigMaker.sol";
7+
8+
//from https://github.com/wormhole-foundation/wormhole/blob/39081fa2936badf178f8b7e5eb63074d3308bf7d/ethereum/forge-test/CustomConsistencyLevel.t.sol
9+
contract CustomConsistencyLevelTest is Test {
10+
function test_makeAdditionalBlocksConfig() public {
11+
bytes32 expected = 0x01c9002a00000000000000000000000000000000000000000000000000000000;
12+
bytes32 result = ConsistencyConfigMaker.makeAdditionalBlocksConfig(CONSISTENCY_LEVEL_SAFE, 42);
13+
assertEq(expected, result);
14+
}
15+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.13;
3+
4+
import {Test, console} from "forge-std/Test.sol";
5+
import {ExecutorMessages} from "../../src/libraries/executor/ExecutorMessages.sol";
6+
7+
//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/test/ExecutorMessages.t.sol
8+
contract ExecutorMessagesTest is Test {
9+
function test_makeVAAv1Request() public {
10+
uint16 emitterChain = 7;
11+
bytes32 emitterAddress = bytes32(uint256(uint160(0xdeadbeef)));
12+
bytes memory expected = abi.encodePacked("ERV1", emitterChain, emitterAddress, uint64(42));
13+
bytes memory buf = ExecutorMessages.makeVAAv1Request(emitterChain, emitterAddress, 42);
14+
assertEq(expected, buf);
15+
}
16+
17+
function test_makeNTTv1Request() public {
18+
uint16 srcChain = 7;
19+
bytes32 srcManager = bytes32(uint256(uint160(0xdeadbeef)));
20+
bytes32 messageId = bytes32(uint256(42));
21+
bytes memory expected = abi.encodePacked("ERN1", srcChain, srcManager, messageId);
22+
bytes memory buf = ExecutorMessages.makeNTTv1Request(srcChain, srcManager, messageId);
23+
assertEq(expected, buf);
24+
}
25+
26+
function test_makeCCTPv1Request() public {
27+
uint32 srcDomain = 7;
28+
uint64 nonce = 42;
29+
bytes memory expected = abi.encodePacked("ERC1", srcDomain, nonce);
30+
bytes memory buf = ExecutorMessages.makeCCTPv1Request(srcDomain, nonce);
31+
assertEq(expected, buf);
32+
}
33+
34+
function test_makeCCTPv2Request() public {
35+
bytes memory expected = abi.encodePacked("ERC2", uint8(1));
36+
bytes memory buf = ExecutorMessages.makeCCTPv2Request();
37+
assertEq(expected, buf);
38+
}
39+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.13;
3+
4+
import {Test, console} from "forge-std/Test.sol";
5+
import {RelayInstructions} from "../../src/libraries/executor/RelayInstructions.sol";
6+
7+
//from https://github.com/wormholelabs-xyz/example-messaging-executor/blob/ec5daea3c03f8860a62c23e28db5c6dc8771a9ce/evm/test/RelayInstructions.t.sol
8+
contract RelayInstructionsTest is Test {
9+
function test_encodeGas() public {
10+
uint128 gasLimit = 123456000;
11+
uint128 msgVal = 42000;
12+
bytes memory expected = abi.encodePacked(uint8(1), gasLimit, msgVal);
13+
bytes memory buf = RelayInstructions.encodeGas(gasLimit, msgVal);
14+
assertEq(expected, buf);
15+
}
16+
17+
function test_encodeGasDropOffInstructions() public {
18+
uint128 dropOff = 123456000;
19+
bytes32 recipient = bytes32(uint256(uint160(0xdeadbeef)));
20+
bytes memory expected = abi.encodePacked(uint8(2), dropOff, recipient);
21+
bytes memory buf = RelayInstructions.encodeGasDropOffInstructions(dropOff, recipient);
22+
assertEq(expected, buf);
23+
}
24+
25+
function test_multipleInstructions() public {
26+
uint128 gasLimit = 123456000;
27+
uint128 msgVal = 42000;
28+
uint128 dropOff = 123456000;
29+
bytes32 recipient = bytes32(uint256(uint160(0xdeadbeef)));
30+
bytes memory expected = abi.encodePacked(uint8(1), gasLimit, msgVal, uint8(2), dropOff, recipient);
31+
bytes memory buf = abi.encodePacked(
32+
RelayInstructions.encodeGas(gasLimit, msgVal),
33+
RelayInstructions.encodeGasDropOffInstructions(dropOff, recipient)
34+
);
35+
assertEq(expected, buf);
36+
}
37+
}

0 commit comments

Comments
 (0)