@rootzero/contracts 1.13.0 → 1.14.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 (73) hide show
  1. package/CHANGELOG.md +45 -3
  2. package/Codec.sol +21 -0
  3. package/Commands.sol +14 -0
  4. package/Core.sol +2 -3
  5. package/Endpoints.sol +1 -5
  6. package/README.md +34 -30
  7. package/Utils.sol +2 -4
  8. package/codec/Blocks.sol +1606 -0
  9. package/codec/Buffers.sol +165 -0
  10. package/codec/Decoders.sol +558 -0
  11. package/codec/Descriptors.sol +124 -0
  12. package/{blocks → codec}/Keys.sol +4 -16
  13. package/codec/Readers.sol +114 -0
  14. package/{blocks → codec}/Schema.sol +38 -80
  15. package/codec/Specs.sol +218 -0
  16. package/codec/Writers.sol +487 -0
  17. package/commands/Allocate.sol +21 -20
  18. package/commands/Base.sol +71 -37
  19. package/commands/Burn.sol +18 -13
  20. package/commands/Credit.sol +21 -20
  21. package/commands/Debit.sol +25 -28
  22. package/commands/Deposit.sol +34 -35
  23. package/commands/Payout.sol +21 -15
  24. package/commands/Provision.sol +37 -38
  25. package/commands/Recover.sol +20 -19
  26. package/commands/Relay.sol +24 -22
  27. package/commands/Withdraw.sol +15 -18
  28. package/commands/admin/AllowAssets.sol +19 -16
  29. package/commands/admin/Allowance.sol +18 -13
  30. package/commands/admin/Appoint.sol +17 -15
  31. package/commands/admin/Authorize.sol +23 -14
  32. package/commands/admin/Base.sol +1 -1
  33. package/commands/admin/DenyAssets.sol +19 -16
  34. package/commands/admin/Dismiss.sol +17 -15
  35. package/commands/admin/Execute.sol +20 -19
  36. package/commands/admin/Label.sol +17 -13
  37. package/commands/admin/Schemas.sol +18 -14
  38. package/commands/admin/Unauthorize.sol +23 -14
  39. package/core/Calls.sol +3 -11
  40. package/core/Endpoint.sol +42 -127
  41. package/core/Pipeline.sol +16 -15
  42. package/core/Types.sol +1 -1
  43. package/docs/Schema.md +35 -29
  44. package/events/Endpoint.sol +2 -2
  45. package/events/Schema.sol +5 -5
  46. package/execution/Budget.sol +40 -0
  47. package/execution/Execution.sol +1083 -0
  48. package/guards/Base.sol +8 -9
  49. package/guards/Revoke.sol +11 -9
  50. package/package.json +1 -1
  51. package/ports/AllowAssets.sol +12 -15
  52. package/ports/Allowance.sol +11 -9
  53. package/ports/Base.sol +18 -11
  54. package/ports/Credit.sol +11 -9
  55. package/ports/Debit.sol +11 -9
  56. package/ports/DenyAssets.sol +10 -13
  57. package/ports/Dispatch.sol +13 -15
  58. package/ports/Pipe.sol +14 -12
  59. package/ports/Redeem.sol +12 -9
  60. package/ports/Settle.sol +11 -9
  61. package/queries/Assets.sol +15 -15
  62. package/queries/Balances.sol +17 -17
  63. package/queries/Base.sol +11 -12
  64. package/utils/Actions.sol +1 -0
  65. package/utils/Cursors.sol +308 -0
  66. package/utils/Lanes.sol +14 -0
  67. package/utils/Selectors.sol +2 -2
  68. package/utils/Utils.sol +46 -0
  69. package/Cursors.sol +0 -16
  70. package/blocks/Cursors.sol +0 -1529
  71. package/blocks/Writers.sol +0 -1036
  72. package/core/Payable.sol +0 -53
  73. package/utils/Value.sol +0 -43
@@ -1,1036 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import {AssetAmount, AccountAmount, HostAmount, Tx} from "../core/Types.sol";
5
- import {Sizes} from "./Schema.sol";
6
- import {Keys} from "./Keys.sol";
7
- import {max32} from "../utils/Utils.sol";
8
-
9
- /// @notice Sequential block stream writer backed by a pre-allocated memory buffer.
10
- struct Writer {
11
- /// @dev Current write position: number of bytes written so far.
12
- uint i;
13
- /// @dev Logical buffer capacity in bytes; writers should not advance past this limit.
14
- uint end;
15
- /// @dev Whether append helpers may expand the backing buffer when more capacity is needed.
16
- bool growable;
17
- /// @dev Destination buffer. Physical capacity may be padded up to a full 32-byte word;
18
- /// final length is set to `i` by `finish`.
19
- bytes dst;
20
- }
21
-
22
- /// @title Hints
23
- /// @notice Initial per-block capacity estimates for growable writers.
24
- library Hints {
25
- uint constant Any = 128;
26
- uint constant Bytes = 128;
27
- uint constant String = 128;
28
- uint constant Step = 256;
29
- uint constant Call = 256;
30
- uint constant Context = 512;
31
- }
32
-
33
- /// @title Writers
34
- /// @notice Response block stream builder for the rootzero protocol.
35
- /// Allocates a fixed-size memory buffer up front and writes binary-encoded
36
- /// blocks into it sequentially. Physical allocation is rounded up to whole
37
- /// 32-byte words for scratch space, while `Writer.end` tracks the logical
38
- /// requested capacity. Call `finish` to trim the buffer to the number of
39
- /// bytes actually written and return the result.
40
- library Writers {
41
- /// @dev `append` or a `write*` function tried to write past the end of `dst`.
42
- error WriterOverflow();
43
- /// @dev `finish` called with a writer whose `i` exceeds `dst.length`.
44
- error IncompleteWriter();
45
- /// @dev An alloc function received a zero count, or `finish` found no bytes written.
46
- error EmptyRequest();
47
- /// @dev A fixed-width low-level writer received an invalid final-word keep length.
48
- error InvalidKeep();
49
-
50
- // -------------------------------------------------------------------------
51
- // Allocation helpers
52
- // -------------------------------------------------------------------------
53
-
54
- /// @notice Allocate a writer with a logical byte capacity.
55
- /// The backing buffer is rounded up to whole 32-byte words, while
56
- /// `writer.end` remains the exact logical byte capacity requested.
57
- /// @param len Number of logical bytes to pre-allocate.
58
- /// @return writer Freshly allocated writer positioned at index 0.
59
- function alloc(uint len) internal pure returns (Writer memory writer) {
60
- // Extra 32 bytes ensure mstore in write/append32 never reaches past allocated memory,
61
- // even when a sub-word packed write starts within the last 31 bytes of the logical region.
62
- uint padded = ((len + 31) & ~uint(31)) + 32;
63
- writer = Writer({i: 0, end: len, growable: false, dst: new bytes(padded)});
64
- }
65
-
66
- /// @notice Allocate a growable writer with an initial logical byte capacity.
67
- /// @param hint Initial logical byte capacity to allocate.
68
- /// @return writer Freshly allocated growable writer positioned at index 0.
69
- function dynamic(uint hint) internal pure returns (Writer memory writer) {
70
- writer = alloc(hint);
71
- writer.growable = true;
72
- }
73
-
74
- /// @notice Core allocation routine used by all counted `alloc*` helpers.
75
- /// Computes `count * blockLen` and allocates that many bytes.
76
- /// @param count Number of output blocks.
77
- /// @param blockLen Logical byte size of each output block (including 8-byte header).
78
- /// @return writer Allocated writer.
79
- function allocFromCount(uint count, uint blockLen) internal pure returns (Writer memory writer) {
80
- if (count == 0) revert EmptyRequest();
81
- writer = alloc(count * blockLen);
82
- }
83
-
84
- /// @notice Core allocation routine used by counted growable `alloc*` helpers.
85
- /// Computes `count * hint` and allocates an expandable writer with that initial capacity.
86
- /// @param count Number of output blocks.
87
- /// @param hint Initial logical byte capacity per output block.
88
- /// @return writer Allocated growable writer.
89
- function allocFromHint(uint count, uint hint) internal pure returns (Writer memory writer) {
90
- if (count == 0) revert EmptyRequest();
91
- writer = dynamic(count * hint);
92
- }
93
-
94
- /// @notice Allocate a writer sized for exactly `count` dynamic blocks with a shared payload length.
95
- /// Each block reserves `Sizes.Header + payloadLen` bytes.
96
- /// @param count Number of blocks to allocate space for.
97
- /// @param payloadLen Payload byte length for each block.
98
- /// @return writer Allocated writer.
99
- function allocBytes(uint count, uint payloadLen) internal pure returns (Writer memory writer) {
100
- return allocFromCount(count, Sizes.Header + payloadLen);
101
- }
102
-
103
- /// @notice Allocate a writer for `count` variable-sized blocks using a per-block capacity hint.
104
- /// @dev The backing buffer expands automatically if encoded blocks exceed the initial hint.
105
- /// @param count Number of blocks to allocate space for.
106
- /// @return writer Allocated growable writer.
107
- function allocAny(uint count) internal pure returns (Writer memory writer) {
108
- return allocFromHint(count, Hints.Any);
109
- }
110
-
111
- /// @notice Allocate a writer for `count` BYTES blocks using a per-block capacity hint.
112
- /// @dev The backing buffer expands automatically if encoded bytes blocks exceed the initial hint.
113
- /// @param count Number of bytes blocks to allocate space for.
114
- /// @return writer Allocated growable writer.
115
- function allocBytes(uint count) internal pure returns (Writer memory writer) {
116
- return allocFromHint(count, Hints.Bytes);
117
- }
118
-
119
- /// @notice Allocate a writer for `count` STRING blocks using a per-block capacity hint.
120
- /// @dev The backing buffer expands automatically if encoded string blocks exceed the initial hint.
121
- /// @param count Number of string blocks to allocate space for.
122
- /// @return writer Allocated growable writer.
123
- function allocStrings(uint count) internal pure returns (Writer memory writer) {
124
- return allocFromHint(count, Hints.String);
125
- }
126
-
127
- /// @notice Allocate a writer sized for exactly `count` 32-byte-payload blocks.
128
- /// @param count Number of blocks to allocate space for.
129
- /// @return writer Allocated writer.
130
- function alloc32s(uint count) internal pure returns (Writer memory writer) {
131
- return allocFromCount(count, Sizes.B32);
132
- }
133
-
134
- /// @notice Allocate a writer sized for exactly `count` 64-byte-payload blocks.
135
- /// @param count Number of blocks to allocate space for.
136
- /// @return writer Allocated writer.
137
- function alloc64s(uint count) internal pure returns (Writer memory writer) {
138
- return allocFromCount(count, Sizes.B64);
139
- }
140
-
141
- /// @notice Allocate a writer sized for exactly `count` 96-byte-payload blocks.
142
- /// @param count Number of blocks to allocate space for.
143
- /// @return writer Allocated writer.
144
- function alloc96s(uint count) internal pure returns (Writer memory writer) {
145
- return allocFromCount(count, Sizes.B96);
146
- }
147
-
148
- /// @notice Allocate a writer sized for exactly `count` 128-byte-payload blocks.
149
- /// @param count Number of blocks to allocate space for.
150
- /// @return writer Allocated writer.
151
- function alloc128s(uint count) internal pure returns (Writer memory writer) {
152
- return allocFromCount(count, Sizes.B128);
153
- }
154
-
155
- /// @notice Allocate a writer sized for exactly `count` 160-byte-payload blocks.
156
- /// @param count Number of blocks to allocate space for.
157
- /// @return writer Allocated writer.
158
- function alloc160s(uint count) internal pure returns (Writer memory writer) {
159
- return allocFromCount(count, Sizes.B160);
160
- }
161
-
162
- /// @notice Allocate a writer sized for exactly `count` STATUS form blocks.
163
- /// @param count Number of blocks to allocate space for.
164
- /// @return writer Allocated writer.
165
- function allocStatuses(uint count) internal pure returns (Writer memory writer) {
166
- return allocFromCount(count, Sizes.Status);
167
- }
168
-
169
- /// @notice Allocate a writer sized for exactly `count` ASSET blocks.
170
- /// @param count Number of asset blocks to allocate space for.
171
- /// @return writer Allocated writer.
172
- function allocAssets(uint count) internal pure returns (Writer memory writer) {
173
- return alloc32s(count);
174
- }
175
-
176
- /// @notice Allocate a writer sized for exactly `count` AMOUNT blocks.
177
- /// @param count Number of amount blocks to allocate space for.
178
- /// @return writer Allocated writer.
179
- function allocAmounts(uint count) internal pure returns (Writer memory writer) {
180
- return alloc64s(count);
181
- }
182
-
183
- /// @notice Allocate a writer sized for exactly `count` BALANCE blocks.
184
- /// @param count Number of balance blocks to allocate space for.
185
- /// @return writer Allocated writer.
186
- function allocBalances(uint count) internal pure returns (Writer memory writer) {
187
- return alloc64s(count);
188
- }
189
-
190
- /// @notice Allocate a writer sized for exactly `count` ACCOUNT_AMOUNT form blocks.
191
- /// @param count Number of account amount blocks to allocate space for.
192
- /// @return writer Allocated writer.
193
- function allocAccountAmounts(uint count) internal pure returns (Writer memory writer) {
194
- return alloc96s(count);
195
- }
196
-
197
- /// @notice Allocate a writer sized for exactly `count` CUSTODY blocks.
198
- /// @param count Number of custody blocks to allocate space for.
199
- /// @return writer Allocated writer.
200
- function allocCustodies(uint count) internal pure returns (Writer memory writer) {
201
- return alloc96s(count);
202
- }
203
-
204
- /// @notice Allocate a writer sized for exactly `count` TRANSACTION blocks.
205
- /// @param count Number of transaction blocks to allocate space for.
206
- /// @return writer Allocated writer.
207
- function allocTransactions(uint count) internal pure returns (Writer memory writer) {
208
- return alloc128s(count);
209
- }
210
-
211
- /// @notice Allocate a writer for `count` STEP blocks using a per-block capacity hint.
212
- /// @dev The backing buffer expands automatically if encoded steps exceed the initial hint.
213
- /// @param count Number of step blocks to allocate space for.
214
- /// @return writer Allocated growable writer.
215
- function allocSteps(uint count) internal pure returns (Writer memory writer) {
216
- return allocFromHint(count, Hints.Step);
217
- }
218
-
219
- /// @notice Allocate a writer for `count` CALL blocks using a per-block capacity hint.
220
- /// @dev The backing buffer expands automatically if encoded calls exceed the initial hint.
221
- /// @param count Number of call blocks to allocate space for.
222
- /// @return writer Allocated growable writer.
223
- function allocCalls(uint count) internal pure returns (Writer memory writer) {
224
- return allocFromHint(count, Hints.Call);
225
- }
226
-
227
- /// @notice Allocate a writer for `count` CONTEXT blocks using a per-block capacity hint.
228
- /// @dev The backing buffer expands automatically if encoded contexts exceed the initial hint.
229
- /// @param count Number of context blocks to allocate space for.
230
- /// @return writer Allocated growable writer.
231
- function allocContexts(uint count) internal pure returns (Writer memory writer) {
232
- return allocFromHint(count, Hints.Context);
233
- }
234
-
235
- // -------------------------------------------------------------------------
236
- // Fixed-width write helpers
237
- // -------------------------------------------------------------------------
238
-
239
- /// @notice Write a low-level block header and return its memory pointer.
240
- /// The header occupies the most-significant 8 bytes of the first stored word.
241
- /// @param dst Destination buffer.
242
- /// @param i Write offset within `dst`.
243
- /// @param key Four-byte block type identifier.
244
- /// @param len Payload byte length.
245
- /// @return p Memory pointer to the start of the block header within `dst`.
246
- function writeHeader(bytes memory dst, uint i, bytes4 key, uint32 len) private pure returns (uint p) {
247
- uint header = (uint(uint32(key)) << 224) | (uint(len) << 192);
248
- assembly ("memory-safe") {
249
- p := add(add(dst, 0x20), i)
250
- mstore(p, header)
251
- }
252
- }
253
-
254
- /// @notice Write raw bytes directly into `dst` at byte offset `i` without a block header.
255
- /// @param dst Destination buffer.
256
- /// @param i Write offset within `dst`.
257
- /// @param data Bytes to copy.
258
- /// @return next Byte offset immediately after the copied bytes.
259
- function write(bytes memory dst, uint i, bytes memory data) internal pure returns (uint next) {
260
- next = i + data.length;
261
- if (next > dst.length) revert WriterOverflow();
262
- assembly ("memory-safe") {
263
- mcopy(add(add(dst, 0x20), i), add(data, 0x20), mload(data))
264
- }
265
- }
266
-
267
- /// @notice Write a raw 32-byte word directly into `dst` at byte offset `i` without a block header.
268
- /// `keep` controls how many leading bytes of the word are included in the logical write.
269
- /// @param dst Destination buffer; must have at least `i + 32` bytes.
270
- /// @param i Write offset within `dst`.
271
- /// @param value Word to write.
272
- /// @param keep Number of bytes to keep from the word (1..32).
273
- /// @return next Byte offset immediately after the written bytes.
274
- function write32(bytes memory dst, uint i, bytes32 value, uint keep) internal pure returns (uint next) {
275
- if (keep == 0 || keep > 32) revert InvalidKeep();
276
- if (i + 32 > dst.length) revert WriterOverflow();
277
- next = i + keep;
278
- assembly ("memory-safe") {
279
- mstore(add(add(dst, 0x20), i), value)
280
- }
281
- }
282
-
283
- /// @notice Write two raw 32-byte words directly into `dst` at byte offset `i` without a block header.
284
- /// `keep` controls how many leading bytes of the final word are included in the logical write.
285
- /// @param dst Destination buffer; must have at least `i + 64` bytes.
286
- /// @param i Write offset within `dst`.
287
- /// @param a First word to write.
288
- /// @param b Second word to write.
289
- /// @param keep Number of bytes to keep from the final word (1..32).
290
- /// @return next Byte offset immediately after the written bytes.
291
- function write64(bytes memory dst, uint i, bytes32 a, bytes32 b, uint keep) internal pure returns (uint next) {
292
- if (keep == 0 || keep > 32) revert InvalidKeep();
293
- if (i + 64 > dst.length) revert WriterOverflow();
294
- next = i + 32 + keep;
295
- assembly ("memory-safe") {
296
- let p := add(add(dst, 0x20), i)
297
- mstore(p, a)
298
- mstore(add(p, 0x20), b)
299
- }
300
- }
301
-
302
- /// @notice Write three raw 32-byte words directly into `dst` at byte offset `i` without a block header.
303
- /// `keep` controls how many leading bytes of the final word are included in the logical write.
304
- /// @param dst Destination buffer; must have at least `i + 96` bytes.
305
- /// @param i Write offset within `dst`.
306
- /// @param a First word to write.
307
- /// @param b Second word to write.
308
- /// @param c Third word to write.
309
- /// @param keep Number of bytes to keep from the final word (1..32).
310
- /// @return next Byte offset immediately after the written bytes.
311
- function write96(
312
- bytes memory dst,
313
- uint i,
314
- bytes32 a,
315
- bytes32 b,
316
- bytes32 c,
317
- uint keep
318
- ) internal pure returns (uint next) {
319
- if (keep == 0 || keep > 32) revert InvalidKeep();
320
- if (i + 96 > dst.length) revert WriterOverflow();
321
- next = i + 64 + keep;
322
- assembly ("memory-safe") {
323
- let p := add(add(dst, 0x20), i)
324
- mstore(p, a)
325
- mstore(add(p, 0x20), b)
326
- mstore(add(p, 0x40), c)
327
- }
328
- }
329
-
330
- /// @notice Write a dynamic block directly into `dst` at byte offset `i`.
331
- /// @param dst Destination buffer; must have at least `i + Sizes.Header + data.length` bytes.
332
- /// @param i Write offset within `dst`.
333
- /// @param key Block type key.
334
- /// @param data Dynamic payload bytes.
335
- /// @return next Byte offset immediately after the written block.
336
- function writeBlock(bytes memory dst, uint i, bytes4 key, bytes memory data) internal pure returns (uint next) {
337
- next = i + Sizes.Header + data.length;
338
- if (next > dst.length) revert WriterOverflow();
339
- uint p = writeHeader(dst, i, key, uint32(max32(data.length)));
340
- assembly ("memory-safe") {
341
- mcopy(add(p, 0x08), add(data, 0x20), mload(data))
342
- }
343
- }
344
-
345
- /// @notice Write a fixed-width 32-byte-payload block directly into `dst` at byte offset `i`.
346
- /// `keep` controls how many leading bytes of the final payload word are included.
347
- /// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
348
- /// @param dst Destination buffer; must have at least `i + Sizes.B32` bytes.
349
- /// @param i Write offset within `dst`.
350
- /// @param key Block type key.
351
- /// @param a First payload word.
352
- /// @param keep Number of bytes to keep from the final payload word (1..32).
353
- /// @return next Byte offset immediately after the written block.
354
- function writeBlock32(
355
- bytes memory dst,
356
- uint i,
357
- bytes4 key,
358
- bytes32 a,
359
- uint keep
360
- ) internal pure returns (uint next) {
361
- if (keep == 0 || keep > 32) revert InvalidKeep();
362
- if (i + Sizes.B32 > dst.length) revert WriterOverflow();
363
- uint len = keep;
364
- next = i + Sizes.Header + len;
365
- uint p = writeHeader(dst, i, key, uint32(len));
366
- assembly ("memory-safe") {
367
- mstore(add(p, 0x08), a)
368
- }
369
- }
370
-
371
- /// @notice Write a fixed-width 64-byte-payload block directly into `dst` at byte offset `i`.
372
- /// `keep` controls how many leading bytes of the final payload word are included.
373
- /// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
374
- /// @param dst Destination buffer; must have at least `i + Sizes.B64` bytes.
375
- /// @param i Write offset within `dst`.
376
- /// @param key Block type key.
377
- /// @param a First payload word.
378
- /// @param b Second payload word.
379
- /// @param keep Number of bytes to keep from the final payload word (1..32).
380
- /// @return next Byte offset immediately after the written block.
381
- function writeBlock64(
382
- bytes memory dst,
383
- uint i,
384
- bytes4 key,
385
- bytes32 a,
386
- bytes32 b,
387
- uint keep
388
- ) internal pure returns (uint next) {
389
- if (keep == 0 || keep > 32) revert InvalidKeep();
390
- if (i + Sizes.B64 > dst.length) revert WriterOverflow();
391
- uint len = 32 + keep;
392
- next = i + Sizes.Header + len;
393
- uint p = writeHeader(dst, i, key, uint32(len));
394
- assembly ("memory-safe") {
395
- mstore(add(p, 0x08), a)
396
- mstore(add(p, 0x28), b)
397
- }
398
- }
399
-
400
- /// @notice Write a fixed-width 96-byte-payload block directly into `dst` at byte offset `i`.
401
- /// `keep` controls how many leading bytes of the final payload word are included.
402
- /// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
403
- /// @param dst Destination buffer; must have at least `i + Sizes.B96` bytes.
404
- /// @param i Write offset within `dst`.
405
- /// @param key Block type key.
406
- /// @param a First payload word.
407
- /// @param b Second payload word.
408
- /// @param c Third payload word.
409
- /// @param keep Number of bytes to keep from the final payload word (1..32).
410
- /// @return next Byte offset immediately after the written block.
411
- function writeBlock96(
412
- bytes memory dst,
413
- uint i,
414
- bytes4 key,
415
- bytes32 a,
416
- bytes32 b,
417
- bytes32 c,
418
- uint keep
419
- ) internal pure returns (uint next) {
420
- if (keep == 0 || keep > 32) revert InvalidKeep();
421
- if (i + Sizes.B96 > dst.length) revert WriterOverflow();
422
- uint len = 64 + keep;
423
- next = i + Sizes.Header + len;
424
- uint p = writeHeader(dst, i, key, uint32(len));
425
- assembly ("memory-safe") {
426
- mstore(add(p, 0x08), a)
427
- mstore(add(p, 0x28), b)
428
- mstore(add(p, 0x48), c)
429
- }
430
- }
431
-
432
- /// @notice Write a fixed-width 128-byte-payload block directly into `dst` at byte offset `i`.
433
- /// `keep` controls how many leading bytes of the final payload word are included.
434
- /// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
435
- /// @param dst Destination buffer; must have at least `i + Sizes.B128` bytes.
436
- /// @param i Write offset within `dst`.
437
- /// @param key Block type key.
438
- /// @param a First payload word.
439
- /// @param b Second payload word.
440
- /// @param c Third payload word.
441
- /// @param d Fourth payload word.
442
- /// @param keep Number of bytes to keep from the final payload word (1..32).
443
- /// @return next Byte offset immediately after the written block.
444
- function writeBlock128(
445
- bytes memory dst,
446
- uint i,
447
- bytes4 key,
448
- bytes32 a,
449
- bytes32 b,
450
- bytes32 c,
451
- bytes32 d,
452
- uint keep
453
- ) internal pure returns (uint next) {
454
- if (keep == 0 || keep > 32) revert InvalidKeep();
455
- if (i + Sizes.B128 > dst.length) revert WriterOverflow();
456
- uint len = 96 + keep;
457
- next = i + Sizes.Header + len;
458
- uint p = writeHeader(dst, i, key, uint32(len));
459
- assembly ("memory-safe") {
460
- mstore(add(p, 0x08), a)
461
- mstore(add(p, 0x28), b)
462
- mstore(add(p, 0x48), c)
463
- mstore(add(p, 0x68), d)
464
- }
465
- }
466
-
467
- /// @notice Write a fixed-width 160-byte-payload block directly into `dst` at byte offset `i`.
468
- /// `keep` controls how many leading bytes of the final payload word are included.
469
- /// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
470
- /// @param dst Destination buffer; must have at least `i + Sizes.B160` bytes.
471
- /// @param i Write offset within `dst`.
472
- /// @param key Block type key.
473
- /// @param a First payload word.
474
- /// @param b Second payload word.
475
- /// @param c Third payload word.
476
- /// @param d Fourth payload word.
477
- /// @param e Fifth payload word.
478
- /// @param keep Number of bytes to keep from the final payload word (1..32).
479
- /// @return next Byte offset immediately after the written block.
480
- function writeBlock160(
481
- bytes memory dst,
482
- uint i,
483
- bytes4 key,
484
- bytes32 a,
485
- bytes32 b,
486
- bytes32 c,
487
- bytes32 d,
488
- bytes32 e,
489
- uint keep
490
- ) internal pure returns (uint next) {
491
- if (keep == 0 || keep > 32) revert InvalidKeep();
492
- if (i + Sizes.B160 > dst.length) revert WriterOverflow();
493
- uint len = 128 + keep;
494
- next = i + Sizes.Header + len;
495
- uint p = writeHeader(dst, i, key, uint32(len));
496
- assembly ("memory-safe") {
497
- mstore(add(p, 0x08), a)
498
- mstore(add(p, 0x28), b)
499
- mstore(add(p, 0x48), c)
500
- mstore(add(p, 0x68), d)
501
- mstore(add(p, 0x88), e)
502
- }
503
- }
504
-
505
- /// @notice Write a block with a 32-byte head and two nested BYTES payloads.
506
- /// @param dst Destination buffer; must have at least `i + Sizes.B32 + 2 * Sizes.Header + b.length + c.length` bytes.
507
- /// @param i Write offset within `dst`.
508
- /// @param key Block key.
509
- /// @param a Fixed head word.
510
- /// @param b First raw nested payload.
511
- /// @param c Second raw nested payload.
512
- /// @return next Byte offset immediately after the written block.
513
- function writeBlock32BytesBytes(
514
- bytes memory dst,
515
- uint i,
516
- bytes4 key,
517
- bytes32 a,
518
- bytes memory b,
519
- bytes memory c
520
- ) internal pure returns (uint next) {
521
- uint bLen = b.length;
522
- uint len = 32 + 2 * Sizes.Header + bLen + c.length;
523
- next = i + Sizes.Header + len;
524
- if (next > dst.length) revert WriterOverflow();
525
-
526
- {
527
- uint p = writeHeader(dst, i, key, uint32(max32(len)));
528
- assembly ("memory-safe") {
529
- mstore(add(p, 0x08), a)
530
- }
531
- }
532
-
533
- {
534
- uint q = writeHeader(dst, i + Sizes.Header + 32, Keys.Bytes, uint32(max32(bLen)));
535
- assembly ("memory-safe") {
536
- mcopy(add(q, 0x08), add(b, 0x20), mload(b))
537
- }
538
- }
539
-
540
- {
541
- uint r = writeHeader(dst, i + Sizes.Header + 32 + Sizes.Header + bLen, Keys.Bytes, uint32(max32(c.length)));
542
- assembly ("memory-safe") {
543
- mcopy(add(r, 0x08), add(c, 0x20), mload(c))
544
- }
545
- }
546
- }
547
-
548
- /// @notice Write a block with a 64-byte head and two nested BYTES payloads.
549
- /// @param dst Destination buffer; must have at least `i + Sizes.B64 + 2 * Sizes.Header + c.length + d.length` bytes.
550
- /// @param i Write offset within `dst`.
551
- /// @param key Block key.
552
- /// @param a First head word.
553
- /// @param b Second head word.
554
- /// @param c First raw nested payload.
555
- /// @param d Second raw nested payload.
556
- /// @return next Byte offset immediately after the written block.
557
- function writeBlock64BytesBytes(
558
- bytes memory dst,
559
- uint i,
560
- bytes4 key,
561
- bytes32 a,
562
- bytes32 b,
563
- bytes memory c,
564
- bytes memory d
565
- ) internal pure returns (uint next) {
566
- uint cLen = c.length;
567
- uint len = 64 + 2 * Sizes.Header + cLen + d.length;
568
- next = i + Sizes.Header + len;
569
- if (next > dst.length) revert WriterOverflow();
570
-
571
- {
572
- uint p = writeHeader(dst, i, key, uint32(max32(len)));
573
- assembly ("memory-safe") {
574
- mstore(add(p, 0x08), a)
575
- mstore(add(p, 0x28), b)
576
- }
577
- }
578
-
579
- {
580
- uint q = writeHeader(dst, i + Sizes.Header + 64, Keys.Bytes, uint32(max32(cLen)));
581
- assembly ("memory-safe") {
582
- mcopy(add(q, 0x08), add(c, 0x20), mload(c))
583
- }
584
- }
585
-
586
- {
587
- uint r = writeHeader(dst, i + Sizes.Header + 64 + Sizes.Header + cLen, Keys.Bytes, uint32(max32(d.length)));
588
- assembly ("memory-safe") {
589
- mcopy(add(r, 0x08), add(d, 0x20), mload(d))
590
- }
591
- }
592
- }
593
-
594
- /// @notice Write a block with a 64-byte head and nested BYTES payload.
595
- /// @param dst Destination buffer; must have at least `i + Sizes.B64 + Sizes.Header + c.length` bytes.
596
- /// @param i Write offset within `dst`.
597
- /// @param key Block key.
598
- /// @param a First head word.
599
- /// @param b Second head word.
600
- /// @param c Raw nested payload.
601
- /// @return next Byte offset immediately after the written block.
602
- function writeBlock64Bytes(
603
- bytes memory dst,
604
- uint i,
605
- bytes4 key,
606
- bytes32 a,
607
- bytes32 b,
608
- bytes memory c
609
- ) internal pure returns (uint next) {
610
- uint cLen = c.length;
611
- uint len = 64 + Sizes.Header + cLen;
612
- next = i + Sizes.Header + len;
613
- if (next > dst.length) revert WriterOverflow();
614
-
615
- {
616
- uint p = writeHeader(dst, i, key, uint32(max32(len)));
617
- assembly ("memory-safe") {
618
- mstore(add(p, 0x08), a)
619
- mstore(add(p, 0x28), b)
620
- }
621
- }
622
-
623
- {
624
- uint q = writeHeader(dst, i + Sizes.Header + 64, Keys.Bytes, uint32(max32(cLen)));
625
- assembly ("memory-safe") {
626
- mcopy(add(q, 0x08), add(c, 0x20), mload(c))
627
- }
628
- }
629
- }
630
-
631
- /// @notice Reserve physical write space and advance the logical writer position.
632
- /// Fixed writers may use padded backing space but cannot advance past logical capacity;
633
- /// growable writers expand when `touch` exceeds current capacity.
634
- /// @return i Original write offset.
635
- function reserve(Writer memory writer, uint next, uint touch) private pure returns (uint i) {
636
- i = writer.i;
637
- if (writer.growable) {
638
- if (touch > writer.end) {
639
- uint end = writer.end == 0 ? 64 : writer.end * 2;
640
- while (end < touch) {
641
- end *= 2;
642
- }
643
-
644
- uint padded = ((end + 31) & ~uint(31)) + 32;
645
- bytes memory src = writer.dst;
646
- bytes memory dst = new bytes(padded);
647
- assembly ("memory-safe") {
648
- mcopy(add(dst, 0x20), add(src, 0x20), i)
649
- }
650
- writer.end = end;
651
- writer.dst = dst;
652
- }
653
- } else if (touch > writer.dst.length) revert WriterOverflow();
654
-
655
- if (next > writer.end) revert WriterOverflow();
656
- writer.i = next;
657
- }
658
-
659
- // -------------------------------------------------------------------------
660
- // Append helpers
661
- // -------------------------------------------------------------------------
662
-
663
- /// @notice Append arbitrary bytes to the writer.
664
- /// @param writer Destination writer; `i` is advanced by `data.length`.
665
- /// @param data Bytes to append.
666
- function append(Writer memory writer, bytes memory data) internal pure {
667
- uint next = writer.i + data.length;
668
- uint i = reserve(writer, next, next);
669
- write(writer.dst, i, data);
670
- }
671
-
672
- /// @notice Append a raw 32-byte word without a block header.
673
- /// @param writer Destination writer; `i` is advanced by `keep`.
674
- /// @param value Word to append.
675
- /// @param keep Number of bytes to keep from the word (1..32).
676
- function append32(Writer memory writer, bytes32 value, uint keep) internal pure {
677
- uint i = writer.i;
678
- uint next = i + keep;
679
- i = reserve(writer, next, i + 32);
680
- write32(writer.dst, i, value, keep);
681
- }
682
-
683
- /// @notice Append two raw 32-byte words without a block header.
684
- /// @param writer Destination writer; `i` is advanced by `32 + keep`.
685
- /// @param a First word to append.
686
- /// @param b Second word to append.
687
- /// @param keep Number of bytes to keep from the final word (1..32).
688
- function append64(Writer memory writer, bytes32 a, bytes32 b, uint keep) internal pure {
689
- uint i = writer.i;
690
- uint next = i + 32 + keep;
691
- i = reserve(writer, next, i + 64);
692
- write64(writer.dst, i, a, b, keep);
693
- }
694
-
695
- /// @notice Append three raw 32-byte words without a block header.
696
- /// @param writer Destination writer; `i` is advanced by `64 + keep`.
697
- /// @param a First word to append.
698
- /// @param b Second word to append.
699
- /// @param c Third word to append.
700
- /// @param keep Number of bytes to keep from the final word (1..32).
701
- function append96(Writer memory writer, bytes32 a, bytes32 b, bytes32 c, uint keep) internal pure {
702
- uint i = writer.i;
703
- uint next = i + 64 + keep;
704
- i = reserve(writer, next, i + 96);
705
- write96(writer.dst, i, a, b, c, keep);
706
- }
707
-
708
- /// @notice Append a dynamic block.
709
- /// @param writer Destination writer; `i` is advanced by `Sizes.Header + data.length`.
710
- /// @param key Block type key.
711
- /// @param data Dynamic payload bytes.
712
- function appendBlock(Writer memory writer, bytes4 key, bytes memory data) internal pure {
713
- uint next = writer.i + Sizes.Header + data.length;
714
- uint i = reserve(writer, next, next);
715
- writeBlock(writer.dst, i, key, data);
716
- }
717
-
718
- /// @notice Append a fixed-width 32-byte-payload block.
719
- /// @param writer Destination writer; `i` is advanced by the kept logical block length.
720
- /// @param key Block type key.
721
- /// @param a First payload word.
722
- /// @param keep Number of bytes to keep from the final payload word (1..32).
723
- function appendBlock32(Writer memory writer, bytes4 key, bytes32 a, uint keep) internal pure {
724
- uint i = writer.i;
725
- uint next = i + Sizes.Header + keep;
726
- i = reserve(writer, next, i + Sizes.B32);
727
- writeBlock32(writer.dst, i, key, a, keep);
728
- }
729
-
730
- /// @notice Append a fixed-width 64-byte-payload block.
731
- /// @param writer Destination writer; `i` is advanced by the kept logical block length.
732
- /// @param key Block type key.
733
- /// @param a First payload word.
734
- /// @param b Second payload word.
735
- /// @param keep Number of bytes to keep from the final payload word (1..32).
736
- function appendBlock64(Writer memory writer, bytes4 key, bytes32 a, bytes32 b, uint keep) internal pure {
737
- uint i = writer.i;
738
- uint next = i + Sizes.Header + 32 + keep;
739
- i = reserve(writer, next, i + Sizes.B64);
740
- writeBlock64(writer.dst, i, key, a, b, keep);
741
- }
742
-
743
- /// @notice Append a fixed-width 96-byte-payload block.
744
- /// @param writer Destination writer; `i` is advanced by the kept logical block length.
745
- /// @param key Block type key.
746
- /// @param a First payload word.
747
- /// @param b Second payload word.
748
- /// @param c Third payload word.
749
- /// @param keep Number of bytes to keep from the final payload word (1..32).
750
- function appendBlock96(Writer memory writer, bytes4 key, bytes32 a, bytes32 b, bytes32 c, uint keep) internal pure {
751
- uint i = writer.i;
752
- uint next = i + Sizes.Header + 64 + keep;
753
- i = reserve(writer, next, i + Sizes.B96);
754
- writeBlock96(writer.dst, i, key, a, b, c, keep);
755
- }
756
-
757
- /// @notice Append a fixed-width 128-byte-payload block.
758
- /// @param writer Destination writer; `i` is advanced by the kept logical block length.
759
- /// @param key Block type key.
760
- /// @param a First payload word.
761
- /// @param b Second payload word.
762
- /// @param c Third payload word.
763
- /// @param d Fourth payload word.
764
- /// @param keep Number of bytes to keep from the final payload word (1..32).
765
- function appendBlock128(
766
- Writer memory writer,
767
- bytes4 key,
768
- bytes32 a,
769
- bytes32 b,
770
- bytes32 c,
771
- bytes32 d,
772
- uint keep
773
- ) internal pure {
774
- uint i = writer.i;
775
- uint next = i + Sizes.Header + 96 + keep;
776
- i = reserve(writer, next, i + Sizes.B128);
777
- writeBlock128(writer.dst, i, key, a, b, c, d, keep);
778
- }
779
-
780
- /// @notice Append a fixed-width 160-byte-payload block.
781
- /// @param writer Destination writer; `i` is advanced by the kept logical block length.
782
- /// @param key Block type key.
783
- /// @param a First payload word.
784
- /// @param b Second payload word.
785
- /// @param c Third payload word.
786
- /// @param d Fourth payload word.
787
- /// @param e Fifth payload word.
788
- /// @param keep Number of bytes to keep from the final payload word (1..32).
789
- function appendBlock160(
790
- Writer memory writer,
791
- bytes4 key,
792
- bytes32 a,
793
- bytes32 b,
794
- bytes32 c,
795
- bytes32 d,
796
- bytes32 e,
797
- uint keep
798
- ) internal pure {
799
- uint i = writer.i;
800
- uint next = i + Sizes.Header + 128 + keep;
801
- i = reserve(writer, next, i + Sizes.B160);
802
- writeBlock160(writer.dst, i, key, a, b, c, d, e, keep);
803
- }
804
-
805
- /// @notice Append a block with a 32-byte head and two nested BYTES payloads.
806
- /// @param writer Destination writer; `i` is advanced by the encoded block length.
807
- /// @param key Block key.
808
- /// @param a Fixed head word.
809
- /// @param b First raw nested payload.
810
- /// @param c Second raw nested payload.
811
- function appendBlock32BytesBytes(
812
- Writer memory writer,
813
- bytes4 key,
814
- bytes32 a,
815
- bytes memory b,
816
- bytes memory c
817
- ) internal pure {
818
- uint i = writer.i;
819
- uint next = i + Sizes.B32 + 2 * Sizes.Header + b.length + c.length;
820
- i = reserve(writer, next, next);
821
- writeBlock32BytesBytes(writer.dst, i, key, a, b, c);
822
- }
823
-
824
- /// @notice Append a block with a 64-byte head and two nested BYTES payloads.
825
- /// @param writer Destination writer; `i` is advanced by the encoded block length.
826
- /// @param key Block key.
827
- /// @param a First head word.
828
- /// @param b Second head word.
829
- /// @param c First raw nested payload.
830
- /// @param d Second raw nested payload.
831
- function appendBlock64BytesBytes(
832
- Writer memory writer,
833
- bytes4 key,
834
- bytes32 a,
835
- bytes32 b,
836
- bytes memory c,
837
- bytes memory d
838
- ) internal pure {
839
- uint i = writer.i;
840
- uint next = i + Sizes.B64 + 2 * Sizes.Header + c.length + d.length;
841
- i = reserve(writer, next, next);
842
- writeBlock64BytesBytes(writer.dst, i, key, a, b, c, d);
843
- }
844
-
845
- /// @notice Append a block with a 64-byte head and nested BYTES payload.
846
- /// @param writer Destination writer; `i` is advanced by the encoded block length.
847
- /// @param key Block key.
848
- /// @param a First head word.
849
- /// @param b Second head word.
850
- /// @param c Raw nested payload.
851
- function appendBlock64Bytes(Writer memory writer, bytes4 key, bytes32 a, bytes32 b, bytes memory c) internal pure {
852
- uint i = writer.i;
853
- uint next = i + Sizes.B64 + Sizes.Header + c.length;
854
- i = reserve(writer, next, next);
855
- writeBlock64Bytes(writer.dst, i, key, a, b, c);
856
- }
857
-
858
- /// @notice Append a BYTES block.
859
- /// @param writer Destination writer; `i` is advanced by the encoded BYTES block length.
860
- /// @param data Raw bytes payload.
861
- function appendBytes(Writer memory writer, bytes memory data) internal pure {
862
- appendBlock(writer, Keys.Bytes, data);
863
- }
864
-
865
- /// @notice Append a STRING block.
866
- /// @param writer Destination writer; `i` is advanced by the encoded STRING block length.
867
- /// @param data String payload.
868
- function appendString(Writer memory writer, string memory data) internal pure {
869
- appendBlock(writer, Keys.String, bytes(data));
870
- }
871
-
872
- /// @notice Append a STEP block with a nested request BYTES payload.
873
- /// @param writer Destination writer; `i` is advanced by the encoded STEP block length.
874
- /// @param target Command target identifier.
875
- /// @param resources Packed resources assigned to the step.
876
- /// @param request Raw nested request payload.
877
- function appendStep(Writer memory writer, uint target, uint resources, bytes memory request) internal pure {
878
- appendBlock64Bytes(writer, Keys.Step, bytes32(target), bytes32(resources), request);
879
- }
880
-
881
- /// @notice Append a CALL block with a nested payload BYTES block.
882
- /// @param writer Destination writer; `i` is advanced by the encoded CALL block length.
883
- /// @param target Call target identifier.
884
- /// @param resources Packed resources assigned to the call.
885
- /// @param data Raw nested call payload.
886
- function appendCall(Writer memory writer, uint target, uint resources, bytes memory data) internal pure {
887
- appendBlock64Bytes(writer, Keys.Call, bytes32(target), bytes32(resources), data);
888
- }
889
-
890
- /// @notice Append a CONTEXT block with nested state/request BYTES payloads.
891
- /// @param writer Destination writer; `i` is advanced by the encoded CONTEXT block length.
892
- /// @param account Command account identifier.
893
- /// @param state Raw nested state payload.
894
- /// @param request Raw nested request payload.
895
- function appendContext(Writer memory writer, bytes32 account, bytes memory state, bytes memory request) internal pure {
896
- appendBlock32BytesBytes(writer, Keys.Context, account, state, request);
897
- }
898
-
899
- /// @notice Append a STATUS form block.
900
- /// @param writer Destination writer; `i` is advanced by `Sizes.Status`.
901
- /// @param code Status code to encode.
902
- function appendStatus(Writer memory writer, uint code) internal pure {
903
- appendBlock32(writer, Keys.Status, bytes32(code), 32);
904
- }
905
-
906
- /// @notice Append a BALANCE block using separate field values.
907
- /// @param writer Destination writer; `i` is advanced by `Sizes.Balance`.
908
- /// @param asset Asset identifier.
909
- /// @param amount Token amount.
910
- function appendBalance(Writer memory writer, bytes32 asset, uint amount) internal pure {
911
- appendBlock64(writer, Keys.Balance, asset, bytes32(amount), 32);
912
- }
913
-
914
- /// @notice Append a BALANCE block from a struct.
915
- /// @param writer Destination writer; `i` is advanced by `Sizes.Balance`.
916
- /// @param value Balance fields to encode.
917
- function appendBalance(Writer memory writer, AssetAmount memory value) internal pure {
918
- appendBalance(writer, value.asset, value.amount);
919
- }
920
-
921
- /// @notice Append an AMOUNT block using separate field values.
922
- /// @param writer Destination writer; `i` is advanced by `Sizes.Amount`.
923
- /// @param asset Asset identifier.
924
- /// @param amount Token amount.
925
- function appendAmount(Writer memory writer, bytes32 asset, uint amount) internal pure {
926
- appendBlock64(writer, Keys.Amount, asset, bytes32(amount), 32);
927
- }
928
-
929
- /// @notice Append an AMOUNT block from a struct.
930
- /// @param writer Destination writer; `i` is advanced by `Sizes.Amount`.
931
- /// @param value Amount fields to encode.
932
- function appendAmount(Writer memory writer, AssetAmount memory value) internal pure {
933
- appendAmount(writer, value.asset, value.amount);
934
- }
935
-
936
- /// @notice Append an ACCOUNT_AMOUNT form block using separate field values.
937
- /// @param writer Destination writer; `i` is advanced by `Sizes.B96`.
938
- /// @param account Account identifier.
939
- /// @param asset Asset identifier.
940
- /// @param amount Token amount.
941
- function appendAccountAmount(
942
- Writer memory writer,
943
- bytes32 account,
944
- bytes32 asset,
945
- uint amount
946
- ) internal pure {
947
- appendBlock96(writer, Keys.AccountAmount, account, asset, bytes32(amount), 32);
948
- }
949
-
950
- /// @notice Append an ACCOUNT_AMOUNT form block from a struct.
951
- /// @param writer Destination writer; `i` is advanced by `Sizes.B96`.
952
- /// @param value Account amount fields to encode.
953
- function appendAccountAmount(Writer memory writer, AccountAmount memory value) internal pure {
954
- appendAccountAmount(writer, value.account, value.asset, value.amount);
955
- }
956
-
957
- /// @notice Append an ASSET block.
958
- /// @param writer Destination writer; `i` is advanced by `Sizes.B32`.
959
- /// @param asset Asset identifier.
960
- function appendAsset(Writer memory writer, bytes32 asset) internal pure {
961
- appendBlock32(writer, Keys.Asset, asset, 32);
962
- }
963
-
964
- /// @notice Append a BOUNTY block to the writer.
965
- /// @param writer Destination writer; `i` is advanced by `Sizes.Bounty`.
966
- /// @param amount Relayer reward amount.
967
- /// @param relayer Relayer account identifier.
968
- function appendBounty(Writer memory writer, uint amount, bytes32 relayer) internal pure {
969
- appendBlock64(writer, Keys.Bounty, bytes32(amount), relayer, 32);
970
- }
971
-
972
- /// @notice Append a CUSTODY block using separate field values.
973
- /// @param writer Destination writer; `i` is advanced by `Sizes.HostAmount`.
974
- /// @param host Host node ID.
975
- /// @param asset Asset identifier.
976
- /// @param amount Token amount.
977
- function appendCustody(Writer memory writer, uint host, bytes32 asset, uint amount) internal pure {
978
- appendBlock96(writer, Keys.Custody, bytes32(host), asset, bytes32(amount), 32);
979
- }
980
-
981
- /// @notice Append a CUSTODY block from a host and asset amount.
982
- /// @param writer Destination writer; `i` is advanced by `Sizes.HostAmount`.
983
- /// @param host Host node ID.
984
- /// @param value Custody fields to encode.
985
- function appendCustody(Writer memory writer, uint host, AssetAmount memory value) internal pure {
986
- appendCustody(writer, host, value.asset, value.amount);
987
- }
988
-
989
- /// @notice Append a CUSTODY block from a host amount struct.
990
- /// @param writer Destination writer; `i` is advanced by `Sizes.HostAmount`.
991
- /// @param value Custody fields to encode.
992
- function appendCustody(Writer memory writer, HostAmount memory value) internal pure {
993
- appendCustody(writer, value.host, value.asset, value.amount);
994
- }
995
-
996
- /// @notice Append a TRANSACTION block using separate field values.
997
- /// @param writer Destination writer; `i` is advanced by `Sizes.Transaction`.
998
- /// @param from Source account identifier.
999
- /// @param to Destination account identifier.
1000
- /// @param asset Asset identifier.
1001
- /// @param amount Transfer amount.
1002
- function appendTransaction(
1003
- Writer memory writer,
1004
- bytes32 from,
1005
- bytes32 to,
1006
- bytes32 asset,
1007
- uint amount
1008
- ) internal pure {
1009
- appendBlock128(writer, Keys.Transaction, from, to, asset, bytes32(amount), 32);
1010
- }
1011
-
1012
- /// @notice Append a TRANSACTION block from a struct.
1013
- /// @param writer Destination writer; `i` is advanced by `Sizes.Transaction`.
1014
- /// @param value Transfer record fields to encode.
1015
- function appendTransaction(Writer memory writer, Tx memory value) internal pure {
1016
- appendTransaction(writer, value.from, value.to, value.asset, value.amount);
1017
- }
1018
-
1019
- // -------------------------------------------------------------------------
1020
- // Finalisation
1021
- // -------------------------------------------------------------------------
1022
-
1023
- /// @notice Trim `dst` to the number of bytes actually written and return it.
1024
- /// Sets the `bytes` length slot in memory to `writer.i` without copying.
1025
- /// @param writer Completed writer.
1026
- /// @return out The written block stream; length equals `writer.i`.
1027
- function finish(Writer memory writer) internal pure returns (bytes memory out) {
1028
- if (writer.i == 0) revert EmptyRequest();
1029
- if (writer.i > writer.end || writer.i > writer.dst.length) revert IncompleteWriter();
1030
- out = writer.dst;
1031
- // Overwrite the memory length word of `out` with the actual written length.
1032
- assembly ("memory-safe") {
1033
- mstore(out, mload(writer))
1034
- }
1035
- }
1036
- }