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
|
@@ -3,7 +3,9 @@ pragma solidity ^0.8.28;
|
|
|
3
3
|
|
|
4
4
|
import {Bytes4} from "../../../Scale/Bytes.sol";
|
|
5
5
|
import {Compact} from "../../../Scale/Compact.sol";
|
|
6
|
-
import {BodyId,
|
|
6
|
+
import {BodyId, BodyIdVariant, MonikerParams, IndexParams} from "./BodyId.sol";
|
|
7
|
+
import {BytesUtils} from "../../../Utils/BytesUtils.sol";
|
|
8
|
+
import {UnsignedUtils} from "../../../Utils/UnsignedUtils.sol";
|
|
7
9
|
|
|
8
10
|
/// @title SCALE Codec for XCM v5 `BodyId`
|
|
9
11
|
/// @notice SCALE-compliant encoder/decoder for the `BodyId` type.
|
|
@@ -11,13 +13,13 @@ import {BodyId, BodyIdType} from "./BodyId.sol";
|
|
|
11
13
|
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
12
14
|
library BodyIdCodec {
|
|
13
15
|
error InvalidBodyIdLength();
|
|
14
|
-
error
|
|
16
|
+
error InvalidBodyIdVariant(uint8 variant);
|
|
15
17
|
|
|
16
18
|
/// @notice Encodes a `BodyId` into bytes.
|
|
17
19
|
/// @param bodyId The `BodyId` to encode.
|
|
18
20
|
/// @return SCALE-encoded byte sequence representing the `BodyId`.
|
|
19
21
|
function encode(BodyId memory bodyId) internal pure returns (bytes memory) {
|
|
20
|
-
return abi.encodePacked(uint8(bodyId.
|
|
22
|
+
return abi.encodePacked(uint8(bodyId.variant), bodyId.payload);
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
/// @notice Returns the number of bytes that a `BodyId` struct would occupy when SCALE-encoded, starting at a given offset in the data.
|
|
@@ -31,26 +33,26 @@ library BodyIdCodec {
|
|
|
31
33
|
if (data.length < offset + 1) {
|
|
32
34
|
revert InvalidBodyIdLength();
|
|
33
35
|
}
|
|
34
|
-
uint8
|
|
35
|
-
|
|
36
|
+
uint8 variantValue = uint8(data[offset]);
|
|
37
|
+
BodyIdVariant variant = BodyIdVariant(variantValue);
|
|
36
38
|
uint256 payloadLength;
|
|
37
39
|
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
variant == BodyIdVariant.Unit ||
|
|
41
|
+
variant == BodyIdVariant.Executive ||
|
|
42
|
+
variant == BodyIdVariant.Technical ||
|
|
43
|
+
variant == BodyIdVariant.Legislative ||
|
|
44
|
+
variant == BodyIdVariant.Judicial ||
|
|
45
|
+
variant == BodyIdVariant.Defense ||
|
|
46
|
+
variant == BodyIdVariant.Administration ||
|
|
47
|
+
variant == BodyIdVariant.Treasury
|
|
46
48
|
) {
|
|
47
49
|
payloadLength = 0;
|
|
48
|
-
} else if (
|
|
50
|
+
} else if (variant == BodyIdVariant.Moniker) {
|
|
49
51
|
payloadLength = 4;
|
|
50
|
-
} else if (
|
|
52
|
+
} else if (variant == BodyIdVariant.Index) {
|
|
51
53
|
payloadLength = 4;
|
|
52
54
|
} else {
|
|
53
|
-
revert
|
|
55
|
+
revert InvalidBodyIdVariant(variantValue);
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
if (data.length < offset + 1 + payloadLength) {
|
|
@@ -79,50 +81,41 @@ library BodyIdCodec {
|
|
|
79
81
|
bytes memory data,
|
|
80
82
|
uint256 offset
|
|
81
83
|
) internal pure returns (BodyId memory bodyId, uint256 bytesRead) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
uint256 payloadLength = encodedSizeAt(data, offset) - 1; // subtract 1 byte for the bodyIdType
|
|
88
|
-
bytes memory payload = new bytes(payloadLength);
|
|
89
|
-
|
|
90
|
-
for (uint256 i = 0; i < payloadLength; i++) {
|
|
91
|
-
payload[i] = data[offset + 1 + i];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
bodyId = BodyId({bodyIdType: bodyIdType, payload: payload});
|
|
84
|
+
uint256 payloadLength = encodedSizeAt(data, offset) - 1; // subtract 1 byte for the variant
|
|
85
|
+
uint8 variantValue = uint8(data[offset]);
|
|
86
|
+
BodyIdVariant variant = BodyIdVariant(variantValue);
|
|
87
|
+
bytes memory payload = BytesUtils.copy(data, offset + 1, payloadLength);
|
|
88
|
+
bodyId = BodyId({variant: variant, payload: payload});
|
|
95
89
|
bytesRead = 1 + payloadLength;
|
|
96
90
|
}
|
|
97
91
|
|
|
98
92
|
/// @notice Helper function to decode a `BodyId` and extract the moniker name if the type is `Moniker`.
|
|
99
93
|
/// @param bodyId The `BodyId` to extract the moniker name from.
|
|
100
|
-
/// @return
|
|
94
|
+
/// @return params A `MonikerParams` struct containing the moniker name if the `variant` is `Moniker`.
|
|
101
95
|
function asMoniker(
|
|
102
96
|
BodyId memory bodyId
|
|
103
|
-
) internal pure returns (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
return Bytes4.decode(bodyId.payload);
|
|
97
|
+
) internal pure returns (MonikerParams memory params) {
|
|
98
|
+
_assertVariant(bodyId, BodyIdVariant.Moniker);
|
|
99
|
+
params.name = Bytes4.decode(bodyId.payload);
|
|
108
100
|
}
|
|
109
101
|
|
|
110
102
|
/// @notice Helper function to decode a `BodyId` and extract the index if the type is `Index`.
|
|
111
103
|
/// @param bodyId The `BodyId` to extract the index from.
|
|
112
|
-
/// @return
|
|
113
|
-
function asIndex(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (bodyId.payload.length != 4) {
|
|
118
|
-
revert InvalidBodyIdLength();
|
|
119
|
-
}
|
|
104
|
+
/// @return params An `IndexParams` struct containing the index if the `variant` is `Index`.
|
|
105
|
+
function asIndex(
|
|
106
|
+
BodyId memory bodyId
|
|
107
|
+
) internal pure returns (IndexParams memory params) {
|
|
108
|
+
_assertVariant(bodyId, BodyIdVariant.Index);
|
|
120
109
|
(uint256 decodedIndex, ) = Compact.decode(bodyId.payload);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
110
|
+
params.index = UnsignedUtils.toU32(decodedIndex);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function _assertVariant(
|
|
114
|
+
BodyId memory bodyId,
|
|
115
|
+
BodyIdVariant expected
|
|
116
|
+
) internal pure {
|
|
117
|
+
if (bodyId.variant != expected) {
|
|
118
|
+
revert InvalidBodyIdVariant(uint8(bodyId.variant));
|
|
126
119
|
}
|
|
127
120
|
}
|
|
128
121
|
}
|
|
@@ -4,7 +4,7 @@ pragma solidity ^0.8.28;
|
|
|
4
4
|
import {Compact} from "../../../Scale/Compact.sol";
|
|
5
5
|
|
|
6
6
|
/// @dev Discriminant for the different types of BodyParts in XCM v5. Each variant corresponds to a specific structure of the payload.
|
|
7
|
-
enum
|
|
7
|
+
enum BodyPartVariant {
|
|
8
8
|
/// @custom:variant The body's declaration, under whatever means it decides.
|
|
9
9
|
Voice,
|
|
10
10
|
/// @custom:variant A given number of members of the body.
|
|
@@ -19,8 +19,8 @@ enum BodyPartType {
|
|
|
19
19
|
|
|
20
20
|
/// @notice A part of a pluralistic body.
|
|
21
21
|
struct BodyPart {
|
|
22
|
-
/// @custom:property The type of BodyPart, which determines how to interpret the payload. See `
|
|
23
|
-
|
|
22
|
+
/// @custom:property The type of BodyPart, which determines how to interpret the payload. See `BodyPartVariant` enum for possible values.
|
|
23
|
+
BodyPartVariant variant;
|
|
24
24
|
/// @custom:property For Members, this will hold the count. For Fraction, AtLeastProportion, and MoreThanProportion, this will hold the encoded Proportion struct. For Voice, this will be empty.
|
|
25
25
|
bytes payload;
|
|
26
26
|
}
|
|
@@ -31,12 +31,36 @@ struct MembersParams {
|
|
|
31
31
|
uint32 count;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/// @notice Parameters for the `Fraction` variant.
|
|
35
|
+
struct FractionParams {
|
|
36
|
+
/// @custom:property The numerator of the fraction, representing the number of members in favor.
|
|
37
|
+
uint32 nominator;
|
|
38
|
+
/// @custom:property The denominator of the fraction, representing the total number of members considered.
|
|
39
|
+
uint32 denominator;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// @notice Parameters for the `AtLeastProportion` variant.
|
|
43
|
+
struct AtLeastProportionParams {
|
|
44
|
+
/// @custom:property The numerator of the proportion, representing the minimum number of members in favor.
|
|
45
|
+
uint32 nominator;
|
|
46
|
+
/// @custom:property The denominator of the proportion, representing the total number of members considered.
|
|
47
|
+
uint32 denominator;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// @notice Parameters for the `MoreThanProportion` variant.
|
|
51
|
+
struct MoreThanProportionParams {
|
|
52
|
+
/// @custom:property The numerator of the proportion, representing the minimum number of members in favor.
|
|
53
|
+
uint32 nominator;
|
|
54
|
+
/// @custom:property The denominator of the proportion, representing the total number of members considered.
|
|
55
|
+
uint32 denominator;
|
|
56
|
+
}
|
|
57
|
+
|
|
34
58
|
// ============ Factory Functions ============
|
|
35
59
|
|
|
36
60
|
/// @notice Creates a `BodyPart` struct representing a `Voice` body part.
|
|
37
61
|
/// @return A `BodyPart` with the `Voice` variant.
|
|
38
62
|
function voice() pure returns (BodyPart memory) {
|
|
39
|
-
return BodyPart({
|
|
63
|
+
return BodyPart({variant: BodyPartVariant.Voice, payload: ""});
|
|
40
64
|
}
|
|
41
65
|
|
|
42
66
|
/// @notice Creates a `BodyPart` struct representing a `Members` body part with the given count.
|
|
@@ -45,61 +69,53 @@ function voice() pure returns (BodyPart memory) {
|
|
|
45
69
|
function members(MembersParams memory params) pure returns (BodyPart memory) {
|
|
46
70
|
return
|
|
47
71
|
BodyPart({
|
|
48
|
-
|
|
72
|
+
variant: BodyPartVariant.Members,
|
|
49
73
|
payload: Compact.encode(params.count)
|
|
50
74
|
});
|
|
51
75
|
}
|
|
52
76
|
|
|
53
77
|
/// @notice Creates a `BodyPart` struct representing a `Fraction` body part with the given proportion.
|
|
54
|
-
/// @param
|
|
55
|
-
/// @param denominator The denominator of the proportion, representing the total number of members considered.
|
|
78
|
+
/// @param params Parameters for the fraction variant.
|
|
56
79
|
/// @return A `BodyPart` with the `Fraction` variant and the encoded proportion in the payload.
|
|
57
|
-
function fraction(
|
|
58
|
-
uint32 nominator,
|
|
59
|
-
uint32 denominator
|
|
60
|
-
) pure returns (BodyPart memory) {
|
|
80
|
+
function fraction(FractionParams memory params) pure returns (BodyPart memory) {
|
|
61
81
|
return
|
|
62
82
|
BodyPart({
|
|
63
|
-
|
|
83
|
+
variant: BodyPartVariant.Fraction,
|
|
64
84
|
payload: abi.encodePacked(
|
|
65
|
-
Compact.encode(nominator),
|
|
66
|
-
Compact.encode(denominator)
|
|
85
|
+
Compact.encode(params.nominator),
|
|
86
|
+
Compact.encode(params.denominator)
|
|
67
87
|
)
|
|
68
88
|
});
|
|
69
89
|
}
|
|
70
90
|
|
|
71
91
|
/// @notice Creates a `BodyPart` struct representing an `AtLeastProportion` body part with the given proportion.
|
|
72
|
-
/// @param
|
|
73
|
-
/// @param denominator The denominator of the proportion, representing the total number of members considered.
|
|
92
|
+
/// @param params Parameters for the at least proportion variant.
|
|
74
93
|
/// @return A `BodyPart` with the `AtLeastProportion` variant and the encoded proportion in the payload.
|
|
75
94
|
function atLeastProportion(
|
|
76
|
-
|
|
77
|
-
uint32 denominator
|
|
95
|
+
AtLeastProportionParams memory params
|
|
78
96
|
) pure returns (BodyPart memory) {
|
|
79
97
|
return
|
|
80
98
|
BodyPart({
|
|
81
|
-
|
|
99
|
+
variant: BodyPartVariant.AtLeastProportion,
|
|
82
100
|
payload: abi.encodePacked(
|
|
83
|
-
Compact.encode(nominator),
|
|
84
|
-
Compact.encode(denominator)
|
|
101
|
+
Compact.encode(params.nominator),
|
|
102
|
+
Compact.encode(params.denominator)
|
|
85
103
|
)
|
|
86
104
|
});
|
|
87
105
|
}
|
|
88
106
|
|
|
89
107
|
/// @notice Creates a `BodyPart` struct representing a `MoreThanProportion` body part with the given proportion.
|
|
90
|
-
/// @param
|
|
91
|
-
/// @param denominator The denominator of the proportion, representing the total number of members considered.
|
|
108
|
+
/// @param params Parameters for the more than proportion variant.
|
|
92
109
|
/// @return A `BodyPart` with the `MoreThanProportion` variant and the encoded proportion in the payload.
|
|
93
110
|
function moreThanProportion(
|
|
94
|
-
|
|
95
|
-
uint32 denominator
|
|
111
|
+
MoreThanProportionParams memory params
|
|
96
112
|
) pure returns (BodyPart memory) {
|
|
97
113
|
return
|
|
98
114
|
BodyPart({
|
|
99
|
-
|
|
115
|
+
variant: BodyPartVariant.MoreThanProportion,
|
|
100
116
|
payload: abi.encodePacked(
|
|
101
|
-
Compact.encode(nominator),
|
|
102
|
-
Compact.encode(denominator)
|
|
117
|
+
Compact.encode(params.nominator),
|
|
118
|
+
Compact.encode(params.denominator)
|
|
103
119
|
)
|
|
104
120
|
});
|
|
105
121
|
}
|
|
@@ -2,7 +2,16 @@
|
|
|
2
2
|
pragma solidity ^0.8.28;
|
|
3
3
|
|
|
4
4
|
import {Compact} from "../../../Scale/Compact.sol";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
BodyPart,
|
|
7
|
+
BodyPartVariant,
|
|
8
|
+
MembersParams,
|
|
9
|
+
FractionParams,
|
|
10
|
+
AtLeastProportionParams,
|
|
11
|
+
MoreThanProportionParams
|
|
12
|
+
} from "./BodyPart.sol";
|
|
13
|
+
import {BytesUtils} from "../../../Utils/BytesUtils.sol";
|
|
14
|
+
import {UnsignedUtils} from "../../../Utils/UnsignedUtils.sol";
|
|
6
15
|
|
|
7
16
|
/// @title SCALE Codec for XCM v5 `BodyPart`
|
|
8
17
|
/// @notice SCALE-compliant encoder/decoder for the `BodyPart` type.
|
|
@@ -10,8 +19,7 @@ import {BodyPart, BodyPartType} from "./BodyPart.sol";
|
|
|
10
19
|
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
11
20
|
library BodyPartCodec {
|
|
12
21
|
error InvalidBodyPartLength();
|
|
13
|
-
error
|
|
14
|
-
error InvalidBodyPartPayload();
|
|
22
|
+
error InvalidBodyPartVariant(uint8 variant);
|
|
15
23
|
|
|
16
24
|
/// @notice Encodes a `BodyPart` struct into bytes.
|
|
17
25
|
/// @param bodyPart The `BodyPart` struct to encode.
|
|
@@ -19,7 +27,7 @@ library BodyPartCodec {
|
|
|
19
27
|
function encode(
|
|
20
28
|
BodyPart memory bodyPart
|
|
21
29
|
) internal pure returns (bytes memory) {
|
|
22
|
-
return abi.encodePacked(uint8(bodyPart.
|
|
30
|
+
return abi.encodePacked(uint8(bodyPart.variant), bodyPart.payload);
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
/// @notice Returns the number of bytes that a `BodyPart` struct would occupy when SCALE-encoded.
|
|
@@ -32,23 +40,23 @@ library BodyPartCodec {
|
|
|
32
40
|
) internal pure returns (uint256) {
|
|
33
41
|
if (offset >= data.length) revert InvalidBodyPartLength();
|
|
34
42
|
|
|
35
|
-
uint8
|
|
43
|
+
uint8 variant = uint8(data[offset]);
|
|
36
44
|
uint256 payloadLength;
|
|
37
|
-
if (
|
|
45
|
+
if (variant == uint8(BodyPartVariant.Voice)) {
|
|
38
46
|
payloadLength = 0;
|
|
39
|
-
} else if (
|
|
47
|
+
} else if (variant == uint8(BodyPartVariant.Members)) {
|
|
40
48
|
payloadLength = Compact.encodedSizeAt(data, offset + 1);
|
|
41
49
|
} else if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
variant == uint8(BodyPartVariant.Fraction) ||
|
|
51
|
+
variant == uint8(BodyPartVariant.AtLeastProportion) ||
|
|
52
|
+
variant == uint8(BodyPartVariant.MoreThanProportion)
|
|
45
53
|
) {
|
|
46
54
|
uint256 innerLength = Compact.encodedSizeAt(data, offset + 1);
|
|
47
55
|
payloadLength =
|
|
48
56
|
innerLength +
|
|
49
57
|
Compact.encodedSizeAt(data, offset + 1 + innerLength);
|
|
50
58
|
} else {
|
|
51
|
-
revert
|
|
59
|
+
revert InvalidBodyPartVariant(variant);
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
if (data.length < offset + 1 + payloadLength) {
|
|
@@ -77,18 +85,13 @@ library BodyPartCodec {
|
|
|
77
85
|
bytes memory data,
|
|
78
86
|
uint256 offset
|
|
79
87
|
) internal pure returns (BodyPart memory bodyPart, uint256 bytesRead) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
uint8 bodyPartType = uint8(data[offset]);
|
|
83
|
-
uint256 payloadLength = encodedSizeAt(data, offset) - 1; // total size minus 1 byte for the bodyPartType
|
|
88
|
+
uint256 payloadLength = encodedSizeAt(data, offset) - 1; // total size minus 1 byte for the variant
|
|
89
|
+
uint8 variant = uint8(data[offset]);
|
|
84
90
|
|
|
85
|
-
bytes memory payload =
|
|
86
|
-
for (uint256 i = 0; i < payloadLength; i++) {
|
|
87
|
-
payload[i] = data[offset + 1 + i];
|
|
88
|
-
}
|
|
91
|
+
bytes memory payload = BytesUtils.copy(data, offset + 1, payloadLength);
|
|
89
92
|
|
|
90
93
|
bodyPart = BodyPart({
|
|
91
|
-
|
|
94
|
+
variant: BodyPartVariant(variant),
|
|
92
95
|
payload: payload
|
|
93
96
|
});
|
|
94
97
|
bytesRead = 1 + payloadLength;
|
|
@@ -96,31 +99,52 @@ library BodyPartCodec {
|
|
|
96
99
|
|
|
97
100
|
/// @notice Decodes a `Members` body part to extract the member count.
|
|
98
101
|
/// @param bodyPart The `BodyPart` struct to decode, which must be of type `Members`.
|
|
99
|
-
/// @return
|
|
102
|
+
/// @return params A `MembersParams` struct containing the member count encoded in the body part's payload.
|
|
100
103
|
function asMembers(
|
|
101
104
|
BodyPart memory bodyPart
|
|
102
|
-
) internal pure returns (
|
|
103
|
-
|
|
104
|
-
revert InvalidBodyPartType(uint8(bodyPart.bodyPartType));
|
|
105
|
-
}
|
|
105
|
+
) internal pure returns (MembersParams memory params) {
|
|
106
|
+
_assertVariant(bodyPart, BodyPartVariant.Members);
|
|
106
107
|
(uint256 decodedCount, ) = Compact.decode(bodyPart.payload);
|
|
107
|
-
count =
|
|
108
|
+
params.count = UnsignedUtils.toU32(decodedCount);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/// @notice Decodes a `Fraction` body part to extract the nominator and denominator.
|
|
112
|
+
/// @param bodyPart The `BodyPart` struct to decode, which must be of type `Fraction`.
|
|
113
|
+
/// @return params A `FractionParams` struct containing the nominator and denominator encoded in the body part's payload.
|
|
114
|
+
function asFraction(
|
|
115
|
+
BodyPart memory bodyPart
|
|
116
|
+
) internal pure returns (FractionParams memory params) {
|
|
117
|
+
_assertVariant(bodyPart, BodyPartVariant.Fraction);
|
|
118
|
+
(params.nominator, params.denominator) = _asProportion(bodyPart);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// @notice Decodes a `AtLeastProportion` body part to extract the nominator and denominator.
|
|
122
|
+
/// @param bodyPart The `BodyPart` struct to decode, which must be of type `AtLeastProportion`.
|
|
123
|
+
/// @return params An `AtLeastProportionParams` struct containing the nominator and denominator encoded in the body part's payload.
|
|
124
|
+
function asAtLeastProportion(
|
|
125
|
+
BodyPart memory bodyPart
|
|
126
|
+
) internal pure returns (AtLeastProportionParams memory params) {
|
|
127
|
+
_assertVariant(bodyPart, BodyPartVariant.AtLeastProportion);
|
|
128
|
+
(params.nominator, params.denominator) = _asProportion(bodyPart);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// @notice Decodes a `MoreThanProportion` body part to extract the nominator and denominator.
|
|
132
|
+
/// @param bodyPart The `BodyPart` struct to decode, which must be of type `MoreThanProportion`.
|
|
133
|
+
/// @return params A `MoreThanProportionParams` struct containing the nominator and denominator encoded in the body part's payload.
|
|
134
|
+
function asMoreThanProportion(
|
|
135
|
+
BodyPart memory bodyPart
|
|
136
|
+
) internal pure returns (MoreThanProportionParams memory params) {
|
|
137
|
+
_assertVariant(bodyPart, BodyPartVariant.MoreThanProportion);
|
|
138
|
+
(params.nominator, params.denominator) = _asProportion(bodyPart);
|
|
108
139
|
}
|
|
109
140
|
|
|
110
141
|
/// @notice Decodes a `Fraction`, `AtLeastProportion`, or `MoreThanProportion` body part to extract the nominator and denominator.
|
|
111
142
|
/// @param bodyPart The `BodyPart` struct to decode, which must be of type `Fraction`, `AtLeastProportion`, or `MoreThanProportion`.
|
|
112
143
|
/// @return nominator The numerator of the proportion encoded in the body part's payload.
|
|
113
144
|
/// @return denominator The denominator of the proportion encoded in the body part's payload.
|
|
114
|
-
function
|
|
145
|
+
function _asProportion(
|
|
115
146
|
BodyPart memory bodyPart
|
|
116
|
-
)
|
|
117
|
-
if (
|
|
118
|
-
bodyPart.bodyPartType != BodyPartType.Fraction &&
|
|
119
|
-
bodyPart.bodyPartType != BodyPartType.AtLeastProportion &&
|
|
120
|
-
bodyPart.bodyPartType != BodyPartType.MoreThanProportion
|
|
121
|
-
) {
|
|
122
|
-
revert InvalidBodyPartType(uint8(bodyPart.bodyPartType));
|
|
123
|
-
}
|
|
147
|
+
) private pure returns (uint32 nominator, uint32 denominator) {
|
|
124
148
|
(uint256 decodedNominator, uint256 offset) = Compact.decode(
|
|
125
149
|
bodyPart.payload
|
|
126
150
|
);
|
|
@@ -128,7 +152,16 @@ library BodyPartCodec {
|
|
|
128
152
|
bodyPart.payload,
|
|
129
153
|
offset
|
|
130
154
|
);
|
|
131
|
-
nominator =
|
|
132
|
-
denominator =
|
|
155
|
+
nominator = UnsignedUtils.toU32(decodedNominator);
|
|
156
|
+
denominator = UnsignedUtils.toU32(decodedDenominator);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function _assertVariant(
|
|
160
|
+
BodyPart memory bodyPart,
|
|
161
|
+
BodyPartVariant expected
|
|
162
|
+
) internal pure {
|
|
163
|
+
if (bodyPart.variant != expected) {
|
|
164
|
+
revert InvalidBodyPartVariant(uint8(bodyPart.variant));
|
|
165
|
+
}
|
|
133
166
|
}
|
|
134
167
|
}
|
package/src/Xcm/v5/Constants.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
pragma solidity ^0.8.28;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {HintVariant} from "./Hint/Hint.sol";
|
|
5
5
|
|
|
6
6
|
// Maximum number of items we expect in a single Assets value.
|
|
7
7
|
uint64 constant MAX_ITEMS_IN_ASSETS = 20;
|
|
@@ -12,4 +12,4 @@ uint32 constant MAX_ASSET_TRANSFER_FILTERS = 6;
|
|
|
12
12
|
// Maximum length of a pallet name in bytes.
|
|
13
13
|
uint32 constant MAX_PALLET_NAME_LEN = 48;
|
|
14
14
|
// Maximum number of hints in a `SetHints` instruction, equal to the number of variants in the `Hint` enum.
|
|
15
|
-
uint32 constant HINT_NUM_VARIANTS = uint32(type(
|
|
15
|
+
uint32 constant HINT_NUM_VARIANTS = uint32(type(HintVariant).max) + 1;
|
|
@@ -6,7 +6,7 @@ import {AssetInstance} from "../AssetInstance/AssetInstance.sol";
|
|
|
6
6
|
import {AssetInstanceCodec} from "../AssetInstance/AssetInstanceCodec.sol";
|
|
7
7
|
|
|
8
8
|
/// @dev Discriminant for the different types of Fungibility in XCM v5.
|
|
9
|
-
enum
|
|
9
|
+
enum FungibilityVariant {
|
|
10
10
|
/// @custom:variant A fungible asset; we record a number of units, as a `uint128` in the inner item.
|
|
11
11
|
Fungible,
|
|
12
12
|
/// @custom:variant A non-fungible asset. We record the instance identifier in the inner item. Only one asset of each instance identifier may ever be in existence at once.
|
|
@@ -15,9 +15,9 @@ enum FungibilityType {
|
|
|
15
15
|
|
|
16
16
|
/// @notice Classification of whether an asset is fungible or not, along with a mandatory amount or instance.
|
|
17
17
|
struct Fungibility {
|
|
18
|
-
/// @custom:property The type of fungibility, determining how to interpret the payload. See `
|
|
19
|
-
|
|
20
|
-
/// @custom:property The encoded payload containing the fungibility data, whose structure depends on the `
|
|
18
|
+
/// @custom:property The type of fungibility, determining how to interpret the payload. See `FungibilityVariant` enum for possible values.
|
|
19
|
+
FungibilityVariant variant;
|
|
20
|
+
/// @custom:property The encoded payload containing the fungibility data, whose structure depends on the `variant`.
|
|
21
21
|
bytes payload;
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -42,7 +42,7 @@ function fungible(
|
|
|
42
42
|
) pure returns (Fungibility memory) {
|
|
43
43
|
return
|
|
44
44
|
Fungibility({
|
|
45
|
-
|
|
45
|
+
variant: FungibilityVariant.Fungible,
|
|
46
46
|
payload: Compact.encode(params.amount)
|
|
47
47
|
});
|
|
48
48
|
}
|
|
@@ -54,7 +54,7 @@ function nonFungible(
|
|
|
54
54
|
) pure returns (Fungibility memory) {
|
|
55
55
|
return
|
|
56
56
|
Fungibility({
|
|
57
|
-
|
|
57
|
+
variant: FungibilityVariant.NonFungible,
|
|
58
58
|
payload: AssetInstanceCodec.encode(params.instance)
|
|
59
59
|
});
|
|
60
60
|
}
|
|
@@ -4,7 +4,14 @@ pragma solidity ^0.8.28;
|
|
|
4
4
|
import {Compact} from "../../../Scale/Compact.sol";
|
|
5
5
|
import {AssetInstance} from "../AssetInstance/AssetInstance.sol";
|
|
6
6
|
import {AssetInstanceCodec} from "../AssetInstance/AssetInstanceCodec.sol";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
Fungibility,
|
|
9
|
+
FungibilityVariant,
|
|
10
|
+
FungibleParams,
|
|
11
|
+
NonFungibleParams
|
|
12
|
+
} from "./Fungibility.sol";
|
|
13
|
+
import {BytesUtils} from "../../../Utils/BytesUtils.sol";
|
|
14
|
+
import {UnsignedUtils} from "../../../Utils/UnsignedUtils.sol";
|
|
8
15
|
|
|
9
16
|
/// @title SCALE Codec for XCM v5 `Fungibility`
|
|
10
17
|
/// @notice SCALE-compliant encoder/decoder for the `Fungibility` type.
|
|
@@ -12,8 +19,7 @@ import {Fungibility, FungibilityType} from "./Fungibility.sol";
|
|
|
12
19
|
/// @dev XCM v5 reference: https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/index.html
|
|
13
20
|
library FungibilityCodec {
|
|
14
21
|
error InvalidFungibilityLength();
|
|
15
|
-
error
|
|
16
|
-
error InvalidFungibilityPayload();
|
|
22
|
+
error InvalidFungibilityVariant(uint8 variant);
|
|
17
23
|
|
|
18
24
|
/// @notice Encodes a `Fungibility` struct into bytes.
|
|
19
25
|
/// @param fungibility The `Fungibility` struct to encode.
|
|
@@ -21,7 +27,8 @@ library FungibilityCodec {
|
|
|
21
27
|
function encode(
|
|
22
28
|
Fungibility memory fungibility
|
|
23
29
|
) internal pure returns (bytes memory) {
|
|
24
|
-
return
|
|
30
|
+
return
|
|
31
|
+
abi.encodePacked(uint8(fungibility.variant), fungibility.payload);
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
/// @notice Returns the number of bytes that a `Fungibility` struct would occupy when SCALE-encoded, starting at a given offset in the data.
|
|
@@ -35,15 +42,15 @@ library FungibilityCodec {
|
|
|
35
42
|
if (data.length < offset + 1) {
|
|
36
43
|
revert InvalidFungibilityLength();
|
|
37
44
|
}
|
|
38
|
-
uint8
|
|
45
|
+
uint8 variant = uint8(data[offset]);
|
|
39
46
|
uint256 payloadLength;
|
|
40
47
|
++offset;
|
|
41
|
-
if (
|
|
48
|
+
if (variant == uint8(FungibilityVariant.Fungible)) {
|
|
42
49
|
payloadLength = Compact.encodedSizeAt(data, offset);
|
|
43
|
-
} else if (
|
|
50
|
+
} else if (variant == uint8(FungibilityVariant.NonFungible)) {
|
|
44
51
|
payloadLength = AssetInstanceCodec.encodedSizeAt(data, offset);
|
|
45
52
|
} else {
|
|
46
|
-
revert
|
|
53
|
+
revert InvalidFungibilityVariant(variant);
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
if (data.length < offset + payloadLength) {
|
|
@@ -80,49 +87,46 @@ library FungibilityCodec {
|
|
|
80
87
|
pure
|
|
81
88
|
returns (Fungibility memory fungibility, uint256 bytesRead)
|
|
82
89
|
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
uint8 fType = uint8(data[offset]);
|
|
87
|
-
uint256 payloadLength = encodedSizeAt(data, offset) - 1; // subtract 1 byte for the fType
|
|
88
|
-
bytes memory payload = new bytes(payloadLength);
|
|
89
|
-
for (uint256 i = 0; i < payloadLength; i++) {
|
|
90
|
-
payload[i] = data[offset + 1 + i];
|
|
91
|
-
}
|
|
90
|
+
uint256 payloadLength = encodedSizeAt(data, offset) - 1; // subtract 1 byte for the variant
|
|
91
|
+
uint8 variant = uint8(data[offset]);
|
|
92
|
+
bytes memory payload = BytesUtils.copy(data, offset + 1, payloadLength);
|
|
92
93
|
|
|
93
94
|
return (
|
|
94
|
-
Fungibility({
|
|
95
|
+
Fungibility({
|
|
96
|
+
variant: FungibilityVariant(variant),
|
|
97
|
+
payload: payload
|
|
98
|
+
}),
|
|
95
99
|
1 + payloadLength
|
|
96
100
|
);
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
/// @notice Decodes a `Fungibility` struct representing a fungible asset and extracts the amount.
|
|
100
|
-
/// @param fungibility The `Fungibility` struct to decode, which must have `
|
|
101
|
-
/// @return
|
|
104
|
+
/// @param fungibility The `Fungibility` struct to decode, which must have `variant` equal to `FungibilityVariant.Fungible`.
|
|
105
|
+
/// @return params A `FungibleParams` struct containing the amount of the fungible asset.
|
|
102
106
|
function asFungible(
|
|
103
107
|
Fungibility memory fungibility
|
|
104
|
-
) internal pure returns (
|
|
105
|
-
|
|
106
|
-
revert InvalidFungibilityType(uint8(fungibility.fType));
|
|
107
|
-
}
|
|
108
|
+
) internal pure returns (FungibleParams memory params) {
|
|
109
|
+
_assertVariant(fungibility, FungibilityVariant.Fungible);
|
|
108
110
|
(uint256 decodedAmount, ) = Compact.decode(fungibility.payload);
|
|
109
|
-
|
|
110
|
-
revert InvalidFungibilityPayload();
|
|
111
|
-
}
|
|
112
|
-
unchecked {
|
|
113
|
-
amount = uint128(decodedAmount);
|
|
114
|
-
}
|
|
111
|
+
params.amount = UnsignedUtils.toU128(decodedAmount);
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
/// @notice Decodes a `Fungibility` struct representing a non-fungible asset and extracts the instance identifier.
|
|
118
|
-
/// @param fungibility The `Fungibility` struct to decode, which must have `
|
|
119
|
-
/// @return
|
|
115
|
+
/// @param fungibility The `Fungibility` struct to decode, which must have `variant` equal to `FungibilityVariant.NonFungible`.
|
|
116
|
+
/// @return params A `NonFungibleParams` struct containing the specific non-fungible asset instance.
|
|
120
117
|
function asNonFungible(
|
|
121
118
|
Fungibility memory fungibility
|
|
122
|
-
) internal pure returns (
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
) internal pure returns (NonFungibleParams memory params) {
|
|
120
|
+
_assertVariant(fungibility, FungibilityVariant.NonFungible);
|
|
121
|
+
(params.instance, ) = AssetInstanceCodec.decode(fungibility.payload);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function _assertVariant(
|
|
125
|
+
Fungibility memory fungibility,
|
|
126
|
+
FungibilityVariant expected
|
|
127
|
+
) private pure {
|
|
128
|
+
if (fungibility.variant != expected) {
|
|
129
|
+
revert InvalidFungibilityVariant(uint8(fungibility.variant));
|
|
125
130
|
}
|
|
126
|
-
(instance, ) = AssetInstanceCodec.decode(fungibility.payload);
|
|
127
131
|
}
|
|
128
132
|
}
|