solidity-scale-codec 1.0.0 → 2.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 +16 -0
- package/README.md +10 -28
- package/package.json +2 -2
- package/src/Scale/Bytes.sol +1 -0
- package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCode.sol +5 -5
- package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCodeCodec.sol +34 -13
- package/src/Xcm/v5/PalletInfo/PalletInfo.sol +2 -2
- package/src/Xcm/v5/PalletInfo/PalletInfoCodec.sol +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
[Unreleased]
|
|
9
9
|
|
|
10
|
+
## Version 2.0.0
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add `Bytes.sol` to barrel import - [#2dbc1ab](https://github.com/LucasGrasso/solidity-scale-codec/commit/2dbc1ab)
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Change all `uint8[]` to `bytes` for better ergonomics and consistency with typical byte handling in Solidity. - [#ab6c226](https://github.com/LucasGrasso/solidity-scale-codec/commit/ab6c226)
|
|
19
|
+
|
|
20
|
+
## Version 1.0.1
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- More docs and examples - [#5006d28](https://github.com/LucasGrasso/solidity-scale-codec/commit/5006d28)
|
|
25
|
+
|
|
10
26
|
## Version 1.0.0
|
|
11
27
|
|
|
12
28
|
### Added
|
package/README.md
CHANGED
|
@@ -26,10 +26,16 @@ See the [Definitions](https://lucasgrasso.github.io/solidity-scale-codec/Definit
|
|
|
26
26
|
|
|
27
27
|
## Usage
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Check out the examples section of the documentation for how to use the library to encode and decode different types, and how to build XCM messages in Solidity.
|
|
30
|
+
|
|
31
|
+
### Encode Structs
|
|
30
32
|
|
|
31
33
|
See this [example](https://github.com/LucasGrasso/solidity-scale-codec/blob/main/contracts/examples/Foo.sol).
|
|
32
34
|
|
|
35
|
+
### Encode XCM messages
|
|
36
|
+
|
|
37
|
+
Check out the [Xcm Builder](https://lucasgrasso.github.io/solidity-scale-codec/Xcm/v5/Xcm/XcmBuilder.html) for an ergonomic API to build XCM messages in Solidity, and how you can use it in this [example](https://github.com/LucasGrasso/solidity-scale-codec/blob/main/test/VersionedXcm.t.sol#L120)
|
|
38
|
+
|
|
33
39
|
## About the libraries
|
|
34
40
|
|
|
35
41
|
### src/LittleEndian
|
|
@@ -95,34 +101,9 @@ Implementation notes:
|
|
|
95
101
|
- Enum-like XCM types are represented as structs with a type discriminator plus `bytes payload`.
|
|
96
102
|
- Each type has a codec library with `encode`, `encodedSizeAt`, `decode`, and `decodeAt`.
|
|
97
103
|
- `VersionedXcm` currently supports v5 payloads.
|
|
104
|
+
- The `XcmBuilder` library provides an ergonomic API to build XCM messages in Solidity, with functions for building various XCM instructions.
|
|
98
105
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```solidity
|
|
102
|
-
import {Instruction} from "../src/Xcm/v5/Instruction/Instruction.sol";
|
|
103
|
-
import {Xcm, fromInstructions} from "../src/Xcm/v5/Xcm/Xcm.sol";
|
|
104
|
-
import {v5} from "../src/Xcm/VersionedXcm/VersionedXcm.sol";
|
|
105
|
-
import {VersionedXcmCodec} from "../src/Xcm/VersionedXcm/VersionedXcmCodec.sol";
|
|
106
|
-
import {Weight} from "../src/Xcm/v5/Weight/Weight.sol";
|
|
107
|
-
import {WeightCodec} from "../src/Xcm/v5/Weight/WeightCodec.sol";
|
|
108
|
-
|
|
109
|
-
address constant XCM_PRECOMPILE_ADDRESS = 0x00000000000000000000000000000000000a0000;
|
|
110
|
-
|
|
111
|
-
contract XcmWeightEstimator {
|
|
112
|
-
function weighMessage(
|
|
113
|
-
Instruction[] memory instructions
|
|
114
|
-
) external view returns (Weight memory) {
|
|
115
|
-
Xcm memory xcm = fromInstructions(instructions);
|
|
116
|
-
(bool success, bytes memory result) = XCM_PRECOMPILE_ADDRESS.staticcall(
|
|
117
|
-
VersionedXcmCodec.encode(v5(xcm))
|
|
118
|
-
);
|
|
119
|
-
require(success, "XCM precompile call failed");
|
|
120
|
-
(Weight memory weight, ) = WeightCodec.decode(result);
|
|
121
|
-
return weight;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
```
|
|
106
|
+
````
|
|
126
107
|
|
|
127
108
|
### Running Tests
|
|
128
109
|
|
|
@@ -144,3 +125,4 @@ npx hardhat test nodejs
|
|
|
144
125
|
Copyright 2025 Lucas Grasso
|
|
145
126
|
|
|
146
127
|
This project is licensed under the the [Apache License, Version 2.0](LICENSE).
|
|
128
|
+
````
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solidity-scale-codec",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Solidity implementation of scale-codec.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"solidity",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"hardhat": "^3.0.15",
|
|
48
48
|
"prettier": "^3.8.1",
|
|
49
49
|
"prettier-plugin-solidity": "^2.2.1",
|
|
50
|
-
"solidity-doc-generator": "^1.2.
|
|
50
|
+
"solidity-doc-generator": "^1.2.4",
|
|
51
51
|
"typescript": "~5.8.0",
|
|
52
52
|
"viem": "^2.40.3",
|
|
53
53
|
"vitepress": "^1.6.4",
|
package/src/Scale/Bytes.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 {Bytes} from "../../../Scale/Bytes.sol";
|
|
5
5
|
import {MAX_DISPATCH_ERROR_LEN} from "../Constants.sol";
|
|
6
6
|
|
|
7
7
|
/// @notice Discriminant for the `MaybeErrorCode` enum.
|
|
@@ -25,13 +25,13 @@ struct MaybeErrorCode {
|
|
|
25
25
|
/// @notice Parameters for the `Error` variant.
|
|
26
26
|
struct ErrorParams {
|
|
27
27
|
/// @custom:property Dispatch error bytes.
|
|
28
|
-
|
|
28
|
+
bytes errorBytes;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/// @notice Parameters for the `TruncatedError` variant.
|
|
32
32
|
struct TruncatedErrorParams {
|
|
33
33
|
/// @custom:property Truncated dispatch error bytes.
|
|
34
|
-
|
|
34
|
+
bytes errorBytes;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
// ============ Factory Functions ============
|
|
@@ -52,7 +52,7 @@ function error(ErrorParams memory params) pure returns (MaybeErrorCode memory) {
|
|
|
52
52
|
return
|
|
53
53
|
MaybeErrorCode({
|
|
54
54
|
variant: MaybeErrorCodeVariant.Error,
|
|
55
|
-
payload:
|
|
55
|
+
payload: Bytes.encode(params.errorBytes)
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -67,7 +67,7 @@ function truncatedError(
|
|
|
67
67
|
return
|
|
68
68
|
MaybeErrorCode({
|
|
69
69
|
variant: MaybeErrorCodeVariant.TruncatedError,
|
|
70
|
-
payload:
|
|
70
|
+
payload: Bytes.encode(params.errorBytes)
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
pragma solidity ^0.8.28;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import {Bytes} from "../../../Scale/Bytes.sol";
|
|
5
|
+
import {
|
|
6
|
+
MaybeErrorCode,
|
|
7
|
+
MaybeErrorCodeVariant,
|
|
8
|
+
ErrorParams,
|
|
9
|
+
TruncatedErrorParams
|
|
10
|
+
} from "./MaybeErrorCode.sol";
|
|
6
11
|
import {BytesUtils} from "../../../Utils/BytesUtils.sol";
|
|
7
12
|
|
|
8
13
|
/// @title SCALE Codec for XCM v3 `MaybeErrorCode`
|
|
@@ -38,7 +43,7 @@ library MaybeErrorCodeCodec {
|
|
|
38
43
|
variant == uint8(MaybeErrorCodeVariant.Error) ||
|
|
39
44
|
variant == uint8(MaybeErrorCodeVariant.TruncatedError)
|
|
40
45
|
) {
|
|
41
|
-
return 1 +
|
|
46
|
+
return 1 + Bytes.encodedSizeAt(data, offset + 1);
|
|
42
47
|
} else {
|
|
43
48
|
revert InvalidMaybeErrorCodeVariant(variant);
|
|
44
49
|
}
|
|
@@ -78,16 +83,32 @@ library MaybeErrorCodeCodec {
|
|
|
78
83
|
bytesRead = size;
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
/// @notice
|
|
82
|
-
/// @param me The `MaybeErrorCode` struct to
|
|
83
|
-
/// @return
|
|
84
|
-
function
|
|
86
|
+
/// @notice Extracts the `Error` parameters from a `MaybeErrorCode` struct. Reverts if the variant is not `Error`.
|
|
87
|
+
/// @param me The `MaybeErrorCode` struct to extract from. Must be of type `Error`.
|
|
88
|
+
/// @return params An `ErrorParams` struct containing the decoded dispatch error
|
|
89
|
+
function asError(
|
|
85
90
|
MaybeErrorCode memory me
|
|
86
|
-
) internal pure returns (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
) internal pure returns (ErrorParams memory params) {
|
|
92
|
+
_assertVariant(me, MaybeErrorCodeVariant.Error);
|
|
93
|
+
(params.errorBytes, ) = Bytes.decode(me.payload);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/// @notice Extracts the `TruncatedError` parameters from a `MaybeErrorCode` struct. Reverts if the variant is not `TruncatedError`.
|
|
97
|
+
/// @param me The `MaybeErrorCode` struct to extract from. Must be of type `TruncatedError`.
|
|
98
|
+
/// @return params A `TruncatedErrorParams` struct containing the decoded truncated dispatch error
|
|
99
|
+
function asTruncatedError(
|
|
100
|
+
MaybeErrorCode memory me
|
|
101
|
+
) internal pure returns (TruncatedErrorParams memory params) {
|
|
102
|
+
_assertVariant(me, MaybeErrorCodeVariant.TruncatedError);
|
|
103
|
+
(params.errorBytes, ) = Bytes.decode(me.payload);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function _assertVariant(
|
|
107
|
+
MaybeErrorCode memory me,
|
|
108
|
+
MaybeErrorCodeVariant expected
|
|
109
|
+
) private pure {
|
|
110
|
+
if (me.variant != expected) {
|
|
111
|
+
revert InvalidMaybeErrorCodeVariant(uint8(me.variant));
|
|
112
|
+
}
|
|
92
113
|
}
|
|
93
114
|
}
|
|
@@ -6,9 +6,9 @@ struct PalletInfo {
|
|
|
6
6
|
/// @custom:property The index which identifies the pallet.
|
|
7
7
|
uint32 index;
|
|
8
8
|
/// @custom:property The name of the pallet. Max length is `MAX_PALLET_NAME_LEN`.
|
|
9
|
-
|
|
9
|
+
bytes name;
|
|
10
10
|
/// @custom:property The module name of the pallet. Max length is `MAX_PALLET_NAME_LEN`.
|
|
11
|
-
|
|
11
|
+
bytes moduleName;
|
|
12
12
|
/// @custom:property The major version of the crate which implements the pallet.
|
|
13
13
|
uint32 major;
|
|
14
14
|
/// @custom:property The minor version of the crate which implements the pallet.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.28;
|
|
3
3
|
|
|
4
4
|
import {Compact} from "../../../Scale/Compact.sol";
|
|
5
|
-
import {
|
|
5
|
+
import {Bytes} from "../../../Scale/Bytes.sol";
|
|
6
6
|
import {MAX_PALLET_NAME_LEN} from "../Constants.sol";
|
|
7
7
|
import {PalletInfo} from "./PalletInfo.sol";
|
|
8
8
|
|
|
@@ -27,8 +27,8 @@ library PalletInfoCodec {
|
|
|
27
27
|
return
|
|
28
28
|
abi.encodePacked(
|
|
29
29
|
Compact.encode(info.index),
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
Bytes.encode(info.name),
|
|
31
|
+
Bytes.encode(info.moduleName),
|
|
32
32
|
Compact.encode(info.major),
|
|
33
33
|
Compact.encode(info.minor),
|
|
34
34
|
Compact.encode(info.patch)
|
|
@@ -46,8 +46,8 @@ library PalletInfoCodec {
|
|
|
46
46
|
if (data.length < offset + 1) revert InvalidPalletInfoLength();
|
|
47
47
|
uint256 pos = offset;
|
|
48
48
|
pos += Compact.encodedSizeAt(data, pos); // index
|
|
49
|
-
pos +=
|
|
50
|
-
pos +=
|
|
49
|
+
pos += Bytes.encodedSizeAt(data, pos); // name
|
|
50
|
+
pos += Bytes.encodedSizeAt(data, pos); // moduleName
|
|
51
51
|
pos += Compact.encodedSizeAt(data, pos); // major
|
|
52
52
|
pos += Compact.encodedSizeAt(data, pos); // minor
|
|
53
53
|
pos += Compact.encodedSizeAt(data, pos); // patch
|
|
@@ -80,12 +80,12 @@ library PalletInfoCodec {
|
|
|
80
80
|
(index, read) = Compact.decodeAt(data, pos);
|
|
81
81
|
pos += read;
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
(name, read) =
|
|
83
|
+
bytes memory name;
|
|
84
|
+
(name, read) = Bytes.decodeAt(data, pos);
|
|
85
85
|
pos += read;
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
(moduleName, read) =
|
|
87
|
+
bytes memory moduleName;
|
|
88
|
+
(moduleName, read) = Bytes.decodeAt(data, pos);
|
|
89
89
|
pos += read;
|
|
90
90
|
|
|
91
91
|
uint256 major;
|