solidity-scale-codec 0.1.3 → 0.3.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 +25 -0
- package/DEFINITIONS.md +132 -0
- package/README.md +97 -1
- package/package.json +16 -4
- 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,53 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
/// @title Scale Codec for the `bytes8` type.
|
|
5
|
+
/// @notice SCALE-compliant encoder/decoder for the `bytes8` type.
|
|
6
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
7
|
+
library Bytes8 {
|
|
8
|
+
error InvalidBytes8Length();
|
|
9
|
+
|
|
10
|
+
/// @notice Encodes an `bytes8` into SCALE format.
|
|
11
|
+
/// @param value The `bytes8` to encode.
|
|
12
|
+
/// @return SCALE-encoded byte sequence.
|
|
13
|
+
function encode(bytes8 value) internal pure returns (bytes memory) {
|
|
14
|
+
return abi.encodePacked(value);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// @notice Returns the number of bytes that a `bytes8` would occupy when SCALE-encoded.
|
|
18
|
+
/// @param data The byte sequence containing the encoded `bytes8`.
|
|
19
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `bytes8`.
|
|
20
|
+
/// @return The number of bytes that the `bytes8` would occupy when SCALE-encoded.
|
|
21
|
+
function encodedSizeAt(
|
|
22
|
+
bytes memory data,
|
|
23
|
+
uint256 offset
|
|
24
|
+
) internal pure returns (uint256) {
|
|
25
|
+
if (data.length < offset + 8) {
|
|
26
|
+
revert InvalidBytes8Length();
|
|
27
|
+
}
|
|
28
|
+
return 8;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// @notice Decodes SCALE-encoded bytes into an `bytes8`.
|
|
32
|
+
/// @param data The SCALE-encoded byte sequence.
|
|
33
|
+
/// @return The decoded `bytes8`.
|
|
34
|
+
function decode(bytes memory data) internal pure returns (bytes8) {
|
|
35
|
+
return decodeAt(data, 0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// @notice Decodes an `bytes8` from SCALE format at the specified offset.
|
|
39
|
+
/// @param data The SCALE-encoded byte sequence.
|
|
40
|
+
/// @param offset The byte offset to start decoding from.
|
|
41
|
+
/// @return value The decoded `bytes8`.
|
|
42
|
+
function decodeAt(
|
|
43
|
+
bytes memory data,
|
|
44
|
+
uint256 offset
|
|
45
|
+
) internal pure returns (bytes8 value) {
|
|
46
|
+
if (data.length < offset + 8) {
|
|
47
|
+
revert InvalidBytes8Length();
|
|
48
|
+
}
|
|
49
|
+
assembly {
|
|
50
|
+
value := mload(add(add(data, 32), offset))
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Bytes2} from "./Bytes/Bytes2.sol";
|
|
5
|
+
import {Bytes4} from "./Bytes/Bytes4.sol";
|
|
6
|
+
import {Bytes8} from "./Bytes/Bytes8.sol";
|
|
7
|
+
import {Bytes16} from "./Bytes/Bytes16.sol";
|
|
8
|
+
import {Bytes32} from "./Bytes/Bytes32.sol";
|
|
@@ -43,6 +43,35 @@ library Compact {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/// @notice Returns the number of bytes that the Compact-encoded value at the given offset occupies
|
|
47
|
+
/// @param data The byte sequence containing the Compact-encoded value
|
|
48
|
+
/// @param offset The byte offset to start reading from
|
|
49
|
+
/// @return size The total number of bytes occupied by the Compact-encoded value, including the header byte
|
|
50
|
+
/// @dev Reverts if the offset is out of bounds or if the header byte indicates an invalid encoding mode
|
|
51
|
+
function encodedSizeAt(
|
|
52
|
+
bytes memory data,
|
|
53
|
+
uint256 offset
|
|
54
|
+
) internal pure returns (uint256 size) {
|
|
55
|
+
if (offset >= data.length) revert OffsetOutOfBounds();
|
|
56
|
+
uint8 header;
|
|
57
|
+
assembly {
|
|
58
|
+
header := shr(248, mload(add(add(data, 32), offset)))
|
|
59
|
+
}
|
|
60
|
+
uint8 mode = header & 0x03;
|
|
61
|
+
if (mode == MODE_SINGLE) {
|
|
62
|
+
size = 1;
|
|
63
|
+
} else if (mode == MODE_TWO) {
|
|
64
|
+
size = 2;
|
|
65
|
+
} else if (mode == MODE_FOUR) {
|
|
66
|
+
size = 4;
|
|
67
|
+
} else {
|
|
68
|
+
uint8 m = (header >> 2) + 4;
|
|
69
|
+
size = 1 + m;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (data.length < offset + size) revert OffsetOutOfBounds();
|
|
73
|
+
}
|
|
74
|
+
|
|
46
75
|
///@notice Decodes a uint256 value from SCALE Compact format
|
|
47
76
|
/// @dev Reverts if the encoding is invalid or non-canonical, or if the decoded value exceeds uint256 range
|
|
48
77
|
/// @param data The Compact-encoded byte sequence
|
|
@@ -74,15 +103,20 @@ library Compact {
|
|
|
74
103
|
value = uint256(header) >> 2;
|
|
75
104
|
bytesRead = 1;
|
|
76
105
|
} else if (mode == MODE_TWO) {
|
|
77
|
-
|
|
106
|
+
if (data.length < offset + 2) revert OffsetOutOfBounds();
|
|
107
|
+
value =
|
|
108
|
+
uint256(LittleEndianU16.fromLittleEndian(data, offset)) >> 2;
|
|
78
109
|
bytesRead = 2;
|
|
79
110
|
} else if (mode == MODE_FOUR) {
|
|
80
|
-
|
|
111
|
+
if (data.length < offset + 4) revert OffsetOutOfBounds();
|
|
112
|
+
value =
|
|
113
|
+
uint256(LittleEndianU32.fromLittleEndian(data, offset)) >> 2;
|
|
81
114
|
bytesRead = 4;
|
|
82
115
|
} else {
|
|
83
116
|
uint8 m = (header >> 2) + 4;
|
|
84
117
|
if (m > 32) revert ValueOutOfRange();
|
|
85
|
-
|
|
118
|
+
if (data.length < offset + 1 + m) revert OffsetOutOfBounds();
|
|
119
|
+
value = LittleEndianU256.fromLittleEndian(data, offset + 1);
|
|
86
120
|
if (m < 32) {
|
|
87
121
|
value &= (uint256(1) << (uint256(m) * 8)) - 1; // zero out bytes beyond m
|
|
88
122
|
}
|
|
@@ -16,6 +16,17 @@ library I128 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `int128` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `int128`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int128`.
|
|
22
|
+
/// @return The number of bytes that the `int128` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
return U128.encodedSizeAt(data, offset);
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
/// @notice Decodes SCALE-encoded bytes into an `int128`.
|
|
20
31
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
32
|
/// @return The decoded `int128`.
|
package/src/Scale/Signed/I16.sol
CHANGED
|
@@ -16,6 +16,17 @@ library I16 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `int16` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `int16`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int16`.
|
|
22
|
+
/// @return The number of bytes that the `int16` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
return U16.encodedSizeAt(data, offset);
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
/// @notice Decodes SCALE-encoded bytes into an `int16`.
|
|
20
31
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
32
|
/// @return The decoded `int16`.
|
|
@@ -16,6 +16,17 @@ library I256 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `int256` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `int256`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int256`.
|
|
22
|
+
/// @return The number of bytes that the `int256` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
return U256.encodedSizeAt(data, offset);
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
/// @notice Decodes SCALE-encoded bytes into an `int256`.
|
|
20
31
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
32
|
/// @return The decoded `int256`.
|
package/src/Scale/Signed/I32.sol
CHANGED
|
@@ -16,6 +16,17 @@ library I32 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `int32` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `int32`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int32`.
|
|
22
|
+
/// @return The number of bytes that the `int32` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
return U32.encodedSizeAt(data, offset);
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
/// @notice Decodes SCALE-encoded bytes into an `int32`.
|
|
20
31
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
32
|
/// @return The decoded `int32`.
|
package/src/Scale/Signed/I64.sol
CHANGED
|
@@ -16,6 +16,17 @@ library I64 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `int64` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `int64`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int64`.
|
|
22
|
+
/// @return The number of bytes that the `int64` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
return U64.encodedSizeAt(data, offset);
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
/// @notice Decodes SCALE-encoded bytes into an `int64`.
|
|
20
31
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
32
|
/// @return The decoded `int64`.
|
package/src/Scale/Signed/I8.sol
CHANGED
|
@@ -16,6 +16,17 @@ library I8 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `int8` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `int8`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int8`.
|
|
22
|
+
/// @return The number of bytes that the `int8` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
return U8.encodedSizeAt(data, offset);
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
/// @notice Decodes SCALE-encoded bytes into an `int8`.
|
|
20
31
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
32
|
/// @return The decoded `int8`.
|
|
@@ -16,6 +16,20 @@ library U128 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `uint128` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `uint128`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `uint128`.
|
|
22
|
+
/// @return The number of bytes that the `uint128` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
if (data.length < offset + 16) {
|
|
28
|
+
revert InvalidU128Length();
|
|
29
|
+
}
|
|
30
|
+
return 16;
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
/// @notice Decodes SCALE-encoded bytes into an `uint128`.
|
|
20
34
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
35
|
/// @return The decoded `uint128`.
|
|
@@ -32,7 +46,7 @@ library U128 {
|
|
|
32
46
|
uint256 offset
|
|
33
47
|
) internal pure returns (uint128 value) {
|
|
34
48
|
if (data.length < offset + 16) revert InvalidU128Length();
|
|
35
|
-
return LittleEndianU128.
|
|
49
|
+
return LittleEndianU128.fromLittleEndian(data, offset);
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
/// @notice Converts an `uint128` to little-endian bytes16
|
|
@@ -41,6 +55,6 @@ library U128 {
|
|
|
41
55
|
function toLittleEndian(
|
|
42
56
|
uint128 value
|
|
43
57
|
) internal pure returns (bytes16 result) {
|
|
44
|
-
return LittleEndianU128.
|
|
58
|
+
return LittleEndianU128.toLittleEndian(value);
|
|
45
59
|
}
|
|
46
60
|
}
|
|
@@ -16,6 +16,20 @@ library U16 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `uint16` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `uint16`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `uint16`.
|
|
22
|
+
/// @return The number of bytes that the `uint16` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
if (data.length < offset + 2) {
|
|
28
|
+
revert InvalidU16Length();
|
|
29
|
+
}
|
|
30
|
+
return 2;
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
/// @notice Decodes SCALE-encoded bytes into an `uint16`.
|
|
20
34
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
35
|
/// @return The decoded `uint16`.
|
|
@@ -32,7 +46,7 @@ library U16 {
|
|
|
32
46
|
uint256 offset
|
|
33
47
|
) internal pure returns (uint16 value) {
|
|
34
48
|
if (data.length < offset + 2) revert InvalidU16Length();
|
|
35
|
-
return LittleEndianU16.
|
|
49
|
+
return LittleEndianU16.fromLittleEndian(data, offset);
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
/// @notice Converts an `uint16` to little-endian bytes2
|
|
@@ -41,6 +55,6 @@ library U16 {
|
|
|
41
55
|
function toLittleEndian(
|
|
42
56
|
uint16 value
|
|
43
57
|
) internal pure returns (bytes2 result) {
|
|
44
|
-
return LittleEndianU16.
|
|
58
|
+
return LittleEndianU16.toLittleEndian(value);
|
|
45
59
|
}
|
|
46
60
|
}
|
|
@@ -16,6 +16,20 @@ library U256 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `uint256` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `uint256`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `uint256`.
|
|
22
|
+
/// @return The number of bytes that the `uint256` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
if (data.length < offset + 32) {
|
|
28
|
+
revert InvalidU256Length();
|
|
29
|
+
}
|
|
30
|
+
return 32;
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
/// @notice Decodes SCALE-encoded bytes into an `uint256`.
|
|
20
34
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
35
|
/// @return The decoded `uint256`.
|
|
@@ -32,7 +46,7 @@ library U256 {
|
|
|
32
46
|
uint256 offset
|
|
33
47
|
) internal pure returns (uint256 value) {
|
|
34
48
|
if (data.length < offset + 32) revert InvalidU256Length();
|
|
35
|
-
return LittleEndianU256.
|
|
49
|
+
return LittleEndianU256.fromLittleEndian(data, offset);
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
/// @notice Converts an `uint256` to little-endian bytes32
|
|
@@ -41,6 +55,6 @@ library U256 {
|
|
|
41
55
|
function toLittleEndian(
|
|
42
56
|
uint256 value
|
|
43
57
|
) internal pure returns (bytes32 result) {
|
|
44
|
-
return LittleEndianU256.
|
|
58
|
+
return LittleEndianU256.toLittleEndian(value);
|
|
45
59
|
}
|
|
46
60
|
}
|
|
@@ -16,6 +16,20 @@ library U32 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `uint32` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `uint32`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `uint32`.
|
|
22
|
+
/// @return The number of bytes that the `uint32` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
if (data.length < offset + 4) {
|
|
28
|
+
revert InvalidU32Length();
|
|
29
|
+
}
|
|
30
|
+
return 4;
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
/// @notice Decodes SCALE-encoded bytes into an `uint32`.
|
|
20
34
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
35
|
/// @return The decoded `uint32`.
|
|
@@ -32,7 +46,7 @@ library U32 {
|
|
|
32
46
|
uint256 offset
|
|
33
47
|
) internal pure returns (uint32 value) {
|
|
34
48
|
if (data.length < offset + 4) revert InvalidU32Length();
|
|
35
|
-
return LittleEndianU32.
|
|
49
|
+
return LittleEndianU32.fromLittleEndian(data, offset);
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
/// @notice Converts an `uint32` to little-endian bytes4
|
|
@@ -41,6 +55,6 @@ library U32 {
|
|
|
41
55
|
function toLittleEndian(
|
|
42
56
|
uint32 value
|
|
43
57
|
) internal pure returns (bytes4 result) {
|
|
44
|
-
return LittleEndianU32.
|
|
58
|
+
return LittleEndianU32.toLittleEndian(value);
|
|
45
59
|
}
|
|
46
60
|
}
|
|
@@ -16,6 +16,20 @@ library U64 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `uint64` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `uint64`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `uint64`.
|
|
22
|
+
/// @return The number of bytes that the `uint64` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
if (data.length < offset + 8) {
|
|
28
|
+
revert InvalidU64Length();
|
|
29
|
+
}
|
|
30
|
+
return 8;
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
/// @notice Decodes SCALE-encoded bytes into an `uint64`.
|
|
20
34
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
35
|
/// @return The decoded `uint64`.
|
|
@@ -32,7 +46,7 @@ library U64 {
|
|
|
32
46
|
uint256 offset
|
|
33
47
|
) internal pure returns (uint64 value) {
|
|
34
48
|
if (data.length < offset + 8) revert InvalidU64Length();
|
|
35
|
-
return LittleEndianU64.
|
|
49
|
+
return LittleEndianU64.fromLittleEndian(data, offset);
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
/// @notice Converts an `uint64` to little-endian bytes8
|
|
@@ -41,6 +55,6 @@ library U64 {
|
|
|
41
55
|
function toLittleEndian(
|
|
42
56
|
uint64 value
|
|
43
57
|
) internal pure returns (bytes8 result) {
|
|
44
|
-
return LittleEndianU64.
|
|
58
|
+
return LittleEndianU64.toLittleEndian(value);
|
|
45
59
|
}
|
|
46
60
|
}
|
|
@@ -16,6 +16,20 @@ library U8 {
|
|
|
16
16
|
return abi.encodePacked(toLittleEndian(value));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/// @notice Returns the number of bytes that a `uint8` would occupy when SCALE-encoded.
|
|
20
|
+
/// @param data The byte sequence containing the encoded `uint8`.
|
|
21
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `uint8`.
|
|
22
|
+
/// @return The number of bytes that the `uint8` would occupy when SCALE-encoded.
|
|
23
|
+
function encodedSizeAt(
|
|
24
|
+
bytes memory data,
|
|
25
|
+
uint256 offset
|
|
26
|
+
) internal pure returns (uint256) {
|
|
27
|
+
if (data.length < offset + 1) {
|
|
28
|
+
revert InvalidU8Length();
|
|
29
|
+
}
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
/// @notice Decodes SCALE-encoded bytes into an `uint8`.
|
|
20
34
|
/// @param data The SCALE-encoded byte sequence.
|
|
21
35
|
/// @return The decoded `uint8`.
|
|
@@ -32,13 +46,13 @@ library U8 {
|
|
|
32
46
|
uint256 offset
|
|
33
47
|
) internal pure returns (uint8 value) {
|
|
34
48
|
if (data.length < offset + 1) revert InvalidU8Length();
|
|
35
|
-
return LittleEndianU8.
|
|
49
|
+
return LittleEndianU8.fromLittleEndian(data, offset);
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
/// @notice Converts an `uint8` to little-endian bytes1
|
|
39
53
|
/// @param value The unsigned 8-bit integer to convert.
|
|
40
54
|
/// @return result Little-endian byte representation of the input value.
|
|
41
55
|
function toLittleEndian(uint8 value) internal pure returns (bytes1 result) {
|
|
42
|
-
return LittleEndianU8.
|
|
56
|
+
return LittleEndianU8.toLittleEndian(value);
|
|
43
57
|
}
|
|
44
58
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {Xcm as XcmV5} from "../v5/Xcm/Xcm.sol";
|
|
5
|
+
import {XcmCodec as XcmV5Codec} from "../v5/Xcm/XcmCodec.sol";
|
|
6
|
+
|
|
7
|
+
/// @notice The XCM versions supported by this package.
|
|
8
|
+
enum XcmVersion {
|
|
9
|
+
_unsupported_V2,
|
|
10
|
+
_unsupported_V3,
|
|
11
|
+
V5
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/// @notice A single XCM message, together with its version code.
|
|
15
|
+
struct VersionedXcm {
|
|
16
|
+
/// @custom:property The version of the XCM message.
|
|
17
|
+
XcmVersion version;
|
|
18
|
+
/// @custom:property The XCM message, encoded according to its version.
|
|
19
|
+
bytes xcm;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// @notice Creates a `VersionedXcm` with version `V5` from an `XcmV5` struct.
|
|
23
|
+
/// @param xcm The `XcmV5` struct to wrap.
|
|
24
|
+
/// @return A `VersionedXcm` with version `V5` and the ABI-encoded `xcm` as its payload.
|
|
25
|
+
function v5(XcmV5 memory xcm) pure returns (VersionedXcm memory) {
|
|
26
|
+
return VersionedXcm({version: XcmVersion.V5, xcm: XcmV5Codec.encode(xcm)});
|
|
27
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {VersionedXcm, XcmVersion} from "./VersionedXcm.sol";
|
|
5
|
+
import {Xcm as XcmV5} from "../v5/Xcm/Xcm.sol";
|
|
6
|
+
import {XcmCodec as XcmV5Codec} from "../v5/Xcm/XcmCodec.sol";
|
|
7
|
+
|
|
8
|
+
library VersionedXcmCodec {
|
|
9
|
+
error InvalidVersionedXcmLength();
|
|
10
|
+
error UnsupportedXcmVersion(XcmVersion version);
|
|
11
|
+
|
|
12
|
+
/// @notice Encodes a `VersionedXcm` into bytes, using the appropriate encoding for its version.
|
|
13
|
+
/// @param versionedXcm The `VersionedXcm` to encode.
|
|
14
|
+
/// @return The encoded bytes of the `VersionedXcm`.
|
|
15
|
+
function encode(
|
|
16
|
+
VersionedXcm memory versionedXcm
|
|
17
|
+
) internal pure returns (bytes memory) {
|
|
18
|
+
if (versionedXcm.version == XcmVersion.V5) {
|
|
19
|
+
return
|
|
20
|
+
abi.encodePacked(uint8(versionedXcm.version), versionedXcm.xcm);
|
|
21
|
+
} else {
|
|
22
|
+
revert UnsupportedXcmVersion(versionedXcm.version);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// @notice Decodes a `VersionedXcm` from bytes, using the appropriate decoding for its version.
|
|
27
|
+
/// @param data The byte sequence containing the encoded `VersionedXcm`.
|
|
28
|
+
/// @return versionedXcm The decoded `VersionedXcm` struct.
|
|
29
|
+
/// @return bytesRead The number of bytes read from `data` to decode the `VersionedXcm`.
|
|
30
|
+
function decode(
|
|
31
|
+
bytes memory data
|
|
32
|
+
)
|
|
33
|
+
internal
|
|
34
|
+
pure
|
|
35
|
+
returns (VersionedXcm memory versionedXcm, uint256 bytesRead)
|
|
36
|
+
{
|
|
37
|
+
return decodeAt(data, 0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// @notice Decodes a `VersionedXcm` from bytes starting at a given offset, using the appropriate decoding for its version.
|
|
41
|
+
/// @param data The byte sequence containing the encoded `VersionedXcm`.
|
|
42
|
+
/// @param offset The starting index in `data` from which to decode the `VersionedXcm`.
|
|
43
|
+
/// @return versionedXcm The decoded `VersionedXcm` struct.
|
|
44
|
+
/// @return bytesRead The number of bytes read from `data` to decode the `VersionedXcm`.
|
|
45
|
+
function decodeAt(
|
|
46
|
+
bytes memory data,
|
|
47
|
+
uint256 offset
|
|
48
|
+
)
|
|
49
|
+
internal
|
|
50
|
+
pure
|
|
51
|
+
returns (VersionedXcm memory versionedXcm, uint256 bytesRead)
|
|
52
|
+
{
|
|
53
|
+
if (data.length < offset + 1) revert InvalidVersionedXcmLength();
|
|
54
|
+
XcmVersion version = XcmVersion(uint8(data[offset]));
|
|
55
|
+
uint256 xcmByteLength;
|
|
56
|
+
bytes memory xcmBytes;
|
|
57
|
+
if (version == XcmVersion.V5) {
|
|
58
|
+
xcmByteLength = XcmV5Codec.encodedSizeAt(data, offset + 1);
|
|
59
|
+
if (data.length < offset + 1 + xcmByteLength)
|
|
60
|
+
revert InvalidVersionedXcmLength();
|
|
61
|
+
xcmBytes = new bytes(xcmByteLength);
|
|
62
|
+
for (uint256 i = 0; i < xcmByteLength; i++)
|
|
63
|
+
xcmBytes[i] = data[offset + 1 + i];
|
|
64
|
+
versionedXcm = VersionedXcm({version: version, xcm: xcmBytes});
|
|
65
|
+
bytesRead = 1 + xcmByteLength;
|
|
66
|
+
} else {
|
|
67
|
+
revert UnsupportedXcmVersion(version);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import {U8Arr} from "../../../Scale/Array.sol";
|
|
5
|
+
import {MAX_DISPATCH_ERROR_LEN} from "../Constants.sol";
|
|
6
|
+
|
|
7
|
+
/// @notice Discriminant for the `MaybeErrorCode` enum.
|
|
8
|
+
enum MaybeErrorCodeType {
|
|
9
|
+
/// @custom:variant No error occurred.
|
|
10
|
+
Success,
|
|
11
|
+
/// @custom:variant An error occurred, containing the dispatch error bytes.
|
|
12
|
+
Error,
|
|
13
|
+
/// @custom:variant An error occurred but the error code was truncated to MAX_DISPATCH_ERROR_LEN bytes.
|
|
14
|
+
TruncatedError
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// @notice The result of a `Transact` dispatch, either success or an error code.
|
|
18
|
+
struct MaybeErrorCode {
|
|
19
|
+
/// @custom:property The type of the result. See `MaybeErrorCodeType` enum for possible values.
|
|
20
|
+
MaybeErrorCodeType meType;
|
|
21
|
+
/// @custom:property The SCALE-encoded dispatch error bytes. Only meaningful when `meType` is `Error` or `TruncatedError`. Max length is MAX_DISPATCH_ERROR_LEN (128 bytes).
|
|
22
|
+
bytes payload;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// @notice Parameters for the `Error` variant.
|
|
26
|
+
struct ErrorParams {
|
|
27
|
+
/// @custom:property Dispatch error bytes.
|
|
28
|
+
uint8[] errorBytes;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// @notice Parameters for the `TruncatedError` variant.
|
|
32
|
+
struct TruncatedErrorParams {
|
|
33
|
+
/// @custom:property Truncated dispatch error bytes.
|
|
34
|
+
uint8[] errorBytes;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ============ Factory Functions ============
|
|
38
|
+
|
|
39
|
+
/// @notice Creates a `Success` MaybeErrorCode.
|
|
40
|
+
/// @return A `MaybeErrorCode` struct representing success.
|
|
41
|
+
function success() pure returns (MaybeErrorCode memory) {
|
|
42
|
+
return MaybeErrorCode({meType: MaybeErrorCodeType.Success, payload: ""});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// @notice Creates an `Error` MaybeErrorCode with the given dispatch error bytes.
|
|
46
|
+
/// @param params Parameters for the error variant.
|
|
47
|
+
/// @return A `MaybeErrorCode` struct representing the error.
|
|
48
|
+
function error(ErrorParams memory params) pure returns (MaybeErrorCode memory) {
|
|
49
|
+
if (params.errorBytes.length > MAX_DISPATCH_ERROR_LEN)
|
|
50
|
+
revert MaybeErrorCodeTooLong(params.errorBytes.length);
|
|
51
|
+
return
|
|
52
|
+
MaybeErrorCode({
|
|
53
|
+
meType: MaybeErrorCodeType.Error,
|
|
54
|
+
payload: U8Arr.encode(params.errorBytes)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// @notice Creates a `TruncatedError` MaybeErrorCode with the given dispatch error bytes.
|
|
59
|
+
/// @param params Parameters for the truncated-error variant.
|
|
60
|
+
/// @return A `MaybeErrorCode` struct representing the truncated error.
|
|
61
|
+
function truncatedError(
|
|
62
|
+
TruncatedErrorParams memory params
|
|
63
|
+
) pure returns (MaybeErrorCode memory) {
|
|
64
|
+
if (params.errorBytes.length > MAX_DISPATCH_ERROR_LEN)
|
|
65
|
+
revert MaybeErrorCodeTooLong(params.errorBytes.length);
|
|
66
|
+
return
|
|
67
|
+
MaybeErrorCode({
|
|
68
|
+
meType: MaybeErrorCodeType.TruncatedError,
|
|
69
|
+
payload: U8Arr.encode(params.errorBytes)
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
error MaybeErrorCodeTooLong(uint256 length);
|