@rootzero/contracts 1.25.0 → 1.26.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 +101 -0
- package/Codec.sol +1 -2
- package/Endpoints.sol +2 -0
- package/README.md +61 -51
- package/Utils.sol +2 -1
- package/codec/Blocks.sol +276 -88
- package/codec/Buffers.sol +24 -20
- package/codec/Decoders.sol +35 -37
- package/codec/Descriptors.sol +75 -72
- package/codec/Keys.sol +5 -1
- package/codec/Schema.sol +5 -1
- package/codec/Specs.sol +19 -9
- package/codec/Writers.sol +14 -19
- package/commands/Allocate.sol +8 -7
- package/commands/Base.sol +14 -49
- package/commands/Bootstrap.sol +95 -0
- package/commands/Burn.sol +7 -7
- package/commands/Cashout.sol +85 -0
- package/commands/Credit.sol +18 -16
- package/commands/Debit.sol +23 -19
- package/commands/Deposit.sol +13 -13
- package/commands/Payout.sol +8 -8
- package/commands/Provision.sol +13 -13
- package/commands/Recover.sol +7 -7
- package/commands/Relay.sol +22 -23
- package/commands/Repay.sol +36 -34
- package/commands/Settle.sol +24 -22
- package/commands/Withdraw.sol +7 -7
- package/commands/admin/AllowAssets.sol +7 -7
- package/commands/admin/Allowance.sol +7 -7
- package/commands/admin/Annotate.sol +7 -7
- package/commands/admin/Appoint.sol +7 -7
- package/commands/admin/Authorize.sol +7 -7
- package/commands/admin/Base.sol +5 -8
- package/commands/admin/DenyAssets.sol +7 -7
- package/commands/admin/Dismiss.sol +7 -7
- package/commands/admin/Execute.sol +8 -8
- package/commands/admin/Unauthorize.sol +7 -7
- package/core/Calls.sol +3 -3
- package/core/Endpoint.sol +7 -7
- package/core/Pipeline.sol +19 -20
- package/execution/Budget.sol +2 -3
- package/execution/Execution.sol +271 -509
- package/guards/Base.sol +1 -1
- package/guards/Revoke.sol +7 -7
- package/package.json +1 -1
- package/ports/Allowance.sol +3 -3
- package/ports/Assets.sol +7 -7
- package/ports/Base.sol +1 -1
- package/ports/Credit.sol +3 -3
- package/ports/Debit.sol +3 -3
- package/ports/Dispatch.sol +3 -3
- package/ports/Pipe.sol +3 -3
- package/ports/Post.sol +3 -3
- package/ports/Redeem.sol +3 -3
- package/queries/Assets.sol +3 -3
- package/queries/Balances.sol +3 -3
- package/queries/Base.sol +1 -1
- package/utils/Accounts.sol +1 -3
- package/utils/Actions.sol +2 -0
- package/utils/Assets.sol +1 -10
- package/utils/Cursors.sol +60 -116
- package/utils/Errors.sol +50 -0
- package/utils/Ids.sol +2 -5
- package/utils/Lanes.sol +0 -2
- package/utils/Nodes.sol +1 -3
- package/utils/Utils.sol +2 -9
- package/codec/Readers.sol +0 -190
package/utils/Cursors.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {MissingCursor, OutOfBounds, UnexpectedPosition, ValueOverflow} from "./Errors.sol";
|
|
5
5
|
|
|
6
6
|
/// @notice Mutable memory wrapper around a packed cursor.
|
|
7
7
|
/// @dev A second tagged cursor may occupy the upper 128-bit lane of `state`.
|
|
@@ -17,7 +17,8 @@ struct Cur {
|
|
|
17
17
|
/// bits 0-31 i
|
|
18
18
|
/// bits 32-63 offset
|
|
19
19
|
/// bits 64-95 len
|
|
20
|
-
/// bits 96-
|
|
20
|
+
/// bits 96-103 stride (optional blocks per group)
|
|
21
|
+
/// bits 104-111 reserved
|
|
21
22
|
/// bits 112-119 flags (consumer-defined)
|
|
22
23
|
/// bits 120-127 tag
|
|
23
24
|
///
|
|
@@ -27,15 +28,6 @@ struct Cur {
|
|
|
27
28
|
/// inspection operations target it, and `select` swaps a requested tagged
|
|
28
29
|
/// cursor into that position while preserving the pair.
|
|
29
30
|
///
|
|
30
|
-
/// A mark is a standalone cursor value used as an immutable positional
|
|
31
|
-
/// reference. It retains the cursor's offset, length, count, flags, and tag,
|
|
32
|
-
/// but may carry a different `i`. A mark has no intrinsic boundary or movement
|
|
33
|
-
/// semantics; callers may later use its position for comparison, validation,
|
|
34
|
-
/// seeking, or another operation. Because it has the ordinary single-cursor
|
|
35
|
-
/// layout, existing positional decoding and absolute-position rules also apply
|
|
36
|
-
/// to marks. A zero mark identifies the empty cursor at position zero; `before`
|
|
37
|
-
/// therefore treats it as already reached.
|
|
38
|
-
///
|
|
39
31
|
/// Cursor navigation assumes packed cursor inputs satisfy `i <= len`.
|
|
40
32
|
/// Constructors and composition helpers establish this invariant, and navigation
|
|
41
33
|
/// helpers preserve it. Manually constructing or modifying packed cursor words
|
|
@@ -43,33 +35,20 @@ struct Cur {
|
|
|
43
35
|
///
|
|
44
36
|
/// The zero word represents an absent cursor.
|
|
45
37
|
library Cursors {
|
|
46
|
-
/// @dev A cursor position exceeds its logical length.
|
|
47
|
-
error OutOfBounds();
|
|
48
|
-
|
|
49
|
-
/// @dev A cursor is not positioned at the expected offset.
|
|
50
|
-
error UnexpectedPosition();
|
|
51
|
-
|
|
52
|
-
/// @dev Paired cursors must have different identity tags.
|
|
53
|
-
error DuplicateTag(uint8 tag);
|
|
54
|
-
|
|
55
|
-
/// @dev Neither packed cursor matches the requested identity.
|
|
56
|
-
error MissingCursor();
|
|
57
|
-
|
|
58
38
|
// Creation and sources
|
|
59
39
|
|
|
60
40
|
/// @notice Create a cursor positioned at its beginning.
|
|
61
41
|
/// @param offset Absolute source or buffer offset.
|
|
62
42
|
/// @param len Logical byte length.
|
|
63
|
-
/// @param
|
|
43
|
+
/// @param stride Optional blocks per group associated with the region.
|
|
64
44
|
/// @param flags Consumer-defined flags.
|
|
65
45
|
/// @param tag Cursor identity tag.
|
|
66
46
|
/// @return cur Packed cursor.
|
|
67
|
-
function create(uint offset, uint len,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
cur
|
|
72
|
-
cur |= uint(tag) << 120;
|
|
47
|
+
function create(uint offset, uint len, uint8 stride, uint8 flags, uint8 tag) internal pure returns (uint cur) {
|
|
48
|
+
if (offset > type(uint32).max || len > type(uint32).max) {
|
|
49
|
+
revert ValueOverflow();
|
|
50
|
+
}
|
|
51
|
+
cur = (offset << 32) | (len << 64) | (uint(stride) << 96) | (uint(flags) << 112) | (uint(tag) << 120);
|
|
73
52
|
}
|
|
74
53
|
|
|
75
54
|
/// @notice Return the absolute calldata position where `source` begins.
|
|
@@ -86,17 +65,30 @@ library Cursors {
|
|
|
86
65
|
/// @return abs Absolute start position.
|
|
87
66
|
/// @return end Absolute exclusive end position.
|
|
88
67
|
function bounds(bytes calldata source) internal pure returns (uint abs, uint end) {
|
|
89
|
-
|
|
90
|
-
|
|
68
|
+
assembly ("memory-safe") {
|
|
69
|
+
abs := source.offset
|
|
70
|
+
end := add(abs, source.length)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// @notice Return the absolute start and exclusive end of the lower cursor frame.
|
|
75
|
+
/// @dev Ignores the cursor's current relative position and any upper cursor.
|
|
76
|
+
/// @param cur Packed cursor or cursor pair whose active frame is inspected.
|
|
77
|
+
/// @return abs Absolute frame start position.
|
|
78
|
+
/// @return end Absolute exclusive frame end position.
|
|
79
|
+
function bounds(uint cur) internal pure returns (uint abs, uint end) {
|
|
80
|
+
abs = uint32(cur >> 32);
|
|
81
|
+
end = abs + uint32(cur >> 64);
|
|
91
82
|
}
|
|
92
83
|
|
|
93
84
|
/// @notice Create a cursor backed by a calldata slice.
|
|
94
85
|
/// @param source Calldata slice represented by the cursor.
|
|
95
|
-
/// @param flags Consumer-defined flags.
|
|
96
86
|
/// @param tag Cursor identity tag.
|
|
97
87
|
/// @return cur Packed cursor positioned at the slice beginning.
|
|
98
|
-
function wrap(bytes calldata source, uint8
|
|
99
|
-
|
|
88
|
+
function wrap(bytes calldata source, uint8 tag) internal pure returns (uint cur) {
|
|
89
|
+
assembly ("memory-safe") {
|
|
90
|
+
cur := or(or(shl(32, source.offset), shl(64, source.length)), shl(120, tag))
|
|
91
|
+
}
|
|
100
92
|
}
|
|
101
93
|
|
|
102
94
|
// Inspection
|
|
@@ -115,9 +107,9 @@ library Cursors {
|
|
|
115
107
|
/// @notice Return the active cursor without its position.
|
|
116
108
|
/// @dev Ignores the upper cursor when `cur` is a pair.
|
|
117
109
|
/// @param cur Packed cursor or cursor pair.
|
|
118
|
-
/// @return The lower cursor's offset, length,
|
|
110
|
+
/// @return The lower cursor's offset, length, stride, flags, and tag.
|
|
119
111
|
function frame(uint cur) internal pure returns (uint) {
|
|
120
|
-
return
|
|
112
|
+
return uint128(cur) & ~uint(type(uint32).max);
|
|
121
113
|
}
|
|
122
114
|
|
|
123
115
|
/// @notice Return the absolute position of the lower cursor as `offset + i`.
|
|
@@ -128,22 +120,17 @@ library Cursors {
|
|
|
128
120
|
return uint32(cur) + uint32(cur >> 32);
|
|
129
121
|
}
|
|
130
122
|
|
|
131
|
-
/// @notice Decode the consumer
|
|
123
|
+
/// @notice Decode the optional stride, consumer flags, and identity tag.
|
|
132
124
|
/// @param cur Packed cursor or cursor pair.
|
|
133
|
-
/// @return
|
|
125
|
+
/// @return stride Optional blocks per group.
|
|
134
126
|
/// @return flags Consumer-defined flags.
|
|
135
127
|
/// @return tag Cursor identity tag.
|
|
136
|
-
function meta(uint cur) internal pure returns (
|
|
137
|
-
|
|
128
|
+
function meta(uint cur) internal pure returns (uint8 stride, uint8 flags, uint8 tag) {
|
|
129
|
+
stride = uint8(cur >> 96);
|
|
138
130
|
flags = uint8(cur >> 112);
|
|
139
131
|
tag = uint8(cur >> 120);
|
|
140
132
|
}
|
|
141
133
|
|
|
142
|
-
/// @notice Return the opaque item count attached to the active cursor.
|
|
143
|
-
function count(uint cur) internal pure returns (uint) {
|
|
144
|
-
return uint16(cur >> 96);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
134
|
/// @notice Return whether both packed cursors remain at their initial positions.
|
|
148
135
|
/// @param cur Packed cursor or cursor pair.
|
|
149
136
|
/// @return Whether both lane positions are zero.
|
|
@@ -162,7 +149,7 @@ library Cursors {
|
|
|
162
149
|
/// @param cur Packed cursor or cursor pair.
|
|
163
150
|
/// @return Whether either lane has bytes remaining.
|
|
164
151
|
function any(uint cur) internal pure returns (bool) {
|
|
165
|
-
return
|
|
152
|
+
return uint32(cur) < uint32(cur >> 64) || uint32(cur >> 128) < uint32(cur >> 192);
|
|
166
153
|
}
|
|
167
154
|
|
|
168
155
|
/// @notice Require the lower cursor to be positioned at `i`.
|
|
@@ -176,7 +163,7 @@ library Cursors {
|
|
|
176
163
|
/// @param cur Packed cursor or cursor pair.
|
|
177
164
|
/// @param abs Expected absolute position.
|
|
178
165
|
function expectAbs(uint cur, uint abs) internal pure {
|
|
179
|
-
if (
|
|
166
|
+
if (uint32(cur) + uint32(cur >> 32) != abs) revert UnexpectedPosition();
|
|
180
167
|
}
|
|
181
168
|
|
|
182
169
|
/// @notice Return whether the lower cursor contains `flag`.
|
|
@@ -189,14 +176,6 @@ library Cursors {
|
|
|
189
176
|
|
|
190
177
|
// Navigation
|
|
191
178
|
|
|
192
|
-
/// @dev Return `cur` after ensuring its lower position does not exceed its length.
|
|
193
|
-
/// @param cur Packed cursor or cursor pair.
|
|
194
|
-
/// @return Validated cursor unchanged.
|
|
195
|
-
function validate(uint cur) private pure returns (uint) {
|
|
196
|
-
if (uint32(cur) > uint32(cur >> 64)) revert OutOfBounds();
|
|
197
|
-
return cur;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
179
|
/// @notice Move the lower cursor forward to `i`.
|
|
201
180
|
/// @param cur Packed cursor or cursor pair.
|
|
202
181
|
/// @param i New relative position; must not move backward.
|
|
@@ -205,7 +184,7 @@ library Cursors {
|
|
|
205
184
|
uint current = uint32(cur);
|
|
206
185
|
uint len = uint32(cur >> 64);
|
|
207
186
|
if (i < current || i > len) revert OutOfBounds();
|
|
208
|
-
updated =
|
|
187
|
+
updated = (cur & ~uint(type(uint32).max)) | i;
|
|
209
188
|
}
|
|
210
189
|
|
|
211
190
|
/// @notice Replace the lower cursor's position using an absolute position.
|
|
@@ -215,7 +194,9 @@ library Cursors {
|
|
|
215
194
|
function seekAbs(uint cur, uint abs) internal pure returns (uint updated) {
|
|
216
195
|
uint offset = uint32(cur >> 32);
|
|
217
196
|
if (abs < offset) revert OutOfBounds();
|
|
218
|
-
|
|
197
|
+
uint i = abs - offset;
|
|
198
|
+
if (i < uint32(cur) || i > uint32(cur >> 64)) revert OutOfBounds();
|
|
199
|
+
updated = (cur & ~uint(type(uint32).max)) | i;
|
|
219
200
|
}
|
|
220
201
|
|
|
221
202
|
/// @notice Advance the current position of the lower cursor.
|
|
@@ -236,8 +217,9 @@ library Cursors {
|
|
|
236
217
|
/// @param len New logical length.
|
|
237
218
|
/// @return updated Cursor with the replaced length.
|
|
238
219
|
function resize(uint cur, uint len) internal pure returns (uint updated) {
|
|
239
|
-
if (
|
|
240
|
-
|
|
220
|
+
if (len > type(uint32).max) revert ValueOverflow();
|
|
221
|
+
if (uint32(cur) > len) revert OutOfBounds();
|
|
222
|
+
updated = (cur & ~(uint(type(uint32).max) << 64)) | (len << 64);
|
|
241
223
|
}
|
|
242
224
|
|
|
243
225
|
/// @notice Create a child cursor over `[start, end)` within the lower cursor.
|
|
@@ -250,30 +232,15 @@ library Cursors {
|
|
|
250
232
|
/// @param tag Child identity tag.
|
|
251
233
|
/// @return child Packed child cursor.
|
|
252
234
|
function slice(uint cur, uint start, uint end, uint8 tag) internal pure returns (uint child) {
|
|
253
|
-
|
|
235
|
+
uint offset = uint32(cur >> 32);
|
|
236
|
+
uint len = uint32(cur >> 64);
|
|
254
237
|
if (start > end || end > len) revert OutOfBounds();
|
|
255
|
-
|
|
238
|
+
uint childOffset = offset + start;
|
|
239
|
+
if (childOffset > type(uint32).max) revert ValueOverflow();
|
|
240
|
+
child = (childOffset << 32) | ((end - start) << 64) | (uint(tag) << 120);
|
|
256
241
|
}
|
|
257
242
|
|
|
258
|
-
//
|
|
259
|
-
|
|
260
|
-
/// @notice Combine two cursors into one packed word.
|
|
261
|
-
/// @dev Zero represents absence and acts as the identity value.
|
|
262
|
-
/// @param low Cursor placed in the lower lane.
|
|
263
|
-
/// @param high Cursor placed in the higher lane.
|
|
264
|
-
/// @return cur Packed cursor pair, or the nonzero cursor when one is absent.
|
|
265
|
-
function pair(uint low, uint high) internal pure returns (uint cur) {
|
|
266
|
-
low = validate(max128(low));
|
|
267
|
-
high = validate(max128(high));
|
|
268
|
-
|
|
269
|
-
if (low == 0) return high;
|
|
270
|
-
if (high == 0) return low;
|
|
271
|
-
|
|
272
|
-
uint8 tag = uint8(low >> 120);
|
|
273
|
-
if (tag == uint8(high >> 120)) revert DuplicateTag(tag);
|
|
274
|
-
|
|
275
|
-
cur = low | (high << 128);
|
|
276
|
-
}
|
|
243
|
+
// Selection
|
|
277
244
|
|
|
278
245
|
/// @notice Swap the lower and higher cursors.
|
|
279
246
|
/// @param cur Packed cursor pair.
|
|
@@ -299,41 +266,10 @@ library Cursors {
|
|
|
299
266
|
function select(uint cur, uint8 expected) internal pure returns (uint updated) {
|
|
300
267
|
if (uint8(cur >> 120) == expected) return cur;
|
|
301
268
|
|
|
302
|
-
updated =
|
|
269
|
+
updated = (cur << 128) | (cur >> 128);
|
|
303
270
|
if (uint8(updated >> 120) != expected) revert MissingCursor();
|
|
304
271
|
}
|
|
305
272
|
|
|
306
|
-
// Marks
|
|
307
|
-
|
|
308
|
-
/// @notice Select the live cursor whose frame matches the active cursor in `mark`.
|
|
309
|
-
/// @dev Only the lower 128 bits of `mark` are considered. The returned value
|
|
310
|
-
/// preserves the cursor pair and places the matching cursor in the lower half.
|
|
311
|
-
/// A zero frame may select an empty cursor lane.
|
|
312
|
-
/// @param cur Packed cursor or cursor pair to search.
|
|
313
|
-
/// @param mark Cursor-shaped positional reference to match.
|
|
314
|
-
/// @return located Cursor pair with the matching cursor active.
|
|
315
|
-
function locate(uint cur, uint mark) internal pure returns (uint located) {
|
|
316
|
-
uint expected = frame(mark);
|
|
317
|
-
if (frame(cur) == expected) return cur;
|
|
318
|
-
|
|
319
|
-
located = swap(cur);
|
|
320
|
-
if (frame(located) != expected) revert MissingCursor();
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/// @notice Return whether a matched cursor is positioned before `mark`.
|
|
324
|
-
/// @dev Returns false at the mark and reverts after it. Only the active lower
|
|
325
|
-
/// cursor in `mark` participates in the comparison. A zero mark represents
|
|
326
|
-
/// the already-reached position of an empty cursor.
|
|
327
|
-
/// @param cur Packed cursor or cursor pair containing the marked cursor.
|
|
328
|
-
/// @param mark Cursor-shaped positional reference.
|
|
329
|
-
/// @return Whether the live cursor position precedes the marked position.
|
|
330
|
-
function before(uint cur, uint mark) internal pure returns (bool) {
|
|
331
|
-
uint i = uint32(locate(cur, mark));
|
|
332
|
-
uint target = uint32(mark);
|
|
333
|
-
if (i > target) revert OutOfBounds();
|
|
334
|
-
return i < target;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
273
|
// Consumption
|
|
338
274
|
|
|
339
275
|
/// @notice Return a cursor's absolute position and advance it.
|
|
@@ -343,8 +279,11 @@ library Cursors {
|
|
|
343
279
|
/// @return updated Cursor advanced by `amount`.
|
|
344
280
|
/// @return abs Absolute pre-advance position.
|
|
345
281
|
function consume(uint cur, uint amount) internal pure returns (uint updated, uint abs) {
|
|
346
|
-
|
|
347
|
-
|
|
282
|
+
uint i = uint32(cur);
|
|
283
|
+
uint len = uint32(cur >> 64);
|
|
284
|
+
if (amount > len - i) revert OutOfBounds();
|
|
285
|
+
abs = uint32(cur >> 32) + i;
|
|
286
|
+
updated = cur + amount;
|
|
348
287
|
}
|
|
349
288
|
|
|
350
289
|
/// @notice Select a tagged cursor, return its absolute position, and advance it.
|
|
@@ -355,6 +294,11 @@ library Cursors {
|
|
|
355
294
|
/// @return abs Absolute pre-advance position in the selected lane.
|
|
356
295
|
function consume(uint cur, uint8 tag, uint amount) internal pure returns (uint updated, uint abs) {
|
|
357
296
|
updated = select(cur, tag);
|
|
358
|
-
|
|
297
|
+
|
|
298
|
+
uint i = uint32(updated);
|
|
299
|
+
uint len = uint32(updated >> 64);
|
|
300
|
+
if (amount > len - i) revert OutOfBounds();
|
|
301
|
+
abs = uint32(updated >> 32) + i;
|
|
302
|
+
updated += amount;
|
|
359
303
|
}
|
|
360
304
|
}
|
package/utils/Errors.sol
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
/// @dev Thrown when an operation attempts to spend more value than remains.
|
|
5
|
+
error InsufficientValue();
|
|
6
|
+
|
|
7
|
+
/// @dev Thrown when a decoder or execution is finalized with unread data.
|
|
8
|
+
error UnconsumedData();
|
|
9
|
+
|
|
10
|
+
/// @dev Thrown when an ID does not match the expected convention or type.
|
|
11
|
+
error InvalidId();
|
|
12
|
+
|
|
13
|
+
/// @dev Thrown when an operation exceeds its logical data boundary.
|
|
14
|
+
error OutOfBounds();
|
|
15
|
+
|
|
16
|
+
/// @dev Thrown when a value exceeds the target integer width.
|
|
17
|
+
error ValueOverflow();
|
|
18
|
+
|
|
19
|
+
/// @dev Thrown when a value is not evenly divisible by its divisor.
|
|
20
|
+
error NotDivisible();
|
|
21
|
+
|
|
22
|
+
/// @dev Thrown when an identifier contains a zero address.
|
|
23
|
+
error ZeroAddress();
|
|
24
|
+
|
|
25
|
+
/// @dev Thrown when an address does not contain deployed bytecode.
|
|
26
|
+
error InvalidContract();
|
|
27
|
+
|
|
28
|
+
/// @dev Thrown when an account ID does not match the expected family or type.
|
|
29
|
+
error InvalidAccount();
|
|
30
|
+
|
|
31
|
+
/// @dev Thrown when an asset ID does not match the expected type or chain.
|
|
32
|
+
error InvalidAsset();
|
|
33
|
+
|
|
34
|
+
/// @dev Thrown when an asset is not authorized for an operation.
|
|
35
|
+
error UnauthorizedAsset();
|
|
36
|
+
|
|
37
|
+
/// @dev Thrown when a required nonzero amount is zero.
|
|
38
|
+
error ZeroAmount();
|
|
39
|
+
|
|
40
|
+
/// @dev Thrown when an amount falls outside its allowed range.
|
|
41
|
+
error BadAmount(uint amount);
|
|
42
|
+
|
|
43
|
+
/// @dev Thrown when an opaque ID preimage is missing or unsupported.
|
|
44
|
+
error InvalidPreimage();
|
|
45
|
+
|
|
46
|
+
/// @dev Thrown when a cursor is not positioned at the expected offset.
|
|
47
|
+
error UnexpectedPosition();
|
|
48
|
+
|
|
49
|
+
/// @dev Thrown when no packed cursor matches a requested identity.
|
|
50
|
+
error MissingCursor();
|
package/utils/Ids.sol
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
+
import {InvalidId, InvalidPreimage} from "./Errors.sol";
|
|
5
|
+
|
|
4
6
|
/// @title Ids
|
|
5
7
|
/// @notice Shared helpers for the protocol-wide 256-bit ID convention.
|
|
6
8
|
///
|
|
@@ -10,11 +12,6 @@ pragma solidity ^0.8.33;
|
|
|
10
12
|
/// Opaque keccak preimages start with `0x01`, and the ID is derived as:
|
|
11
13
|
/// `0x00 || bytes31(keccak256(preimage))`
|
|
12
14
|
library Ids {
|
|
13
|
-
/// @dev Thrown when an ID does not match the expected convention.
|
|
14
|
-
error InvalidId();
|
|
15
|
-
/// @dev Thrown when an opaque ID preimage is missing or uses an unsupported format/hash tag.
|
|
16
|
-
error InvalidPreimage();
|
|
17
|
-
|
|
18
15
|
/// @dev Preimage format/hash tag for keccak256-derived opaque IDs.
|
|
19
16
|
uint8 constant Keccak = 0x01;
|
|
20
17
|
|
package/utils/Lanes.sol
CHANGED
|
@@ -9,6 +9,4 @@ library Lanes {
|
|
|
9
9
|
uint8 internal constant State = 2;
|
|
10
10
|
/// @dev Writer lane containing regular endpoint output blocks.
|
|
11
11
|
uint8 internal constant Output = 3;
|
|
12
|
-
/// @dev Writer lane containing deferred transaction blocks.
|
|
13
|
-
uint8 internal constant Transactions = 4;
|
|
14
12
|
}
|
package/utils/Nodes.sol
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {Layout} from "./Layout.sol";
|
|
5
|
+
import {InvalidId} from "./Errors.sol";
|
|
5
6
|
import {Ids} from "./Ids.sol";
|
|
6
7
|
import {ensureAddr, isFamily, matchesBase, toLocalBase} from "./Utils.sol";
|
|
7
8
|
|
|
@@ -20,9 +21,6 @@ import {ensureAddr, isFamily, matchesBase, toLocalBase} from "./Utils.sol";
|
|
|
20
21
|
///
|
|
21
22
|
/// The helpers in this library validate and deconstruct structured node IDs.
|
|
22
23
|
library Nodes {
|
|
23
|
-
/// @dev Thrown when an ID does not match the expected node type or chain.
|
|
24
|
-
error InvalidId();
|
|
25
|
-
|
|
26
24
|
/// @dev 24-bit family tag shared by all node types (Evm + Node category).
|
|
27
25
|
uint24 constant Family = (uint24(Layout.Evm) << 8) | uint24(Layout.Node);
|
|
28
26
|
/// @dev Full 4-byte type prefix for chain/domain nodes.
|
package/utils/Utils.sol
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
+
import {InvalidContract, NotDivisible, ValueOverflow, ZeroAddress} from "./Errors.sol";
|
|
5
|
+
|
|
4
6
|
// Basis-points denominator: 10_000 BPS == 100.00%.
|
|
5
7
|
uint16 constant MAX_BPS = 10_000;
|
|
6
8
|
|
|
7
|
-
/// @dev Thrown by max* helpers when a value exceeds the target integer width.
|
|
8
|
-
error ValueOverflow();
|
|
9
|
-
/// @dev Thrown by `divisible` when `n` is not evenly divisible by `divisor`.
|
|
10
|
-
error NotDivisible();
|
|
11
|
-
/// @dev Thrown when an ID claims to carry an address but the embedded address is zero.
|
|
12
|
-
error ZeroAddress();
|
|
13
|
-
/// @dev Thrown when an address does not contain deployed bytecode.
|
|
14
|
-
error InvalidContract();
|
|
15
|
-
|
|
16
9
|
/// @notice Assert that `value` fits in uint8 and return it as uint8.
|
|
17
10
|
function max8(uint value) pure returns (uint8) {
|
|
18
11
|
if (value > type(uint8).max) {
|
package/codec/Readers.sol
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import {Sizes, Specs} from "./Specs.sol";
|
|
5
|
-
import {Keys} from "./Keys.sol";
|
|
6
|
-
|
|
7
|
-
/// @notice Mutable reader over a block stream stored in memory.
|
|
8
|
-
/// All positions (`i`) are byte offsets relative to the start of `source`.
|
|
9
|
-
struct Reader {
|
|
10
|
-
/// @dev Current read position, relative to the source start.
|
|
11
|
-
uint i;
|
|
12
|
-
/// @dev Memory bytes containing the complete source region.
|
|
13
|
-
bytes source;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
using Readers for Reader;
|
|
17
|
-
|
|
18
|
-
/// @title Readers
|
|
19
|
-
/// @notice Memory block stream parser for the rootzero protocol.
|
|
20
|
-
/// A `Reader` advances through an existing `bytes memory` source without copying its contents.
|
|
21
|
-
/// Blocks are encoded as `[bytes4 key][bytes4 payloadLen][payload]`.
|
|
22
|
-
library Readers {
|
|
23
|
-
/// @dev The current block has a truncated header or payload, an unexpected key,
|
|
24
|
-
/// or a payload size outside the accepted range.
|
|
25
|
-
error InvalidBlock();
|
|
26
|
-
|
|
27
|
-
/// @notice Create a reader backed by a memory byte array.
|
|
28
|
-
/// @param source Memory bytes containing the block stream.
|
|
29
|
-
/// @return cur Reader positioned at the beginning of `source`.
|
|
30
|
-
function open(bytes memory source) internal pure returns (Reader memory cur) {
|
|
31
|
-
cur.source = source;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/// @notice Return whether the reader has consumed its entire source.
|
|
35
|
-
/// @param cur Reader whose position should be checked.
|
|
36
|
-
/// @return Whether `cur.i` equals the source length.
|
|
37
|
-
function done(Reader memory cur) internal pure returns (bool) {
|
|
38
|
-
return cur.i == cur.source.length;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/// @notice Return whether the reader has bytes left to consume.
|
|
42
|
-
/// @param cur Reader whose position should be checked.
|
|
43
|
-
/// @return Whether `cur.i` differs from the source length.
|
|
44
|
-
function more(Reader memory cur) internal pure returns (bool) {
|
|
45
|
-
return cur.i != cur.source.length;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/// @notice Return whether the current block has `key` and an empty payload.
|
|
49
|
-
/// @param cur Reader inspected without advancing.
|
|
50
|
-
/// @param key Expected block key.
|
|
51
|
-
/// @return Whether a complete matching empty block header occurs at the current position.
|
|
52
|
-
function isEmpty(Reader memory cur, bytes4 key) internal pure returns (bool) {
|
|
53
|
-
bytes memory source = cur.source;
|
|
54
|
-
uint i = cur.i;
|
|
55
|
-
if (i > source.length || source.length - i < Sizes.Header) return false;
|
|
56
|
-
|
|
57
|
-
uint header;
|
|
58
|
-
assembly ("memory-safe") {
|
|
59
|
-
header := mload(add(add(source, 0x20), i))
|
|
60
|
-
}
|
|
61
|
-
return bytes4(uint32(header >> 224)) == key && uint32(header >> 192) == 0;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/// @notice Consume a matching empty block from the reader when present.
|
|
65
|
-
/// @param cur Reader advanced only when the matching block is empty.
|
|
66
|
-
/// @param key Expected block key.
|
|
67
|
-
/// @return Whether an empty block was consumed.
|
|
68
|
-
function tryConsumeEmpty(Reader memory cur, bytes4 key) internal pure returns (bool) {
|
|
69
|
-
bytes memory source = cur.source;
|
|
70
|
-
uint i = cur.i;
|
|
71
|
-
if (i > source.length || source.length - i < Sizes.Header) revert InvalidBlock();
|
|
72
|
-
|
|
73
|
-
bytes4 current;
|
|
74
|
-
uint len;
|
|
75
|
-
assembly ("memory-safe") {
|
|
76
|
-
let header := mload(add(add(source, 0x20), i))
|
|
77
|
-
current := header
|
|
78
|
-
len := and(shr(192, header), 0xffffffff)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (len > source.length - i - Sizes.Header) revert InvalidBlock();
|
|
82
|
-
if (current != key || len != 0) return false;
|
|
83
|
-
cur.i += Sizes.Header;
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/// @notice Validate and consume the current block, advancing `cur.i` past it.
|
|
88
|
-
/// @param cur Reader to advance.
|
|
89
|
-
/// @param key Expected block key.
|
|
90
|
-
/// @param min Minimum payload length.
|
|
91
|
-
/// @param max Maximum payload length; zero means unbounded.
|
|
92
|
-
/// @return abs Absolute memory address of the payload start.
|
|
93
|
-
function consume(
|
|
94
|
-
Reader memory cur,
|
|
95
|
-
bytes4 key,
|
|
96
|
-
uint min,
|
|
97
|
-
uint max
|
|
98
|
-
) private pure returns (uint abs) {
|
|
99
|
-
bytes memory source = cur.source;
|
|
100
|
-
uint i = cur.i;
|
|
101
|
-
|
|
102
|
-
if (i > source.length || source.length - i < Sizes.Header) revert InvalidBlock();
|
|
103
|
-
|
|
104
|
-
bytes4 current;
|
|
105
|
-
uint len;
|
|
106
|
-
assembly ("memory-safe") {
|
|
107
|
-
let header := mload(add(add(source, 0x20), i))
|
|
108
|
-
current := header
|
|
109
|
-
len := and(shr(192, header), 0xffffffff)
|
|
110
|
-
abs := add(add(source, 0x28), i)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (current != key || len < min || (max != 0 && len > max)) revert InvalidBlock();
|
|
114
|
-
if (len > source.length - i - Sizes.Header) revert InvalidBlock();
|
|
115
|
-
cur.i = i + Sizes.Header + len;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/// @notice Validate and consume the current block described by `spec`.
|
|
119
|
-
function consume(Reader memory cur, uint spec) internal pure returns (uint abs) {
|
|
120
|
-
(bytes4 key, uint32 min, uint32 max) = Specs.decode(spec);
|
|
121
|
-
return consume(cur, key, min, max);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/// @notice Consume a BALANCE block and return its fields.
|
|
125
|
-
/// @param cur Reader; advanced past the block.
|
|
126
|
-
/// @return asset Asset identifier.
|
|
127
|
-
/// @return amount Token amount.
|
|
128
|
-
function unpackBalance(Reader memory cur) internal pure returns (bytes32 asset, uint amount) {
|
|
129
|
-
uint abs = consume(cur, Keys.Balance, 64, 64);
|
|
130
|
-
assembly ("memory-safe") {
|
|
131
|
-
asset := mload(abs)
|
|
132
|
-
amount := mload(add(abs, 0x20))
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/// @notice Consume a DEBT block and return its fields.
|
|
137
|
-
/// @param cur Reader; advanced past the block.
|
|
138
|
-
/// @return liability Liability identifier.
|
|
139
|
-
/// @return debt Debt quantity.
|
|
140
|
-
function unpackDebt(Reader memory cur) internal pure returns (bytes32 liability, uint debt) {
|
|
141
|
-
uint abs = consume(cur, Keys.Debt, 64, 64);
|
|
142
|
-
assembly ("memory-safe") {
|
|
143
|
-
liability := mload(abs)
|
|
144
|
-
debt := mload(add(abs, 0x20))
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/// @notice Consume a HOST_ASSET block and return its fields.
|
|
149
|
-
/// @param cur Reader; advanced past the block.
|
|
150
|
-
/// @return host Host identifier.
|
|
151
|
-
/// @return asset Asset identifier.
|
|
152
|
-
function unpackHostAsset(Reader memory cur) internal pure returns (uint host, bytes32 asset) {
|
|
153
|
-
uint abs = consume(cur, Keys.HostAsset, 64, 64);
|
|
154
|
-
assembly ("memory-safe") {
|
|
155
|
-
host := mload(abs)
|
|
156
|
-
asset := mload(add(abs, 0x20))
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/// @notice Consume a POSITION block and return its fields.
|
|
161
|
-
function unpackPosition(
|
|
162
|
-
Reader memory cur
|
|
163
|
-
) internal pure returns (bytes32 asset, uint amount, bytes32 liability, uint debt) {
|
|
164
|
-
uint abs = consume(cur, Keys.Position, 128, 128);
|
|
165
|
-
assembly ("memory-safe") {
|
|
166
|
-
asset := mload(abs)
|
|
167
|
-
amount := mload(add(abs, 0x20))
|
|
168
|
-
liability := mload(add(abs, 0x40))
|
|
169
|
-
debt := mload(add(abs, 0x60))
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/// @notice Consume a TRANSACTION block and return its fields.
|
|
174
|
-
/// @param cur Reader; advanced past the block.
|
|
175
|
-
/// @return from Source account identifier.
|
|
176
|
-
/// @return to Destination account identifier.
|
|
177
|
-
/// @return asset Asset identifier.
|
|
178
|
-
/// @return amount Token amount.
|
|
179
|
-
function unpackTransaction(
|
|
180
|
-
Reader memory cur
|
|
181
|
-
) internal pure returns (bytes32 from, bytes32 to, bytes32 asset, uint amount) {
|
|
182
|
-
uint abs = consume(cur, Keys.Transaction, 128, 128);
|
|
183
|
-
assembly ("memory-safe") {
|
|
184
|
-
from := mload(abs)
|
|
185
|
-
to := mload(add(abs, 0x20))
|
|
186
|
-
asset := mload(add(abs, 0x40))
|
|
187
|
-
amount := mload(add(abs, 0x60))
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|