@rootzero/contracts 0.9.3 → 0.9.4
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/Commands.sol +3 -2
- package/Core.sol +3 -0
- package/Cursors.sol +1 -1
- package/README.md +18 -24
- package/blocks/Cursors.sol +294 -339
- package/blocks/Keys.sol +38 -57
- package/blocks/Schema.sol +55 -208
- package/blocks/Writers.sol +345 -135
- package/commands/Base.sol +6 -48
- package/commands/Burn.sol +2 -2
- package/commands/Credit.sol +3 -3
- package/commands/Debit.sol +3 -2
- package/commands/Deposit.sol +11 -8
- package/commands/Provision.sol +11 -8
- package/commands/Transfer.sol +2 -2
- package/commands/Withdraw.sol +3 -3
- package/commands/admin/AllowAssets.sol +1 -1
- package/commands/admin/Allowance.sol +1 -1
- package/commands/admin/Authorize.sol +1 -1
- package/commands/admin/DenyAssets.sol +1 -1
- package/commands/admin/Execute.sol +7 -6
- package/commands/admin/Unauthorize.sol +1 -1
- package/core/Access.sol +11 -0
- package/core/Context.sol +3 -4
- package/core/Payable.sol +57 -0
- package/core/Pipeline.sol +55 -0
- package/docs/Schema.md +194 -0
- package/events/Command.sol +1 -2
- package/package.json +2 -2
- package/peer/AllowAssets.sol +1 -1
- package/peer/Allowance.sol +1 -1
- package/peer/BalancePull.sol +1 -1
- package/peer/DenyAssets.sol +1 -1
- package/peer/Pipe.sol +38 -0
- package/peer/Settle.sol +1 -1
- package/queries/Assets.sol +4 -3
- package/queries/Balances.sol +2 -1
- package/queries/Positions.sol +12 -12
- package/utils/Value.sol +8 -14
- package/commands/Pipe.sol +0 -67
- package/docs/GETTING_STARTED.md +0 -294
package/blocks/Cursors.sol
CHANGED
|
@@ -4,7 +4,6 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
import {AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, Tx} from "../core/Types.sol";
|
|
5
5
|
import {Sizes} from "./Schema.sol";
|
|
6
6
|
import {Keys} from "./Keys.sol";
|
|
7
|
-
import {Writer, Writers} from "./Writers.sol";
|
|
8
7
|
|
|
9
8
|
/// @notice Zero-copy view into a calldata block stream.
|
|
10
9
|
/// All positions (`i`, `bound`) are byte offsets relative to the start of the source region.
|
|
@@ -47,6 +46,7 @@ library Cursors {
|
|
|
47
46
|
error UnexpectedValue();
|
|
48
47
|
/// @dev Prime block counts are not divisible by, or do not match, their declared group sizes.
|
|
49
48
|
error BadRatio();
|
|
49
|
+
|
|
50
50
|
// -------------------------------------------------------------------------
|
|
51
51
|
// Cursor construction and navigation
|
|
52
52
|
// -------------------------------------------------------------------------
|
|
@@ -65,6 +65,17 @@ library Cursors {
|
|
|
65
65
|
cur.len = source.length;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/// @notice Create a cursor and prime it for a grouped iteration pass.
|
|
69
|
+
/// Equivalent to `open(source)` followed by `primeRun(group)`.
|
|
70
|
+
/// @param source Calldata slice that forms the block stream.
|
|
71
|
+
/// @param group Expected block group size (e.g. 1 for single, 2 for paired).
|
|
72
|
+
/// @return cur Cursor with `bound` set to the end of the first run.
|
|
73
|
+
/// @return groups Number of block groups in the run (`prime block count / group`).
|
|
74
|
+
function init(bytes calldata source, uint group) internal pure returns (Cur memory cur, uint groups) {
|
|
75
|
+
cur = open(source);
|
|
76
|
+
(, groups) = cur.primeRun(group);
|
|
77
|
+
}
|
|
78
|
+
|
|
68
79
|
/// @notice Move the cursor to an absolute position within the source region.
|
|
69
80
|
/// @param cur Cursor to update.
|
|
70
81
|
/// @param i New read position (byte offset relative to source start).
|
|
@@ -75,6 +86,26 @@ library Cursors {
|
|
|
75
86
|
return cur;
|
|
76
87
|
}
|
|
77
88
|
|
|
89
|
+
/// @notice Advance the cursor by `n` bytes within the source region.
|
|
90
|
+
/// Reverts with `IncompleteCursor` if `n` exceeds the remaining cursor region length.
|
|
91
|
+
/// @param cur Cursor to advance.
|
|
92
|
+
/// @param n Number of bytes to skip from the current read position.
|
|
93
|
+
function skip(Cur memory cur, uint n) internal pure returns (Cur memory) {
|
|
94
|
+
if (n > cur.len - cur.i) revert IncompleteCursor();
|
|
95
|
+
cur.i += n;
|
|
96
|
+
return cur;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// @notice Advance the cursor to a later absolute position within the source region.
|
|
100
|
+
/// Reverts with `IncompleteCursor` if `i` exceeds the cursor region length or is before `cur.i`.
|
|
101
|
+
/// @param cur Cursor to advance.
|
|
102
|
+
/// @param i New read position (byte offset relative to source start).
|
|
103
|
+
function skipTo(Cur memory cur, uint i) internal pure returns (Cur memory) {
|
|
104
|
+
if (i > cur.len || cur.i > i) revert IncompleteCursor();
|
|
105
|
+
cur.i = i;
|
|
106
|
+
return cur;
|
|
107
|
+
}
|
|
108
|
+
|
|
78
109
|
/// @notice Create a subcursor over the half-open range `[from, to)` within the source region.
|
|
79
110
|
/// The returned cursor starts at position zero within that sliced region.
|
|
80
111
|
/// @param cur Source cursor.
|
|
@@ -103,7 +134,19 @@ library Cursors {
|
|
|
103
134
|
/// @param to End byte offset within the source region (exclusive).
|
|
104
135
|
/// @return data Calldata view over the requested sub-range.
|
|
105
136
|
function raw(Cur memory cur, uint from, uint to) internal pure returns (bytes calldata data) {
|
|
106
|
-
|
|
137
|
+
if (from > to || to > cur.len) revert MalformedBlocks();
|
|
138
|
+
if (cur.len > msg.data.length || cur.offset > msg.data.length - cur.len) revert MalformedBlocks();
|
|
139
|
+
data = msg.data[cur.offset + from:cur.offset + to];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/// @notice Hash a sub-range of the cursor region.
|
|
143
|
+
/// Does not advance the cursor; `from` and `to` are relative to the source region.
|
|
144
|
+
/// @param cur Source cursor.
|
|
145
|
+
/// @param from Start byte offset within the source region (inclusive).
|
|
146
|
+
/// @param to End byte offset within the source region (exclusive).
|
|
147
|
+
/// @return digest Keccak256 hash of the requested sub-range.
|
|
148
|
+
function hash(Cur memory cur, uint from, uint to) internal pure returns (bytes32 digest) {
|
|
149
|
+
digest = keccak256(cur.raw(from, to));
|
|
107
150
|
}
|
|
108
151
|
|
|
109
152
|
/// @notice Read a block header at position `i` without advancing the cursor.
|
|
@@ -112,11 +155,11 @@ library Cursors {
|
|
|
112
155
|
/// @return key Four-byte block type identifier.
|
|
113
156
|
/// @return len Payload byte length declared in the header.
|
|
114
157
|
function peek(Cur memory cur, uint i) internal pure returns (bytes4 key, uint len) {
|
|
115
|
-
if (i +
|
|
158
|
+
if (i + Sizes.Header > cur.len) revert MalformedBlocks();
|
|
116
159
|
uint abs = cur.offset + i;
|
|
117
160
|
key = bytes4(msg.data[abs:abs + 4]);
|
|
118
161
|
len = uint32(bytes4(msg.data[abs + 4:abs + 8]));
|
|
119
|
-
if (i +
|
|
162
|
+
if (i + Sizes.Header + len > cur.len) revert MalformedBlocks();
|
|
120
163
|
}
|
|
121
164
|
|
|
122
165
|
/// @notice Return the byte offset immediately past the block at the current cursor position.
|
|
@@ -128,34 +171,49 @@ library Cursors {
|
|
|
128
171
|
return cur.i + Sizes.Header + len;
|
|
129
172
|
}
|
|
130
173
|
|
|
174
|
+
/// @notice Return true if position `i` is at a block header with the given key.
|
|
175
|
+
/// Returns false when `i` is out of bounds or the key differs.
|
|
176
|
+
/// @param cur Source cursor.
|
|
177
|
+
/// @param i Byte offset of the block header within the source region.
|
|
178
|
+
/// @param key Expected block type identifier.
|
|
179
|
+
/// @return Whether the block header at `i` uses `key`.
|
|
180
|
+
function hasAt(Cur memory cur, uint i, bytes4 key) internal pure returns (bool) {
|
|
181
|
+
if (i > cur.len || Sizes.Header > cur.len - i) return false;
|
|
182
|
+
uint abs = cur.offset + i;
|
|
183
|
+
return bytes4(msg.data[abs:abs + 4]) == key;
|
|
184
|
+
}
|
|
185
|
+
|
|
131
186
|
/// @notice Return true if the current cursor position is at a block header with the given key.
|
|
132
187
|
/// Returns false when `cur.i` is out of bounds or the key differs.
|
|
133
188
|
/// @param cur Source cursor.
|
|
134
189
|
/// @param key Expected block type identifier.
|
|
135
190
|
/// @return Whether the block header at `cur.i` uses `key`.
|
|
136
191
|
function isAt(Cur memory cur, bytes4 key) internal pure returns (bool) {
|
|
137
|
-
|
|
138
|
-
uint abs = cur.offset + cur.i;
|
|
139
|
-
return bytes4(msg.data[abs:abs + 4]) == key;
|
|
192
|
+
return cur.hasAt(cur.i, key);
|
|
140
193
|
}
|
|
141
194
|
|
|
142
|
-
/// @notice
|
|
143
|
-
///
|
|
144
|
-
///
|
|
145
|
-
///
|
|
146
|
-
/// @param
|
|
147
|
-
/// @
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
195
|
+
/// @notice Enter a block at the current position and return its next offset.
|
|
196
|
+
/// Advances `cur.i` past the block header so the payload can be parsed
|
|
197
|
+
/// directly from the same cursor. The returned `next` is the byte offset
|
|
198
|
+
/// immediately after the block payload, relative to the current cursor region.
|
|
199
|
+
/// @param cur Cursor positioned at the expected block; advanced past the 8-byte header.
|
|
200
|
+
/// @param key Expected block key.
|
|
201
|
+
/// @param min Minimum acceptable payload length.
|
|
202
|
+
/// @param max Maximum acceptable payload length; 0 means unbounded.
|
|
203
|
+
/// @return next Byte offset immediately after the block payload.
|
|
204
|
+
function enter(Cur memory cur, bytes4 key, uint min, uint max) internal pure returns (uint next) {
|
|
205
|
+
(bytes4 current, uint len) = peek(cur, cur.i);
|
|
206
|
+
if (current != key) revert InvalidBlock();
|
|
207
|
+
if (len < min || (max != 0 && len > max)) revert InvalidBlock();
|
|
208
|
+
next = cur.i + Sizes.Header + len;
|
|
209
|
+
cur.i += Sizes.Header;
|
|
153
210
|
}
|
|
154
211
|
|
|
155
212
|
/// @notice Validate a block at position `i` and return its payload location.
|
|
156
213
|
/// Does not advance the cursor.
|
|
157
214
|
/// @param cur Source cursor.
|
|
158
215
|
/// @param i Byte offset of the block within the source region.
|
|
216
|
+
/// @param end Required next offset after the block; 0 means no exact-end check.
|
|
159
217
|
/// @param key Expected block type key; reverts if actual key differs.
|
|
160
218
|
/// @param min Minimum acceptable payload length (inclusive).
|
|
161
219
|
/// @param max Maximum acceptable payload length (inclusive); 0 means unbounded.
|
|
@@ -164,15 +222,30 @@ library Cursors {
|
|
|
164
222
|
function expect(
|
|
165
223
|
Cur memory cur,
|
|
166
224
|
uint i,
|
|
225
|
+
uint end,
|
|
167
226
|
bytes4 key,
|
|
168
227
|
uint min,
|
|
169
228
|
uint max
|
|
170
229
|
) internal pure returns (uint abs, uint next) {
|
|
171
230
|
(bytes4 current, uint len) = peek(cur, i);
|
|
172
231
|
if (current != key) revert InvalidBlock();
|
|
173
|
-
abs = cur.offset + i + 8;
|
|
174
|
-
next = i + 8 + len;
|
|
175
232
|
if (len < min || (max != 0 && len > max)) revert InvalidBlock();
|
|
233
|
+
abs = cur.offset + i + Sizes.Header;
|
|
234
|
+
next = i + Sizes.Header + len;
|
|
235
|
+
if (end != 0 && next != end) revert IncompleteCursor();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/// @notice Validate and consume the current block, advancing `cur.i` past it.
|
|
239
|
+
/// @param cur Cursor to advance.
|
|
240
|
+
/// @param end Required next offset after the block; 0 means no exact-end check.
|
|
241
|
+
/// @param key Expected block type key.
|
|
242
|
+
/// @param min Minimum payload length.
|
|
243
|
+
/// @param max Maximum payload length (0 = unbounded).
|
|
244
|
+
/// @return abs Absolute calldata offset of the payload start.
|
|
245
|
+
function consume(Cur memory cur, uint end, bytes4 key, uint min, uint max) internal pure returns (uint abs) {
|
|
246
|
+
uint next;
|
|
247
|
+
(abs, next) = expect(cur, cur.i, end, key, min, max);
|
|
248
|
+
cur.i = next;
|
|
176
249
|
}
|
|
177
250
|
|
|
178
251
|
/// @notice Count consecutive blocks of the same key starting at `i`.
|
|
@@ -186,7 +259,7 @@ library Cursors {
|
|
|
186
259
|
while (next < cur.len) {
|
|
187
260
|
(bytes4 current, uint len) = peek(cur, next);
|
|
188
261
|
if (current != key) break;
|
|
189
|
-
next +=
|
|
262
|
+
next += Sizes.Header + len;
|
|
190
263
|
|
|
191
264
|
unchecked {
|
|
192
265
|
++total;
|
|
@@ -197,20 +270,19 @@ library Cursors {
|
|
|
197
270
|
/// @notice Initialise the cursor for a grouped iteration pass.
|
|
198
271
|
/// Reads the key of the first block, counts the consecutive run of that key,
|
|
199
272
|
/// stores the run end in `cur.bound`, validates that the count is a
|
|
200
|
-
/// multiple of `group`, and returns
|
|
201
|
-
/// normalized quotient (`count / group`).
|
|
273
|
+
/// multiple of `group`, and returns the run key and normalized group count.
|
|
202
274
|
/// @param cur Cursor to prime; `cur.bound` is updated in place.
|
|
203
275
|
/// @param group Expected group size (e.g. 1 for single-asset, 2 for paired input/output).
|
|
204
276
|
/// @return key Block type identifier of the run.
|
|
205
|
-
/// @return
|
|
206
|
-
|
|
207
|
-
function primeRun(Cur memory cur, uint group) internal pure returns (bytes4 key, uint count, uint quotient) {
|
|
277
|
+
/// @return groups Number of groups represented by the run (`block count / group`).
|
|
278
|
+
function primeRun(Cur memory cur, uint group) internal pure returns (bytes4 key, uint groups) {
|
|
208
279
|
if (group == 0) revert ZeroGroup();
|
|
209
280
|
key = cur.i + 4 > cur.len ? bytes4(0) : bytes4(msg.data[cur.offset + cur.i:cur.offset + cur.i + 4]);
|
|
281
|
+
uint count;
|
|
210
282
|
(count, cur.bound) = countRun(cur, cur.i, key);
|
|
211
283
|
if (count == 0) revert ZeroCursor();
|
|
212
284
|
if (count % group != 0) revert BadRatio();
|
|
213
|
-
|
|
285
|
+
groups = count / group;
|
|
214
286
|
}
|
|
215
287
|
|
|
216
288
|
/// @notice Scan forward from `i` for the first block matching `key`.
|
|
@@ -222,7 +294,7 @@ library Cursors {
|
|
|
222
294
|
while (i < cur.len) {
|
|
223
295
|
(bytes4 current, uint len) = peek(cur, i);
|
|
224
296
|
if (current == key) return i;
|
|
225
|
-
i +=
|
|
297
|
+
i += Sizes.Header + len;
|
|
226
298
|
}
|
|
227
299
|
return cur.len;
|
|
228
300
|
}
|
|
@@ -235,29 +307,6 @@ library Cursors {
|
|
|
235
307
|
return find(cur, cur.i, key);
|
|
236
308
|
}
|
|
237
309
|
|
|
238
|
-
/// @notice Validate and consume the current block, advancing `cur.i` past it.
|
|
239
|
-
/// @param cur Cursor to advance.
|
|
240
|
-
/// @param key Expected block type key.
|
|
241
|
-
/// @param min Minimum payload length.
|
|
242
|
-
/// @param max Maximum payload length (0 = unbounded).
|
|
243
|
-
/// @return abs Absolute calldata offset of the payload start.
|
|
244
|
-
function consume(Cur memory cur, bytes4 key, uint min, uint max) internal pure returns (uint abs) {
|
|
245
|
-
uint next;
|
|
246
|
-
(abs, next) = expect(cur, cur.i, key, min, max);
|
|
247
|
-
cur.i = next;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/// @notice Enter a Bundle block at the current position and return the next offset.
|
|
251
|
-
/// Advances `cur.i` past the bundle header so the bundled members can be parsed
|
|
252
|
-
/// directly from the same cursor. The returned `next` is the byte offset
|
|
253
|
-
/// immediately after the bundle payload, relative to the current cursor region.
|
|
254
|
-
/// @param cur Cursor positioned at a bundle block; advanced past the 8-byte header.
|
|
255
|
-
/// @return next Byte offset immediately after the bundle payload.
|
|
256
|
-
function bundle(Cur memory cur) internal pure returns (uint next) {
|
|
257
|
-
(, next) = expect(cur, cur.i, Keys.Bundle, 0, 0);
|
|
258
|
-
cur.i += 8;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
310
|
/// @notice Enter a List block at the current position and return the next offset.
|
|
262
311
|
/// Advances `cur.i` past the list header so the list members can be parsed
|
|
263
312
|
/// directly from the same cursor. The returned `next` is the byte offset
|
|
@@ -265,8 +314,7 @@ library Cursors {
|
|
|
265
314
|
/// @param cur Cursor positioned at a list block; advanced past the 8-byte header.
|
|
266
315
|
/// @return next Byte offset immediately after the list payload.
|
|
267
316
|
function list(Cur memory cur) internal pure returns (uint next) {
|
|
268
|
-
|
|
269
|
-
cur.i += 8;
|
|
317
|
+
next = enter(cur, Keys.List, 0, 0);
|
|
270
318
|
}
|
|
271
319
|
|
|
272
320
|
/// @notice Consume a block with the given key at the current position and return a cursor over the full block slice.
|
|
@@ -276,11 +324,24 @@ library Cursors {
|
|
|
276
324
|
/// @param key Expected block type key.
|
|
277
325
|
/// @return out Cursor scoped to the full block.
|
|
278
326
|
function take(Cur memory cur, bytes4 key) internal pure returns (Cur memory out) {
|
|
279
|
-
(, uint next) = expect(cur, cur.i, key, 0, 0);
|
|
327
|
+
(, uint next) = expect(cur, cur.i, 0, key, 0, 0);
|
|
280
328
|
out = cur.slice(cur.i, next);
|
|
281
329
|
cur.i = next;
|
|
282
330
|
}
|
|
283
331
|
|
|
332
|
+
/// @notice Return whether the remaining cursor region is empty or exactly one block with `key`.
|
|
333
|
+
/// Returns false for an empty remaining region. Reverts if the next block has another key or
|
|
334
|
+
/// if a matching block is followed by trailing bytes.
|
|
335
|
+
/// @param cur Source cursor.
|
|
336
|
+
/// @param key Expected optional block key.
|
|
337
|
+
/// @return Whether the remaining region contains exactly one block with `key`.
|
|
338
|
+
function maybeOnly(Cur memory cur, bytes4 key) internal pure returns (bool) {
|
|
339
|
+
if (cur.i == cur.len) return false;
|
|
340
|
+
if (!cur.isAt(key)) revert InvalidBlock();
|
|
341
|
+
if (cur.past() != cur.len) revert IncompleteCursor();
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
|
|
284
345
|
/// @notice Consume an optional block with the given key and return a cursor over the full block slice.
|
|
285
346
|
/// If the current block key does not match, returns an empty cursor and leaves `cur.i` unchanged.
|
|
286
347
|
/// Otherwise behaves like `take(cur, key)`.
|
|
@@ -291,13 +352,13 @@ library Cursors {
|
|
|
291
352
|
return cur.isAt(key) ? take(cur, key) : cur.slice(cur.i, cur.i);
|
|
292
353
|
}
|
|
293
354
|
|
|
294
|
-
/// @notice Consume an optional
|
|
295
|
-
/// If the current block is not
|
|
296
|
-
/// Otherwise behaves like `take(cur, Keys.
|
|
297
|
-
/// @param cur Cursor positioned at an optional
|
|
298
|
-
/// @return out Cursor scoped to the full
|
|
299
|
-
function
|
|
300
|
-
return maybeTake(cur, Keys.
|
|
355
|
+
/// @notice Consume an optional DATA block at the current position and return a cursor over the full block slice.
|
|
356
|
+
/// If the current block is not DATA, returns an empty cursor and leaves `cur.i` unchanged.
|
|
357
|
+
/// Otherwise behaves like `take(cur, Keys.Data)`.
|
|
358
|
+
/// @param cur Cursor positioned at an optional DATA block.
|
|
359
|
+
/// @return out Cursor scoped to the full DATA block, or empty when no DATA block is present.
|
|
360
|
+
function maybeData(Cur memory cur) internal pure returns (Cur memory out) {
|
|
361
|
+
return maybeTake(cur, Keys.Data);
|
|
301
362
|
}
|
|
302
363
|
|
|
303
364
|
/// @notice Enter a List block, prime its member run, and return the group count.
|
|
@@ -307,56 +368,45 @@ library Cursors {
|
|
|
307
368
|
/// @return next Byte offset immediately after the list payload.
|
|
308
369
|
function list(Cur memory cur, uint group) internal pure returns (uint groups, uint next) {
|
|
309
370
|
next = list(cur);
|
|
310
|
-
(,
|
|
371
|
+
(, groups) = cur.primeRun(group);
|
|
311
372
|
if (cur.bound != next) revert IncompleteCursor();
|
|
312
373
|
}
|
|
313
374
|
|
|
375
|
+
/// @notice Exit a nested region at an exact boundary.
|
|
376
|
+
/// Reverts with `IncompleteCursor` if `end` exceeds the cursor region length
|
|
377
|
+
/// or `cur.i != end`.
|
|
378
|
+
/// @param cur Cursor to check.
|
|
379
|
+
/// @param end Relative end offset of the nested region.
|
|
380
|
+
function exit(Cur memory cur, uint end) internal pure {
|
|
381
|
+
if (end > cur.len || cur.i != end) revert IncompleteCursor();
|
|
382
|
+
}
|
|
383
|
+
|
|
314
384
|
/// @notice Assert that the cursor has consumed exactly up to `bound`.
|
|
315
385
|
/// Reverts with `IncompleteCursor` if `bound` is zero or `cur.i != cur.bound`.
|
|
316
386
|
/// @param cur Cursor to check.
|
|
317
|
-
function
|
|
387
|
+
function close(Cur memory cur) internal pure {
|
|
318
388
|
if (cur.bound == 0 || cur.i != cur.bound) revert IncompleteCursor();
|
|
319
389
|
}
|
|
320
390
|
|
|
321
391
|
/// @notice Assert that the cursor has consumed its entire source region.
|
|
322
392
|
/// Reverts with `IncompleteCursor` when `cur.i != cur.len`.
|
|
323
393
|
/// @param cur Cursor to check.
|
|
324
|
-
function
|
|
394
|
+
function complete(Cur memory cur) internal pure {
|
|
325
395
|
if (cur.i != cur.len) revert IncompleteCursor();
|
|
326
396
|
}
|
|
327
397
|
|
|
328
|
-
/// @notice Resume parsing after a nested region delimited by `resumeAt`.
|
|
329
|
-
/// Reverts with `IncompleteCursor` if `cur.i` has advanced past `resumeAt` or `resumeAt`
|
|
330
|
-
/// exceeds the cursor region length. Otherwise moves `cur.i` to `end`.
|
|
331
|
-
/// @param cur Cursor to advance.
|
|
332
|
-
/// @param resumeAt Relative end offset of the nested region to resume after.
|
|
333
|
-
function resume(Cur memory cur, uint resumeAt) internal pure {
|
|
334
|
-
if (resumeAt > cur.len || cur.i > resumeAt) revert IncompleteCursor();
|
|
335
|
-
cur.i = resumeAt;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/// @notice Ensure that parsing has reached an exact nested-region boundary.
|
|
339
|
-
/// Reverts with `IncompleteCursor` if `ensureAt` exceeds the cursor region length
|
|
340
|
-
/// or `cur.i != ensureAt`.
|
|
341
|
-
/// @param cur Cursor to check.
|
|
342
|
-
/// @param ensureAt Relative offset that `cur.i` must match exactly.
|
|
343
|
-
function ensure(Cur memory cur, uint ensureAt) internal pure {
|
|
344
|
-
if (ensureAt > cur.len || cur.i != ensureAt) revert IncompleteCursor();
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/// @notice Assert completion and finalise a writer in one step.
|
|
348
|
-
/// @param cur Cursor to check.
|
|
349
|
-
/// @param writer Writer to finalise.
|
|
350
|
-
/// @return Trimmed output bytes from the writer.
|
|
351
|
-
function complete(Cur memory cur, Writer memory writer) internal pure returns (bytes memory) {
|
|
352
|
-
if (cur.bound == 0 || cur.i != cur.bound) revert IncompleteCursor();
|
|
353
|
-
return Writers.finish(writer);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
398
|
// -------------------------------------------------------------------------
|
|
357
399
|
// Block factory helpers
|
|
358
400
|
// -------------------------------------------------------------------------
|
|
359
401
|
|
|
402
|
+
/// @notice Encode a block with a raw payload.
|
|
403
|
+
/// @param key Block type key.
|
|
404
|
+
/// @param data Raw payload bytes.
|
|
405
|
+
/// @return Encoded block bytes.
|
|
406
|
+
function createBlock(bytes4 key, bytes memory data) internal pure returns (bytes memory) {
|
|
407
|
+
return bytes.concat(key, bytes4(uint32(data.length)), data);
|
|
408
|
+
}
|
|
409
|
+
|
|
360
410
|
/// @notice Encode a block with a single 32-byte payload word.
|
|
361
411
|
/// @param key Block type key.
|
|
362
412
|
/// @param value 32-byte payload.
|
|
@@ -420,28 +470,11 @@ library Cursors {
|
|
|
420
470
|
return bytes.concat(key, bytes4(uint32(0xa0)), a, b, c, d, e);
|
|
421
471
|
}
|
|
422
472
|
|
|
423
|
-
/// @notice Encode a block with a
|
|
424
|
-
/// @param
|
|
425
|
-
/// @
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
function createBlockHead32(bytes4 key, bytes32 head, bytes memory tail) internal pure returns (bytes memory) {
|
|
429
|
-
return bytes.concat(key, bytes4(uint32(0x20 + tail.length)), head, tail);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/// @notice Encode a block with a 64-byte fixed head followed by a variable-length tail.
|
|
433
|
-
/// @param key Block type key.
|
|
434
|
-
/// @param a First fixed payload word.
|
|
435
|
-
/// @param b Second fixed payload word.
|
|
436
|
-
/// @param tail Variable-length payload bytes appended after the fixed head.
|
|
437
|
-
/// @return Encoded block bytes.
|
|
438
|
-
function createBlockHead64(
|
|
439
|
-
bytes4 key,
|
|
440
|
-
bytes32 a,
|
|
441
|
-
bytes32 b,
|
|
442
|
-
bytes memory tail
|
|
443
|
-
) internal pure returns (bytes memory) {
|
|
444
|
-
return bytes.concat(key, bytes4(uint32(0x40 + tail.length)), a, b, tail);
|
|
473
|
+
/// @notice Encode a BYTES block with a raw payload.
|
|
474
|
+
/// @param data Raw payload bytes.
|
|
475
|
+
/// @return Encoded BYTES block bytes.
|
|
476
|
+
function toBytesBlock(bytes memory data) internal pure returns (bytes memory) {
|
|
477
|
+
return createBlock(Keys.Bytes, data);
|
|
445
478
|
}
|
|
446
479
|
|
|
447
480
|
/// @notice Encode a BOUNTY block.
|
|
@@ -452,24 +485,6 @@ library Cursors {
|
|
|
452
485
|
return createBlock64(Keys.Bounty, bytes32(bounty), relayer);
|
|
453
486
|
}
|
|
454
487
|
|
|
455
|
-
/// @notice Encode a STEP block.
|
|
456
|
-
/// @param target Command target identifier.
|
|
457
|
-
/// @param value Native value forwarded with the step.
|
|
458
|
-
/// @param request Variable-length nested request payload.
|
|
459
|
-
/// @return Encoded STEP block bytes.
|
|
460
|
-
function toStepBlock(uint target, uint value, bytes memory request) internal pure returns (bytes memory) {
|
|
461
|
-
return createBlockHead64(Keys.Step, bytes32(target), bytes32(value), request);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/// @notice Encode a CALL block.
|
|
465
|
-
/// @param target Target node identifier.
|
|
466
|
-
/// @param value Native value forwarded with the call.
|
|
467
|
-
/// @param data Raw calldata payload for the target.
|
|
468
|
-
/// @return Encoded CALL block bytes.
|
|
469
|
-
function toCallBlock(uint target, uint value, bytes memory data) internal pure returns (bytes memory) {
|
|
470
|
-
return createBlockHead64(Keys.Call, bytes32(target), bytes32(value), data);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
488
|
/// @notice Encode a BALANCE block.
|
|
474
489
|
/// @param asset Asset identifier.
|
|
475
490
|
/// @param meta Asset metadata slot.
|
|
@@ -485,87 +500,121 @@ library Cursors {
|
|
|
485
500
|
/// @param meta Asset metadata slot.
|
|
486
501
|
/// @param amount Token amount.
|
|
487
502
|
/// @return Encoded CUSTODY block bytes.
|
|
488
|
-
function toCustodyBlock(
|
|
489
|
-
uint host,
|
|
490
|
-
bytes32 asset,
|
|
491
|
-
bytes32 meta,
|
|
492
|
-
uint amount
|
|
493
|
-
) internal pure returns (bytes memory) {
|
|
503
|
+
function toCustodyBlock(uint host, bytes32 asset, bytes32 meta, uint amount) internal pure returns (bytes memory) {
|
|
494
504
|
return createBlock128(Keys.Custody, bytes32(host), asset, meta, bytes32(amount));
|
|
495
505
|
}
|
|
496
506
|
|
|
507
|
+
/// @notice Encode a STEP block.
|
|
508
|
+
/// @param target Command target identifier.
|
|
509
|
+
/// @param value Native value forwarded with the step.
|
|
510
|
+
/// @param request Raw nested request payload.
|
|
511
|
+
/// @return Encoded STEP block bytes.
|
|
512
|
+
function toStepBlock(uint target, uint value, bytes memory request) internal pure returns (bytes memory) {
|
|
513
|
+
return createBlock(Keys.Step, bytes.concat(bytes32(target), bytes32(value), toBytesBlock(request)));
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/// @notice Encode a CALL block.
|
|
517
|
+
/// @param target Target node identifier.
|
|
518
|
+
/// @param value Native value forwarded with the call.
|
|
519
|
+
/// @param data Raw calldata payload for the target.
|
|
520
|
+
/// @return Encoded CALL block bytes.
|
|
521
|
+
function toCallBlock(uint target, uint value, bytes memory data) internal pure returns (bytes memory) {
|
|
522
|
+
return createBlock(Keys.Call, bytes.concat(bytes32(target), bytes32(value), toBytesBlock(data)));
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/// @notice Encode a CONTEXT block.
|
|
526
|
+
/// @param account Command account identifier.
|
|
527
|
+
/// @param value Native value budget assigned to the context.
|
|
528
|
+
/// @param state Embedded state block stream.
|
|
529
|
+
/// @param request Embedded request block stream.
|
|
530
|
+
/// @return Encoded CONTEXT block bytes.
|
|
531
|
+
function toContextBlock(
|
|
532
|
+
bytes32 account,
|
|
533
|
+
uint value,
|
|
534
|
+
bytes memory state,
|
|
535
|
+
bytes memory request
|
|
536
|
+
) internal pure returns (bytes memory) {
|
|
537
|
+
return createBlock(Keys.Context, bytes.concat(account, bytes32(value), toBytesBlock(state), toBytesBlock(request)));
|
|
538
|
+
}
|
|
539
|
+
|
|
497
540
|
// -------------------------------------------------------------------------
|
|
498
541
|
// Raw calldata loaders
|
|
499
542
|
// -------------------------------------------------------------------------
|
|
500
543
|
|
|
501
|
-
/// @notice
|
|
502
|
-
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
503
|
-
///
|
|
504
|
-
/// @
|
|
505
|
-
|
|
544
|
+
/// @notice Read the next calldata word from the cursor and advance by `n` bytes.
|
|
545
|
+
/// @dev Performs no bounds, key, length, or cursor checks. Always loads 32 bytes;
|
|
546
|
+
/// callers may cast the returned word to `bytesN` when `n < 32`.
|
|
547
|
+
/// @param cur Cursor whose current position is advanced by `n` bytes.
|
|
548
|
+
/// @param n Number of bytes to advance.
|
|
549
|
+
/// @return value Loaded word.
|
|
550
|
+
function read(Cur memory cur, uint n) internal pure returns (bytes32 value) {
|
|
551
|
+
uint abs = cur.offset + cur.i;
|
|
506
552
|
assembly ("memory-safe") {
|
|
507
|
-
|
|
553
|
+
value := calldataload(abs)
|
|
508
554
|
}
|
|
555
|
+
cur.i += n;
|
|
509
556
|
}
|
|
510
557
|
|
|
511
|
-
/// @notice
|
|
558
|
+
/// @notice Read the next 16 bytes from the cursor and advance by 16 bytes.
|
|
512
559
|
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
513
|
-
/// @param
|
|
514
|
-
/// @return
|
|
515
|
-
|
|
516
|
-
|
|
560
|
+
/// @param cur Cursor whose current position is advanced by 16 bytes.
|
|
561
|
+
/// @return value Loaded bytes16 value.
|
|
562
|
+
function read16(Cur memory cur) internal pure returns (bytes16 value) {
|
|
563
|
+
uint abs = cur.offset + cur.i;
|
|
517
564
|
assembly ("memory-safe") {
|
|
518
|
-
|
|
519
|
-
b := calldataload(add(abs, 0x20))
|
|
565
|
+
value := calldataload(abs)
|
|
520
566
|
}
|
|
567
|
+
cur.i += 16;
|
|
521
568
|
}
|
|
522
569
|
|
|
523
|
-
/// @notice
|
|
570
|
+
/// @notice Read the next 32-byte word from the cursor and advance by one word.
|
|
524
571
|
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
525
|
-
/// @param
|
|
526
|
-
/// @return
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
function load96(uint abs) internal pure returns (bytes32 a, bytes32 b, bytes32 c) {
|
|
572
|
+
/// @param cur Cursor whose current position is advanced by 32 bytes.
|
|
573
|
+
/// @return value Loaded word.
|
|
574
|
+
function read32(Cur memory cur) internal pure returns (bytes32 value) {
|
|
575
|
+
uint abs = cur.offset + cur.i;
|
|
530
576
|
assembly ("memory-safe") {
|
|
531
|
-
|
|
532
|
-
b := calldataload(add(abs, 0x20))
|
|
533
|
-
c := calldataload(add(abs, 0x40))
|
|
577
|
+
value := calldataload(abs)
|
|
534
578
|
}
|
|
579
|
+
cur.i += 32;
|
|
535
580
|
}
|
|
536
581
|
|
|
537
|
-
/// @notice
|
|
582
|
+
/// @notice Read the next two 32-byte words from the cursor and advance by 64 bytes.
|
|
538
583
|
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
539
|
-
/// @param
|
|
584
|
+
/// @param cur Cursor whose current position is advanced by 64 bytes.
|
|
540
585
|
/// @return a First loaded word.
|
|
541
586
|
/// @return b Second loaded word.
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
function load128(uint abs) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d) {
|
|
587
|
+
function read64(Cur memory cur) internal pure returns (bytes32 a, bytes32 b) {
|
|
588
|
+
uint abs = cur.offset + cur.i;
|
|
545
589
|
assembly ("memory-safe") {
|
|
546
590
|
a := calldataload(abs)
|
|
547
591
|
b := calldataload(add(abs, 0x20))
|
|
548
|
-
c := calldataload(add(abs, 0x40))
|
|
549
|
-
d := calldataload(add(abs, 0x60))
|
|
550
592
|
}
|
|
593
|
+
cur.i += 64;
|
|
551
594
|
}
|
|
552
595
|
|
|
553
|
-
/// @notice
|
|
596
|
+
/// @notice Read the next three 32-byte words from the cursor and advance by 96 bytes.
|
|
554
597
|
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
555
|
-
/// @param
|
|
598
|
+
/// @param cur Cursor whose current position is advanced by 96 bytes.
|
|
556
599
|
/// @return a First loaded word.
|
|
557
600
|
/// @return b Second loaded word.
|
|
558
601
|
/// @return c Third loaded word.
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
function load160(uint abs) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d, bytes32 e) {
|
|
602
|
+
function read96(Cur memory cur) internal pure returns (bytes32 a, bytes32 b, bytes32 c) {
|
|
603
|
+
uint abs = cur.offset + cur.i;
|
|
562
604
|
assembly ("memory-safe") {
|
|
563
605
|
a := calldataload(abs)
|
|
564
606
|
b := calldataload(add(abs, 0x20))
|
|
565
607
|
c := calldataload(add(abs, 0x40))
|
|
566
|
-
d := calldataload(add(abs, 0x60))
|
|
567
|
-
e := calldataload(add(abs, 0x80))
|
|
568
608
|
}
|
|
609
|
+
cur.i += 96;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/// @notice Consume the next 32-byte word and require it to match `expected`.
|
|
613
|
+
/// @dev Performs no bounds, key, length, or cursor checks beyond the value comparison.
|
|
614
|
+
/// @param cur Cursor whose current position is advanced by 32 bytes.
|
|
615
|
+
/// @param expected Required word value.
|
|
616
|
+
function require32(Cur memory cur, bytes32 expected) internal pure {
|
|
617
|
+
if (read32(cur) != expected) revert UnexpectedValue();
|
|
569
618
|
}
|
|
570
619
|
|
|
571
620
|
// -------------------------------------------------------------------------
|
|
@@ -580,17 +629,24 @@ library Cursors {
|
|
|
580
629
|
/// @param key Expected dynamic block key.
|
|
581
630
|
/// @return data Raw block payload bytes.
|
|
582
631
|
function unpackRaw(Cur memory cur, bytes4 key) internal pure returns (bytes calldata data) {
|
|
583
|
-
(uint abs, uint next) = expect(cur, cur.i, key, 0, 0);
|
|
632
|
+
(uint abs, uint next) = expect(cur, cur.i, 0, key, 0, 0);
|
|
584
633
|
data = msg.data[abs:cur.offset + next];
|
|
585
634
|
cur.i = next;
|
|
586
635
|
}
|
|
587
636
|
|
|
637
|
+
/// @notice Consume a reserved BYTES block and return its raw payload.
|
|
638
|
+
/// @param cur Cursor; advanced past the BYTES block.
|
|
639
|
+
/// @return data Raw BYTES payload.
|
|
640
|
+
function unpackBytes(Cur memory cur) internal pure returns (bytes calldata data) {
|
|
641
|
+
return unpackRaw(cur, Keys.Bytes);
|
|
642
|
+
}
|
|
643
|
+
|
|
588
644
|
/// @notice Consume a dynamic block with a single bytes32 payload.
|
|
589
645
|
/// @param cur Cursor; advanced past the block.
|
|
590
646
|
/// @param key Expected dynamic block key.
|
|
591
647
|
/// @return value Decoded bytes32.
|
|
592
648
|
function unpack32(Cur memory cur, bytes4 key) internal pure returns (bytes32 value) {
|
|
593
|
-
uint abs = consume(cur, key, 32, 32);
|
|
649
|
+
uint abs = consume(cur, 0, key, 32, 32);
|
|
594
650
|
value = bytes32(msg.data[abs:abs + 32]);
|
|
595
651
|
}
|
|
596
652
|
|
|
@@ -600,7 +656,7 @@ library Cursors {
|
|
|
600
656
|
/// @return a First decoded bytes32.
|
|
601
657
|
/// @return b Second decoded bytes32.
|
|
602
658
|
function unpack64(Cur memory cur, bytes4 key) internal pure returns (bytes32 a, bytes32 b) {
|
|
603
|
-
uint abs = consume(cur, key, 64, 64);
|
|
659
|
+
uint abs = consume(cur, 0, key, 64, 64);
|
|
604
660
|
a = bytes32(msg.data[abs:abs + 32]);
|
|
605
661
|
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
606
662
|
}
|
|
@@ -612,7 +668,7 @@ library Cursors {
|
|
|
612
668
|
/// @return b Second decoded bytes32.
|
|
613
669
|
/// @return c Third decoded bytes32.
|
|
614
670
|
function unpack96(Cur memory cur, bytes4 key) internal pure returns (bytes32 a, bytes32 b, bytes32 c) {
|
|
615
|
-
uint abs = consume(cur, key, 96, 96);
|
|
671
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
616
672
|
a = bytes32(msg.data[abs:abs + 32]);
|
|
617
673
|
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
618
674
|
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -625,11 +681,8 @@ library Cursors {
|
|
|
625
681
|
/// @return b Second decoded bytes32.
|
|
626
682
|
/// @return c Third decoded bytes32.
|
|
627
683
|
/// @return d Fourth decoded bytes32.
|
|
628
|
-
function unpack128(
|
|
629
|
-
|
|
630
|
-
bytes4 key
|
|
631
|
-
) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d) {
|
|
632
|
-
uint abs = consume(cur, key, 128, 128);
|
|
684
|
+
function unpack128(Cur memory cur, bytes4 key) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d) {
|
|
685
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
633
686
|
a = bytes32(msg.data[abs:abs + 32]);
|
|
634
687
|
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
635
688
|
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -648,7 +701,7 @@ library Cursors {
|
|
|
648
701
|
Cur memory cur,
|
|
649
702
|
bytes4 key
|
|
650
703
|
) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d, bytes32 e) {
|
|
651
|
-
uint abs = consume(cur, key, 160, 160);
|
|
704
|
+
uint abs = consume(cur, 0, key, 160, 160);
|
|
652
705
|
a = bytes32(msg.data[abs:abs + 32]);
|
|
653
706
|
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
654
707
|
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -656,102 +709,6 @@ library Cursors {
|
|
|
656
709
|
e = bytes32(msg.data[abs + 128:abs + 160]);
|
|
657
710
|
}
|
|
658
711
|
|
|
659
|
-
/// @notice Consume a dynamic block with a single uint payload.
|
|
660
|
-
/// @param cur Cursor; advanced past the block.
|
|
661
|
-
/// @param key Expected dynamic block key.
|
|
662
|
-
/// @return value Decoded uint value.
|
|
663
|
-
function unpackUint(Cur memory cur, bytes4 key) internal pure returns (uint value) {
|
|
664
|
-
value = uint(unpack32(cur, key));
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
/// @notice Consume a dynamic block with two uint payload words.
|
|
668
|
-
/// @param cur Cursor; advanced past the block.
|
|
669
|
-
/// @param key Expected dynamic block key.
|
|
670
|
-
/// @return a First decoded uint.
|
|
671
|
-
/// @return b Second decoded uint.
|
|
672
|
-
function unpack2Uint(Cur memory cur, bytes4 key) internal pure returns (uint a, uint b) {
|
|
673
|
-
(bytes32 x, bytes32 y) = unpack64(cur, key);
|
|
674
|
-
return (uint(x), uint(y));
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
/// @notice Consume a dynamic block with three uint payload words.
|
|
678
|
-
/// @param cur Cursor; advanced past the block.
|
|
679
|
-
/// @param key Expected dynamic block key.
|
|
680
|
-
/// @return a First decoded uint.
|
|
681
|
-
/// @return b Second decoded uint.
|
|
682
|
-
/// @return c Third decoded uint.
|
|
683
|
-
function unpack3Uint(Cur memory cur, bytes4 key) internal pure returns (uint a, uint b, uint c) {
|
|
684
|
-
(bytes32 x, bytes32 y, bytes32 z) = unpack96(cur, key);
|
|
685
|
-
return (uint(x), uint(y), uint(z));
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// Generic fixed-head decoders
|
|
689
|
-
|
|
690
|
-
/// @notice Consume a dynamic block with a 32-byte fixed head followed by a variable-length tail.
|
|
691
|
-
/// @param cur Cursor; advanced past the block.
|
|
692
|
-
/// @param key Expected dynamic block key.
|
|
693
|
-
/// @return head Fixed 32-byte head.
|
|
694
|
-
/// @return tail Variable-length payload bytes after the fixed head.
|
|
695
|
-
function unpackHead32(Cur memory cur, bytes4 key) internal pure returns (bytes32 head, bytes calldata tail) {
|
|
696
|
-
uint abs = consume(cur, key, 32, 0);
|
|
697
|
-
head = bytes32(msg.data[abs:abs + 32]);
|
|
698
|
-
tail = msg.data[abs + 32:cur.offset + cur.i];
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
/// @notice Consume a dynamic block with a 64-byte fixed head followed by a variable-length tail.
|
|
702
|
-
/// @param cur Cursor; advanced past the block.
|
|
703
|
-
/// @param key Expected dynamic block key.
|
|
704
|
-
/// @return a First fixed head word.
|
|
705
|
-
/// @return b Second fixed head word.
|
|
706
|
-
/// @return tail Variable-length payload bytes after the fixed head.
|
|
707
|
-
function unpackHead64(
|
|
708
|
-
Cur memory cur,
|
|
709
|
-
bytes4 key
|
|
710
|
-
) internal pure returns (bytes32 a, bytes32 b, bytes calldata tail) {
|
|
711
|
-
uint abs = consume(cur, key, 64, 0);
|
|
712
|
-
a = bytes32(msg.data[abs:abs + 32]);
|
|
713
|
-
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
714
|
-
tail = msg.data[abs + 64:cur.offset + cur.i];
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
/// @notice Consume a dynamic block with a 96-byte fixed head followed by a variable-length tail.
|
|
718
|
-
/// @param cur Cursor; advanced past the block.
|
|
719
|
-
/// @param key Expected dynamic block key.
|
|
720
|
-
/// @return a First fixed head word.
|
|
721
|
-
/// @return b Second fixed head word.
|
|
722
|
-
/// @return c Third fixed head word.
|
|
723
|
-
/// @return tail Variable-length payload bytes after the fixed head.
|
|
724
|
-
function unpackHead96(
|
|
725
|
-
Cur memory cur,
|
|
726
|
-
bytes4 key
|
|
727
|
-
) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes calldata tail) {
|
|
728
|
-
uint abs = consume(cur, key, 96, 0);
|
|
729
|
-
a = bytes32(msg.data[abs:abs + 32]);
|
|
730
|
-
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
731
|
-
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
732
|
-
tail = msg.data[abs + 96:cur.offset + cur.i];
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
/// @notice Consume a dynamic block with a 128-byte fixed head followed by a variable-length tail.
|
|
736
|
-
/// @param cur Cursor; advanced past the block.
|
|
737
|
-
/// @param key Expected dynamic block key.
|
|
738
|
-
/// @return a First fixed head word.
|
|
739
|
-
/// @return b Second fixed head word.
|
|
740
|
-
/// @return c Third fixed head word.
|
|
741
|
-
/// @return d Fourth fixed head word.
|
|
742
|
-
/// @return tail Variable-length payload bytes after the fixed head.
|
|
743
|
-
function unpackHead128(
|
|
744
|
-
Cur memory cur,
|
|
745
|
-
bytes4 key
|
|
746
|
-
) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d, bytes calldata tail) {
|
|
747
|
-
uint abs = consume(cur, key, 128, 0);
|
|
748
|
-
a = bytes32(msg.data[abs:abs + 32]);
|
|
749
|
-
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
750
|
-
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
751
|
-
d = bytes32(msg.data[abs + 96:abs + 128]);
|
|
752
|
-
tail = msg.data[abs + 128:cur.offset + cur.i];
|
|
753
|
-
}
|
|
754
|
-
|
|
755
712
|
// Generic typed-shape decoders
|
|
756
713
|
|
|
757
714
|
/// @notice Consume a fixed-size asset amount block and return asset, meta, and amount.
|
|
@@ -764,7 +721,7 @@ library Cursors {
|
|
|
764
721
|
Cur memory cur,
|
|
765
722
|
bytes4 key
|
|
766
723
|
) internal pure returns (bytes32 asset, bytes32 meta, uint amount) {
|
|
767
|
-
uint abs = consume(cur, key, 96, 96);
|
|
724
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
768
725
|
asset = bytes32(msg.data[abs:abs + 32]);
|
|
769
726
|
meta = bytes32(msg.data[abs + 32:abs + 64]);
|
|
770
727
|
amount = uint(bytes32(msg.data[abs + 64:abs + 96]));
|
|
@@ -781,7 +738,7 @@ library Cursors {
|
|
|
781
738
|
Cur memory cur,
|
|
782
739
|
bytes4 key
|
|
783
740
|
) internal pure returns (bytes32 account, bytes32 asset, bytes32 meta, uint amount) {
|
|
784
|
-
uint abs = consume(cur, key, 128, 128);
|
|
741
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
785
742
|
account = bytes32(msg.data[abs:abs + 32]);
|
|
786
743
|
asset = bytes32(msg.data[abs + 32:abs + 64]);
|
|
787
744
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -799,7 +756,7 @@ library Cursors {
|
|
|
799
756
|
Cur memory cur,
|
|
800
757
|
bytes4 key
|
|
801
758
|
) internal pure returns (uint host, bytes32 asset, bytes32 meta, uint amount) {
|
|
802
|
-
uint abs = consume(cur, key, 128, 128);
|
|
759
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
803
760
|
host = uint(bytes32(msg.data[abs:abs + 32]));
|
|
804
761
|
asset = bytes32(msg.data[abs + 32:abs + 64]);
|
|
805
762
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -817,7 +774,7 @@ library Cursors {
|
|
|
817
774
|
Cur memory cur,
|
|
818
775
|
bytes4 key
|
|
819
776
|
) internal pure returns (uint host, bytes32 account, bytes32 asset, bytes32 meta) {
|
|
820
|
-
uint abs = consume(cur, key, 128, 128);
|
|
777
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
821
778
|
host = uint(bytes32(msg.data[abs:abs + 32]));
|
|
822
779
|
account = bytes32(msg.data[abs + 32:abs + 64]);
|
|
823
780
|
asset = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -836,7 +793,7 @@ library Cursors {
|
|
|
836
793
|
Cur memory cur,
|
|
837
794
|
bytes4 key
|
|
838
795
|
) internal pure returns (bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount) {
|
|
839
|
-
uint abs = consume(cur, key, 160, 160);
|
|
796
|
+
uint abs = consume(cur, 0, key, 160, 160);
|
|
840
797
|
from = bytes32(msg.data[abs:abs + 32]);
|
|
841
798
|
to = bytes32(msg.data[abs + 32:abs + 64]);
|
|
842
799
|
asset = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -860,20 +817,6 @@ library Cursors {
|
|
|
860
817
|
node = uint(unpack32(cur, Keys.Node));
|
|
861
818
|
}
|
|
862
819
|
|
|
863
|
-
/// @notice Consume a RATE block and return the value.
|
|
864
|
-
/// @param cur Cursor; advanced past the block.
|
|
865
|
-
/// @return value Encoded ratio or rate.
|
|
866
|
-
function unpackRate(Cur memory cur) internal pure returns (uint value) {
|
|
867
|
-
value = uint(unpack32(cur, Keys.Rate));
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
/// @notice Consume a QUANTITY block and return the amount.
|
|
871
|
-
/// @param cur Cursor; advanced past the block.
|
|
872
|
-
/// @return amount Scalar quantity value.
|
|
873
|
-
function unpackQuantity(Cur memory cur) internal pure returns (uint amount) {
|
|
874
|
-
amount = uint(unpack32(cur, Keys.Quantity));
|
|
875
|
-
}
|
|
876
|
-
|
|
877
820
|
/// @notice Consume a FEE block and return the amount.
|
|
878
821
|
/// @param cur Cursor; advanced past the block.
|
|
879
822
|
/// @return amount Fee amount.
|
|
@@ -895,7 +838,7 @@ library Cursors {
|
|
|
895
838
|
/// @return asset Asset identifier.
|
|
896
839
|
/// @return meta Asset metadata slot.
|
|
897
840
|
function unpackAccountAsset(Cur memory cur) internal pure returns (bytes32 account, bytes32 asset, bytes32 meta) {
|
|
898
|
-
uint abs = consume(cur, Keys.AccountAsset, 96, 96);
|
|
841
|
+
uint abs = consume(cur, 0, Keys.AccountAsset, 96, 96);
|
|
899
842
|
account = bytes32(msg.data[abs:abs + 32]);
|
|
900
843
|
asset = bytes32(msg.data[abs + 32:abs + 64]);
|
|
901
844
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -918,18 +861,6 @@ library Cursors {
|
|
|
918
861
|
relayer = y;
|
|
919
862
|
}
|
|
920
863
|
|
|
921
|
-
/// @notice Consume a BOUNDS block and return the signed min and max values.
|
|
922
|
-
/// @param cur Cursor; advanced past the block.
|
|
923
|
-
/// @return min Lower signed bound.
|
|
924
|
-
/// @return max Upper signed bound.
|
|
925
|
-
function unpackBounds(Cur memory cur) internal pure returns (int min, int max) {
|
|
926
|
-
uint abs = consume(cur, Keys.Bounds, 64, 64);
|
|
927
|
-
assembly ("memory-safe") {
|
|
928
|
-
min := calldataload(abs)
|
|
929
|
-
max := calldataload(add(abs, 0x20))
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
|
|
933
864
|
/// @notice Consume an AMOUNT block and return its fields as separate values.
|
|
934
865
|
/// @param cur Cursor; advanced past the block.
|
|
935
866
|
/// @return asset Asset identifier.
|
|
@@ -1095,9 +1026,7 @@ library Cursors {
|
|
|
1095
1026
|
/// @return asset Asset identifier.
|
|
1096
1027
|
/// @return meta Asset metadata slot.
|
|
1097
1028
|
/// @return amount Token amount.
|
|
1098
|
-
function unpackCustody(
|
|
1099
|
-
Cur memory cur
|
|
1100
|
-
) internal pure returns (uint host, bytes32 asset, bytes32 meta, uint amount) {
|
|
1029
|
+
function unpackCustody(Cur memory cur) internal pure returns (uint host, bytes32 asset, bytes32 meta, uint amount) {
|
|
1101
1030
|
return unpackHostAmount(cur, Keys.Custody);
|
|
1102
1031
|
}
|
|
1103
1032
|
|
|
@@ -1131,25 +1060,49 @@ library Cursors {
|
|
|
1131
1060
|
// Type-specific dynamic decoders
|
|
1132
1061
|
|
|
1133
1062
|
/// @notice Consume a STEP block and return its sub-command invocation fields.
|
|
1134
|
-
/// The `req` slice
|
|
1063
|
+
/// The `req` slice is the raw payload of the block's required BYTES child.
|
|
1135
1064
|
/// @param cur Cursor; advanced past the block.
|
|
1136
1065
|
/// @return target Destination node ID for the sub-command.
|
|
1137
1066
|
/// @return value Native value to forward with the call.
|
|
1138
1067
|
/// @return req Embedded request bytes for the sub-command.
|
|
1139
1068
|
function unpackStep(Cur memory cur) internal pure returns (uint target, uint value, bytes calldata req) {
|
|
1140
|
-
|
|
1141
|
-
|
|
1069
|
+
uint end = cur.enter(Keys.Step, 64 + Sizes.Header, 0);
|
|
1070
|
+
target = uint(cur.read32());
|
|
1071
|
+
value = uint(cur.read32());
|
|
1072
|
+
req = cur.unpackBytes();
|
|
1073
|
+
cur.exit(end);
|
|
1142
1074
|
}
|
|
1143
1075
|
|
|
1144
1076
|
/// @notice Consume a CALL block and return its target invocation fields.
|
|
1145
|
-
/// The `data` slice
|
|
1077
|
+
/// The `data` slice is the raw payload of the block's required BYTES child.
|
|
1146
1078
|
/// @param cur Cursor; advanced past the block.
|
|
1147
1079
|
/// @return target Target node ID to call.
|
|
1148
1080
|
/// @return value Native value to forward with the call.
|
|
1149
1081
|
/// @return data Raw calldata payload for the target.
|
|
1150
1082
|
function unpackCall(Cur memory cur) internal pure returns (uint target, uint value, bytes calldata data) {
|
|
1151
|
-
|
|
1152
|
-
|
|
1083
|
+
uint end = cur.enter(Keys.Call, 64 + Sizes.Header, 0);
|
|
1084
|
+
target = uint(cur.read32());
|
|
1085
|
+
value = uint(cur.read32());
|
|
1086
|
+
data = cur.unpackBytes();
|
|
1087
|
+
cur.exit(end);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
/// @notice Consume a CONTEXT block and return its command context fields.
|
|
1091
|
+
/// The `state` and `request` slices are the raw payloads of the required BYTES children.
|
|
1092
|
+
/// @param cur Cursor; advanced past the block.
|
|
1093
|
+
/// @return account Command account identifier.
|
|
1094
|
+
/// @return value Native value budget assigned to the context.
|
|
1095
|
+
/// @return state Embedded state block stream.
|
|
1096
|
+
/// @return request Embedded request block stream.
|
|
1097
|
+
function unpackContext(
|
|
1098
|
+
Cur memory cur
|
|
1099
|
+
) internal pure returns (bytes32 account, uint value, bytes calldata state, bytes calldata request) {
|
|
1100
|
+
uint end = cur.enter(Keys.Context, 64 + 2 * Sizes.Header, 0);
|
|
1101
|
+
account = cur.read32();
|
|
1102
|
+
value = uint(cur.read32());
|
|
1103
|
+
state = cur.unpackBytes();
|
|
1104
|
+
request = cur.unpackBytes();
|
|
1105
|
+
cur.exit(end);
|
|
1153
1106
|
}
|
|
1154
1107
|
|
|
1155
1108
|
// Type-specific validators
|
|
@@ -1162,10 +1115,12 @@ library Cursors {
|
|
|
1162
1115
|
/// @return deadline Expiry timestamp.
|
|
1163
1116
|
/// @return proof Raw proof bytes (layout: `[bytes20 signer][bytes65 sig]`).
|
|
1164
1117
|
function expectAuth(Cur memory cur, uint i, uint cid) internal pure returns (uint deadline, bytes calldata proof) {
|
|
1165
|
-
(uint abs, uint next) = expect(cur, i, Keys.Auth,
|
|
1118
|
+
(uint abs, uint next) = expect(cur, i, 0, Keys.Auth, 64 + Sizes.Header + Sizes.Proof, 0);
|
|
1166
1119
|
if (uint(bytes32(msg.data[abs:abs + 32])) != cid) revert UnexpectedValue();
|
|
1167
1120
|
deadline = uint(bytes32(msg.data[abs + 32:abs + 64]));
|
|
1168
|
-
|
|
1121
|
+
|
|
1122
|
+
(abs, ) = expect(cur, i + Sizes.Header + 64, next, Keys.Bytes, Sizes.Proof, Sizes.Proof);
|
|
1123
|
+
proof = msg.data[abs:abs + Sizes.Proof];
|
|
1169
1124
|
}
|
|
1170
1125
|
|
|
1171
1126
|
// -------------------------------------------------------------------------
|
|
@@ -1183,7 +1138,7 @@ library Cursors {
|
|
|
1183
1138
|
bytes4 key,
|
|
1184
1139
|
bytes32 asset
|
|
1185
1140
|
) internal pure returns (bytes32 meta, uint amount) {
|
|
1186
|
-
uint abs = consume(cur, key, 96, 96);
|
|
1141
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
1187
1142
|
if (bytes32(msg.data[abs:abs + 32]) != asset) revert UnexpectedValue();
|
|
1188
1143
|
meta = bytes32(msg.data[abs + 32:abs + 64]);
|
|
1189
1144
|
amount = uint(bytes32(msg.data[abs + 64:abs + 96]));
|
|
@@ -1201,7 +1156,7 @@ library Cursors {
|
|
|
1201
1156
|
bytes32 asset,
|
|
1202
1157
|
bytes32 meta
|
|
1203
1158
|
) internal pure returns (uint amount) {
|
|
1204
|
-
uint abs = consume(cur, key, 96, 96);
|
|
1159
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
1205
1160
|
if (bytes32(msg.data[abs:abs + 32]) != asset) revert UnexpectedValue();
|
|
1206
1161
|
if (bytes32(msg.data[abs + 32:abs + 64]) != meta) revert UnexpectedValue();
|
|
1207
1162
|
amount = uint(bytes32(msg.data[abs + 64:abs + 96]));
|
|
@@ -1213,7 +1168,7 @@ library Cursors {
|
|
|
1213
1168
|
/// @param asset Expected asset identifier.
|
|
1214
1169
|
/// @return meta Metadata slot from the block.
|
|
1215
1170
|
function requireUnitAssetAmount(Cur memory cur, bytes4 key, bytes32 asset) internal pure returns (bytes32 meta) {
|
|
1216
|
-
uint abs = consume(cur, key, 96, 96);
|
|
1171
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
1217
1172
|
if (bytes32(msg.data[abs:abs + 32]) != asset) revert UnexpectedValue();
|
|
1218
1173
|
meta = bytes32(msg.data[abs + 32:abs + 64]);
|
|
1219
1174
|
if (uint(bytes32(msg.data[abs + 64:abs + 96])) != 1) revert UnexpectedValue();
|
|
@@ -1240,7 +1195,7 @@ library Cursors {
|
|
|
1240
1195
|
bytes4 key,
|
|
1241
1196
|
uint host
|
|
1242
1197
|
) internal pure returns (bytes32 asset, bytes32 meta, uint amount) {
|
|
1243
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1198
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1244
1199
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1245
1200
|
asset = bytes32(msg.data[abs + 32:abs + 64]);
|
|
1246
1201
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1260,7 +1215,7 @@ library Cursors {
|
|
|
1260
1215
|
uint host,
|
|
1261
1216
|
bytes32 asset
|
|
1262
1217
|
) internal pure returns (bytes32 meta, uint amount) {
|
|
1263
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1218
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1264
1219
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1265
1220
|
if (bytes32(msg.data[abs + 32:abs + 64]) != asset) revert UnexpectedValue();
|
|
1266
1221
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1279,7 +1234,7 @@ library Cursors {
|
|
|
1279
1234
|
uint host,
|
|
1280
1235
|
bytes32 asset
|
|
1281
1236
|
) internal pure returns (bytes32 meta) {
|
|
1282
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1237
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1283
1238
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1284
1239
|
if (bytes32(msg.data[abs + 32:abs + 64]) != asset) revert UnexpectedValue();
|
|
1285
1240
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1299,7 +1254,7 @@ library Cursors {
|
|
|
1299
1254
|
uint host,
|
|
1300
1255
|
bytes32 account
|
|
1301
1256
|
) internal pure returns (bytes32 asset, bytes32 meta) {
|
|
1302
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1257
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1303
1258
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1304
1259
|
if (bytes32(msg.data[abs + 32:abs + 64]) != account) revert UnexpectedValue();
|
|
1305
1260
|
asset = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1318,7 +1273,7 @@ library Cursors {
|
|
|
1318
1273
|
bytes4 key,
|
|
1319
1274
|
uint host
|
|
1320
1275
|
) internal pure returns (bytes32 account, bytes32 asset, bytes32 meta) {
|
|
1321
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1276
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1322
1277
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1323
1278
|
account = bytes32(msg.data[abs + 32:abs + 64]);
|
|
1324
1279
|
asset = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1345,7 +1300,7 @@ library Cursors {
|
|
|
1345
1300
|
/// @return proof Raw proof bytes.
|
|
1346
1301
|
function requireAuth(Cur memory cur, uint cid) internal pure returns (uint deadline, bytes calldata proof) {
|
|
1347
1302
|
(deadline, proof) = expectAuth(cur, cur.i, cid);
|
|
1348
|
-
cur.i += Sizes.
|
|
1303
|
+
cur.i += Sizes.Auth;
|
|
1349
1304
|
}
|
|
1350
1305
|
|
|
1351
1306
|
// -------------------------------------------------------------------------
|
|
@@ -1362,7 +1317,7 @@ library Cursors {
|
|
|
1362
1317
|
uint i = find(cur, 0, Keys.Node);
|
|
1363
1318
|
if (i == cur.len) return backup;
|
|
1364
1319
|
|
|
1365
|
-
(uint abs, ) = expect(cur, i, Keys.Node, 32, 32);
|
|
1320
|
+
(uint abs, ) = expect(cur, i, 0, Keys.Node, 32, 32);
|
|
1366
1321
|
return uint(bytes32(msg.data[abs:abs + 32]));
|
|
1367
1322
|
}
|
|
1368
1323
|
|
|
@@ -1386,7 +1341,7 @@ library Cursors {
|
|
|
1386
1341
|
uint i = find(cur, 0, Keys.Account);
|
|
1387
1342
|
if (i == cur.len) return backup;
|
|
1388
1343
|
|
|
1389
|
-
(uint abs, ) = expect(cur, i, Keys.Account, 32, 32);
|
|
1344
|
+
(uint abs, ) = expect(cur, i, 0, Keys.Account, 32, 32);
|
|
1390
1345
|
return bytes32(msg.data[abs:abs + 32]);
|
|
1391
1346
|
}
|
|
1392
1347
|
|
|
@@ -1399,7 +1354,7 @@ library Cursors {
|
|
|
1399
1354
|
uint i = find(cur, cur.bound, Keys.Node);
|
|
1400
1355
|
if (i == cur.len) return backup;
|
|
1401
1356
|
|
|
1402
|
-
(uint abs, ) = expect(cur, i, Keys.Node, 32, 32);
|
|
1357
|
+
(uint abs, ) = expect(cur, i, 0, Keys.Node, 32, 32);
|
|
1403
1358
|
return uint(bytes32(msg.data[abs:abs + 32]));
|
|
1404
1359
|
}
|
|
1405
1360
|
|
|
@@ -1412,7 +1367,7 @@ library Cursors {
|
|
|
1412
1367
|
uint i = find(cur, cur.bound, Keys.Account);
|
|
1413
1368
|
if (i == cur.len) return backup;
|
|
1414
1369
|
|
|
1415
|
-
(uint abs, ) = expect(cur, i, Keys.Account, 32, 32);
|
|
1370
|
+
(uint abs, ) = expect(cur, i, 0, Keys.Account, 32, 32);
|
|
1416
1371
|
return bytes32(msg.data[abs:abs + 32]);
|
|
1417
1372
|
}
|
|
1418
1373
|
|
|
@@ -1422,19 +1377,19 @@ library Cursors {
|
|
|
1422
1377
|
/// The signed slice covers from `cur.i` up to (but not including) the AUTH proof bytes.
|
|
1423
1378
|
/// @param cur Source cursor; `bound` marks the end of the primary data region.
|
|
1424
1379
|
/// @param cid Command ID that the signature must be bound to.
|
|
1425
|
-
/// @return
|
|
1380
|
+
/// @return digest keccak256 of the signed message slice.
|
|
1426
1381
|
/// @return deadline Expiry timestamp from the AUTH block.
|
|
1427
1382
|
/// @return proof Raw proof bytes (layout: `[bytes20 signer][bytes65 sig]`).
|
|
1428
1383
|
function authLast(
|
|
1429
1384
|
Cur memory cur,
|
|
1430
1385
|
uint cid
|
|
1431
|
-
) internal pure returns (bytes32
|
|
1386
|
+
) internal pure returns (bytes32 digest, uint deadline, bytes calldata proof) {
|
|
1432
1387
|
if (cur.len - cur.i < Sizes.Auth) revert MalformedBlocks();
|
|
1433
1388
|
|
|
1434
1389
|
uint i = cur.len - Sizes.Auth;
|
|
1435
1390
|
if (i < cur.bound) revert MalformedBlocks();
|
|
1436
1391
|
|
|
1437
1392
|
(deadline, proof) = expectAuth(cur, i, cid);
|
|
1438
|
-
|
|
1393
|
+
digest = cur.hash(cur.i, cur.len - Sizes.Proof);
|
|
1439
1394
|
}
|
|
1440
1395
|
}
|