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.
- package/CHANGELOG.md +36 -2
- package/README.md +1 -1
- package/package.json +2 -2
- package/src/Utils/BytesUtils.sol +26 -0
- package/src/Utils/UnsignedUtils.sol +52 -0
- package/src/Xcm/VersionedXcm/VersionedXcm.sol +4 -1
- package/src/Xcm/VersionedXcm/VersionedXcmCodec.sol +11 -0
- package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCode.sol +8 -7
- package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCodeCodec.sol +18 -19
- package/src/Xcm/v5/AssetFilter/AssetFilter.sol +8 -8
- package/src/Xcm/v5/AssetFilter/AssetFilterCodec.sol +47 -34
- package/src/Xcm/v5/AssetInstance/AssetInstance.sol +13 -12
- package/src/Xcm/v5/AssetInstance/AssetInstanceCodec.sol +53 -56
- package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilter.sol +12 -12
- package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilterCodec.sol +48 -20
- package/src/Xcm/v5/Assets/Assets.sol +16 -0
- package/src/Xcm/v5/Assets/AssetsCodec.sol +3 -3
- package/src/Xcm/v5/BodyId/BodyId.sol +24 -24
- package/src/Xcm/v5/BodyId/BodyIdCodec.sol +41 -48
- package/src/Xcm/v5/BodyPart/BodyPart.sol +44 -28
- package/src/Xcm/v5/BodyPart/BodyPartCodec.sol +70 -37
- package/src/Xcm/v5/Constants.sol +2 -2
- package/src/Xcm/v5/Fungibility/Fungibility.sol +6 -6
- package/src/Xcm/v5/Fungibility/FungibilityCodec.sol +40 -36
- package/src/Xcm/v5/Hint/Hint.sol +5 -5
- package/src/Xcm/v5/Hint/HintCodec.sol +24 -20
- package/src/Xcm/v5/Instruction/Instruction.sol +81 -55
- package/src/Xcm/v5/Instruction/InstructionCodec.sol +1047 -73
- package/src/Xcm/v5/Junction/Junction.sol +55 -69
- package/src/Xcm/v5/Junction/JunctionCodec.sol +72 -135
- package/src/Xcm/v5/Junctions/Junctions.sol +34 -0
- package/src/Xcm/v5/Junctions/JunctionsCodec.sol +0 -18
- package/src/Xcm/v5/Location/Location.sol +8 -0
- package/src/Xcm/v5/NetworkId/NetworkId.sol +15 -16
- package/src/Xcm/v5/NetworkId/NetworkIdCodec.sol +57 -34
- package/src/Xcm/v5/OriginKind/OriginKindCodec.sol +1 -1
- package/src/Xcm/v5/Response/Response.sol +49 -40
- package/src/Xcm/v5/Response/ResponseCodec.sol +64 -54
- package/src/Xcm/v5/Weight/WeightCodec.sol +3 -2
- package/src/Xcm/v5/WeightLimit/WeightLimit.sol +6 -6
- package/src/Xcm/v5/WeightLimit/WeightLimitCodec.sol +32 -23
- package/src/Xcm/v5/WildAsset/WildAsset.sol +17 -25
- package/src/Xcm/v5/WildAsset/WildAssetCodec.sol +35 -38
- package/src/Xcm/v5/WildFungibility/WildFungibilityCodec.sol +6 -6
- package/src/Xcm/v5/Xcm/XcmBuilder.sol +689 -0
- package/src/Xcm/v5/XcmError/XcmError.sol +7 -7
- package/src/Xcm/v5/XcmError/XcmErrorCodec.sol +25 -22
- package/DEFINITIONS.md +0 -132
package/CHANGELOG.md
CHANGED
|
@@ -7,15 +7,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
[Unreleased]
|
|
9
9
|
|
|
10
|
+
## Version 1.0.0
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `BytesUtils.sol`, a new utility library for byte manipulation, including functions for copying byte arrays. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
15
|
+
- `UnsignedUtils.sol`, a new utility library for safely converting `uint256` values to smaller unsigned integer types (`uint8`, `uint16`, `uint32`, `uint64`, `uint128`) with overflow checks. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
16
|
+
- `XcmBuilder.sol`, a new utility library for constructing XCM messages in a more ergonomic way, with functions for building various XCM instructions. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
17
|
+
- Added `parent()` helper function in `Location.sol` to create a `Location` struct representing the parent location (one level up in the hierarchy). - [#93618bf](https://github.com/LucasGrasso/solidity-scale-codec/commit/93618bf)
|
|
18
|
+
- Added `fromAsset(Asset)` and `fromAssets(Asset[])` helper functions in `Assets.sol` to construct `Assets` values ergonomically from a single asset or an array. - [#dd79e86](https://github.com/LucasGrasso/solidity-scale-codec/commit/dd79e86)
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- For every enum equivalent, rename `Type` suffix to `Variant` for better clarity and consistency. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
23
|
+
- Type Checking with `UnsignedUtils` in all codecs to ensure safe downcasting of `uint256` to smaller unsigned integer types, preventing potential overflow issues and improving robustness. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
24
|
+
- DRY with `BytesUtils.copy` in all codecs to replace manual byte copying loops, improving code readability, maintainability, and gas efficiency. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
25
|
+
- Removed unnecessary length checks at the beginning of decoding functions since `encodedSizeAt` and `BytesUtils.copy` will handle those checks and revert if data is insufficient, simplifying the code and centralizing error handling. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
26
|
+
- Moved helper `Junction` functions to outside of the codec. - [#b91bdfa](https://github.com/LucasGrasso/solidity-scale-codec/commit/b91bdfa24472fe931ee5dd6625ae2b4796d23248)
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Inconsistencies in Xcm Codec libraries:
|
|
31
|
+
- `decode`, `decodeAt` functions not returning `bytesRead` in some codecs. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
32
|
+
- Now returning `{Variant}Params` structs in `as{Variant}` decoding functions for consistency and better ergonomics. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
33
|
+
- Inconsistencies in Xcm Instruction factory functions:
|
|
34
|
+
- Some factory functions were taking individual parameters instead of `{Variant}Params` structs, leading to less consistent and ergonomic API. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
35
|
+
- Now checking Variant bounds when calling `decodeAt` at all enum equivalents. - [#3](https://github.com/LucasGrasso/solidity-scale-codec/pull/3)
|
|
36
|
+
- Optional encoding in `Junction` factory functions was not correctly implemented, leading to incorrect encoding when `hasNetwork` was false. - [#93618bf](https://github.com/LucasGrasso/solidity-scale-codec/commit/93618bf)
|
|
37
|
+
|
|
38
|
+
## Version 0.3.4
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- Move Definitions to website docs - [#f57c914](https://github.com/LucasGrasso/solidity-scale-codec/commit/7e88534930cdb8ac47b5f16a02f2203c588a7e7f)
|
|
43
|
+
|
|
10
44
|
## Version 0.3.3
|
|
11
45
|
|
|
12
|
-
|
|
46
|
+
### Changed
|
|
13
47
|
|
|
14
48
|
- Homepage for the docsite - [#fcbac35](https://github.com/LucasGrasso/solidity-scale-codec/commit/757cddcce6d9f7a82f9535471c86f0cffa878956)
|
|
15
49
|
|
|
16
50
|
## Version 0.3.2
|
|
17
51
|
|
|
18
|
-
|
|
52
|
+
### Changed
|
|
19
53
|
|
|
20
54
|
- Better Changelog - [#288b3e9](https://github.com/LucasGrasso/solidity-scale-codec/commit/288b3e966ff1d030b7e50dcc40d0610cd30b201c)
|
|
21
55
|
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ This library provides a Highly-Modular implementation of SCALE in solidity.
|
|
|
22
22
|
| `Compact` | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2\*\*536) and is more efficient at encoding most values than the fixed-width version. (Though for single-byte values, the fixed-width integer is never worse.) | `0` | `0x00` |
|
|
23
23
|
| `Arrays` | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. Currently `[uintN]`,`[intN]`, `[bool]` are supported. | `[1,0]` | `0x080100` |
|
|
24
24
|
|
|
25
|
-
See the [Definitions](
|
|
25
|
+
See the [Definitions](https://lucasgrasso.github.io/solidity-scale-codec/Definitions.html) for more details on the encoding of different types.
|
|
26
26
|
|
|
27
27
|
## Usage
|
|
28
28
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solidity-scale-codec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Solidity implementation of scale-codec.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"solidity",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"hardhat": "^3.0.15",
|
|
48
48
|
"prettier": "^3.8.1",
|
|
49
49
|
"prettier-plugin-solidity": "^2.2.1",
|
|
50
|
-
"solidity-doc-generator": "^1.
|
|
50
|
+
"solidity-doc-generator": "^1.2.1",
|
|
51
51
|
"typescript": "~5.8.0",
|
|
52
52
|
"viem": "^2.40.3",
|
|
53
53
|
"vitepress": "^1.6.4",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
/// @notice Utility functions for working with byte arrays, such as copying segments of bytes.
|
|
5
|
+
library BytesUtils {
|
|
6
|
+
error InvalidBounds();
|
|
7
|
+
|
|
8
|
+
/// @notice Copies a segment of bytes from a source byte array.
|
|
9
|
+
/// @param src The source byte array from which to copy.
|
|
10
|
+
/// @param from The starting index in the source array from which to begin copying.
|
|
11
|
+
/// @param count The number of bytes to copy from the source array.
|
|
12
|
+
function copy(
|
|
13
|
+
bytes memory src,
|
|
14
|
+
uint256 from,
|
|
15
|
+
uint256 count
|
|
16
|
+
) internal pure returns (bytes memory) {
|
|
17
|
+
if (src.length < from + count) {
|
|
18
|
+
revert InvalidBounds();
|
|
19
|
+
}
|
|
20
|
+
bytes memory result = new bytes(count);
|
|
21
|
+
for (uint256 i = 0; i < count; i++) {
|
|
22
|
+
result[i] = src[from + i];
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
/// @notice Utility functions for safely downcasting `uint256` values to smaller unsigned integer types.
|
|
5
|
+
library UnsignedUtils {
|
|
6
|
+
error NumberTooLarge(uint256 value, uint256 max);
|
|
7
|
+
|
|
8
|
+
function toU8(uint256 value) internal pure returns (uint8) {
|
|
9
|
+
if (value > type(uint8).max) {
|
|
10
|
+
revert NumberTooLarge(value, type(uint8).max);
|
|
11
|
+
}
|
|
12
|
+
unchecked {
|
|
13
|
+
return uint8(value);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function toU16(uint256 value) internal pure returns (uint16) {
|
|
18
|
+
if (value > type(uint16).max) {
|
|
19
|
+
revert NumberTooLarge(value, type(uint16).max);
|
|
20
|
+
}
|
|
21
|
+
unchecked {
|
|
22
|
+
return uint16(value);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function toU32(uint256 value) internal pure returns (uint32) {
|
|
27
|
+
if (value > type(uint32).max) {
|
|
28
|
+
revert NumberTooLarge(value, type(uint32).max);
|
|
29
|
+
}
|
|
30
|
+
unchecked {
|
|
31
|
+
return uint32(value);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function toU64(uint256 value) internal pure returns (uint64) {
|
|
36
|
+
if (value > type(uint64).max) {
|
|
37
|
+
revert NumberTooLarge(value, type(uint64).max);
|
|
38
|
+
}
|
|
39
|
+
unchecked {
|
|
40
|
+
return uint64(value);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function toU128(uint256 value) internal pure returns (uint128) {
|
|
45
|
+
if (value > type(uint128).max) {
|
|
46
|
+
revert NumberTooLarge(value, type(uint128).max);
|
|
47
|
+
}
|
|
48
|
+
unchecked {
|
|
49
|
+
return uint128(value);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -6,8 +6,11 @@ import {XcmCodec as XcmV5Codec} from "../v5/Xcm/XcmCodec.sol";
|
|
|
6
6
|
|
|
7
7
|
/// @notice The XCM versions supported by this package.
|
|
8
8
|
enum XcmVersion {
|
|
9
|
-
|
|
9
|
+
_reserved0,
|
|
10
|
+
_reserved1,
|
|
11
|
+
_reserved2,
|
|
10
12
|
_unsupported_V3,
|
|
13
|
+
_unsupported_V4,
|
|
11
14
|
V5
|
|
12
15
|
}
|
|
13
16
|
|
|
@@ -67,4 +67,15 @@ library VersionedXcmCodec {
|
|
|
67
67
|
revert UnsupportedXcmVersion(version);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
|
|
71
|
+
/// @notice Converts a `VersionedXcm` to an `XcmV5` struct, if it is of version `V5`.
|
|
72
|
+
/// @param versionedXcm The `VersionedXcm` to convert.
|
|
73
|
+
/// @return xcm The decoded `XcmV5` struct contained in the `VersionedXcm`.
|
|
74
|
+
function asV5(
|
|
75
|
+
VersionedXcm memory versionedXcm
|
|
76
|
+
) internal pure returns (XcmV5 memory xcm) {
|
|
77
|
+
if (versionedXcm.version != XcmVersion.V5)
|
|
78
|
+
revert UnsupportedXcmVersion(versionedXcm.version);
|
|
79
|
+
(xcm, ) = XcmV5Codec.decode(versionedXcm.xcm);
|
|
80
|
+
}
|
|
70
81
|
}
|
|
@@ -5,7 +5,7 @@ import {U8Arr} from "../../../Scale/Array.sol";
|
|
|
5
5
|
import {MAX_DISPATCH_ERROR_LEN} from "../Constants.sol";
|
|
6
6
|
|
|
7
7
|
/// @notice Discriminant for the `MaybeErrorCode` enum.
|
|
8
|
-
enum
|
|
8
|
+
enum MaybeErrorCodeVariant {
|
|
9
9
|
/// @custom:variant No error occurred.
|
|
10
10
|
Success,
|
|
11
11
|
/// @custom:variant An error occurred, containing the dispatch error bytes.
|
|
@@ -16,9 +16,9 @@ enum MaybeErrorCodeType {
|
|
|
16
16
|
|
|
17
17
|
/// @notice The result of a `Transact` dispatch, either success or an error code.
|
|
18
18
|
struct MaybeErrorCode {
|
|
19
|
-
/// @custom:property The type of the result. See `
|
|
20
|
-
|
|
21
|
-
/// @custom:property The SCALE-encoded dispatch error bytes. Only meaningful when `
|
|
19
|
+
/// @custom:property The type of the result. See `MaybeErrorCodeVariant` enum for possible values.
|
|
20
|
+
MaybeErrorCodeVariant variant;
|
|
21
|
+
/// @custom:property The SCALE-encoded dispatch error bytes. Only meaningful when `variant` is `Error` or `TruncatedError`. Max length is MAX_DISPATCH_ERROR_LEN (128 bytes).
|
|
22
22
|
bytes payload;
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -39,7 +39,8 @@ struct TruncatedErrorParams {
|
|
|
39
39
|
/// @notice Creates a `Success` MaybeErrorCode.
|
|
40
40
|
/// @return A `MaybeErrorCode` struct representing success.
|
|
41
41
|
function success() pure returns (MaybeErrorCode memory) {
|
|
42
|
-
return
|
|
42
|
+
return
|
|
43
|
+
MaybeErrorCode({variant: MaybeErrorCodeVariant.Success, payload: ""});
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
/// @notice Creates an `Error` MaybeErrorCode with the given dispatch error bytes.
|
|
@@ -50,7 +51,7 @@ function error(ErrorParams memory params) pure returns (MaybeErrorCode memory) {
|
|
|
50
51
|
revert MaybeErrorCodeTooLong(params.errorBytes.length);
|
|
51
52
|
return
|
|
52
53
|
MaybeErrorCode({
|
|
53
|
-
|
|
54
|
+
variant: MaybeErrorCodeVariant.Error,
|
|
54
55
|
payload: U8Arr.encode(params.errorBytes)
|
|
55
56
|
});
|
|
56
57
|
}
|
|
@@ -65,7 +66,7 @@ function truncatedError(
|
|
|
65
66
|
revert MaybeErrorCodeTooLong(params.errorBytes.length);
|
|
66
67
|
return
|
|
67
68
|
MaybeErrorCode({
|
|
68
|
-
|
|
69
|
+
variant: MaybeErrorCodeVariant.TruncatedError,
|
|
69
70
|
payload: U8Arr.encode(params.errorBytes)
|
|
70
71
|
});
|
|
71
72
|
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
pragma solidity ^0.8.28;
|
|
3
3
|
|
|
4
4
|
import {U8Arr} from "../../../Scale/Array.sol";
|
|
5
|
-
import {MaybeErrorCode,
|
|
5
|
+
import {MaybeErrorCode, MaybeErrorCodeVariant} from "./MaybeErrorCode.sol";
|
|
6
|
+
import {BytesUtils} from "../../../Utils/BytesUtils.sol";
|
|
6
7
|
|
|
7
8
|
/// @title SCALE Codec for XCM v3 `MaybeErrorCode`
|
|
8
9
|
/// @notice SCALE-compliant encoder/decoder for the `MaybeErrorCode` type.
|
|
@@ -10,7 +11,7 @@ import {MaybeErrorCode, MaybeErrorCodeType} from "./MaybeErrorCode.sol";
|
|
|
10
11
|
/// @dev XCM v3 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v3/index.html
|
|
11
12
|
library MaybeErrorCodeCodec {
|
|
12
13
|
error InvalidMaybeErrorCodeLength();
|
|
13
|
-
error
|
|
14
|
+
error InvalidMaybeErrorCodeVariant(uint8 variant);
|
|
14
15
|
|
|
15
16
|
/// @notice Encodes a `MaybeErrorCode` struct into SCALE bytes.
|
|
16
17
|
/// @param me The `MaybeErrorCode` struct to encode.
|
|
@@ -18,7 +19,7 @@ library MaybeErrorCodeCodec {
|
|
|
18
19
|
function encode(
|
|
19
20
|
MaybeErrorCode memory me
|
|
20
21
|
) internal pure returns (bytes memory) {
|
|
21
|
-
return abi.encodePacked(uint8(me.
|
|
22
|
+
return abi.encodePacked(uint8(me.variant), me.payload);
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
/// @notice Returns the number of bytes that a `MaybeErrorCode` would occupy when SCALE-encoded.
|
|
@@ -30,16 +31,16 @@ library MaybeErrorCodeCodec {
|
|
|
30
31
|
uint256 offset
|
|
31
32
|
) internal pure returns (uint256) {
|
|
32
33
|
if (data.length < offset + 1) revert InvalidMaybeErrorCodeLength();
|
|
33
|
-
uint8
|
|
34
|
-
if (
|
|
34
|
+
uint8 variant = uint8(data[offset]);
|
|
35
|
+
if (variant == uint8(MaybeErrorCodeVariant.Success)) {
|
|
35
36
|
return 1;
|
|
36
37
|
} else if (
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
variant == uint8(MaybeErrorCodeVariant.Error) ||
|
|
39
|
+
variant == uint8(MaybeErrorCodeVariant.TruncatedError)
|
|
39
40
|
) {
|
|
40
41
|
return 1 + U8Arr.encodedSizeAt(data, offset + 1);
|
|
41
42
|
} else {
|
|
42
|
-
revert
|
|
43
|
+
revert InvalidMaybeErrorCodeVariant(variant);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -63,17 +64,15 @@ library MaybeErrorCodeCodec {
|
|
|
63
64
|
uint256 offset
|
|
64
65
|
) internal pure returns (MaybeErrorCode memory me, uint256 bytesRead) {
|
|
65
66
|
if (data.length < offset + 1) revert InvalidMaybeErrorCodeLength();
|
|
66
|
-
uint8
|
|
67
|
-
if (
|
|
68
|
-
revert
|
|
67
|
+
uint8 variant = uint8(data[offset]);
|
|
68
|
+
if (variant > uint8(type(MaybeErrorCodeVariant).max)) {
|
|
69
|
+
revert InvalidMaybeErrorCodeVariant(variant);
|
|
70
|
+
}
|
|
69
71
|
uint256 size = encodedSizeAt(data, offset);
|
|
70
72
|
uint256 payloadLength = size - 1;
|
|
71
|
-
bytes memory payload =
|
|
72
|
-
for (uint256 i = 0; i < payloadLength; ++i) {
|
|
73
|
-
payload[i] = data[offset + 1 + i];
|
|
74
|
-
}
|
|
73
|
+
bytes memory payload = BytesUtils.copy(data, offset + 1, payloadLength);
|
|
75
74
|
me = MaybeErrorCode({
|
|
76
|
-
|
|
75
|
+
variant: MaybeErrorCodeVariant(variant),
|
|
77
76
|
payload: payload
|
|
78
77
|
});
|
|
79
78
|
bytesRead = size;
|
|
@@ -86,9 +85,9 @@ library MaybeErrorCodeCodec {
|
|
|
86
85
|
MaybeErrorCode memory me
|
|
87
86
|
) internal pure returns (uint8[] memory errorBytes) {
|
|
88
87
|
if (
|
|
89
|
-
me.
|
|
90
|
-
me.
|
|
91
|
-
) revert
|
|
88
|
+
me.variant != MaybeErrorCodeVariant.Error &&
|
|
89
|
+
me.variant != MaybeErrorCodeVariant.TruncatedError
|
|
90
|
+
) revert InvalidMaybeErrorCodeVariant(uint8(me.variant));
|
|
92
91
|
(errorBytes, ) = U8Arr.decode(me.payload);
|
|
93
92
|
}
|
|
94
93
|
}
|
|
@@ -7,7 +7,7 @@ import {WildAsset} from "../WildAsset/WildAsset.sol";
|
|
|
7
7
|
import {WildAssetCodec} from "../WildAsset/WildAssetCodec.sol";
|
|
8
8
|
|
|
9
9
|
/// @notice Discriminant for the type of asset filter being specified in an `AssetFilter`.
|
|
10
|
-
enum
|
|
10
|
+
enum AssetFilterVariant {
|
|
11
11
|
/// @custom:variant Specify the filter as being everything contained by the given `Assets` inner.
|
|
12
12
|
Definite,
|
|
13
13
|
/// @custom:variant Specify the filter as the given `WildAsset` wildcard.
|
|
@@ -16,9 +16,9 @@ enum AssetFilterType {
|
|
|
16
16
|
|
|
17
17
|
/// @notice `Asset` collection, defined either by a number of `Assets` or a single wildcard.
|
|
18
18
|
struct AssetFilter {
|
|
19
|
-
/// @custom:property The type of asset filter, determining how to interpret the payload. See `
|
|
20
|
-
|
|
21
|
-
/// @custom:property The encoded payload containing the asset filter data, whose structure depends on the `
|
|
19
|
+
/// @custom:property The type of asset filter, determining how to interpret the payload. See `AssetFilterVariant` enum for possible values.
|
|
20
|
+
AssetFilterVariant variant;
|
|
21
|
+
/// @custom:property The encoded payload containing the asset filter data, whose structure depends on the `variant`.
|
|
22
22
|
bytes payload;
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ struct DefiniteParams {
|
|
|
31
31
|
/// @notice Parameters for the `Wild` variant.
|
|
32
32
|
struct WildParams {
|
|
33
33
|
/// @custom:property The wildcard asset selector.
|
|
34
|
-
WildAsset
|
|
34
|
+
WildAsset wildAsset;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
// ============ Factory Functions ============
|
|
@@ -44,7 +44,7 @@ function definite(
|
|
|
44
44
|
) pure returns (AssetFilter memory) {
|
|
45
45
|
return
|
|
46
46
|
AssetFilter({
|
|
47
|
-
|
|
47
|
+
variant: AssetFilterVariant.Definite,
|
|
48
48
|
payload: AssetsCodec.encode(params.assets)
|
|
49
49
|
});
|
|
50
50
|
}
|
|
@@ -55,7 +55,7 @@ function definite(
|
|
|
55
55
|
function wild(WildParams memory params) pure returns (AssetFilter memory) {
|
|
56
56
|
return
|
|
57
57
|
AssetFilter({
|
|
58
|
-
|
|
59
|
-
payload: WildAssetCodec.encode(params.
|
|
58
|
+
variant: AssetFilterVariant.Wild,
|
|
59
|
+
payload: WildAssetCodec.encode(params.wildAsset)
|
|
60
60
|
});
|
|
61
61
|
}
|
|
@@ -5,7 +5,13 @@ import {Assets} from "../Assets/Assets.sol";
|
|
|
5
5
|
import {AssetsCodec} from "../Assets/AssetsCodec.sol";
|
|
6
6
|
import {WildAsset} from "../WildAsset/WildAsset.sol";
|
|
7
7
|
import {WildAssetCodec} from "../WildAsset/WildAssetCodec.sol";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
AssetFilter,
|
|
10
|
+
AssetFilterVariant,
|
|
11
|
+
DefiniteParams,
|
|
12
|
+
WildParams
|
|
13
|
+
} from "./AssetFilter.sol";
|
|
14
|
+
import {BytesUtils} from "../../../Utils/BytesUtils.sol";
|
|
9
15
|
|
|
10
16
|
/// @title SCALE Codec for XCM v5 `AssetFilter`
|
|
11
17
|
/// @notice SCALE-compliant encoder/decoder for the `AssetFilter` type.
|
|
@@ -13,8 +19,7 @@ import {AssetFilter, AssetFilterType} from "./AssetFilter.sol";
|
|
|
13
19
|
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
14
20
|
library AssetFilterCodec {
|
|
15
21
|
error InvalidAssetFilterLength();
|
|
16
|
-
error
|
|
17
|
-
error InvalidAssetFilterPayload();
|
|
22
|
+
error InvalidAssetFilterVariant(uint8 variant);
|
|
18
23
|
|
|
19
24
|
/// @notice Encodes an `AssetFilter` struct into a SCALE-compliant byte array.
|
|
20
25
|
/// @param assetFilter The `AssetFilter` struct to encode.
|
|
@@ -22,7 +27,8 @@ library AssetFilterCodec {
|
|
|
22
27
|
function encode(
|
|
23
28
|
AssetFilter memory assetFilter
|
|
24
29
|
) internal pure returns (bytes memory) {
|
|
25
|
-
return
|
|
30
|
+
return
|
|
31
|
+
abi.encodePacked(uint8(assetFilter.variant), assetFilter.payload);
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
/// @notice Returns the number of bytes that a `AssetFilter` struct would occupy when SCALE-encoded.
|
|
@@ -36,22 +42,27 @@ library AssetFilterCodec {
|
|
|
36
42
|
if (data.length < offset + 1) {
|
|
37
43
|
revert InvalidAssetFilterLength();
|
|
38
44
|
}
|
|
39
|
-
uint8
|
|
40
|
-
if (
|
|
45
|
+
uint8 variant = uint8(data[offset]);
|
|
46
|
+
if (variant == uint8(AssetFilterVariant.Definite)) {
|
|
41
47
|
return 1 + AssetsCodec.encodedSizeAt(data, offset + 1);
|
|
42
|
-
} else if (
|
|
48
|
+
} else if (variant == uint8(AssetFilterVariant.Wild)) {
|
|
43
49
|
return 1 + WildAssetCodec.encodedSizeAt(data, offset + 1);
|
|
44
50
|
} else {
|
|
45
|
-
revert
|
|
51
|
+
revert InvalidAssetFilterVariant(variant);
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
/// @notice Decodes an `AssetFilter` struct from a SCALE-encoded byte array starting at the beginning of the data.
|
|
50
56
|
/// @param data The byte sequence containing the encoded `AssetFilter`.
|
|
51
57
|
/// @return assetFilter The decoded `AssetFilter` struct.
|
|
58
|
+
/// @return bytesRead The total number of bytes read from `data` to decode the `AssetFilter`.
|
|
52
59
|
function decode(
|
|
53
60
|
bytes memory data
|
|
54
|
-
)
|
|
61
|
+
)
|
|
62
|
+
internal
|
|
63
|
+
pure
|
|
64
|
+
returns (AssetFilter memory assetFilter, uint256 bytesRead)
|
|
65
|
+
{
|
|
55
66
|
return decodeAt(data, 0);
|
|
56
67
|
}
|
|
57
68
|
|
|
@@ -59,47 +70,49 @@ library AssetFilterCodec {
|
|
|
59
70
|
/// @param data The byte sequence containing the encoded `AssetFilter`.
|
|
60
71
|
/// @param offset The starting index in `data` from which to decode the `AssetFilter`.
|
|
61
72
|
/// @return assetFilter The decoded `AssetFilter` struct.
|
|
73
|
+
/// @return bytesRead The total number of bytes read from `data` to decode the `AssetFilter`.
|
|
62
74
|
function decodeAt(
|
|
63
75
|
bytes memory data,
|
|
64
76
|
uint256 offset
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
uint256 payloadLength = encodedSizeAt(data, offset) - 1; // Subtract 1 byte for the
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
bytes memory payload = new bytes(payloadLength);
|
|
75
|
-
for (uint256 i = 0; i < payloadLength; i++) {
|
|
76
|
-
payload[i] = data[offset + 1 + i];
|
|
77
|
-
}
|
|
78
|
-
assetFilter.afType = AssetFilterType(afType);
|
|
77
|
+
)
|
|
78
|
+
internal
|
|
79
|
+
pure
|
|
80
|
+
returns (AssetFilter memory assetFilter, uint256 bytesRead)
|
|
81
|
+
{
|
|
82
|
+
uint256 payloadLength = 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, payloadLength);
|
|
85
|
+
assetFilter.variant = AssetFilterVariant(variant);
|
|
79
86
|
assetFilter.payload = payload;
|
|
87
|
+
bytesRead = 1 + payloadLength;
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
/// @notice Extracs the inner `Assets` collection. Reverts if the `AssetFilter` is not of the `Definite` variant.
|
|
83
91
|
/// @param assetFilter The `AssetFilter` struct to decode, which must have the `Definite` variant.
|
|
84
|
-
/// @return
|
|
92
|
+
/// @return params A `DefiniteParams` struct containing the decoded `Assets` collection.
|
|
85
93
|
function asDefinite(
|
|
86
94
|
AssetFilter memory assetFilter
|
|
87
|
-
) internal pure returns (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
(assets, ) = AssetsCodec.decode(assetFilter.payload);
|
|
95
|
+
) internal pure returns (DefiniteParams memory params) {
|
|
96
|
+
_assertVariant(assetFilter, AssetFilterVariant.Definite);
|
|
97
|
+
(params.assets, ) = AssetsCodec.decode(assetFilter.payload);
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
/// @notice Extracts the inner `WildAsset` wildcard. Reverts if the `AssetFilter` is not of the `Wild` variant.
|
|
95
101
|
/// @param assetFilter The `AssetFilter` struct to decode, which must have the `Wild` variant.
|
|
96
|
-
/// @return
|
|
102
|
+
/// @return params A `WildParams` struct containing the decoded `WildAsset` wildcard.
|
|
97
103
|
function asWild(
|
|
98
104
|
AssetFilter memory assetFilter
|
|
99
|
-
) internal pure returns (
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
) internal pure returns (WildParams memory params) {
|
|
106
|
+
_assertVariant(assetFilter, AssetFilterVariant.Wild);
|
|
107
|
+
(params.wildAsset, ) = WildAssetCodec.decode(assetFilter.payload);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function _assertVariant(
|
|
111
|
+
AssetFilter memory assetFilter,
|
|
112
|
+
AssetFilterVariant expected
|
|
113
|
+
) private pure {
|
|
114
|
+
if (assetFilter.variant != expected) {
|
|
115
|
+
revert InvalidAssetFilterVariant(uint8(assetFilter.variant));
|
|
102
116
|
}
|
|
103
|
-
(wA, ) = WildAssetCodec.decode(assetFilter.payload);
|
|
104
117
|
}
|
|
105
118
|
}
|
|
@@ -13,7 +13,7 @@ using Bytes16 for bytes16;
|
|
|
13
13
|
using Bytes32 for bytes32;
|
|
14
14
|
|
|
15
15
|
/// @dev Discriminant for the different types of AssetInstances in XCM v5.
|
|
16
|
-
enum
|
|
16
|
+
enum AssetInstanceVariant {
|
|
17
17
|
/// @custom:variant Used if the non-fungible asset class has only one instance.
|
|
18
18
|
Undefined,
|
|
19
19
|
/// @custom:variant A compact index up to 2^128 - 1.
|
|
@@ -30,16 +30,16 @@ enum AssetInstanceType {
|
|
|
30
30
|
|
|
31
31
|
/// @notice A general identifier for an instance of a non-fungible asset class.
|
|
32
32
|
struct AssetInstance {
|
|
33
|
-
/// @custom:property The type of asset instance, determining how to interpret the payload. See `
|
|
34
|
-
|
|
35
|
-
/// @custom:property The encoded payload containing the asset instance data, whose structure depends on the `
|
|
33
|
+
/// @custom:property The type of asset instance, determining how to interpret the payload. See `AssetInstanceVariant` enum for possible values.
|
|
34
|
+
AssetInstanceVariant variant;
|
|
35
|
+
/// @custom:property The encoded payload containing the asset instance data, whose structure depends on the `variant`.
|
|
36
36
|
bytes payload;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/// @notice Parameters for the `Index` variant.
|
|
40
40
|
struct IndexParams {
|
|
41
41
|
/// @custom:property The compact index value.
|
|
42
|
-
uint128
|
|
42
|
+
uint128 index;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/// @notice Parameters for the `Array4` variant.
|
|
@@ -73,7 +73,7 @@ struct Array32Params {
|
|
|
73
73
|
function undefined() pure returns (AssetInstance memory) {
|
|
74
74
|
return
|
|
75
75
|
AssetInstance({
|
|
76
|
-
|
|
76
|
+
variant: AssetInstanceVariant.Undefined,
|
|
77
77
|
payload: new bytes(0)
|
|
78
78
|
});
|
|
79
79
|
}
|
|
@@ -82,8 +82,9 @@ function undefined() pure returns (AssetInstance memory) {
|
|
|
82
82
|
/// @param params Parameters for the index variant.
|
|
83
83
|
/// @return An `AssetInstance` struct with type `Index` and the provided index value encoded in the payload.
|
|
84
84
|
function index(IndexParams memory params) pure returns (AssetInstance memory) {
|
|
85
|
-
bytes memory payload = Compact.encode(params.
|
|
86
|
-
return
|
|
85
|
+
bytes memory payload = Compact.encode(params.index);
|
|
86
|
+
return
|
|
87
|
+
AssetInstance({variant: AssetInstanceVariant.Index, payload: payload});
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
/// @notice Creates an `Array4` asset instance with the given 4-byte data.
|
|
@@ -94,7 +95,7 @@ function array4(
|
|
|
94
95
|
) pure returns (AssetInstance memory) {
|
|
95
96
|
return
|
|
96
97
|
AssetInstance({
|
|
97
|
-
|
|
98
|
+
variant: AssetInstanceVariant.Array4,
|
|
98
99
|
payload: params.data.encode()
|
|
99
100
|
});
|
|
100
101
|
}
|
|
@@ -107,7 +108,7 @@ function array8(
|
|
|
107
108
|
) pure returns (AssetInstance memory) {
|
|
108
109
|
return
|
|
109
110
|
AssetInstance({
|
|
110
|
-
|
|
111
|
+
variant: AssetInstanceVariant.Array8,
|
|
111
112
|
payload: params.data.encode()
|
|
112
113
|
});
|
|
113
114
|
}
|
|
@@ -120,7 +121,7 @@ function array16(
|
|
|
120
121
|
) pure returns (AssetInstance memory) {
|
|
121
122
|
return
|
|
122
123
|
AssetInstance({
|
|
123
|
-
|
|
124
|
+
variant: AssetInstanceVariant.Array16,
|
|
124
125
|
payload: params.data.encode()
|
|
125
126
|
});
|
|
126
127
|
}
|
|
@@ -133,7 +134,7 @@ function array32(
|
|
|
133
134
|
) pure returns (AssetInstance memory) {
|
|
134
135
|
return
|
|
135
136
|
AssetInstance({
|
|
136
|
-
|
|
137
|
+
variant: AssetInstanceVariant.Array32,
|
|
137
138
|
payload: params.data.encode()
|
|
138
139
|
});
|
|
139
140
|
}
|