solidity-scale-codec 0.3.4 → 1.0.1

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 (47) hide show
  1. package/CHANGELOG.md +37 -3
  2. package/README.md +10 -28
  3. package/package.json +2 -2
  4. package/src/Utils/BytesUtils.sol +26 -0
  5. package/src/Utils/UnsignedUtils.sol +52 -0
  6. package/src/Xcm/VersionedXcm/VersionedXcm.sol +4 -1
  7. package/src/Xcm/VersionedXcm/VersionedXcmCodec.sol +11 -0
  8. package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCode.sol +8 -7
  9. package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCodeCodec.sol +18 -19
  10. package/src/Xcm/v5/AssetFilter/AssetFilter.sol +8 -8
  11. package/src/Xcm/v5/AssetFilter/AssetFilterCodec.sol +47 -34
  12. package/src/Xcm/v5/AssetInstance/AssetInstance.sol +13 -12
  13. package/src/Xcm/v5/AssetInstance/AssetInstanceCodec.sol +53 -56
  14. package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilter.sol +12 -12
  15. package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilterCodec.sol +48 -20
  16. package/src/Xcm/v5/Assets/Assets.sol +16 -0
  17. package/src/Xcm/v5/Assets/AssetsCodec.sol +3 -3
  18. package/src/Xcm/v5/BodyId/BodyId.sol +24 -24
  19. package/src/Xcm/v5/BodyId/BodyIdCodec.sol +41 -48
  20. package/src/Xcm/v5/BodyPart/BodyPart.sol +44 -28
  21. package/src/Xcm/v5/BodyPart/BodyPartCodec.sol +70 -37
  22. package/src/Xcm/v5/Constants.sol +2 -2
  23. package/src/Xcm/v5/Fungibility/Fungibility.sol +6 -6
  24. package/src/Xcm/v5/Fungibility/FungibilityCodec.sol +40 -36
  25. package/src/Xcm/v5/Hint/Hint.sol +5 -5
  26. package/src/Xcm/v5/Hint/HintCodec.sol +24 -20
  27. package/src/Xcm/v5/Instruction/Instruction.sol +81 -55
  28. package/src/Xcm/v5/Instruction/InstructionCodec.sol +1047 -73
  29. package/src/Xcm/v5/Junction/Junction.sol +55 -69
  30. package/src/Xcm/v5/Junction/JunctionCodec.sol +72 -135
  31. package/src/Xcm/v5/Junctions/Junctions.sol +34 -0
  32. package/src/Xcm/v5/Junctions/JunctionsCodec.sol +0 -18
  33. package/src/Xcm/v5/Location/Location.sol +8 -0
  34. package/src/Xcm/v5/NetworkId/NetworkId.sol +15 -16
  35. package/src/Xcm/v5/NetworkId/NetworkIdCodec.sol +57 -34
  36. package/src/Xcm/v5/OriginKind/OriginKindCodec.sol +1 -1
  37. package/src/Xcm/v5/Response/Response.sol +49 -40
  38. package/src/Xcm/v5/Response/ResponseCodec.sol +64 -54
  39. package/src/Xcm/v5/Weight/WeightCodec.sol +3 -2
  40. package/src/Xcm/v5/WeightLimit/WeightLimit.sol +6 -6
  41. package/src/Xcm/v5/WeightLimit/WeightLimitCodec.sol +32 -23
  42. package/src/Xcm/v5/WildAsset/WildAsset.sol +17 -25
  43. package/src/Xcm/v5/WildAsset/WildAssetCodec.sol +35 -38
  44. package/src/Xcm/v5/WildFungibility/WildFungibilityCodec.sol +6 -6
  45. package/src/Xcm/v5/Xcm/XcmBuilder.sol +689 -0
  46. package/src/Xcm/v5/XcmError/XcmError.sol +7 -7
  47. package/src/Xcm/v5/XcmError/XcmErrorCodec.sol +25 -22
@@ -5,7 +5,7 @@ import {Compact} from "../../../Scale/Compact.sol";
5
5
  import {LittleEndianU64} from "../../../LittleEndian/LittleEndianU64.sol";
6
6
 
7
7
  /// @dev Discriminant for the different types of NetworkIds in XCM v5.
8
- enum NetworkIdType {
8
+ enum NetworkIdVariant {
9
9
  /// @custom:variant Network specified by the first 32 bytes of its genesis block.
10
10
  ByGenesis,
11
11
  /// @custom:variant Network defined by the first 32-bytes of the hash and number of some block it contains.
@@ -52,9 +52,9 @@ struct ByGenesisParams {
52
52
 
53
53
  /// @dev Notice A global identifier of a data structure existing within consensus.
54
54
  struct NetworkId {
55
- /// @custom:property The type of network ID, determining how to interpret the payload. See `NetworkIdType` enum for possible values.
56
- NetworkIdType nType;
57
- /// @custom:property The encoded payload containing the network identifier data, whose structure depends on the `nType`.
55
+ /// @custom:property The type of network ID, determining how to interpret the payload. See `NetworkIdVariant` enum for possible values.
56
+ NetworkIdVariant variant;
57
+ /// @custom:property The encoded payload containing the network identifier data, whose structure depends on the `variant`.
58
58
  bytes payload;
59
59
  }
60
60
 
@@ -70,36 +70,35 @@ function byGenesis(
70
70
  ) pure returns (NetworkId memory) {
71
71
  return
72
72
  NetworkId({
73
- nType: NetworkIdType.ByGenesis,
73
+ variant: NetworkIdVariant.ByGenesis,
74
74
  payload: abi.encodePacked(params.genesisHash)
75
75
  });
76
76
  }
77
77
 
78
78
  /// @notice Creates a `ByFork` network ID.
79
- /// @param blockNumber The block number of the fork point.
80
- /// @param blockHash The 32-byte hash of the block at the fork point.
79
+ /// @param params Parameters for the by-fork variant.
81
80
  /// @return A `NetworkId` struct with type `ByFork` and the provided block number and hash encoded in the payload.
82
- function byFork(
83
- uint64 blockNumber,
84
- bytes32 blockHash
85
- ) pure returns (NetworkId memory) {
81
+ function byFork(ByForkParams memory params) pure returns (NetworkId memory) {
86
82
  return
87
83
  NetworkId({
88
- nType: NetworkIdType.ByFork,
89
- payload: abi.encodePacked(blockNumber.toLittleEndian(), blockHash)
84
+ variant: NetworkIdVariant.ByFork,
85
+ payload: abi.encodePacked(
86
+ params.blockNumber.toLittleEndian(),
87
+ params.blockHash
88
+ )
90
89
  });
91
90
  }
92
91
 
93
92
  /// @notice Creates a `Polkadot` network ID.
94
93
  /// @return A `NetworkId` struct with type `Polkadot` and an empty payload.
95
94
  function polkadot() pure returns (NetworkId memory) {
96
- return NetworkId({nType: NetworkIdType.Polkadot, payload: ""});
95
+ return NetworkId({variant: NetworkIdVariant.Polkadot, payload: ""});
97
96
  }
98
97
 
99
98
  /// @notice Creates a `Kusama` network ID.
100
99
  /// @return A `NetworkId` struct with type `Kusama` and an empty payload.
101
100
  function kusama() pure returns (NetworkId memory) {
102
- return NetworkId({nType: NetworkIdType.Kusama, payload: ""});
101
+ return NetworkId({variant: NetworkIdVariant.Kusama, payload: ""});
103
102
  }
104
103
 
105
104
  /// @notice Creates an `Ethereum` network ID.
@@ -109,7 +108,7 @@ function ethereum(
109
108
  ) pure returns (NetworkId memory) {
110
109
  return
111
110
  NetworkId({
112
- nType: NetworkIdType.Ethereum,
111
+ variant: NetworkIdVariant.Ethereum,
113
112
  payload: Compact.encode(params.chainId)
114
113
  });
115
114
  }
@@ -2,7 +2,17 @@
2
2
  pragma solidity ^0.8.28;
3
3
 
4
4
  import {Compact} from "../../../Scale/Compact.sol";
5
- import {NetworkId, NetworkIdType} from "./NetworkId.sol";
5
+ import {
6
+ NetworkId,
7
+ NetworkIdVariant,
8
+ ByForkParams,
9
+ ByGenesisParams,
10
+ EthereumParams
11
+ } from "./NetworkId.sol";
12
+ import {LittleEndianU64} from "../../../LittleEndian/LittleEndianU64.sol";
13
+ import {Bytes32} from "../../../Scale/Bytes.sol";
14
+ import {BytesUtils} from "../../../Utils/BytesUtils.sol";
15
+ import {UnsignedUtils} from "../../../Utils/UnsignedUtils.sol";
6
16
 
7
17
  /// @title SCALE Codec for XCM v5 `NetworkId`
8
18
  /// @notice SCALE-compliant encoder/decoder for the `NetworkId` type.
@@ -10,14 +20,13 @@ import {NetworkId, NetworkIdType} from "./NetworkId.sol";
10
20
  /// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
11
21
  library NetworkIdCodec {
12
22
  error InvalidNetworkIdLength();
13
- error InvalidNetworkIdType(uint8 nType);
14
- error InvalidNetworkIdPayload();
23
+ error InvalidNetworkIdVariant(uint8 variant);
15
24
 
16
25
  /// @notice Encodes a `NetworkId` struct into SCALE format.
17
26
  function encode(
18
27
  NetworkId memory networkId
19
28
  ) internal pure returns (bytes memory) {
20
- return abi.encodePacked(uint8(networkId.nType), networkId.payload);
29
+ return abi.encodePacked(uint8(networkId.variant), networkId.payload);
21
30
  }
22
31
 
23
32
  /// @notice Returns the number of bytes that a `NetworkId` struct would occupy when SCALE-encoded.
@@ -30,21 +39,21 @@ library NetworkIdCodec {
30
39
  ) internal pure returns (uint256) {
31
40
  if (offset >= data.length) revert InvalidNetworkIdLength();
32
41
 
33
- uint8 nType = uint8(data[offset]);
42
+ uint8 variant = uint8(data[offset]);
34
43
  uint256 payloadLen;
35
44
 
36
45
  // Determine payload length based on type to ensure we don't over-read
37
- if (nType == uint8(NetworkIdType.ByGenesis)) {
46
+ if (variant == uint8(NetworkIdVariant.ByGenesis)) {
38
47
  payloadLen = 32;
39
- } else if (nType == uint8(NetworkIdType.ByFork)) {
48
+ } else if (variant == uint8(NetworkIdVariant.ByFork)) {
40
49
  payloadLen = 40; // 8 (u64) + 32 (bytes32)
41
- } else if (nType == uint8(NetworkIdType.Ethereum)) {
50
+ } else if (variant == uint8(NetworkIdVariant.Ethereum)) {
42
51
  payloadLen = Compact.encodedSizeAt(data, offset + 1);
43
- } else if (nType < 4) {
52
+ } else if (variant < 4) {
44
53
  payloadLen = 0; // Static variants
45
54
  } else {
46
55
  // Reserved or unknown types are invalid
47
- revert InvalidNetworkIdType(nType);
56
+ revert InvalidNetworkIdVariant(variant);
48
57
  }
49
58
 
50
59
  if (offset + 1 + payloadLen > data.length)
@@ -70,45 +79,59 @@ library NetworkIdCodec {
70
79
  bytes memory data,
71
80
  uint256 offset
72
81
  ) 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
- }
82
+ uint256 payloadLen = encodedSizeAt(data, offset) - 1; // Subtract 1 byte for the variant
83
+ uint8 variant = uint8(data[offset]);
84
+ bytes memory payload = BytesUtils.copy(data, offset + 1, payloadLen);
81
85
 
82
- networkId = NetworkId({nType: NetworkIdType(nType), payload: payload});
86
+ networkId = NetworkId({
87
+ variant: NetworkIdVariant(variant),
88
+ payload: payload
89
+ });
83
90
 
84
91
  bytesRead = 1 + payloadLen;
85
92
  }
86
93
 
87
94
  /// @notice Decodes a `ByGenesis` network ID, returning the genesis hash.
88
95
  /// @param networkId The `NetworkId` struct to decode.
89
- /// @return genesisHash The genesis hash extracted from the network ID.
96
+ /// @return params A `ByGenesisParams` struct containing the genesis hash extracted from the network ID.
90
97
  function asByGenesis(
91
98
  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);
99
+ ) internal pure returns (ByGenesisParams memory params) {
100
+ _assertVariant(networkId, NetworkIdVariant.ByGenesis);
101
+ params.genesisHash = Bytes32.decode(networkId.payload);
97
102
  }
98
103
 
99
- /// @notice Decodes a `ByFork` network ID, returning the block number and hash.
104
+ /// @notice Decodes a `Ethereum` network ID, returning the chain ID.
100
105
  /// @param networkId The `NetworkId` struct to decode.
101
- /// @return chainId The chain ID extracted from the network ID.
106
+ /// @return params An `EthereumParams` struct containing the chain ID extracted from the network ID.
102
107
  function asEthereum(
103
108
  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();
109
+ ) internal pure returns (EthereumParams memory params) {
110
+ _assertVariant(networkId, NetworkIdVariant.Ethereum);
108
111
  (uint256 decodedChainId, ) = Compact.decode(networkId.payload);
109
- if (decodedChainId > type(uint64).max) revert InvalidNetworkIdPayload();
110
- unchecked {
111
- chainId = uint64(decodedChainId);
112
+ params.chainId = UnsignedUtils.toU64(decodedChainId);
113
+ }
114
+
115
+ /// @notice Decodes a `ByFork` network ID, returning the block number and block hash of the fork point.
116
+ /// @param networkId The `NetworkId` struct to decode.
117
+ /// @return params A `ByForkParams` struct containing the block number and block hash extracted from the network ID.
118
+ function asFork(
119
+ NetworkId memory networkId
120
+ ) internal pure returns (ByForkParams memory params) {
121
+ _assertVariant(networkId, NetworkIdVariant.ByFork);
122
+ params.blockNumber = LittleEndianU64.fromLittleEndian(
123
+ networkId.payload,
124
+ 0
125
+ );
126
+ params.blockHash = Bytes32.decodeAt(networkId.payload, 8);
127
+ }
128
+
129
+ function _assertVariant(
130
+ NetworkId memory networkId,
131
+ NetworkIdVariant expected
132
+ ) private pure {
133
+ if (networkId.variant != expected) {
134
+ revert InvalidNetworkIdVariant(uint8(networkId.variant));
112
135
  }
113
136
  }
114
137
  }
@@ -57,7 +57,7 @@ library OriginKindCodec {
57
57
  revert InvalidOriginKindLength();
58
58
  }
59
59
  uint8 originKindValue = uint8(data[offset]);
60
- if (originKindValue > uint8(OriginKind.Xcm)) {
60
+ if (originKindValue > uint8(type(OriginKind).max)) {
61
61
  revert InvalidOriginKind(originKindValue);
62
62
  }
63
63
  originKind = OriginKind(originKindValue);
@@ -15,7 +15,7 @@ import {LittleEndianU32} from "../../../LittleEndian/LittleEndianU32.sol";
15
15
  import {MAX_PALLETS_INFO} from "../Constants.sol";
16
16
 
17
17
  /// @notice Discriminant for the `Response` enum.
18
- enum ResponseType {
18
+ enum ResponseVariant {
19
19
  /// @custom:variant No response. Serves as a neutral default.
20
20
  Null,
21
21
  /// @custom:variant Some assets.
@@ -32,9 +32,9 @@ enum ResponseType {
32
32
 
33
33
  /// @notice Response data to a query.
34
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`.
35
+ /// @custom:property The type of the response. See `ResponseVariant` enum for possible values.
36
+ ResponseVariant variant;
37
+ /// @custom:property The SCALE-encoded payload of the response. Structure depends on `variant`.
38
38
  bytes payload;
39
39
  }
40
40
 
@@ -44,12 +44,28 @@ struct AssetsParams {
44
44
  Assets assets;
45
45
  }
46
46
 
47
+ /// @notice Parameters for the `ExecutionResult` response variant.
48
+ struct ExecutionResultParams {
49
+ /// @custom:property Indicates if there was an error.
50
+ bool hasError;
51
+ /// @custom:property The index of the instruction that caused the error.
52
+ uint32 index;
53
+ /// @custom:property The XCM error that occurred.
54
+ XcmError err;
55
+ }
56
+
47
57
  /// @notice Parameters for the `Version` response variant.
48
58
  struct VersionParams {
49
59
  /// @custom:property XCM version value.
50
60
  uint32 version;
51
61
  }
52
62
 
63
+ /// @notice Parameters for the `PalletsInfo` response variant.
64
+ struct PalletsInfoParams {
65
+ /// @custom:property Array of `PalletInfo` structs, containing the info of the pallets. Max length is MAX_PALLETS_INFO (64).
66
+ PalletInfo[] pallets;
67
+ }
68
+
53
69
  /// @notice Parameters for the `DispatchResult` response variant.
54
70
  struct DispatchResultParams {
55
71
  /// @custom:property Dispatch result status.
@@ -63,7 +79,7 @@ using LittleEndianU32 for uint32;
63
79
  /// @notice Creates a `Null` response.
64
80
  /// @return A `Response` struct representing the null response.
65
81
  function null_() pure returns (Response memory) {
66
- return Response({rType: ResponseType.Null, payload: ""});
82
+ return Response({variant: ResponseVariant.Null, payload: ""});
67
83
  }
68
84
 
69
85
  /// @notice Creates an `Assets` response.
@@ -72,39 +88,29 @@ function null_() pure returns (Response memory) {
72
88
  function assets(AssetsParams memory params) pure returns (Response memory) {
73
89
  return
74
90
  Response({
75
- rType: ResponseType.Assets,
91
+ variant: ResponseVariant.Assets,
76
92
  payload: AssetsCodec.encode(params.assets)
77
93
  });
78
94
  }
79
95
 
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
96
+ /// @notice Creates an `ExecutionResult` response.
97
+ /// @param params Parameters for the execution result variant.
98
+ /// @return A `Response` struct representing the execution result response.
99
+ function executionResult(
100
+ ExecutionResultParams memory params
98
101
  ) pure returns (Response memory) {
102
+ bytes memory payload;
103
+ if (!params.hasError) {
104
+ payload = abi.encodePacked(uint8(0));
105
+ } else {
106
+ payload = abi.encodePacked(
107
+ uint8(1),
108
+ params.index.toLittleEndian(),
109
+ XcmErrorCodec.encode(params.err)
110
+ );
111
+ }
99
112
  return
100
- Response({
101
- rType: ResponseType.ExecutionResult,
102
- payload: abi.encodePacked(
103
- uint8(1),
104
- index.toLittleEndian(),
105
- XcmErrorCodec.encode(err)
106
- )
107
- });
113
+ Response({variant: ResponseVariant.ExecutionResult, payload: payload});
108
114
  }
109
115
 
110
116
  /// @notice Creates a `Version` response.
@@ -113,22 +119,25 @@ function executionResultError(
113
119
  function version(VersionParams memory params) pure returns (Response memory) {
114
120
  return
115
121
  Response({
116
- rType: ResponseType.Version,
122
+ variant: ResponseVariant.Version,
117
123
  payload: abi.encodePacked(params.version.toLittleEndian())
118
124
  });
119
125
  }
120
126
 
121
127
  /// @notice Creates a `PalletsInfo` response.
122
- /// @param pallets The pallet info array. Max length is MAX_PALLETS_INFO (64).
128
+ /// @param params Parameters for the pallets info variant.
123
129
  /// @return A `Response` struct representing the pallets info response.
124
130
  function palletsInfo(
125
- PalletInfo[] memory pallets
131
+ PalletsInfoParams memory params
126
132
  ) 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]));
133
+ bytes memory encoded = Compact.encode(params.pallets.length);
134
+ for (uint256 i = 0; i < params.pallets.length; ++i) {
135
+ encoded = bytes.concat(
136
+ encoded,
137
+ PalletInfoCodec.encode(params.pallets[i])
138
+ );
130
139
  }
131
- return Response({rType: ResponseType.PalletsInfo, payload: encoded});
140
+ return Response({variant: ResponseVariant.PalletsInfo, payload: encoded});
132
141
  }
133
142
 
134
143
  /// @notice Creates a `DispatchResult` response.
@@ -139,7 +148,7 @@ function dispatchResult(
139
148
  ) pure returns (Response memory) {
140
149
  return
141
150
  Response({
142
- rType: ResponseType.DispatchResult,
151
+ variant: ResponseVariant.DispatchResult,
143
152
  payload: MaybeErrorCodeCodec.encode(params.result)
144
153
  });
145
154
  }
@@ -11,7 +11,17 @@ import {MaybeErrorCode} from "../../v3/MaybeErrorCode/MaybeErrorCode.sol";
11
11
  import {MaybeErrorCodeCodec} from "../../v3/MaybeErrorCode/MaybeErrorCodeCodec.sol";
12
12
  import {Compact} from "../../../Scale/Compact.sol";
13
13
  import {LittleEndianU32} from "../../../LittleEndian/LittleEndianU32.sol";
14
- import {Response, ResponseType} from "./Response.sol";
14
+ import {
15
+ Response,
16
+ ResponseVariant,
17
+ AssetsParams,
18
+ VersionParams,
19
+ DispatchResultParams,
20
+ ExecutionResultParams,
21
+ PalletsInfoParams
22
+ } from "./Response.sol";
23
+
24
+ import {BytesUtils} from "../../../Utils/BytesUtils.sol";
15
25
 
16
26
  /// @title SCALE Codec for XCM v5 `Response`
17
27
  /// @notice SCALE-compliant encoder/decoder for the `Response` type.
@@ -19,13 +29,13 @@ import {Response, ResponseType} from "./Response.sol";
19
29
  /// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
20
30
  library ResponseCodec {
21
31
  error InvalidResponseLength();
22
- error InvalidResponseType(uint8 rType);
32
+ error InvalidResponseVariant(uint8 variant);
23
33
 
24
34
  /// @notice Encodes a `Response` struct into SCALE bytes.
25
35
  /// @param r The `Response` struct to encode.
26
36
  /// @return SCALE-encoded bytes representing the `Response`.
27
37
  function encode(Response memory r) internal pure returns (bytes memory) {
28
- return abi.encodePacked(uint8(r.rType), r.payload);
38
+ return abi.encodePacked(uint8(r.variant), r.payload);
29
39
  }
30
40
 
31
41
  /// @notice Returns the number of bytes that a `Response` would occupy when SCALE-encoded.
@@ -37,22 +47,22 @@ library ResponseCodec {
37
47
  uint256 offset
38
48
  ) internal pure returns (uint256) {
39
49
  if (data.length < offset + 1) revert InvalidResponseLength();
40
- uint8 rType = uint8(data[offset]);
50
+ uint8 variant = uint8(data[offset]);
41
51
  uint256 pos = offset + 1;
42
52
 
43
- if (rType == uint8(ResponseType.Null)) {
53
+ if (variant == uint8(ResponseVariant.Null)) {
44
54
  return 1;
45
- } else if (rType == uint8(ResponseType.Assets)) {
55
+ } else if (variant == uint8(ResponseVariant.Assets)) {
46
56
  return 1 + AssetsCodec.encodedSizeAt(data, pos);
47
- } else if (rType == uint8(ResponseType.ExecutionResult)) {
57
+ } else if (variant == uint8(ResponseVariant.ExecutionResult)) {
48
58
  if (data.length < pos + 1) revert InvalidResponseLength();
49
59
  uint8 isSome = uint8(data[pos]);
50
60
  if (isSome == 0) return 2; // 1 type + 1 None byte
51
61
  return 2 + 4 + XcmErrorCodec.encodedSizeAt(data, pos + 1 + 4);
52
- } else if (rType == uint8(ResponseType.Version)) {
62
+ } else if (variant == uint8(ResponseVariant.Version)) {
53
63
  if (data.length < pos + 4) revert InvalidResponseLength();
54
64
  return 1 + 4; // 1 type + 4 bytes for version
55
- } else if (rType == uint8(ResponseType.PalletsInfo)) {
65
+ } else if (variant == uint8(ResponseVariant.PalletsInfo)) {
56
66
  (uint256 count, uint256 prefixSize) = Compact.decodeAt(data, pos);
57
67
  uint256 size = prefixSize;
58
68
  uint256 innerPos = pos + prefixSize;
@@ -65,10 +75,10 @@ library ResponseCodec {
65
75
  innerPos += palletSize;
66
76
  }
67
77
  return 1 + size;
68
- } else if (rType == uint8(ResponseType.DispatchResult)) {
78
+ } else if (variant == uint8(ResponseVariant.DispatchResult)) {
69
79
  return 1 + MaybeErrorCodeCodec.encodedSizeAt(data, pos);
70
80
  } else {
71
- revert InvalidResponseType(rType);
81
+ revert InvalidResponseVariant(variant);
72
82
  }
73
83
  }
74
84
 
@@ -91,84 +101,84 @@ library ResponseCodec {
91
101
  bytes memory data,
92
102
  uint256 offset
93
103
  ) internal pure returns (Response memory r, uint256 bytesRead) {
94
- if (data.length < offset + 1) revert InvalidResponseLength();
95
- uint8 rType = uint8(data[offset]);
96
104
  uint256 size = encodedSizeAt(data, offset);
105
+ uint8 variant = uint8(data[offset]);
97
106
  uint256 payloadLength = size - 1;
98
- bytes memory payload = new bytes(payloadLength);
99
- for (uint256 i = 0; i < payloadLength; ++i) {
100
- payload[i] = data[offset + 1 + i];
101
- }
102
- r = Response({rType: ResponseType(rType), payload: payload});
107
+ bytes memory payload = BytesUtils.copy(data, offset + 1, payloadLength);
108
+ r = Response({variant: ResponseVariant(variant), payload: payload});
103
109
  bytesRead = size;
104
110
  }
105
111
 
106
112
  /// @notice Decodes the `Assets` from an `Assets` response.
107
113
  /// @param r The `Response` struct. Must be of type `Assets`.
108
- /// @return The decoded `Assets`.
109
- function asAssets(Response memory r) internal pure returns (Assets memory) {
110
- if (r.rType != ResponseType.Assets)
111
- revert InvalidResponseType(uint8(r.rType));
112
- (Assets memory a, ) = AssetsCodec.decode(r.payload);
113
- return a;
114
+ /// @return params An `AssetsParams` struct containing the decoded assets.
115
+ function asAssets(
116
+ Response memory r
117
+ ) internal pure returns (AssetsParams memory params) {
118
+ _assertVariant(r, ResponseVariant.Assets);
119
+ (params.assets, ) = AssetsCodec.decode(r.payload);
114
120
  }
115
121
 
116
122
  /// @notice Decodes the execution result from an `ExecutionResult` response.
117
123
  /// @param r The `Response` struct. Must be of type `ExecutionResult`.
118
- /// @return hasError Whether the execution result contains an error.
119
- /// @return index The instruction index that caused the error. Only meaningful if `hasError` is true.
120
- /// @return err The XCM error. Only meaningful if `hasError` is true.
124
+ /// @return params An `ExecutionResultParams` struct containing the execution result details.
121
125
  function asExecutionResult(
122
126
  Response memory r
123
- ) internal pure returns (bool hasError, uint32 index, XcmError memory err) {
124
- if (r.rType != ResponseType.ExecutionResult)
125
- revert InvalidResponseType(uint8(r.rType));
126
- if (r.payload.length < 1) revert InvalidResponseLength();
127
- hasError = r.payload[0] != 0;
128
- if (hasError) {
129
- if (r.payload.length < 4) revert InvalidResponseLength();
130
- index = LittleEndianU32.fromLittleEndian(r.payload, 1);
131
- (err, ) = XcmErrorCodec.decodeAt(r.payload, 1 + 4);
127
+ ) internal pure returns (ExecutionResultParams memory params) {
128
+ _assertVariant(r, ResponseVariant.ExecutionResult);
129
+ params.hasError = r.payload[0] != 0;
130
+ if (params.hasError) {
131
+ params.index = LittleEndianU32.fromLittleEndian(r.payload, 1);
132
+ (params.err, ) = XcmErrorCodec.decodeAt(r.payload, 1 + 4);
132
133
  }
133
134
  }
134
135
 
135
136
  /// @notice Decodes the version from a `Version` response.
136
137
  /// @param r The `Response` struct. Must be of type `Version`.
137
- /// @return The decoded version.
138
- function asVersion(Response memory r) internal pure returns (uint32) {
139
- if (r.rType != ResponseType.Version)
140
- revert InvalidResponseType(uint8(r.rType));
141
- if (r.payload.length != 4) revert InvalidResponseLength();
142
- return LittleEndianU32.fromLittleEndian(r.payload, 0);
138
+ /// @return params A `VersionParams` struct containing the decoded version number.
139
+ function asVersion(
140
+ Response memory r
141
+ ) internal pure returns (VersionParams memory params) {
142
+ _assertVariant(r, ResponseVariant.Version);
143
+ params.version = LittleEndianU32.fromLittleEndian(r.payload, 0);
143
144
  }
144
145
 
145
146
  /// @notice Decodes the pallets info from a `PalletsInfo` response.
146
147
  /// @param r The `Response` struct. Must be of type `PalletsInfo`.
147
- /// @return pallets The decoded array of `PalletInfo`.
148
+ /// @return params A `PalletsInfoParams` struct containing the decoded array of `PalletInfo`.
148
149
  function asPalletsInfo(
149
150
  Response memory r
150
- ) internal pure returns (PalletInfo[] memory pallets) {
151
- if (r.rType != ResponseType.PalletsInfo)
152
- revert InvalidResponseType(uint8(r.rType));
151
+ ) internal pure returns (PalletsInfoParams memory params) {
152
+ _assertVariant(r, ResponseVariant.PalletsInfo);
153
153
  (uint256 count, uint256 prefixSize) = Compact.decodeAt(r.payload, 0);
154
- pallets = new PalletInfo[](count);
154
+ params.pallets = new PalletInfo[](count);
155
155
  uint256 pos = prefixSize;
156
156
  for (uint256 i = 0; i < count; ++i) {
157
157
  uint256 read;
158
- (pallets[i], read) = PalletInfoCodec.decodeAt(r.payload, pos);
158
+ (params.pallets[i], read) = PalletInfoCodec.decodeAt(
159
+ r.payload,
160
+ pos
161
+ );
159
162
  pos += read;
160
163
  }
161
164
  }
162
165
 
163
166
  /// @notice Decodes the dispatch result from a `DispatchResult` response.
164
167
  /// @param r The `Response` struct. Must be of type `DispatchResult`.
165
- /// @return The decoded `MaybeErrorCode`.
168
+ /// @return params A `DispatchResultParams` struct containing the decoded dispatch result.
166
169
  function asDispatchResult(
167
170
  Response memory r
168
- ) internal pure returns (MaybeErrorCode memory) {
169
- if (r.rType != ResponseType.DispatchResult)
170
- revert InvalidResponseType(uint8(r.rType));
171
- (MaybeErrorCode memory me, ) = MaybeErrorCodeCodec.decode(r.payload);
172
- return me;
171
+ ) internal pure returns (DispatchResultParams memory params) {
172
+ _assertVariant(r, ResponseVariant.DispatchResult);
173
+ (params.result, ) = MaybeErrorCodeCodec.decode(r.payload);
174
+ }
175
+
176
+ function _assertVariant(
177
+ Response memory r,
178
+ ResponseVariant expected
179
+ ) internal pure {
180
+ if (r.variant != expected) {
181
+ revert InvalidResponseVariant(uint8(r.variant));
182
+ }
173
183
  }
174
184
  }
@@ -3,6 +3,7 @@ pragma solidity ^0.8.28;
3
3
 
4
4
  import {Compact} from "../../../Scale/Compact.sol";
5
5
  import {Weight} from "./Weight.sol";
6
+ import {UnsignedUtils} from "../../../Utils/UnsignedUtils.sol";
6
7
 
7
8
  /// @title SCALE Codec for XCM v5 `Weight`
8
9
  /// @notice SCALE-compliant encoder/decoder for the `Weight` type.
@@ -79,8 +80,8 @@ library WeightCodec {
79
80
  offset += proofSizeBytes;
80
81
 
81
82
  weight = Weight({
82
- refTime: uint64(refTime),
83
- proofSize: uint64(proofSize)
83
+ refTime: UnsignedUtils.toU64(refTime),
84
+ proofSize: UnsignedUtils.toU64(proofSize)
84
85
  });
85
86
  bytesRead = refTimeBytes + proofSizeBytes;
86
87
  }
@@ -5,7 +5,7 @@ import {Weight} from "../Weight/Weight.sol";
5
5
  import {WeightCodec} from "../Weight/WeightCodec.sol";
6
6
 
7
7
  /// @notice Discriminant for the `WeightLimit` enum.
8
- enum WeightLimitType {
8
+ enum WeightLimitVariant {
9
9
  /// @custom:variant No limit on weight.
10
10
  Unlimited,
11
11
  /// @custom:variant A specific weight limit.
@@ -14,9 +14,9 @@ enum WeightLimitType {
14
14
 
15
15
  /// @notice An optional weight limit.
16
16
  struct WeightLimit {
17
- /// @custom:property The type of the weight limit. See `WeightLimitType` enum for possible values.
18
- WeightLimitType wlType;
19
- /// @custom:property The SCALE-encoded `Weight`. Only meaningful when `wlType` is `Limited`.
17
+ /// @custom:property The type of the weight limit. See `WeightLimitVariant` enum for possible values.
18
+ WeightLimitVariant variant;
19
+ /// @custom:property The SCALE-encoded `Weight`. Only meaningful when `variant` is `Limited`.
20
20
  bytes payload;
21
21
  }
22
22
 
@@ -31,7 +31,7 @@ struct LimitedParams {
31
31
  /// @notice Creates an `Unlimited` weight limit.
32
32
  /// @return A `WeightLimit` struct representing no limit.
33
33
  function unlimited() pure returns (WeightLimit memory) {
34
- return WeightLimit({wlType: WeightLimitType.Unlimited, payload: ""});
34
+ return WeightLimit({variant: WeightLimitVariant.Unlimited, payload: ""});
35
35
  }
36
36
 
37
37
  /// @notice Creates a `Limited` weight limit with the given `Weight`.
@@ -42,7 +42,7 @@ function limited(
42
42
  ) pure returns (WeightLimit memory) {
43
43
  return
44
44
  WeightLimit({
45
- wlType: WeightLimitType.Limited,
45
+ variant: WeightLimitVariant.Limited,
46
46
  payload: WeightCodec.encode(params.weight)
47
47
  });
48
48
  }