@layerzerolabs/protocol-v2-messagelib-evm-contracts 1.2.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/contracts/Executor.sol +339 -0
- package/contracts/ExecutorFeeLib.sol +241 -0
- package/contracts/MessageLibBase.sol +21 -0
- package/contracts/PriceFeed.sol +304 -0
- package/contracts/ReceiveLibBaseE2.sol +28 -0
- package/contracts/SendLibBase.sol +258 -0
- package/contracts/SendLibBaseE2.sol +140 -0
- package/contracts/SimpleReadExecutor.sol +110 -0
- package/contracts/Treasury.sol +74 -0
- package/contracts/Worker.sol +167 -0
- package/contracts/decompressor/DVNDecoder.sol +52 -0
- package/contracts/decompressor/DVNDecompressor.sol +70 -0
- package/contracts/decompressor/DecompressorExtension.sol +204 -0
- package/contracts/decompressor/ExecutorDecoder.sol +147 -0
- package/contracts/decompressor/ExecutorDecompressor.sol +58 -0
- package/contracts/interfaces/IExecutor.sol +47 -0
- package/contracts/interfaces/IExecutorFeeLib.sol +56 -0
- package/contracts/interfaces/ILayerZeroExecutor.sol +29 -0
- package/contracts/interfaces/ILayerZeroPriceFeed.sol +61 -0
- package/contracts/interfaces/ILayerZeroReadExecutor.sol +15 -0
- package/contracts/interfaces/ILayerZeroTreasury.sol +19 -0
- package/contracts/interfaces/IWorker.sol +29 -0
- package/contracts/libs/ExecutorOptions.sol +104 -0
- package/contracts/libs/SafeCall.sol +123 -0
- package/contracts/lowlat/EssenceDVNWrapper.sol +77 -0
- package/contracts/lowlat/MultiCall.sol +42 -0
- package/contracts/mocks/DVNMock.sol +28 -0
- package/contracts/mocks/ExecutorMock.sol +95 -0
- package/contracts/uln/LzExecutor.sol +129 -0
- package/contracts/uln/ReceiveUlnBase.sol +125 -0
- package/contracts/uln/SendUlnBase.sol +129 -0
- package/contracts/uln/UlnBase.sol +195 -0
- package/contracts/uln/dvn/DVN.sol +393 -0
- package/contracts/uln/dvn/DVNFeeLib.sol +288 -0
- package/contracts/uln/dvn/DeadDVN.sol +30 -0
- package/contracts/uln/dvn/MultiSig.sol +135 -0
- package/contracts/uln/dvn/SimpleReadDVN.sol +112 -0
- package/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapter.sol +151 -0
- package/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapterFeeLib.sol +71 -0
- package/contracts/uln/dvn/adapters/DVNAdapterBase.sol +114 -0
- package/contracts/uln/dvn/adapters/arbitrum/ArbitrumDVNAdapterL1.sol +126 -0
- package/contracts/uln/dvn/adapters/arbitrum/ArbitrumDVNAdapterL2.sol +50 -0
- package/contracts/uln/dvn/adapters/avalanche/NOTES.md +4 -0
- package/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapter.sol +152 -0
- package/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapterFeeLib.sol +127 -0
- package/contracts/uln/dvn/adapters/libs/DVNAdapterMessageCodec.sol +41 -0
- package/contracts/uln/dvn/adapters/optimism/OptimismDVNAdapterL1.sol +86 -0
- package/contracts/uln/dvn/adapters/optimism/OptimismDVNAdapterL2.sol +58 -0
- package/contracts/uln/interfaces/IDVN.sol +26 -0
- package/contracts/uln/interfaces/IDVNFeeLib.sol +56 -0
- package/contracts/uln/interfaces/ILayerZeroDVN.sol +34 -0
- package/contracts/uln/interfaces/ILayerZeroReadDVN.sol +27 -0
- package/contracts/uln/interfaces/IReceiveUlnE2.sol +13 -0
- package/contracts/uln/interfaces/adapters/IAxelarDVNAdapter.sol +50 -0
- package/contracts/uln/interfaces/adapters/IAxelarDVNAdapterFeeLib.sol +49 -0
- package/contracts/uln/interfaces/adapters/ICCIPDVNAdapter.sol +34 -0
- package/contracts/uln/interfaces/adapters/ICCIPDVNAdapterFeeLib.sol +46 -0
- package/contracts/uln/libs/DVNOptions.sol +181 -0
- package/contracts/uln/libs/ReadCmdCodecV1.sol +136 -0
- package/contracts/uln/libs/SupportedCmdTypes.sol +29 -0
- package/contracts/uln/libs/UlnOptions.sol +176 -0
- package/contracts/uln/readlib/ReadLib1002.sol +518 -0
- package/contracts/uln/readlib/ReadLib1002View.sol +98 -0
- package/contracts/uln/readlib/ReadLibBase.sol +187 -0
- package/contracts/uln/uln301/AddressSizeConfig.sol +22 -0
- package/contracts/uln/uln301/ReceiveLibBaseE1.sol +103 -0
- package/contracts/uln/uln301/ReceiveUln301.sol +83 -0
- package/contracts/uln/uln301/ReceiveUln301View.sol +89 -0
- package/contracts/uln/uln301/SendLibBaseE1.sol +194 -0
- package/contracts/uln/uln301/SendUln301.sol +99 -0
- package/contracts/uln/uln301/TreasuryFeeHandler.sol +41 -0
- package/contracts/uln/uln301/interfaces/IMessageLibE1.sol +22 -0
- package/contracts/uln/uln301/interfaces/INonceContract.sol +7 -0
- package/contracts/uln/uln301/interfaces/ITreasuryFeeHandler.sol +13 -0
- package/contracts/uln/uln301/interfaces/IUltraLightNode301.sol +7 -0
- package/contracts/uln/uln301/mocks/NonceContractMock.sol +23 -0
- package/contracts/uln/uln302/ReceiveUln302.sol +85 -0
- package/contracts/uln/uln302/ReceiveUln302View.sol +89 -0
- package/contracts/uln/uln302/SendUln302.sol +86 -0
- package/contracts/upgradeable/WorkerUpgradeable.sol +186 -0
- package/contracts/upgradeable/proxy/ProxyAdmin.sol +96 -0
- package/contracts/upgradeable/proxy/TransparentUpgradeableProxy.sol +131 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.8.0;
|
|
4
|
+
|
|
5
|
+
import { IDVN } from "./IDVN.sol";
|
|
6
|
+
|
|
7
|
+
interface IDVNFeeLib {
|
|
8
|
+
struct FeeParams {
|
|
9
|
+
address priceFeed;
|
|
10
|
+
uint32 dstEid;
|
|
11
|
+
uint64 confirmations;
|
|
12
|
+
address sender;
|
|
13
|
+
uint64 quorum;
|
|
14
|
+
uint16 defaultMultiplierBps;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
struct FeeParamsForRead {
|
|
18
|
+
address priceFeed;
|
|
19
|
+
address sender;
|
|
20
|
+
uint64 quorum;
|
|
21
|
+
uint16 defaultMultiplierBps;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
error DVN_UnsupportedOptionType(uint8 optionType);
|
|
25
|
+
error DVN_EidNotSupported(uint32 eid);
|
|
26
|
+
error DVN_TimestampOutOfRange(uint32 eid, uint64 timestamp);
|
|
27
|
+
error DVN_INVALID_INPUT_LENGTH();
|
|
28
|
+
|
|
29
|
+
function getFeeOnSend(
|
|
30
|
+
FeeParams calldata _params,
|
|
31
|
+
IDVN.DstConfig calldata _dstConfig,
|
|
32
|
+
bytes calldata _options
|
|
33
|
+
) external payable returns (uint256 fee);
|
|
34
|
+
|
|
35
|
+
function getFee(
|
|
36
|
+
FeeParams calldata _params,
|
|
37
|
+
IDVN.DstConfig calldata _dstConfig,
|
|
38
|
+
bytes calldata _options
|
|
39
|
+
) external view returns (uint256 fee);
|
|
40
|
+
|
|
41
|
+
function getFeeOnSend(
|
|
42
|
+
FeeParamsForRead calldata _params,
|
|
43
|
+
IDVN.DstConfig calldata _dstConfig,
|
|
44
|
+
bytes calldata _cmd,
|
|
45
|
+
bytes calldata _options
|
|
46
|
+
) external payable returns (uint256 fee);
|
|
47
|
+
|
|
48
|
+
function getFee(
|
|
49
|
+
FeeParamsForRead calldata _params,
|
|
50
|
+
IDVN.DstConfig calldata _dstConfig,
|
|
51
|
+
bytes calldata _cmd,
|
|
52
|
+
bytes calldata _options
|
|
53
|
+
) external view returns (uint256 fee);
|
|
54
|
+
|
|
55
|
+
function version() external view returns (uint64 major, uint8 minor);
|
|
56
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.8.0;
|
|
4
|
+
|
|
5
|
+
interface ILayerZeroDVN {
|
|
6
|
+
struct AssignJobParam {
|
|
7
|
+
uint32 dstEid;
|
|
8
|
+
bytes packetHeader;
|
|
9
|
+
bytes32 payloadHash;
|
|
10
|
+
uint64 confirmations;
|
|
11
|
+
address sender;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// @notice query price and assign jobs at the same time
|
|
15
|
+
// @param _dstEid - the destination endpoint identifier
|
|
16
|
+
// @param _packetHeader - version + nonce + path
|
|
17
|
+
// @param _payloadHash - hash of guid + message
|
|
18
|
+
// @param _confirmations - block confirmation delay before relaying blocks
|
|
19
|
+
// @param _sender - the source sending contract address
|
|
20
|
+
// @param _options - options
|
|
21
|
+
function assignJob(AssignJobParam calldata _param, bytes calldata _options) external payable returns (uint256 fee);
|
|
22
|
+
|
|
23
|
+
// @notice query the dvn fee for relaying block information to the destination chain
|
|
24
|
+
// @param _dstEid the destination endpoint identifier
|
|
25
|
+
// @param _confirmations - block confirmation delay before relaying blocks
|
|
26
|
+
// @param _sender - the source sending contract address
|
|
27
|
+
// @param _options - options
|
|
28
|
+
function getFee(
|
|
29
|
+
uint32 _dstEid,
|
|
30
|
+
uint64 _confirmations,
|
|
31
|
+
address _sender,
|
|
32
|
+
bytes calldata _options
|
|
33
|
+
) external view returns (uint256 fee);
|
|
34
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.8.0;
|
|
4
|
+
|
|
5
|
+
interface ILayerZeroReadDVN {
|
|
6
|
+
// @notice query price and assign jobs at the same time
|
|
7
|
+
// @param _packetHeader - version + nonce + path
|
|
8
|
+
// @param _cmd - the command to be executed to obtain the payload
|
|
9
|
+
// @param _options - options
|
|
10
|
+
function assignJob(
|
|
11
|
+
address _sender,
|
|
12
|
+
bytes calldata _packetHeader,
|
|
13
|
+
bytes calldata _cmd,
|
|
14
|
+
bytes calldata _options
|
|
15
|
+
) external payable returns (uint256 fee);
|
|
16
|
+
|
|
17
|
+
// @notice query the dvn fee for relaying block information to the destination chain
|
|
18
|
+
// @param _packetHeader - version + nonce + path
|
|
19
|
+
// @param _cmd - the command to be executed to obtain the payload
|
|
20
|
+
// @param _options - options
|
|
21
|
+
function getFee(
|
|
22
|
+
address _sender,
|
|
23
|
+
bytes calldata _packetHeader,
|
|
24
|
+
bytes calldata _cmd,
|
|
25
|
+
bytes calldata _options
|
|
26
|
+
) external view returns (uint256 fee);
|
|
27
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.8.0;
|
|
4
|
+
|
|
5
|
+
/// @dev should be implemented by the ReceiveUln302 contract and future ReceiveUln contracts on EndpointV2
|
|
6
|
+
interface IReceiveUlnE2 {
|
|
7
|
+
/// @notice for each dvn to verify the payload
|
|
8
|
+
/// @dev this function signature 0x0223536e
|
|
9
|
+
function verify(bytes calldata _packetHeader, bytes32 _payloadHash, uint64 _confirmations) external;
|
|
10
|
+
|
|
11
|
+
/// @notice verify the payload at endpoint, will check if all DVNs verified
|
|
12
|
+
function commitVerification(bytes calldata _packetHeader, bytes32 _payloadHash) external;
|
|
13
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.8.0;
|
|
4
|
+
|
|
5
|
+
interface IAxelarDVNAdapter {
|
|
6
|
+
struct MultiplierParam {
|
|
7
|
+
uint32 dstEid;
|
|
8
|
+
uint16 multiplierBps;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
struct FloorMarginUSDParam {
|
|
12
|
+
uint32 dstEid;
|
|
13
|
+
uint128 floorMarginUSD;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
struct NativeGasFeeParam {
|
|
17
|
+
uint32 dstEid;
|
|
18
|
+
uint256 nativeGasFee;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
struct DstConfigParam {
|
|
22
|
+
uint32 eid;
|
|
23
|
+
string chainName;
|
|
24
|
+
string peer;
|
|
25
|
+
uint16 multiplierBps;
|
|
26
|
+
uint256 nativeGasFee;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
struct DstConfig {
|
|
30
|
+
string chainName;
|
|
31
|
+
string peer;
|
|
32
|
+
uint16 multiplierBps;
|
|
33
|
+
uint256 nativeGasFee;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
struct SrcConfig {
|
|
37
|
+
uint32 eid;
|
|
38
|
+
string peer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
event DstConfigSet(DstConfigParam[] params);
|
|
42
|
+
event NativeGasFeeSet(NativeGasFeeParam[] params);
|
|
43
|
+
event MultiplierSet(MultiplierParam[] params);
|
|
44
|
+
event FloorMarginUSDSet(FloorMarginUSDParam[] params);
|
|
45
|
+
|
|
46
|
+
error AxelarDVNAdapter_UntrustedPeer(string chainName, string peer);
|
|
47
|
+
error AxelarDVNAdapter_OnlyWorkerFeeLib();
|
|
48
|
+
|
|
49
|
+
function withdrawToFeeLib(address _sendLib) external;
|
|
50
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.8.0;
|
|
4
|
+
|
|
5
|
+
import { IAxelarDVNAdapter } from "./IAxelarDVNAdapter.sol";
|
|
6
|
+
|
|
7
|
+
interface IAxelarDVNAdapterFeeLib {
|
|
8
|
+
struct Param {
|
|
9
|
+
uint32 dstEid;
|
|
10
|
+
uint64 confirmations;
|
|
11
|
+
address sender;
|
|
12
|
+
uint16 defaultMultiplierBps;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
struct DstConfig {
|
|
16
|
+
uint64 gas;
|
|
17
|
+
uint128 floorMarginUSD; // uses priceFeed PRICE_RATIO_DENOMINATOR
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
struct DstConfigParam {
|
|
21
|
+
uint32 dstEid;
|
|
22
|
+
uint64 gas;
|
|
23
|
+
uint128 floorMarginUSD; // uses priceFeed PRICE_RATIO_DENOMINATOR
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
event DstConfigSet(DstConfigParam[] params);
|
|
27
|
+
event TokenWithdrawn(address token, address to, uint256 amount);
|
|
28
|
+
event GasServiceSet(address gasService);
|
|
29
|
+
event PriceFeedSet(address priceFeed);
|
|
30
|
+
event NativeGasFeeMultiplierBpsSet(uint16 multiplierBps);
|
|
31
|
+
|
|
32
|
+
error AxelarDVNAdapter_OptionsUnsupported();
|
|
33
|
+
error AxelarDVNAdapter_InsufficientBalance(uint256 actual, uint256 requested);
|
|
34
|
+
error AxelarDVNAdapter_EidNotSupported(uint32 eid);
|
|
35
|
+
|
|
36
|
+
function getFeeOnSend(
|
|
37
|
+
Param calldata _params,
|
|
38
|
+
IAxelarDVNAdapter.DstConfig calldata _dstConfig,
|
|
39
|
+
bytes memory _payload,
|
|
40
|
+
bytes calldata _options,
|
|
41
|
+
address _sendLib
|
|
42
|
+
) external payable returns (uint256 totalFee);
|
|
43
|
+
|
|
44
|
+
function getFee(
|
|
45
|
+
Param calldata _params,
|
|
46
|
+
IAxelarDVNAdapter.DstConfig calldata _dstConfig,
|
|
47
|
+
bytes calldata _options
|
|
48
|
+
) external view returns (uint256 totalFee);
|
|
49
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.8.0;
|
|
4
|
+
|
|
5
|
+
interface ICCIPDVNAdapter {
|
|
6
|
+
struct DstConfigParam {
|
|
7
|
+
uint32 eid;
|
|
8
|
+
uint16 multiplierBps;
|
|
9
|
+
uint64 chainSelector;
|
|
10
|
+
uint256 gas;
|
|
11
|
+
bytes peer;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
struct DstConfig {
|
|
15
|
+
// https://docs.chain.link/ccip/supported-networks/v1_2_0/testnet#ethereum-sepolia
|
|
16
|
+
// https://docs.chain.link/ccip/supported-networks/v1_0_0/mainnet
|
|
17
|
+
uint64 chainSelector;
|
|
18
|
+
uint16 multiplierBps;
|
|
19
|
+
// https://github.com/smartcontractkit/ccip/blob/ccip-develop/contracts/src/v0.8/ccip/libraries/Client.sol#L22C51-L22C51
|
|
20
|
+
// for destination is evm chain, need to use `abi.encode(address)` to get the peer
|
|
21
|
+
bytes peer;
|
|
22
|
+
uint256 gas;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
struct SrcConfig {
|
|
26
|
+
uint32 eid;
|
|
27
|
+
bytes peer;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
event DstConfigSet(DstConfigParam[] params);
|
|
31
|
+
|
|
32
|
+
error CCIPDVNAdapter_UntrustedPeer(uint64 chainSelector, bytes peer);
|
|
33
|
+
error CCIPDVNAdapter_InvalidRouter(address router);
|
|
34
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity >=0.8.0;
|
|
4
|
+
|
|
5
|
+
import { Client } from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
|
|
6
|
+
import { IRouterClient } from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";
|
|
7
|
+
import { ICCIPDVNAdapter } from "./ICCIPDVNAdapter.sol";
|
|
8
|
+
|
|
9
|
+
interface ICCIPDVNAdapterFeeLib {
|
|
10
|
+
struct Param {
|
|
11
|
+
uint32 dstEid;
|
|
12
|
+
uint64 confirmations;
|
|
13
|
+
address sender;
|
|
14
|
+
uint16 defaultMultiplierBps;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
struct DstConfig {
|
|
18
|
+
uint128 floorMarginUSD; // uses priceFeed PRICE_RATIO_DENOMINATOR
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
struct DstConfigParam {
|
|
22
|
+
uint32 dstEid;
|
|
23
|
+
uint128 floorMarginUSD; // uses priceFeed PRICE_RATIO_DENOMINATOR
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
event DstConfigSet(DstConfigParam[] params);
|
|
27
|
+
|
|
28
|
+
error CCIPDVNAdapter_OptionsUnsupported();
|
|
29
|
+
error CCIPDVNAdapter_EidNotSupported(uint32 eid);
|
|
30
|
+
|
|
31
|
+
function getFeeOnSend(
|
|
32
|
+
Param calldata _params,
|
|
33
|
+
ICCIPDVNAdapter.DstConfig calldata _dstConfig,
|
|
34
|
+
Client.EVM2AnyMessage calldata _message,
|
|
35
|
+
bytes calldata _options,
|
|
36
|
+
IRouterClient _router
|
|
37
|
+
) external payable returns (uint256 ccipFee, uint256 totalFee);
|
|
38
|
+
|
|
39
|
+
function getFee(
|
|
40
|
+
Param calldata _params,
|
|
41
|
+
ICCIPDVNAdapter.DstConfig calldata _dstConfig,
|
|
42
|
+
Client.EVM2AnyMessage calldata _message,
|
|
43
|
+
bytes calldata _options,
|
|
44
|
+
IRouterClient _router
|
|
45
|
+
) external view returns (uint256 totalFee);
|
|
46
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// SPDX-License-Identifier: LZBL-1.2
|
|
2
|
+
|
|
3
|
+
pragma solidity ^0.8.20;
|
|
4
|
+
|
|
5
|
+
import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol";
|
|
6
|
+
|
|
7
|
+
import { BitMap256 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/BitMaps.sol";
|
|
8
|
+
import { CalldataBytesLib } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol";
|
|
9
|
+
|
|
10
|
+
library DVNOptions {
|
|
11
|
+
using CalldataBytesLib for bytes;
|
|
12
|
+
using BytesLib for bytes;
|
|
13
|
+
|
|
14
|
+
uint8 internal constant WORKER_ID = 2;
|
|
15
|
+
uint8 internal constant OPTION_TYPE_PRECRIME = 1;
|
|
16
|
+
|
|
17
|
+
error DVN_InvalidDVNIdx();
|
|
18
|
+
error DVN_InvalidDVNOptions(uint256 cursor);
|
|
19
|
+
|
|
20
|
+
/// @dev group dvn options by its idx
|
|
21
|
+
/// @param _options [dvn_id][dvn_option][dvn_id][dvn_option]...
|
|
22
|
+
/// dvn_option = [option_size][dvn_idx][option_type][option]
|
|
23
|
+
/// option_size = len(dvn_idx) + len(option_type) + len(option)
|
|
24
|
+
/// dvn_id: uint8, dvn_idx: uint8, option_size: uint16, option_type: uint8, option: bytes
|
|
25
|
+
/// @return dvnOptions the grouped options, still share the same format of _options
|
|
26
|
+
/// @return dvnIndices the dvn indices
|
|
27
|
+
function groupDVNOptionsByIdx(
|
|
28
|
+
bytes memory _options
|
|
29
|
+
) internal pure returns (bytes[] memory dvnOptions, uint8[] memory dvnIndices) {
|
|
30
|
+
if (_options.length == 0) return (dvnOptions, dvnIndices);
|
|
31
|
+
|
|
32
|
+
uint8 numDVNs = getNumDVNs(_options);
|
|
33
|
+
|
|
34
|
+
// if there is only 1 dvn, we can just return the whole options
|
|
35
|
+
if (numDVNs == 1) {
|
|
36
|
+
dvnOptions = new bytes[](1);
|
|
37
|
+
dvnOptions[0] = _options;
|
|
38
|
+
|
|
39
|
+
dvnIndices = new uint8[](1);
|
|
40
|
+
dvnIndices[0] = _options.toUint8(3); // dvn idx
|
|
41
|
+
return (dvnOptions, dvnIndices);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// otherwise, we need to group the options by dvn_idx
|
|
45
|
+
dvnIndices = new uint8[](numDVNs);
|
|
46
|
+
dvnOptions = new bytes[](numDVNs);
|
|
47
|
+
unchecked {
|
|
48
|
+
uint256 cursor = 0;
|
|
49
|
+
uint256 start = 0;
|
|
50
|
+
uint8 lastDVNIdx = 255; // 255 is an invalid dvn_idx
|
|
51
|
+
|
|
52
|
+
while (cursor < _options.length) {
|
|
53
|
+
++cursor; // skip worker_id
|
|
54
|
+
|
|
55
|
+
// optionLength asserted in getNumDVNs (skip check)
|
|
56
|
+
uint16 optionLength = _options.toUint16(cursor);
|
|
57
|
+
cursor += 2;
|
|
58
|
+
|
|
59
|
+
// dvnIdx asserted in getNumDVNs (skip check)
|
|
60
|
+
uint8 dvnIdx = _options.toUint8(cursor);
|
|
61
|
+
|
|
62
|
+
// dvnIdx must equal to the lastDVNIdx for the first option
|
|
63
|
+
// so it is always skipped in the first option
|
|
64
|
+
// this operation slices out options whenever the scan finds a different lastDVNIdx
|
|
65
|
+
if (lastDVNIdx == 255) {
|
|
66
|
+
lastDVNIdx = dvnIdx;
|
|
67
|
+
} else if (dvnIdx != lastDVNIdx) {
|
|
68
|
+
uint256 len = cursor - start - 3; // 3 is for worker_id and option_length
|
|
69
|
+
bytes memory opt = _options.slice(start, len);
|
|
70
|
+
_insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, opt);
|
|
71
|
+
|
|
72
|
+
// reset the start and lastDVNIdx
|
|
73
|
+
start += len;
|
|
74
|
+
lastDVNIdx = dvnIdx;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
cursor += optionLength;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// skip check the cursor here because the cursor is asserted in getNumDVNs
|
|
81
|
+
// if we have reached the end of the options, we need to process the last dvn
|
|
82
|
+
uint256 size = cursor - start;
|
|
83
|
+
bytes memory op = _options.slice(start, size);
|
|
84
|
+
_insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, op);
|
|
85
|
+
|
|
86
|
+
// revert dvnIndices to start from 0
|
|
87
|
+
for (uint8 i = 0; i < numDVNs; ++i) {
|
|
88
|
+
--dvnIndices[i];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function _insertDVNOptions(
|
|
94
|
+
bytes[] memory _dvnOptions,
|
|
95
|
+
uint8[] memory _dvnIndices,
|
|
96
|
+
uint8 _dvnIdx,
|
|
97
|
+
bytes memory _newOptions
|
|
98
|
+
) internal pure {
|
|
99
|
+
// dvnIdx starts from 0 but default value of dvnIndices is 0,
|
|
100
|
+
// so we tell if the slot is empty by adding 1 to dvnIdx
|
|
101
|
+
if (_dvnIdx == 255) revert DVN_InvalidDVNIdx();
|
|
102
|
+
uint8 dvnIdxAdj = _dvnIdx + 1;
|
|
103
|
+
|
|
104
|
+
for (uint256 j = 0; j < _dvnIndices.length; ++j) {
|
|
105
|
+
uint8 index = _dvnIndices[j];
|
|
106
|
+
if (dvnIdxAdj == index) {
|
|
107
|
+
_dvnOptions[j] = abi.encodePacked(_dvnOptions[j], _newOptions);
|
|
108
|
+
break;
|
|
109
|
+
} else if (index == 0) {
|
|
110
|
+
// empty slot, that means it is the first time we see this dvn
|
|
111
|
+
_dvnIndices[j] = dvnIdxAdj;
|
|
112
|
+
_dvnOptions[j] = _newOptions;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// @dev get the number of unique dvns
|
|
119
|
+
/// @param _options the format is the same as groupDVNOptionsByIdx
|
|
120
|
+
function getNumDVNs(bytes memory _options) internal pure returns (uint8 numDVNs) {
|
|
121
|
+
uint256 cursor = 0;
|
|
122
|
+
BitMap256 bitmap;
|
|
123
|
+
|
|
124
|
+
// find number of unique dvn_idx
|
|
125
|
+
unchecked {
|
|
126
|
+
while (cursor < _options.length) {
|
|
127
|
+
++cursor; // skip worker_id
|
|
128
|
+
|
|
129
|
+
uint16 optionLength = _options.toUint16(cursor);
|
|
130
|
+
cursor += 2;
|
|
131
|
+
if (optionLength < 2) revert DVN_InvalidDVNOptions(cursor); // at least 1 byte for dvn_idx and 1 byte for option_type
|
|
132
|
+
|
|
133
|
+
uint8 dvnIdx = _options.toUint8(cursor);
|
|
134
|
+
|
|
135
|
+
// if dvnIdx is not set, increment numDVNs
|
|
136
|
+
// max num of dvns is 255, 255 is an invalid dvn_idx
|
|
137
|
+
// The order of the dvnIdx is not required to be sequential, as enforcing the order may weaken
|
|
138
|
+
// the composability of the options. e.g. if we refrain from enforcing the order, an OApp that has
|
|
139
|
+
// already enforced certain options can append additional options to the end of the enforced
|
|
140
|
+
// ones without restrictions.
|
|
141
|
+
if (dvnIdx == 255) revert DVN_InvalidDVNIdx();
|
|
142
|
+
if (!bitmap.get(dvnIdx)) {
|
|
143
|
+
++numDVNs;
|
|
144
|
+
bitmap = bitmap.set(dvnIdx);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
cursor += optionLength;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (cursor != _options.length) revert DVN_InvalidDVNOptions(cursor);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/// @dev decode the next dvn option from _options starting from the specified cursor
|
|
154
|
+
/// @param _options the format is the same as groupDVNOptionsByIdx
|
|
155
|
+
/// @param _cursor the cursor to start decoding
|
|
156
|
+
/// @return optionType the type of the option
|
|
157
|
+
/// @return option the option
|
|
158
|
+
/// @return cursor the cursor to start decoding the next option
|
|
159
|
+
function nextDVNOption(
|
|
160
|
+
bytes calldata _options,
|
|
161
|
+
uint256 _cursor
|
|
162
|
+
) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) {
|
|
163
|
+
unchecked {
|
|
164
|
+
// skip worker id
|
|
165
|
+
cursor = _cursor + 1;
|
|
166
|
+
|
|
167
|
+
// read option size
|
|
168
|
+
uint16 size = _options.toU16(cursor);
|
|
169
|
+
cursor += 2;
|
|
170
|
+
|
|
171
|
+
// read option type
|
|
172
|
+
optionType = _options.toU8(cursor + 1); // skip dvn_idx
|
|
173
|
+
|
|
174
|
+
// startCursor and endCursor are used to slice the option from _options
|
|
175
|
+
uint256 startCursor = cursor + 2; // skip option type and dvn_idx
|
|
176
|
+
uint256 endCursor = cursor + size;
|
|
177
|
+
option = _options[startCursor:endCursor];
|
|
178
|
+
cursor += size;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// SPDX-License-Identifier: LZBL-1.2
|
|
2
|
+
|
|
3
|
+
pragma solidity ^0.8.20;
|
|
4
|
+
|
|
5
|
+
import { SupportedCmdTypes, SupportedCmdTypesLib } from "./SupportedCmdTypes.sol";
|
|
6
|
+
|
|
7
|
+
library ReadCmdCodecV1 {
|
|
8
|
+
uint16 internal constant CMD_VERSION = 1;
|
|
9
|
+
uint8 internal constant REQUEST_VERSION = 1;
|
|
10
|
+
uint16 internal constant RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL = 1;
|
|
11
|
+
uint8 internal constant COMPUTE_VERSION = 1;
|
|
12
|
+
uint16 internal constant COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL = 1;
|
|
13
|
+
|
|
14
|
+
uint8 internal constant COMPUTE_SETTING_MAP_ONLY = 0;
|
|
15
|
+
uint8 internal constant COMPUTE_SETTING_REDUCE_ONLY = 1;
|
|
16
|
+
uint8 internal constant COMPUTE_SETTING_MAP_AND_REDUCE = 2;
|
|
17
|
+
|
|
18
|
+
error InvalidCmd();
|
|
19
|
+
error InvalidVersion();
|
|
20
|
+
error InvalidType();
|
|
21
|
+
|
|
22
|
+
struct Cmd {
|
|
23
|
+
uint16 numEvmCallRequestV1;
|
|
24
|
+
bool evmCallComputeV1Map;
|
|
25
|
+
bool evmCallComputeV1Reduce;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function decode(
|
|
29
|
+
bytes calldata _cmd,
|
|
30
|
+
function(uint32, bool, uint64, uint8) view _assertCmdTypeSupported
|
|
31
|
+
) internal view returns (Cmd memory cmd) {
|
|
32
|
+
uint256 cursor = 0;
|
|
33
|
+
// decode the header in scope, depress stack too deep
|
|
34
|
+
{
|
|
35
|
+
uint16 cmdVersion = uint16(bytes2(_cmd[cursor:cursor + 2]));
|
|
36
|
+
cursor += 2;
|
|
37
|
+
if (cmdVersion != CMD_VERSION) revert InvalidVersion();
|
|
38
|
+
|
|
39
|
+
cursor += 2; // skip appCmdLabel
|
|
40
|
+
|
|
41
|
+
uint16 requestCount = uint16(bytes2(_cmd[cursor:cursor + 2]));
|
|
42
|
+
cursor += 2;
|
|
43
|
+
|
|
44
|
+
// there is only one request type in this version, so total request count should be the same as numEvmCallRequestV1
|
|
45
|
+
if (requestCount == 0) revert InvalidCmd();
|
|
46
|
+
cmd.numEvmCallRequestV1 = requestCount;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// decode the requests
|
|
50
|
+
for (uint16 i = 0; i < cmd.numEvmCallRequestV1; i++) {
|
|
51
|
+
uint8 requestVersion = uint8(_cmd[cursor]);
|
|
52
|
+
cursor += 1;
|
|
53
|
+
if (requestVersion != REQUEST_VERSION) revert InvalidVersion();
|
|
54
|
+
|
|
55
|
+
// skip appRequestLabel
|
|
56
|
+
cursor += 2;
|
|
57
|
+
|
|
58
|
+
uint16 resolverType = uint16(bytes2(_cmd[cursor:cursor + 2]));
|
|
59
|
+
cursor += 2;
|
|
60
|
+
|
|
61
|
+
if (resolverType == RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL) {
|
|
62
|
+
uint16 requestSize = uint16(bytes2(_cmd[cursor:cursor + 2]));
|
|
63
|
+
cursor += 2;
|
|
64
|
+
|
|
65
|
+
// decode the request in scope, depress stack too deep
|
|
66
|
+
{
|
|
67
|
+
uint256 requestCursor = cursor;
|
|
68
|
+
uint32 targetEid = uint32(bytes4(_cmd[requestCursor:requestCursor + 4]));
|
|
69
|
+
requestCursor += 4;
|
|
70
|
+
|
|
71
|
+
bool isBlockNum = uint8(_cmd[requestCursor]) == 1;
|
|
72
|
+
requestCursor += 1;
|
|
73
|
+
|
|
74
|
+
uint64 blockNumOrTimestamp = uint64(bytes8(_cmd[requestCursor:requestCursor + 8]));
|
|
75
|
+
|
|
76
|
+
_assertCmdTypeSupported(
|
|
77
|
+
targetEid,
|
|
78
|
+
isBlockNum,
|
|
79
|
+
blockNumOrTimestamp,
|
|
80
|
+
SupportedCmdTypesLib.CMD_V1__REQUEST_V1__EVM_CALL
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (cursor + requestSize > _cmd.length) revert InvalidCmd();
|
|
85
|
+
cursor += requestSize;
|
|
86
|
+
} else {
|
|
87
|
+
revert InvalidType();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// decode the compute if it exists
|
|
92
|
+
if (cursor < _cmd.length) {
|
|
93
|
+
uint8 computeVersion = uint8(_cmd[cursor]);
|
|
94
|
+
cursor += 1;
|
|
95
|
+
if (computeVersion != COMPUTE_VERSION) revert InvalidVersion();
|
|
96
|
+
|
|
97
|
+
uint16 computeType = uint16(bytes2(_cmd[cursor:cursor + 2]));
|
|
98
|
+
cursor += 2;
|
|
99
|
+
if (computeType != COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL) revert InvalidType();
|
|
100
|
+
|
|
101
|
+
uint8 computeSetting = uint8(_cmd[cursor]);
|
|
102
|
+
cursor += 1;
|
|
103
|
+
|
|
104
|
+
if (computeSetting == COMPUTE_SETTING_MAP_ONLY) {
|
|
105
|
+
cmd.evmCallComputeV1Map = true;
|
|
106
|
+
} else if (computeSetting == COMPUTE_SETTING_REDUCE_ONLY) {
|
|
107
|
+
cmd.evmCallComputeV1Reduce = true;
|
|
108
|
+
} else if (computeSetting == COMPUTE_SETTING_MAP_AND_REDUCE) {
|
|
109
|
+
cmd.evmCallComputeV1Map = true;
|
|
110
|
+
cmd.evmCallComputeV1Reduce = true;
|
|
111
|
+
} else {
|
|
112
|
+
revert InvalidType();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
uint32 targetEid = uint32(bytes4(_cmd[cursor:cursor + 4]));
|
|
116
|
+
cursor += 4;
|
|
117
|
+
|
|
118
|
+
bool isBlockNum = uint8(_cmd[cursor]) == 1;
|
|
119
|
+
cursor += 1;
|
|
120
|
+
|
|
121
|
+
uint64 blockNumOrTimestamp = uint64(bytes8(_cmd[cursor:cursor + 8]));
|
|
122
|
+
cursor += 8;
|
|
123
|
+
|
|
124
|
+
_assertCmdTypeSupported(
|
|
125
|
+
targetEid,
|
|
126
|
+
isBlockNum,
|
|
127
|
+
blockNumOrTimestamp,
|
|
128
|
+
SupportedCmdTypesLib.CMD_V1__COMPUTE_V1__EVM_CALL
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
// assert the remaining length: confirmations(2), to(20)
|
|
132
|
+
cursor += 22;
|
|
133
|
+
}
|
|
134
|
+
if (cursor != _cmd.length) revert InvalidCmd();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity ^0.8.20;
|
|
4
|
+
|
|
5
|
+
import { BitMap256 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/BitMaps.sol";
|
|
6
|
+
|
|
7
|
+
struct SupportedCmdTypes {
|
|
8
|
+
mapping(uint32 => BitMap256) cmdTypes; // support options
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
using SupportedCmdTypesLib for SupportedCmdTypes global;
|
|
12
|
+
|
|
13
|
+
library SupportedCmdTypesLib {
|
|
14
|
+
// the max number of supported command types is 256
|
|
15
|
+
uint8 internal constant CMD_V1__REQUEST_V1__EVM_CALL = 0;
|
|
16
|
+
uint8 internal constant CMD_V1__COMPUTE_V1__EVM_CALL = 1;
|
|
17
|
+
uint8 internal constant CMD_V1__TIMESTAMP_VALIDATE = 2; // validate timestamp, to check if the timestamp is out of range
|
|
18
|
+
// more types can be added here in the future
|
|
19
|
+
|
|
20
|
+
error UnsupportedTargetEid();
|
|
21
|
+
|
|
22
|
+
function assertSupported(SupportedCmdTypes storage _self, uint32 _targetEid, uint8 _type) internal view {
|
|
23
|
+
if (!isSupported(_self, _targetEid, _type)) revert UnsupportedTargetEid();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isSupported(SupportedCmdTypes storage _self, uint32 _targetEid, uint8 _type) internal view returns (bool) {
|
|
27
|
+
return _self.cmdTypes[_targetEid].get(_type);
|
|
28
|
+
}
|
|
29
|
+
}
|