solidity-scale-codec 0.1.3 → 0.2.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.
Files changed (104) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/DEFINITIONS.md +132 -0
  3. package/README.md +95 -1
  4. package/package.json +8 -3
  5. package/src/LittleEndian/LittleEndianU128.sol +4 -2
  6. package/src/LittleEndian/LittleEndianU16.sol +2 -2
  7. package/src/LittleEndian/LittleEndianU256.sol +4 -2
  8. package/src/LittleEndian/LittleEndianU32.sol +4 -2
  9. package/src/LittleEndian/LittleEndianU64.sol +4 -2
  10. package/src/LittleEndian/LittleEndianU8.sol +2 -2
  11. package/src/Scale/Address/Address.sol +55 -0
  12. package/src/Scale/Address.sol +4 -0
  13. package/src/Scale/Array/BoolArr.sol +16 -2
  14. package/src/Scale/Array/I128Arr.sol +16 -2
  15. package/src/Scale/Array/I16Arr.sol +16 -2
  16. package/src/Scale/Array/I256Arr.sol +16 -2
  17. package/src/Scale/Array/I32Arr.sol +16 -2
  18. package/src/Scale/Array/I64Arr.sol +16 -2
  19. package/src/Scale/Array/I8Arr.sol +16 -2
  20. package/src/Scale/Array/U128Arr.sol +16 -2
  21. package/src/Scale/Array/U16Arr.sol +16 -2
  22. package/src/Scale/Array/U256Arr.sol +16 -2
  23. package/src/Scale/Array/U32Arr.sol +16 -2
  24. package/src/Scale/Array/U64Arr.sol +16 -2
  25. package/src/Scale/Array/U8Arr.sol +16 -2
  26. package/src/Scale/Bool/Bool.sol +12 -0
  27. package/src/Scale/Bytes/Bytes.sol +63 -0
  28. package/src/Scale/Bytes/Bytes16.sol +53 -0
  29. package/src/Scale/Bytes/Bytes2.sol +53 -0
  30. package/src/Scale/Bytes/Bytes32.sol +53 -0
  31. package/src/Scale/Bytes/Bytes4.sol +53 -0
  32. package/src/Scale/Bytes/Bytes8.sol +53 -0
  33. package/src/Scale/Bytes.sol +8 -0
  34. package/src/Scale/Compact/Compact.sol +37 -3
  35. package/src/Scale/Signed/I128.sol +11 -0
  36. package/src/Scale/Signed/I16.sol +11 -0
  37. package/src/Scale/Signed/I256.sol +11 -0
  38. package/src/Scale/Signed/I32.sol +11 -0
  39. package/src/Scale/Signed/I64.sol +11 -0
  40. package/src/Scale/Signed/I8.sol +11 -0
  41. package/src/Scale/Unsigned/U128.sol +16 -2
  42. package/src/Scale/Unsigned/U16.sol +16 -2
  43. package/src/Scale/Unsigned/U256.sol +16 -2
  44. package/src/Scale/Unsigned/U32.sol +16 -2
  45. package/src/Scale/Unsigned/U64.sol +16 -2
  46. package/src/Scale/Unsigned/U8.sol +16 -2
  47. package/src/Xcm/Types/Version.sol +5 -0
  48. package/src/Xcm/VersionedXcm/VersionedXcm.sol +27 -0
  49. package/src/Xcm/VersionedXcm/VersionedXcmCodec.sol +70 -0
  50. package/src/Xcm/v3/Constants.sol +5 -0
  51. package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCode.sol +73 -0
  52. package/src/Xcm/v3/MaybeErrorCode/MaybeErrorCodeCodec.sol +94 -0
  53. package/src/Xcm/v5/Asset/Asset.sol +13 -0
  54. package/src/Xcm/v5/Asset/AssetCodec.sol +72 -0
  55. package/src/Xcm/v5/AssetFilter/AssetFilter.sol +61 -0
  56. package/src/Xcm/v5/AssetFilter/AssetFilterCodec.sol +105 -0
  57. package/src/Xcm/v5/AssetId/AssetId.sol +10 -0
  58. package/src/Xcm/v5/AssetId/AssetIdCodec.sol +57 -0
  59. package/src/Xcm/v5/AssetInstance/AssetInstance.sol +139 -0
  60. package/src/Xcm/v5/AssetInstance/AssetInstanceCodec.sol +174 -0
  61. package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilter.sol +82 -0
  62. package/src/Xcm/v5/AssetTransferFilter/AssetTransferFilterCodec.sol +95 -0
  63. package/src/Xcm/v5/Assets/Assets.sol +14 -0
  64. package/src/Xcm/v5/Assets/AssetsCodec.sol +94 -0
  65. package/src/Xcm/v5/BodyId/BodyId.sol +121 -0
  66. package/src/Xcm/v5/BodyId/BodyIdCodec.sol +128 -0
  67. package/src/Xcm/v5/BodyPart/BodyPart.sol +105 -0
  68. package/src/Xcm/v5/BodyPart/BodyPartCodec.sol +134 -0
  69. package/src/Xcm/v5/Constants.sol +15 -0
  70. package/src/Xcm/v5/Fungibility/Fungibility.sol +60 -0
  71. package/src/Xcm/v5/Fungibility/FungibilityCodec.sol +128 -0
  72. package/src/Xcm/v5/Hint/Hint.sol +40 -0
  73. package/src/Xcm/v5/Hint/HintCodec.sol +82 -0
  74. package/src/Xcm/v5/Instruction/Instruction.sol +1217 -0
  75. package/src/Xcm/v5/Instruction/InstructionCodec.sol +321 -0
  76. package/src/Xcm/v5/Junction/Junction.sol +258 -0
  77. package/src/Xcm/v5/Junction/JunctionCodec.sol +329 -0
  78. package/src/Xcm/v5/Junctions/Junctions.sol +12 -0
  79. package/src/Xcm/v5/Junctions/JunctionsCodec.sol +120 -0
  80. package/src/Xcm/v5/Location/Location.sol +12 -0
  81. package/src/Xcm/v5/Location/LocationCodec.sol +68 -0
  82. package/src/Xcm/v5/NetworkId/NetworkId.sol +115 -0
  83. package/src/Xcm/v5/NetworkId/NetworkIdCodec.sol +114 -0
  84. package/src/Xcm/v5/OriginKind/OriginKind.sol +14 -0
  85. package/src/Xcm/v5/OriginKind/OriginKindCodec.sol +66 -0
  86. package/src/Xcm/v5/PalletInfo/PalletInfo.sol +18 -0
  87. package/src/Xcm/v5/PalletInfo/PalletInfoCodec.sol +119 -0
  88. package/src/Xcm/v5/QueryResponseInfo/QueryResponseInfo.sol +16 -0
  89. package/src/Xcm/v5/QueryResponseInfo/QueryResponseInfoCodec.sol +91 -0
  90. package/src/Xcm/v5/Response/Response.sol +145 -0
  91. package/src/Xcm/v5/Response/ResponseCodec.sol +174 -0
  92. package/src/Xcm/v5/Types/QueryId.sol +5 -0
  93. package/src/Xcm/v5/Weight/Weight.sol +10 -0
  94. package/src/Xcm/v5/Weight/WeightCodec.sol +87 -0
  95. package/src/Xcm/v5/WeightLimit/WeightLimit.sol +48 -0
  96. package/src/Xcm/v5/WeightLimit/WeightLimitCodec.sol +88 -0
  97. package/src/Xcm/v5/WildAsset/WildAsset.sol +112 -0
  98. package/src/Xcm/v5/WildAsset/WildAssetCodec.sol +166 -0
  99. package/src/Xcm/v5/WildFungibility/WildFungibility.sol +10 -0
  100. package/src/Xcm/v5/WildFungibility/WildFungibilityCodec.sol +74 -0
  101. package/src/Xcm/v5/Xcm/Xcm.sol +27 -0
  102. package/src/Xcm/v5/Xcm/XcmCodec.sol +83 -0
  103. package/src/Xcm/v5/XcmError/XcmError.sol +122 -0
  104. package/src/Xcm/v5/XcmError/XcmErrorCodec.sol +85 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ ## Version 0.2.0
2
+
3
+ ### Added
4
+
5
+ - 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)
6
+
7
+ - Added Codecs for Bytes, Address - [#2](https://github.com/LucasGrasso/solidity-scale-codec/pull/2)
8
+
9
+ ### Changed
10
+
11
+ - 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)
12
+
13
+ - Fix typos and add `encodedSizeAt` functions to all codecs for better safety and consistency. - [#2](https://github.com/LucasGrasso/solidity-scale-codec/pull/2)
14
+
15
+ - 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
@@ -20,7 +20,7 @@ This library provides a Highly-Modular implementation of SCALE in solidity.
20
20
  | `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
21
  | `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
22
 
23
- See the [Definitions](definitions.md) for more details on the encoding of different types.
23
+ See the [Definitions](DEFINITIONS.md) for more details on the encoding of different types.
24
24
 
25
25
  ## Usage
26
26
 
@@ -28,6 +28,100 @@ See the [Definitions](definitions.md) for more details on the encoding of differ
28
28
 
29
29
  See this [example](https://github.com/LucasGrasso/solidity-scale-codec/blob/main/contracts/examples/Foo.sol).
30
30
 
31
+ ## About the libraries
32
+
33
+ ### src/LittleEndian
34
+
35
+ The `LittleEndian` library provides functions to encode and decode unsigned integers in little-endian format.
36
+
37
+ All libraries here provide the following functions:
38
+
39
+ ```solidity
40
+ function toLittleEndian(uintN value) internal pure returns (bytesM){}
41
+ function fromLittleEndian(
42
+ bytes memory data,
43
+ uint256 offset
44
+ ) internal pure returns (uintN value) {}
45
+ ```
46
+
47
+ ### src/Scale
48
+
49
+ 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.
50
+
51
+ - All Codec libraries provide the following encoding functions:
52
+
53
+ ```solidity
54
+ function encode(T value) internal pure returns (bytes memory){}
55
+ function encodedSizeAt(bytes memory data, uint256 offset) internal pure returns (uint256 size){}
56
+ ```
57
+
58
+ - Libraries for fixed length types provide the following functions for encoding:
59
+
60
+ ```solidity
61
+ function decode(bytes memory data) internal pure returns (T value){}
62
+ function decodeAt(bytes memory data, uint256 offset) internal pure returns (T value){}
63
+ ```
64
+
65
+ > Note: `decode(data)` = `decodeAt(data, 0)`
66
+
67
+ Integer libraries also provide Little-Endian encoding functions, using the `LittleEndian` library:
68
+
69
+ ```solidity
70
+ function toLittleEndian(T value) internal pure returns (bytesM){}
71
+ ```
72
+
73
+ - 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.
74
+
75
+ ```solidity
76
+ function decode(bytes memory data) internal pure returns (T value, uint256 bytesRead){}
77
+ function decodeAt(bytes memory data, uint256 offset) internal pure returns (T value, uint256 bytesRead){}
78
+ ```
79
+
80
+ > Note: `decode(data)` = `decodeAt(data, 0)`
81
+
82
+ ### src/Xcm
83
+
84
+ The `Xcm` library contains SCALE-compatible Solidity representations and codecs for XCM types.
85
+
86
+ Current support includes:
87
+
88
+ - XCM v5 domain types in `src/Xcm/v5/*` (instructions, locations, assets, responses, errors, weights, and related codecs).
89
+ - A versioned wrapper in `src/Xcm/VersionedXcm/*`.
90
+
91
+ Implementation notes:
92
+
93
+ - Enum-like XCM types are represented as structs with a type discriminator plus `bytes payload`.
94
+ - Each type has a codec library with `encode`, `encodedSizeAt`, `decode`, and `decodeAt`.
95
+ - `VersionedXcm` currently supports v5 payloads.
96
+
97
+ Minimal usage example:
98
+
99
+ ```solidity
100
+ import {Instruction} from "../src/Xcm/v5/Instruction/Instruction.sol";
101
+ import {Xcm, fromInstructions} from "../src/Xcm/v5/Xcm/Xcm.sol";
102
+ import {v5} from "../src/Xcm/VersionedXcm/VersionedXcm.sol";
103
+ import {VersionedXcmCodec} from "../src/Xcm/VersionedXcm/VersionedXcmCodec.sol";
104
+ import {Weight} from "../src/Xcm/v5/Weight/Weight.sol";
105
+ import {WeightCodec} from "../src/Xcm/v5/Weight/WeightCodec.sol";
106
+
107
+ address constant XCM_PRECOMPILE_ADDRESS = 0x00000000000000000000000000000000000a0000;
108
+
109
+ contract XcmWeightEstimator {
110
+ function weighMessage(
111
+ Instruction[] memory instructions
112
+ ) external view returns (Weight memory) {
113
+ Xcm memory xcm = fromInstructions(instructions);
114
+ (bool success, bytes memory result) = XCM_PRECOMPILE_ADDRESS.staticcall(
115
+ VersionedXcmCodec.encode(v5(xcm))
116
+ );
117
+ require(success, "XCM precompile call failed");
118
+ (Weight memory weight, ) = WeightCodec.decode(result);
119
+ return weight;
120
+ }
121
+ }
122
+
123
+ ```
124
+
31
125
  ### Running Tests
32
126
 
33
127
  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.1.3",
3
+ "version": "0.2.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,8 @@
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"
31
36
  },
32
37
  "type": "module",
33
38
  "devDependencies": {
@@ -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 toLE(uint128 value) internal pure returns (bytes16 result) {
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 fromLE(
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 toLE(uint16 value) internal pure returns (bytes2) {
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 fromLE(
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 toLE(uint256 value) internal pure returns (bytes32 result) {
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 fromLE(
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 toLE(uint32 value) internal pure returns (bytes4 result) {
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 fromLE(
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 toLE(uint64 value) internal pure returns (bytes8 result) {
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 fromLE(
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 toLE(uint8 value) internal pure returns (bytes1) {
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 fromLE(
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
+ }
@@ -0,0 +1,4 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.28;
3
+
4
+ import {Address} from "./Address/Address.sol";
@@ -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 InvalidBoolArrLenght();
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 InvalidBoolArrLenght();
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 InvalidI128ArrLenght();
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 InvalidI128ArrLenght();
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 InvalidI16ArrLenght();
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 InvalidI16ArrLenght();
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 InvalidI256ArrLenght();
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 InvalidI256ArrLenght();
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) {
@@ -8,7 +8,7 @@ import {I32} from "../Signed.sol";
8
8
  /// @notice SCALE-compliant encoder/decoder for the `int32[]` type.
9
9
  /// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
10
10
  library I32Arr {
11
- error InvalidI32ArrLenght();
11
+ error InvalidI32ArrLength();
12
12
 
13
13
  using I32 for int32;
14
14
 
@@ -23,6 +23,20 @@ library I32Arr {
23
23
  return result;
24
24
  }
25
25
 
26
+ /// @notice Returns the number of bytes that a `int32[]` would occupy when SCALE-encoded.
27
+ /// @param data The byte sequence containing the encoded `int32[]`.
28
+ /// @param offset The starting index in `data` from which to calculate the encoded size of the `int32[]`.
29
+ /// @return The number of bytes that the `int32[]` 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 * 4);
36
+ if (offset + totalSize > data.length) revert InvalidI32ArrLength();
37
+ return totalSize;
38
+ }
39
+
26
40
  /// @notice Decodes an `int32[]` from SCALE format.
27
41
  /// @param data The SCALE-encoded byte sequence.
28
42
  /// @return arr The decoded array of `int32`.
@@ -45,7 +59,7 @@ library I32Arr {
45
59
  (uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
46
60
  uint256 pos = offset + compactBytes;
47
61
 
48
- if (pos + (length * 4) > data.length) revert InvalidI32ArrLenght();
62
+ if (pos + (length * 4) > data.length) revert InvalidI32ArrLength();
49
63
 
50
64
  arr = new int32[](length);
51
65
  for (uint256 i = 0; i < length; ++i) {