@rootzero/contracts 1.25.0 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/Codec.sol +1 -2
  3. package/Endpoints.sol +2 -0
  4. package/README.md +73 -51
  5. package/Utils.sol +2 -1
  6. package/codec/Blocks.sol +276 -88
  7. package/codec/Buffers.sol +24 -20
  8. package/codec/Decoders.sol +35 -37
  9. package/codec/Descriptors.sol +75 -72
  10. package/codec/Keys.sol +5 -1
  11. package/codec/Schema.sol +7 -1
  12. package/codec/Specs.sol +19 -9
  13. package/codec/Writers.sol +14 -19
  14. package/commands/Allocate.sol +8 -7
  15. package/commands/Base.sol +14 -49
  16. package/commands/Bootstrap.sol +81 -0
  17. package/commands/Burn.sol +7 -7
  18. package/commands/Cashout.sol +86 -0
  19. package/commands/Credit.sol +20 -17
  20. package/commands/Debit.sol +25 -20
  21. package/commands/Deposit.sol +13 -13
  22. package/commands/Payout.sol +8 -8
  23. package/commands/Provision.sol +13 -13
  24. package/commands/Recover.sol +7 -7
  25. package/commands/Relay.sol +22 -23
  26. package/commands/Repay.sol +38 -35
  27. package/commands/Settle.sol +26 -23
  28. package/commands/Withdraw.sol +7 -7
  29. package/commands/admin/AllowAssets.sol +7 -7
  30. package/commands/admin/Allowance.sol +7 -7
  31. package/commands/admin/Annotate.sol +7 -7
  32. package/commands/admin/Appoint.sol +7 -7
  33. package/commands/admin/Authorize.sol +7 -7
  34. package/commands/admin/Base.sol +5 -8
  35. package/commands/admin/DenyAssets.sol +7 -7
  36. package/commands/admin/Dismiss.sol +7 -7
  37. package/commands/admin/Execute.sol +8 -8
  38. package/commands/admin/Unauthorize.sol +7 -7
  39. package/core/Access.sol +1 -0
  40. package/core/Calls.sol +3 -3
  41. package/core/Endpoint.sol +7 -7
  42. package/core/Pipeline.sol +19 -23
  43. package/core/Settlement.sol +2 -1
  44. package/core/Types.sol +1 -0
  45. package/execution/Budget.sol +2 -3
  46. package/execution/Execution.sol +270 -511
  47. package/guards/Base.sol +1 -1
  48. package/guards/Revoke.sol +7 -7
  49. package/package.json +1 -1
  50. package/ports/Allowance.sol +3 -3
  51. package/ports/Assets.sol +7 -7
  52. package/ports/Base.sol +1 -1
  53. package/ports/Credit.sol +3 -3
  54. package/ports/Debit.sol +3 -3
  55. package/ports/Dispatch.sol +3 -3
  56. package/ports/Pipe.sol +3 -3
  57. package/ports/Post.sol +3 -3
  58. package/ports/Redeem.sol +3 -3
  59. package/queries/Assets.sol +3 -3
  60. package/queries/Balances.sol +3 -3
  61. package/queries/Base.sol +1 -1
  62. package/utils/Accounts.sol +17 -10
  63. package/utils/Actions.sol +2 -0
  64. package/utils/Assets.sol +1 -10
  65. package/utils/Cursors.sol +60 -116
  66. package/utils/Errors.sol +56 -0
  67. package/utils/Ids.sol +2 -5
  68. package/utils/Lanes.sol +0 -2
  69. package/utils/Nodes.sol +1 -3
  70. package/utils/Utils.sol +2 -9
  71. package/codec/Readers.sol +0 -190
@@ -5,11 +5,10 @@ import {AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAcc
5
5
  import {Blocks} from "../codec/Blocks.sol";
6
6
  import {Buffers} from "../codec/Buffers.sol";
7
7
  import {Sizes, Specs} from "../codec/Specs.sol";
8
- import {Descriptors} from "../codec/Descriptors.sol";
9
8
  import {Cursors, Cur} from "../utils/Cursors.sol";
9
+ import {InsufficientValue, UnconsumedData} from "../utils/Errors.sol";
10
10
  import {Lanes} from "../utils/Lanes.sol";
11
11
  import {Budget} from "./Budget.sol";
12
- import {max16} from "../utils/Utils.sol";
13
12
 
14
13
  /// @notice Mutable state shared across one endpoint execution.
15
14
  /// @dev `decoders` contains tagged input and state cursor lanes. Cursor operations
@@ -18,165 +17,28 @@ struct Execution {
18
17
  bytes32 account;
19
18
  uint budget;
20
19
  uint decoders;
21
- uint writers;
22
- bytes transactions;
20
+ uint writer;
23
21
  bytes output;
24
22
  }
25
23
 
26
24
  /// @title Executions
27
- /// @notice Opening, decoding, output, transaction, and value helpers for executions.
25
+ /// @notice Opening, decoding, output, and value helpers for executions.
28
26
  /// @dev `output*` helpers consume memory inputs; `outputCopy*` helpers copy
29
27
  /// calldata inputs directly to the output lane.
30
28
  library Executions {
31
29
  using Cursors for uint;
32
30
 
33
- /// @dev Thrown when an execution attempts to spend more value than remains in its budget.
34
- error InsufficientValue();
35
- /// @dev Decoder block counts do not form compatible descriptor groups.
36
- error BadRatio();
37
- /// @dev A descriptor-empty lane received a non-empty block source.
38
- error ZeroStride();
39
-
40
31
  // -------------------------------------------------------------------------
41
32
  // Opening
42
33
  // -------------------------------------------------------------------------
43
34
 
44
- /// @dev A lane with stride zero accepts only an empty source and returns the zero cursor.
45
- /// @param source Calldata source for the decoder lane.
46
- /// @param descriptor Packed endpoint descriptor.
47
- /// @param lane Input or state lane identifier.
48
- /// @return cur Tagged packed decoder cursor carrying its raw block count, or zero for an absent lane.
49
- function openDecoder(bytes calldata source, uint descriptor, uint8 lane) private pure returns (uint cur) {
50
- uint stride = Descriptors.stride(descriptor, lane);
51
- (uint abs, uint limit) = Cursors.bounds(source);
52
- if (stride == 0 && abs == limit) return 0;
53
- if (stride == 0) revert ZeroStride();
54
-
55
- bytes4 key = Descriptors.key(descriptor, lane);
56
- (uint count, uint end) = Blocks.runExact(abs, limit, key);
57
- if (count == 0) revert Blocks.EmptyRun();
58
- cur = Cursors.create(abs, end - abs, count, 0, lane);
59
- }
60
-
61
- /// @dev Convert one decoder lane's raw block count into descriptor groups.
62
- function groupCount(uint decoders, uint descriptor, uint8 lane) private pure returns (uint groups) {
63
- uint stride = Descriptors.stride(descriptor, lane);
64
- if (stride == 0) return 0;
65
-
66
- uint count = decoders.select(lane).count();
67
- if (count % stride != 0) revert BadRatio();
68
- groups = count / stride;
69
- }
70
-
71
- /// @dev Reconcile decoder lane groups once at endpoint execution opening.
72
- function reconcile(uint decoders, uint descriptor, uint expected) private pure returns (uint groups) {
73
- uint input = groupCount(decoders, descriptor, Lanes.Input);
74
- uint state = groupCount(decoders, descriptor, Lanes.State);
75
- if (input != 0 && state != 0 && input != state) revert BadRatio();
76
-
77
- groups = input != 0 ? input : state;
78
- if (groups != 0 && expected != 0 && groups != expected) revert BadRatio();
79
- if (groups == 0) groups = expected;
80
- max16(groups);
81
- }
82
-
83
- /// @dev Initialize one tagged writer cursor from a descriptor lane.
84
- /// @param descriptor Packed endpoint descriptor.
85
- /// @param batches Reconciled execution batch count.
86
- /// @param lane Output or transaction lane identifier.
87
- /// @param padding Additional logical capacity reserved for the lane.
88
- /// @return cur Tagged packed writer cursor, or zero for an absent lane.
89
- function initWriter(uint descriptor, uint batches, uint8 lane, uint padding) private pure returns (uint cur) {
90
- (uint capacity, bool growable) = Descriptors.allocation(descriptor, lane, batches);
91
- if (capacity == 0) return 0;
92
-
93
- uint count = batches * Descriptors.stride(descriptor, lane);
94
- if (padding != 0) count += padding / Sizes.Transaction;
95
- cur = Buffers.cursor(capacity + padding, count, growable, lane);
96
- }
97
-
98
- /// @dev Open and pair the input and state decoder cursors.
99
- /// @param state State calldata source.
100
- /// @param input Input calldata source.
101
- /// @param descriptor Packed endpoint descriptor.
102
- /// @return Paired decoder cursors.
103
- function decodeCursors(bytes calldata state, bytes calldata input, uint descriptor) private pure returns (uint) {
104
- return
105
- Cursors.pair(openDecoder(input, descriptor, Lanes.Input), openDecoder(state, descriptor, Lanes.State));
106
- }
107
-
108
- /// @dev Initialize and pair the output and transaction writer cursors.
109
- /// @param descriptor Packed endpoint descriptor.
110
- /// @param batches Reconciled execution batch count.
111
- /// @return Paired writer cursors.
112
- function writerCursors(uint descriptor, uint batches) private pure returns (uint) {
113
- return
114
- Cursors.pair(
115
- initWriter(descriptor, batches, Lanes.Output, 0),
116
- initWriter(descriptor, batches, Lanes.Transactions, Sizes.Transaction)
117
- );
118
- }
119
-
120
- /// @dev Complete execution initialization from pre-opened decoder cursors.
121
- /// @param decoders Packed decoder cursor or pair.
122
- /// @param descriptor Packed endpoint descriptor.
123
- /// @param batches Expected batch count; zero derives it from the decoders.
124
- /// @return exec Initialized execution.
125
- function open(uint decoders, uint descriptor, uint batches) private view returns (Execution memory exec) {
126
- exec.budget = msg.value;
127
- exec.decoders = decoders;
128
- batches = reconcile(decoders, descriptor, batches);
129
- exec.writers = writerCursors(descriptor, batches);
130
- }
131
-
132
35
  /// @notice Open an execution containing only the current call-value budget.
133
- /// @dev Decoders, writers, output, and transactions remain empty.
36
+ /// @dev Decoders, writer, and output remain empty.
134
37
  /// @return exec Budget-only execution initialized with `msg.value`.
135
38
  function open() internal view returns (Execution memory exec) {
136
39
  exec.budget = msg.value;
137
40
  }
138
41
 
139
- /// @notice Open an execution with an input decoder and descriptor writers.
140
- /// @param input Input block stream.
141
- /// @param descriptor Packed endpoint descriptor.
142
- /// @param batches Expected batch count; zero derives it from the input run.
143
- /// @return exec Initialized execution.
144
- function openInput(
145
- bytes calldata input,
146
- uint descriptor,
147
- uint batches
148
- ) internal view returns (Execution memory exec) {
149
- return open(openDecoder(input, descriptor, Lanes.Input), descriptor, batches);
150
- }
151
-
152
- /// @notice Open an execution with a state decoder and descriptor writers.
153
- /// @param state State block stream.
154
- /// @param descriptor Packed endpoint descriptor.
155
- /// @param batches Expected batch count; zero derives it from the state run.
156
- /// @return exec Initialized execution.
157
- function openState(
158
- bytes calldata state,
159
- uint descriptor,
160
- uint batches
161
- ) internal view returns (Execution memory exec) {
162
- return open(openDecoder(state, descriptor, Lanes.State), descriptor, batches);
163
- }
164
-
165
- /// @notice Open an execution with paired state and input decoders.
166
- /// @param state State block stream.
167
- /// @param input Input block stream.
168
- /// @param descriptor Packed endpoint descriptor.
169
- /// @param batches Expected batch count; zero derives it from the decoder runs.
170
- /// @return exec Initialized execution.
171
- function open(
172
- bytes calldata state,
173
- bytes calldata input,
174
- uint descriptor,
175
- uint batches
176
- ) internal view returns (Execution memory exec) {
177
- return open(decodeCursors(state, input, descriptor), descriptor, batches);
178
- }
179
-
180
42
  // -------------------------------------------------------------------------
181
43
  // Traversal
182
44
  // -------------------------------------------------------------------------
@@ -188,99 +50,134 @@ library Executions {
188
50
  return exec.decoders.any();
189
51
  }
190
52
 
191
- /// @notice Return a decoder lane's current absolute calldata position.
53
+ /// @notice Make the input decoder the active low lane.
54
+ /// @return exec The same execution, allowing chained decoding.
55
+ function oninput(Execution memory exec) internal pure returns (Execution memory) {
56
+ exec.decoders = exec.decoders.select(Lanes.Input);
57
+ return exec;
58
+ }
59
+
60
+ /// @notice Make the state decoder the active low lane.
61
+ /// @return exec The same execution, allowing chained decoding.
62
+ function onstate(Execution memory exec) internal pure returns (Execution memory) {
63
+ exec.decoders = exec.decoders.select(Lanes.State);
64
+ return exec;
65
+ }
66
+
67
+ /// @notice Return the active decoder's current absolute calldata position.
192
68
  /// @param exec Execution whose decoder is inspected.
193
- /// @param lane Decoder lane to select.
194
- /// @return Current absolute calldata position of the selected lane.
195
- function absolute(Execution memory exec, uint8 lane) internal pure returns (uint) {
196
- return exec.decoders.select(lane).absolute();
69
+ /// @return Current absolute calldata position of the active lane.
70
+ function absolute(Execution memory exec) internal pure returns (uint) {
71
+ return exec.decoders.absolute();
197
72
  }
198
73
 
199
- /// @dev Return the complete validated calldata source for a decoder lane.
74
+ /// @dev Return the complete bounded calldata source for a decoder lane.
200
75
  /// @dev Does not consume or depend on the lane's current position. A lane
201
76
  /// absent because its descriptor is EMPTY returns an empty calldata slice.
202
77
  /// @param exec Execution whose input or state source is requested.
203
- /// @param lane Input or state decoder lane.
204
78
  /// @return data Complete calldata region represented by the lane.
205
79
  function raw(Execution memory exec, uint8 lane) private pure returns (bytes calldata data) {
206
80
  if (!exec.decoders.contains(lane)) return msg.data[0:0];
207
81
 
208
82
  uint cur = exec.decoders.select(lane);
209
- (, uint offset, uint len) = cur.decode();
210
- if (len > msg.data.length || offset > msg.data.length - len) revert Blocks.MalformedBlocks();
211
- return msg.data[offset:offset + len];
83
+ if (uint8(cur >> 96) == 0) return msg.data[0:0];
84
+ (uint abs, uint end) = cur.bounds();
85
+ if (end > msg.data.length) revert Blocks.MalformedBlocks();
86
+ return msg.data[abs:end];
212
87
  }
213
88
 
214
- /// @notice Return the complete validated command state without consuming it.
89
+ /// @notice Return the complete bounded command state without consuming it.
215
90
  /// @dev Remains the complete original state after the state cursor advances.
216
91
  function rawState(Execution memory exec) internal pure returns (bytes calldata) {
217
92
  return raw(exec, Lanes.State);
218
93
  }
219
94
 
220
- /// @notice Return the complete validated endpoint input without consuming it.
95
+ /// @notice Return the complete state lane and mark it fully consumed.
96
+ /// @dev Intended for commands that forward their state intact without decoding it.
97
+ /// A lane declared EMPTY is returned empty and remains unconsumed so close
98
+ /// still rejects any state supplied against the descriptor.
99
+ function takeRawState(Execution memory exec) internal pure returns (bytes calldata data) {
100
+ data = raw(exec, Lanes.State);
101
+ if (!exec.decoders.contains(Lanes.State)) return data;
102
+
103
+ uint cur = exec.decoders.select(Lanes.State);
104
+ if (uint8(cur >> 96) == 0) return data;
105
+ (, , uint len) = cur.decode();
106
+ exec.decoders = cur.seek(len);
107
+ }
108
+
109
+ /// @notice Return the complete bounded endpoint input without consuming it.
221
110
  /// @dev Remains the complete original input after the input cursor advances.
222
111
  function rawInput(Execution memory exec) internal pure returns (bytes calldata) {
223
112
  return raw(exec, Lanes.Input);
224
113
  }
225
114
 
115
+ /// @notice Return the complete input lane and mark it fully consumed.
116
+ /// @dev Intended for endpoints that forward their input intact without decoding it.
117
+ /// A lane declared EMPTY is returned empty and remains unconsumed so close
118
+ /// still rejects any input supplied against the descriptor.
119
+ function takeRawInput(Execution memory exec) internal pure returns (bytes calldata data) {
120
+ data = raw(exec, Lanes.Input);
121
+ if (!exec.decoders.contains(Lanes.Input)) return data;
122
+
123
+ uint cur = exec.decoders.select(Lanes.Input);
124
+ if (uint8(cur >> 96) == 0) return data;
125
+ (, , uint len) = cur.decode();
126
+ exec.decoders = cur.seek(len);
127
+ }
128
+
226
129
  /// @notice Return whether the next block on `lane` has `key` and an empty payload.
227
130
  /// @param exec Execution whose decoder is inspected without advancing.
228
- /// @param lane Decoder lane to inspect.
229
131
  /// @param key Expected block key.
230
132
  /// @return Whether a complete matching empty block header occurs next.
231
- function isEmpty(Execution memory exec, uint8 lane, bytes4 key) internal pure returns (bool) {
232
- uint cur = exec.decoders.select(lane);
133
+ function isEmpty(Execution memory exec, bytes4 key) internal pure returns (bool) {
134
+ uint cur = exec.decoders;
233
135
  (uint i, uint offset, uint len) = cur.decode();
234
136
  return Blocks.isEmpty(offset + i, offset + len, key);
235
137
  }
236
138
 
237
139
  /// @notice Validate and consume the next block from an execution decoder lane.
238
- /// @param exec Execution whose selected decoder cursor is advanced over the complete block.
239
- /// @param lane Execution decoder lane to select.
140
+ /// @param exec Execution whose active decoder cursor is advanced over the complete block.
240
141
  /// @param spec Expected block specification.
241
142
  /// @return abs Absolute position of the first payload byte.
242
143
  /// @return end Absolute position immediately after the payload.
243
- function consume(Execution memory exec, uint8 lane, uint spec) internal pure returns (uint abs, uint end) {
244
- uint cur = exec.decoders.select(lane);
144
+ function consume(Execution memory exec, uint spec) internal pure returns (uint abs, uint end) {
145
+ uint cur = exec.decoders;
245
146
  (abs, end) = Blocks.expect(cur.absolute(), spec);
246
147
  exec.decoders = cur.seekAbs(end);
247
148
  }
248
149
 
249
150
  /// @notice Validate a known key and consume the next block from an execution decoder lane.
250
151
  /// @dev Validates no payload-size constraint beyond proving the complete block
251
- /// lies within the selected lane's logical region.
252
- /// @param exec Execution whose selected decoder cursor is advanced over the complete block.
253
- /// @param lane Execution decoder lane to select.
152
+ /// lies within the active lane's logical region.
153
+ /// @param exec Execution whose active decoder cursor is advanced over the complete block.
254
154
  /// @param key Expected block key.
255
155
  /// @return abs Absolute position of the first payload byte.
256
156
  /// @return end Absolute position immediately after the payload.
257
- function consume(Execution memory exec, uint8 lane, bytes4 key) internal pure returns (uint abs, uint end) {
258
- uint cur = exec.decoders.select(lane);
157
+ function consume(Execution memory exec, bytes4 key) internal pure returns (uint abs, uint end) {
158
+ uint cur = exec.decoders;
259
159
  (abs, end) = Blocks.expectKey(cur.absolute(), key);
260
160
  exec.decoders = cur.seekAbs(end);
261
161
  }
262
162
 
263
163
  /// @notice Validate and consume one block from a decoder lane, returning its complete encoding.
264
- /// @param exec Execution whose selected decoder cursor is advanced past the block.
265
- /// @param lane Execution decoder lane to select.
164
+ /// @param exec Execution whose active decoder cursor is advanced past the block.
266
165
  /// @param key Expected block key.
267
166
  /// @return data Calldata view of the complete block, including its header.
268
167
  function takeBlock(
269
168
  Execution memory exec,
270
- uint8 lane,
271
169
  bytes4 key
272
170
  ) internal pure returns (bytes calldata data) {
273
- (uint abs, uint end) = consume(exec, lane, key);
171
+ (uint abs, uint end) = consume(exec, key);
274
172
  data = msg.data[abs - Sizes.Header:end];
275
173
  }
276
174
 
277
175
  /// @notice Consume a matching empty block from an execution decoder lane when present.
278
- /// @param exec Execution whose selected decoder advances only for a matching empty block.
279
- /// @param lane Decoder lane to consume.
176
+ /// @param exec Execution whose active decoder advances only for a matching empty block.
280
177
  /// @param key Expected block key.
281
178
  /// @return Whether an empty block was consumed.
282
- function tryConsumeEmpty(Execution memory exec, uint8 lane, bytes4 key) internal pure returns (bool) {
283
- uint cur = exec.decoders.select(lane);
179
+ function tryConsumeEmpty(Execution memory exec, bytes4 key) internal pure returns (bool) {
180
+ uint cur = exec.decoders;
284
181
  (uint i, uint offset, uint size) = cur.decode();
285
182
  (bytes4 current, uint len) = Blocks.peek(offset + i, offset + size);
286
183
  if (current != key || len != 0) return false;
@@ -289,34 +186,31 @@ library Executions {
289
186
  }
290
187
 
291
188
  /// @notice Validate and enter the payload of the next block in an execution decoder lane.
292
- /// @dev The selected lane remains in its existing frame so callers can decode
189
+ /// @dev The active lane remains in its existing frame so callers can decode
293
190
  /// child blocks in place. Callers should prove complete payload consumption
294
191
  /// with `exec.expectAbs(end)` after decoding the children from the same lane.
295
- /// @param exec Execution whose selected decoder cursor advances over the block header.
296
- /// @param lane Execution decoder lane to select.
192
+ /// @param exec Execution whose active decoder cursor advances over the block header.
297
193
  /// @param spec Expected parent block specification.
298
194
  /// @return abs Absolute position of the first payload byte.
299
195
  /// @return end Absolute position immediately after the payload.
300
- function enter(Execution memory exec, uint8 lane, uint spec) internal pure returns (uint abs, uint end) {
301
- return enter(exec, lane, spec, 0);
196
+ function enter(Execution memory exec, uint spec) internal pure returns (uint abs, uint end) {
197
+ return enter(exec, spec, 0);
302
198
  }
303
199
 
304
200
  /// @notice Validate a parent block and advance over a fixed payload prefix.
305
201
  /// @dev `amount` is relative to the payload start and cannot exceed the
306
202
  /// current parent payload. The returned `abs` remains the payload start.
307
- /// @param exec Execution whose selected decoder advances over the header and fixed prefix.
308
- /// @param lane Execution decoder lane to select.
203
+ /// @param exec Execution whose active decoder advances over the header and fixed prefix.
309
204
  /// @param spec Expected parent block specification.
310
205
  /// @param amount Number of initial payload bytes to advance over.
311
206
  /// @return abs Absolute position of the first payload byte.
312
207
  /// @return end Absolute position immediately after the payload.
313
208
  function enter(
314
209
  Execution memory exec,
315
- uint8 lane,
316
210
  uint spec,
317
211
  uint amount
318
212
  ) internal pure returns (uint abs, uint end) {
319
- uint cur = exec.decoders.select(lane);
213
+ uint cur = exec.decoders;
320
214
  (abs, end) = Blocks.expect(cur.absolute(), spec);
321
215
  if (amount > end - abs) revert Blocks.InvalidBlock();
322
216
  exec.decoders = cur.seekAbs(abs + amount);
@@ -324,26 +218,24 @@ library Executions {
324
218
 
325
219
  /// @notice Advance an execution decoder lane by a raw byte count.
326
220
  /// @dev No block header or schema is validated.
327
- /// @param exec Execution whose selected decoder cursor is advanced.
328
- /// @param lane Decoder lane to select.
221
+ /// @param exec Execution whose active decoder cursor is advanced.
329
222
  /// @param amount Number of bytes to advance.
330
- function advance(Execution memory exec, uint8 lane, uint amount) internal pure {
331
- uint cur = exec.decoders.select(lane);
223
+ function advance(Execution memory exec, uint amount) internal pure {
224
+ uint cur = exec.decoders;
332
225
  exec.decoders = cur.advance(amount);
333
226
  }
334
227
 
335
228
  /// @notice Take a raw byte range from an execution decoder lane.
336
229
  /// @dev No block header or schema is validated.
337
- /// @param exec Execution whose selected decoder cursor is advanced.
338
- /// @param lane Decoder lane to select.
230
+ /// @param exec Execution whose active decoder cursor is advanced.
339
231
  /// @param amount Number of bytes to take.
340
232
  /// @return abs Absolute position of the first taken byte.
341
- function take(Execution memory exec, uint8 lane, uint amount) internal pure returns (uint abs) {
342
- (exec.decoders, abs) = exec.decoders.consume(lane, amount);
233
+ function take(Execution memory exec, uint amount) internal pure returns (uint abs) {
234
+ (exec.decoders, abs) = exec.decoders.consume(amount);
343
235
  }
344
236
 
345
237
  /// @notice Require the active execution decoder to be at absolute position `abs`.
346
- /// @dev The most recent lane-aware decoder operation determines the active lane.
238
+ /// @dev `oninput()` and `onstate()` determine the active lane.
347
239
  /// @param exec Execution whose active decoder position is validated.
348
240
  /// @param abs Expected absolute position.
349
241
  function expectAbs(Execution memory exec, uint abs) internal pure {
@@ -352,19 +244,17 @@ library Executions {
352
244
 
353
245
  /// @notice Consume a LIST block and return a cursor scoped to its payload.
354
246
  /// @param exec Execution whose decoder is advanced.
355
- /// @param lane Decoder lane containing the LIST block.
356
247
  /// @return items Cursor over the nested list items.
357
- function list(Execution memory exec, uint8 lane) internal pure returns (Cur memory items) {
358
- return list(exec, Specs.List, lane);
248
+ function list(Execution memory exec) internal pure returns (Cur memory items) {
249
+ return list(exec, Specs.List);
359
250
  }
360
251
 
361
252
  /// @notice Consume a list block described by `spec` and return a cursor scoped to its payload.
362
253
  /// @param exec Execution whose decoder is advanced.
363
254
  /// @param spec Custom list block specification.
364
- /// @param lane Decoder lane containing the list block.
365
255
  /// @return items Cursor over the nested list items.
366
- function list(Execution memory exec, uint spec, uint8 lane) internal pure returns (Cur memory items) {
367
- (uint abs, uint end) = consume(exec, lane, spec);
256
+ function list(Execution memory exec, uint spec) internal pure returns (Cur memory items) {
257
+ (uint abs, uint end) = consume(exec, spec);
368
258
  items.state = Cursors.create(abs, end - abs, 0, 0, 0);
369
259
  }
370
260
 
@@ -372,400 +262,350 @@ library Executions {
372
262
  // Fixed-width block decoding
373
263
  // -------------------------------------------------------------------------
374
264
 
375
- /// @dev Return the next raw calldata word from `lane` and advance by `size` bytes.
376
- function next(Execution memory exec, uint8 lane, uint size) private pure returns (bytes32 value) {
377
- value = Blocks.read32(take(exec, lane, size));
265
+ /// @dev Return the next raw calldata word from the active lane and advance by `size` bytes.
266
+ function next(Execution memory exec, uint size) private pure returns (bytes32 value) {
267
+ value = Blocks.read32(take(exec, size));
378
268
  }
379
269
 
380
270
  /// @notice Return the next raw byte from a decoder lane and advance it by one byte.
381
- function next1(Execution memory exec, uint8 lane) internal pure returns (bytes1 value) {
382
- value = bytes1(next(exec, lane, 1));
271
+ function next1(Execution memory exec) internal pure returns (bytes1 value) {
272
+ value = bytes1(next(exec, 1));
383
273
  }
384
274
 
385
275
  /// @notice Return the next two raw bytes from a decoder lane and advance it by two bytes.
386
- function next2(Execution memory exec, uint8 lane) internal pure returns (bytes2 value) {
387
- value = bytes2(next(exec, lane, 2));
276
+ function next2(Execution memory exec) internal pure returns (bytes2 value) {
277
+ value = bytes2(next(exec, 2));
388
278
  }
389
279
 
390
280
  /// @notice Return the next four raw bytes from a decoder lane and advance it by four bytes.
391
- function next4(Execution memory exec, uint8 lane) internal pure returns (bytes4 value) {
392
- value = bytes4(next(exec, lane, 4));
281
+ function next4(Execution memory exec) internal pure returns (bytes4 value) {
282
+ value = bytes4(next(exec, 4));
393
283
  }
394
284
 
395
285
  /// @notice Return the next eight raw bytes from a decoder lane and advance it by eight bytes.
396
- function next8(Execution memory exec, uint8 lane) internal pure returns (bytes8 value) {
397
- value = bytes8(next(exec, lane, 8));
286
+ function next8(Execution memory exec) internal pure returns (bytes8 value) {
287
+ value = bytes8(next(exec, 8));
398
288
  }
399
289
 
400
290
  /// @notice Return the next sixteen raw bytes from a decoder lane and advance it by sixteen bytes.
401
- function next16(Execution memory exec, uint8 lane) internal pure returns (bytes16 value) {
402
- value = bytes16(next(exec, lane, 16));
291
+ function next16(Execution memory exec) internal pure returns (bytes16 value) {
292
+ value = bytes16(next(exec, 16));
403
293
  }
404
294
 
405
295
  /// @notice Return the next raw calldata word from a decoder lane and advance it.
406
- /// @param exec Execution whose selected decoder cursor advances by one word.
407
- /// @param lane Execution decoder lane to select.
408
- /// @return value Raw word at the selected lane's previous position.
409
- function next32(Execution memory exec, uint8 lane) internal pure returns (bytes32 value) {
410
- value = next(exec, lane, Sizes.Word);
296
+ /// @param exec Execution whose active decoder cursor advances by one word.
297
+ /// @return value Raw word at the active lane's previous position.
298
+ function next32(Execution memory exec) internal pure returns (bytes32 value) {
299
+ value = next(exec, Sizes.Word);
411
300
  }
412
301
 
413
- /// @notice Decode one fixed 32-byte payload from `lane`.
302
+ /// @notice Decode one fixed 32-byte payload from the active lane.
414
303
  /// @param exec Execution whose decoder is advanced.
415
- /// @param lane Decoder lane to consume.
416
304
  /// @param spec Expected fixed block specification.
417
305
  /// @return value Decoded payload word.
418
- function unpack32(Execution memory exec, uint8 lane, uint spec) internal pure returns (bytes32 value) {
306
+ function unpack32(Execution memory exec, uint spec) internal pure returns (bytes32 value) {
419
307
  uint abs;
420
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B32);
308
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B32);
421
309
  if (Blocks.header(abs, Specs.key(spec)) != 32) revert Blocks.InvalidBlock();
422
310
  assembly ("memory-safe") {
423
311
  value := calldataload(add(abs, 0x08))
424
312
  }
425
313
  }
426
314
 
427
- /// @notice Decode and consume one ACCOUNT block from `lane`.
315
+ /// @notice Decode and consume one ACCOUNT block from the active lane.
428
316
  /// @param exec Execution whose decoder is advanced.
429
- /// @param lane Decoder lane to consume.
430
317
  /// @return account Decoded account identifier.
431
- function unpackAccount(Execution memory exec, uint8 lane) internal pure returns (bytes32 account) {
318
+ function unpackAccount(Execution memory exec) internal pure returns (bytes32 account) {
432
319
  uint abs;
433
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B32);
320
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B32);
434
321
  account = Blocks.unpackAccount(abs);
435
322
  }
436
323
 
437
- /// @notice Decode and consume one NODE block from `lane`.
324
+ /// @notice Decode and consume one NODE block from the active lane.
438
325
  /// @param exec Execution whose decoder is advanced.
439
- /// @param lane Decoder lane to consume.
440
326
  /// @return node Decoded node identifier.
441
- function unpackNode(Execution memory exec, uint8 lane) internal pure returns (uint node) {
327
+ function unpackNode(Execution memory exec) internal pure returns (uint node) {
442
328
  uint abs;
443
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B32);
329
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B32);
444
330
  node = Blocks.unpackNode(abs);
445
331
  }
446
332
 
447
- /// @notice Decode and consume one ASSET block from `lane`.
333
+ /// @notice Decode and consume one CASHOUT block from the active lane.
334
+ /// @param exec Execution whose decoder is advanced.
335
+ /// @return amount Native-asset amount to withdraw.
336
+ function unpackCashout(Execution memory exec) internal pure returns (uint amount) {
337
+ uint abs;
338
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.Cashout);
339
+ amount = Blocks.unpackCashout(abs);
340
+ }
341
+
342
+ /// @notice Decode and consume one BOOTSTRAP block from the active lane.
343
+ /// @param exec Execution whose decoder is advanced.
344
+ /// @return asset Decoded asset identifier.
345
+ /// @return amount Decoded balance amount.
346
+ /// @return budget Decoded native-value budget contribution.
347
+ function unpackBootstrap(
348
+ Execution memory exec
349
+ ) internal pure returns (bytes32 asset, uint amount, uint budget) {
350
+ uint abs;
351
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.Bootstrap);
352
+ return Blocks.unpackBootstrap(abs);
353
+ }
354
+
355
+ /// @notice Decode and consume one ASSET block from the active lane.
448
356
  /// @param exec Execution whose decoder is advanced.
449
- /// @param lane Decoder lane to consume.
450
357
  /// @return asset Decoded asset identifier.
451
- function unpackAsset(Execution memory exec, uint8 lane) internal pure returns (bytes32 asset) {
358
+ function unpackAsset(Execution memory exec) internal pure returns (bytes32 asset) {
452
359
  uint abs;
453
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B32);
360
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B32);
454
361
  asset = Blocks.unpackAsset(abs);
455
362
  }
456
363
 
457
- /// @notice Decode and consume one ACCOUNT_ASSET block from `lane`.
364
+ /// @notice Decode and consume one ACCOUNT_ASSET block from the active lane.
458
365
  /// @param exec Execution whose decoder is advanced.
459
- /// @param lane Decoder lane to consume.
460
366
  /// @return account Decoded account identifier.
461
367
  /// @return asset Decoded asset identifier.
462
- function unpackAccountAsset(
463
- Execution memory exec,
464
- uint8 lane
465
- ) internal pure returns (bytes32 account, bytes32 asset) {
368
+ function unpackAccountAsset(Execution memory exec) internal pure returns (bytes32 account, bytes32 asset) {
466
369
  uint abs;
467
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B64);
370
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B64);
468
371
  (account, asset) = Blocks.unpackAccountAsset(abs);
469
372
  }
470
373
 
471
374
  /// @notice Decode one ACCOUNT_ASSET block into its structured value.
472
375
  /// @param exec Execution whose decoder is advanced.
473
- /// @param lane Decoder lane to consume.
474
376
  /// @return value Decoded account and asset.
475
- function unpackAccountAssetValue(
476
- Execution memory exec,
477
- uint8 lane
478
- ) internal pure returns (AccountAsset memory value) {
479
- (value.account, value.asset) = unpackAccountAsset(exec, lane);
377
+ function unpackAccountAssetValue(Execution memory exec) internal pure returns (AccountAsset memory value) {
378
+ (value.account, value.asset) = unpackAccountAsset(exec);
480
379
  }
481
380
 
482
- /// @notice Decode and consume one HOST_ASSET block from `lane`.
381
+ /// @notice Decode and consume one HOST_ASSET block from the active lane.
483
382
  /// @param exec Execution whose decoder is advanced.
484
- /// @param lane Decoder lane to consume.
485
383
  /// @return host Decoded host identifier.
486
384
  /// @return asset Decoded asset identifier.
487
- function unpackHostAsset(
488
- Execution memory exec,
489
- uint8 lane
490
- ) internal pure returns (uint host, bytes32 asset) {
385
+ function unpackHostAsset(Execution memory exec) internal pure returns (uint host, bytes32 asset) {
491
386
  uint abs;
492
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.HostAsset);
387
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.HostAsset);
493
388
  (host, asset) = Blocks.unpackHostAsset(abs);
494
389
  }
495
390
 
496
391
  /// @notice Decode one HOST_ASSET block into its structured value.
497
392
  /// @param exec Execution whose decoder is advanced.
498
- /// @param lane Decoder lane to consume.
499
393
  /// @return value Decoded host and asset.
500
- function unpackHostAssetValue(
501
- Execution memory exec,
502
- uint8 lane
503
- ) internal pure returns (HostAsset memory value) {
504
- (value.host, value.asset) = unpackHostAsset(exec, lane);
394
+ function unpackHostAssetValue(Execution memory exec) internal pure returns (HostAsset memory value) {
395
+ (value.host, value.asset) = unpackHostAsset(exec);
505
396
  }
506
397
 
507
- /// @notice Decode and consume one AMOUNT block from `lane`.
398
+ /// @notice Decode and consume one AMOUNT block from the active lane.
508
399
  /// @param exec Execution whose decoder is advanced.
509
- /// @param lane Decoder lane to consume.
510
400
  /// @return asset Decoded asset identifier.
511
401
  /// @return amount Decoded amount.
512
- function unpackAmount(Execution memory exec, uint8 lane) internal pure returns (bytes32 asset, uint amount) {
402
+ function unpackAmount(Execution memory exec) internal pure returns (bytes32 asset, uint amount) {
513
403
  uint abs;
514
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Amount);
404
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.Amount);
515
405
  (asset, amount) = Blocks.unpackAmount(abs);
516
406
  }
517
407
 
518
408
  /// @notice Decode one AMOUNT block into its structured value.
519
409
  /// @param exec Execution whose decoder is advanced.
520
- /// @param lane Decoder lane to consume.
521
410
  /// @return value Decoded asset and amount.
522
- function unpackAmountValue(Execution memory exec, uint8 lane) internal pure returns (AssetAmount memory value) {
523
- (value.asset, value.amount) = unpackAmount(exec, lane);
411
+ function unpackAmountValue(Execution memory exec) internal pure returns (AssetAmount memory value) {
412
+ (value.asset, value.amount) = unpackAmount(exec);
524
413
  }
525
414
 
526
- /// @notice Decode and consume one BALANCE block from `lane`.
415
+ /// @notice Decode and consume one BALANCE block from the active lane.
527
416
  /// @param exec Execution whose decoder is advanced.
528
- /// @param lane Decoder lane to consume.
529
417
  /// @return asset Decoded asset identifier.
530
418
  /// @return amount Decoded balance amount.
531
- function unpackBalance(Execution memory exec, uint8 lane) internal pure returns (bytes32 asset, uint amount) {
419
+ function unpackBalance(Execution memory exec) internal pure returns (bytes32 asset, uint amount) {
532
420
  uint abs;
533
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Balance);
421
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.Balance);
534
422
  (asset, amount) = Blocks.unpackBalance(abs);
535
423
  }
536
424
 
537
425
  /// @notice Decode one BALANCE block into its structured value.
538
426
  /// @param exec Execution whose decoder is advanced.
539
- /// @param lane Decoder lane to consume.
540
427
  /// @return value Decoded asset and balance amount.
541
- function unpackBalanceValue(Execution memory exec, uint8 lane) internal pure returns (AssetAmount memory value) {
542
- (value.asset, value.amount) = unpackBalance(exec, lane);
428
+ function unpackBalanceValue(Execution memory exec) internal pure returns (AssetAmount memory value) {
429
+ (value.asset, value.amount) = unpackBalance(exec);
543
430
  }
544
431
 
545
- /// @notice Decode and consume one DEBT block from `lane`.
546
- function unpackDebt(Execution memory exec, uint8 lane) internal pure returns (bytes32 liability, uint debt) {
432
+ /// @notice Decode and consume one DEBT block from the active lane.
433
+ function unpackDebt(Execution memory exec) internal pure returns (bytes32 liability, uint debt) {
547
434
  uint abs;
548
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Debt);
435
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.Debt);
549
436
  (liability, debt) = Blocks.unpackDebt(abs);
550
437
  }
551
438
 
552
439
  /// @notice Decode one DEBT block into its structured value.
553
- function unpackDebtValue(Execution memory exec, uint8 lane) internal pure returns (Debt memory value) {
554
- (value.liability, value.debt) = unpackDebt(exec, lane);
440
+ function unpackDebtValue(Execution memory exec) internal pure returns (Debt memory value) {
441
+ (value.liability, value.debt) = unpackDebt(exec);
555
442
  }
556
443
 
557
- /// @notice Decode and consume one POSITION block from `lane`.
558
- function unpackPosition(
559
- Execution memory exec,
560
- uint8 lane
561
- ) internal pure returns (bytes32 asset, uint amount, bytes32 liability, uint debt) {
444
+ /// @notice Decode and consume one POSITION block from the active lane.
445
+ function unpackPosition(Execution memory exec) internal pure returns (bytes32 asset, uint amount, bytes32 liability, uint debt) {
562
446
  uint abs;
563
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Position);
447
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.Position);
564
448
  (asset, amount, liability, debt) = Blocks.unpackPosition(abs);
565
449
  }
566
450
 
567
451
  /// @notice Decode one POSITION block into its structured value.
568
- function unpackPositionValue(
569
- Execution memory exec,
570
- uint8 lane
571
- ) internal pure returns (Position memory value) {
572
- (value.asset, value.amount, value.liability, value.debt) = unpackPosition(exec, lane);
452
+ function unpackPositionValue(Execution memory exec) internal pure returns (Position memory value) {
453
+ (value.asset, value.amount, value.liability, value.debt) = unpackPosition(exec);
573
454
  }
574
455
 
575
456
  /// @notice Decode one BALANCE block and associate it with `host`.
576
457
  /// @param exec Execution whose decoder is advanced.
577
- /// @param lane Decoder lane to consume.
578
458
  /// @param host Host associated with the decoded balance.
579
459
  /// @return value Host-scoped asset amount.
580
460
  function unpackBalanceForHost(
581
461
  Execution memory exec,
582
- uint8 lane,
583
462
  uint host
584
463
  ) internal pure returns (HostAmount memory value) {
585
464
  uint abs;
586
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Balance);
465
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.Balance);
587
466
  value.host = host;
588
467
  (value.asset, value.amount) = Blocks.unpackBalance(abs);
589
468
  }
590
469
 
591
- /// @notice Decode and consume one ACCOUNT_AMOUNT block from `lane`.
470
+ /// @notice Decode and consume one ACCOUNT_AMOUNT block from the active lane.
592
471
  /// @param exec Execution whose decoder is advanced.
593
- /// @param lane Decoder lane to consume.
594
472
  /// @return account Decoded account identifier.
595
473
  /// @return asset Decoded asset identifier.
596
474
  /// @return amount Decoded amount.
597
- function unpackAccountAmount(
598
- Execution memory exec,
599
- uint8 lane
600
- ) internal pure returns (bytes32 account, bytes32 asset, uint amount) {
475
+ function unpackAccountAmount(Execution memory exec) internal pure returns (bytes32 account, bytes32 asset, uint amount) {
601
476
  uint abs;
602
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B96);
477
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B96);
603
478
  (account, asset, amount) = Blocks.unpackAccountAmount(abs);
604
479
  }
605
480
 
606
481
  /// @notice Decode one ACCOUNT_AMOUNT block into its structured value.
607
482
  /// @param exec Execution whose decoder is advanced.
608
- /// @param lane Decoder lane to consume.
609
483
  /// @return value Decoded account, asset, and amount.
610
- function unpackAccountAmountValue(
611
- Execution memory exec,
612
- uint8 lane
613
- ) internal pure returns (AccountAmount memory value) {
614
- (value.account, value.asset, value.amount) = unpackAccountAmount(exec, lane);
484
+ function unpackAccountAmountValue(Execution memory exec) internal pure returns (AccountAmount memory value) {
485
+ (value.account, value.asset, value.amount) = unpackAccountAmount(exec);
615
486
  }
616
487
 
617
- /// @notice Decode and consume one ALLOCATION block from `lane`.
488
+ /// @notice Decode and consume one ALLOCATION block from the active lane.
618
489
  /// @param exec Execution whose decoder is advanced.
619
- /// @param lane Decoder lane to consume.
620
490
  /// @return host Decoded host identifier.
621
491
  /// @return asset Decoded asset identifier.
622
492
  /// @return amount Decoded amount.
623
- function unpackAllocation(
624
- Execution memory exec,
625
- uint8 lane
626
- ) internal pure returns (uint host, bytes32 asset, uint amount) {
493
+ function unpackAllocation(Execution memory exec) internal pure returns (uint host, bytes32 asset, uint amount) {
627
494
  uint abs;
628
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B96);
495
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B96);
629
496
  (host, asset, amount) = Blocks.unpackAllocation(abs);
630
497
  }
631
498
 
632
499
  /// @notice Decode one ALLOCATION block into its structured value.
633
500
  /// @param exec Execution whose decoder is advanced.
634
- /// @param lane Decoder lane to consume.
635
501
  /// @return value Decoded host, asset, and amount.
636
- function unpackAllocationValue(Execution memory exec, uint8 lane) internal pure returns (HostAmount memory value) {
637
- (value.host, value.asset, value.amount) = unpackAllocation(exec, lane);
502
+ function unpackAllocationValue(Execution memory exec) internal pure returns (HostAmount memory value) {
503
+ (value.host, value.asset, value.amount) = unpackAllocation(exec);
638
504
  }
639
505
 
640
- /// @notice Decode and consume one ALLOWANCE block from `lane`.
506
+ /// @notice Decode and consume one ALLOWANCE block from the active lane.
641
507
  /// @param exec Execution whose decoder is advanced.
642
- /// @param lane Decoder lane to consume.
643
508
  /// @return host Decoded host identifier.
644
509
  /// @return asset Decoded asset identifier.
645
510
  /// @return amount Decoded allowance amount.
646
- function unpackAllowance(
647
- Execution memory exec,
648
- uint8 lane
649
- ) internal pure returns (uint host, bytes32 asset, uint amount) {
511
+ function unpackAllowance(Execution memory exec) internal pure returns (uint host, bytes32 asset, uint amount) {
650
512
  uint abs;
651
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B96);
513
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B96);
652
514
  (host, asset, amount) = Blocks.unpackAllowance(abs);
653
515
  }
654
516
 
655
517
  /// @notice Decode one ALLOWANCE block into its structured value.
656
518
  /// @param exec Execution whose decoder is advanced.
657
- /// @param lane Decoder lane to consume.
658
519
  /// @return value Decoded host, asset, and allowance amount.
659
- function unpackAllowanceValue(Execution memory exec, uint8 lane) internal pure returns (HostAmount memory value) {
660
- (value.host, value.asset, value.amount) = unpackAllowance(exec, lane);
520
+ function unpackAllowanceValue(Execution memory exec) internal pure returns (HostAmount memory value) {
521
+ (value.host, value.asset, value.amount) = unpackAllowance(exec);
661
522
  }
662
523
 
663
- /// @notice Decode and consume one CUSTODY block from `lane`.
524
+ /// @notice Decode and consume one CUSTODY block from the active lane.
664
525
  /// @param exec Execution whose decoder is advanced.
665
- /// @param lane Decoder lane to consume.
666
526
  /// @return host Decoded host identifier.
667
527
  /// @return asset Decoded asset identifier.
668
528
  /// @return amount Decoded custody amount.
669
- function unpackCustody(
670
- Execution memory exec,
671
- uint8 lane
672
- ) internal pure returns (uint host, bytes32 asset, uint amount) {
529
+ function unpackCustody(Execution memory exec) internal pure returns (uint host, bytes32 asset, uint amount) {
673
530
  uint abs;
674
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B96);
531
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B96);
675
532
  (host, asset, amount) = Blocks.unpackCustody(abs);
676
533
  }
677
534
 
678
535
  /// @notice Decode one CUSTODY block into its structured value.
679
536
  /// @param exec Execution whose decoder is advanced.
680
- /// @param lane Decoder lane to consume.
681
537
  /// @return value Decoded host, asset, and custody amount.
682
- function unpackCustodyValue(Execution memory exec, uint8 lane) internal pure returns (HostAmount memory value) {
683
- (value.host, value.asset, value.amount) = unpackCustody(exec, lane);
538
+ function unpackCustodyValue(Execution memory exec) internal pure returns (HostAmount memory value) {
539
+ (value.host, value.asset, value.amount) = unpackCustody(exec);
684
540
  }
685
541
 
686
- /// @notice Decode and consume one HOST_ACCOUNT_ASSET block from `lane`.
542
+ /// @notice Decode and consume one HOST_ACCOUNT_ASSET block from the active lane.
687
543
  /// @param exec Execution whose decoder is advanced.
688
- /// @param lane Decoder lane to consume.
689
544
  /// @return host Decoded host identifier.
690
545
  /// @return account Decoded account identifier.
691
546
  /// @return asset Decoded asset identifier.
692
- function unpackHostAccountAsset(
693
- Execution memory exec,
694
- uint8 lane
695
- ) internal pure returns (uint host, bytes32 account, bytes32 asset) {
547
+ function unpackHostAccountAsset(Execution memory exec) internal pure returns (uint host, bytes32 account, bytes32 asset) {
696
548
  uint abs;
697
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.B96);
549
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.B96);
698
550
  (host, account, asset) = Blocks.unpackHostAccountAsset(abs);
699
551
  }
700
552
 
701
553
  /// @notice Decode one HOST_ACCOUNT_ASSET block into its structured value.
702
554
  /// @param exec Execution whose decoder is advanced.
703
- /// @param lane Decoder lane to consume.
704
555
  /// @return value Decoded host, account, and asset.
705
- function unpackHostAccountAssetValue(
706
- Execution memory exec,
707
- uint8 lane
708
- ) internal pure returns (HostAccountAsset memory value) {
709
- (value.host, value.account, value.asset) = unpackHostAccountAsset(exec, lane);
556
+ function unpackHostAccountAssetValue(Execution memory exec) internal pure returns (HostAccountAsset memory value) {
557
+ (value.host, value.account, value.asset) = unpackHostAccountAsset(exec);
710
558
  }
711
559
 
712
- /// @notice Decode and consume one TRANSACTION block from `lane`.
560
+ /// @notice Decode and consume one TRANSACTION block from the active lane.
713
561
  /// @param exec Execution whose decoder is advanced.
714
- /// @param lane Decoder lane to consume.
715
562
  /// @return from Decoded debit account.
716
563
  /// @return to Decoded credit account.
717
564
  /// @return asset Decoded asset identifier.
718
565
  /// @return amount Decoded transaction amount.
719
- function unpackTransaction(
720
- Execution memory exec,
721
- uint8 lane
722
- ) internal pure returns (bytes32 from, bytes32 to, bytes32 asset, uint amount) {
566
+ function unpackTransaction(Execution memory exec) internal pure returns (bytes32 from, bytes32 to, bytes32 asset, uint amount) {
723
567
  uint abs;
724
- (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Transaction);
568
+ (exec.decoders, abs) = exec.decoders.consume(Sizes.Transaction);
725
569
  (from, to, asset, amount) = Blocks.unpackTransaction(abs);
726
570
  }
727
571
 
728
572
  /// @notice Decode one TRANSACTION block into its structured value.
729
573
  /// @param exec Execution whose decoder is advanced.
730
- /// @param lane Decoder lane to consume.
731
574
  /// @return value Decoded transaction.
732
- function unpackTransactionValue(Execution memory exec, uint8 lane) internal pure returns (Tx memory value) {
733
- (value.from, value.to, value.asset, value.amount) = unpackTransaction(exec, lane);
575
+ function unpackTransactionValue(Execution memory exec) internal pure returns (Tx memory value) {
576
+ (value.from, value.to, value.asset, value.amount) = unpackTransaction(exec);
734
577
  }
735
578
 
736
579
  // -------------------------------------------------------------------------
737
580
  // Dynamic block decoding
738
581
  // -------------------------------------------------------------------------
739
582
 
740
- /// @notice Decode and consume a block described by `spec` from `lane`.
583
+ /// @notice Decode and consume a block described by `spec` from the active lane.
741
584
  /// @param exec Execution whose decoder is advanced.
742
- /// @param lane Decoder lane to consume.
743
585
  /// @param spec Expected block specification.
744
586
  /// @return data Calldata view of the decoded payload.
745
- function unpackRaw(Execution memory exec, uint8 lane, uint spec) internal pure returns (bytes calldata data) {
746
- uint cur = exec.decoders.select(lane);
587
+ function unpackRaw(Execution memory exec, uint spec) internal pure returns (bytes calldata data) {
588
+ uint cur = exec.decoders;
747
589
  uint end;
748
590
  (data, end) = Blocks.unpackRaw(cur.absolute(), spec);
749
591
  exec.decoders = cur.seekAbs(end);
750
592
  }
751
593
 
752
- /// @notice Decode and consume one BYTES block from `lane`.
594
+ /// @notice Decode and consume one BYTES block from the active lane.
753
595
  /// @param exec Execution whose decoder is advanced.
754
- /// @param lane Decoder lane to consume.
755
596
  /// @return data Decoded byte payload.
756
- function unpackBytes(Execution memory exec, uint8 lane) internal pure returns (bytes calldata data) {
757
- uint cur = exec.decoders.select(lane);
597
+ function unpackBytes(Execution memory exec) internal pure returns (bytes calldata data) {
598
+ uint cur = exec.decoders;
758
599
  uint end;
759
600
  (data, end) = Blocks.unpackBytes(cur.absolute());
760
601
  exec.decoders = cur.seekAbs(end);
761
602
  }
762
603
 
763
- /// @notice Decode and consume one STRING block from `lane`.
604
+ /// @notice Decode and consume one STRING block from the active lane.
764
605
  /// @param exec Execution whose decoder is advanced.
765
- /// @param lane Decoder lane to consume.
766
606
  /// @return data Decoded string payload.
767
- function unpackString(Execution memory exec, uint8 lane) internal pure returns (string memory data) {
768
- uint cur = exec.decoders.select(lane);
607
+ function unpackString(Execution memory exec) internal pure returns (string memory data) {
608
+ uint cur = exec.decoders;
769
609
  bytes calldata value;
770
610
  uint end;
771
611
  (value, end) = Blocks.unpackString(cur.absolute());
@@ -773,149 +613,113 @@ library Executions {
773
613
  data = string(value);
774
614
  }
775
615
 
776
- /// @notice Decode and consume one STEP block from `lane`.
616
+ /// @notice Decode and consume one STEP block from the active lane.
777
617
  /// @param exec Execution whose decoder is advanced.
778
- /// @param lane Decoder lane to consume.
779
618
  /// @return cmd Decoded command identifier.
780
- /// @return resources Decoded packed resources.
619
+ /// @return value Decoded native value.
781
620
  /// @return input Decoded nested input.
782
- function unpackStep(
783
- Execution memory exec,
784
- uint8 lane
785
- ) internal pure returns (uint cmd, uint resources, bytes calldata input) {
786
- uint cur = exec.decoders.select(lane);
621
+ function unpackStep(Execution memory exec) internal pure returns (uint cmd, uint128 value, bytes calldata input) {
622
+ uint cur = exec.decoders;
787
623
  uint end;
788
- (cmd, resources, input, end) = Blocks.unpackStep(cur.absolute());
624
+ (cmd, value, input, end) = Blocks.unpackStep(cur.absolute());
789
625
  exec.decoders = cur.seekAbs(end);
790
626
  }
791
627
 
792
- /// @notice Decode and consume one CALL block from `lane`.
628
+ /// @notice Decode and consume one CALL block from the active lane.
793
629
  /// @param exec Execution whose decoder is advanced.
794
- /// @param lane Decoder lane to consume.
795
630
  /// @return target Decoded call target.
796
631
  /// @return resources Decoded packed resources.
797
632
  /// @return data Decoded call payload.
798
- function unpackCall(
799
- Execution memory exec,
800
- uint8 lane
801
- ) internal pure returns (uint target, uint resources, bytes calldata data) {
802
- uint cur = exec.decoders.select(lane);
633
+ function unpackCall(Execution memory exec) internal pure returns (uint target, uint resources, bytes calldata data) {
634
+ uint cur = exec.decoders;
803
635
  uint abs = cur.absolute();
804
636
  uint end;
805
637
  (target, resources, data, end) = Blocks.unpackCall(abs);
806
638
  exec.decoders = cur.seekAbs(end);
807
639
  }
808
640
 
809
- /// @notice Decode and consume one ANNOTATION block from `lane`.
641
+ /// @notice Decode and consume one ANNOTATION block from the active lane.
810
642
  /// @param exec Execution whose decoder is advanced.
811
- /// @param lane Decoder lane to consume.
812
643
  /// @return entity Decoded entity identifier.
813
644
  /// @return data Decoded annotation block stream.
814
- function unpackAnnotation(
815
- Execution memory exec,
816
- uint8 lane
817
- ) internal pure returns (uint entity, bytes calldata data) {
818
- uint cur = exec.decoders.select(lane);
645
+ function unpackAnnotation(Execution memory exec) internal pure returns (uint entity, bytes calldata data) {
646
+ uint cur = exec.decoders;
819
647
  uint end;
820
648
  (entity, data, end) = Blocks.unpackAnnotation(cur.absolute());
821
649
  exec.decoders = cur.seekAbs(end);
822
650
  }
823
651
 
824
- /// @notice Decode and consume one CONTEXT block from `lane`.
652
+ /// @notice Decode and consume one CONTEXT block from the active lane.
825
653
  /// @param exec Execution whose decoder is advanced.
826
- /// @param lane Decoder lane to consume.
827
654
  /// @return account Decoded account identifier.
828
655
  /// @return state Decoded nested state.
829
656
  /// @return input Decoded nested input.
830
- function unpackContext(
831
- Execution memory exec,
832
- uint8 lane
833
- ) internal pure returns (bytes32 account, bytes calldata state, bytes calldata input) {
834
- uint cur = exec.decoders.select(lane);
657
+ function unpackContext(Execution memory exec) internal pure returns (bytes32 account, bytes calldata state, bytes calldata input) {
658
+ uint cur = exec.decoders;
835
659
  uint abs = cur.absolute();
836
660
  uint end;
837
661
  (account, state, input, end) = Blocks.unpackContext(abs);
838
662
  exec.decoders = cur.seekAbs(end);
839
663
  }
840
664
 
841
- /// @notice Decode and consume one RELAY block from `lane`.
665
+ /// @notice Decode and consume one RELAY block from the active lane.
842
666
  /// @param exec Execution whose decoder is advanced.
843
- /// @param lane Decoder lane to consume.
844
667
  /// @return portal Decoded destination portal.
845
668
  /// @return resources Decoded packed resources.
846
669
  /// @return input Decoded nested input.
847
- function unpackRelay(
848
- Execution memory exec,
849
- uint8 lane
850
- ) internal pure returns (uint portal, uint resources, bytes calldata input) {
851
- uint cur = exec.decoders.select(lane);
670
+ function unpackRelay(Execution memory exec) internal pure returns (uint portal, uint resources, bytes calldata input) {
671
+ uint cur = exec.decoders;
852
672
  uint end;
853
673
  (portal, resources, input, end) = Blocks.unpackRelay(cur.absolute());
854
674
  exec.decoders = cur.seekAbs(end);
855
675
  }
856
676
 
857
- /// @notice Decode and consume one DISPATCH block from `lane`.
677
+ /// @notice Decode and consume one DISPATCH block from the active lane.
858
678
  /// @param exec Execution whose decoder is advanced.
859
- /// @param lane Decoder lane to consume.
860
679
  /// @return portal Decoded destination portal.
861
680
  /// @return resources Decoded packed resources.
862
681
  /// @return payload Decoded dispatch payload.
863
- function unpackDispatch(
864
- Execution memory exec,
865
- uint8 lane
866
- ) internal pure returns (uint portal, uint resources, bytes calldata payload) {
867
- uint cur = exec.decoders.select(lane);
682
+ function unpackDispatch(Execution memory exec) internal pure returns (uint portal, uint resources, bytes calldata payload) {
683
+ uint cur = exec.decoders;
868
684
  uint abs = cur.absolute();
869
685
  uint end;
870
686
  (portal, resources, payload, end) = Blocks.unpackDispatch(abs);
871
687
  exec.decoders = cur.seekAbs(end);
872
688
  }
873
689
 
874
- /// @notice Decode and consume one LABEL block from `lane`.
690
+ /// @notice Decode and consume one LABEL block from the active lane.
875
691
  /// @param exec Execution whose decoder is advanced.
876
- /// @param lane Decoder lane to consume.
877
692
  /// @return namespace Decoded label namespace.
878
693
  /// @return name Decoded label text.
879
- function unpackLabel(
880
- Execution memory exec,
881
- uint8 lane
882
- ) internal pure returns (bytes32 namespace, string memory name) {
883
- uint cur = exec.decoders.select(lane);
694
+ function unpackLabel(Execution memory exec) internal pure returns (bytes32 namespace, string memory name) {
695
+ uint cur = exec.decoders;
884
696
  uint abs = cur.absolute();
885
697
  uint end;
886
698
  (namespace, name, end) = Blocks.unpackLabel(abs);
887
699
  exec.decoders = cur.seekAbs(end);
888
700
  }
889
701
 
890
- /// @notice Decode and consume one SCHEMA block from `lane`.
702
+ /// @notice Decode and consume one SCHEMA block from the active lane.
891
703
  /// @param exec Execution whose decoder is advanced.
892
- /// @param lane Decoder lane to consume.
893
704
  /// @return spec Decoded block specification.
894
705
  /// @return body Decoded schema body.
895
706
  /// @return name Decoded schema name.
896
- function unpackSchema(
897
- Execution memory exec,
898
- uint8 lane
899
- ) internal pure returns (uint spec, string memory body, bytes32 name) {
900
- uint cur = exec.decoders.select(lane);
707
+ function unpackSchema(Execution memory exec) internal pure returns (uint spec, string memory body, bytes32 name) {
708
+ uint cur = exec.decoders;
901
709
  uint abs = cur.absolute();
902
710
  uint end;
903
711
  (spec, body, name, end) = Blocks.unpackSchema(abs);
904
712
  exec.decoders = cur.seekAbs(end);
905
713
  }
906
714
 
907
- /// @notice Decode and consume one RECOVER block from `lane`.
715
+ /// @notice Decode and consume one RECOVER block from the active lane.
908
716
  /// @param exec Execution whose decoder is advanced.
909
- /// @param lane Decoder lane to consume.
910
717
  /// @return handler Decoded recovery handler.
911
718
  /// @return resources Decoded packed resources.
912
719
  /// @return key Decoded recovery key.
913
720
  /// @return witness Decoded recovery witness.
914
- function unpackRecover(
915
- Execution memory exec,
916
- uint8 lane
917
- ) internal pure returns (uint handler, uint resources, bytes32 key, bytes calldata witness) {
918
- uint cur = exec.decoders.select(lane);
721
+ function unpackRecover(Execution memory exec) internal pure returns (uint handler, uint resources, bytes32 key, bytes calldata witness) {
722
+ uint cur = exec.decoders;
919
723
  uint abs = cur.absolute();
920
724
  uint end;
921
725
  (handler, resources, key, witness, end) = Blocks.unpackRecover(abs);
@@ -932,8 +736,7 @@ library Executions {
932
736
  /// @param touch Number of bytes that must be addressable by the write.
933
737
  /// @return i Relative output offset reserved for the write.
934
738
  function reserve(Execution memory exec, uint amount, uint touch) internal pure returns (uint i) {
935
- uint writers = exec.writers.select(Lanes.Output);
936
- (exec.writers, exec.output, i) = Buffers.reserve(writers, exec.output, amount, touch);
739
+ (exec.writer, exec.output, i) = Buffers.reserve(exec.writer, exec.output, amount, touch);
937
740
  }
938
741
 
939
742
  /// @dev Reserve an exact number of output bytes.
@@ -941,7 +744,7 @@ library Executions {
941
744
  /// @param size Number of bytes to reserve and touch.
942
745
  /// @return i Relative output offset reserved for the write.
943
746
  function reserve(Execution memory exec, uint size) private pure returns (uint i) {
944
- return reserve(exec, size, size);
747
+ (exec.writer, exec.output, i) = Buffers.reserve(exec.writer, exec.output, size, size);
945
748
  }
946
749
 
947
750
  /// @notice Append an empty block to execution output.
@@ -1224,12 +1027,12 @@ library Executions {
1224
1027
  /// @notice Append a STEP block to execution output.
1225
1028
  /// @param exec Execution receiving the block.
1226
1029
  /// @param cmd Command identifier to encode.
1227
- /// @param resources Packed resources to encode.
1030
+ /// @param value Native value to encode.
1228
1031
  /// @param input Command input to encode.
1229
- function outputStep(Execution memory exec, uint cmd, uint resources, bytes memory input) internal pure {
1230
- uint size = Sizes.B64 + Sizes.Header + input.length;
1032
+ function outputStep(Execution memory exec, uint cmd, uint128 value, bytes memory input) internal pure {
1033
+ uint size = Sizes.Step + input.length;
1231
1034
  uint i = reserve(exec, size);
1232
- Blocks.writeStep(exec.output, i, cmd, resources, input);
1035
+ Blocks.writeStep(exec.output, i, cmd, value, input);
1233
1036
  }
1234
1037
 
1235
1038
  /// @notice Append a CALL block to execution output.
@@ -1361,10 +1164,10 @@ library Executions {
1361
1164
  }
1362
1165
 
1363
1166
  /// @notice Append a STEP block to execution output by copying its nested input from calldata.
1364
- function outputCopyStep(Execution memory exec, uint cmd, uint resources, bytes calldata input) internal pure {
1365
- uint size = Sizes.B64 + Sizes.Header + input.length;
1167
+ function outputCopyStep(Execution memory exec, uint cmd, uint128 value, bytes calldata input) internal pure {
1168
+ uint size = Sizes.Step + input.length;
1366
1169
  uint i = reserve(exec, size);
1367
- Blocks.copyStep(exec.output, i, cmd, resources, input);
1170
+ Blocks.copyStep(exec.output, i, cmd, value, input);
1368
1171
  }
1369
1172
 
1370
1173
  /// @notice Append a CALL block to execution output by copying its nested payload from calldata.
@@ -1414,7 +1217,7 @@ library Executions {
1414
1217
  }
1415
1218
 
1416
1219
  // -------------------------------------------------------------------------
1417
- // Value and transaction writing
1220
+ // Value
1418
1221
  // -------------------------------------------------------------------------
1419
1222
 
1420
1223
  /// @notice Remove and return the remaining execution value budget.
@@ -1452,63 +1255,6 @@ library Executions {
1452
1255
  return uint128(useValue(exec, uint128(resources)));
1453
1256
  }
1454
1257
 
1455
- /// @notice Append a deferred transaction to the transaction writer lane.
1456
- /// @param exec Execution receiving the transaction.
1457
- /// @param from Debit account identifier.
1458
- /// @param to Credit account identifier.
1459
- /// @param asset Asset identifier.
1460
- /// @param amount Transaction amount.
1461
- function queueTransaction(
1462
- Execution memory exec,
1463
- bytes32 from,
1464
- bytes32 to,
1465
- bytes32 asset,
1466
- uint amount
1467
- ) internal pure {
1468
- uint i;
1469
- uint size = Sizes.Transaction;
1470
- uint writers = exec.writers.select(Lanes.Transactions);
1471
- (exec.writers, exec.transactions, i) = Buffers.reserve(writers, exec.transactions, size, size);
1472
- Blocks.writeTransaction(exec.transactions, i, from, to, asset, amount);
1473
- }
1474
-
1475
- /// @notice Queue a transaction that debits `account`.
1476
- /// @param exec Execution receiving the transaction.
1477
- /// @param account Account to debit.
1478
- /// @param asset Asset to debit.
1479
- /// @param amount Amount to debit.
1480
- function queueDebit(Execution memory exec, bytes32 account, bytes32 asset, uint amount) internal pure {
1481
- queueTransaction(exec, account, bytes32(0), asset, amount);
1482
- }
1483
-
1484
- /// @notice Queue a transaction that credits `account`.
1485
- /// @param exec Execution receiving the transaction.
1486
- /// @param account Account to credit.
1487
- /// @param asset Asset to credit.
1488
- /// @param amount Amount to credit.
1489
- function queueCredit(Execution memory exec, bytes32 account, bytes32 asset, uint amount) internal pure {
1490
- queueTransaction(exec, bytes32(0), account, asset, amount);
1491
- }
1492
-
1493
- /// @notice Drain the remaining value budget and queue it as an account refund.
1494
- /// @dev Creates a one-transaction writer lane when the descriptor declared none.
1495
- /// @param exec Execution whose remaining budget is refunded.
1496
- /// @param account Account receiving the refund.
1497
- /// @param asset Asset identifier used for the refund transaction.
1498
- /// @return amount Value removed from the execution budget and queued for refund.
1499
- function refundValue(Execution memory exec, bytes32 account, bytes32 asset) internal pure returns (uint amount) {
1500
- amount = exec.budget;
1501
- if (amount == 0) return 0;
1502
-
1503
- exec.budget = 0;
1504
- if (!exec.writers.contains(Lanes.Transactions)) {
1505
- uint refunds = Buffers.cursor(Sizes.Transaction, 1, false, Lanes.Transactions);
1506
- exec.writers = Cursors.pair(exec.writers, refunds);
1507
- }
1508
-
1509
- queueCredit(exec, account, asset, amount);
1510
- }
1511
-
1512
1258
  // -------------------------------------------------------------------------
1513
1259
  // Finalization
1514
1260
  // -------------------------------------------------------------------------
@@ -1517,19 +1263,32 @@ library Executions {
1517
1263
  /// @param exec Execution whose output is finalized.
1518
1264
  /// @return out Trimmed output bytes.
1519
1265
  function finish(Execution memory exec) internal pure returns (bytes memory out) {
1266
+ if (exec.decoders.any()) revert UnconsumedData();
1520
1267
  if (exec.output.length == 0) return new bytes(0);
1521
1268
 
1522
- uint writers = exec.writers.select(Lanes.Output);
1523
- out = Buffers.finish(writers, exec.output);
1269
+ out = Buffers.finish(exec.writer, exec.output);
1524
1270
  }
1525
1271
 
1526
- /// @notice Finalize and return queued execution transactions.
1527
- /// @param exec Execution whose transactions are finalized.
1528
- /// @return out Trimmed transaction bytes.
1529
- function finishTransactions(Execution memory exec) internal pure returns (bytes memory out) {
1530
- if (exec.transactions.length == 0) return new bytes(0);
1272
+ /// @notice Close an execution and return its output and remaining budget.
1273
+ /// @param exec Execution whose lanes, writer, and budget are finalized.
1274
+ /// @return output Final encoded output block stream.
1275
+ /// @return credit Remaining native value to credit to the caller's budget.
1276
+ function close(Execution memory exec) internal pure returns (bytes memory output, uint credit) {
1277
+ return close(exec, 0);
1278
+ }
1531
1279
 
1532
- uint writers = exec.writers.select(Lanes.Transactions);
1533
- out = Buffers.finish(writers, exec.transactions);
1280
+ /// @notice Close an execution and combine its remaining budget with additional command credit.
1281
+ /// @param exec Execution whose lanes, writer, and budget are finalized.
1282
+ /// @param extraCredit Additional trusted credit produced by the command.
1283
+ /// @return output Final encoded output block stream.
1284
+ /// @return credit Remaining execution budget plus `extraCredit`.
1285
+ function close(
1286
+ Execution memory exec,
1287
+ uint extraCredit
1288
+ ) internal pure returns (bytes memory output, uint credit) {
1289
+ output = finish(exec);
1290
+ credit = exec.budget + extraCredit;
1291
+ exec.budget = 0;
1534
1292
  }
1293
+
1535
1294
  }