solidity-scale-codec 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/DEFINITIONS.md +132 -0
- package/README.md +95 -1
- package/package.json +8 -3
- package/src/LittleEndian/LittleEndianU128.sol +4 -2
- package/src/LittleEndian/LittleEndianU16.sol +2 -2
- package/src/LittleEndian/LittleEndianU256.sol +4 -2
- package/src/LittleEndian/LittleEndianU32.sol +4 -2
- package/src/LittleEndian/LittleEndianU64.sol +4 -2
- package/src/LittleEndian/LittleEndianU8.sol +2 -2
- package/src/Scale/Address/Address.sol +55 -0
- package/src/Scale/Address.sol +4 -0
- package/src/Scale/Array/BoolArr.sol +16 -2
- package/src/Scale/Array/I128Arr.sol +16 -2
- package/src/Scale/Array/I16Arr.sol +16 -2
- package/src/Scale/Array/I256Arr.sol +16 -2
- package/src/Scale/Array/I32Arr.sol +16 -2
- package/src/Scale/Array/I64Arr.sol +16 -2
- package/src/Scale/Array/I8Arr.sol +16 -2
- package/src/Scale/Array/U128Arr.sol +16 -2
- package/src/Scale/Array/U16Arr.sol +16 -2
- package/src/Scale/Array/U256Arr.sol +16 -2
- package/src/Scale/Array/U32Arr.sol +16 -2
- package/src/Scale/Array/U64Arr.sol +16 -2
- package/src/Scale/Array/U8Arr.sol +16 -2
- package/src/Scale/Bool/Bool.sol +12 -0
- package/src/Scale/Bytes/Bytes.sol +63 -0
- package/src/Scale/Bytes/Bytes16.sol +53 -0
- package/src/Scale/Bytes/Bytes2.sol +53 -0
- package/src/Scale/Bytes/Bytes32.sol +53 -0
- package/src/Scale/Bytes/Bytes4.sol +53 -0
- package/src/Scale/Bytes/Bytes8.sol +53 -0
- package/src/Scale/Bytes.sol +8 -0
- package/src/Scale/Compact/Compact.sol +37 -3
- package/src/Scale/Signed/I128.sol +11 -0
- package/src/Scale/Signed/I16.sol +11 -0
- package/src/Scale/Signed/I256.sol +11 -0
- package/src/Scale/Signed/I32.sol +11 -0
- package/src/Scale/Signed/I64.sol +11 -0
- package/src/Scale/Signed/I8.sol +11 -0
- package/src/Scale/Unsigned/U128.sol +16 -2
- package/src/Scale/Unsigned/U16.sol +16 -2
- package/src/Scale/Unsigned/U256.sol +16 -2
- package/src/Scale/Unsigned/U32.sol +16 -2
- package/src/Scale/Unsigned/U64.sol +16 -2
- package/src/Scale/Unsigned/U8.sol +16 -2
- package/src/Xcm/Types/Version.sol +5 -0
- package/src/Xcm/VersionedXcm/VersionedXcm.sol +27 -0
- package/src/Xcm/VersionedXcm/VersionedXcmCodec.sol +70 -0
- package/src/Xcm/v3/Constants.sol +5 -0
- package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCode.sol +73 -0
- package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCodeCodec.sol +94 -0
- package/src/Xcm/v5/Asset/Asset.sol +13 -0
- package/src/Xcm/v5/Asset/AssetCodec.sol +72 -0
- package/src/Xcm/v5/AssetFilter/AssetFilter.sol +61 -0
- package/src/Xcm/v5/AssetFilter/AssetFilterCodec.sol +105 -0
- package/src/Xcm/v5/AssetId/AssetId.sol +10 -0
- package/src/Xcm/v5/AssetId/AssetIdCodec.sol +57 -0
- package/src/Xcm/v5/AssetInstance/AssetInstance.sol +139 -0
- package/src/Xcm/v5/AssetInstance/AssetInstanceCodec.sol +174 -0
- package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilter.sol +82 -0
- package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilterCodec.sol +95 -0
- package/src/Xcm/v5/Assets/Assets.sol +14 -0
- package/src/Xcm/v5/Assets/AssetsCodec.sol +94 -0
- package/src/Xcm/v5/BodyId/BodyId.sol +121 -0
- package/src/Xcm/v5/BodyId/BodyIdCodec.sol +128 -0
- package/src/Xcm/v5/BodyPart/BodyPart.sol +105 -0
- package/src/Xcm/v5/BodyPart/BodyPartCodec.sol +134 -0
- package/src/Xcm/v5/Constants.sol +15 -0
- package/src/Xcm/v5/Fungibility/Fungibility.sol +60 -0
- package/src/Xcm/v5/Fungibility/FungibilityCodec.sol +128 -0
- package/src/Xcm/v5/Hint/Hint.sol +40 -0
- package/src/Xcm/v5/Hint/HintCodec.sol +82 -0
- package/src/Xcm/v5/Instruction/Instruction.sol +1217 -0
- package/src/Xcm/v5/Instruction/InstructionCodec.sol +321 -0
- package/src/Xcm/v5/Junction/Junction.sol +258 -0
- package/src/Xcm/v5/Junction/JunctionCodec.sol +329 -0
- package/src/Xcm/v5/Junctions/Junctions.sol +12 -0
- package/src/Xcm/v5/Junctions/JunctionsCodec.sol +120 -0
- package/src/Xcm/v5/Location/Location.sol +12 -0
- package/src/Xcm/v5/Location/LocationCodec.sol +68 -0
- package/src/Xcm/v5/NetworkId/NetworkId.sol +115 -0
- package/src/Xcm/v5/NetworkId/NetworkIdCodec.sol +114 -0
- package/src/Xcm/v5/OriginKind/OriginKind.sol +14 -0
- package/src/Xcm/v5/OriginKind/OriginKindCodec.sol +66 -0
- package/src/Xcm/v5/PalletInfo/PalletInfo.sol +18 -0
- package/src/Xcm/v5/PalletInfo/PalletInfoCodec.sol +119 -0
- package/src/Xcm/v5/QueryResponseInfo/QueryResponseInfo.sol +16 -0
- package/src/Xcm/v5/QueryResponseInfo/QueryResponseInfoCodec.sol +91 -0
- package/src/Xcm/v5/Response/Response.sol +145 -0
- package/src/Xcm/v5/Response/ResponseCodec.sol +174 -0
- package/src/Xcm/v5/Types/QueryId.sol +5 -0
- package/src/Xcm/v5/Weight/Weight.sol +10 -0
- package/src/Xcm/v5/Weight/WeightCodec.sol +87 -0
- package/src/Xcm/v5/WeightLimit/WeightLimit.sol +48 -0
- package/src/Xcm/v5/WeightLimit/WeightLimitCodec.sol +88 -0
- package/src/Xcm/v5/WildAsset/WildAsset.sol +112 -0
- package/src/Xcm/v5/WildAsset/WildAssetCodec.sol +166 -0
- package/src/Xcm/v5/WildFungibility/WildFungibility.sol +10 -0
- package/src/Xcm/v5/WildFungibility/WildFungibilityCodec.sol +74 -0
- package/src/Xcm/v5/Xcm/Xcm.sol +27 -0
- package/src/Xcm/v5/Xcm/XcmCodec.sol +83 -0
- package/src/Xcm/v5/XcmError/XcmError.sol +122 -0
- package/src/Xcm/v5/XcmError/XcmErrorCodec.sol +85 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {U8Arr} from "../../../Scale/Array.sol";
|
|
5
|
+
import {MaybeErrorCode, MaybeErrorCodeType} from "./MaybeErrorCode.sol";
|
|
6
|
+
|
|
7
|
+
/// @title SCALE Codec for XCM v3 `MaybeErrorCode`
|
|
8
|
+
/// @notice SCALE-compliant encoder/decoder for the `MaybeErrorCode` type.
|
|
9
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
10
|
+
/// @dev XCM v3 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v3/index.html
|
|
11
|
+
library MaybeErrorCodeCodec {
|
|
12
|
+
error InvalidMaybeErrorCodeLength();
|
|
13
|
+
error InvalidMaybeErrorCodeType(uint8 meType);
|
|
14
|
+
|
|
15
|
+
/// @notice Encodes a `MaybeErrorCode` struct into SCALE bytes.
|
|
16
|
+
/// @param me The `MaybeErrorCode` struct to encode.
|
|
17
|
+
/// @return SCALE-encoded bytes representing the `MaybeErrorCode`.
|
|
18
|
+
function encode(
|
|
19
|
+
MaybeErrorCode memory me
|
|
20
|
+
) internal pure returns (bytes memory) {
|
|
21
|
+
return abi.encodePacked(uint8(me.meType), me.payload);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// @notice Returns the number of bytes that a `MaybeErrorCode` would occupy when SCALE-encoded.
|
|
25
|
+
/// @param data The byte sequence containing the encoded `MaybeErrorCode`.
|
|
26
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size.
|
|
27
|
+
/// @return The number of bytes occupied by the encoded `MaybeErrorCode`.
|
|
28
|
+
function encodedSizeAt(
|
|
29
|
+
bytes memory data,
|
|
30
|
+
uint256 offset
|
|
31
|
+
) internal pure returns (uint256) {
|
|
32
|
+
if (data.length < offset + 1) revert InvalidMaybeErrorCodeLength();
|
|
33
|
+
uint8 meType = uint8(data[offset]);
|
|
34
|
+
if (meType == uint8(MaybeErrorCodeType.Success)) {
|
|
35
|
+
return 1;
|
|
36
|
+
} else if (
|
|
37
|
+
meType == uint8(MaybeErrorCodeType.Error) ||
|
|
38
|
+
meType == uint8(MaybeErrorCodeType.TruncatedError)
|
|
39
|
+
) {
|
|
40
|
+
return 1 + U8Arr.encodedSizeAt(data, offset + 1);
|
|
41
|
+
} else {
|
|
42
|
+
revert InvalidMaybeErrorCodeType(meType);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// @notice Decodes a `MaybeErrorCode` from SCALE bytes starting at the beginning.
|
|
47
|
+
/// @param data The byte sequence containing the encoded `MaybeErrorCode`.
|
|
48
|
+
/// @return me The decoded `MaybeErrorCode` struct.
|
|
49
|
+
/// @return bytesRead The number of bytes read.
|
|
50
|
+
function decode(
|
|
51
|
+
bytes memory data
|
|
52
|
+
) internal pure returns (MaybeErrorCode memory me, uint256 bytesRead) {
|
|
53
|
+
return decodeAt(data, 0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// @notice Decodes a `MaybeErrorCode` from SCALE bytes starting at a given offset.
|
|
57
|
+
/// @param data The byte sequence containing the encoded `MaybeErrorCode`.
|
|
58
|
+
/// @param offset The starting index in `data` from which to decode.
|
|
59
|
+
/// @return me The decoded `MaybeErrorCode` struct.
|
|
60
|
+
/// @return bytesRead The number of bytes read.
|
|
61
|
+
function decodeAt(
|
|
62
|
+
bytes memory data,
|
|
63
|
+
uint256 offset
|
|
64
|
+
) internal pure returns (MaybeErrorCode memory me, uint256 bytesRead) {
|
|
65
|
+
if (data.length < offset + 1) revert InvalidMaybeErrorCodeLength();
|
|
66
|
+
uint8 meType = uint8(data[offset]);
|
|
67
|
+
if (meType > uint8(MaybeErrorCodeType.TruncatedError))
|
|
68
|
+
revert InvalidMaybeErrorCodeType(meType);
|
|
69
|
+
uint256 size = encodedSizeAt(data, offset);
|
|
70
|
+
uint256 payloadLength = size - 1;
|
|
71
|
+
bytes memory payload = new bytes(payloadLength);
|
|
72
|
+
for (uint256 i = 0; i < payloadLength; ++i) {
|
|
73
|
+
payload[i] = data[offset + 1 + i];
|
|
74
|
+
}
|
|
75
|
+
me = MaybeErrorCode({
|
|
76
|
+
meType: MaybeErrorCodeType(meType),
|
|
77
|
+
payload: payload
|
|
78
|
+
});
|
|
79
|
+
bytesRead = size;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// @notice Decodes the dispatch error bytes from an `Error` or `TruncatedError` MaybeErrorCode.
|
|
83
|
+
/// @param me The `MaybeErrorCode` struct to decode. Must be of type `Error` or `TruncatedError`.
|
|
84
|
+
/// @return errorBytes The decoded dispatch error bytes.
|
|
85
|
+
function decodeError(
|
|
86
|
+
MaybeErrorCode memory me
|
|
87
|
+
) internal pure returns (uint8[] memory errorBytes) {
|
|
88
|
+
if (
|
|
89
|
+
me.meType != MaybeErrorCodeType.Error &&
|
|
90
|
+
me.meType != MaybeErrorCodeType.TruncatedError
|
|
91
|
+
) revert InvalidMaybeErrorCodeType(uint8(me.meType));
|
|
92
|
+
(errorBytes, ) = U8Arr.decode(me.payload);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {AssetId} from "../AssetId/AssetId.sol";
|
|
5
|
+
import {Fungibility} from "../Fungibility/Fungibility.sol";
|
|
6
|
+
|
|
7
|
+
/// @notice Either an amount of a single fungible asset, or a single well-identified non-fungible asset.
|
|
8
|
+
struct Asset {
|
|
9
|
+
/// @custom:property The overall asset identity (aka class, in the case of a non-fungible).
|
|
10
|
+
AssetId id;
|
|
11
|
+
/// @custom:property The fungibility of the asset, which contains either the amount (in the case of a fungible asset) or the instance ID, the secondary asset identifier.
|
|
12
|
+
Fungibility fungibility;
|
|
13
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {AssetId} from "../AssetId/AssetId.sol";
|
|
5
|
+
import {AssetIdCodec} from "../AssetId/AssetIdCodec.sol";
|
|
6
|
+
import {Fungibility} from "../Fungibility/Fungibility.sol";
|
|
7
|
+
import {FungibilityCodec} from "../Fungibility/FungibilityCodec.sol";
|
|
8
|
+
import {Asset} from "./Asset.sol";
|
|
9
|
+
|
|
10
|
+
/// @title SCALE Codec for XCM v5 `Asset`
|
|
11
|
+
/// @notice SCALE-compliant encoder/decoder for the `Asset` type.
|
|
12
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
13
|
+
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
14
|
+
library AssetCodec {
|
|
15
|
+
/// @notice Encodes an `Asset` struct into bytes.
|
|
16
|
+
/// @param asset The `Asset` struct to encode.
|
|
17
|
+
/// @return SCALE-encoded byte sequence representing the `Asset`.
|
|
18
|
+
function encode(Asset memory asset) internal pure returns (bytes memory) {
|
|
19
|
+
bytes memory encodedId = AssetIdCodec.encode(asset.id);
|
|
20
|
+
bytes memory encodedFungibility = FungibilityCodec.encode(
|
|
21
|
+
asset.fungibility
|
|
22
|
+
);
|
|
23
|
+
return abi.encodePacked(encodedId, encodedFungibility);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// @notice Returns the number of bytes that an `Asset` struct would occupy when SCALE-encoded.
|
|
27
|
+
/// @param data The byte sequence containing the encoded `Asset`.
|
|
28
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `Asset`.
|
|
29
|
+
/// @return The number of bytes that the `Asset` struct would occupy when SCALE-encoded.
|
|
30
|
+
function encodedSizeAt(
|
|
31
|
+
bytes memory data,
|
|
32
|
+
uint256 offset
|
|
33
|
+
) internal pure returns (uint256) {
|
|
34
|
+
uint256 idSize = AssetIdCodec.encodedSizeAt(data, offset);
|
|
35
|
+
uint256 fungibilitySize = FungibilityCodec.encodedSizeAt(
|
|
36
|
+
data,
|
|
37
|
+
offset + idSize
|
|
38
|
+
);
|
|
39
|
+
return idSize + fungibilitySize;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// @notice Decodes an `Asset` struct from bytes starting at the beginning of the data.
|
|
43
|
+
/// @param data The byte sequence containing the encoded `Asset`.
|
|
44
|
+
/// @return asset The decoded `Asset` struct.
|
|
45
|
+
/// @return bytesRead The total number of bytes read from `data` to decode the `Asset`.
|
|
46
|
+
function decode(
|
|
47
|
+
bytes memory data
|
|
48
|
+
) internal pure returns (Asset memory asset, uint256 bytesRead) {
|
|
49
|
+
return decodeAt(data, 0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// @notice Decodes an `Asset` struct from bytes starting at a given offset.
|
|
53
|
+
/// @param data The byte sequence containing the encoded `Asset`.
|
|
54
|
+
/// @param offset The starting index in `data` from which to decode the `Asset`.
|
|
55
|
+
/// @return asset The decoded `Asset` struct.
|
|
56
|
+
/// @return bytesRead The total number of bytes read from `data` to decode the `Asset`.
|
|
57
|
+
function decodeAt(
|
|
58
|
+
bytes memory data,
|
|
59
|
+
uint256 offset
|
|
60
|
+
) internal pure returns (Asset memory asset, uint256 bytesRead) {
|
|
61
|
+
(AssetId memory id, uint256 idBytesRead) = AssetIdCodec.decodeAt(
|
|
62
|
+
data,
|
|
63
|
+
offset
|
|
64
|
+
);
|
|
65
|
+
(
|
|
66
|
+
Fungibility memory fungibility,
|
|
67
|
+
uint256 fungibilityBytesRead
|
|
68
|
+
) = FungibilityCodec.decodeAt(data, offset + idBytesRead);
|
|
69
|
+
asset = Asset({id: id, fungibility: fungibility});
|
|
70
|
+
bytesRead = idBytesRead + fungibilityBytesRead;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
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 {WildAsset} from "../WildAsset/WildAsset.sol";
|
|
7
|
+
import {WildAssetCodec} from "../WildAsset/WildAssetCodec.sol";
|
|
8
|
+
|
|
9
|
+
/// @notice Discriminant for the type of asset filter being specified in an `AssetFilter`.
|
|
10
|
+
enum AssetFilterType {
|
|
11
|
+
/// @custom:variant Specify the filter as being everything contained by the given `Assets` inner.
|
|
12
|
+
Definite,
|
|
13
|
+
/// @custom:variant Specify the filter as the given `WildAsset` wildcard.
|
|
14
|
+
Wild
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// @notice `Asset` collection, defined either by a number of `Assets` or a single wildcard.
|
|
18
|
+
struct AssetFilter {
|
|
19
|
+
/// @custom:property The type of asset filter, determining how to interpret the payload. See `AssetFilterType` enum for possible values.
|
|
20
|
+
AssetFilterType afType;
|
|
21
|
+
/// @custom:property The encoded payload containing the asset filter data, whose structure depends on the `afType`.
|
|
22
|
+
bytes payload;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// @notice Parameters for the `Definite` variant.
|
|
26
|
+
struct DefiniteParams {
|
|
27
|
+
/// @custom:property The concrete assets used by the filter.
|
|
28
|
+
Assets assets;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// @notice Parameters for the `Wild` variant.
|
|
32
|
+
struct WildParams {
|
|
33
|
+
/// @custom:property The wildcard asset selector.
|
|
34
|
+
WildAsset wA;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ============ Factory Functions ============
|
|
38
|
+
|
|
39
|
+
/// @notice Creates an `AssetFilter` struct representing the `Definite` variant, which matches all assets contained by the given `Assets` inner.
|
|
40
|
+
/// @param params Parameters for the definite variant.
|
|
41
|
+
/// @return An `AssetFilter` with the `Assets` variant and the given `Assets` inner as its payload.
|
|
42
|
+
function definite(
|
|
43
|
+
DefiniteParams memory params
|
|
44
|
+
) pure returns (AssetFilter memory) {
|
|
45
|
+
return
|
|
46
|
+
AssetFilter({
|
|
47
|
+
afType: AssetFilterType.Definite,
|
|
48
|
+
payload: AssetsCodec.encode(params.assets)
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// @notice Creates an `AssetFilter` struct representing the `Wild` variant, which matches all assets contained by the given `WildAsset` wildcard.
|
|
53
|
+
/// @param params Parameters for the wild variant.
|
|
54
|
+
/// @return An `AssetFilter` with the `Wild` variant and the given `WildAsset` wildcard as its payload.
|
|
55
|
+
function wild(WildParams memory params) pure returns (AssetFilter memory) {
|
|
56
|
+
return
|
|
57
|
+
AssetFilter({
|
|
58
|
+
afType: AssetFilterType.Wild,
|
|
59
|
+
payload: WildAssetCodec.encode(params.wA)
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
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 {WildAsset} from "../WildAsset/WildAsset.sol";
|
|
7
|
+
import {WildAssetCodec} from "../WildAsset/WildAssetCodec.sol";
|
|
8
|
+
import {AssetFilter, AssetFilterType} from "./AssetFilter.sol";
|
|
9
|
+
|
|
10
|
+
/// @title SCALE Codec for XCM v5 `AssetFilter`
|
|
11
|
+
/// @notice SCALE-compliant encoder/decoder for the `AssetFilter` type.
|
|
12
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
13
|
+
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
14
|
+
library AssetFilterCodec {
|
|
15
|
+
error InvalidAssetFilterLength();
|
|
16
|
+
error InvalidAssetFilterType(uint8 afType);
|
|
17
|
+
error InvalidAssetFilterPayload();
|
|
18
|
+
|
|
19
|
+
/// @notice Encodes an `AssetFilter` struct into a SCALE-compliant byte array.
|
|
20
|
+
/// @param assetFilter The `AssetFilter` struct to encode.
|
|
21
|
+
/// @return A byte array containing the SCALE-encoded representation of the `AssetFilter`.
|
|
22
|
+
function encode(
|
|
23
|
+
AssetFilter memory assetFilter
|
|
24
|
+
) internal pure returns (bytes memory) {
|
|
25
|
+
return abi.encodePacked(uint8(assetFilter.afType), assetFilter.payload);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// @notice Returns the number of bytes that a `AssetFilter` struct would occupy when SCALE-encoded.
|
|
29
|
+
/// @param data The byte sequence containing the encoded `AssetFilter`.
|
|
30
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `AssetFilter`.
|
|
31
|
+
/// @return The number of bytes that the `AssetFilter` struct would occupy when SCALE-encoded.
|
|
32
|
+
function encodedSizeAt(
|
|
33
|
+
bytes memory data,
|
|
34
|
+
uint256 offset
|
|
35
|
+
) internal pure returns (uint256) {
|
|
36
|
+
if (data.length < offset + 1) {
|
|
37
|
+
revert InvalidAssetFilterLength();
|
|
38
|
+
}
|
|
39
|
+
uint8 afType = uint8(data[offset]);
|
|
40
|
+
if (afType == uint8(AssetFilterType.Definite)) {
|
|
41
|
+
return 1 + AssetsCodec.encodedSizeAt(data, offset + 1);
|
|
42
|
+
} else if (afType == uint8(AssetFilterType.Wild)) {
|
|
43
|
+
return 1 + WildAssetCodec.encodedSizeAt(data, offset + 1);
|
|
44
|
+
} else {
|
|
45
|
+
revert InvalidAssetFilterType(afType);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// @notice Decodes an `AssetFilter` struct from a SCALE-encoded byte array starting at the beginning of the data.
|
|
50
|
+
/// @param data The byte sequence containing the encoded `AssetFilter`.
|
|
51
|
+
/// @return assetFilter The decoded `AssetFilter` struct.
|
|
52
|
+
function decode(
|
|
53
|
+
bytes memory data
|
|
54
|
+
) internal pure returns (AssetFilter memory) {
|
|
55
|
+
return decodeAt(data, 0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// @notice Decodes an `AssetFilter` struct from a SCALE-encoded byte array starting at a given offset.
|
|
59
|
+
/// @param data The byte sequence containing the encoded `AssetFilter`.
|
|
60
|
+
/// @param offset The starting index in `data` from which to decode the `AssetFilter`.
|
|
61
|
+
/// @return assetFilter The decoded `AssetFilter` struct.
|
|
62
|
+
function decodeAt(
|
|
63
|
+
bytes memory data,
|
|
64
|
+
uint256 offset
|
|
65
|
+
) internal pure returns (AssetFilter memory assetFilter) {
|
|
66
|
+
if (data.length < offset + 1) {
|
|
67
|
+
revert InvalidAssetFilterLength();
|
|
68
|
+
}
|
|
69
|
+
uint8 afType = uint8(data[offset]);
|
|
70
|
+
uint256 payloadLength = encodedSizeAt(data, offset) - 1; // Subtract 1 byte for the afType
|
|
71
|
+
if (data.length < offset + 1 + payloadLength) {
|
|
72
|
+
revert InvalidAssetFilterLength();
|
|
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);
|
|
79
|
+
assetFilter.payload = payload;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// @notice Extracs the inner `Assets` collection. Reverts if the `AssetFilter` is not of the `Definite` variant.
|
|
83
|
+
/// @param assetFilter The `AssetFilter` struct to decode, which must have the `Definite` variant.
|
|
84
|
+
/// @return assets The `Assets` collection contained within the `AssetFilter` if it is of the `Definite` variant.
|
|
85
|
+
function asDefinite(
|
|
86
|
+
AssetFilter memory assetFilter
|
|
87
|
+
) internal pure returns (Assets memory assets) {
|
|
88
|
+
if (assetFilter.afType != AssetFilterType.Definite) {
|
|
89
|
+
revert InvalidAssetFilterPayload();
|
|
90
|
+
}
|
|
91
|
+
(assets, ) = AssetsCodec.decode(assetFilter.payload);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// @notice Extracts the inner `WildAsset` wildcard. Reverts if the `AssetFilter` is not of the `Wild` variant.
|
|
95
|
+
/// @param assetFilter The `AssetFilter` struct to decode, which must have the `Wild` variant.
|
|
96
|
+
/// @return wA The `WildAsset` wildcard contained within the `AssetFilter` if it is of the `Wild` variant.
|
|
97
|
+
function asWild(
|
|
98
|
+
AssetFilter memory assetFilter
|
|
99
|
+
) internal pure returns (WildAsset memory wA) {
|
|
100
|
+
if (assetFilter.afType != AssetFilterType.Wild) {
|
|
101
|
+
revert InvalidAssetFilterPayload();
|
|
102
|
+
}
|
|
103
|
+
(wA, ) = WildAssetCodec.decode(assetFilter.payload);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Location} from "../Location/Location.sol";
|
|
5
|
+
|
|
6
|
+
/// @notice Location to identify an asset.
|
|
7
|
+
struct AssetId {
|
|
8
|
+
/// @custom:property The location of the asset.
|
|
9
|
+
Location location;
|
|
10
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
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 {AssetId} from "./AssetId.sol";
|
|
7
|
+
|
|
8
|
+
/// @title SCALE Codec for XCM v5 `AssetId`
|
|
9
|
+
/// @notice SCALE-compliant encoder/decoder for the `AssetId` type.
|
|
10
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
11
|
+
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
12
|
+
library AssetIdCodec {
|
|
13
|
+
/// @notice Encodes an `AssetId` struct into bytes.
|
|
14
|
+
/// @param assetId The `AssetId` struct to encode.
|
|
15
|
+
/// @return SCALE-encoded byte sequence representing the `AssetId`.
|
|
16
|
+
function encode(
|
|
17
|
+
AssetId memory assetId
|
|
18
|
+
) internal pure returns (bytes memory) {
|
|
19
|
+
return LocationCodec.encode(assetId.location);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// @notice Returns the number of bytes that an `AssetId` struct would occupy when SCALE-encoded.
|
|
23
|
+
/// @param data The byte sequence containing the encoded `AssetId`.
|
|
24
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `AssetId`.
|
|
25
|
+
/// @return The number of bytes that the `AssetId` struct would occupy when SCALE-encoded.
|
|
26
|
+
function encodedSizeAt(
|
|
27
|
+
bytes memory data,
|
|
28
|
+
uint256 offset
|
|
29
|
+
) internal pure returns (uint256) {
|
|
30
|
+
return LocationCodec.encodedSizeAt(data, offset);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// @notice Decodes an `AssetId` struct from bytes starting at the beginning of the data.
|
|
34
|
+
/// @param data The byte sequence containing the encoded `AssetId`.
|
|
35
|
+
/// @return assetId The decoded `AssetId` struct.
|
|
36
|
+
/// @return bytesRead The total number of bytes read from `data` to decode the `AssetId`.
|
|
37
|
+
function decode(
|
|
38
|
+
bytes memory data
|
|
39
|
+
) internal pure returns (AssetId memory assetId, uint256 bytesRead) {
|
|
40
|
+
return decodeAt(data, 0);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// @notice Decodes an `AssetId` struct from bytes starting at a given offset.
|
|
44
|
+
/// @param data The byte sequence containing the encoded `AssetId`.
|
|
45
|
+
/// @param offset The starting index in `data` from which to decode the `AssetId`.
|
|
46
|
+
/// @return assetId The decoded `AssetId` struct.
|
|
47
|
+
/// @return bytesRead The total number of bytes read from `data` to decode the `AssetId`.
|
|
48
|
+
function decodeAt(
|
|
49
|
+
bytes memory data,
|
|
50
|
+
uint256 offset
|
|
51
|
+
) internal pure returns (AssetId memory assetId, uint256 bytesRead) {
|
|
52
|
+
(Location memory location, uint256 locationBytesRead) = LocationCodec
|
|
53
|
+
.decodeAt(data, offset);
|
|
54
|
+
assetId = AssetId({location: location});
|
|
55
|
+
bytesRead = locationBytesRead;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Compact} from "../../../Scale/Compact.sol";
|
|
5
|
+
import {Bytes4} from "../../../Scale/Bytes/Bytes4.sol";
|
|
6
|
+
import {Bytes8} from "../../../Scale/Bytes/Bytes8.sol";
|
|
7
|
+
import {Bytes16} from "../../../Scale/Bytes/Bytes16.sol";
|
|
8
|
+
import {Bytes32} from "../../../Scale/Bytes/Bytes32.sol";
|
|
9
|
+
|
|
10
|
+
using Bytes4 for bytes4;
|
|
11
|
+
using Bytes8 for bytes8;
|
|
12
|
+
using Bytes16 for bytes16;
|
|
13
|
+
using Bytes32 for bytes32;
|
|
14
|
+
|
|
15
|
+
/// @dev Discriminant for the different types of AssetInstances in XCM v5.
|
|
16
|
+
enum AssetInstanceType {
|
|
17
|
+
/// @custom:variant Used if the non-fungible asset class has only one instance.
|
|
18
|
+
Undefined,
|
|
19
|
+
/// @custom:variant A compact index up to 2^128 - 1.
|
|
20
|
+
Index,
|
|
21
|
+
/// @custom:variant A 4-byte fixed-length datum.
|
|
22
|
+
Array4,
|
|
23
|
+
/// @custom:variant An 8-byte fixed-length datum.
|
|
24
|
+
Array8,
|
|
25
|
+
/// @custom:variant A 16-byte fixed-length datum.
|
|
26
|
+
Array16,
|
|
27
|
+
/// @custom:variant A 32-byte fixed-length datum.
|
|
28
|
+
Array32
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// @notice A general identifier for an instance of a non-fungible asset class.
|
|
32
|
+
struct AssetInstance {
|
|
33
|
+
/// @custom:property The type of asset instance, determining how to interpret the payload. See `AssetInstanceType` enum for possible values.
|
|
34
|
+
AssetInstanceType iType;
|
|
35
|
+
/// @custom:property The encoded payload containing the asset instance data, whose structure depends on the `iType`.
|
|
36
|
+
bytes payload;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// @notice Parameters for the `Index` variant.
|
|
40
|
+
struct IndexParams {
|
|
41
|
+
/// @custom:property The compact index value.
|
|
42
|
+
uint128 idx;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// @notice Parameters for the `Array4` variant.
|
|
46
|
+
struct Array4Params {
|
|
47
|
+
/// @custom:property The 4-byte fixed data.
|
|
48
|
+
bytes4 data;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// @notice Parameters for the `Array8` variant.
|
|
52
|
+
struct Array8Params {
|
|
53
|
+
/// @custom:property The 8-byte fixed data.
|
|
54
|
+
bytes8 data;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// @notice Parameters for the `Array16` variant.
|
|
58
|
+
struct Array16Params {
|
|
59
|
+
/// @custom:property The 16-byte fixed data.
|
|
60
|
+
bytes16 data;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// @notice Parameters for the `Array32` variant.
|
|
64
|
+
struct Array32Params {
|
|
65
|
+
/// @custom:property The 32-byte fixed data.
|
|
66
|
+
bytes32 data;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ============ Factory Functions ============
|
|
70
|
+
|
|
71
|
+
/// @notice Creates an `Undefined` asset instance.
|
|
72
|
+
/// @return An `AssetInstance` struct with type `Undefined` and an empty payload.
|
|
73
|
+
function undefined() pure returns (AssetInstance memory) {
|
|
74
|
+
return
|
|
75
|
+
AssetInstance({
|
|
76
|
+
iType: AssetInstanceType.Undefined,
|
|
77
|
+
payload: new bytes(0)
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// @notice Creates an `Index` asset instance with the given index value.
|
|
82
|
+
/// @param params Parameters for the index variant.
|
|
83
|
+
/// @return An `AssetInstance` struct with type `Index` and the provided index value encoded in the payload.
|
|
84
|
+
function index(IndexParams memory params) pure returns (AssetInstance memory) {
|
|
85
|
+
bytes memory payload = Compact.encode(params.idx);
|
|
86
|
+
return AssetInstance({iType: AssetInstanceType.Index, payload: payload});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// @notice Creates an `Array4` asset instance with the given 4-byte data.
|
|
90
|
+
/// @param params Parameters for the array4 variant.
|
|
91
|
+
/// @return An `AssetInstance` struct with type `Array4` and the provided data encoded in the payload.
|
|
92
|
+
function array4(
|
|
93
|
+
Array4Params memory params
|
|
94
|
+
) pure returns (AssetInstance memory) {
|
|
95
|
+
return
|
|
96
|
+
AssetInstance({
|
|
97
|
+
iType: AssetInstanceType.Array4,
|
|
98
|
+
payload: params.data.encode()
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// @notice Creates an `Array8` asset instance with the given 8-byte data.
|
|
103
|
+
/// @param params Parameters for the array8 variant.
|
|
104
|
+
/// @return An `AssetInstance` struct with type `Array8` and the provided data encoded in the payload.
|
|
105
|
+
function array8(
|
|
106
|
+
Array8Params memory params
|
|
107
|
+
) pure returns (AssetInstance memory) {
|
|
108
|
+
return
|
|
109
|
+
AssetInstance({
|
|
110
|
+
iType: AssetInstanceType.Array8,
|
|
111
|
+
payload: params.data.encode()
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// @notice Creates an `Array16` asset instance with the given 16-byte data.
|
|
116
|
+
/// @param params Parameters for the array16 variant.
|
|
117
|
+
/// @return An `AssetInstance` struct with type `Array16` and the provided data encoded in the payload.
|
|
118
|
+
function array16(
|
|
119
|
+
Array16Params memory params
|
|
120
|
+
) pure returns (AssetInstance memory) {
|
|
121
|
+
return
|
|
122
|
+
AssetInstance({
|
|
123
|
+
iType: AssetInstanceType.Array16,
|
|
124
|
+
payload: params.data.encode()
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// @notice Creates an `Array32` asset instance with the given 32-byte data.
|
|
129
|
+
/// @param params Parameters for the array32 variant.
|
|
130
|
+
/// @return An `AssetInstance` struct with type `Array32` and the provided data encoded in the payload.
|
|
131
|
+
function array32(
|
|
132
|
+
Array32Params memory params
|
|
133
|
+
) pure returns (AssetInstance memory) {
|
|
134
|
+
return
|
|
135
|
+
AssetInstance({
|
|
136
|
+
iType: AssetInstanceType.Array32,
|
|
137
|
+
payload: params.data.encode()
|
|
138
|
+
});
|
|
139
|
+
}
|