@rootzero/contracts 1.10.0 → 1.11.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 (58) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/Core.sol +1 -0
  3. package/Endpoints.sol +1 -3
  4. package/Events.sol +2 -5
  5. package/README.md +35 -33
  6. package/Utils.sol +2 -1
  7. package/blocks/Cursors.sol +26 -75
  8. package/blocks/Keys.sol +14 -4
  9. package/blocks/Schema.sol +49 -44
  10. package/commands/Base.sol +43 -13
  11. package/commands/Burn.sol +3 -6
  12. package/commands/Credit.sol +9 -6
  13. package/commands/Debit.sol +15 -11
  14. package/commands/Deposit.sol +19 -23
  15. package/commands/Payout.sol +6 -10
  16. package/commands/Provision.sol +19 -23
  17. package/commands/Recover.sol +7 -9
  18. package/commands/Relay.sol +10 -11
  19. package/commands/Withdraw.sol +3 -6
  20. package/commands/admin/AllowAssets.sol +7 -10
  21. package/commands/admin/Allowance.sol +7 -10
  22. package/commands/admin/Appoint.sol +7 -10
  23. package/commands/admin/Authorize.sol +7 -10
  24. package/commands/admin/Base.sol +1 -2
  25. package/commands/admin/DenyAssets.sol +7 -10
  26. package/commands/admin/Dismiss.sol +7 -10
  27. package/commands/admin/Execute.sol +7 -10
  28. package/commands/admin/Label.sol +8 -11
  29. package/commands/admin/Unauthorize.sol +7 -10
  30. package/core/Endpoint.sol +153 -0
  31. package/docs/Schema.md +114 -82
  32. package/events/Endpoint.sol +19 -0
  33. package/events/Schema.sol +23 -0
  34. package/guards/Base.sol +17 -8
  35. package/guards/Revoke.sol +4 -6
  36. package/package.json +1 -1
  37. package/ports/AllowAssets.sol +6 -9
  38. package/ports/Allowance.sol +6 -9
  39. package/ports/Base.sol +21 -8
  40. package/ports/Credit.sol +6 -9
  41. package/ports/Debit.sol +6 -9
  42. package/ports/DenyAssets.sol +6 -9
  43. package/ports/Dispatch.sol +6 -9
  44. package/ports/Pipe.sol +4 -7
  45. package/ports/Redeem.sol +4 -7
  46. package/ports/Settle.sol +6 -9
  47. package/queries/Assets.sol +9 -12
  48. package/queries/Balances.sol +7 -9
  49. package/queries/Base.sol +19 -11
  50. package/utils/Selectors.sol +49 -0
  51. package/commands/admin/Destroy.sol +0 -43
  52. package/commands/admin/Init.sol +0 -43
  53. package/events/Admin.sol +0 -32
  54. package/events/Command.sol +0 -32
  55. package/events/Guard.sol +0 -18
  56. package/events/Port.sol +0 -22
  57. package/events/Query.sol +0 -20
  58. package/queries/Positions.sol +0 -54
package/ports/Debit.sol CHANGED
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import { PortBase } from "./Base.sol";
5
5
  import { DebitAccountHook } from "../commands/Debit.sol";
6
- import { Cursors, Cur, Forms } from "../Cursors.sol";
6
+ import { Cursors, Cur, Keys } from "../Cursors.sol";
7
7
 
8
8
  using Cursors for Cur;
9
9
 
@@ -11,25 +11,22 @@ using Cursors for Cur;
11
11
  /// @notice Port that lets a trusted peer debit supplied accounts directly.
12
12
  /// Each ACCOUNT_AMOUNT block calls `debitAccount` for its account.
13
13
  abstract contract PortDebitAccount is PortBase, DebitAccountHook {
14
- uint internal immutable portDebitAccountId = portId(this.portDebitAccount.selector);
14
+ bytes32 private immutable descriptor;
15
15
 
16
16
  constructor() {
17
- emit Port(host, portDebitAccountId, "1:0", Forms.AccountAmount, "", false);
18
- emit Labeled(portDebitAccountId, bytes32(0), "portDebitAccount");
17
+ (, descriptor) = port("portDebitAccount", Keys.AccountAmount, Keys.Empty, 0, false);
19
18
  }
20
19
 
21
20
  /// @notice Execute the port-debit call.
22
21
  /// @param data ACCOUNT_AMOUNT block stream supplied by the trusted peer.
23
22
  /// @return Empty response bytes.
24
23
  function portDebitAccount(bytes calldata data) external onlyPeer returns (bytes memory) {
25
- (Cur memory amounts, ) = Cursors.init(data, 1);
24
+ (Cur memory input, ) = openInput(data, descriptor);
26
25
 
27
- while (amounts.i < amounts.len) {
28
- (bytes32 account, bytes32 asset, uint amount) = amounts.unpackAccountAmount();
26
+ while (input.i < input.len) {
27
+ (bytes32 account, bytes32 asset, uint amount) = input.unpackAccountAmount();
29
28
  debitAccount(account, asset, amount);
30
29
  }
31
-
32
- amounts.complete();
33
30
  return "";
34
31
  }
35
32
  }
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
5
  import {DenyAssetsHook} from "../commands/admin/DenyAssets.sol";
6
- import {Cursors, Cur, Schemas} from "../Cursors.sol";
6
+ import {Cursors, Cur, Keys} from "../Cursors.sol";
7
7
 
8
8
  using Cursors for Cur;
9
9
 
@@ -11,25 +11,22 @@ using Cursors for Cur;
11
11
  /// @notice Port that blocks a list of assets on behalf of a peer host.
12
12
  /// Each ASSET block in the request calls `denyAsset`. Restricted to trusted peers.
13
13
  abstract contract PortDenyAssets is PortBase, DenyAssetsHook {
14
- uint internal immutable portDenyAssetsId = portId(this.portDenyAssets.selector);
14
+ bytes32 private immutable descriptor;
15
15
 
16
16
  constructor() {
17
- emit Port(host, portDenyAssetsId, "1:0", Schemas.Asset, "", false);
18
- emit Labeled(portDenyAssetsId, bytes32(0), "portDenyAssets");
17
+ (, descriptor) = port("portDenyAssets", Keys.Asset, Keys.Empty, 0, false);
19
18
  }
20
19
 
21
20
  /// @notice Execute the deny-assets peer call.
22
21
  /// @param data ASSET block stream supplied by the trusted peer.
23
22
  /// @return Empty response bytes.
24
23
  function portDenyAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
25
- (Cur memory assets, ) = Cursors.init(data, 1);
24
+ (Cur memory input, ) = openInput(data, descriptor);
26
25
 
27
- while (assets.i < assets.len) {
28
- bytes32 asset = assets.unpackAsset();
26
+ while (input.i < input.len) {
27
+ bytes32 asset = input.unpackAsset();
29
28
  denyAsset(asset);
30
29
  }
31
-
32
- assets.complete();
33
30
  return "";
34
31
  }
35
32
  }
@@ -4,7 +4,7 @@ pragma solidity ^0.8.33;
4
4
  import { PortBase } from "./Base.sol";
5
5
  import { Payable } from "../core/Payable.sol";
6
6
  import { RoutePayableHook } from "../commands/Relay.sol";
7
- import { Cursors, Cur, Schemas } from "../Cursors.sol";
7
+ import { Cursors, Cur, Keys } from "../Cursors.sol";
8
8
  import { Budget } from "../utils/Value.sol";
9
9
 
10
10
  using Cursors for Cur;
@@ -12,28 +12,25 @@ using Cursors for Cur;
12
12
  /// @title PortDispatchPayable
13
13
  /// @notice Port endpoint that forwards DISPATCH blocks to a host-defined route hook.
14
14
  abstract contract PortDispatchPayable is PortBase, Payable, RoutePayableHook {
15
- uint internal immutable portDispatchPayableId = portId(this.portDispatchPayable.selector);
15
+ bytes32 private immutable descriptor;
16
16
 
17
17
  constructor() {
18
- emit Port(host, portDispatchPayableId, "1:0", Schemas.Dispatch, "", true);
19
- emit Labeled(portDispatchPayableId, bytes32(0), "portDispatchPayable");
18
+ (, descriptor) = port("portDispatchPayable", Keys.Dispatch, Keys.Empty, 0, true);
20
19
  }
21
20
 
22
21
  /// @notice Forward peer-supplied dispatches to the host-defined route hook.
23
22
  /// @dev Route hooks receive the shared top-level source value
24
23
  /// budget. Any `msg.value` not spent by the hook remains on this host.
25
24
  /// @param data DISPATCH block stream supplied by the trusted peer.
26
- /// @return output Empty response bytes.
27
- function portDispatchPayable(bytes calldata data) external payable onlyPeer returns (bytes memory output) {
28
- (Cur memory input, ) = Cursors.init(data, 1);
25
+ /// @return Empty response bytes.
26
+ function portDispatchPayable(bytes calldata data) external payable onlyPeer returns (bytes memory) {
27
+ (Cur memory input, ) = openInput(data, descriptor);
29
28
  Budget memory budget = openValue();
30
29
 
31
30
  while (input.i < input.len) {
32
31
  (uint portal, uint resources, bytes calldata payload) = input.unpackDispatch();
33
32
  route(portal, resources, bytes(payload), budget);
34
33
  }
35
-
36
- input.complete();
37
34
  return "";
38
35
  }
39
36
 
package/ports/Pipe.sol CHANGED
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
5
  import {Pipeline} from "../core/Pipeline.sol";
6
- import {Cursors, Cur, Schemas} from "../Cursors.sol";
6
+ import {Cursors, Cur, Keys} from "../Cursors.sol";
7
7
  import {Budget} from "../utils/Value.sol";
8
8
 
9
9
  using Cursors for Cur;
@@ -12,11 +12,10 @@ using Cursors for Cur;
12
12
  /// @notice Port that consumes CONTEXT blocks and executes each request as a step stream.
13
13
  /// Each context's request bytes are passed to the shared pipeline.
14
14
  abstract contract PortPipePayable is PortBase, Pipeline {
15
- uint internal immutable portPipePayableId = portId(this.portPipePayable.selector);
15
+ bytes32 private immutable descriptor;
16
16
 
17
17
  constructor() {
18
- emit Port(host, portPipePayableId, "1:0", Schemas.Context, "", true);
19
- emit Labeled(portPipePayableId, bytes32(0), "portPipePayable");
18
+ (, descriptor) = port("portPipePayable", Keys.Context, Keys.Empty, 0, true);
20
19
  }
21
20
 
22
21
  /// @notice Execute peer-supplied contexts through the shared payable pipe.
@@ -25,15 +24,13 @@ abstract contract PortPipePayable is PortBase, Pipeline {
25
24
  /// @param data CONTEXT block stream supplied by the trusted peer.
26
25
  /// @return Empty response bytes.
27
26
  function portPipePayable(bytes calldata data) external payable onlyPeer returns (bytes memory) {
28
- (Cur memory input, ) = Cursors.init(data, 1);
27
+ (Cur memory input, ) = openInput(data, descriptor);
29
28
  Budget memory budget = openValue();
30
29
 
31
30
  while (input.i < input.len) {
32
31
  (bytes32 account, bytes calldata state, bytes calldata request) = input.unpackContext();
33
32
  pipe(account, state, request, budget);
34
33
  }
35
-
36
- input.complete();
37
34
  return "";
38
35
  }
39
36
  }
package/ports/Redeem.sol CHANGED
@@ -2,7 +2,7 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
- import {Cursors, Cur, Schemas} from "../Cursors.sol";
5
+ import {Cursors, Cur, Keys} from "../Cursors.sol";
6
6
 
7
7
  using Cursors for Cur;
8
8
 
@@ -19,26 +19,23 @@ abstract contract RedeemBalanceHook {
19
19
  /// Each BALANCE block in the request calls `redeemBalance(peer, asset, amount)`.
20
20
  /// Restricted to trusted peers.
21
21
  abstract contract PortRedeemBalance is PortBase, RedeemBalanceHook {
22
- uint internal immutable portRedeemBalanceId = portId(this.portRedeemBalance.selector);
22
+ bytes32 private immutable descriptor;
23
23
 
24
24
  constructor() {
25
- emit Port(host, portRedeemBalanceId, "1:0", Schemas.Balance, "", false);
26
- emit Labeled(portRedeemBalanceId, bytes32(0), "portRedeemBalance");
25
+ (, descriptor) = port("portRedeemBalance", Keys.Balance, Keys.Empty, 0, false);
27
26
  }
28
27
 
29
28
  /// @notice Execute the balance redemption port call.
30
29
  /// @param data BALANCE block stream supplied by the trusted peer.
31
30
  /// @return Empty response bytes.
32
31
  function portRedeemBalance(bytes calldata data) external onlyPeer returns (bytes memory) {
33
- (Cur memory input, ) = Cursors.init(data, 1);
32
+ (Cur memory input, ) = openInput(data, descriptor);
34
33
  uint peer = caller();
35
34
 
36
35
  while (input.i < input.len) {
37
36
  (bytes32 asset, uint amount) = input.unpackBalance();
38
37
  redeemBalance(peer, asset, amount);
39
38
  }
40
-
41
- input.complete();
42
39
  return "";
43
40
  }
44
41
  }
package/ports/Settle.sol CHANGED
@@ -4,7 +4,7 @@ pragma solidity ^0.8.33;
4
4
  import { PortBase } from "./Base.sol";
5
5
  import { CreditAccountHook } from "../commands/Credit.sol";
6
6
  import { DebitAccountHook } from "../commands/Debit.sol";
7
- import { Cursors, Cur, Schemas } from "../Cursors.sol";
7
+ import { Cursors, Cur, Keys } from "../Cursors.sol";
8
8
 
9
9
  using Cursors for Cur;
10
10
 
@@ -12,26 +12,23 @@ using Cursors for Cur;
12
12
  /// @notice Port that consumes peer-supplied TRANSACTION blocks through debit and credit hooks.
13
13
  /// Each TRANSACTION block calls `debitAccount` for `from` and `creditAccount` for `to`.
14
14
  abstract contract PortSettle is PortBase, DebitAccountHook, CreditAccountHook {
15
- uint internal immutable portSettleId = portId(this.portSettle.selector);
15
+ bytes32 private immutable descriptor;
16
16
 
17
17
  constructor() {
18
- emit Port(host, portSettleId, "1:0", Schemas.Transaction, "", false);
19
- emit Labeled(portSettleId, bytes32(0), "portSettle");
18
+ (, descriptor) = port("portSettle", Keys.Transaction, Keys.Empty, 0, false);
20
19
  }
21
20
 
22
21
  /// @notice Execute the port-settle call.
23
22
  /// @param data TRANSACTION block stream supplied by the trusted peer.
24
23
  /// @return Empty response bytes.
25
24
  function portSettle(bytes calldata data) external onlyPeer returns (bytes memory) {
26
- (Cur memory state, ) = Cursors.init(data, 1);
25
+ (Cur memory input, ) = openInput(data, descriptor);
27
26
 
28
- while (state.i < state.len) {
29
- (bytes32 from, bytes32 to, bytes32 asset, uint amount) = state.unpackTransaction();
27
+ while (input.i < input.len) {
28
+ (bytes32 from, bytes32 to, bytes32 asset, uint amount) = input.unpackTransaction();
30
29
  if (from != 0) debitAccount(from, asset, amount);
31
30
  if (to != 0) creditAccount(to, asset, amount);
32
31
  }
33
-
34
- state.complete();
35
32
  return "";
36
33
  }
37
34
  }
@@ -1,8 +1,7 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import {Cur, Cursors, Writer, Writers} from "../Cursors.sol";
5
- import {Forms, Schemas} from "../blocks/Schema.sol";
4
+ import {Cur, Cursors, Keys, Writer, Writers} from "../Cursors.sol";
6
5
  import {QueryBase} from "./Base.sol";
7
6
 
8
7
  using Cursors for Cur;
@@ -21,27 +20,25 @@ abstract contract AssetStatusHook {
21
20
  /// The request is a run of `ASSET` blocks.
22
21
  /// The response returns one `STATUS` form block per query entry, preserving request order.
23
22
  abstract contract AssetStatus is QueryBase, AssetStatusHook {
24
- uint public immutable assetStatusId = queryId(this.assetStatus.selector);
23
+ bytes32 private immutable descriptor;
25
24
 
26
25
  constructor() {
27
- emit Query(host, assetStatusId, "1:1", Schemas.Asset, Forms.Status);
28
- emit Labeled(assetStatusId, bytes32(0), "assetStatus");
26
+ (, descriptor) = query("assetStatus", Keys.Asset, Keys.Status, 0);
29
27
  }
30
28
 
31
29
  /// @notice Resolve asset support status for a run of requested assets.
32
- /// @param request Block-stream request consisting of `#asset { bytes32 asset }` blocks.
33
- /// @return Block-stream response containing one `#status { uint code }` per asset block.
30
+ /// @param request Block-stream request consisting of `asset { bytes32 asset }` blocks.
31
+ /// @return Block-stream response containing one `status { uint code }` form block per asset block.
34
32
  function assetStatus(bytes calldata request) external view returns (bytes memory) {
35
- (Cur memory query, uint groups) = Cursors.init(request, 1);
36
- Writer memory response = Writers.allocStatuses(groups);
33
+ (Cur memory input, uint outputs) = openInput(request, descriptor);
34
+ Writer memory response = Writers.allocStatuses(outputs);
37
35
 
38
- while (query.i < query.len) {
39
- bytes32 asset = query.unpackAsset();
36
+ while (input.i < input.len) {
37
+ bytes32 asset = input.unpackAsset();
40
38
  uint status = assetStatus(asset);
41
39
  response.appendStatus(status);
42
40
  }
43
41
 
44
- query.complete();
45
42
  return response.finish();
46
43
  }
47
44
  }
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import {Cur, Cursors, Forms, Writer, Writers} from "../Cursors.sol";
4
+ import {Cur, Cursors, Keys, Writer, Writers} from "../Cursors.sol";
5
5
  import {QueryBase} from "./Base.sol";
6
6
 
7
7
  using Cursors for Cur;
@@ -21,27 +21,25 @@ abstract contract GetBalancesHook {
21
21
  /// The request is a run of `ACCOUNT_ASSET` form blocks.
22
22
  /// The response returns one `ACCOUNT_AMOUNT` form block per requested position, preserving request order.
23
23
  abstract contract GetBalances is QueryBase, GetBalancesHook {
24
- uint public immutable getBalancesId = queryId(this.getBalances.selector);
24
+ bytes32 private immutable descriptor;
25
25
 
26
26
  constructor() {
27
- emit Query(host, getBalancesId, "1:1", Forms.AccountAsset, Forms.AccountAmount);
28
- emit Labeled(getBalancesId, bytes32(0), "getBalances");
27
+ (, descriptor) = query("getBalances", Keys.AccountAsset, Keys.AccountAmount, 0);
29
28
  }
30
29
 
31
30
  /// @notice Resolve balances for a run of requested `(account, asset)` tuples.
32
31
  /// @param request Block-stream request consisting of `accountAsset(account, asset)*`.
33
32
  /// @return Block-stream response containing one `accountAmount(account, asset, amount)` block per request block.
34
33
  function getBalances(bytes calldata request) external view returns (bytes memory) {
35
- (Cur memory query, uint groups) = Cursors.init(request, 1);
36
- Writer memory response = Writers.allocAccountAmounts(groups);
34
+ (Cur memory input, uint outputs) = openInput(request, descriptor);
35
+ Writer memory response = Writers.allocAccountAmounts(outputs);
37
36
 
38
- while (query.i < query.len) {
39
- (bytes32 account, bytes32 asset) = query.unpackAccountAsset();
37
+ while (input.i < input.len) {
38
+ (bytes32 account, bytes32 asset) = input.unpackAccountAsset();
40
39
  uint amount = getBalance(account, asset);
41
40
  response.appendAccountAmount(account, asset, amount);
42
41
  }
43
42
 
44
- query.complete();
45
43
  return response.finish();
46
44
  }
47
45
  }
package/queries/Base.sol CHANGED
@@ -1,23 +1,31 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import { Runtime } from "../core/Runtime.sol";
5
- import { LabeledEvent } from "../events/Labeled.sol";
6
- import { QueryEvent } from "../events/Query.sol";
4
+ import { EndpointBase } from "../core/Endpoint.sol";
7
5
  import { Nodes } from "../utils/Nodes.sol";
6
+ import { Selectors } from "../utils/Selectors.sol";
8
7
 
9
8
  /// @title QueryBase
10
9
  /// @notice Abstract base for rootzero query contracts.
11
10
  /// Queries are view-only entry points that consume a block-stream request and
12
11
  /// return a block-stream response.
13
- abstract contract QueryBase is Runtime, QueryEvent, LabeledEvent {
12
+ abstract contract QueryBase is EndpointBase {
14
13
 
15
- /// @notice Derive the deterministic node ID for a query selector on this contract.
16
- /// The ID encodes the ABI selector and `address(this)`, making it unique
17
- /// per (function selector, contract address) pair.
18
- /// @param selector Query entrypoint selector.
19
- /// @return Query node ID.
20
- function queryId(bytes4 selector) internal view returns (uint) {
21
- return Nodes.toQuery(selector, address(this));
14
+ /// @notice Publish query metadata and a default label.
15
+ /// @param name Default human-readable query label and selector name.
16
+ /// @param input Packed input lane plus optional group byte.
17
+ /// @param output Packed output lane plus optional group byte.
18
+ /// @param selector Query ABI selector, or zero to derive it from `name`.
19
+ /// @return id Query node ID.
20
+ /// @return descriptor Packed endpoint lane metadata and flags.
21
+ function query(
22
+ string memory name,
23
+ bytes9 input,
24
+ bytes9 output,
25
+ bytes4 selector
26
+ ) internal returns (uint id, bytes32 descriptor) {
27
+ selector = selector == bytes4(0) ? Selectors.query(name) : selector;
28
+ id = Nodes.toQuery(selector, address(this));
29
+ descriptor = endpoint(id, name, bytes9(0), input, output, false, false);
22
30
  }
23
31
  }
@@ -0,0 +1,49 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ /// @title Selectors
5
+ /// @notice Canonical ABI selector derivation for rootzero endpoint types.
6
+ library Selectors {
7
+ /// @notice Derive the ABI selector for a command entrypoint.
8
+ /// @param name Command function name.
9
+ /// @return Selector for `name((bytes32,bytes,bytes))`.
10
+ function command(string memory name) internal pure returns (bytes4) {
11
+ return derive(name, "((bytes32,bytes,bytes))");
12
+ }
13
+
14
+ /// @notice Derive the ABI selector for a port entrypoint.
15
+ /// @param name Port function name.
16
+ /// @return Selector for `name(bytes)`.
17
+ function port(string memory name) internal pure returns (bytes4) {
18
+ return direct(name);
19
+ }
20
+
21
+ /// @notice Derive the ABI selector for a query entrypoint.
22
+ /// @param name Query function name.
23
+ /// @return Selector for `name(bytes)`.
24
+ function query(string memory name) internal pure returns (bytes4) {
25
+ return direct(name);
26
+ }
27
+
28
+ /// @notice Derive the ABI selector for a guard action entrypoint.
29
+ /// @param name Guard action function name.
30
+ /// @return Selector for `name(bytes)`.
31
+ function guard(string memory name) internal pure returns (bytes4) {
32
+ return direct(name);
33
+ }
34
+
35
+ /// @dev Derive a direct endpoint selector with a single `bytes` argument.
36
+ /// @param name Endpoint function name.
37
+ /// @return Selector for `name(bytes)`.
38
+ function direct(string memory name) private pure returns (bytes4) {
39
+ return derive(name, "(bytes)");
40
+ }
41
+
42
+ /// @dev Derive an ABI selector from a function name and argument signature suffix.
43
+ /// @param name Function name.
44
+ /// @param args Parenthesized ABI argument signature.
45
+ /// @return First four bytes of the function signature hash.
46
+ function derive(string memory name, string memory args) private pure returns (bytes4) {
47
+ return bytes4(keccak256(bytes(string.concat(name, args))));
48
+ }
49
+ }
@@ -1,43 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import { AdminBase, CommandContext, Keys } from "./Base.sol";
5
- import { Cursors, Cur } from "../../Cursors.sol";
6
-
7
- using Cursors for Cur;
8
-
9
- abstract contract DestroyHook {
10
- /// @notice Override to run host teardown or destruction logic.
11
- /// @param input Cursor over the full request byte stream.
12
- function destroy(Cur memory input) internal virtual;
13
- }
14
-
15
- /// @title Destroy
16
- /// @notice Admin command that runs host teardown logic via a virtual hook.
17
- /// The full request is passed to `destroy` as a cursor. Only callable by the admin account.
18
- abstract contract Destroy is AdminBase, DestroyHook {
19
- uint internal immutable destroyId = commandId(this.destroy.selector);
20
-
21
- /// @param input Request schema advertised for destruction input.
22
- constructor(string memory input) {
23
- emit Admin(host, destroyId, "1:0:0", input, Keys.Empty, Keys.Empty, false);
24
- emit Labeled(destroyId, bytes32(0), "destroy");
25
- }
26
-
27
- /// @notice Run host teardown logic over the full admin request.
28
- /// @param c Admin command context; `c.request` is passed through as a cursor.
29
- /// @return Empty output state.
30
- function destroy(
31
- CommandContext calldata c
32
- ) external onlyAdmin(c.account) returns (bytes memory) {
33
- destroy(Cursors.open(c.request));
34
- return "";
35
- }
36
- }
37
-
38
-
39
-
40
-
41
-
42
-
43
-
@@ -1,43 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import { AdminBase, CommandContext, Keys } from "./Base.sol";
5
- import { Cursors, Cur } from "../../Cursors.sol";
6
-
7
- using Cursors for Cur;
8
-
9
- abstract contract InitHook {
10
- /// @notice Override to run host initialization logic.
11
- /// @param input Cursor over the full request byte stream.
12
- function init(Cur memory input) internal virtual;
13
- }
14
-
15
- /// @title Init
16
- /// @notice Admin command that runs host initialization logic via a virtual hook.
17
- /// The full request is passed to `init` as a cursor. Only callable by the admin account.
18
- abstract contract Init is AdminBase, InitHook {
19
- uint internal immutable initId = commandId(this.init.selector);
20
-
21
- /// @param input Request schema advertised for initialization input.
22
- constructor(string memory input) {
23
- emit Admin(host, initId, "1:0:0", input, Keys.Empty, Keys.Empty, false);
24
- emit Labeled(initId, bytes32(0), "init");
25
- }
26
-
27
- /// @notice Run host initialization logic over the full admin request.
28
- /// @param c Admin command context; `c.request` is passed through as a cursor.
29
- /// @return Empty output state.
30
- function init(
31
- CommandContext calldata c
32
- ) external onlyAdmin(c.account) returns (bytes memory) {
33
- init(Cursors.open(c.request));
34
- return "";
35
- }
36
- }
37
-
38
-
39
-
40
-
41
-
42
-
43
-
package/events/Admin.sol DELETED
@@ -1,32 +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 once per admin command during host deployment to publish its request schema and state keys.
7
- abstract contract AdminEvent is EventEmitter {
8
- string private constant ABI =
9
- "event Admin(uint indexed host, uint id, bytes32 shape, string request, bytes4 state, bytes4 output, bool funded)";
10
-
11
- /// @param host Host node ID that owns this admin command.
12
- /// @param id Command node ID.
13
- /// @param shape Per-operation block counts encoded as `request:state:output`.
14
- /// Request and state are each a single run of blocks under the current command convention.
15
- /// @param request Schema DSL string describing the input request run, or empty if none.
16
- /// @param state Block key expected for input state, `Keys.Empty`, or `Keys.Any`.
17
- /// @param output Block key produced for output state, or `Keys.Empty`.
18
- /// @param funded Whether the command entrypoint accepts nonzero `msg.value`.
19
- event Admin(
20
- uint indexed host,
21
- uint id,
22
- bytes32 shape,
23
- string request,
24
- bytes4 state,
25
- bytes4 output,
26
- bool funded
27
- );
28
-
29
- constructor() {
30
- emit EventAbi(ABI);
31
- }
32
- }
@@ -1,32 +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 once per command during host deployment to publish its request schema and state keys.
7
- abstract contract CommandEvent is EventEmitter {
8
- string private constant ABI =
9
- "event Command(uint indexed host, uint id, bytes32 shape, string request, bytes4 state, bytes4 output, bool funded)";
10
-
11
- /// @param host Host node ID that owns this command.
12
- /// @param id Command node ID.
13
- /// @param shape Per-operation block counts encoded as `request:state:output`.
14
- /// Request and state are each a single run of blocks under the current command convention.
15
- /// @param request Schema string describing the input request run, or empty if none.
16
- /// @param state Block key expected for input state, `Keys.Empty`, or `Keys.Any`.
17
- /// @param output Block key produced for output state, or `Keys.Empty`.
18
- /// @param funded Whether the command entrypoint accepts nonzero `msg.value`.
19
- event Command(
20
- uint indexed host,
21
- uint id,
22
- bytes32 shape,
23
- string request,
24
- bytes4 state,
25
- bytes4 output,
26
- bool funded
27
- );
28
-
29
- constructor() {
30
- emit EventAbi(ABI);
31
- }
32
- }
package/events/Guard.sol DELETED
@@ -1,18 +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 once per guard action during host deployment to publish its request schema.
7
- abstract contract GuardEvent is EventEmitter {
8
- string private constant ABI = "event Guard(uint indexed host, uint id, string request)";
9
-
10
- /// @param host Host node ID that owns this guard action.
11
- /// @param id Guard action node ID.
12
- /// @param request Schema DSL string describing the guard action request shape.
13
- event Guard(uint indexed host, uint id, string request);
14
-
15
- constructor() {
16
- emit EventAbi(ABI);
17
- }
18
- }
package/events/Port.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 by hosts to advertise callable peer-facing ports.
7
- abstract contract PortEvent is EventEmitter {
8
- string private constant ABI =
9
- "event Port(uint indexed host, uint id, bytes32 shape, string request, string response, bool funded)";
10
-
11
- /// @param host Host node ID that exposes the port.
12
- /// @param id Port node ID.
13
- /// @param shape Block shape/version descriptor.
14
- /// @param request Human-readable request schema.
15
- /// @param response Human-readable response schema.
16
- /// @param funded True if the port accepts native value.
17
- event Port(uint indexed host, uint id, bytes32 shape, string request, string response, bool funded);
18
-
19
- constructor() {
20
- emit EventAbi(ABI);
21
- }
22
- }
package/events/Query.sol DELETED
@@ -1,20 +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 once per query during host deployment to publish its request and response schemas.
7
- abstract contract QueryEvent is EventEmitter {
8
- string private constant ABI = "event Query(uint indexed host, uint id, bytes32 shape, string request, string response)";
9
-
10
- /// @param host Host node ID that owns this query.
11
- /// @param id Query node ID.
12
- /// @param shape Per-operation block counts encoded as `request:response`.
13
- /// @param request Schema DSL string describing the input request run, or empty if none.
14
- /// @param response Schema DSL string describing the query response shape.
15
- event Query(uint indexed host, uint id, bytes32 shape, string request, string response);
16
-
17
- constructor() {
18
- emit EventAbi(ABI);
19
- }
20
- }