solidity-scale-codec 0.1.3 → 0.3.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.
Files changed (104) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/DEFINITIONS.md +132 -0
  3. package/README.md +97 -1
  4. package/package.json +16 -4
  5. package/src/LittleEndian/LittleEndianU128.sol +4 -2
  6. package/src/LittleEndian/LittleEndianU16.sol +2 -2
  7. package/src/LittleEndian/LittleEndianU256.sol +4 -2
  8. package/src/LittleEndian/LittleEndianU32.sol +4 -2
  9. package/src/LittleEndian/LittleEndianU64.sol +4 -2
  10. package/src/LittleEndian/LittleEndianU8.sol +2 -2
  11. package/src/Scale/Address/Address.sol +55 -0
  12. package/src/Scale/Address.sol +4 -0
  13. package/src/Scale/Array/BoolArr.sol +16 -2
  14. package/src/Scale/Array/I128Arr.sol +16 -2
  15. package/src/Scale/Array/I16Arr.sol +16 -2
  16. package/src/Scale/Array/I256Arr.sol +16 -2
  17. package/src/Scale/Array/I32Arr.sol +16 -2
  18. package/src/Scale/Array/I64Arr.sol +16 -2
  19. package/src/Scale/Array/I8Arr.sol +16 -2
  20. package/src/Scale/Array/U128Arr.sol +16 -2
  21. package/src/Scale/Array/U16Arr.sol +16 -2
  22. package/src/Scale/Array/U256Arr.sol +16 -2
  23. package/src/Scale/Array/U32Arr.sol +16 -2
  24. package/src/Scale/Array/U64Arr.sol +16 -2
  25. package/src/Scale/Array/U8Arr.sol +16 -2
  26. package/src/Scale/Bool/Bool.sol +12 -0
  27. package/src/Scale/Bytes/Bytes.sol +63 -0
  28. package/src/Scale/Bytes/Bytes16.sol +53 -0
  29. package/src/Scale/Bytes/Bytes2.sol +53 -0
  30. package/src/Scale/Bytes/Bytes32.sol +53 -0
  31. package/src/Scale/Bytes/Bytes4.sol +53 -0
  32. package/src/Scale/Bytes/Bytes8.sol +53 -0
  33. package/src/Scale/Bytes.sol +8 -0
  34. package/src/Scale/Compact/Compact.sol +37 -3
  35. package/src/Scale/Signed/I128.sol +11 -0
  36. package/src/Scale/Signed/I16.sol +11 -0
  37. package/src/Scale/Signed/I256.sol +11 -0
  38. package/src/Scale/Signed/I32.sol +11 -0
  39. package/src/Scale/Signed/I64.sol +11 -0
  40. package/src/Scale/Signed/I8.sol +11 -0
  41. package/src/Scale/Unsigned/U128.sol +16 -2
  42. package/src/Scale/Unsigned/U16.sol +16 -2
  43. package/src/Scale/Unsigned/U256.sol +16 -2
  44. package/src/Scale/Unsigned/U32.sol +16 -2
  45. package/src/Scale/Unsigned/U64.sol +16 -2
  46. package/src/Scale/Unsigned/U8.sol +16 -2
  47. package/src/Xcm/Types/Version.sol +5 -0
  48. package/src/Xcm/VersionedXcm/VersionedXcm.sol +27 -0
  49. package/src/Xcm/VersionedXcm/VersionedXcmCodec.sol +70 -0
  50. package/src/Xcm/v3/Constants.sol +5 -0
  51. package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCode.sol +73 -0
  52. package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCodeCodec.sol +94 -0
  53. package/src/Xcm/v5/Asset/Asset.sol +13 -0
  54. package/src/Xcm/v5/Asset/AssetCodec.sol +72 -0
  55. package/src/Xcm/v5/AssetFilter/AssetFilter.sol +61 -0
  56. package/src/Xcm/v5/AssetFilter/AssetFilterCodec.sol +105 -0
  57. package/src/Xcm/v5/AssetId/AssetId.sol +10 -0
  58. package/src/Xcm/v5/AssetId/AssetIdCodec.sol +57 -0
  59. package/src/Xcm/v5/AssetInstance/AssetInstance.sol +139 -0
  60. package/src/Xcm/v5/AssetInstance/AssetInstanceCodec.sol +174 -0
  61. package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilter.sol +82 -0
  62. package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilterCodec.sol +95 -0
  63. package/src/Xcm/v5/Assets/Assets.sol +14 -0
  64. package/src/Xcm/v5/Assets/AssetsCodec.sol +94 -0
  65. package/src/Xcm/v5/BodyId/BodyId.sol +121 -0
  66. package/src/Xcm/v5/BodyId/BodyIdCodec.sol +128 -0
  67. package/src/Xcm/v5/BodyPart/BodyPart.sol +105 -0
  68. package/src/Xcm/v5/BodyPart/BodyPartCodec.sol +134 -0
  69. package/src/Xcm/v5/Constants.sol +15 -0
  70. package/src/Xcm/v5/Fungibility/Fungibility.sol +60 -0
  71. package/src/Xcm/v5/Fungibility/FungibilityCodec.sol +128 -0
  72. package/src/Xcm/v5/Hint/Hint.sol +40 -0
  73. package/src/Xcm/v5/Hint/HintCodec.sol +82 -0
  74. package/src/Xcm/v5/Instruction/Instruction.sol +1217 -0
  75. package/src/Xcm/v5/Instruction/InstructionCodec.sol +321 -0
  76. package/src/Xcm/v5/Junction/Junction.sol +258 -0
  77. package/src/Xcm/v5/Junction/JunctionCodec.sol +329 -0
  78. package/src/Xcm/v5/Junctions/Junctions.sol +12 -0
  79. package/src/Xcm/v5/Junctions/JunctionsCodec.sol +120 -0
  80. package/src/Xcm/v5/Location/Location.sol +12 -0
  81. package/src/Xcm/v5/Location/LocationCodec.sol +68 -0
  82. package/src/Xcm/v5/NetworkId/NetworkId.sol +115 -0
  83. package/src/Xcm/v5/NetworkId/NetworkIdCodec.sol +114 -0
  84. package/src/Xcm/v5/OriginKind/OriginKind.sol +14 -0
  85. package/src/Xcm/v5/OriginKind/OriginKindCodec.sol +66 -0
  86. package/src/Xcm/v5/PalletInfo/PalletInfo.sol +18 -0
  87. package/src/Xcm/v5/PalletInfo/PalletInfoCodec.sol +119 -0
  88. package/src/Xcm/v5/QueryResponseInfo/QueryResponseInfo.sol +16 -0
  89. package/src/Xcm/v5/QueryResponseInfo/QueryResponseInfoCodec.sol +91 -0
  90. package/src/Xcm/v5/Response/Response.sol +145 -0
  91. package/src/Xcm/v5/Response/ResponseCodec.sol +174 -0
  92. package/src/Xcm/v5/Types/QueryId.sol +5 -0
  93. package/src/Xcm/v5/Weight/Weight.sol +10 -0
  94. package/src/Xcm/v5/Weight/WeightCodec.sol +87 -0
  95. package/src/Xcm/v5/WeightLimit/WeightLimit.sol +48 -0
  96. package/src/Xcm/v5/WeightLimit/WeightLimitCodec.sol +88 -0
  97. package/src/Xcm/v5/WildAsset/WildAsset.sol +112 -0
  98. package/src/Xcm/v5/WildAsset/WildAssetCodec.sol +166 -0
  99. package/src/Xcm/v5/WildFungibility/WildFungibility.sol +10 -0
  100. package/src/Xcm/v5/WildFungibility/WildFungibilityCodec.sol +74 -0
  101. package/src/Xcm/v5/Xcm/Xcm.sol +27 -0
  102. package/src/Xcm/v5/Xcm/XcmCodec.sol +83 -0
  103. package/src/Xcm/v5/XcmError/XcmError.sol +122 -0
  104. 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
+ }