@rootzero/contracts 0.7.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Commands.sol +15 -20
- package/Core.sol +3 -4
- package/Cursors.sol +3 -2
- package/Events.sol +1 -1
- package/Queries.sol +3 -3
- package/README.md +18 -19
- package/Utils.sol +3 -3
- package/blocks/Cursors.sol +937 -551
- package/blocks/Keys.sol +60 -34
- package/blocks/Schema.sol +112 -122
- package/blocks/Writers.sol +476 -301
- package/commands/Base.sol +32 -22
- package/commands/Burn.sol +14 -12
- package/commands/Credit.sol +16 -15
- package/commands/Debit.sol +14 -12
- package/commands/Deposit.sol +30 -37
- package/commands/Pipe.sol +14 -20
- package/commands/Provision.sol +19 -49
- package/commands/Transfer.sol +9 -18
- package/commands/Withdraw.sol +15 -14
- package/commands/admin/AllowAssets.sol +3 -3
- package/commands/admin/Allowance.sol +43 -0
- package/commands/admin/Authorize.sol +4 -4
- package/commands/admin/DenyAssets.sol +3 -3
- package/commands/admin/Destroy.sol +10 -8
- package/commands/admin/Execute.sol +38 -0
- package/commands/admin/Init.sol +10 -8
- package/commands/admin/Relocate.sol +5 -5
- package/commands/admin/Unauthorize.sol +4 -4
- package/core/Access.sol +38 -34
- package/core/Balances.sol +17 -18
- package/core/{Operation.sol → Calls.sol} +5 -8
- package/core/{CursorBase.sol → Context.sol} +11 -5
- package/core/Host.sol +11 -10
- package/core/Types.sol +86 -0
- package/docs/GETTING_STARTED.md +37 -29
- package/events/Asset.sol +1 -1
- package/events/Command.sol +10 -10
- package/events/Deposit.sol +3 -4
- package/events/Listing.sol +1 -1
- package/events/Peer.sol +3 -3
- package/events/Position.sol +21 -0
- package/events/Query.sol +3 -3
- package/events/Withdraw.sol +2 -3
- package/package.json +1 -1
- package/peer/AllowAssets.sol +1 -1
- package/peer/Allowance.sol +36 -0
- package/peer/AssetPull.sol +33 -31
- package/peer/Base.sol +8 -4
- package/peer/DenyAssets.sol +1 -1
- package/peer/Settle.sol +3 -4
- package/queries/Assets.sol +18 -16
- package/queries/Balances.sol +21 -19
- package/queries/Base.sol +2 -3
- package/queries/Positions.sol +32 -24
- package/utils/Accounts.sol +14 -13
- package/utils/Assets.sol +137 -62
- package/utils/Ids.sol +9 -9
- package/utils/Layout.sol +5 -3
- package/utils/Utils.sol +10 -0
- package/commands/Create.sol +0 -42
- package/commands/Remove.sol +0 -42
- package/commands/Settle.sol +0 -38
- package/commands/Stake.sol +0 -47
- package/commands/Supply.sol +0 -41
- package/commands/admin/Allocate.sol +0 -41
- package/core/HostBound.sol +0 -14
- package/events/Erc721.sol +0 -20
- package/peer/Pull.sol +0 -39
- package/peer/Push.sol +0 -45
- package/utils/State.sol +0 -22
package/blocks/Writers.sol
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
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";
|
|
5
8
|
|
|
6
9
|
/// @notice Sequential block stream writer backed by a pre-allocated memory buffer.
|
|
7
10
|
struct Writer {
|
|
8
11
|
/// @dev Current write position: number of bytes written so far.
|
|
9
12
|
uint i;
|
|
10
|
-
/// @dev
|
|
13
|
+
/// @dev Logical buffer capacity in bytes; writers should not advance past this limit.
|
|
11
14
|
uint end;
|
|
12
|
-
/// @dev Destination buffer
|
|
15
|
+
/// @dev Destination buffer. Physical capacity may be padded up to a full 32-byte word;
|
|
16
|
+
/// final length is set to `i` by `finish`.
|
|
13
17
|
bytes dst;
|
|
14
18
|
}
|
|
15
19
|
|
|
@@ -21,8 +25,10 @@ uint constant ALLOC_SCALE = 10_000;
|
|
|
21
25
|
/// @title Writers
|
|
22
26
|
/// @notice Response block stream builder for the rootzero protocol.
|
|
23
27
|
/// Allocates a fixed-size memory buffer up front and writes binary-encoded
|
|
24
|
-
/// blocks into it sequentially.
|
|
25
|
-
///
|
|
28
|
+
/// blocks into it sequentially. Physical allocation is rounded up to whole
|
|
29
|
+
/// 32-byte words for scratch space, while `Writer.end` tracks the logical
|
|
30
|
+
/// requested capacity. Call `finish` to trim the buffer to the number of
|
|
31
|
+
/// bytes actually written and return the result.
|
|
26
32
|
library Writers {
|
|
27
33
|
/// @dev `append` or a `write*` function tried to write past the end of `dst`.
|
|
28
34
|
error WriterOverflow();
|
|
@@ -30,55 +36,43 @@ library Writers {
|
|
|
30
36
|
error IncompleteWriter();
|
|
31
37
|
/// @dev An alloc function received a zero count, or `finish` found no bytes written.
|
|
32
38
|
error EmptyRequest();
|
|
33
|
-
/// @dev Block payload length exceeds `uint32` max; cannot be encoded in the 4-byte header field.
|
|
34
|
-
error BlockLengthOverflow();
|
|
35
39
|
/// @dev `scaledRatio * count` is not evenly divisible by `ALLOC_SCALE`.
|
|
36
40
|
error BadWriterRatio();
|
|
41
|
+
/// @dev A fixed-width low-level writer received an invalid final-word keep length.
|
|
42
|
+
error InvalidKeep();
|
|
37
43
|
|
|
38
44
|
// -------------------------------------------------------------------------
|
|
39
|
-
//
|
|
45
|
+
// Allocation helpers
|
|
40
46
|
// -------------------------------------------------------------------------
|
|
41
47
|
|
|
42
|
-
/// @notice
|
|
43
|
-
/// The
|
|
44
|
-
///
|
|
45
|
-
/// @param len
|
|
46
|
-
/// @return Packed header as a uint (key in bits [255:224], len in bits [223:192]).
|
|
47
|
-
function toBlockHeader(bytes4 key, uint len) internal pure returns (uint) {
|
|
48
|
-
if (len > type(uint32).max) revert BlockLengthOverflow();
|
|
49
|
-
return (uint(uint32(key)) << 224) | (uint(uint32(len)) << 192);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// -------------------------------------------------------------------------
|
|
53
|
-
// Allocation
|
|
54
|
-
// -------------------------------------------------------------------------
|
|
55
|
-
|
|
56
|
-
/// @notice Allocate a writer with an exact byte capacity.
|
|
57
|
-
/// @param len Number of bytes to pre-allocate.
|
|
48
|
+
/// @notice Allocate a writer with a logical byte capacity.
|
|
49
|
+
/// The backing buffer is rounded up to whole 32-byte words, while
|
|
50
|
+
/// `writer.end` remains the exact logical byte capacity requested.
|
|
51
|
+
/// @param len Number of logical bytes to pre-allocate.
|
|
58
52
|
/// @return writer Freshly allocated writer positioned at index 0.
|
|
59
53
|
function alloc(uint len) internal pure returns (Writer memory writer) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
/// @param count Number of balance blocks to allocate space for.
|
|
65
|
-
/// @return writer Allocated writer.
|
|
66
|
-
function allocBalances(uint count) internal pure returns (Writer memory writer) {
|
|
67
|
-
return alloc96s(count);
|
|
54
|
+
// Extra 32 bytes ensure mstore in write/append32 never reaches past allocated memory,
|
|
55
|
+
// even when a sub-word packed write starts within the last 31 bytes of the logical region.
|
|
56
|
+
uint padded = ((len + 31) & ~uint(31)) + 32;
|
|
57
|
+
writer = Writer({i: 0, end: len, dst: new bytes(padded)});
|
|
68
58
|
}
|
|
69
59
|
|
|
70
|
-
/// @notice
|
|
71
|
-
///
|
|
72
|
-
/// @
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/// @notice Allocate a writer sized for exactly `count` ASSET blocks (1:1 ratio).
|
|
78
|
-
/// @param count Number of asset blocks to allocate space for.
|
|
60
|
+
/// @notice Core allocation routine used by all counted `alloc*` helpers.
|
|
61
|
+
/// Computes `(count * scaledRatio / ALLOC_SCALE) * blockLen` and allocates that many bytes.
|
|
62
|
+
/// @param count Number of input blocks.
|
|
63
|
+
/// @param scaledRatio Output-to-input ratio in `ALLOC_SCALE` units.
|
|
64
|
+
/// @param blockLen Logical byte size of each output block (including 8-byte header).
|
|
79
65
|
/// @return writer Allocated writer.
|
|
80
|
-
function
|
|
81
|
-
|
|
66
|
+
function allocFromScaledCount(
|
|
67
|
+
uint count,
|
|
68
|
+
uint scaledRatio,
|
|
69
|
+
uint blockLen
|
|
70
|
+
) internal pure returns (Writer memory writer) {
|
|
71
|
+
if (count == 0) revert EmptyRequest();
|
|
72
|
+
uint scaledCount = count * scaledRatio;
|
|
73
|
+
if (scaledCount % ALLOC_SCALE != 0) revert BadWriterRatio();
|
|
74
|
+
uint len = (scaledCount / ALLOC_SCALE) * blockLen;
|
|
75
|
+
writer = alloc(len);
|
|
82
76
|
}
|
|
83
77
|
|
|
84
78
|
/// @notice Allocate a writer sized for exactly `count` dynamic blocks with a shared payload length.
|
|
@@ -125,40 +119,17 @@ library Writers {
|
|
|
125
119
|
return allocFromScaledCount(count, ALLOC_SCALE, Sizes.B160);
|
|
126
120
|
}
|
|
127
121
|
|
|
128
|
-
/// @notice Allocate a writer for BALANCE blocks with a custom output-to-input ratio.
|
|
129
|
-
/// @param count Number of input blocks.
|
|
130
|
-
/// @param scaledRatio Output count multiplier expressed in `ALLOC_SCALE` units
|
|
131
|
-
/// (e.g. `ALLOC_SCALE` = 1:1, `2 * ALLOC_SCALE` = 2:1).
|
|
132
|
-
/// @return writer Allocated writer.
|
|
133
|
-
function allocScaledBalances(uint count, uint scaledRatio) internal pure returns (Writer memory writer) {
|
|
134
|
-
return allocScaled96s(count, scaledRatio);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/// @notice Allocate a writer for AMOUNT blocks with a custom output-to-input ratio.
|
|
138
|
-
/// @param count Number of input blocks.
|
|
139
|
-
/// @param scaledRatio Output count multiplier expressed in `ALLOC_SCALE` units
|
|
140
|
-
/// (e.g. `ALLOC_SCALE` = 1:1, `2 * ALLOC_SCALE` = 2:1).
|
|
141
|
-
/// @return writer Allocated writer.
|
|
142
|
-
function allocScaledAmounts(uint count, uint scaledRatio) internal pure returns (Writer memory writer) {
|
|
143
|
-
return allocScaled96s(count, scaledRatio);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/// @notice Allocate a writer for ASSET blocks with a custom output-to-input ratio.
|
|
147
|
-
/// @param count Number of input blocks.
|
|
148
|
-
/// @param scaledRatio Output count multiplier expressed in `ALLOC_SCALE` units
|
|
149
|
-
/// (e.g. `ALLOC_SCALE` = 1:1, `2 * ALLOC_SCALE` = 2:1).
|
|
150
|
-
/// @return writer Allocated writer.
|
|
151
|
-
function allocScaledAssets(uint count, uint scaledRatio) internal pure returns (Writer memory writer) {
|
|
152
|
-
return allocScaled64s(count, scaledRatio);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
122
|
/// @notice Allocate a writer for dynamic blocks with a shared payload length and custom output ratio.
|
|
156
123
|
/// Each block reserves `Sizes.Header + payloadLen` bytes.
|
|
157
124
|
/// @param count Number of input blocks.
|
|
158
125
|
/// @param scaledRatio Output count multiplier expressed in `ALLOC_SCALE` units.
|
|
159
126
|
/// @param payloadLen Payload byte length for each block.
|
|
160
127
|
/// @return writer Allocated writer.
|
|
161
|
-
function allocScaledBytes(
|
|
128
|
+
function allocScaledBytes(
|
|
129
|
+
uint count,
|
|
130
|
+
uint scaledRatio,
|
|
131
|
+
uint payloadLen
|
|
132
|
+
) internal pure returns (Writer memory writer) {
|
|
162
133
|
return allocFromScaledCount(count, scaledRatio, Sizes.Header + payloadLen);
|
|
163
134
|
}
|
|
164
135
|
|
|
@@ -202,11 +173,39 @@ library Writers {
|
|
|
202
173
|
return allocFromScaledCount(count, scaledRatio, Sizes.B160);
|
|
203
174
|
}
|
|
204
175
|
|
|
205
|
-
/// @notice Allocate a writer sized for exactly `count`
|
|
206
|
-
/// @param count Number of
|
|
176
|
+
/// @notice Allocate a writer sized for exactly `count` STATUS form blocks.
|
|
177
|
+
/// @param count Number of blocks to allocate space for.
|
|
207
178
|
/// @return writer Allocated writer.
|
|
208
|
-
function
|
|
209
|
-
return
|
|
179
|
+
function allocStatuses(uint count) internal pure returns (Writer memory writer) {
|
|
180
|
+
return alloc32s(count);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// @notice Allocate a writer sized for exactly `count` ASSET blocks (1:1 ratio).
|
|
184
|
+
/// @param count Number of asset blocks to allocate space for.
|
|
185
|
+
/// @return writer Allocated writer.
|
|
186
|
+
function allocAssets(uint count) internal pure returns (Writer memory writer) {
|
|
187
|
+
return alloc64s(count);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// @notice Allocate a writer sized for exactly `count` AMOUNT blocks (1:1 ratio).
|
|
191
|
+
/// @param count Number of amount blocks to allocate space for.
|
|
192
|
+
/// @return writer Allocated writer.
|
|
193
|
+
function allocAmounts(uint count) internal pure returns (Writer memory writer) {
|
|
194
|
+
return alloc96s(count);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/// @notice Allocate a writer sized for exactly `count` BALANCE blocks (1:1 ratio).
|
|
198
|
+
/// @param count Number of balance blocks to allocate space for.
|
|
199
|
+
/// @return writer Allocated writer.
|
|
200
|
+
function allocBalances(uint count) internal pure returns (Writer memory writer) {
|
|
201
|
+
return alloc96s(count);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/// @notice Allocate a writer sized for exactly `count` ACCOUNT_AMOUNT form blocks (1:1 ratio).
|
|
205
|
+
/// @param count Number of account amount blocks to allocate space for.
|
|
206
|
+
/// @return writer Allocated writer.
|
|
207
|
+
function allocAccountAmounts(uint count) internal pure returns (Writer memory writer) {
|
|
208
|
+
return alloc128s(count);
|
|
210
209
|
}
|
|
211
210
|
|
|
212
211
|
/// @notice Allocate a writer sized for exactly `count` CUSTODY blocks (1:1 ratio).
|
|
@@ -216,105 +215,247 @@ library Writers {
|
|
|
216
215
|
return alloc128s(count);
|
|
217
216
|
}
|
|
218
217
|
|
|
219
|
-
/// @notice Allocate a writer for
|
|
218
|
+
/// @notice Allocate a writer sized for exactly `count` TRANSACTION blocks (1:1 ratio).
|
|
219
|
+
/// @param count Number of transaction blocks to allocate space for.
|
|
220
|
+
/// @return writer Allocated writer.
|
|
221
|
+
function allocTransactions(uint count) internal pure returns (Writer memory writer) {
|
|
222
|
+
return alloc160s(count);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/// @notice Allocate a writer for ASSET blocks with a custom output-to-input ratio.
|
|
220
226
|
/// @param count Number of input blocks.
|
|
221
|
-
/// @param scaledRatio Output count multiplier in `ALLOC_SCALE` units
|
|
227
|
+
/// @param scaledRatio Output count multiplier expressed in `ALLOC_SCALE` units
|
|
228
|
+
/// (e.g. `ALLOC_SCALE` = 1:1, `2 * ALLOC_SCALE` = 2:1).
|
|
222
229
|
/// @return writer Allocated writer.
|
|
223
|
-
function
|
|
224
|
-
return
|
|
230
|
+
function allocScaledAssets(uint count, uint scaledRatio) internal pure returns (Writer memory writer) {
|
|
231
|
+
return allocScaled64s(count, scaledRatio);
|
|
225
232
|
}
|
|
226
233
|
|
|
227
|
-
/// @notice
|
|
228
|
-
/// Computes `(count * scaledRatio / ALLOC_SCALE) * blockLen` and allocates that many bytes.
|
|
234
|
+
/// @notice Allocate a writer for AMOUNT blocks with a custom output-to-input ratio.
|
|
229
235
|
/// @param count Number of input blocks.
|
|
230
|
-
/// @param scaledRatio Output
|
|
231
|
-
///
|
|
236
|
+
/// @param scaledRatio Output count multiplier expressed in `ALLOC_SCALE` units
|
|
237
|
+
/// (e.g. `ALLOC_SCALE` = 1:1, `2 * ALLOC_SCALE` = 2:1).
|
|
232
238
|
/// @return writer Allocated writer.
|
|
233
|
-
function
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
239
|
+
function allocScaledAmounts(uint count, uint scaledRatio) internal pure returns (Writer memory writer) {
|
|
240
|
+
return allocScaled96s(count, scaledRatio);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/// @notice Allocate a writer for BALANCE blocks with a custom output-to-input ratio.
|
|
244
|
+
/// @param count Number of input blocks.
|
|
245
|
+
/// @param scaledRatio Output count multiplier expressed in `ALLOC_SCALE` units
|
|
246
|
+
/// (e.g. `ALLOC_SCALE` = 1:1, `2 * ALLOC_SCALE` = 2:1).
|
|
247
|
+
/// @return writer Allocated writer.
|
|
248
|
+
function allocScaledBalances(uint count, uint scaledRatio) internal pure returns (Writer memory writer) {
|
|
249
|
+
return allocScaled96s(count, scaledRatio);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/// @notice Allocate a writer for CUSTODY blocks with a custom output-to-input ratio.
|
|
253
|
+
/// @param count Number of input blocks.
|
|
254
|
+
/// @param scaledRatio Output count multiplier in `ALLOC_SCALE` units.
|
|
255
|
+
/// @return writer Allocated writer.
|
|
256
|
+
function allocScaledCustodies(uint count, uint scaledRatio) internal pure returns (Writer memory writer) {
|
|
257
|
+
return allocScaled128s(count, scaledRatio);
|
|
243
258
|
}
|
|
244
259
|
|
|
245
260
|
// -------------------------------------------------------------------------
|
|
246
261
|
// Fixed-width write helpers
|
|
247
262
|
// -------------------------------------------------------------------------
|
|
248
263
|
|
|
249
|
-
/// @notice Write a
|
|
250
|
-
///
|
|
264
|
+
/// @notice Write a low-level block header and return its memory pointer.
|
|
265
|
+
/// The header occupies the most-significant 8 bytes of the first stored word.
|
|
266
|
+
/// @param dst Destination buffer.
|
|
267
|
+
/// @param i Write offset within `dst`.
|
|
268
|
+
/// @param key Four-byte block type identifier.
|
|
269
|
+
/// @param len Payload byte length.
|
|
270
|
+
/// @return p Memory pointer to the start of the block header within `dst`.
|
|
271
|
+
function writeHeader(bytes memory dst, uint i, bytes4 key, uint32 len) private pure returns (uint p) {
|
|
272
|
+
uint header = (uint(uint32(key)) << 224) | (uint(len) << 192);
|
|
273
|
+
assembly ("memory-safe") {
|
|
274
|
+
p := add(add(dst, 0x20), i)
|
|
275
|
+
mstore(p, header)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/// @notice Commit a logical writer advance after a low-level write.
|
|
280
|
+
/// @dev Low-level write helpers validate the padded backing buffer. This
|
|
281
|
+
/// enforces the caller-requested logical capacity recorded in `end`.
|
|
282
|
+
function commit(Writer memory writer, uint next) private pure {
|
|
283
|
+
if (next > writer.end) revert WriterOverflow();
|
|
284
|
+
writer.i = next;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/// @notice Write raw bytes directly into `dst` at byte offset `i` without a block header.
|
|
288
|
+
/// @param dst Destination buffer.
|
|
289
|
+
/// @param i Write offset within `dst`.
|
|
290
|
+
/// @param data Bytes to copy.
|
|
291
|
+
/// @return next Byte offset immediately after the copied bytes.
|
|
292
|
+
function write(bytes memory dst, uint i, bytes memory data) internal pure returns (uint next) {
|
|
293
|
+
next = i + data.length;
|
|
294
|
+
if (next > dst.length) revert WriterOverflow();
|
|
295
|
+
assembly ("memory-safe") {
|
|
296
|
+
mcopy(add(add(dst, 0x20), i), add(data, 0x20), mload(data))
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/// @notice Write a raw 32-byte word directly into `dst` at byte offset `i` without a block header.
|
|
301
|
+
/// `keep` controls how many leading bytes of the word are included in the logical write.
|
|
302
|
+
/// @param dst Destination buffer; must have at least `i + 32` bytes.
|
|
303
|
+
/// @param i Write offset within `dst`.
|
|
304
|
+
/// @param value Word to write.
|
|
305
|
+
/// @param keep Number of bytes to keep from the word (1..32).
|
|
306
|
+
/// @return next Byte offset immediately after the written bytes.
|
|
307
|
+
function write32(bytes memory dst, uint i, bytes32 value, uint keep) internal pure returns (uint next) {
|
|
308
|
+
if (keep == 0 || keep > 32) revert InvalidKeep();
|
|
309
|
+
if (i + 32 > dst.length) revert WriterOverflow();
|
|
310
|
+
next = i + keep;
|
|
311
|
+
assembly ("memory-safe") {
|
|
312
|
+
mstore(add(add(dst, 0x20), i), value)
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/// @notice Write two raw 32-byte words directly into `dst` at byte offset `i` without a block header.
|
|
317
|
+
/// `keep` controls how many leading bytes of the final word are included in the logical write.
|
|
318
|
+
/// @param dst Destination buffer; must have at least `i + 64` bytes.
|
|
319
|
+
/// @param i Write offset within `dst`.
|
|
320
|
+
/// @param a First word to write.
|
|
321
|
+
/// @param b Second word to write.
|
|
322
|
+
/// @param keep Number of bytes to keep from the final word (1..32).
|
|
323
|
+
/// @return next Byte offset immediately after the written bytes.
|
|
324
|
+
function write64(bytes memory dst, uint i, bytes32 a, bytes32 b, uint keep) internal pure returns (uint next) {
|
|
325
|
+
if (keep == 0 || keep > 32) revert InvalidKeep();
|
|
326
|
+
if (i + 64 > dst.length) revert WriterOverflow();
|
|
327
|
+
next = i + 32 + keep;
|
|
328
|
+
assembly ("memory-safe") {
|
|
329
|
+
let p := add(add(dst, 0x20), i)
|
|
330
|
+
mstore(p, a)
|
|
331
|
+
mstore(add(p, 0x20), b)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/// @notice Write three raw 32-byte words directly into `dst` at byte offset `i` without a block header.
|
|
336
|
+
/// `keep` controls how many leading bytes of the final word are included in the logical write.
|
|
337
|
+
/// @param dst Destination buffer; must have at least `i + 96` bytes.
|
|
338
|
+
/// @param i Write offset within `dst`.
|
|
339
|
+
/// @param a First word to write.
|
|
340
|
+
/// @param b Second word to write.
|
|
341
|
+
/// @param c Third word to write.
|
|
342
|
+
/// @param keep Number of bytes to keep from the final word (1..32).
|
|
343
|
+
/// @return next Byte offset immediately after the written bytes.
|
|
344
|
+
function write96(
|
|
345
|
+
bytes memory dst,
|
|
346
|
+
uint i,
|
|
347
|
+
bytes32 a,
|
|
348
|
+
bytes32 b,
|
|
349
|
+
bytes32 c,
|
|
350
|
+
uint keep
|
|
351
|
+
) internal pure returns (uint next) {
|
|
352
|
+
if (keep == 0 || keep > 32) revert InvalidKeep();
|
|
353
|
+
if (i + 96 > dst.length) revert WriterOverflow();
|
|
354
|
+
next = i + 64 + keep;
|
|
355
|
+
assembly ("memory-safe") {
|
|
356
|
+
let p := add(add(dst, 0x20), i)
|
|
357
|
+
mstore(p, a)
|
|
358
|
+
mstore(add(p, 0x20), b)
|
|
359
|
+
mstore(add(p, 0x40), c)
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/// @notice Write a dynamic block directly into `dst` at byte offset `i`.
|
|
364
|
+
/// @param dst Destination buffer; must have at least `i + Sizes.Header + data.length` bytes.
|
|
251
365
|
/// @param i Write offset within `dst`.
|
|
252
366
|
/// @param key Block type key.
|
|
253
|
-
/// @param
|
|
367
|
+
/// @param data Dynamic payload bytes.
|
|
254
368
|
/// @return next Byte offset immediately after the written block.
|
|
255
|
-
function
|
|
256
|
-
next = i + Sizes.
|
|
369
|
+
function writeBlock(bytes memory dst, uint i, bytes4 key, bytes memory data) internal pure returns (uint next) {
|
|
370
|
+
next = i + Sizes.Header + data.length;
|
|
257
371
|
if (next > dst.length) revert WriterOverflow();
|
|
258
|
-
uint
|
|
372
|
+
uint p = writeHeader(dst, i, key, uint32(max32(data.length)));
|
|
259
373
|
assembly ("memory-safe") {
|
|
260
|
-
|
|
261
|
-
mstore(p, header)
|
|
262
|
-
mstore(add(p, 0x08), a)
|
|
374
|
+
mcopy(add(p, 0x08), add(data, 0x20), mload(data))
|
|
263
375
|
}
|
|
264
376
|
}
|
|
265
377
|
|
|
266
|
-
/// @notice Write
|
|
267
|
-
///
|
|
378
|
+
/// @notice Write a fixed-width 32-byte-payload block directly into `dst` at byte offset `i`.
|
|
379
|
+
/// `keep` controls how many leading bytes of the final payload word are included.
|
|
380
|
+
/// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
|
|
268
381
|
/// @param dst Destination buffer; must have at least `i + Sizes.B32` bytes.
|
|
269
382
|
/// @param i Write offset within `dst`.
|
|
270
383
|
/// @param key Block type key.
|
|
271
|
-
/// @param
|
|
384
|
+
/// @param a First payload word.
|
|
385
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
272
386
|
/// @return next Byte offset immediately after the written block.
|
|
273
|
-
function
|
|
274
|
-
|
|
387
|
+
function writeBlock32(
|
|
388
|
+
bytes memory dst,
|
|
389
|
+
uint i,
|
|
390
|
+
bytes4 key,
|
|
391
|
+
bytes32 a,
|
|
392
|
+
uint keep
|
|
393
|
+
) internal pure returns (uint next) {
|
|
394
|
+
if (keep == 0 || keep > 32) revert InvalidKeep();
|
|
395
|
+
if (i + Sizes.B32 > dst.length) revert WriterOverflow();
|
|
396
|
+
uint len = keep;
|
|
397
|
+
next = i + Sizes.Header + len;
|
|
398
|
+
uint p = writeHeader(dst, i, key, uint32(len));
|
|
399
|
+
assembly ("memory-safe") {
|
|
400
|
+
mstore(add(p, 0x08), a)
|
|
401
|
+
}
|
|
275
402
|
}
|
|
276
403
|
|
|
277
404
|
/// @notice Write a fixed-width 64-byte-payload block directly into `dst` at byte offset `i`.
|
|
405
|
+
/// `keep` controls how many leading bytes of the final payload word are included.
|
|
406
|
+
/// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
|
|
278
407
|
/// @param dst Destination buffer; must have at least `i + Sizes.B64` bytes.
|
|
279
408
|
/// @param i Write offset within `dst`.
|
|
280
409
|
/// @param key Block type key.
|
|
281
410
|
/// @param a First payload word.
|
|
282
411
|
/// @param b Second payload word.
|
|
412
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
283
413
|
/// @return next Byte offset immediately after the written block.
|
|
284
|
-
function
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
414
|
+
function writeBlock64(
|
|
415
|
+
bytes memory dst,
|
|
416
|
+
uint i,
|
|
417
|
+
bytes4 key,
|
|
418
|
+
bytes32 a,
|
|
419
|
+
bytes32 b,
|
|
420
|
+
uint keep
|
|
421
|
+
) internal pure returns (uint next) {
|
|
422
|
+
if (keep == 0 || keep > 32) revert InvalidKeep();
|
|
423
|
+
if (i + Sizes.B64 > dst.length) revert WriterOverflow();
|
|
424
|
+
uint len = 32 + keep;
|
|
425
|
+
next = i + Sizes.Header + len;
|
|
426
|
+
uint p = writeHeader(dst, i, key, uint32(len));
|
|
288
427
|
assembly ("memory-safe") {
|
|
289
|
-
let p := add(add(dst, 0x20), i)
|
|
290
|
-
mstore(p, header)
|
|
291
428
|
mstore(add(p, 0x08), a)
|
|
292
429
|
mstore(add(p, 0x28), b)
|
|
293
430
|
}
|
|
294
431
|
}
|
|
295
432
|
|
|
296
433
|
/// @notice Write a fixed-width 96-byte-payload block directly into `dst` at byte offset `i`.
|
|
434
|
+
/// `keep` controls how many leading bytes of the final payload word are included.
|
|
435
|
+
/// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
|
|
297
436
|
/// @param dst Destination buffer; must have at least `i + Sizes.B96` bytes.
|
|
298
437
|
/// @param i Write offset within `dst`.
|
|
299
438
|
/// @param key Block type key.
|
|
300
439
|
/// @param a First payload word.
|
|
301
440
|
/// @param b Second payload word.
|
|
302
441
|
/// @param c Third payload word.
|
|
442
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
303
443
|
/// @return next Byte offset immediately after the written block.
|
|
304
|
-
function
|
|
444
|
+
function writeBlock96(
|
|
305
445
|
bytes memory dst,
|
|
306
446
|
uint i,
|
|
307
447
|
bytes4 key,
|
|
308
448
|
bytes32 a,
|
|
309
449
|
bytes32 b,
|
|
310
|
-
bytes32 c
|
|
450
|
+
bytes32 c,
|
|
451
|
+
uint keep
|
|
311
452
|
) internal pure returns (uint next) {
|
|
312
|
-
|
|
313
|
-
if (
|
|
314
|
-
uint
|
|
453
|
+
if (keep == 0 || keep > 32) revert InvalidKeep();
|
|
454
|
+
if (i + Sizes.B96 > dst.length) revert WriterOverflow();
|
|
455
|
+
uint len = 64 + keep;
|
|
456
|
+
next = i + Sizes.Header + len;
|
|
457
|
+
uint p = writeHeader(dst, i, key, uint32(len));
|
|
315
458
|
assembly ("memory-safe") {
|
|
316
|
-
let p := add(add(dst, 0x20), i)
|
|
317
|
-
mstore(p, header)
|
|
318
459
|
mstore(add(p, 0x08), a)
|
|
319
460
|
mstore(add(p, 0x28), b)
|
|
320
461
|
mstore(add(p, 0x48), c)
|
|
@@ -322,6 +463,8 @@ library Writers {
|
|
|
322
463
|
}
|
|
323
464
|
|
|
324
465
|
/// @notice Write a fixed-width 128-byte-payload block directly into `dst` at byte offset `i`.
|
|
466
|
+
/// `keep` controls how many leading bytes of the final payload word are included.
|
|
467
|
+
/// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
|
|
325
468
|
/// @param dst Destination buffer; must have at least `i + Sizes.B128` bytes.
|
|
326
469
|
/// @param i Write offset within `dst`.
|
|
327
470
|
/// @param key Block type key.
|
|
@@ -329,22 +472,24 @@ library Writers {
|
|
|
329
472
|
/// @param b Second payload word.
|
|
330
473
|
/// @param c Third payload word.
|
|
331
474
|
/// @param d Fourth payload word.
|
|
475
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
332
476
|
/// @return next Byte offset immediately after the written block.
|
|
333
|
-
function
|
|
477
|
+
function writeBlock128(
|
|
334
478
|
bytes memory dst,
|
|
335
479
|
uint i,
|
|
336
480
|
bytes4 key,
|
|
337
481
|
bytes32 a,
|
|
338
482
|
bytes32 b,
|
|
339
483
|
bytes32 c,
|
|
340
|
-
bytes32 d
|
|
484
|
+
bytes32 d,
|
|
485
|
+
uint keep
|
|
341
486
|
) internal pure returns (uint next) {
|
|
342
|
-
|
|
343
|
-
if (
|
|
344
|
-
uint
|
|
487
|
+
if (keep == 0 || keep > 32) revert InvalidKeep();
|
|
488
|
+
if (i + Sizes.B128 > dst.length) revert WriterOverflow();
|
|
489
|
+
uint len = 96 + keep;
|
|
490
|
+
next = i + Sizes.Header + len;
|
|
491
|
+
uint p = writeHeader(dst, i, key, uint32(len));
|
|
345
492
|
assembly ("memory-safe") {
|
|
346
|
-
let p := add(add(dst, 0x20), i)
|
|
347
|
-
mstore(p, header)
|
|
348
493
|
mstore(add(p, 0x08), a)
|
|
349
494
|
mstore(add(p, 0x28), b)
|
|
350
495
|
mstore(add(p, 0x48), c)
|
|
@@ -353,6 +498,8 @@ library Writers {
|
|
|
353
498
|
}
|
|
354
499
|
|
|
355
500
|
/// @notice Write a fixed-width 160-byte-payload block directly into `dst` at byte offset `i`.
|
|
501
|
+
/// `keep` controls how many leading bytes of the final payload word are included.
|
|
502
|
+
/// Writes still use full-word stores, so `dst` must have capacity for the untrimmed block.
|
|
356
503
|
/// @param dst Destination buffer; must have at least `i + Sizes.B160` bytes.
|
|
357
504
|
/// @param i Write offset within `dst`.
|
|
358
505
|
/// @param key Block type key.
|
|
@@ -361,8 +508,9 @@ library Writers {
|
|
|
361
508
|
/// @param c Third payload word.
|
|
362
509
|
/// @param d Fourth payload word.
|
|
363
510
|
/// @param e Fifth payload word.
|
|
511
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
364
512
|
/// @return next Byte offset immediately after the written block.
|
|
365
|
-
function
|
|
513
|
+
function writeBlock160(
|
|
366
514
|
bytes memory dst,
|
|
367
515
|
uint i,
|
|
368
516
|
bytes4 key,
|
|
@@ -370,14 +518,15 @@ library Writers {
|
|
|
370
518
|
bytes32 b,
|
|
371
519
|
bytes32 c,
|
|
372
520
|
bytes32 d,
|
|
373
|
-
bytes32 e
|
|
521
|
+
bytes32 e,
|
|
522
|
+
uint keep
|
|
374
523
|
) internal pure returns (uint next) {
|
|
375
|
-
|
|
376
|
-
if (
|
|
377
|
-
uint
|
|
524
|
+
if (keep == 0 || keep > 32) revert InvalidKeep();
|
|
525
|
+
if (i + Sizes.B160 > dst.length) revert WriterOverflow();
|
|
526
|
+
uint len = 128 + keep;
|
|
527
|
+
next = i + Sizes.Header + len;
|
|
528
|
+
uint p = writeHeader(dst, i, key, uint32(len));
|
|
378
529
|
assembly ("memory-safe") {
|
|
379
|
-
let p := add(add(dst, 0x20), i)
|
|
380
|
-
mstore(p, header)
|
|
381
530
|
mstore(add(p, 0x08), a)
|
|
382
531
|
mstore(add(p, 0x28), b)
|
|
383
532
|
mstore(add(p, 0x48), c)
|
|
@@ -393,19 +542,18 @@ library Writers {
|
|
|
393
542
|
/// @param a Fixed head word.
|
|
394
543
|
/// @param tail Dynamic payload bytes appended after the head.
|
|
395
544
|
/// @return next Byte offset immediately after the written block.
|
|
396
|
-
function
|
|
545
|
+
function writeBlockHead32(
|
|
397
546
|
bytes memory dst,
|
|
398
547
|
uint i,
|
|
399
548
|
bytes4 key,
|
|
400
549
|
bytes32 a,
|
|
401
550
|
bytes memory tail
|
|
402
551
|
) internal pure returns (uint next) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
552
|
+
uint len = 32 + tail.length;
|
|
553
|
+
next = i + Sizes.Header + len;
|
|
554
|
+
if (i + Sizes.B32 + tail.length > dst.length) revert WriterOverflow();
|
|
555
|
+
uint p = writeHeader(dst, i, key, uint32(max32(len)));
|
|
406
556
|
assembly ("memory-safe") {
|
|
407
|
-
let p := add(add(dst, 0x20), i)
|
|
408
|
-
mstore(p, header)
|
|
409
557
|
mstore(add(p, 0x08), a)
|
|
410
558
|
mcopy(add(p, 0x28), add(tail, 0x20), mload(tail))
|
|
411
559
|
}
|
|
@@ -419,7 +567,7 @@ library Writers {
|
|
|
419
567
|
/// @param b Second fixed head word.
|
|
420
568
|
/// @param tail Dynamic payload bytes appended after the head.
|
|
421
569
|
/// @return next Byte offset immediately after the written block.
|
|
422
|
-
function
|
|
570
|
+
function writeBlockHead64(
|
|
423
571
|
bytes memory dst,
|
|
424
572
|
uint i,
|
|
425
573
|
bytes4 key,
|
|
@@ -427,187 +575,133 @@ library Writers {
|
|
|
427
575
|
bytes32 b,
|
|
428
576
|
bytes memory tail
|
|
429
577
|
) internal pure returns (uint next) {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
578
|
+
uint len = 64 + tail.length;
|
|
579
|
+
next = i + Sizes.Header + len;
|
|
580
|
+
if (i + Sizes.B64 + tail.length > dst.length) revert WriterOverflow();
|
|
581
|
+
uint p = writeHeader(dst, i, key, uint32(max32(len)));
|
|
433
582
|
assembly ("memory-safe") {
|
|
434
|
-
let p := add(add(dst, 0x20), i)
|
|
435
|
-
mstore(p, header)
|
|
436
583
|
mstore(add(p, 0x08), a)
|
|
437
584
|
mstore(add(p, 0x28), b)
|
|
438
585
|
mcopy(add(p, 0x48), add(tail, 0x20), mload(tail))
|
|
439
586
|
}
|
|
440
587
|
}
|
|
441
588
|
|
|
442
|
-
/// @notice Write a dynamic block directly into `dst` at byte offset `i`.
|
|
443
|
-
/// @param dst Destination buffer; must have at least `i + Sizes.Header + data.length` bytes.
|
|
444
|
-
/// @param i Write offset within `dst`.
|
|
445
|
-
/// @param key Block type key.
|
|
446
|
-
/// @param data Dynamic payload bytes.
|
|
447
|
-
/// @return next Byte offset immediately after the written block.
|
|
448
|
-
function write(bytes memory dst, uint i, bytes4 key, bytes memory data) internal pure returns (uint next) {
|
|
449
|
-
next = i + Sizes.Header + data.length;
|
|
450
|
-
if (next > dst.length) revert WriterOverflow();
|
|
451
|
-
uint header = toBlockHeader(key, data.length);
|
|
452
|
-
assembly ("memory-safe") {
|
|
453
|
-
let p := add(add(dst, 0x20), i)
|
|
454
|
-
mstore(p, header)
|
|
455
|
-
mcopy(add(p, 0x08), add(data, 0x20), mload(data))
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
589
|
// -------------------------------------------------------------------------
|
|
460
|
-
//
|
|
590
|
+
// Append helpers
|
|
461
591
|
// -------------------------------------------------------------------------
|
|
462
592
|
|
|
463
|
-
/// @notice
|
|
464
|
-
/// @param
|
|
465
|
-
/// @param
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
function writeBalanceBlock(bytes memory dst, uint i, AssetAmount memory value) internal pure returns (uint next) {
|
|
469
|
-
return write96(dst, i, Keys.Balance, value.asset, value.meta, bytes32(value.amount));
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
/// @notice Write an AMOUNT block directly into `dst` at byte offset `i`.
|
|
473
|
-
/// @param dst Destination buffer; must have at least `i + Sizes.Balance` bytes.
|
|
474
|
-
/// @param i Write offset within `dst`.
|
|
475
|
-
/// @param value Amount fields to encode.
|
|
476
|
-
/// @return next Byte offset immediately after the written block.
|
|
477
|
-
function writeAmountBlock(bytes memory dst, uint i, AssetAmount memory value) internal pure returns (uint next) {
|
|
478
|
-
return write96(dst, i, Keys.Amount, value.asset, value.meta, bytes32(value.amount));
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/// @notice Write an ASSET block directly into `dst` at byte offset `i`.
|
|
482
|
-
/// @param dst Destination buffer; must have at least `i + Sizes.B64` bytes.
|
|
483
|
-
/// @param i Write offset within `dst`.
|
|
484
|
-
/// @param asset Asset identifier.
|
|
485
|
-
/// @param meta Asset metadata slot.
|
|
486
|
-
/// @return next Byte offset immediately after the written block.
|
|
487
|
-
function writeAssetBlock(bytes memory dst, uint i, bytes32 asset, bytes32 meta) internal pure returns (uint next) {
|
|
488
|
-
return write64(dst, i, Keys.Asset, asset, meta);
|
|
593
|
+
/// @notice Append arbitrary bytes to the writer.
|
|
594
|
+
/// @param writer Destination writer; `i` is advanced by `data.length`.
|
|
595
|
+
/// @param data Bytes to append.
|
|
596
|
+
function append(Writer memory writer, bytes memory data) internal pure {
|
|
597
|
+
commit(writer, write(writer.dst, writer.i, data));
|
|
489
598
|
}
|
|
490
599
|
|
|
491
|
-
/// @notice
|
|
492
|
-
/// @param
|
|
493
|
-
/// @param
|
|
494
|
-
/// @param
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
function writeBountyBlock(bytes memory dst, uint i, uint amount, bytes32 relayer) internal pure returns (uint next) {
|
|
498
|
-
return write64(dst, i, Keys.Bounty, bytes32(amount), relayer);
|
|
600
|
+
/// @notice Append a raw 32-byte word without a block header.
|
|
601
|
+
/// @param writer Destination writer; `i` is advanced by `keep`.
|
|
602
|
+
/// @param value Word to append.
|
|
603
|
+
/// @param keep Number of bytes to keep from the word (1..32).
|
|
604
|
+
function append32(Writer memory writer, bytes32 value, uint keep) internal pure {
|
|
605
|
+
commit(writer, write32(writer.dst, writer.i, value, keep));
|
|
499
606
|
}
|
|
500
607
|
|
|
501
|
-
/// @notice
|
|
502
|
-
/// @param
|
|
503
|
-
/// @param
|
|
504
|
-
/// @param
|
|
505
|
-
/// @
|
|
506
|
-
function
|
|
507
|
-
|
|
608
|
+
/// @notice Append two raw 32-byte words without a block header.
|
|
609
|
+
/// @param writer Destination writer; `i` is advanced by `32 + keep`.
|
|
610
|
+
/// @param a First word to append.
|
|
611
|
+
/// @param b Second word to append.
|
|
612
|
+
/// @param keep Number of bytes to keep from the final word (1..32).
|
|
613
|
+
function append64(Writer memory writer, bytes32 a, bytes32 b, uint keep) internal pure {
|
|
614
|
+
commit(writer, write64(writer.dst, writer.i, a, b, keep));
|
|
508
615
|
}
|
|
509
616
|
|
|
510
|
-
/// @notice
|
|
511
|
-
/// @param
|
|
512
|
-
/// @param
|
|
513
|
-
/// @param
|
|
514
|
-
/// @
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
i,
|
|
519
|
-
Keys.Transaction,
|
|
520
|
-
bytes32(value.from),
|
|
521
|
-
bytes32(value.to),
|
|
522
|
-
value.asset,
|
|
523
|
-
value.meta,
|
|
524
|
-
bytes32(value.amount)
|
|
525
|
-
);
|
|
617
|
+
/// @notice Append three raw 32-byte words without a block header.
|
|
618
|
+
/// @param writer Destination writer; `i` is advanced by `64 + keep`.
|
|
619
|
+
/// @param a First word to append.
|
|
620
|
+
/// @param b Second word to append.
|
|
621
|
+
/// @param c Third word to append.
|
|
622
|
+
/// @param keep Number of bytes to keep from the final word (1..32).
|
|
623
|
+
function append96(Writer memory writer, bytes32 a, bytes32 b, bytes32 c, uint keep) internal pure {
|
|
624
|
+
commit(writer, write96(writer.dst, writer.i, a, b, c, keep));
|
|
526
625
|
}
|
|
527
626
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
/// @param data Bytes to append.
|
|
535
|
-
function append(Writer memory writer, bytes memory data) internal pure {
|
|
536
|
-
uint next = writer.i + data.length;
|
|
537
|
-
if (next > writer.dst.length) revert WriterOverflow();
|
|
538
|
-
// Copy `data` into `dst` starting at the current write position.
|
|
539
|
-
assembly ("memory-safe") {
|
|
540
|
-
mcopy(add(add(mload(add(writer, 0x40)), 0x20), mload(writer)), add(data, 0x20), mload(data))
|
|
541
|
-
}
|
|
542
|
-
writer.i = next;
|
|
627
|
+
/// @notice Append a dynamic block.
|
|
628
|
+
/// @param writer Destination writer; `i` is advanced by `Sizes.Header + data.length`.
|
|
629
|
+
/// @param key Block type key.
|
|
630
|
+
/// @param data Dynamic payload bytes.
|
|
631
|
+
function appendBlock(Writer memory writer, bytes4 key, bytes memory data) internal pure {
|
|
632
|
+
commit(writer, writeBlock(writer.dst, writer.i, key, data));
|
|
543
633
|
}
|
|
544
634
|
|
|
545
635
|
/// @notice Append a fixed-width 32-byte-payload block.
|
|
546
|
-
/// @param writer Destination writer; `i` is advanced by
|
|
636
|
+
/// @param writer Destination writer; `i` is advanced by the kept logical block length.
|
|
547
637
|
/// @param key Block type key.
|
|
548
638
|
/// @param a First payload word.
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
/// @notice Append an ABI-style boolean as a 32-byte scalar payload block.
|
|
554
|
-
/// Encodes `false` as `bytes32(0)` and `true` as `bytes32(uint(1))`.
|
|
555
|
-
/// @param writer Destination writer; `i` is advanced by `Sizes.B32`.
|
|
556
|
-
/// @param key Block type key.
|
|
557
|
-
/// @param value Boolean value to encode.
|
|
558
|
-
function appendBool(Writer memory writer, bytes4 key, bool value) internal pure {
|
|
559
|
-
writer.i = writeBool(writer.dst, writer.i, key, value);
|
|
639
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
640
|
+
function appendBlock32(Writer memory writer, bytes4 key, bytes32 a, uint keep) internal pure {
|
|
641
|
+
commit(writer, writeBlock32(writer.dst, writer.i, key, a, keep));
|
|
560
642
|
}
|
|
561
643
|
|
|
562
|
-
|
|
563
644
|
/// @notice Append a fixed-width 64-byte-payload block.
|
|
564
|
-
/// @param writer Destination writer; `i` is advanced by
|
|
645
|
+
/// @param writer Destination writer; `i` is advanced by the kept logical block length.
|
|
565
646
|
/// @param key Block type key.
|
|
566
647
|
/// @param a First payload word.
|
|
567
648
|
/// @param b Second payload word.
|
|
568
|
-
|
|
569
|
-
|
|
649
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
650
|
+
function appendBlock64(Writer memory writer, bytes4 key, bytes32 a, bytes32 b, uint keep) internal pure {
|
|
651
|
+
commit(writer, writeBlock64(writer.dst, writer.i, key, a, b, keep));
|
|
570
652
|
}
|
|
571
653
|
|
|
572
654
|
/// @notice Append a fixed-width 96-byte-payload block.
|
|
573
|
-
/// @param writer Destination writer; `i` is advanced by
|
|
655
|
+
/// @param writer Destination writer; `i` is advanced by the kept logical block length.
|
|
574
656
|
/// @param key Block type key.
|
|
575
657
|
/// @param a First payload word.
|
|
576
658
|
/// @param b Second payload word.
|
|
577
659
|
/// @param c Third payload word.
|
|
578
|
-
|
|
579
|
-
|
|
660
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
661
|
+
function appendBlock96(Writer memory writer, bytes4 key, bytes32 a, bytes32 b, bytes32 c, uint keep) internal pure {
|
|
662
|
+
commit(writer, writeBlock96(writer.dst, writer.i, key, a, b, c, keep));
|
|
580
663
|
}
|
|
581
664
|
|
|
582
665
|
/// @notice Append a fixed-width 128-byte-payload block.
|
|
583
|
-
/// @param writer Destination writer; `i` is advanced by
|
|
666
|
+
/// @param writer Destination writer; `i` is advanced by the kept logical block length.
|
|
584
667
|
/// @param key Block type key.
|
|
585
668
|
/// @param a First payload word.
|
|
586
669
|
/// @param b Second payload word.
|
|
587
670
|
/// @param c Third payload word.
|
|
588
671
|
/// @param d Fourth payload word.
|
|
589
|
-
|
|
590
|
-
|
|
672
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
673
|
+
function appendBlock128(
|
|
674
|
+
Writer memory writer,
|
|
675
|
+
bytes4 key,
|
|
676
|
+
bytes32 a,
|
|
677
|
+
bytes32 b,
|
|
678
|
+
bytes32 c,
|
|
679
|
+
bytes32 d,
|
|
680
|
+
uint keep
|
|
681
|
+
) internal pure {
|
|
682
|
+
commit(writer, writeBlock128(writer.dst, writer.i, key, a, b, c, d, keep));
|
|
591
683
|
}
|
|
592
684
|
|
|
593
685
|
/// @notice Append a fixed-width 160-byte-payload block.
|
|
594
|
-
/// @param writer Destination writer; `i` is advanced by
|
|
686
|
+
/// @param writer Destination writer; `i` is advanced by the kept logical block length.
|
|
595
687
|
/// @param key Block type key.
|
|
596
688
|
/// @param a First payload word.
|
|
597
689
|
/// @param b Second payload word.
|
|
598
690
|
/// @param c Third payload word.
|
|
599
691
|
/// @param d Fourth payload word.
|
|
600
692
|
/// @param e Fifth payload word.
|
|
601
|
-
|
|
693
|
+
/// @param keep Number of bytes to keep from the final payload word (1..32).
|
|
694
|
+
function appendBlock160(
|
|
602
695
|
Writer memory writer,
|
|
603
696
|
bytes4 key,
|
|
604
697
|
bytes32 a,
|
|
605
698
|
bytes32 b,
|
|
606
699
|
bytes32 c,
|
|
607
700
|
bytes32 d,
|
|
608
|
-
bytes32 e
|
|
701
|
+
bytes32 e,
|
|
702
|
+
uint keep
|
|
609
703
|
) internal pure {
|
|
610
|
-
writer
|
|
704
|
+
commit(writer, writeBlock160(writer.dst, writer.i, key, a, b, c, d, e, keep));
|
|
611
705
|
}
|
|
612
706
|
|
|
613
707
|
/// @notice Append a dynamic block with a fixed 32-byte head word.
|
|
@@ -615,8 +709,8 @@ library Writers {
|
|
|
615
709
|
/// @param key Block type key.
|
|
616
710
|
/// @param a Fixed head word.
|
|
617
711
|
/// @param tail Dynamic payload bytes appended after the head.
|
|
618
|
-
function
|
|
619
|
-
writer
|
|
712
|
+
function appendBlockHead32(Writer memory writer, bytes4 key, bytes32 a, bytes memory tail) internal pure {
|
|
713
|
+
commit(writer, writeBlockHead32(writer.dst, writer.i, key, a, tail));
|
|
620
714
|
}
|
|
621
715
|
|
|
622
716
|
/// @notice Append a dynamic block with a fixed 64-byte head.
|
|
@@ -625,16 +719,21 @@ library Writers {
|
|
|
625
719
|
/// @param a First fixed head word.
|
|
626
720
|
/// @param b Second fixed head word.
|
|
627
721
|
/// @param tail Dynamic payload bytes appended after the head.
|
|
628
|
-
function
|
|
629
|
-
|
|
722
|
+
function appendBlockHead64(
|
|
723
|
+
Writer memory writer,
|
|
724
|
+
bytes4 key,
|
|
725
|
+
bytes32 a,
|
|
726
|
+
bytes32 b,
|
|
727
|
+
bytes memory tail
|
|
728
|
+
) internal pure {
|
|
729
|
+
commit(writer, writeBlockHead64(writer.dst, writer.i, key, a, b, tail));
|
|
630
730
|
}
|
|
631
731
|
|
|
632
|
-
/// @notice Append a
|
|
633
|
-
/// @param writer Destination writer; `i` is advanced by `Sizes.
|
|
634
|
-
/// @param
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
writer.i = write(writer.dst, writer.i, key, data);
|
|
732
|
+
/// @notice Append a STATUS form block.
|
|
733
|
+
/// @param writer Destination writer; `i` is advanced by `Sizes.B32`.
|
|
734
|
+
/// @param ok Status value to encode.
|
|
735
|
+
function appendStatus(Writer memory writer, bool ok) internal pure {
|
|
736
|
+
commit(writer, writeBlock32(writer.dst, writer.i, Keys.Status, ok ? bytes32(uint(1)) : bytes32(0), 32));
|
|
638
737
|
}
|
|
639
738
|
|
|
640
739
|
/// @notice Append a BALANCE block using separate field values.
|
|
@@ -643,14 +742,17 @@ library Writers {
|
|
|
643
742
|
/// @param meta Asset metadata slot.
|
|
644
743
|
/// @param amount Token amount.
|
|
645
744
|
function appendBalance(Writer memory writer, bytes32 asset, bytes32 meta, uint amount) internal pure {
|
|
646
|
-
|
|
745
|
+
commit(writer, writeBlock96(writer.dst, writer.i, Keys.Balance, asset, meta, bytes32(amount), 32));
|
|
647
746
|
}
|
|
648
747
|
|
|
649
748
|
/// @notice Append a BALANCE block from a struct.
|
|
650
749
|
/// @param writer Destination writer; `i` is advanced by `Sizes.Balance`.
|
|
651
750
|
/// @param value Balance fields to encode.
|
|
652
751
|
function appendBalance(Writer memory writer, AssetAmount memory value) internal pure {
|
|
653
|
-
|
|
752
|
+
commit(
|
|
753
|
+
writer,
|
|
754
|
+
writeBlock96(writer.dst, writer.i, Keys.Balance, value.asset, value.meta, bytes32(value.amount), 32)
|
|
755
|
+
);
|
|
654
756
|
}
|
|
655
757
|
|
|
656
758
|
/// @notice Append an AMOUNT block using separate field values.
|
|
@@ -659,38 +761,63 @@ library Writers {
|
|
|
659
761
|
/// @param meta Asset metadata slot.
|
|
660
762
|
/// @param amount Token amount.
|
|
661
763
|
function appendAmount(Writer memory writer, bytes32 asset, bytes32 meta, uint amount) internal pure {
|
|
662
|
-
|
|
764
|
+
commit(writer, writeBlock96(writer.dst, writer.i, Keys.Amount, asset, meta, bytes32(amount), 32));
|
|
663
765
|
}
|
|
664
766
|
|
|
665
767
|
/// @notice Append an AMOUNT block from a struct.
|
|
666
768
|
/// @param writer Destination writer; `i` is advanced by `Sizes.Balance`.
|
|
667
769
|
/// @param value Amount fields to encode.
|
|
668
770
|
function appendAmount(Writer memory writer, AssetAmount memory value) internal pure {
|
|
669
|
-
|
|
771
|
+
commit(
|
|
772
|
+
writer,
|
|
773
|
+
writeBlock96(writer.dst, writer.i, Keys.Amount, value.asset, value.meta, bytes32(value.amount), 32)
|
|
774
|
+
);
|
|
670
775
|
}
|
|
671
776
|
|
|
672
|
-
/// @notice Append an
|
|
673
|
-
/// @param writer Destination writer; `i` is advanced by `Sizes.
|
|
777
|
+
/// @notice Append an ACCOUNT_AMOUNT form block using separate field values.
|
|
778
|
+
/// @param writer Destination writer; `i` is advanced by `Sizes.B128`.
|
|
779
|
+
/// @param account Account identifier.
|
|
674
780
|
/// @param asset Asset identifier.
|
|
675
781
|
/// @param meta Asset metadata slot.
|
|
676
|
-
|
|
677
|
-
|
|
782
|
+
/// @param amount Token amount.
|
|
783
|
+
function appendAccountAmount(
|
|
784
|
+
Writer memory writer,
|
|
785
|
+
bytes32 account,
|
|
786
|
+
bytes32 asset,
|
|
787
|
+
bytes32 meta,
|
|
788
|
+
uint amount
|
|
789
|
+
) internal pure {
|
|
790
|
+
commit(
|
|
791
|
+
writer,
|
|
792
|
+
writeBlock128(writer.dst, writer.i, Keys.AccountAmount, account, asset, meta, bytes32(amount), 32)
|
|
793
|
+
);
|
|
678
794
|
}
|
|
679
795
|
|
|
680
|
-
/// @notice Append
|
|
681
|
-
/// @param writer Destination writer.
|
|
682
|
-
/// @param
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
796
|
+
/// @notice Append an ACCOUNT_AMOUNT form block from a struct.
|
|
797
|
+
/// @param writer Destination writer; `i` is advanced by `Sizes.B128`.
|
|
798
|
+
/// @param value Account amount fields to encode.
|
|
799
|
+
function appendAccountAmount(Writer memory writer, AccountAmount memory value) internal pure {
|
|
800
|
+
commit(
|
|
801
|
+
writer,
|
|
802
|
+
writeBlock128(
|
|
803
|
+
writer.dst,
|
|
804
|
+
writer.i,
|
|
805
|
+
Keys.AccountAmount,
|
|
806
|
+
value.account,
|
|
807
|
+
value.asset,
|
|
808
|
+
value.meta,
|
|
809
|
+
bytes32(value.amount),
|
|
810
|
+
32
|
|
811
|
+
)
|
|
812
|
+
);
|
|
687
813
|
}
|
|
688
814
|
|
|
689
|
-
/// @notice Append
|
|
690
|
-
/// @param writer Destination writer.
|
|
691
|
-
/// @param
|
|
692
|
-
|
|
693
|
-
|
|
815
|
+
/// @notice Append an ASSET block.
|
|
816
|
+
/// @param writer Destination writer; `i` is advanced by `Sizes.B64`.
|
|
817
|
+
/// @param asset Asset identifier.
|
|
818
|
+
/// @param meta Asset metadata slot.
|
|
819
|
+
function appendAsset(Writer memory writer, bytes32 asset, bytes32 meta) internal pure {
|
|
820
|
+
commit(writer, writeBlock64(writer.dst, writer.i, Keys.Asset, asset, meta, 32));
|
|
694
821
|
}
|
|
695
822
|
|
|
696
823
|
/// @notice Append a BOUNTY block to the writer.
|
|
@@ -698,31 +825,79 @@ library Writers {
|
|
|
698
825
|
/// @param amount Relayer reward amount.
|
|
699
826
|
/// @param relayer Relayer account identifier.
|
|
700
827
|
function appendBounty(Writer memory writer, uint amount, bytes32 relayer) internal pure {
|
|
701
|
-
writer
|
|
828
|
+
commit(writer, writeBlock64(writer.dst, writer.i, Keys.Bounty, bytes32(amount), relayer, 32));
|
|
702
829
|
}
|
|
703
830
|
|
|
704
831
|
/// @notice Append a CUSTODY block using separate field values.
|
|
705
|
-
/// @param writer Destination writer; `i` is advanced by `Sizes.
|
|
832
|
+
/// @param writer Destination writer; `i` is advanced by `Sizes.HostAmount`.
|
|
706
833
|
/// @param host Host node ID.
|
|
707
834
|
/// @param asset Asset identifier.
|
|
708
835
|
/// @param meta Asset metadata slot.
|
|
709
836
|
/// @param amount Token amount.
|
|
710
837
|
function appendCustody(Writer memory writer, uint host, bytes32 asset, bytes32 meta, uint amount) internal pure {
|
|
711
|
-
|
|
838
|
+
commit(
|
|
839
|
+
writer,
|
|
840
|
+
writeBlock128(writer.dst, writer.i, Keys.Custody, bytes32(host), asset, meta, bytes32(amount), 32)
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/// @notice Append a CUSTODY block from a host and asset amount.
|
|
845
|
+
/// @param writer Destination writer; `i` is advanced by `Sizes.HostAmount`.
|
|
846
|
+
/// @param host Host node ID.
|
|
847
|
+
/// @param value Custody fields to encode.
|
|
848
|
+
function appendCustody(Writer memory writer, uint host, AssetAmount memory value) internal pure {
|
|
849
|
+
commit(
|
|
850
|
+
writer,
|
|
851
|
+
writeBlock128(
|
|
852
|
+
writer.dst,
|
|
853
|
+
writer.i,
|
|
854
|
+
Keys.Custody,
|
|
855
|
+
bytes32(host),
|
|
856
|
+
value.asset,
|
|
857
|
+
value.meta,
|
|
858
|
+
bytes32(value.amount),
|
|
859
|
+
32
|
|
860
|
+
)
|
|
861
|
+
);
|
|
712
862
|
}
|
|
713
863
|
|
|
714
|
-
/// @notice Append a CUSTODY block from a struct.
|
|
715
|
-
/// @param writer Destination writer; `i` is advanced by `Sizes.
|
|
864
|
+
/// @notice Append a CUSTODY block from a host amount struct.
|
|
865
|
+
/// @param writer Destination writer; `i` is advanced by `Sizes.HostAmount`.
|
|
716
866
|
/// @param value Custody fields to encode.
|
|
717
867
|
function appendCustody(Writer memory writer, HostAmount memory value) internal pure {
|
|
718
|
-
|
|
868
|
+
commit(
|
|
869
|
+
writer,
|
|
870
|
+
writeBlock128(
|
|
871
|
+
writer.dst,
|
|
872
|
+
writer.i,
|
|
873
|
+
Keys.Custody,
|
|
874
|
+
bytes32(value.host),
|
|
875
|
+
value.asset,
|
|
876
|
+
value.meta,
|
|
877
|
+
bytes32(value.amount),
|
|
878
|
+
32
|
|
879
|
+
)
|
|
880
|
+
);
|
|
719
881
|
}
|
|
720
882
|
|
|
721
883
|
/// @notice Append a TRANSACTION block from a struct.
|
|
722
884
|
/// @param writer Destination writer; `i` is advanced by `Sizes.Transaction`.
|
|
723
885
|
/// @param value Transfer record fields to encode.
|
|
724
|
-
function
|
|
725
|
-
|
|
886
|
+
function appendTransaction(Writer memory writer, Tx memory value) internal pure {
|
|
887
|
+
commit(
|
|
888
|
+
writer,
|
|
889
|
+
writeBlock160(
|
|
890
|
+
writer.dst,
|
|
891
|
+
writer.i,
|
|
892
|
+
Keys.Transaction,
|
|
893
|
+
bytes32(value.from),
|
|
894
|
+
bytes32(value.to),
|
|
895
|
+
value.asset,
|
|
896
|
+
value.meta,
|
|
897
|
+
bytes32(value.amount),
|
|
898
|
+
32
|
|
899
|
+
)
|
|
900
|
+
);
|
|
726
901
|
}
|
|
727
902
|
|
|
728
903
|
// -------------------------------------------------------------------------
|
|
@@ -735,7 +910,7 @@ library Writers {
|
|
|
735
910
|
/// @return out The written block stream; length equals `writer.i`.
|
|
736
911
|
function finish(Writer memory writer) internal pure returns (bytes memory out) {
|
|
737
912
|
if (writer.i == 0) revert EmptyRequest();
|
|
738
|
-
if (writer.i > writer.dst.length) revert IncompleteWriter();
|
|
913
|
+
if (writer.i > writer.end || writer.i > writer.dst.length) revert IncompleteWriter();
|
|
739
914
|
out = writer.dst;
|
|
740
915
|
// Overwrite the memory length word of `out` with the actual written length.
|
|
741
916
|
assembly ("memory-safe") {
|