solidity-scale-codec 0.1.3 → 0.2.0
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/CHANGELOG.md +15 -0
- package/DEFINITIONS.md +132 -0
- package/README.md +95 -1
- package/package.json +8 -3
- package/src/LittleEndian/LittleEndianU128.sol +4 -2
- package/src/LittleEndian/LittleEndianU16.sol +2 -2
- package/src/LittleEndian/LittleEndianU256.sol +4 -2
- package/src/LittleEndian/LittleEndianU32.sol +4 -2
- package/src/LittleEndian/LittleEndianU64.sol +4 -2
- package/src/LittleEndian/LittleEndianU8.sol +2 -2
- package/src/Scale/Address/Address.sol +55 -0
- package/src/Scale/Address.sol +4 -0
- package/src/Scale/Array/BoolArr.sol +16 -2
- package/src/Scale/Array/I128Arr.sol +16 -2
- package/src/Scale/Array/I16Arr.sol +16 -2
- package/src/Scale/Array/I256Arr.sol +16 -2
- package/src/Scale/Array/I32Arr.sol +16 -2
- package/src/Scale/Array/I64Arr.sol +16 -2
- package/src/Scale/Array/I8Arr.sol +16 -2
- package/src/Scale/Array/U128Arr.sol +16 -2
- package/src/Scale/Array/U16Arr.sol +16 -2
- package/src/Scale/Array/U256Arr.sol +16 -2
- package/src/Scale/Array/U32Arr.sol +16 -2
- package/src/Scale/Array/U64Arr.sol +16 -2
- package/src/Scale/Array/U8Arr.sol +16 -2
- package/src/Scale/Bool/Bool.sol +12 -0
- package/src/Scale/Bytes/Bytes.sol +63 -0
- package/src/Scale/Bytes/Bytes16.sol +53 -0
- package/src/Scale/Bytes/Bytes2.sol +53 -0
- package/src/Scale/Bytes/Bytes32.sol +53 -0
- package/src/Scale/Bytes/Bytes4.sol +53 -0
- package/src/Scale/Bytes/Bytes8.sol +53 -0
- package/src/Scale/Bytes.sol +8 -0
- package/src/Scale/Compact/Compact.sol +37 -3
- package/src/Scale/Signed/I128.sol +11 -0
- package/src/Scale/Signed/I16.sol +11 -0
- package/src/Scale/Signed/I256.sol +11 -0
- package/src/Scale/Signed/I32.sol +11 -0
- package/src/Scale/Signed/I64.sol +11 -0
- package/src/Scale/Signed/I8.sol +11 -0
- package/src/Scale/Unsigned/U128.sol +16 -2
- package/src/Scale/Unsigned/U16.sol +16 -2
- package/src/Scale/Unsigned/U256.sol +16 -2
- package/src/Scale/Unsigned/U32.sol +16 -2
- package/src/Scale/Unsigned/U64.sol +16 -2
- package/src/Scale/Unsigned/U8.sol +16 -2
- package/src/Xcm/Types/Version.sol +5 -0
- package/src/Xcm/VersionedXcm/VersionedXcm.sol +27 -0
- package/src/Xcm/VersionedXcm/VersionedXcmCodec.sol +70 -0
- package/src/Xcm/v3/Constants.sol +5 -0
- package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCode.sol +73 -0
- package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCodeCodec.sol +94 -0
- package/src/Xcm/v5/Asset/Asset.sol +13 -0
- package/src/Xcm/v5/Asset/AssetCodec.sol +72 -0
- package/src/Xcm/v5/AssetFilter/AssetFilter.sol +61 -0
- package/src/Xcm/v5/AssetFilter/AssetFilterCodec.sol +105 -0
- package/src/Xcm/v5/AssetId/AssetId.sol +10 -0
- package/src/Xcm/v5/AssetId/AssetIdCodec.sol +57 -0
- package/src/Xcm/v5/AssetInstance/AssetInstance.sol +139 -0
- package/src/Xcm/v5/AssetInstance/AssetInstanceCodec.sol +174 -0
- package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilter.sol +82 -0
- package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilterCodec.sol +95 -0
- package/src/Xcm/v5/Assets/Assets.sol +14 -0
- package/src/Xcm/v5/Assets/AssetsCodec.sol +94 -0
- package/src/Xcm/v5/BodyId/BodyId.sol +121 -0
- package/src/Xcm/v5/BodyId/BodyIdCodec.sol +128 -0
- package/src/Xcm/v5/BodyPart/BodyPart.sol +105 -0
- package/src/Xcm/v5/BodyPart/BodyPartCodec.sol +134 -0
- package/src/Xcm/v5/Constants.sol +15 -0
- package/src/Xcm/v5/Fungibility/Fungibility.sol +60 -0
- package/src/Xcm/v5/Fungibility/FungibilityCodec.sol +128 -0
- package/src/Xcm/v5/Hint/Hint.sol +40 -0
- package/src/Xcm/v5/Hint/HintCodec.sol +82 -0
- package/src/Xcm/v5/Instruction/Instruction.sol +1217 -0
- package/src/Xcm/v5/Instruction/InstructionCodec.sol +321 -0
- package/src/Xcm/v5/Junction/Junction.sol +258 -0
- package/src/Xcm/v5/Junction/JunctionCodec.sol +329 -0
- package/src/Xcm/v5/Junctions/Junctions.sol +12 -0
- package/src/Xcm/v5/Junctions/JunctionsCodec.sol +120 -0
- package/src/Xcm/v5/Location/Location.sol +12 -0
- package/src/Xcm/v5/Location/LocationCodec.sol +68 -0
- package/src/Xcm/v5/NetworkId/NetworkId.sol +115 -0
- package/src/Xcm/v5/NetworkId/NetworkIdCodec.sol +114 -0
- package/src/Xcm/v5/OriginKind/OriginKind.sol +14 -0
- package/src/Xcm/v5/OriginKind/OriginKindCodec.sol +66 -0
- package/src/Xcm/v5/PalletInfo/PalletInfo.sol +18 -0
- package/src/Xcm/v5/PalletInfo/PalletInfoCodec.sol +119 -0
- package/src/Xcm/v5/QueryResponseInfo/QueryResponseInfo.sol +16 -0
- package/src/Xcm/v5/QueryResponseInfo/QueryResponseInfoCodec.sol +91 -0
- package/src/Xcm/v5/Response/Response.sol +145 -0
- package/src/Xcm/v5/Response/ResponseCodec.sol +174 -0
- package/src/Xcm/v5/Types/QueryId.sol +5 -0
- package/src/Xcm/v5/Weight/Weight.sol +10 -0
- package/src/Xcm/v5/Weight/WeightCodec.sol +87 -0
- package/src/Xcm/v5/WeightLimit/WeightLimit.sol +48 -0
- package/src/Xcm/v5/WeightLimit/WeightLimitCodec.sol +88 -0
- package/src/Xcm/v5/WildAsset/WildAsset.sol +112 -0
- package/src/Xcm/v5/WildAsset/WildAssetCodec.sol +166 -0
- package/src/Xcm/v5/WildFungibility/WildFungibility.sol +10 -0
- package/src/Xcm/v5/WildFungibility/WildFungibilityCodec.sol +74 -0
- package/src/Xcm/v5/Xcm/Xcm.sol +27 -0
- package/src/Xcm/v5/Xcm/XcmCodec.sol +83 -0
- package/src/Xcm/v5/XcmError/XcmError.sol +122 -0
- package/src/Xcm/v5/XcmError/XcmErrorCodec.sol +85 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Compact} from "../../../Scale/Compact.sol";
|
|
5
|
+
import {NetworkId, NetworkIdType} from "./NetworkId.sol";
|
|
6
|
+
|
|
7
|
+
/// @title SCALE Codec for XCM v5 `NetworkId`
|
|
8
|
+
/// @notice SCALE-compliant encoder/decoder for the `NetworkId` type.
|
|
9
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
10
|
+
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
11
|
+
library NetworkIdCodec {
|
|
12
|
+
error InvalidNetworkIdLength();
|
|
13
|
+
error InvalidNetworkIdType(uint8 nType);
|
|
14
|
+
error InvalidNetworkIdPayload();
|
|
15
|
+
|
|
16
|
+
/// @notice Encodes a `NetworkId` struct into SCALE format.
|
|
17
|
+
function encode(
|
|
18
|
+
NetworkId memory networkId
|
|
19
|
+
) internal pure returns (bytes memory) {
|
|
20
|
+
return abi.encodePacked(uint8(networkId.nType), networkId.payload);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// @notice Returns the number of bytes that a `NetworkId` struct would occupy when SCALE-encoded.
|
|
24
|
+
/// @param data The byte sequence containing the encoded `NetworkId`.
|
|
25
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `NetworkId`.
|
|
26
|
+
/// @return The number of bytes that the `NetworkId` struct would occupy when SCALE-encoded.
|
|
27
|
+
function encodedSizeAt(
|
|
28
|
+
bytes memory data,
|
|
29
|
+
uint256 offset
|
|
30
|
+
) internal pure returns (uint256) {
|
|
31
|
+
if (offset >= data.length) revert InvalidNetworkIdLength();
|
|
32
|
+
|
|
33
|
+
uint8 nType = uint8(data[offset]);
|
|
34
|
+
uint256 payloadLen;
|
|
35
|
+
|
|
36
|
+
// Determine payload length based on type to ensure we don't over-read
|
|
37
|
+
if (nType == uint8(NetworkIdType.ByGenesis)) {
|
|
38
|
+
payloadLen = 32;
|
|
39
|
+
} else if (nType == uint8(NetworkIdType.ByFork)) {
|
|
40
|
+
payloadLen = 40; // 8 (u64) + 32 (bytes32)
|
|
41
|
+
} else if (nType == uint8(NetworkIdType.Ethereum)) {
|
|
42
|
+
payloadLen = Compact.encodedSizeAt(data, offset + 1);
|
|
43
|
+
} else if (nType < 4) {
|
|
44
|
+
payloadLen = 0; // Static variants
|
|
45
|
+
} else {
|
|
46
|
+
// Reserved or unknown types are invalid
|
|
47
|
+
revert InvalidNetworkIdType(nType);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (offset + 1 + payloadLen > data.length)
|
|
51
|
+
revert InvalidNetworkIdLength();
|
|
52
|
+
|
|
53
|
+
return 1 + payloadLen;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// @notice Decodes a byte array into a `NetworkId` struct.
|
|
57
|
+
/// @param data The byte array to decode.
|
|
58
|
+
/// @return networkId The decoded `NetworkId` struct.
|
|
59
|
+
function decode(
|
|
60
|
+
bytes memory data
|
|
61
|
+
) internal pure returns (NetworkId memory networkId, uint256 bytesRead) {
|
|
62
|
+
return decodeAt(data, 0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// @notice Decodes a byte array into a `NetworkId` struct.
|
|
66
|
+
/// @param data The byte array to decode.
|
|
67
|
+
/// @param offset The byte offset to start decoding from.
|
|
68
|
+
/// @return networkId The decoded `NetworkId` struct.
|
|
69
|
+
function decodeAt(
|
|
70
|
+
bytes memory data,
|
|
71
|
+
uint256 offset
|
|
72
|
+
) internal pure returns (NetworkId memory networkId, uint256 bytesRead) {
|
|
73
|
+
if (offset >= data.length) revert InvalidNetworkIdLength();
|
|
74
|
+
|
|
75
|
+
uint8 nType = uint8(data[offset]);
|
|
76
|
+
uint256 payloadLen = encodedSizeAt(data, offset) - 1; // Subtract 1 byte for the nType
|
|
77
|
+
bytes memory payload = new bytes(payloadLen);
|
|
78
|
+
for (uint256 i = 0; i < payloadLen; i++) {
|
|
79
|
+
payload[i] = data[offset + 1 + i];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
networkId = NetworkId({nType: NetworkIdType(nType), payload: payload});
|
|
83
|
+
|
|
84
|
+
bytesRead = 1 + payloadLen;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// @notice Decodes a `ByGenesis` network ID, returning the genesis hash.
|
|
88
|
+
/// @param networkId The `NetworkId` struct to decode.
|
|
89
|
+
/// @return genesisHash The genesis hash extracted from the network ID.
|
|
90
|
+
function asByGenesis(
|
|
91
|
+
NetworkId memory networkId
|
|
92
|
+
) internal pure returns (bytes32 genesisHash) {
|
|
93
|
+
if (networkId.nType != NetworkIdType.ByGenesis)
|
|
94
|
+
revert InvalidNetworkIdType(uint8(networkId.nType));
|
|
95
|
+
if (networkId.payload.length != 32) revert InvalidNetworkIdPayload();
|
|
96
|
+
return bytes32(networkId.payload);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// @notice Decodes a `ByFork` network ID, returning the block number and hash.
|
|
100
|
+
/// @param networkId The `NetworkId` struct to decode.
|
|
101
|
+
/// @return chainId The chain ID extracted from the network ID.
|
|
102
|
+
function asEthereum(
|
|
103
|
+
NetworkId memory networkId
|
|
104
|
+
) internal pure returns (uint64 chainId) {
|
|
105
|
+
if (networkId.nType != NetworkIdType.Ethereum)
|
|
106
|
+
revert InvalidNetworkIdType(uint8(networkId.nType));
|
|
107
|
+
if (networkId.payload.length != 8) revert InvalidNetworkIdPayload();
|
|
108
|
+
(uint256 decodedChainId, ) = Compact.decode(networkId.payload);
|
|
109
|
+
if (decodedChainId > type(uint64).max) revert InvalidNetworkIdPayload();
|
|
110
|
+
unchecked {
|
|
111
|
+
chainId = uint64(decodedChainId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
/// @notice Basically just the XCM (more general) version of ParachainDispatchOrigin.
|
|
5
|
+
enum OriginKind {
|
|
6
|
+
/// @custom:variant Origin should just be the native dispatch origin representation for the sender in the local runtime framework. For Cumulus/Frame chains this is the Parachain or Relay origin if coming from a chain, though there may be others if the MultiLocation XCM origin has a primary/native dispatch origin form.
|
|
7
|
+
Native,
|
|
8
|
+
/// @custom:variant Origin should just be the standard account-based origin with the sovereign account of the sender. For Cumulus/Frame chains, this is the Signed origin.
|
|
9
|
+
SovereignAccount,
|
|
10
|
+
/// @custom:variant Origin should be the super-user. For Cumulus/Frame chains, this is the Root origin. This will not usually be an available option.
|
|
11
|
+
Superuser,
|
|
12
|
+
/// @custom:variant Origin should be interpreted as an XCM native origin and the MultiLocation should be encoded directly in the dispatch origin unchanged. For Cumulus/Frame chains, this will be the `pallet_xcm::Origin::Xcm` type.
|
|
13
|
+
Xcm
|
|
14
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {OriginKind} from "./OriginKind.sol";
|
|
5
|
+
|
|
6
|
+
/// @title SCALE Codec for XCM v5 `OriginKind`
|
|
7
|
+
/// @notice SCALE-compliant encoder/decoder for the `OriginKind` type.
|
|
8
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
9
|
+
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
10
|
+
library OriginKindCodec {
|
|
11
|
+
error InvalidOriginKindLength();
|
|
12
|
+
error InvalidOriginKind(uint8 originKind);
|
|
13
|
+
|
|
14
|
+
/// @notice Encodes an `OriginKind` enum value into a bytes array using SCALE encoding.
|
|
15
|
+
/// @param originKind The `OriginKind` value to encode.
|
|
16
|
+
/// @return A bytes array containing the SCALE-encoded `OriginKind`.
|
|
17
|
+
function encode(
|
|
18
|
+
OriginKind originKind
|
|
19
|
+
) internal pure returns (bytes memory) {
|
|
20
|
+
return abi.encodePacked(uint8(originKind));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// @notice Returns the number of bytes that an `OriginKind` enum value would occupy when SCALE-encoded.
|
|
24
|
+
/// @param data The bytes array containing the encoded `OriginKind`.
|
|
25
|
+
/// @param offset The byte offset in the data array to start calculating from.
|
|
26
|
+
/// @return The number of bytes that the `OriginKind` enum value would occupy when SCALE-encoded.
|
|
27
|
+
function encodedSizeAt(
|
|
28
|
+
bytes memory data,
|
|
29
|
+
uint256 offset
|
|
30
|
+
) internal pure returns (uint256) {
|
|
31
|
+
if (offset >= data.length) {
|
|
32
|
+
revert InvalidOriginKindLength();
|
|
33
|
+
}
|
|
34
|
+
return 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// @notice Decodes a bytes array into an `OriginKind` enum value using SCALE decoding.
|
|
38
|
+
/// @param data The bytes array containing the SCALE-encoded `OriginKind`.
|
|
39
|
+
/// @return originKind The decoded `OriginKind` value.
|
|
40
|
+
/// @return bytesRead The number of bytes read from the data array during decoding.
|
|
41
|
+
function decode(
|
|
42
|
+
bytes memory data
|
|
43
|
+
) internal pure returns (OriginKind originKind, uint256 bytesRead) {
|
|
44
|
+
return decodeAt(data, 0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// @notice Decodes a bytes array into an `OriginKind` enum value starting at a specific offset.
|
|
48
|
+
/// @param data The bytes array containing the SCALE-encoded `OriginKind`.
|
|
49
|
+
/// @param offset The byte offset in the data array to start decoding from.
|
|
50
|
+
/// @return originKind The decoded `OriginKind` value.
|
|
51
|
+
/// @return bytesRead The number of bytes read from the data array during decoding.
|
|
52
|
+
function decodeAt(
|
|
53
|
+
bytes memory data,
|
|
54
|
+
uint256 offset
|
|
55
|
+
) internal pure returns (OriginKind originKind, uint256 bytesRead) {
|
|
56
|
+
if (offset >= data.length) {
|
|
57
|
+
revert InvalidOriginKindLength();
|
|
58
|
+
}
|
|
59
|
+
uint8 originKindValue = uint8(data[offset]);
|
|
60
|
+
if (originKindValue > uint8(OriginKind.Xcm)) {
|
|
61
|
+
revert InvalidOriginKind(originKindValue);
|
|
62
|
+
}
|
|
63
|
+
originKind = OriginKind(originKindValue);
|
|
64
|
+
bytesRead = 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
/// @notice Information about a pallet on a Substrate-based chain.
|
|
5
|
+
struct PalletInfo {
|
|
6
|
+
/// @custom:property The index which identifies the pallet.
|
|
7
|
+
uint32 index;
|
|
8
|
+
/// @custom:property The name of the pallet. Max length is `MAX_PALLET_NAME_LEN`.
|
|
9
|
+
uint8[] name;
|
|
10
|
+
/// @custom:property The module name of the pallet. Max length is `MAX_PALLET_NAME_LEN`.
|
|
11
|
+
uint8[] moduleName;
|
|
12
|
+
/// @custom:property The major version of the crate which implements the pallet.
|
|
13
|
+
uint32 major;
|
|
14
|
+
/// @custom:property The minor version of the crate which implements the pallet.
|
|
15
|
+
uint32 minor;
|
|
16
|
+
/// @custom:property The patch version of the crate which implements the pallet.
|
|
17
|
+
uint32 patch;
|
|
18
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Compact} from "../../../Scale/Compact.sol";
|
|
5
|
+
import {U8Arr} from "../../../Scale/Array.sol";
|
|
6
|
+
import {MAX_PALLET_NAME_LEN} from "../Constants.sol";
|
|
7
|
+
import {PalletInfo} from "./PalletInfo.sol";
|
|
8
|
+
|
|
9
|
+
/// @title SCALE Codec for XCM v5 `PalletInfo`
|
|
10
|
+
/// @notice SCALE-compliant encoder/decoder for the `PalletInfo` type.
|
|
11
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
12
|
+
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
13
|
+
library PalletInfoCodec {
|
|
14
|
+
error InvalidPalletInfoLength();
|
|
15
|
+
error PalletNameTooLong(uint256 length);
|
|
16
|
+
|
|
17
|
+
/// @notice Encodes a `PalletInfo` struct into SCALE bytes.
|
|
18
|
+
/// @param info The `PalletInfo` struct to encode.
|
|
19
|
+
/// @return SCALE-encoded bytes representing the `PalletInfo`.
|
|
20
|
+
function encode(
|
|
21
|
+
PalletInfo memory info
|
|
22
|
+
) internal pure returns (bytes memory) {
|
|
23
|
+
if (info.name.length > MAX_PALLET_NAME_LEN)
|
|
24
|
+
revert PalletNameTooLong(info.name.length);
|
|
25
|
+
if (info.moduleName.length > MAX_PALLET_NAME_LEN)
|
|
26
|
+
revert PalletNameTooLong(info.moduleName.length);
|
|
27
|
+
return
|
|
28
|
+
abi.encodePacked(
|
|
29
|
+
Compact.encode(info.index),
|
|
30
|
+
U8Arr.encode(info.name),
|
|
31
|
+
U8Arr.encode(info.moduleName),
|
|
32
|
+
Compact.encode(info.major),
|
|
33
|
+
Compact.encode(info.minor),
|
|
34
|
+
Compact.encode(info.patch)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// @notice Returns the number of bytes that a `PalletInfo` would occupy when SCALE-encoded.
|
|
39
|
+
/// @param data The byte sequence containing the encoded `PalletInfo`.
|
|
40
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size.
|
|
41
|
+
/// @return The number of bytes occupied by the encoded `PalletInfo`.
|
|
42
|
+
function encodedSizeAt(
|
|
43
|
+
bytes memory data,
|
|
44
|
+
uint256 offset
|
|
45
|
+
) internal pure returns (uint256) {
|
|
46
|
+
if (data.length < offset + 1) revert InvalidPalletInfoLength();
|
|
47
|
+
uint256 pos = offset;
|
|
48
|
+
pos += Compact.encodedSizeAt(data, pos); // index
|
|
49
|
+
pos += U8Arr.encodedSizeAt(data, pos); // name
|
|
50
|
+
pos += U8Arr.encodedSizeAt(data, pos); // moduleName
|
|
51
|
+
pos += Compact.encodedSizeAt(data, pos); // major
|
|
52
|
+
pos += Compact.encodedSizeAt(data, pos); // minor
|
|
53
|
+
pos += Compact.encodedSizeAt(data, pos); // patch
|
|
54
|
+
return pos - offset;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// @notice Decodes a `PalletInfo` from SCALE bytes starting at the beginning.
|
|
58
|
+
/// @param data The byte sequence containing the encoded `PalletInfo`.
|
|
59
|
+
/// @return info The decoded `PalletInfo` struct.
|
|
60
|
+
/// @return bytesRead The number of bytes read.
|
|
61
|
+
function decode(
|
|
62
|
+
bytes memory data
|
|
63
|
+
) internal pure returns (PalletInfo memory info, uint256 bytesRead) {
|
|
64
|
+
return decodeAt(data, 0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// @notice Decodes a `PalletInfo` from SCALE bytes starting at a given offset.
|
|
68
|
+
/// @param data The byte sequence containing the encoded `PalletInfo`.
|
|
69
|
+
/// @param offset The starting index in `data` from which to decode.
|
|
70
|
+
/// @return info The decoded `PalletInfo` struct.
|
|
71
|
+
/// @return bytesRead The number of bytes read.
|
|
72
|
+
function decodeAt(
|
|
73
|
+
bytes memory data,
|
|
74
|
+
uint256 offset
|
|
75
|
+
) internal pure returns (PalletInfo memory info, uint256 bytesRead) {
|
|
76
|
+
uint256 pos = offset;
|
|
77
|
+
uint256 index;
|
|
78
|
+
uint256 read;
|
|
79
|
+
|
|
80
|
+
(index, read) = Compact.decodeAt(data, pos);
|
|
81
|
+
pos += read;
|
|
82
|
+
|
|
83
|
+
uint8[] memory name;
|
|
84
|
+
(name, read) = U8Arr.decodeAt(data, pos);
|
|
85
|
+
pos += read;
|
|
86
|
+
|
|
87
|
+
uint8[] memory moduleName;
|
|
88
|
+
(moduleName, read) = U8Arr.decodeAt(data, pos);
|
|
89
|
+
pos += read;
|
|
90
|
+
|
|
91
|
+
uint256 major;
|
|
92
|
+
(major, read) = Compact.decodeAt(data, pos);
|
|
93
|
+
pos += read;
|
|
94
|
+
|
|
95
|
+
uint256 minor;
|
|
96
|
+
(minor, read) = Compact.decodeAt(data, pos);
|
|
97
|
+
pos += read;
|
|
98
|
+
|
|
99
|
+
uint256 patch;
|
|
100
|
+
(patch, read) = Compact.decodeAt(data, pos);
|
|
101
|
+
pos += read;
|
|
102
|
+
|
|
103
|
+
if (name.length > MAX_PALLET_NAME_LEN)
|
|
104
|
+
revert PalletNameTooLong(name.length);
|
|
105
|
+
|
|
106
|
+
if (moduleName.length > MAX_PALLET_NAME_LEN)
|
|
107
|
+
revert PalletNameTooLong(moduleName.length);
|
|
108
|
+
|
|
109
|
+
info = PalletInfo({
|
|
110
|
+
index: uint32(index),
|
|
111
|
+
name: name,
|
|
112
|
+
moduleName: moduleName,
|
|
113
|
+
major: uint32(major),
|
|
114
|
+
minor: uint32(minor),
|
|
115
|
+
patch: uint32(patch)
|
|
116
|
+
});
|
|
117
|
+
bytesRead = pos - offset;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Location} from "../Location/Location.sol";
|
|
5
|
+
import {Weight} from "../Weight/Weight.sol";
|
|
6
|
+
import {QueryId} from "../Types/QueryId.sol";
|
|
7
|
+
|
|
8
|
+
/// @notice Information regarding the composition of a query response.
|
|
9
|
+
struct QueryResponseInfo {
|
|
10
|
+
/// @custom:property The destination to which the query response message should be sent.
|
|
11
|
+
Location destination;
|
|
12
|
+
/// @custom:property The `query_id` field of the `QueryResponse` message.
|
|
13
|
+
QueryId queryId;
|
|
14
|
+
/// @custom:property The `max_weight` field of the `QueryResponse` message.
|
|
15
|
+
Weight maxWeight;
|
|
16
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Location} from "../Location/Location.sol";
|
|
5
|
+
import {LocationCodec} from "../Location/LocationCodec.sol";
|
|
6
|
+
import {Weight} from "../Weight/Weight.sol";
|
|
7
|
+
import {WeightCodec} from "../Weight/WeightCodec.sol";
|
|
8
|
+
import {QueryId} from "../Types/QueryId.sol";
|
|
9
|
+
import {Compact} from "../../../Scale/Compact.sol";
|
|
10
|
+
import {QueryResponseInfo} from "./QueryResponseInfo.sol";
|
|
11
|
+
|
|
12
|
+
/// @title SCALE Codec for XCM v5 `QueryResponseInfo`
|
|
13
|
+
/// @notice SCALE-compliant encoder/decoder for the `QueryResponseInfo` type.
|
|
14
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
15
|
+
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
16
|
+
library QueryResponseInfoCodec {
|
|
17
|
+
error InvalidQueryResponseInfoLength();
|
|
18
|
+
|
|
19
|
+
/// @notice Encodes a `QueryResponseInfo` struct into SCALE bytes.
|
|
20
|
+
/// @param info The `QueryResponseInfo` struct to encode.
|
|
21
|
+
/// @return SCALE-encoded bytes representing the `QueryResponseInfo`.
|
|
22
|
+
function encode(
|
|
23
|
+
QueryResponseInfo memory info
|
|
24
|
+
) internal pure returns (bytes memory) {
|
|
25
|
+
return
|
|
26
|
+
abi.encodePacked(
|
|
27
|
+
LocationCodec.encode(info.destination),
|
|
28
|
+
Compact.encode(QueryId.unwrap(info.queryId)),
|
|
29
|
+
WeightCodec.encode(info.maxWeight)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// @notice Returns the number of bytes that a `QueryResponseInfo` would occupy when SCALE-encoded.
|
|
34
|
+
/// @param data The byte sequence containing the encoded `QueryResponseInfo`.
|
|
35
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size.
|
|
36
|
+
/// @return The number of bytes occupied by the encoded `QueryResponseInfo`.
|
|
37
|
+
function encodedSizeAt(
|
|
38
|
+
bytes memory data,
|
|
39
|
+
uint256 offset
|
|
40
|
+
) internal pure returns (uint256) {
|
|
41
|
+
if (data.length < offset + 1) revert InvalidQueryResponseInfoLength();
|
|
42
|
+
uint256 pos = offset;
|
|
43
|
+
pos += LocationCodec.encodedSizeAt(data, pos);
|
|
44
|
+
pos += Compact.encodedSizeAt(data, pos);
|
|
45
|
+
pos += WeightCodec.encodedSizeAt(data, pos);
|
|
46
|
+
return pos - offset;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// @notice Decodes a `QueryResponseInfo` from SCALE bytes starting at the beginning.
|
|
50
|
+
/// @param data The byte sequence containing the encoded `QueryResponseInfo`.
|
|
51
|
+
/// @return info The decoded `QueryResponseInfo` struct.
|
|
52
|
+
/// @return bytesRead The number of bytes read.
|
|
53
|
+
function decode(
|
|
54
|
+
bytes memory data
|
|
55
|
+
) internal pure returns (QueryResponseInfo memory info, uint256 bytesRead) {
|
|
56
|
+
return decodeAt(data, 0);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// @notice Decodes a `QueryResponseInfo` from SCALE bytes starting at a given offset.
|
|
60
|
+
/// @param data The byte sequence containing the encoded `QueryResponseInfo`.
|
|
61
|
+
/// @param offset The starting index in `data` from which to decode.
|
|
62
|
+
/// @return info The decoded `QueryResponseInfo` struct.
|
|
63
|
+
/// @return bytesRead The number of bytes read.
|
|
64
|
+
function decodeAt(
|
|
65
|
+
bytes memory data,
|
|
66
|
+
uint256 offset
|
|
67
|
+
) internal pure returns (QueryResponseInfo memory info, uint256 bytesRead) {
|
|
68
|
+
if (data.length < offset + 1) revert InvalidQueryResponseInfoLength();
|
|
69
|
+
uint256 pos = offset;
|
|
70
|
+
uint256 read;
|
|
71
|
+
|
|
72
|
+
Location memory destination;
|
|
73
|
+
(destination, read) = LocationCodec.decodeAt(data, pos);
|
|
74
|
+
pos += read;
|
|
75
|
+
|
|
76
|
+
uint256 queryId;
|
|
77
|
+
(queryId, read) = Compact.decodeAt(data, pos);
|
|
78
|
+
pos += read;
|
|
79
|
+
|
|
80
|
+
Weight memory maxWeight;
|
|
81
|
+
(maxWeight, read) = WeightCodec.decodeAt(data, pos);
|
|
82
|
+
pos += read;
|
|
83
|
+
|
|
84
|
+
info = QueryResponseInfo({
|
|
85
|
+
destination: destination,
|
|
86
|
+
queryId: QueryId.wrap(uint64(queryId)),
|
|
87
|
+
maxWeight: maxWeight
|
|
88
|
+
});
|
|
89
|
+
bytesRead = pos - offset;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Assets} from "../Assets/Assets.sol";
|
|
5
|
+
import {AssetsCodec} from "../Assets/AssetsCodec.sol";
|
|
6
|
+
import {XcmError} from "../XcmError/XcmError.sol";
|
|
7
|
+
import {XcmErrorCodec} from "../XcmError/XcmErrorCodec.sol";
|
|
8
|
+
import {PalletInfo} from "../PalletInfo/PalletInfo.sol";
|
|
9
|
+
import {PalletInfoCodec} from "../PalletInfo/PalletInfoCodec.sol";
|
|
10
|
+
import {MaybeErrorCode} from "../../v3/MaybeErrorCode/MaybeErrorCode.sol";
|
|
11
|
+
import {MaybeErrorCodeCodec} from "../../v3/MaybeErrorCode/MaybeErrorCodeCodec.sol";
|
|
12
|
+
import {Version} from "../../Types/Version.sol";
|
|
13
|
+
import {Compact} from "../../../Scale/Compact.sol";
|
|
14
|
+
import {LittleEndianU32} from "../../../LittleEndian/LittleEndianU32.sol";
|
|
15
|
+
import {MAX_PALLETS_INFO} from "../Constants.sol";
|
|
16
|
+
|
|
17
|
+
/// @notice Discriminant for the `Response` enum.
|
|
18
|
+
enum ResponseType {
|
|
19
|
+
/// @custom:variant No response. Serves as a neutral default.
|
|
20
|
+
Null,
|
|
21
|
+
/// @custom:variant Some assets.
|
|
22
|
+
Assets,
|
|
23
|
+
/// @custom:variant The outcome of an XCM instruction.
|
|
24
|
+
ExecutionResult,
|
|
25
|
+
/// @custom:variant An XCM version.
|
|
26
|
+
Version,
|
|
27
|
+
/// @custom:variant The index, instance name, pallet name and version of some pallets.
|
|
28
|
+
PalletsInfo,
|
|
29
|
+
/// @custom:variant The status of a dispatch attempt using `Transact`.
|
|
30
|
+
DispatchResult
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// @notice Response data to a query.
|
|
34
|
+
struct Response {
|
|
35
|
+
/// @custom:property The type of the response. See `ResponseType` enum for possible values.
|
|
36
|
+
ResponseType rType;
|
|
37
|
+
/// @custom:property The SCALE-encoded payload of the response. Structure depends on `rType`.
|
|
38
|
+
bytes payload;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// @notice Parameters for the `Assets` response variant.
|
|
42
|
+
struct AssetsParams {
|
|
43
|
+
/// @custom:property Assets payload.
|
|
44
|
+
Assets assets;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// @notice Parameters for the `Version` response variant.
|
|
48
|
+
struct VersionParams {
|
|
49
|
+
/// @custom:property XCM version value.
|
|
50
|
+
uint32 version;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// @notice Parameters for the `DispatchResult` response variant.
|
|
54
|
+
struct DispatchResultParams {
|
|
55
|
+
/// @custom:property Dispatch result status.
|
|
56
|
+
MaybeErrorCode result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
using LittleEndianU32 for uint32;
|
|
60
|
+
|
|
61
|
+
// ============ Factory Functions ============
|
|
62
|
+
|
|
63
|
+
/// @notice Creates a `Null` response.
|
|
64
|
+
/// @return A `Response` struct representing the null response.
|
|
65
|
+
function null_() pure returns (Response memory) {
|
|
66
|
+
return Response({rType: ResponseType.Null, payload: ""});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// @notice Creates an `Assets` response.
|
|
70
|
+
/// @param params Parameters for the assets variant.
|
|
71
|
+
/// @return A `Response` struct representing the assets response.
|
|
72
|
+
function assets(AssetsParams memory params) pure returns (Response memory) {
|
|
73
|
+
return
|
|
74
|
+
Response({
|
|
75
|
+
rType: ResponseType.Assets,
|
|
76
|
+
payload: AssetsCodec.encode(params.assets)
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// @notice Creates an `ExecutionResult` response with no error.
|
|
81
|
+
/// @return A `Response` struct representing a successful execution result.
|
|
82
|
+
function executionResultSuccess() pure returns (Response memory) {
|
|
83
|
+
// Option<(u32, Error)>: None = 0x00
|
|
84
|
+
return
|
|
85
|
+
Response({
|
|
86
|
+
rType: ResponseType.ExecutionResult,
|
|
87
|
+
payload: abi.encodePacked(uint8(0))
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// @notice Creates an `ExecutionResult` response with an error.
|
|
92
|
+
/// @param index The index of the instruction that caused the error.
|
|
93
|
+
/// @param err The XCM error that occurred.
|
|
94
|
+
/// @return A `Response` struct representing a failed execution result.
|
|
95
|
+
function executionResultError(
|
|
96
|
+
uint32 index,
|
|
97
|
+
XcmError memory err
|
|
98
|
+
) pure returns (Response memory) {
|
|
99
|
+
return
|
|
100
|
+
Response({
|
|
101
|
+
rType: ResponseType.ExecutionResult,
|
|
102
|
+
payload: abi.encodePacked(
|
|
103
|
+
uint8(1),
|
|
104
|
+
index.toLittleEndian(),
|
|
105
|
+
XcmErrorCodec.encode(err)
|
|
106
|
+
)
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// @notice Creates a `Version` response.
|
|
111
|
+
/// @param params Parameters for the version variant.
|
|
112
|
+
/// @return A `Response` struct representing the version response.
|
|
113
|
+
function version(VersionParams memory params) pure returns (Response memory) {
|
|
114
|
+
return
|
|
115
|
+
Response({
|
|
116
|
+
rType: ResponseType.Version,
|
|
117
|
+
payload: abi.encodePacked(params.version.toLittleEndian())
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// @notice Creates a `PalletsInfo` response.
|
|
122
|
+
/// @param pallets The pallet info array. Max length is MAX_PALLETS_INFO (64).
|
|
123
|
+
/// @return A `Response` struct representing the pallets info response.
|
|
124
|
+
function palletsInfo(
|
|
125
|
+
PalletInfo[] memory pallets
|
|
126
|
+
) pure returns (Response memory) {
|
|
127
|
+
bytes memory encoded = Compact.encode(pallets.length);
|
|
128
|
+
for (uint256 i = 0; i < pallets.length; ++i) {
|
|
129
|
+
encoded = bytes.concat(encoded, PalletInfoCodec.encode(pallets[i]));
|
|
130
|
+
}
|
|
131
|
+
return Response({rType: ResponseType.PalletsInfo, payload: encoded});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/// @notice Creates a `DispatchResult` response.
|
|
135
|
+
/// @param params Parameters for the dispatch-result variant.
|
|
136
|
+
/// @return A `Response` struct representing the dispatch result response.
|
|
137
|
+
function dispatchResult(
|
|
138
|
+
DispatchResultParams memory params
|
|
139
|
+
) pure returns (Response memory) {
|
|
140
|
+
return
|
|
141
|
+
Response({
|
|
142
|
+
rType: ResponseType.DispatchResult,
|
|
143
|
+
payload: MaybeErrorCodeCodec.encode(params.result)
|
|
144
|
+
});
|
|
145
|
+
}
|