@rootzero/contracts 1.14.0 → 1.16.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 (68) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/Codec.sol +1 -1
  3. package/Commands.sol +1 -1
  4. package/Core.sol +8 -5
  5. package/Endpoints.sol +6 -6
  6. package/Events.sol +1 -3
  7. package/README.md +118 -35
  8. package/annotations/Action.sol +17 -0
  9. package/annotations/Label.sol +23 -0
  10. package/annotations/Schema.sol +53 -0
  11. package/codec/Blocks.sol +127 -32
  12. package/codec/Buffers.sol +3 -3
  13. package/codec/Decoders.sol +46 -13
  14. package/codec/Descriptors.sol +0 -1
  15. package/codec/Keys.sol +8 -4
  16. package/codec/Readers.sol +13 -0
  17. package/codec/Schema.sol +12 -3
  18. package/codec/Specs.sol +28 -4
  19. package/codec/Writers.sol +21 -6
  20. package/commands/Base.sol +39 -44
  21. package/commands/Burn.sol +8 -4
  22. package/commands/Credit.sol +35 -3
  23. package/commands/Debit.sol +46 -13
  24. package/commands/Deposit.sol +14 -8
  25. package/commands/Payout.sol +6 -2
  26. package/commands/Provision.sol +4 -4
  27. package/commands/Recover.sol +15 -8
  28. package/commands/Relay.sol +37 -12
  29. package/commands/Settle.sol +77 -0
  30. package/commands/Withdraw.sol +8 -4
  31. package/commands/admin/AllowAssets.sol +2 -2
  32. package/commands/admin/Allowance.sol +2 -2
  33. package/commands/admin/Annotate.sol +36 -0
  34. package/commands/admin/Appoint.sol +6 -5
  35. package/commands/admin/Authorize.sol +2 -2
  36. package/commands/admin/Base.sol +8 -1
  37. package/commands/admin/DenyAssets.sol +2 -2
  38. package/commands/admin/Dismiss.sol +6 -5
  39. package/commands/admin/Execute.sol +5 -4
  40. package/commands/admin/Unauthorize.sol +2 -2
  41. package/core/Access.sol +91 -49
  42. package/core/Calls.sol +27 -22
  43. package/core/Endpoint.sol +36 -46
  44. package/core/Host.sol +63 -21
  45. package/core/Pipeline.sol +6 -6
  46. package/core/Settlement.sol +37 -8
  47. package/core/Types.sol +13 -1
  48. package/docs/Schema.md +68 -7
  49. package/events/Annotation.sol +24 -0
  50. package/events/Guardian.sol +2 -2
  51. package/events/Introduction.sol +3 -2
  52. package/execution/Budget.sol +12 -4
  53. package/execution/Execution.sol +113 -18
  54. package/guards/Base.sol +4 -4
  55. package/package.json +1 -1
  56. package/ports/Base.sol +19 -7
  57. package/ports/Dispatch.sol +6 -6
  58. package/ports/{Settle.sol → Post.sol} +13 -9
  59. package/queries/Base.sol +18 -3
  60. package/utils/Accounts.sol +0 -23
  61. package/utils/Actions.sol +1 -0
  62. package/utils/Cursors.sol +79 -34
  63. package/utils/Layout.sol +0 -2
  64. package/commands/admin/Label.sol +0 -36
  65. package/commands/admin/Schemas.sol +0 -36
  66. package/events/Labeled.sol +0 -21
  67. package/events/Position.sol +0 -22
  68. package/events/Schema.sol +0 -23
@@ -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, 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 = bytes4(source);
47
- (uint groups, uint end) = Blocks.scope(abs, limit, key, stride);
48
- cur = Cursors.create(abs, end - abs, groups, 0, lane);
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
- cur = Buffers.cursor(capacity + padding, batches, growable, lane);
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 = Cursors.reconcile(decoders, batches);
125
+ batches = reconcile(decoders, descriptor, batches);
95
126
  exec.writers = writerCursors(descriptor, batches);
96
127
  }
97
128
 
@@ -166,6 +197,14 @@ library Executions {
166
197
  exec.decoders = cur.seekAbs(end);
167
198
  }
168
199
 
200
+ /// @notice Require the active execution decoder to be at absolute position `abs`.
201
+ /// @dev The most recent lane-aware decoder operation determines the active lane.
202
+ /// @param exec Execution whose active decoder position is validated.
203
+ /// @param abs Expected absolute position.
204
+ function expectAbs(Execution memory exec, uint abs) internal pure {
205
+ exec.decoders.expectAbs(abs);
206
+ }
207
+
169
208
  /// @notice Consume a LIST block and return a cursor scoped to its payload.
170
209
  /// @param exec Execution whose decoder is advanced.
171
210
  /// @param lane Decoder lane containing the LIST block.
@@ -286,6 +325,24 @@ library Executions {
286
325
  (value.asset, value.amount) = unpackBalance(exec, lane);
287
326
  }
288
327
 
328
+ /// @notice Decode and consume one POSITION block from `lane`.
329
+ function unpackPosition(
330
+ Execution memory exec,
331
+ uint8 lane
332
+ ) internal pure returns (bytes32 asset, uint amount, bytes32 liability, uint debt) {
333
+ uint abs;
334
+ (exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Position);
335
+ (asset, amount, liability, debt) = Blocks.unpackPosition(abs);
336
+ }
337
+
338
+ /// @notice Decode one POSITION block into its structured value.
339
+ function unpackPositionValue(
340
+ Execution memory exec,
341
+ uint8 lane
342
+ ) internal pure returns (Position memory value) {
343
+ (value.asset, value.amount, value.liability, value.debt) = unpackPosition(exec, lane);
344
+ }
345
+
289
346
  /// @notice Decode one BALANCE block and associate it with `host`.
290
347
  /// @param exec Execution whose decoder is advanced.
291
348
  /// @param lane Decoder lane to consume.
@@ -520,6 +577,21 @@ library Executions {
520
577
  exec.decoders = cur.seekAbs(end);
521
578
  }
522
579
 
580
+ /// @notice Decode and consume one ANNOTATION block from `lane`.
581
+ /// @param exec Execution whose decoder is advanced.
582
+ /// @param lane Decoder lane to consume.
583
+ /// @return entity Decoded entity identifier.
584
+ /// @return data Decoded annotation block stream.
585
+ function unpackAnnotation(
586
+ Execution memory exec,
587
+ uint8 lane
588
+ ) internal pure returns (uint entity, bytes calldata data) {
589
+ uint cur = exec.decoders.select(lane);
590
+ uint end;
591
+ (entity, data, end) = Blocks.unpackAnnotation(cur.absolute());
592
+ exec.decoders = cur.seekAbs(end);
593
+ }
594
+
523
595
  /// @notice Decode and consume one CONTEXT block from `lane`.
524
596
  /// @param exec Execution whose decoder is advanced.
525
597
  /// @param lane Decoder lane to consume.
@@ -573,17 +645,16 @@ library Executions {
573
645
  /// @notice Decode and consume one LABEL block from `lane`.
574
646
  /// @param exec Execution whose decoder is advanced.
575
647
  /// @param lane Decoder lane to consume.
576
- /// @return id Decoded node identifier.
577
648
  /// @return namespace Decoded label namespace.
578
649
  /// @return name Decoded label text.
579
650
  function unpackLabel(
580
651
  Execution memory exec,
581
652
  uint8 lane
582
- ) internal pure returns (uint id, bytes32 namespace, string memory name) {
653
+ ) internal pure returns (bytes32 namespace, string memory name) {
583
654
  uint cur = exec.decoders.select(lane);
584
655
  uint abs = cur.absolute();
585
656
  uint end;
586
- (id, namespace, name, end) = Blocks.unpackLabel(abs);
657
+ (namespace, name, end) = Blocks.unpackLabel(abs);
587
658
  exec.decoders = cur.seekAbs(end);
588
659
  }
589
660
 
@@ -708,6 +779,23 @@ library Executions {
708
779
  outputBalance(exec, value.asset, value.amount);
709
780
  }
710
781
 
782
+ /// @notice Append a POSITION block to execution output.
783
+ function outputPosition(
784
+ Execution memory exec,
785
+ bytes32 asset,
786
+ uint amount,
787
+ bytes32 liability,
788
+ uint debt
789
+ ) internal pure {
790
+ uint i = reserve(exec, Sizes.Position);
791
+ Blocks.writePosition(exec.output, i, asset, amount, liability, debt);
792
+ }
793
+
794
+ /// @notice Append a structured POSITION value to execution output.
795
+ function outputPosition(Execution memory exec, Position memory value) internal pure {
796
+ outputPosition(exec, value.asset, value.amount, value.liability, value.debt);
797
+ }
798
+
711
799
  /// @notice Append an ACCOUNT_ASSET block to execution output.
712
800
  /// @param exec Execution receiving the block.
713
801
  /// @param account Account identifier to encode.
@@ -956,13 +1044,12 @@ library Executions {
956
1044
 
957
1045
  /// @notice Append a LABEL block to execution output.
958
1046
  /// @param exec Execution receiving the block.
959
- /// @param id Node identifier to encode.
960
1047
  /// @param namespace Label namespace to encode.
961
1048
  /// @param name Label text to encode.
962
- function outputLabel(Execution memory exec, uint id, bytes32 namespace, string memory name) internal pure {
963
- uint size = Sizes.B64 + Sizes.Header + bytes(name).length;
1049
+ function outputLabel(Execution memory exec, bytes32 namespace, string memory name) internal pure {
1050
+ uint size = Sizes.B32 + Sizes.Header + bytes(name).length;
964
1051
  uint i = reserve(exec, size);
965
- Blocks.writeLabel(exec.output, i, id, namespace, name);
1052
+ Blocks.writeLabel(exec.output, i, namespace, name);
966
1053
  }
967
1054
 
968
1055
  /// @notice Append a SCHEMA block to execution output.
@@ -989,15 +1076,23 @@ library Executions {
989
1076
  exec.budget = 0;
990
1077
  }
991
1078
 
1079
+ /// @notice Deduct an exact native value from the execution budget.
1080
+ /// @param exec Mutable execution whose budget is charged.
1081
+ /// @param value Native value to consume in wei.
1082
+ /// @return The consumed native value.
1083
+ function useValue(Execution memory exec, uint value) internal pure returns (uint) {
1084
+ if (value > exec.budget) revert InsufficientValue();
1085
+ exec.budget -= value;
1086
+ return value;
1087
+ }
1088
+
992
1089
  /// @notice Deduct the EVM value lane of `resources` from the execution budget.
993
1090
  /// @dev EVM resources use the low 128 bits as native value/endowment.
994
1091
  /// @param exec Mutable execution whose budget is charged.
995
1092
  /// @param resources Packed resources whose value lane should be spent.
996
1093
  /// @return value Native value to forward in wei.
997
- function useValue(Execution memory exec, uint resources) internal pure returns (uint128 value) {
998
- value = uint128(resources);
999
- if (value > exec.budget) revert InsufficientValue();
1000
- exec.budget -= value;
1094
+ function useResourceValue(Execution memory exec, uint resources) internal pure returns (uint128) {
1095
+ return uint128(useValue(exec, uint128(resources)));
1001
1096
  }
1002
1097
 
1003
1098
  /// @notice Append a deferred transaction to the transaction writer lane.
package/guards/Base.sol CHANGED
@@ -1,8 +1,8 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import {AccessControl} from "../core/Access.sol";
5
- import {EndpointBase} from "../core/Endpoint.sol";
4
+ import {InputEndpointBase} from "../core/Endpoint.sol";
5
+ import {GuardianAccess} from "../core/Access.sol";
6
6
  import {Specs} from "../codec/Specs.sol";
7
7
  import {Nodes} from "../utils/Nodes.sol";
8
8
  import {Selectors} from "../utils/Selectors.sol";
@@ -10,10 +10,10 @@ 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 AccessControl, EndpointBase {
13
+ abstract contract GuardBase is GuardianAccess, InputEndpointBase {
14
14
  /// @dev Restrict execution to active guardian addresses.
15
15
  modifier onlyGuardian() {
16
- if (!isGuardian(msg.sender)) revert AccessDenied();
16
+ enforceGuardian(msg.sender);
17
17
  _;
18
18
  }
19
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootzero/contracts",
3
- "version": "1.14.0",
3
+ "version": "1.16.0",
4
4
  "description": "Solidity contracts and protocol building blocks for rootzero hosts and commands.",
5
5
  "private": false,
6
6
  "license": "GPL-3.0-only",
package/ports/Base.sol CHANGED
@@ -2,8 +2,9 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import { NodeCalls } from "../core/Calls.sol";
5
+ import { NodeAccess } from "../core/Access.sol";
5
6
  import { Specs } from "../codec/Specs.sol";
6
- import { EndpointBase } from "../core/Endpoint.sol";
7
+ import { InputEndpointBase } from "../core/Endpoint.sol";
7
8
  import { Nodes } from "../utils/Nodes.sol";
8
9
  import { Selectors } from "../utils/Selectors.sol";
9
10
  import { Descriptors } from "../codec/Descriptors.sol";
@@ -12,14 +13,11 @@ import { Descriptors } from "../codec/Descriptors.sol";
12
13
  /// @notice Abstract base for peer-facing rootzero ports.
13
14
  /// Ports handle inter-host operations between cooperating hosts.
14
15
  /// Access is restricted to trusted peer callers via `onlyPeer`.
15
- abstract contract PortBase is NodeCalls, EndpointBase {
16
- /// @dev Thrown when the commander attempts to call a port entrypoint directly.
17
- error CommanderNotAllowed();
16
+ abstract contract PortBase is NodeCalls, NodeAccess, InputEndpointBase {
18
17
 
19
18
  /// @dev Restrict execution to trusted callers, excluding the commander.
20
19
  modifier onlyPeer() {
21
- if (msg.sender == commander) revert CommanderNotAllowed();
22
- enforceCaller(msg.sender);
20
+ enforcePeer(msg.sender);
23
21
  _;
24
22
  }
25
23
 
@@ -44,7 +42,21 @@ abstract contract PortBase is NodeCalls, EndpointBase {
44
42
  uint output,
45
43
  bool funded
46
44
  ) internal returns (uint id, uint descriptor) {
45
+ descriptor = Descriptors.create(Specs.Empty, input, output, 0, funded ? Descriptors.Funded : 0);
46
+ return port(name, descriptor);
47
+ }
48
+
49
+ /// @notice Publish an already constructed port descriptor and default label.
50
+ /// @param name Port entrypoint name and default label. It must exactly
51
+ /// match the Solidity port function name used by the canonical ABI.
52
+ /// @param descriptor Packed port endpoint descriptor.
53
+ /// @return id Port node ID.
54
+ /// @return published Published endpoint descriptor.
55
+ function port(
56
+ string memory name,
57
+ uint descriptor
58
+ ) internal returns (uint id, uint published) {
47
59
  id = Nodes.toPort(Selectors.port(name), address(this));
48
- descriptor = endpoint(id, name, Specs.Empty, input, output, 0, funded ? Descriptors.Funded : 0);
60
+ published = endpoint(id, name, descriptor);
49
61
  }
50
62
  }
@@ -2,23 +2,23 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
- import {RoutePayableHook} from "../commands/Relay.sol";
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 route hook.
13
- abstract contract PortDispatchPayable is PortBase, RoutePayableHook {
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 route hook.
21
- /// @dev Route hooks receive the shared top-level source value
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
- route(portal, resources, bytes(payload), exec);
30
+ relayTo(portal, resources, bytes(payload), exec);
31
31
  }
32
32
 
33
33
  return "";
@@ -2,33 +2,37 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
- import {Settlement} from "../core/Settlement.sol";
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
+ import {Action} from "../annotations/Action.sol";
9
+ import {Actions} from "../utils/Actions.sol";
8
10
 
9
11
  using Executions for Execution;
10
12
 
11
- /// @title PortSettle
12
- /// @notice Port that consumes peer-supplied TRANSACTION blocks through debit and credit hooks.
13
+ /// @title PortPost
14
+ /// @notice Port that posts peer-supplied TRANSACTION blocks through debit and credit hooks.
13
15
  /// Each TRANSACTION block calls `debitAccount` for `from` and `creditAccount` for `to`.
14
- abstract contract PortSettle is PortBase, Settlement {
16
+ abstract contract PortPost is PortBase, PostHook, Action {
15
17
  uint private immutable descriptor;
16
18
 
17
19
  constructor() {
18
- (, descriptor) = port("portSettle", Specs.Transaction, Specs.Empty, false);
20
+ uint id;
21
+ (id, descriptor) = port("portPost", Specs.Transaction, Specs.Empty, false);
22
+ action(id, Actions.Post);
19
23
  }
20
24
 
21
- /// @notice Execute the port-settle call.
25
+ /// @notice Post peer-supplied transactions.
22
26
  /// @param data TRANSACTION block stream supplied by the trusted peer.
23
27
  /// @return Empty response bytes.
24
- function portSettle(bytes calldata data) external onlyPeer returns (bytes memory) {
28
+ function portPost(bytes calldata data) external onlyPeer returns (bytes memory) {
25
29
  Execution memory exec = openInput(data, descriptor, 0);
26
30
 
27
31
  while (exec.more()) {
28
32
  (bytes32 from, bytes32 to, bytes32 asset, uint amount) = exec.unpackTransaction(Lanes.Input);
29
- settle(from, to, asset, amount);
33
+ post(from, to, asset, amount);
30
34
  }
31
-
35
+
32
36
  return "";
33
37
  }
34
38
  }
package/queries/Base.sol CHANGED
@@ -1,7 +1,8 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import { EndpointBase } from "../core/Endpoint.sol";
4
+ import { InputEndpointBase } from "../core/Endpoint.sol";
5
+ import { Descriptors } from "../codec/Descriptors.sol";
5
6
  import { Specs } from "../codec/Specs.sol";
6
7
  import { Nodes } from "../utils/Nodes.sol";
7
8
  import { Selectors } from "../utils/Selectors.sol";
@@ -10,7 +11,7 @@ import { Selectors } from "../utils/Selectors.sol";
10
11
  /// @notice Abstract base for rootzero query contracts.
11
12
  /// Queries are view-only entry points that consume a block-stream input and
12
13
  /// return a block-stream response.
13
- abstract contract QueryBase is EndpointBase {
14
+ abstract contract QueryBase is InputEndpointBase {
14
15
 
15
16
  /// @notice Publish query metadata and a default label.
16
17
  /// @param name Query entrypoint name and default label. It must exactly
@@ -24,7 +25,21 @@ abstract contract QueryBase is EndpointBase {
24
25
  uint input,
25
26
  uint output
26
27
  ) internal returns (uint id, uint descriptor) {
28
+ descriptor = Descriptors.create(Specs.Empty, input, output, 0, 0);
29
+ return query(name, descriptor);
30
+ }
31
+
32
+ /// @notice Publish an already constructed query descriptor and default label.
33
+ /// @param name Query entrypoint name and default label. It must exactly
34
+ /// match the Solidity query function name used by the canonical ABI.
35
+ /// @param descriptor Packed query endpoint descriptor.
36
+ /// @return id Query node ID.
37
+ /// @return published Published endpoint descriptor.
38
+ function query(
39
+ string memory name,
40
+ uint descriptor
41
+ ) internal returns (uint id, uint published) {
27
42
  id = Nodes.toQuery(Selectors.query(name), address(this));
28
- descriptor = endpoint(id, name, Specs.Empty, input, output, 0, 0);
43
+ published = endpoint(id, name, descriptor);
29
44
  }
30
45
  }
@@ -10,7 +10,6 @@ import {ensureAddr, isFamily, toLocalBase, toUnspecifiedBase} from "./Utils.sol"
10
10
  ///
11
11
  /// Account IDs embed a 4-byte type tag in bits [255:224]:
12
12
  /// - `Admin` — chain-local EVM address in bits [191:32]
13
- /// - `Guardian` — chain-local EVM address in bits [191:32]
14
13
  /// - `User` — chain-agnostic EVM address in bits [191:32]
15
14
  ///
16
15
  /// If the first byte is zero, the account is an opaque
@@ -26,8 +25,6 @@ library Accounts {
26
25
  uint24 constant Family = (uint24(Layout.Evm) << 8) | uint24(Layout.Account);
27
26
  /// @dev Full 4-byte type prefix for admin accounts (chain-local EVM address).
28
27
  uint32 constant Admin = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Admin);
29
- /// @dev Full 4-byte type prefix for guardian accounts (chain-local EVM address).
30
- uint32 constant Guardian = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Guardian);
31
28
  /// @dev Full 4-byte type prefix for user accounts (chain-agnostic EVM address).
32
29
  uint32 constant User = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.User);
33
30
 
@@ -53,11 +50,6 @@ library Accounts {
53
50
  return prefix(account) == Admin;
54
51
  }
55
52
 
56
- /// @notice Return true if `account` is a guardian account.
57
- function isGuardian(bytes32 account) internal pure returns (bool) {
58
- return prefix(account) == Guardian;
59
- }
60
-
61
53
  /// @notice Return true if `account` is a user account.
62
54
  function isUser(bytes32 account) internal pure returns (bool) {
63
55
  return prefix(account) == User;
@@ -87,14 +79,6 @@ library Accounts {
87
79
  return value;
88
80
  }
89
81
 
90
- /// @notice Assert that `value` is a guardian account and return it unchanged.
91
- /// @param value Account identifier to validate.
92
- /// @return account The same `value` if it is a guardian account.
93
- function guardian(bytes32 value) internal pure returns (bytes32 account) {
94
- if (!isGuardian(value)) revert InvalidAccount();
95
- return value;
96
- }
97
-
98
82
  /// @notice Assert that `value` is a user account and return it unchanged.
99
83
  /// @param value Account identifier to validate.
100
84
  /// @return account The same `value` if it is a user account.
@@ -110,13 +94,6 @@ library Accounts {
110
94
  return bytes32(toLocalBase(Admin) | (uint(uint160(account)) << 32));
111
95
  }
112
96
 
113
- /// @notice Encode an EVM address as a chain-local guardian account ID.
114
- /// @param account EVM address to embed.
115
- /// @return Guardian account ID bound to the current chain.
116
- function toGuardian(address account) internal view returns (bytes32) {
117
- return bytes32(toLocalBase(Guardian) | (uint(uint160(account)) << 32));
118
- }
119
-
120
97
  /// @notice Encode an EVM address as a chain-agnostic user account ID.
121
98
  /// @param account EVM address to embed.
122
99
  /// @return User account ID without a chain binding.
package/utils/Actions.sol CHANGED
@@ -17,4 +17,5 @@ library Actions {
17
17
  uint32 constant Repay = 11;
18
18
  uint32 constant Liquidate = 12;
19
19
  uint32 constant Refund = 13;
20
+ uint32 constant Post = 14;
20
21
  }