@rootzero/contracts 1.15.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +90 -0
- package/Codec.sol +1 -1
- package/Commands.sol +1 -1
- package/Core.sol +4 -4
- package/Endpoints.sol +9 -7
- package/Events.sol +0 -1
- package/README.md +88 -30
- package/Utils.sol +1 -1
- package/codec/Blocks.sol +111 -21
- package/codec/Buffers.sol +3 -3
- package/codec/Decoders.sol +48 -10
- package/codec/Descriptors.sol +0 -1
- package/codec/Keys.sol +4 -2
- package/codec/Readers.sol +25 -0
- package/codec/Schema.sol +6 -1
- package/codec/Specs.sol +7 -2
- package/codec/Writers.sol +28 -2
- package/commands/Base.sol +8 -15
- package/commands/Burn.sol +2 -2
- package/commands/Credit.sol +38 -3
- package/commands/Debit.sol +50 -14
- package/commands/Deposit.sol +4 -4
- package/commands/Provision.sol +4 -4
- package/commands/Recover.sol +15 -8
- package/commands/Relay.sol +37 -12
- package/commands/Settle.sol +130 -0
- package/commands/Withdraw.sol +2 -2
- package/commands/admin/AllowAssets.sol +2 -2
- package/commands/admin/Allowance.sol +3 -3
- package/commands/admin/Annotate.sol +2 -2
- package/commands/admin/Appoint.sol +2 -2
- package/commands/admin/Authorize.sol +2 -2
- package/commands/admin/DenyAssets.sol +2 -2
- package/commands/admin/Dismiss.sol +2 -2
- package/commands/admin/Execute.sol +3 -3
- package/commands/admin/Unauthorize.sol +2 -2
- package/core/Endpoint.sol +15 -13
- package/core/Pipeline.sol +6 -6
- package/core/Settlement.sol +37 -8
- package/core/Types.sol +21 -1
- package/docs/Schema.md +52 -2
- package/execution/Budget.sol +12 -4
- package/execution/Execution.sol +119 -11
- package/guards/Base.sol +2 -2
- package/guards/Revoke.sol +21 -0
- package/package.json +1 -1
- package/ports/Base.sol +2 -2
- package/ports/Dispatch.sol +6 -6
- package/ports/{Settle.sol → Post.sol} +10 -10
- package/queries/Base.sol +2 -2
- package/utils/Actions.sol +1 -0
- package/utils/Cursors.sol +16 -30
- package/events/Position.sol +0 -22
package/execution/Execution.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, Tx} from "../core/Types.sol";
|
|
4
|
+
import {AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, Position, Tx} from "../core/Types.sol";
|
|
5
5
|
import {Blocks} from "../codec/Blocks.sol";
|
|
6
6
|
import {Buffers} from "../codec/Buffers.sol";
|
|
7
7
|
import {Sizes, Specs} from "../codec/Specs.sol";
|
|
@@ -9,6 +9,7 @@ import {Descriptors} from "../codec/Descriptors.sol";
|
|
|
9
9
|
import {Cursors, Cur} from "../utils/Cursors.sol";
|
|
10
10
|
import {Lanes} from "../utils/Lanes.sol";
|
|
11
11
|
import {Budget} from "./Budget.sol";
|
|
12
|
+
import {max16} from "../utils/Utils.sol";
|
|
12
13
|
|
|
13
14
|
/// @notice Mutable state shared across one endpoint execution.
|
|
14
15
|
/// @dev `decoders` contains tagged input and state cursor lanes. Cursor operations
|
|
@@ -28,6 +29,10 @@ library Executions {
|
|
|
28
29
|
|
|
29
30
|
/// @dev Thrown when an execution attempts to spend more value than remains in its budget.
|
|
30
31
|
error InsufficientValue();
|
|
32
|
+
/// @dev Decoder block counts do not form compatible descriptor groups.
|
|
33
|
+
error BadRatio();
|
|
34
|
+
/// @dev A descriptor-empty lane received a non-empty block source.
|
|
35
|
+
error ZeroStride();
|
|
31
36
|
|
|
32
37
|
// -------------------------------------------------------------------------
|
|
33
38
|
// Opening
|
|
@@ -37,15 +42,39 @@ library Executions {
|
|
|
37
42
|
/// @param source Calldata source for the decoder lane.
|
|
38
43
|
/// @param descriptor Packed endpoint descriptor.
|
|
39
44
|
/// @param lane Input or state lane identifier.
|
|
40
|
-
/// @return cur Tagged packed decoder cursor, or zero for an absent lane.
|
|
45
|
+
/// @return cur Tagged packed decoder cursor carrying its raw block count, or zero for an absent lane.
|
|
41
46
|
function openDecoder(bytes calldata source, uint descriptor, uint8 lane) private pure returns (uint cur) {
|
|
42
47
|
uint stride = Descriptors.stride(descriptor, lane);
|
|
43
48
|
(uint abs, uint limit) = Cursors.bounds(source);
|
|
44
49
|
if (stride == 0 && abs == limit) return 0;
|
|
50
|
+
if (stride == 0) revert ZeroStride();
|
|
45
51
|
|
|
46
|
-
bytes4 key =
|
|
47
|
-
(uint
|
|
48
|
-
|
|
52
|
+
bytes4 key = Descriptors.key(descriptor, lane);
|
|
53
|
+
(uint count, uint end) = Blocks.runExact(abs, limit, key);
|
|
54
|
+
if (count == 0) revert Blocks.EmptyRun();
|
|
55
|
+
cur = Cursors.create(abs, end - abs, count, 0, lane);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// @dev Convert one decoder lane's raw block count into descriptor groups.
|
|
59
|
+
function groupCount(uint decoders, uint descriptor, uint8 lane) private pure returns (uint groups) {
|
|
60
|
+
uint stride = Descriptors.stride(descriptor, lane);
|
|
61
|
+
if (stride == 0) return 0;
|
|
62
|
+
|
|
63
|
+
uint count = decoders.select(lane).count();
|
|
64
|
+
if (count % stride != 0) revert BadRatio();
|
|
65
|
+
groups = count / stride;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// @dev Reconcile decoder lane groups once at endpoint execution opening.
|
|
69
|
+
function reconcile(uint decoders, uint descriptor, uint expected) private pure returns (uint groups) {
|
|
70
|
+
uint input = groupCount(decoders, descriptor, Lanes.Input);
|
|
71
|
+
uint state = groupCount(decoders, descriptor, Lanes.State);
|
|
72
|
+
if (input != 0 && state != 0 && input != state) revert BadRatio();
|
|
73
|
+
|
|
74
|
+
groups = input != 0 ? input : state;
|
|
75
|
+
if (groups != 0 && expected != 0 && groups != expected) revert BadRatio();
|
|
76
|
+
if (groups == 0) groups = expected;
|
|
77
|
+
max16(groups);
|
|
49
78
|
}
|
|
50
79
|
|
|
51
80
|
/// @dev Initialize one tagged writer cursor from a descriptor lane.
|
|
@@ -58,7 +87,9 @@ library Executions {
|
|
|
58
87
|
(uint capacity, bool growable) = Descriptors.allocation(descriptor, lane, batches);
|
|
59
88
|
if (capacity == 0) return 0;
|
|
60
89
|
|
|
61
|
-
|
|
90
|
+
uint count = batches * Descriptors.stride(descriptor, lane);
|
|
91
|
+
if (padding != 0) count += padding / Sizes.Transaction;
|
|
92
|
+
cur = Buffers.cursor(capacity + padding, count, growable, lane);
|
|
62
93
|
}
|
|
63
94
|
|
|
64
95
|
/// @dev Open and pair the input and state decoder cursors.
|
|
@@ -91,7 +122,7 @@ library Executions {
|
|
|
91
122
|
function open(uint decoders, uint descriptor, uint batches) private view returns (Execution memory exec) {
|
|
92
123
|
exec.budget = msg.value;
|
|
93
124
|
exec.decoders = decoders;
|
|
94
|
-
batches =
|
|
125
|
+
batches = reconcile(decoders, descriptor, batches);
|
|
95
126
|
exec.writers = writerCursors(descriptor, batches);
|
|
96
127
|
}
|
|
97
128
|
|
|
@@ -256,6 +287,31 @@ library Executions {
|
|
|
256
287
|
(value.account, value.asset) = unpackAccountAsset(exec, lane);
|
|
257
288
|
}
|
|
258
289
|
|
|
290
|
+
/// @notice Decode and consume one HOST_ASSET block from `lane`.
|
|
291
|
+
/// @param exec Execution whose decoder is advanced.
|
|
292
|
+
/// @param lane Decoder lane to consume.
|
|
293
|
+
/// @return host Decoded host identifier.
|
|
294
|
+
/// @return asset Decoded asset identifier.
|
|
295
|
+
function unpackHostAsset(
|
|
296
|
+
Execution memory exec,
|
|
297
|
+
uint8 lane
|
|
298
|
+
) internal pure returns (uint host, bytes32 asset) {
|
|
299
|
+
uint abs;
|
|
300
|
+
(exec.decoders, abs) = exec.decoders.consume(lane, Sizes.HostAsset);
|
|
301
|
+
(host, asset) = Blocks.unpackHostAsset(abs);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/// @notice Decode one HOST_ASSET block into its structured value.
|
|
305
|
+
/// @param exec Execution whose decoder is advanced.
|
|
306
|
+
/// @param lane Decoder lane to consume.
|
|
307
|
+
/// @return value Decoded host and asset.
|
|
308
|
+
function unpackHostAssetValue(
|
|
309
|
+
Execution memory exec,
|
|
310
|
+
uint8 lane
|
|
311
|
+
) internal pure returns (HostAsset memory value) {
|
|
312
|
+
(value.host, value.asset) = unpackHostAsset(exec, lane);
|
|
313
|
+
}
|
|
314
|
+
|
|
259
315
|
/// @notice Decode and consume one AMOUNT block from `lane`.
|
|
260
316
|
/// @param exec Execution whose decoder is advanced.
|
|
261
317
|
/// @param lane Decoder lane to consume.
|
|
@@ -294,6 +350,24 @@ library Executions {
|
|
|
294
350
|
(value.asset, value.amount) = unpackBalance(exec, lane);
|
|
295
351
|
}
|
|
296
352
|
|
|
353
|
+
/// @notice Decode and consume one POSITION block from `lane`.
|
|
354
|
+
function unpackPosition(
|
|
355
|
+
Execution memory exec,
|
|
356
|
+
uint8 lane
|
|
357
|
+
) internal pure returns (bytes32 asset, uint amount, bytes32 liability, uint debt) {
|
|
358
|
+
uint abs;
|
|
359
|
+
(exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Position);
|
|
360
|
+
(asset, amount, liability, debt) = Blocks.unpackPosition(abs);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/// @notice Decode one POSITION block into its structured value.
|
|
364
|
+
function unpackPositionValue(
|
|
365
|
+
Execution memory exec,
|
|
366
|
+
uint8 lane
|
|
367
|
+
) internal pure returns (Position memory value) {
|
|
368
|
+
(value.asset, value.amount, value.liability, value.debt) = unpackPosition(exec, lane);
|
|
369
|
+
}
|
|
370
|
+
|
|
297
371
|
/// @notice Decode one BALANCE block and associate it with `host`.
|
|
298
372
|
/// @param exec Execution whose decoder is advanced.
|
|
299
373
|
/// @param lane Decoder lane to consume.
|
|
@@ -730,6 +804,23 @@ library Executions {
|
|
|
730
804
|
outputBalance(exec, value.asset, value.amount);
|
|
731
805
|
}
|
|
732
806
|
|
|
807
|
+
/// @notice Append a POSITION block to execution output.
|
|
808
|
+
function outputPosition(
|
|
809
|
+
Execution memory exec,
|
|
810
|
+
bytes32 asset,
|
|
811
|
+
uint amount,
|
|
812
|
+
bytes32 liability,
|
|
813
|
+
uint debt
|
|
814
|
+
) internal pure {
|
|
815
|
+
uint i = reserve(exec, Sizes.Position);
|
|
816
|
+
Blocks.writePosition(exec.output, i, asset, amount, liability, debt);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/// @notice Append a structured POSITION value to execution output.
|
|
820
|
+
function outputPosition(Execution memory exec, Position memory value) internal pure {
|
|
821
|
+
outputPosition(exec, value.asset, value.amount, value.liability, value.debt);
|
|
822
|
+
}
|
|
823
|
+
|
|
733
824
|
/// @notice Append an ACCOUNT_ASSET block to execution output.
|
|
734
825
|
/// @param exec Execution receiving the block.
|
|
735
826
|
/// @param account Account identifier to encode.
|
|
@@ -739,6 +830,15 @@ library Executions {
|
|
|
739
830
|
Blocks.writeAccountAsset(exec.output, i, account, asset);
|
|
740
831
|
}
|
|
741
832
|
|
|
833
|
+
/// @notice Append a HOST_ASSET block to execution output.
|
|
834
|
+
/// @param exec Execution receiving the block.
|
|
835
|
+
/// @param host Host identifier to encode.
|
|
836
|
+
/// @param asset Asset identifier to encode.
|
|
837
|
+
function outputHostAsset(Execution memory exec, uint host, bytes32 asset) internal pure {
|
|
838
|
+
uint i = reserve(exec, Sizes.HostAsset);
|
|
839
|
+
Blocks.writeHostAsset(exec.output, i, host, asset);
|
|
840
|
+
}
|
|
841
|
+
|
|
742
842
|
/// @notice Append an ALLOCATION block to execution output.
|
|
743
843
|
/// @param exec Execution receiving the block.
|
|
744
844
|
/// @param host Host identifier to encode.
|
|
@@ -1010,15 +1110,23 @@ library Executions {
|
|
|
1010
1110
|
exec.budget = 0;
|
|
1011
1111
|
}
|
|
1012
1112
|
|
|
1113
|
+
/// @notice Deduct an exact native value from the execution budget.
|
|
1114
|
+
/// @param exec Mutable execution whose budget is charged.
|
|
1115
|
+
/// @param value Native value to consume in wei.
|
|
1116
|
+
/// @return The consumed native value.
|
|
1117
|
+
function useValue(Execution memory exec, uint value) internal pure returns (uint) {
|
|
1118
|
+
if (value > exec.budget) revert InsufficientValue();
|
|
1119
|
+
exec.budget -= value;
|
|
1120
|
+
return value;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1013
1123
|
/// @notice Deduct the EVM value lane of `resources` from the execution budget.
|
|
1014
1124
|
/// @dev EVM resources use the low 128 bits as native value/endowment.
|
|
1015
1125
|
/// @param exec Mutable execution whose budget is charged.
|
|
1016
1126
|
/// @param resources Packed resources whose value lane should be spent.
|
|
1017
1127
|
/// @return value Native value to forward in wei.
|
|
1018
|
-
function
|
|
1019
|
-
|
|
1020
|
-
if (value > exec.budget) revert InsufficientValue();
|
|
1021
|
-
exec.budget -= value;
|
|
1128
|
+
function useResourceValue(Execution memory exec, uint resources) internal pure returns (uint128) {
|
|
1129
|
+
return uint128(useValue(exec, uint128(resources)));
|
|
1022
1130
|
}
|
|
1023
1131
|
|
|
1024
1132
|
/// @notice Append a deferred transaction to the transaction writer lane.
|
package/guards/Base.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {InputEndpointBase} from "../core/Endpoint.sol";
|
|
5
5
|
import {GuardianAccess} from "../core/Access.sol";
|
|
6
6
|
import {Specs} from "../codec/Specs.sol";
|
|
7
7
|
import {Nodes} from "../utils/Nodes.sol";
|
|
@@ -10,7 +10,7 @@ import {Selectors} from "../utils/Selectors.sol";
|
|
|
10
10
|
/// @title GuardBase
|
|
11
11
|
/// @notice Abstract base for guardian-only direct host actions.
|
|
12
12
|
/// Guard actions are non-payable direct calls with no command context, state, or response.
|
|
13
|
-
abstract contract GuardBase is GuardianAccess,
|
|
13
|
+
abstract contract GuardBase is GuardianAccess, InputEndpointBase {
|
|
14
14
|
/// @dev Restrict execution to active guardian addresses.
|
|
15
15
|
modifier onlyGuardian() {
|
|
16
16
|
enforceGuardian(msg.sender);
|
package/guards/Revoke.sol
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
+
import {AllowanceHook} from "../commands/admin/Allowance.sol";
|
|
4
5
|
import {GuardBase} from "./Base.sol";
|
|
5
6
|
import {Specs} from "../Codec.sol";
|
|
6
7
|
import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
@@ -25,6 +26,26 @@ abstract contract Revoke is GuardBase {
|
|
|
25
26
|
uint node = exec.unpackNode(Lanes.Input);
|
|
26
27
|
setNode(node, false);
|
|
27
28
|
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// @title RevokeAllowance
|
|
33
|
+
/// @notice Guardian action that revokes host-scoped asset allowances.
|
|
34
|
+
/// @dev Opt-in guard. Hosts expose it by inheriting this contract and implementing AllowanceHook.
|
|
35
|
+
abstract contract RevokeAllowance is GuardBase, AllowanceHook {
|
|
36
|
+
uint private immutable descriptor;
|
|
28
37
|
|
|
38
|
+
constructor() {
|
|
39
|
+
(, descriptor) = guard("revokeAllowance", Specs.HostAsset);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// @notice Revoke every HOST_ASSET allowance in `input` as the active guardian.
|
|
43
|
+
function revokeAllowance(bytes calldata input) external onlyGuardian {
|
|
44
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
45
|
+
|
|
46
|
+
while (exec.more()) {
|
|
47
|
+
(uint peer, bytes32 asset) = exec.unpackHostAsset(Lanes.Input);
|
|
48
|
+
allowance(peer, asset, 0);
|
|
49
|
+
}
|
|
29
50
|
}
|
|
30
51
|
}
|
package/package.json
CHANGED
package/ports/Base.sol
CHANGED
|
@@ -4,7 +4,7 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
import { NodeCalls } from "../core/Calls.sol";
|
|
5
5
|
import { NodeAccess } from "../core/Access.sol";
|
|
6
6
|
import { Specs } from "../codec/Specs.sol";
|
|
7
|
-
import {
|
|
7
|
+
import { InputEndpointBase } from "../core/Endpoint.sol";
|
|
8
8
|
import { Nodes } from "../utils/Nodes.sol";
|
|
9
9
|
import { Selectors } from "../utils/Selectors.sol";
|
|
10
10
|
import { Descriptors } from "../codec/Descriptors.sol";
|
|
@@ -13,7 +13,7 @@ import { Descriptors } from "../codec/Descriptors.sol";
|
|
|
13
13
|
/// @notice Abstract base for peer-facing rootzero ports.
|
|
14
14
|
/// Ports handle inter-host operations between cooperating hosts.
|
|
15
15
|
/// Access is restricted to trusted peer callers via `onlyPeer`.
|
|
16
|
-
abstract contract PortBase is NodeCalls, NodeAccess,
|
|
16
|
+
abstract contract PortBase is NodeCalls, NodeAccess, InputEndpointBase {
|
|
17
17
|
|
|
18
18
|
/// @dev Restrict execution to trusted callers, excluding the commander.
|
|
19
19
|
modifier onlyPeer() {
|
package/ports/Dispatch.sol
CHANGED
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
|
-
import {
|
|
5
|
+
import {RelayPayableHook} from "../commands/Relay.sol";
|
|
6
6
|
import {Specs} from "../Codec.sol";
|
|
7
7
|
import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
8
8
|
|
|
9
9
|
using Executions for Execution;
|
|
10
10
|
|
|
11
11
|
/// @title PortDispatchPayable
|
|
12
|
-
/// @notice Port endpoint that forwards DISPATCH blocks to a host-defined
|
|
13
|
-
abstract contract PortDispatchPayable is PortBase,
|
|
12
|
+
/// @notice Port endpoint that forwards DISPATCH blocks to a host-defined relay hook.
|
|
13
|
+
abstract contract PortDispatchPayable is PortBase, RelayPayableHook {
|
|
14
14
|
uint private immutable descriptor;
|
|
15
15
|
|
|
16
16
|
constructor() {
|
|
17
17
|
(, descriptor) = port("portDispatchPayable", Specs.Dispatch, Specs.Empty, true);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
/// @notice Forward peer-supplied dispatches to the host-defined
|
|
21
|
-
/// @dev
|
|
20
|
+
/// @notice Forward peer-supplied dispatches to the host-defined relay hook.
|
|
21
|
+
/// @dev Relay hooks receive the shared top-level source value
|
|
22
22
|
/// budget. Any `msg.value` not spent by the hook remains on this host.
|
|
23
23
|
/// @param data DISPATCH block stream supplied by the trusted peer.
|
|
24
24
|
/// @return Empty response bytes.
|
|
@@ -27,7 +27,7 @@ abstract contract PortDispatchPayable is PortBase, RoutePayableHook {
|
|
|
27
27
|
|
|
28
28
|
while (exec.more()) {
|
|
29
29
|
(uint portal, uint resources, bytes calldata payload) = exec.unpackDispatch(Lanes.Input);
|
|
30
|
-
|
|
30
|
+
relayTo(portal, resources, bytes(payload), exec);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
return "";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
|
-
import {
|
|
5
|
+
import {PostHook} from "../core/Settlement.sol";
|
|
6
6
|
import {Specs} from "../Codec.sol";
|
|
7
7
|
import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
8
8
|
import {Action} from "../annotations/Action.sol";
|
|
@@ -10,29 +10,29 @@ import {Actions} from "../utils/Actions.sol";
|
|
|
10
10
|
|
|
11
11
|
using Executions for Execution;
|
|
12
12
|
|
|
13
|
-
/// @title
|
|
14
|
-
/// @notice Port that
|
|
13
|
+
/// @title PortPost
|
|
14
|
+
/// @notice Port that posts peer-supplied TRANSACTION blocks through debit and credit hooks.
|
|
15
15
|
/// Each TRANSACTION block calls `debitAccount` for `from` and `creditAccount` for `to`.
|
|
16
|
-
abstract contract
|
|
16
|
+
abstract contract PortPost is PortBase, PostHook, Action {
|
|
17
17
|
uint private immutable descriptor;
|
|
18
18
|
|
|
19
19
|
constructor() {
|
|
20
20
|
uint id;
|
|
21
|
-
(id, descriptor) = port("
|
|
22
|
-
action(id, Actions.
|
|
21
|
+
(id, descriptor) = port("portPost", Specs.Transaction, Specs.Empty, false);
|
|
22
|
+
action(id, Actions.Post);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/// @notice
|
|
25
|
+
/// @notice Post peer-supplied transactions.
|
|
26
26
|
/// @param data TRANSACTION block stream supplied by the trusted peer.
|
|
27
27
|
/// @return Empty response bytes.
|
|
28
|
-
function
|
|
28
|
+
function portPost(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
29
29
|
Execution memory exec = openInput(data, descriptor, 0);
|
|
30
30
|
|
|
31
31
|
while (exec.more()) {
|
|
32
32
|
(bytes32 from, bytes32 to, bytes32 asset, uint amount) = exec.unpackTransaction(Lanes.Input);
|
|
33
|
-
|
|
33
|
+
post(from, to, asset, amount);
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
return "";
|
|
37
37
|
}
|
|
38
38
|
}
|
package/queries/Base.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { InputEndpointBase } from "../core/Endpoint.sol";
|
|
5
5
|
import { Descriptors } from "../codec/Descriptors.sol";
|
|
6
6
|
import { Specs } from "../codec/Specs.sol";
|
|
7
7
|
import { Nodes } from "../utils/Nodes.sol";
|
|
@@ -11,7 +11,7 @@ import { Selectors } from "../utils/Selectors.sol";
|
|
|
11
11
|
/// @notice Abstract base for rootzero query contracts.
|
|
12
12
|
/// Queries are view-only entry points that consume a block-stream input and
|
|
13
13
|
/// return a block-stream response.
|
|
14
|
-
abstract contract QueryBase is
|
|
14
|
+
abstract contract QueryBase is InputEndpointBase {
|
|
15
15
|
|
|
16
16
|
/// @notice Publish query metadata and a default label.
|
|
17
17
|
/// @param name Query entrypoint name and default label. It must exactly
|
package/utils/Actions.sol
CHANGED
package/utils/Cursors.sol
CHANGED
|
@@ -12,12 +12,12 @@ struct Cur {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/// @title Cursors
|
|
15
|
-
/// @notice Packed cursor state and navigation for
|
|
15
|
+
/// @notice Packed cursor state and navigation for byte regions.
|
|
16
16
|
/// @dev Each 128-bit cursor uses the following layout:
|
|
17
17
|
/// bits 0-31 i
|
|
18
18
|
/// bits 32-63 offset
|
|
19
19
|
/// bits 64-95 len
|
|
20
|
-
/// bits 96-111
|
|
20
|
+
/// bits 96-111 count (opaque consumer metadata)
|
|
21
21
|
/// bits 112-119 flags (consumer-defined)
|
|
22
22
|
/// bits 120-127 tag
|
|
23
23
|
///
|
|
@@ -28,7 +28,7 @@ struct Cur {
|
|
|
28
28
|
/// cursor into that position while preserving the pair.
|
|
29
29
|
///
|
|
30
30
|
/// A mark is a standalone cursor value used as an immutable positional
|
|
31
|
-
/// reference. It retains the cursor's offset, length,
|
|
31
|
+
/// reference. It retains the cursor's offset, length, count, flags, and tag,
|
|
32
32
|
/// but may carry a different `i`. A mark has no intrinsic boundary or movement
|
|
33
33
|
/// semantics; callers may later use its position for comparison, validation,
|
|
34
34
|
/// seeking, or another operation. Because it has the ordinary single-cursor
|
|
@@ -41,9 +41,6 @@ library Cursors {
|
|
|
41
41
|
/// @dev A cursor position exceeds its logical length.
|
|
42
42
|
error OutOfBounds();
|
|
43
43
|
|
|
44
|
-
/// @dev Two optional group counts are both set but do not match.
|
|
45
|
-
error BadRatio();
|
|
46
|
-
|
|
47
44
|
/// @dev A cursor is not positioned at the expected offset.
|
|
48
45
|
error UnexpectedPosition();
|
|
49
46
|
|
|
@@ -58,14 +55,14 @@ library Cursors {
|
|
|
58
55
|
/// @notice Create a cursor positioned at its beginning.
|
|
59
56
|
/// @param offset Absolute source or buffer offset.
|
|
60
57
|
/// @param len Logical byte length.
|
|
61
|
-
/// @param
|
|
58
|
+
/// @param items Opaque item count associated with the region.
|
|
62
59
|
/// @param flags Consumer-defined flags.
|
|
63
60
|
/// @param tag Cursor identity tag.
|
|
64
61
|
/// @return cur Packed cursor.
|
|
65
|
-
function create(uint offset, uint len, uint
|
|
62
|
+
function create(uint offset, uint len, uint items, uint8 flags, uint8 tag) internal pure returns (uint cur) {
|
|
66
63
|
cur |= max32(offset) << 32;
|
|
67
64
|
cur |= max32(len) << 64;
|
|
68
|
-
cur |= max16(
|
|
65
|
+
cur |= max16(items) << 96;
|
|
69
66
|
cur |= uint(flags) << 112;
|
|
70
67
|
cur |= uint(tag) << 120;
|
|
71
68
|
}
|
|
@@ -113,7 +110,7 @@ library Cursors {
|
|
|
113
110
|
/// @notice Return the active cursor without its position.
|
|
114
111
|
/// @dev Ignores the upper cursor when `cur` is a pair.
|
|
115
112
|
/// @param cur Packed cursor or cursor pair.
|
|
116
|
-
/// @return The lower cursor's offset, length,
|
|
113
|
+
/// @return The lower cursor's offset, length, count, flags, and tag.
|
|
117
114
|
function frame(uint cur) internal pure returns (uint) {
|
|
118
115
|
return clear32(uint128(cur), 0);
|
|
119
116
|
}
|
|
@@ -128,15 +125,20 @@ library Cursors {
|
|
|
128
125
|
|
|
129
126
|
/// @notice Decode the consumer metadata and identity tag from the lower cursor.
|
|
130
127
|
/// @param cur Packed cursor or cursor pair.
|
|
131
|
-
/// @return
|
|
128
|
+
/// @return items Opaque item count.
|
|
132
129
|
/// @return flags Consumer-defined flags.
|
|
133
130
|
/// @return tag Cursor identity tag.
|
|
134
|
-
function meta(uint cur) internal pure returns (uint
|
|
135
|
-
|
|
131
|
+
function meta(uint cur) internal pure returns (uint items, uint8 flags, uint8 tag) {
|
|
132
|
+
items = uint16(cur >> 96);
|
|
136
133
|
flags = uint8(cur >> 112);
|
|
137
134
|
tag = uint8(cur >> 120);
|
|
138
135
|
}
|
|
139
136
|
|
|
137
|
+
/// @notice Return the opaque item count attached to the active cursor.
|
|
138
|
+
function count(uint cur) internal pure returns (uint) {
|
|
139
|
+
return uint16(cur >> 96);
|
|
140
|
+
}
|
|
141
|
+
|
|
140
142
|
/// @notice Return whether both packed cursors remain at their initial positions.
|
|
141
143
|
/// @param cur Packed cursor or cursor pair.
|
|
142
144
|
/// @return Whether both lane positions are zero.
|
|
@@ -233,7 +235,7 @@ library Cursors {
|
|
|
233
235
|
}
|
|
234
236
|
|
|
235
237
|
/// @notice Create a child cursor over `[start, end)` within the lower cursor.
|
|
236
|
-
/// @dev The child starts at position zero, has no
|
|
238
|
+
/// @dev The child starts at position zero, has no recorded count, and uses the
|
|
237
239
|
/// supplied tag. Any higher cursor is omitted.
|
|
238
240
|
/// @param cur Parent cursor or cursor pair.
|
|
239
241
|
/// @param start Child start relative to the parent base.
|
|
@@ -248,22 +250,6 @@ library Cursors {
|
|
|
248
250
|
|
|
249
251
|
// Pairing and selection
|
|
250
252
|
|
|
251
|
-
/// @notice Reconcile both packed cursor lanes with an expected group count.
|
|
252
|
-
/// @dev Zero lanes and lanes with zero groups do not constrain the result.
|
|
253
|
-
/// @param cur Packed cursor or cursor pair.
|
|
254
|
-
/// @param expected Expected group count; zero accepts the encoded count.
|
|
255
|
-
/// @return groups Reconciled effective group count.
|
|
256
|
-
function reconcile(uint cur, uint expected) internal pure returns (uint groups) {
|
|
257
|
-
uint low = uint16(cur >> 96);
|
|
258
|
-
uint high = uint16(cur >> 224);
|
|
259
|
-
if (low != 0 && high != 0 && low != high) revert BadRatio();
|
|
260
|
-
|
|
261
|
-
groups = low != 0 ? low : high;
|
|
262
|
-
if (groups != 0 && expected != 0 && groups != expected) revert BadRatio();
|
|
263
|
-
if (groups == 0) groups = expected;
|
|
264
|
-
max16(groups);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
253
|
/// @notice Combine two cursors into one packed word.
|
|
268
254
|
/// @dev Zero represents absence and acts as the identity value.
|
|
269
255
|
/// @param low Cursor placed in the lower lane.
|
package/events/Position.sol
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import {EventEmitter} from "./Emitter.sol";
|
|
5
|
-
|
|
6
|
-
/// @notice Emitted when the reported value of an asset-backed position changes or is observed.
|
|
7
|
-
/// A value of 0 should be interpreted as a closed position.
|
|
8
|
-
abstract contract PositionEvent is EventEmitter {
|
|
9
|
-
string private constant ABI = "event Position(bytes32 indexed account, bytes32 asset, uint value, uint32 action, uint context, uint queryId)";
|
|
10
|
-
|
|
11
|
-
/// @param account Account identifier that owns or is associated with the position.
|
|
12
|
-
/// @param asset Asset identifier for the asset class.
|
|
13
|
-
/// @param value Context-specific position value; 0 indicates a closed position.
|
|
14
|
-
/// @param action Primary operation hint from `Actions`.
|
|
15
|
-
/// @param context Reserved context value for future use.
|
|
16
|
-
/// @param queryId Query ID associated with the position lookup or reporting context.
|
|
17
|
-
event Position(bytes32 indexed account, bytes32 asset, uint value, uint32 action, uint context, uint queryId);
|
|
18
|
-
|
|
19
|
-
constructor() {
|
|
20
|
-
emit EventAbi(ABI);
|
|
21
|
-
}
|
|
22
|
-
}
|