solidity-scale-codec 0.3.3 → 1.0.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 (48) hide show
  1. package/CHANGELOG.md +36 -2
  2. package/README.md +1 -1
  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
  48. package/DEFINITIONS.md +0 -132
@@ -6,7 +6,17 @@ import {Bytes4} from "../../../Scale/Bytes/Bytes4.sol";
6
6
  import {Bytes8} from "../../../Scale/Bytes/Bytes8.sol";
7
7
  import {Bytes16} from "../../../Scale/Bytes/Bytes16.sol";
8
8
  import {Bytes32} from "../../../Scale/Bytes/Bytes32.sol";
9
- import {AssetInstance, AssetInstanceType} from "./AssetInstance.sol";
9
+ import {
10
+ AssetInstance,
11
+ AssetInstanceVariant,
12
+ IndexParams,
13
+ Array4Params,
14
+ Array8Params,
15
+ Array16Params,
16
+ Array32Params
17
+ } from "./AssetInstance.sol";
18
+ import {BytesUtils} from "../../../Utils/BytesUtils.sol";
19
+ import {UnsignedUtils} from "../../../Utils/UnsignedUtils.sol";
10
20
 
11
21
  /// @title SCALE Codec for XCM v5 `AssetInstance`
12
22
  /// @notice SCALE-compliant encoder/decoder for the `AssetInstance` type.
@@ -14,8 +24,7 @@ import {AssetInstance, AssetInstanceType} from "./AssetInstance.sol";
14
24
  /// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
15
25
  library AssetInstanceCodec {
16
26
  error InvalidAssetInstanceLength();
17
- error InvalidAssetInstanceType(uint8 iType);
18
- error InvalidAssetInstancePayload();
27
+ error InvalidAssetInstanceVariant(uint8 variant);
19
28
 
20
29
  /// @notice Encodes an `AssetInstance` struct into bytes.
21
30
  /// @param assetInstance The `AssetInstance` struct to encode.
@@ -23,7 +32,7 @@ library AssetInstanceCodec {
23
32
  function encode(
24
33
  AssetInstance memory assetInstance
25
34
  ) internal pure returns (bytes memory) {
26
- return abi.encodePacked(assetInstance.iType, assetInstance.payload);
35
+ return abi.encodePacked(assetInstance.variant, assetInstance.payload);
27
36
  }
28
37
 
29
38
  /// @notice Returns the total number of bytes that an `AssetInstance` would occupy when encoded, based on the type and payload.
@@ -37,22 +46,22 @@ library AssetInstanceCodec {
37
46
  if (data.length < offset + 1) {
38
47
  revert InvalidAssetInstanceLength();
39
48
  }
40
- uint8 iType = uint8(data[offset]);
49
+ uint8 variant = uint8(data[offset]);
41
50
  uint256 payloadLength;
42
- if (iType == uint8(AssetInstanceType.Index)) {
51
+ if (variant == uint8(AssetInstanceVariant.Index)) {
43
52
  payloadLength = Compact.encodedSizeAt(data, offset + 1);
44
- } else if (iType == uint8(AssetInstanceType.Array4)) {
53
+ } else if (variant == uint8(AssetInstanceVariant.Array4)) {
45
54
  payloadLength = 4;
46
- } else if (iType == uint8(AssetInstanceType.Array8)) {
55
+ } else if (variant == uint8(AssetInstanceVariant.Array8)) {
47
56
  payloadLength = 8;
48
- } else if (iType == uint8(AssetInstanceType.Array16)) {
57
+ } else if (variant == uint8(AssetInstanceVariant.Array16)) {
49
58
  payloadLength = 16;
50
- } else if (iType == uint8(AssetInstanceType.Array32)) {
59
+ } else if (variant == uint8(AssetInstanceVariant.Array32)) {
51
60
  payloadLength = 32;
52
- } else if (iType == uint8(AssetInstanceType.Undefined)) {
61
+ } else if (variant == uint8(AssetInstanceVariant.Undefined)) {
53
62
  payloadLength = 0;
54
63
  } else {
55
- revert InvalidAssetInstanceType(iType);
64
+ revert InvalidAssetInstanceVariant(variant);
56
65
  }
57
66
 
58
67
  if (data.length < offset + 1 + payloadLength) {
@@ -89,18 +98,12 @@ library AssetInstanceCodec {
89
98
  pure
90
99
  returns (AssetInstance memory assetInstance, uint256 bytesRead)
91
100
  {
92
- if (data.length < offset + 1) {
93
- revert InvalidAssetInstanceLength();
94
- }
95
- uint8 iType = uint8(data[offset]);
96
- uint256 payloadLength = encodedSizeAt(data, offset) - 1; // subtract 1 byte for the iType
97
- bytes memory payload = new bytes(payloadLength);
98
- for (uint256 i = 0; i < payloadLength; i++) {
99
- payload[i] = data[offset + 1 + i];
100
- }
101
+ uint256 payloadLength = encodedSizeAt(data, offset) - 1; // subtract 1 byte for the variant
102
+ uint8 variant = uint8(data[offset]);
103
+ bytes memory payload = BytesUtils.copy(data, offset + 1, payloadLength);
101
104
 
102
105
  assetInstance = AssetInstance({
103
- iType: AssetInstanceType(iType),
106
+ variant: AssetInstanceVariant(variant),
104
107
  payload: payload
105
108
  });
106
109
  bytesRead = 1 + payloadLength;
@@ -108,67 +111,61 @@ library AssetInstanceCodec {
108
111
 
109
112
  /// @notice Extracts the index value from an `Index` asset instance. Reverts if the asset instance is not of type `Index` or if the decoded index exceeds the maximum value for `uint128`.
110
113
  /// @param assetInstance The `AssetInstance` struct to decode, which must have type `Index`.
111
- /// @return idx The index value extracted from the asset instance.
114
+ /// @return params A `IndexParams` struct containing the decoded index value.
112
115
  function asIndex(
113
116
  AssetInstance memory assetInstance
114
- ) internal pure returns (uint128 idx) {
115
- if (assetInstance.iType != AssetInstanceType.Index) {
116
- revert InvalidAssetInstanceType(uint8(assetInstance.iType));
117
- }
117
+ ) internal pure returns (IndexParams memory params) {
118
+ _assertVariant(assetInstance, AssetInstanceVariant.Index);
118
119
  (uint256 decodedIndex, ) = Compact.decode(assetInstance.payload);
119
- if (decodedIndex > type(uint128).max) {
120
- revert InvalidAssetInstancePayload();
121
- }
122
- unchecked {
123
- idx = uint128(decodedIndex);
124
- }
120
+ params.index = UnsignedUtils.toU128(decodedIndex);
125
121
  }
126
122
 
127
123
  /// @notice Extracts the 4-byte data from an `Array4` asset instance. Reverts if the asset instance is not of type `Array4`.
128
124
  /// @param assetInstance The `AssetInstance` struct to decode, which must have type `Array4`.
129
- /// @return data The 4-byte data extracted from the asset instance.
125
+ /// @return params A `Array4Params` struct containing the decoded 4-byte data.
130
126
  function asArray4(
131
127
  AssetInstance memory assetInstance
132
- ) internal pure returns (bytes4 data) {
133
- if (assetInstance.iType != AssetInstanceType.Array4) {
134
- revert InvalidAssetInstanceType(uint8(assetInstance.iType));
135
- }
136
- return Bytes4.decode(assetInstance.payload);
128
+ ) internal pure returns (Array4Params memory params) {
129
+ _assertVariant(assetInstance, AssetInstanceVariant.Array4);
130
+ params.data = Bytes4.decode(assetInstance.payload);
137
131
  }
138
132
 
139
133
  /// @notice Extracts the 8-byte data from an `Array8` asset instance. Reverts if the asset instance is not of type `Array8`.
140
134
  /// @param assetInstance The `AssetInstance` struct to decode, which must have type `Array8`.
141
- /// @return data The 8-byte data extracted from the asset instance.
135
+ /// @return params A `Array8Params` struct containing the decoded 8-byte data.
142
136
  function asArray8(
143
137
  AssetInstance memory assetInstance
144
- ) internal pure returns (bytes8 data) {
145
- if (assetInstance.iType != AssetInstanceType.Array8) {
146
- revert InvalidAssetInstanceType(uint8(assetInstance.iType));
147
- }
148
- return Bytes8.decode(assetInstance.payload);
138
+ ) internal pure returns (Array8Params memory params) {
139
+ _assertVariant(assetInstance, AssetInstanceVariant.Array8);
140
+ params.data = Bytes8.decode(assetInstance.payload);
149
141
  }
150
142
 
151
143
  /// @notice Extracts the 16-byte data from an `Array16` asset instance. Reverts if the asset instance is not of type `Array16`.
152
144
  /// @param assetInstance The `AssetInstance` struct to decode, which must have type `Array16`.
153
- /// @return data The 16-byte data extracted from the asset instance.
145
+ /// @return params A `Array16Params` struct containing the decoded 16-byte data.
154
146
  function asArray16(
155
147
  AssetInstance memory assetInstance
156
- ) internal pure returns (bytes16 data) {
157
- if (assetInstance.iType != AssetInstanceType.Array16) {
158
- revert InvalidAssetInstanceType(uint8(assetInstance.iType));
159
- }
160
- return Bytes16.decode(assetInstance.payload);
148
+ ) internal pure returns (Array16Params memory params) {
149
+ _assertVariant(assetInstance, AssetInstanceVariant.Array16);
150
+ params.data = Bytes16.decode(assetInstance.payload);
161
151
  }
162
152
 
163
153
  /// @notice Extracts the 32-byte data from an `Array32` asset instance. Reverts if the asset instance is not of type `Array32`.
164
154
  /// @param assetInstance The `AssetInstance` struct to decode, which must have type `Array32`.
165
- /// @return data The 32-byte data extracted from the asset instance.
155
+ /// @return params A `Array32Params` struct containing the decoded 32-byte data.
166
156
  function asArray32(
167
157
  AssetInstance memory assetInstance
168
- ) internal pure returns (bytes32 data) {
169
- if (assetInstance.iType != AssetInstanceType.Array32) {
170
- revert InvalidAssetInstanceType(uint8(assetInstance.iType));
158
+ ) internal pure returns (Array32Params memory params) {
159
+ _assertVariant(assetInstance, AssetInstanceVariant.Array32);
160
+ params.data = Bytes32.decode(assetInstance.payload);
161
+ }
162
+
163
+ function _assertVariant(
164
+ AssetInstance memory assetInstance,
165
+ AssetInstanceVariant expected
166
+ ) private pure {
167
+ if (assetInstance.variant != expected) {
168
+ revert InvalidAssetInstanceVariant(uint8(assetInstance.variant));
171
169
  }
172
- return Bytes32.decode(assetInstance.payload);
173
170
  }
174
171
  }
@@ -5,7 +5,7 @@ import {AssetFilter} from "../AssetFilter/AssetFilter.sol";
5
5
  import {AssetFilterCodec} from "../AssetFilter/AssetFilterCodec.sol";
6
6
 
7
7
  /// @notice Discriminant for the `AssetTransferFilter` enum.
8
- enum AssetTransferFilterType {
8
+ enum AssetTransferFilterVariant {
9
9
  /// @custom:variant Teleport assets matching `AssetFilter` to a specific destination.
10
10
  Teleport,
11
11
  /// @custom:variant Reserve-transfer assets matching `AssetFilter` to a specific destination, using the local chain as reserve.
@@ -16,8 +16,8 @@ enum AssetTransferFilterType {
16
16
 
17
17
  /// @notice Matches assets based on inner `AssetFilter` and tags them for a specific type of asset transfer.
18
18
  struct AssetTransferFilter {
19
- /// @custom:property The type of asset transfer. See `AssetTransferFilterType` enum for possible values.
20
- AssetTransferFilterType atfType;
19
+ /// @custom:property The type of asset transfer. See `AssetTransferFilterVariant` enum for possible values.
20
+ AssetTransferFilterVariant variant;
21
21
  /// @custom:property The SCALE-encoded `AssetFilter` payload.
22
22
  bytes payload;
23
23
  }
@@ -25,19 +25,19 @@ struct AssetTransferFilter {
25
25
  /// @notice Parameters for the `Teleport` variant.
26
26
  struct TeleportParams {
27
27
  /// @custom:property Asset filter used for teleport transfer.
28
- AssetFilter filter;
28
+ AssetFilter assetFilter;
29
29
  }
30
30
 
31
31
  /// @notice Parameters for the `ReserveDeposit` variant.
32
32
  struct ReserveDepositParams {
33
33
  /// @custom:property Asset filter used for reserve-deposit transfer.
34
- AssetFilter filter;
34
+ AssetFilter assetFilter;
35
35
  }
36
36
 
37
37
  /// @notice Parameters for the `ReserveWithdraw` variant.
38
38
  struct ReserveWithdrawParams {
39
39
  /// @custom:property Asset filter used for reserve-withdraw transfer.
40
- AssetFilter filter;
40
+ AssetFilter assetFilter;
41
41
  }
42
42
 
43
43
  // ============ Factory Functions ============
@@ -50,8 +50,8 @@ function teleport(
50
50
  ) pure returns (AssetTransferFilter memory) {
51
51
  return
52
52
  AssetTransferFilter({
53
- atfType: AssetTransferFilterType.Teleport,
54
- payload: AssetFilterCodec.encode(params.filter)
53
+ variant: AssetTransferFilterVariant.Teleport,
54
+ payload: AssetFilterCodec.encode(params.assetFilter)
55
55
  });
56
56
  }
57
57
 
@@ -63,8 +63,8 @@ function reserveDeposit(
63
63
  ) pure returns (AssetTransferFilter memory) {
64
64
  return
65
65
  AssetTransferFilter({
66
- atfType: AssetTransferFilterType.ReserveDeposit,
67
- payload: AssetFilterCodec.encode(params.filter)
66
+ variant: AssetTransferFilterVariant.ReserveDeposit,
67
+ payload: AssetFilterCodec.encode(params.assetFilter)
68
68
  });
69
69
  }
70
70
 
@@ -76,7 +76,7 @@ function reserveWithdraw(
76
76
  ) pure returns (AssetTransferFilter memory) {
77
77
  return
78
78
  AssetTransferFilter({
79
- atfType: AssetTransferFilterType.ReserveWithdraw,
80
- payload: AssetFilterCodec.encode(params.filter)
79
+ variant: AssetTransferFilterVariant.ReserveWithdraw,
80
+ payload: AssetFilterCodec.encode(params.assetFilter)
81
81
  });
82
82
  }
@@ -5,8 +5,12 @@ import {AssetFilter} from "../AssetFilter/AssetFilter.sol";
5
5
  import {AssetFilterCodec} from "../AssetFilter/AssetFilterCodec.sol";
6
6
  import {
7
7
  AssetTransferFilter,
8
- AssetTransferFilterType
8
+ AssetTransferFilterVariant,
9
+ TeleportParams,
10
+ ReserveDepositParams,
11
+ ReserveWithdrawParams
9
12
  } from "./AssetTransferFilter.sol";
13
+ import {BytesUtils} from "../../../Utils/BytesUtils.sol";
10
14
 
11
15
  /// @title SCALE Codec for XCM v5 `AssetTransferFilter`
12
16
  /// @notice SCALE-compliant encoder/decoder for the `AssetTransferFilter` type.
@@ -14,7 +18,7 @@ import {
14
18
  /// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.AssetTransferFilter.html
15
19
  library AssetTransferFilterCodec {
16
20
  error InvalidAssetTransferFilterLength();
17
- error InvalidAssetTransferFilterType(uint8 atfType);
21
+ error InvalidAssetTransferFilterVariant(uint8 variant);
18
22
 
19
23
  /// @notice Encodes an `AssetTransferFilter` struct into SCALE bytes.
20
24
  /// @param atf The `AssetTransferFilter` struct to encode.
@@ -22,7 +26,7 @@ library AssetTransferFilterCodec {
22
26
  function encode(
23
27
  AssetTransferFilter memory atf
24
28
  ) internal pure returns (bytes memory) {
25
- return abi.encodePacked(uint8(atf.atfType), atf.payload);
29
+ return abi.encodePacked(uint8(atf.variant), atf.payload);
26
30
  }
27
31
 
28
32
  /// @notice Returns the number of bytes that an `AssetTransferFilter` would occupy when SCALE-encoded.
@@ -34,9 +38,9 @@ library AssetTransferFilterCodec {
34
38
  uint256 offset
35
39
  ) internal pure returns (uint256) {
36
40
  if (data.length < offset + 1) revert InvalidAssetTransferFilterLength();
37
- uint8 atfType = uint8(data[offset]);
38
- if (atfType > uint8(AssetTransferFilterType.ReserveWithdraw))
39
- revert InvalidAssetTransferFilterType(atfType);
41
+ uint8 variant = uint8(data[offset]);
42
+ if (variant > uint8(AssetTransferFilterVariant.ReserveWithdraw))
43
+ revert InvalidAssetTransferFilterVariant(variant);
40
44
  return 1 + AssetFilterCodec.encodedSizeAt(data, offset + 1);
41
45
  }
42
46
 
@@ -67,29 +71,53 @@ library AssetTransferFilterCodec {
67
71
  pure
68
72
  returns (AssetTransferFilter memory atf, uint256 bytesRead)
69
73
  {
70
- if (data.length < offset + 1) revert InvalidAssetTransferFilterLength();
71
- uint8 atfType = uint8(data[offset]);
72
- if (atfType > uint8(AssetTransferFilterType.ReserveWithdraw))
73
- revert InvalidAssetTransferFilterType(atfType);
74
74
  uint256 size = encodedSizeAt(data, offset);
75
+ uint8 variant = uint8(data[offset]);
75
76
  uint256 payloadLength = size - 1;
76
- bytes memory payload = new bytes(payloadLength);
77
- for (uint256 i = 0; i < payloadLength; ++i) {
78
- payload[i] = data[offset + 1 + i];
79
- }
77
+ bytes memory payload = BytesUtils.copy(data, offset + 1, payloadLength);
80
78
  atf = AssetTransferFilter({
81
- atfType: AssetTransferFilterType(atfType),
79
+ variant: AssetTransferFilterVariant(variant),
82
80
  payload: payload
83
81
  });
84
82
  bytesRead = size;
85
83
  }
86
84
 
87
- /// @notice Extracts the inner `AssetFilter` from an `AssetTransferFilter`.
85
+ /// @notice Extracts the inner `AssetFilter` from an `AssetTransferFilter` with `Teleport` variant
88
86
  /// @param atf The `AssetTransferFilter` struct to decode.
89
- /// @return The inner `AssetFilter`.
90
- function asInner(
87
+ /// @return params A `TeleportParams` struct containing the inner `AssetFilter`.
88
+ function asTeleport(
91
89
  AssetTransferFilter memory atf
92
- ) internal pure returns (AssetFilter memory) {
93
- return AssetFilterCodec.decode(atf.payload);
90
+ ) internal pure returns (TeleportParams memory params) {
91
+ _assertVariant(atf, AssetTransferFilterVariant.Teleport);
92
+ (params.assetFilter, ) = AssetFilterCodec.decode(atf.payload);
93
+ }
94
+
95
+ /// @notice Extracts the inner `AssetFilter` from an `AssetTransferFilter` with `ReserveDeposit` variant
96
+ /// @param atf The `AssetTransferFilter` struct to decode.
97
+ /// @return params A `ReserveDepositParams` struct containing the inner `AssetFilter`.
98
+ function asReserveDeposit(
99
+ AssetTransferFilter memory atf
100
+ ) internal pure returns (ReserveDepositParams memory params) {
101
+ _assertVariant(atf, AssetTransferFilterVariant.ReserveDeposit);
102
+ (params.assetFilter, ) = AssetFilterCodec.decode(atf.payload);
103
+ }
104
+
105
+ /// @notice Extracts the inner `AssetFilter` from an `AssetTransferFilter` with `ReserveWithdraw` variant
106
+ /// @param atf The `AssetTransferFilter` struct to decode.
107
+ /// @return params A `ReserveWithdrawParams` struct containing the inner `AssetFilter`.
108
+ function asReserveWithdraw(
109
+ AssetTransferFilter memory atf
110
+ ) internal pure returns (ReserveWithdrawParams memory params) {
111
+ _assertVariant(atf, AssetTransferFilterVariant.ReserveWithdraw);
112
+ (params.assetFilter, ) = AssetFilterCodec.decode(atf.payload);
113
+ }
114
+
115
+ function _assertVariant(
116
+ AssetTransferFilter memory atf,
117
+ AssetTransferFilterVariant expected
118
+ ) internal pure {
119
+ if (atf.variant != expected) {
120
+ revert InvalidAssetTransferFilterVariant(uint8(atf.variant));
121
+ }
94
122
  }
95
123
  }
@@ -12,3 +12,19 @@ struct Assets {
12
12
  /// @custom:property The items of the array.
13
13
  Asset[] items;
14
14
  }
15
+
16
+ /// @notice Creates an `Assets` wrapper from a single `Asset`.
17
+ /// @param asset The asset to include.
18
+ /// @return An `Assets` struct containing one item.
19
+ function fromAsset(Asset memory asset) pure returns (Assets memory) {
20
+ Asset[] memory items = new Asset[](1);
21
+ items[0] = asset;
22
+ return Assets({items: items});
23
+ }
24
+
25
+ /// @notice Creates an `Assets` wrapper from an asset array.
26
+ /// @param assets The assets to include.
27
+ /// @return An `Assets` struct containing `assets`.
28
+ function fromAssets(Asset[] memory assets) pure returns (Assets memory) {
29
+ return Assets({items: assets});
30
+ }
@@ -41,6 +41,9 @@ library AssetsCodec {
41
41
  revert InvalidAssetsLength();
42
42
  }
43
43
  (uint256 length, uint256 bytesRead) = Compact.decodeAt(data, offset);
44
+ if (length > MAX_ITEMS_IN_ASSETS) {
45
+ revert InvalidAssetsPayload();
46
+ }
44
47
  uint256 currentOffset = offset + bytesRead;
45
48
  for (uint256 i = 0; i < length; i++) {
46
49
  uint256 assetSize = AssetCodec.encodedSizeAt(data, currentOffset);
@@ -68,9 +71,6 @@ library AssetsCodec {
68
71
  bytes memory data,
69
72
  uint256 offset
70
73
  ) internal pure returns (Assets memory assets, uint256 bytesRead) {
71
- if (data.length < offset + 1) {
72
- revert InvalidAssetsLength();
73
- }
74
74
  (uint256 length, uint256 compactBytesRead) = Compact.decodeAt(
75
75
  data,
76
76
  offset
@@ -5,7 +5,7 @@ import {Bytes4} from "../../../Scale/Bytes.sol";
5
5
  import {Compact} from "../../../Scale/Compact.sol";
6
6
 
7
7
  /// @dev Discriminant for the different types of BodyIds in XCM v5. Each variant corresponds to a specific structure of the payload.
8
- enum BodyIdType {
8
+ enum BodyIdVariant {
9
9
  /// @custom:variant The only body in its context.
10
10
  Unit,
11
11
  /// @custom:variant A named body.
@@ -31,7 +31,7 @@ enum BodyIdType {
31
31
  /// @notice An identifier of a pluralistic body.
32
32
  struct BodyId {
33
33
  /// @custom:property The type of BodyId, which determines how to interpret the payload
34
- BodyIdType bodyIdType;
34
+ BodyIdVariant variant;
35
35
  /// @custom:property For Moniker and Index types, this will hold the relevant data
36
36
  bytes payload;
37
37
  }
@@ -45,77 +45,77 @@ struct MonikerParams {
45
45
  /// @notice Parameters for the `Index` variant.
46
46
  struct IndexParams {
47
47
  /// @custom:property The index of the body.
48
- uint32 idx;
48
+ uint32 index;
49
49
  }
50
50
 
51
51
  // ============ Factory Functions ============
52
52
 
53
53
  /// @notice Creates a `BodyId` representing a `Unit` body.
54
- /// @return A `BodyId` with `bodyIdType` set to `Unit` and an empty payload.
54
+ /// @return A `BodyId` with `variant` set to `Unit` and an empty payload.
55
55
  function unit() pure returns (BodyId memory) {
56
- return BodyId({bodyIdType: BodyIdType.Unit, payload: ""});
56
+ return BodyId({variant: BodyIdVariant.Unit, payload: ""});
57
57
  }
58
58
 
59
59
  /// @notice Creates a `BodyId` representing a `Moniker` body with the given 4-byte name.
60
60
  /// @param params Parameters for the moniker variant.
61
- /// @return A `BodyId` with `bodyIdType` set to `Moniker` and the provided name encoded in the payload.
61
+ /// @return A `BodyId` with `variant` set to `Moniker` and the provided name encoded in the payload.
62
62
  function moniker(MonikerParams memory params) pure returns (BodyId memory) {
63
63
  return
64
64
  BodyId({
65
- bodyIdType: BodyIdType.Moniker,
65
+ variant: BodyIdVariant.Moniker,
66
66
  payload: Bytes4.encode(params.name)
67
67
  });
68
68
  }
69
69
 
70
70
  /// @notice Creates a `BodyId` representing an `Index` body with the given index.
71
71
  /// @param params Parameters for the index variant.
72
- /// @return A `BodyId` with `bodyIdType` set to `Index` and the provided index encoded in the payload.
72
+ /// @return A `BodyId` with `variant` set to `Index` and the provided index encoded in the payload.
73
73
  function index(IndexParams memory params) pure returns (BodyId memory) {
74
74
  return
75
75
  BodyId({
76
- bodyIdType: BodyIdType.Index,
77
- payload: Compact.encode(params.idx)
76
+ variant: BodyIdVariant.Index,
77
+ payload: Compact.encode(params.index)
78
78
  });
79
79
  }
80
80
 
81
81
  /// @notice Creates a `BodyId` representing an `Executive` body.
82
- /// @return A `BodyId` with `bodyIdType` set to `Executive` and an empty payload.
82
+ /// @return A `BodyId` with `variant` set to `Executive` and an empty payload.
83
83
  function executive() pure returns (BodyId memory) {
84
- return BodyId({bodyIdType: BodyIdType.Executive, payload: ""});
84
+ return BodyId({variant: BodyIdVariant.Executive, payload: ""});
85
85
  }
86
86
 
87
87
  /// @notice Creates a `BodyId` representing a `Technical` body.
88
- /// @return A `BodyId` with `bodyIdType` set to `Technical` and an empty payload.
88
+ /// @return A `BodyId` with `variant` set to `Technical` and an empty payload.
89
89
  function technical() pure returns (BodyId memory) {
90
- return BodyId({bodyIdType: BodyIdType.Technical, payload: ""});
90
+ return BodyId({variant: BodyIdVariant.Technical, payload: ""});
91
91
  }
92
92
 
93
93
  /// @notice Creates a `BodyId` representing a `Legislative` body.
94
- /// @return A `BodyId` with `bodyIdType` set to `Legislative` and an empty payload.
94
+ /// @return A `BodyId` with `variant` set to `Legislative` and an empty payload.
95
95
  function legislative() pure returns (BodyId memory) {
96
- return BodyId({bodyIdType: BodyIdType.Legislative, payload: ""});
96
+ return BodyId({variant: BodyIdVariant.Legislative, payload: ""});
97
97
  }
98
98
 
99
99
  /// @notice Creates a `BodyId` representing a `Judicial` body.
100
- /// @return A `BodyId` with `bodyIdType` set to `Judicial` and an empty payload.
100
+ /// @return A `BodyId` with `variant` set to `Judicial` and an empty payload.
101
101
  function judicial() pure returns (BodyId memory) {
102
- return BodyId({bodyIdType: BodyIdType.Judicial, payload: ""});
102
+ return BodyId({variant: BodyIdVariant.Judicial, payload: ""});
103
103
  }
104
104
 
105
105
  /// @notice Creates a `BodyId` representing a `Defense` body.
106
- /// @return A `BodyId` with `bodyIdType` set to `Defense` and an empty payload.
106
+ /// @return A `BodyId` with `variant` set to `Defense` and an empty payload.
107
107
  function defense() pure returns (BodyId memory) {
108
- return BodyId({bodyIdType: BodyIdType.Defense, payload: ""});
108
+ return BodyId({variant: BodyIdVariant.Defense, payload: ""});
109
109
  }
110
110
 
111
111
  /// @notice Creates a `BodyId` representing an `Administration` body.
112
- /// @return A `BodyId` with `bodyIdType` set to `Administration` and an empty payload.
112
+ /// @return A `BodyId` with `variant` set to `Administration` and an empty payload.
113
113
  function administration() pure returns (BodyId memory) {
114
- return BodyId({bodyIdType: BodyIdType.Administration, payload: ""});
114
+ return BodyId({variant: BodyIdVariant.Administration, payload: ""});
115
115
  }
116
116
 
117
117
  /// @notice Creates a `BodyId` representing a `Treasury` body.
118
- /// @return A `BodyId` with `bodyIdType` set to `Treasury` and an empty payload.
118
+ /// @return A `BodyId` with `variant` set to `Treasury` and an empty payload.
119
119
  function treasury() pure returns (BodyId memory) {
120
- return BodyId({bodyIdType: BodyIdType.Treasury, payload: ""});
120
+ return BodyId({variant: BodyIdVariant.Treasury, payload: ""});
121
121
  }