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