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
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
## Version 0.2.1
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
- Documentation Site - []()
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Fix docs in Junctions - [#de668af..e7b8edb](https://github.com/LucasGrasso/solidity-scale-codec/commit/e7b8edbfd6f965c0120cb2572f24e3c8e81c78fe)
|
|
10
|
+
|
|
11
|
+
## Version 0.2.0
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Implemented complete XCM v5 support surface with full Instruction model (all variants with Params and factory functions), Instruction/Xcm/VersionedXcm codecs, XCM helper utilities, VersionedXcm harness and cross-fuzz script scaffolding, plus README XCM usage documentation. - [#2](https://github.com/LucasGrasso/solidity-scale-codec/pull/2)
|
|
16
|
+
|
|
17
|
+
- Added Codecs for Bytes, Address - [#2](https://github.com/LucasGrasso/solidity-scale-codec/pull/2)
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Hardened decoding safety and consistency by fixing Transact call length handling, adding/trimming bounds checks at codec boundaries (Response, XcmError, VersionedXcm, Compact, and generated array codecs), updating array codegen template to preserve those checks, and standardizing docs/comments/style across the XCM v5 folder. - [#2](https://github.com/LucasGrasso/solidity-scale-codec/pull/2)
|
|
22
|
+
|
|
23
|
+
- Fix typos and add `encodedSizeAt` functions to all codecs for better safety and consistency. - [#2](https://github.com/LucasGrasso/solidity-scale-codec/pull/2)
|
|
24
|
+
|
|
25
|
+
- General code cleanup and refactoring. - [#2](https://github.com/LucasGrasso/solidity-scale-codec/pull/2)
|
package/DEFINITIONS.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
> Note: These definitions were taken from https://github.com/w3f/polkadot-spec/blob/main/docs. They are provided here for reference. All credits to respective authors.
|
|
2
|
+
|
|
3
|
+
# Notation
|
|
4
|
+
|
|
5
|
+
- Let $\mathbb{{B}}$ be the set of all byte sequences.
|
|
6
|
+
- For $x \in \mathbb{{B}}$, $x_i$ denotes the $i$-th byte of $x$, and $x_i^j$ denotes the $j$-th bit of the $i$-th byte of $x$.
|
|
7
|
+
|
|
8
|
+
# Definitions
|
|
9
|
+
|
|
10
|
+
## Little Endian
|
|
11
|
+
|
|
12
|
+
By the **little-endian** representation of a non-negative integer, ${I}$, represented as
|
|
13
|
+
|
|
14
|
+
$$
|
|
15
|
+
{I}={\left({B}_{{n}}\ldots{B}_{{0}}\right)}_{{256}}
|
|
16
|
+
$$
|
|
17
|
+
|
|
18
|
+
in base 256, we refer to a byte array ${B}={\left({b}_{{0}},{b}_{{1}},\ldots,{b}_{{n}}\right)}$ such that
|
|
19
|
+
|
|
20
|
+
$$
|
|
21
|
+
{b}_{{i}}\:={B}_{{i}}
|
|
22
|
+
$$
|
|
23
|
+
|
|
24
|
+
Accordingly, we define the function ${\mathsf{\text{Enc}}}_{{{\mathsf{\text{LE}}}}}$:
|
|
25
|
+
|
|
26
|
+
$$
|
|
27
|
+
{\mathsf{\text{Enc}}}_{{{\mathsf{\text{LE}}}}}:{\mathbb{{Z}}}^{+}\rightarrow{\mathbb{{B}}};{\left({B}_{{n}}\ldots{B}_{{0}}\right)}_{{256}}{\mid}\rightarrow{\left({B}_{{{0},}}{B}_{{1}},\ldots,{B}_{{n}}\right)}
|
|
28
|
+
$$
|
|
29
|
+
|
|
30
|
+
## Scale Types
|
|
31
|
+
|
|
32
|
+
### Fixed Length Integers
|
|
33
|
+
|
|
34
|
+
The SCALE codec, $\text{Enc}_{{\text{SC}}}$, for fixed length integers not defined here otherwise, is equal to the little-endian encoding of those values.
|
|
35
|
+
|
|
36
|
+
### Varying Data Type
|
|
37
|
+
|
|
38
|
+
> This library does not provide means for encoding/decoding varying data types, but the definitions are provided here for completeness and reference. The implementation is left to the user of the library.
|
|
39
|
+
|
|
40
|
+
We define a **varying data** type to be an ordered set of data types.
|
|
41
|
+
|
|
42
|
+
$$
|
|
43
|
+
{\mathcal{{T}}}={\left\lbrace{T}_{{1}},\ldots,{T}_{{n}}\right\rbrace}
|
|
44
|
+
$$
|
|
45
|
+
|
|
46
|
+
A value ${A}$ of varying data type is a pair ${\left({A}_{{\text{Type}}},{A}_{{\text{Value}}}\right)}$ where ${A}_{{\text{Type}}}={T}_{{i}}$ for some ${T}_{{i}}\in{\mathcal{{T}}}$ and ${A}_{{\text{Value}}}$ is its value of type ${T}_{{i}}$, which can be empty. We define $\text{idx}{\left({T}_{{i}}\right)}={i}-{1}$, unless it is explicitly defined as another value in the definition of a particular varying data type.
|
|
47
|
+
|
|
48
|
+
The SCALE codec for value ${A}={\left({A}_{{\text{Type}}},{A}_{{\text{Value}}}\right)}$ of varying data type ${\mathcal{{T}}}={\left\lbrace{T}_{{i}},\ldots{T}_{{n}}\right\rbrace}$, formally referred to as $\text{Enc}_{{\text{SC}}}{\left({A}\right)}$ is defined as follows:
|
|
49
|
+
|
|
50
|
+
$$
|
|
51
|
+
\text{Enc}_{{\text{SC}}}{\left({A}\right)}\:=\text{Enc}_{{\text{SC}}}{\left(\text{idx}{\left({A}_{{\text{Type}}}\right)}\text{||}\text{Enc}_{{\text{SC}}}{\left({A}_{{\text{Value}}}\right)}\right)}
|
|
52
|
+
$$
|
|
53
|
+
|
|
54
|
+
The SCALE codec does not encode the correspondence between the value and the data type it represents; the decoder needs prior knowledge of such correspondence to decode the data.
|
|
55
|
+
|
|
56
|
+
### Boolean
|
|
57
|
+
|
|
58
|
+
The SCALE codec for a **boolean value** ${b}$ defined as a byte as follows:
|
|
59
|
+
|
|
60
|
+
$$
|
|
61
|
+
\text{Enc}_{{\text{SC}}}:{\left\lbrace\text{False},\text{True}\right\rbrace}\rightarrow{\mathbb{{B}}}_{{1}}
|
|
62
|
+
$$
|
|
63
|
+
|
|
64
|
+
$$
|
|
65
|
+
{b}\rightarrow{\left\lbrace\begin{matrix}{0}&{b}=\text{False}\\{1}&{b}=\text{True}\end{matrix}\right.}
|
|
66
|
+
$$
|
|
67
|
+
|
|
68
|
+
### Compact
|
|
69
|
+
|
|
70
|
+
**SCALE Length encoding** ${\text{Enc}_{{\text{SC}}}^{{\text{Len}}}}$, also known as a _compact encoding_, of a non-negative number ${n}$ is defined as follows:
|
|
71
|
+
|
|
72
|
+
$$
|
|
73
|
+
{\text{Enc}_{{\text{SC}}}^{{\text{Len}}}}:{\mathbb{{N}}}\rightarrow{\mathbb{{B}}}
|
|
74
|
+
$$
|
|
75
|
+
|
|
76
|
+
$$
|
|
77
|
+
{n}\rightarrow{b}\:={\left\lbrace\begin{matrix}{l}_{{1}}&{0}\le{n}<{2}^{{6}}\\{i}_{{1}}{i}_{{2}}&{2}^{{6}}\le{n}<{2}^{{14}}\\{j}_{{1}}{j}_{{2}}{j}_{{3}}{j}_{{4}}&{2}^{{14}}\le{n}<{2}^{{30}}\\{k}_{{1}}{k}_{{2}}\ldots{k}_{{m}+{1}}&{2}^{{30}}\le{n}\end{matrix}\right.}
|
|
78
|
+
$$
|
|
79
|
+
|
|
80
|
+
$$
|
|
81
|
+
{{l}_{{1}}^{{1}}}{{l}_{{1}}^{{0}}}={00}
|
|
82
|
+
$$
|
|
83
|
+
|
|
84
|
+
$$
|
|
85
|
+
{{i}_{{1}}^{{1}}}{{i}_{{1}}^{{0}}}={01}
|
|
86
|
+
$$
|
|
87
|
+
|
|
88
|
+
$$
|
|
89
|
+
{{j}_{{1}}^{{1}}}{{j}_{{1}}^{{0}}}={10}
|
|
90
|
+
$$
|
|
91
|
+
|
|
92
|
+
$$
|
|
93
|
+
{{k}_{{1}}^{{1}}}{{k}_{{1}}^{{0}}}={11}
|
|
94
|
+
$$
|
|
95
|
+
|
|
96
|
+
and the rest of the bits of ${b}$ store the value of ${n}$ in little-endian format in base-2 as follows:
|
|
97
|
+
|
|
98
|
+
$$
|
|
99
|
+
{n}\:={\left\lbrace\begin{matrix}{{l}_{{1}}^{{7}}}\ldots{{l}_{{1}}^{{3}}}{{l}_{{1}}^{{2}}}&{n}<{2}^{{6}}\\{{i}_{{2}}^{{7}}}\ldots{{i}_{{2}}^{{0}}}{{i}_{{1}}^{{7}}}..{{i}_{{1}}^{{2}}}&{2}^{{6}}\le{n}<{2}^{{14}}\\{{j}_{{4}}^{{7}}}\ldots{{j}_{{4}}^{{0}}}{{j}_{{3}}^{{7}}}\ldots{{j}_{{1}}^{{7}}}\ldots{{j}_{{1}}^{{2}}}&{2}^{{14}}\le{n}<{2}^{{30}}\\{k}_{{2}}+{k}_{{3}}{2}^{{8}}+{k}_{{4}}{2}^{{{2}\times{8}}}+\ldots+{k}_{{m}+{1}}{2}^{{{\left({m}-{1}\right)}{8}}}&{2}^{{30}}\le{n}\end{matrix}\right.}
|
|
100
|
+
$$
|
|
101
|
+
|
|
102
|
+
such that:
|
|
103
|
+
|
|
104
|
+
$$
|
|
105
|
+
{{k}_{{1}}^{{7}}}\ldots{{k}_{{1}}^{{3}}}{{k}_{{1}}^{{2}}}\:={m}-{4}
|
|
106
|
+
$$
|
|
107
|
+
|
|
108
|
+
Note that ${m}$ denotes the length of the original integer being encoded and does not include the extra byte describing the length. The encoding can be used for integers up to: $$2^{(63+4)8} -1 = 2^{536} -1$$
|
|
109
|
+
|
|
110
|
+
### Sequence
|
|
111
|
+
|
|
112
|
+
The **SCALE codec** for **sequence** ${S}$ such that:
|
|
113
|
+
|
|
114
|
+
$$
|
|
115
|
+
{S}\:={A}_{{1}},\ldots{A}_{{n}}
|
|
116
|
+
$$
|
|
117
|
+
|
|
118
|
+
where ${A}_{{i}}$’s are values of **the same type** (and the decoder is unable to infer value of ${n}$ from the context) is defined as:
|
|
119
|
+
|
|
120
|
+
$$
|
|
121
|
+
\text{Enc}_{{\text{SC}}}{\left({S}\right)}\:={\text{Enc}_{{\text{SC}}}^{{\text{Len}}}}{\left({\left|{{S}}\right|}\right)}\text{||}\text{Enc}_{{\text{SC}}}{\left({A}_{{2}}\right)}\text{||}\ldots\text{||}\text{Enc}_{{\text{SC}}}{\left({A}_{{n}}\right)}
|
|
122
|
+
$$
|
|
123
|
+
|
|
124
|
+
where ${\text{Enc}_{{\text{SC}}}^{{\text{Len}}}}$ is defined [here](#compact).
|
|
125
|
+
|
|
126
|
+
In some cases, the length indicator ${\text{Enc}_{{\text{SC}}}^{{\text{Len}}}}{\left({\left|{{S}}\right|}\right)}$ is omitted if the length of the sequence is fixed and known by the decoder upfront. Such cases are explicitly stated by the definition of the corresponding type.
|
|
127
|
+
|
|
128
|
+
### String
|
|
129
|
+
|
|
130
|
+
The SCALE codec for a **string value** is an [encoded sequence](#sequence) consisting of UTF-8 encoded bytes.
|
|
131
|
+
|
|
132
|
+
> This can be achieved via encoding the UTF-8 sequence as a `uint8[]` array, which is supported by this library.
|
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
</a>
|
|
5
5
|
<a href="https://github.com/LucasGrasso/solidity-scale-codec/blob/main/LICENSE" target="_blank"><img alt="GitHub License" src="https://img.shields.io/github/license/LucasGrasso/solidity-scale-codec"></a>
|
|
6
6
|
|
|
7
|
+
📖 **[View Documentation](https://lucasgrasso.github.io/solidity-scale-codec/)** — Documentation site with API reference
|
|
8
|
+
|
|
7
9
|
## Description
|
|
8
10
|
|
|
9
11
|
[Substrate](https://github.com/paritytech/substrate) uses a lightweight and efficient [encoding and decoding program](https://docs.polkadot.com/polkadot-protocol/parachain-basics/data-encoding/#data-encoding) to optimize how data is sent and received over the network. The program used to serialize and deserialize data is called the SCALE codec, with SCALE being an acronym for **S**imple **C**oncatenated **A**ggregate **L**ittle-**E**ndian.
|
|
@@ -20,7 +22,7 @@ This library provides a Highly-Modular implementation of SCALE in solidity.
|
|
|
20
22
|
| `Compact` | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2\*\*536) and is more efficient at encoding most values than the fixed-width version. (Though for single-byte values, the fixed-width integer is never worse.) | `0` | `0x00` |
|
|
21
23
|
| `Arrays` | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. Currently `[uintN]`,`[intN]`, `[bool]` are supported. | `[1,0]` | `0x080100` |
|
|
22
24
|
|
|
23
|
-
See the [Definitions](
|
|
25
|
+
See the [Definitions](DEFINITIONS.md) for more details on the encoding of different types.
|
|
24
26
|
|
|
25
27
|
## Usage
|
|
26
28
|
|
|
@@ -28,6 +30,100 @@ See the [Definitions](definitions.md) for more details on the encoding of differ
|
|
|
28
30
|
|
|
29
31
|
See this [example](https://github.com/LucasGrasso/solidity-scale-codec/blob/main/contracts/examples/Foo.sol).
|
|
30
32
|
|
|
33
|
+
## About the libraries
|
|
34
|
+
|
|
35
|
+
### src/LittleEndian
|
|
36
|
+
|
|
37
|
+
The `LittleEndian` library provides functions to encode and decode unsigned integers in little-endian format.
|
|
38
|
+
|
|
39
|
+
All libraries here provide the following functions:
|
|
40
|
+
|
|
41
|
+
```solidity
|
|
42
|
+
function toLittleEndian(uintN value) internal pure returns (bytesM){}
|
|
43
|
+
function fromLittleEndian(
|
|
44
|
+
bytes memory data,
|
|
45
|
+
uint256 offset
|
|
46
|
+
) internal pure returns (uintN value) {}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### src/Scale
|
|
50
|
+
|
|
51
|
+
The `Scale` library provides functions to encode and decode various types in the SCALE format, including booleans, unsigned integers, signed integers, compact integers, and arrays of these types.
|
|
52
|
+
|
|
53
|
+
- All Codec libraries provide the following encoding functions:
|
|
54
|
+
|
|
55
|
+
```solidity
|
|
56
|
+
function encode(T value) internal pure returns (bytes memory){}
|
|
57
|
+
function encodedSizeAt(bytes memory data, uint256 offset) internal pure returns (uint256 size){}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Libraries for fixed length types provide the following functions for encoding:
|
|
61
|
+
|
|
62
|
+
```solidity
|
|
63
|
+
function decode(bytes memory data) internal pure returns (T value){}
|
|
64
|
+
function decodeAt(bytes memory data, uint256 offset) internal pure returns (T value){}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
> Note: `decode(data)` = `decodeAt(data, 0)`
|
|
68
|
+
|
|
69
|
+
Integer libraries also provide Little-Endian encoding functions, using the `LittleEndian` library:
|
|
70
|
+
|
|
71
|
+
```solidity
|
|
72
|
+
function toLittleEndian(T value) internal pure returns (bytesM){}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- Variable length types libraries provide the same encoding functions, but the decoding functions also return the number of bytes read from the input data. This is useful for decoding from a larger byte array where the encoded value is not at the beginning.
|
|
76
|
+
|
|
77
|
+
```solidity
|
|
78
|
+
function decode(bytes memory data) internal pure returns (T value, uint256 bytesRead){}
|
|
79
|
+
function decodeAt(bytes memory data, uint256 offset) internal pure returns (T value, uint256 bytesRead){}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> Note: `decode(data)` = `decodeAt(data, 0)`
|
|
83
|
+
|
|
84
|
+
### src/Xcm
|
|
85
|
+
|
|
86
|
+
The `Xcm` library contains SCALE-compatible Solidity representations and codecs for XCM types.
|
|
87
|
+
|
|
88
|
+
Current support includes:
|
|
89
|
+
|
|
90
|
+
- XCM v5 domain types in `src/Xcm/v5/*` (instructions, locations, assets, responses, errors, weights, and related codecs).
|
|
91
|
+
- A versioned wrapper in `src/Xcm/VersionedXcm/*`.
|
|
92
|
+
|
|
93
|
+
Implementation notes:
|
|
94
|
+
|
|
95
|
+
- Enum-like XCM types are represented as structs with a type discriminator plus `bytes payload`.
|
|
96
|
+
- Each type has a codec library with `encode`, `encodedSizeAt`, `decode`, and `decodeAt`.
|
|
97
|
+
- `VersionedXcm` currently supports v5 payloads.
|
|
98
|
+
|
|
99
|
+
Minimal usage example:
|
|
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
|
+
```
|
|
126
|
+
|
|
31
127
|
### Running Tests
|
|
32
128
|
|
|
33
129
|
To run all the tests in the project, execute the following command:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solidity-scale-codec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Solidity implementation of scale-codec.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"solidity",
|
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"src/**/*.sol",
|
|
20
|
-
"!src/**/*.t.sol"
|
|
20
|
+
"!src/**/*.t.sol",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE",
|
|
23
|
+
"CHANGELOG.md",
|
|
24
|
+
"DEFINITIONS.md"
|
|
21
25
|
],
|
|
22
26
|
"license": "Apache-2.0",
|
|
23
27
|
"author": "LucasGrasso",
|
|
@@ -27,7 +31,12 @@
|
|
|
27
31
|
"gas-report": "env ENABLE_GAS_REPORT=true npm run test",
|
|
28
32
|
"codegen-signed": "npx hardhat run codegen/signed/generate.ts",
|
|
29
33
|
"codegen-unsigned": "npx hardhat run codegen/unsigned/generate.ts",
|
|
30
|
-
"codegen-array": "npx hardhat run codegen/array/generate.ts"
|
|
34
|
+
"codegen-array": "npx hardhat run codegen/array/generate.ts",
|
|
35
|
+
"codegen-bytes": "npx hardhat run codegen/bytes/generate.ts",
|
|
36
|
+
"docs:gen": "solidity-docgen",
|
|
37
|
+
"docs:dev": "npm run docs:gen && vitepress dev docs",
|
|
38
|
+
"docs:build": "npm run docs:gen && vitepress build docs",
|
|
39
|
+
"docs:preview": "vitepress preview docs"
|
|
31
40
|
},
|
|
32
41
|
"type": "module",
|
|
33
42
|
"devDependencies": {
|
|
@@ -39,6 +48,9 @@
|
|
|
39
48
|
"prettier": "^3.8.1",
|
|
40
49
|
"prettier-plugin-solidity": "^2.2.1",
|
|
41
50
|
"typescript": "~5.8.0",
|
|
42
|
-
"viem": "^2.40.3"
|
|
51
|
+
"viem": "^2.40.3",
|
|
52
|
+
"vitepress": "^1.6.4",
|
|
53
|
+
"vue": "^3.4.0",
|
|
54
|
+
"solidity-doc-generator": "^1.0.4"
|
|
43
55
|
}
|
|
44
56
|
}
|
|
@@ -7,7 +7,9 @@ library LittleEndianU128 {
|
|
|
7
7
|
/// @notice Converts a `uint128` to little-endian `bytes16`
|
|
8
8
|
/// @param value The `uint128` value to convert.
|
|
9
9
|
/// @return result The little-endian representation of the input `uint128` as a `bytes16`.
|
|
10
|
-
function
|
|
10
|
+
function toLittleEndian(
|
|
11
|
+
uint128 value
|
|
12
|
+
) internal pure returns (bytes16 result) {
|
|
11
13
|
assembly {
|
|
12
14
|
let v := value
|
|
13
15
|
v := or(
|
|
@@ -31,7 +33,7 @@ library LittleEndianU128 {
|
|
|
31
33
|
/// @param data Raw byte buffer.
|
|
32
34
|
/// @param offset Byte offset into `data`.
|
|
33
35
|
/// @return value Decoded uint128.
|
|
34
|
-
function
|
|
36
|
+
function fromLittleEndian(
|
|
35
37
|
bytes memory data,
|
|
36
38
|
uint256 offset
|
|
37
39
|
) internal pure returns (uint128 value) {
|
|
@@ -7,7 +7,7 @@ library LittleEndianU16 {
|
|
|
7
7
|
/// @notice Converts a `uint16` to little-endian `bytes2`
|
|
8
8
|
/// @param value The `uint16` value to convert
|
|
9
9
|
/// @return result The little-endian representation of the input `uint16` as a `bytes2`
|
|
10
|
-
function
|
|
10
|
+
function toLittleEndian(uint16 value) internal pure returns (bytes2) {
|
|
11
11
|
return bytes2(uint16((value >> 8) | (value << 8)));
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ library LittleEndianU16 {
|
|
|
15
15
|
/// @param data Raw byte buffer.
|
|
16
16
|
/// @param offset Byte offset into `data`.
|
|
17
17
|
/// @return value Decoded uint16.
|
|
18
|
-
function
|
|
18
|
+
function fromLittleEndian(
|
|
19
19
|
bytes memory data,
|
|
20
20
|
uint256 offset
|
|
21
21
|
) internal pure returns (uint16 value) {
|
|
@@ -7,7 +7,9 @@ library LittleEndianU256 {
|
|
|
7
7
|
/// @notice Converts a `uint256` to little-endian `bytes32`
|
|
8
8
|
/// @param value The `uint256` value to convert.
|
|
9
9
|
/// @return result The little-endian representation of the input `uint256` as a `bytes32`.
|
|
10
|
-
function
|
|
10
|
+
function toLittleEndian(
|
|
11
|
+
uint256 value
|
|
12
|
+
) internal pure returns (bytes32 result) {
|
|
11
13
|
assembly {
|
|
12
14
|
let v := value
|
|
13
15
|
v := or(
|
|
@@ -83,7 +85,7 @@ library LittleEndianU256 {
|
|
|
83
85
|
/// @param data Raw byte buffer.
|
|
84
86
|
/// @param offset Byte offset into `data`.
|
|
85
87
|
/// @return value Decoded uint256.
|
|
86
|
-
function
|
|
88
|
+
function fromLittleEndian(
|
|
87
89
|
bytes memory data,
|
|
88
90
|
uint256 offset
|
|
89
91
|
) internal pure returns (uint256 value) {
|
|
@@ -7,7 +7,9 @@ library LittleEndianU32 {
|
|
|
7
7
|
/// @notice Converts a `uint32` to little-endian `bytes4`
|
|
8
8
|
/// @param value The `uint32` value to convert
|
|
9
9
|
/// @return result The little-endian representation of the input `uint32` as a `bytes4`
|
|
10
|
-
function
|
|
10
|
+
function toLittleEndian(
|
|
11
|
+
uint32 value
|
|
12
|
+
) internal pure returns (bytes4 result) {
|
|
11
13
|
assembly {
|
|
12
14
|
let v := or(
|
|
13
15
|
or(
|
|
@@ -24,7 +26,7 @@ library LittleEndianU32 {
|
|
|
24
26
|
/// @param data Raw byte buffer.
|
|
25
27
|
/// @param offset Byte offset into `data`.
|
|
26
28
|
/// @return value Decoded uint32.
|
|
27
|
-
function
|
|
29
|
+
function fromLittleEndian(
|
|
28
30
|
bytes memory data,
|
|
29
31
|
uint256 offset
|
|
30
32
|
) internal pure returns (uint32 value) {
|
|
@@ -7,7 +7,9 @@ library LittleEndianU64 {
|
|
|
7
7
|
/// @notice Converts a `uint64` to little-endian `bytes8`
|
|
8
8
|
/// @param value The `uint64` value to convert.
|
|
9
9
|
/// @return result The little-endian representation of the input `uint64` as a `bytes8`.
|
|
10
|
-
function
|
|
10
|
+
function toLittleEndian(
|
|
11
|
+
uint64 value
|
|
12
|
+
) internal pure returns (bytes8 result) {
|
|
11
13
|
assembly {
|
|
12
14
|
let v := value
|
|
13
15
|
v := or(
|
|
@@ -27,7 +29,7 @@ library LittleEndianU64 {
|
|
|
27
29
|
/// @param data Raw byte buffer.
|
|
28
30
|
/// @param offset Byte offset into `data`.
|
|
29
31
|
/// @return value Decoded uint64.
|
|
30
|
-
function
|
|
32
|
+
function fromLittleEndian(
|
|
31
33
|
bytes memory data,
|
|
32
34
|
uint256 offset
|
|
33
35
|
) internal pure returns (uint64 value) {
|
|
@@ -7,7 +7,7 @@ library LittleEndianU8 {
|
|
|
7
7
|
/// @notice Converts a `uint8` to little-endian `bytes1`
|
|
8
8
|
/// @param value The `uint8` value to convert.
|
|
9
9
|
/// @return result The little-endian representation of the input `uint8` as a `bytes1`.
|
|
10
|
-
function
|
|
10
|
+
function toLittleEndian(uint8 value) internal pure returns (bytes1) {
|
|
11
11
|
return bytes1(value);
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ library LittleEndianU8 {
|
|
|
15
15
|
/// @param data Raw byte buffer.
|
|
16
16
|
/// @param offset Byte offset into `data`.
|
|
17
17
|
/// @return value Decoded uint8.
|
|
18
|
-
function
|
|
18
|
+
function fromLittleEndian(
|
|
19
19
|
bytes memory data,
|
|
20
20
|
uint256 offset
|
|
21
21
|
) internal pure returns (uint8 value) {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
/// @title Scale Codec for the `address` type.
|
|
5
|
+
/// @notice SCALE-compliant encoder/decoder for the `address` type.
|
|
6
|
+
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
7
|
+
library Address {
|
|
8
|
+
error InvalidAddressLength();
|
|
9
|
+
|
|
10
|
+
/// @notice Encodes an `address` into SCALE format (20-byte little-endian).
|
|
11
|
+
/// @param value The `address` to encode.
|
|
12
|
+
/// @return SCALE-encoded byte sequence.
|
|
13
|
+
function encode(address value) internal pure returns (bytes memory) {
|
|
14
|
+
return abi.encodePacked(value);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// @notice Returns the number of bytes that an `address` would occupy when SCALE-encoded.
|
|
18
|
+
/// @param data The byte sequence containing the encoded `address`.
|
|
19
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `address`.
|
|
20
|
+
/// @return The number of bytes that the `address` 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 + 20) {
|
|
26
|
+
revert InvalidAddressLength();
|
|
27
|
+
}
|
|
28
|
+
return 20;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// @notice Decodes SCALE-encoded bytes into an `address`.
|
|
32
|
+
/// @param data The SCALE-encoded byte sequence.
|
|
33
|
+
/// @return The decoded `address`.
|
|
34
|
+
function decode(bytes memory data) internal pure returns (address) {
|
|
35
|
+
return decodeAt(data, 0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// @notice Decodes an `address` 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 The decoded `address`.
|
|
42
|
+
function decodeAt(
|
|
43
|
+
bytes memory data,
|
|
44
|
+
uint256 offset
|
|
45
|
+
) internal pure returns (address) {
|
|
46
|
+
if (data.length < offset + 20) {
|
|
47
|
+
revert InvalidAddressLength();
|
|
48
|
+
}
|
|
49
|
+
bytes memory addrBytes = new bytes(20);
|
|
50
|
+
for (uint256 i = 0; i < 20; i++) {
|
|
51
|
+
addrBytes[i] = data[offset + i];
|
|
52
|
+
}
|
|
53
|
+
return address(bytes20(addrBytes));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -8,7 +8,7 @@ import {Bool} from "../Bool.sol";
|
|
|
8
8
|
/// @notice SCALE-compliant encoder/decoder for the `bool[]` type.
|
|
9
9
|
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
10
10
|
library BoolArr {
|
|
11
|
-
error
|
|
11
|
+
error InvalidBoolArrLength();
|
|
12
12
|
|
|
13
13
|
using Bool for bool;
|
|
14
14
|
|
|
@@ -23,6 +23,20 @@ library BoolArr {
|
|
|
23
23
|
return result;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/// @notice Returns the number of bytes that a `bool[]` would occupy when SCALE-encoded.
|
|
27
|
+
/// @param data The byte sequence containing the encoded `bool[]`.
|
|
28
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `bool[]`.
|
|
29
|
+
/// @return The number of bytes that the `bool[]` would occupy when SCALE-encoded.
|
|
30
|
+
function encodedSizeAt(
|
|
31
|
+
bytes memory data,
|
|
32
|
+
uint256 offset
|
|
33
|
+
) internal pure returns (uint256) {
|
|
34
|
+
(uint256 count, uint256 prefixSize) = Compact.decodeAt(data, offset);
|
|
35
|
+
uint256 totalSize = prefixSize + (count * 1);
|
|
36
|
+
if (offset + totalSize > data.length) revert InvalidBoolArrLength();
|
|
37
|
+
return totalSize;
|
|
38
|
+
}
|
|
39
|
+
|
|
26
40
|
/// @notice Decodes an `bool[]` from SCALE format.
|
|
27
41
|
/// @param data The SCALE-encoded byte sequence.
|
|
28
42
|
/// @return arr The decoded array of `bool`.
|
|
@@ -45,7 +59,7 @@ library BoolArr {
|
|
|
45
59
|
(uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
|
|
46
60
|
uint256 pos = offset + compactBytes;
|
|
47
61
|
|
|
48
|
-
if (pos + (length * 1) > data.length) revert
|
|
62
|
+
if (pos + (length * 1) > data.length) revert InvalidBoolArrLength();
|
|
49
63
|
|
|
50
64
|
arr = new bool[](length);
|
|
51
65
|
for (uint256 i = 0; i < length; ++i) {
|
|
@@ -8,7 +8,7 @@ import {I128} from "../Signed.sol";
|
|
|
8
8
|
/// @notice SCALE-compliant encoder/decoder for the `int128[]` type.
|
|
9
9
|
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
10
10
|
library I128Arr {
|
|
11
|
-
error
|
|
11
|
+
error InvalidI128ArrLength();
|
|
12
12
|
|
|
13
13
|
using I128 for int128;
|
|
14
14
|
|
|
@@ -23,6 +23,20 @@ library I128Arr {
|
|
|
23
23
|
return result;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/// @notice Returns the number of bytes that a `int128[]` would occupy when SCALE-encoded.
|
|
27
|
+
/// @param data The byte sequence containing the encoded `int128[]`.
|
|
28
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int128[]`.
|
|
29
|
+
/// @return The number of bytes that the `int128[]` would occupy when SCALE-encoded.
|
|
30
|
+
function encodedSizeAt(
|
|
31
|
+
bytes memory data,
|
|
32
|
+
uint256 offset
|
|
33
|
+
) internal pure returns (uint256) {
|
|
34
|
+
(uint256 count, uint256 prefixSize) = Compact.decodeAt(data, offset);
|
|
35
|
+
uint256 totalSize = prefixSize + (count * 16);
|
|
36
|
+
if (offset + totalSize > data.length) revert InvalidI128ArrLength();
|
|
37
|
+
return totalSize;
|
|
38
|
+
}
|
|
39
|
+
|
|
26
40
|
/// @notice Decodes an `int128[]` from SCALE format.
|
|
27
41
|
/// @param data The SCALE-encoded byte sequence.
|
|
28
42
|
/// @return arr The decoded array of `int128`.
|
|
@@ -45,7 +59,7 @@ library I128Arr {
|
|
|
45
59
|
(uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
|
|
46
60
|
uint256 pos = offset + compactBytes;
|
|
47
61
|
|
|
48
|
-
if (pos + (length * 16) > data.length) revert
|
|
62
|
+
if (pos + (length * 16) > data.length) revert InvalidI128ArrLength();
|
|
49
63
|
|
|
50
64
|
arr = new int128[](length);
|
|
51
65
|
for (uint256 i = 0; i < length; ++i) {
|
|
@@ -8,7 +8,7 @@ import {I16} from "../Signed.sol";
|
|
|
8
8
|
/// @notice SCALE-compliant encoder/decoder for the `int16[]` type.
|
|
9
9
|
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
10
10
|
library I16Arr {
|
|
11
|
-
error
|
|
11
|
+
error InvalidI16ArrLength();
|
|
12
12
|
|
|
13
13
|
using I16 for int16;
|
|
14
14
|
|
|
@@ -23,6 +23,20 @@ library I16Arr {
|
|
|
23
23
|
return result;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/// @notice Returns the number of bytes that a `int16[]` would occupy when SCALE-encoded.
|
|
27
|
+
/// @param data The byte sequence containing the encoded `int16[]`.
|
|
28
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int16[]`.
|
|
29
|
+
/// @return The number of bytes that the `int16[]` would occupy when SCALE-encoded.
|
|
30
|
+
function encodedSizeAt(
|
|
31
|
+
bytes memory data,
|
|
32
|
+
uint256 offset
|
|
33
|
+
) internal pure returns (uint256) {
|
|
34
|
+
(uint256 count, uint256 prefixSize) = Compact.decodeAt(data, offset);
|
|
35
|
+
uint256 totalSize = prefixSize + (count * 2);
|
|
36
|
+
if (offset + totalSize > data.length) revert InvalidI16ArrLength();
|
|
37
|
+
return totalSize;
|
|
38
|
+
}
|
|
39
|
+
|
|
26
40
|
/// @notice Decodes an `int16[]` from SCALE format.
|
|
27
41
|
/// @param data The SCALE-encoded byte sequence.
|
|
28
42
|
/// @return arr The decoded array of `int16`.
|
|
@@ -45,7 +59,7 @@ library I16Arr {
|
|
|
45
59
|
(uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
|
|
46
60
|
uint256 pos = offset + compactBytes;
|
|
47
61
|
|
|
48
|
-
if (pos + (length * 2) > data.length) revert
|
|
62
|
+
if (pos + (length * 2) > data.length) revert InvalidI16ArrLength();
|
|
49
63
|
|
|
50
64
|
arr = new int16[](length);
|
|
51
65
|
for (uint256 i = 0; i < length; ++i) {
|
|
@@ -8,7 +8,7 @@ import {I256} from "../Signed.sol";
|
|
|
8
8
|
/// @notice SCALE-compliant encoder/decoder for the `int256[]` type.
|
|
9
9
|
/// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
|
|
10
10
|
library I256Arr {
|
|
11
|
-
error
|
|
11
|
+
error InvalidI256ArrLength();
|
|
12
12
|
|
|
13
13
|
using I256 for int256;
|
|
14
14
|
|
|
@@ -23,6 +23,20 @@ library I256Arr {
|
|
|
23
23
|
return result;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/// @notice Returns the number of bytes that a `int256[]` would occupy when SCALE-encoded.
|
|
27
|
+
/// @param data The byte sequence containing the encoded `int256[]`.
|
|
28
|
+
/// @param offset The starting index in `data` from which to calculate the encoded size of the `int256[]`.
|
|
29
|
+
/// @return The number of bytes that the `int256[]` would occupy when SCALE-encoded.
|
|
30
|
+
function encodedSizeAt(
|
|
31
|
+
bytes memory data,
|
|
32
|
+
uint256 offset
|
|
33
|
+
) internal pure returns (uint256) {
|
|
34
|
+
(uint256 count, uint256 prefixSize) = Compact.decodeAt(data, offset);
|
|
35
|
+
uint256 totalSize = prefixSize + (count * 32);
|
|
36
|
+
if (offset + totalSize > data.length) revert InvalidI256ArrLength();
|
|
37
|
+
return totalSize;
|
|
38
|
+
}
|
|
39
|
+
|
|
26
40
|
/// @notice Decodes an `int256[]` from SCALE format.
|
|
27
41
|
/// @param data The SCALE-encoded byte sequence.
|
|
28
42
|
/// @return arr The decoded array of `int256`.
|
|
@@ -45,7 +59,7 @@ library I256Arr {
|
|
|
45
59
|
(uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
|
|
46
60
|
uint256 pos = offset + compactBytes;
|
|
47
61
|
|
|
48
|
-
if (pos + (length * 32) > data.length) revert
|
|
62
|
+
if (pos + (length * 32) > data.length) revert InvalidI256ArrLength();
|
|
49
63
|
|
|
50
64
|
arr = new int256[](length);
|
|
51
65
|
for (uint256 i = 0; i < length; ++i) {
|