@rootzero/contracts 1.2.0 → 1.4.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 (49) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/Endpoints.sol +9 -7
  3. package/Events.sol +2 -2
  4. package/README.md +300 -79
  5. package/blocks/Cursors.sol +10 -14
  6. package/blocks/Schema.sol +7 -4
  7. package/commands/Burn.sol +2 -2
  8. package/commands/Credit.sol +2 -2
  9. package/commands/Debit.sol +2 -2
  10. package/commands/Deposit.sol +4 -4
  11. package/commands/Payout.sol +3 -3
  12. package/commands/Provision.sol +4 -4
  13. package/commands/Relay.sol +2 -2
  14. package/commands/Withdraw.sol +2 -2
  15. package/commands/admin/AllowAssets.sol +2 -2
  16. package/commands/admin/Allowance.sol +2 -2
  17. package/commands/admin/Appoint.sol +2 -2
  18. package/commands/admin/Authorize.sol +2 -2
  19. package/commands/admin/DenyAssets.sol +2 -2
  20. package/commands/admin/Destroy.sol +1 -1
  21. package/commands/admin/Dismiss.sol +2 -2
  22. package/commands/admin/Execute.sol +2 -2
  23. package/commands/admin/Init.sol +1 -1
  24. package/commands/admin/Label.sol +2 -2
  25. package/commands/admin/Unauthorize.sol +2 -2
  26. package/core/Pipeline.sol +1 -1
  27. package/docs/Schema.md +59 -2
  28. package/events/Admin.sol +2 -6
  29. package/events/Command.sol +2 -6
  30. package/events/Commander.sol +19 -0
  31. package/events/Labeled.sol +7 -4
  32. package/events/Route.sol +18 -0
  33. package/guards/Revoke.sol +1 -1
  34. package/package.json +1 -1
  35. package/peer/AllowAssets.sol +6 -2
  36. package/peer/Allowance.sol +6 -2
  37. package/peer/BalancePull.sol +6 -2
  38. package/peer/Credit.sol +39 -0
  39. package/peer/Debit.sol +39 -0
  40. package/peer/DenyAssets.sol +6 -2
  41. package/peer/Dispatch.sol +6 -2
  42. package/peer/Pipe.sol +6 -2
  43. package/peer/Settle.sol +6 -2
  44. package/queries/Assets.sol +1 -1
  45. package/queries/Balances.sol +1 -1
  46. package/queries/Positions.sol +1 -1
  47. package/utils/Actions.sol +1 -0
  48. package/events/Chain.sol +0 -19
  49. package/events/Transfer.sol +0 -22
@@ -40,7 +40,7 @@ abstract contract Deposit is CommandBase, DepositHook {
40
40
  uint internal immutable depositId = commandId(this.deposit.selector);
41
41
 
42
42
  constructor() {
43
- emit Command(host, depositId, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false, false);
43
+ emit Command(host, depositId, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false);
44
44
  emit Labeled(depositId, bytes32(0), "deposit");
45
45
  }
46
46
 
@@ -50,7 +50,7 @@ abstract contract Deposit is CommandBase, DepositHook {
50
50
  function deposit(
51
51
  CommandContext calldata c
52
52
  ) external onlyCommand returns (bytes memory) {
53
- (Cur memory request, uint groups, ) = Cursors.init(c.request, 0, 1);
53
+ (Cur memory request, uint groups, ) = Cursors.init(c.request, 1);
54
54
  Writer memory writer = Writers.allocBalances(groups);
55
55
 
56
56
  while (request.i < request.len) {
@@ -71,7 +71,7 @@ abstract contract DepositPayable is CommandBase, Payable, DepositPayableHook {
71
71
  uint internal immutable depositPayableId = commandId(this.depositPayable.selector);
72
72
 
73
73
  constructor() {
74
- emit Command(host, depositPayableId, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false, true);
74
+ emit Command(host, depositPayableId, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, true);
75
75
  emit Labeled(depositPayableId, bytes32(0), "depositPayable");
76
76
  }
77
77
 
@@ -81,7 +81,7 @@ abstract contract DepositPayable is CommandBase, Payable, DepositPayableHook {
81
81
  function depositPayable(
82
82
  CommandContext calldata c
83
83
  ) external payable onlyCommand returns (bytes memory) {
84
- (Cur memory request, uint groups, ) = Cursors.init(c.request, 0, 1);
84
+ (Cur memory request, uint groups, ) = Cursors.init(c.request, 1);
85
85
  Writer memory writer = Writers.allocBalances(groups);
86
86
  Budget memory budget = valueBudget();
87
87
 
@@ -25,7 +25,7 @@ abstract contract Payout is CommandBase, PayoutHook {
25
25
  uint internal immutable payoutId = commandId(this.payout.selector);
26
26
 
27
27
  constructor() {
28
- emit Command(host, payoutId, "1:1:0", Schemas.Account, Keys.Balance, Keys.Empty, false, false);
28
+ emit Command(host, payoutId, "1:1:0", Schemas.Account, Keys.Balance, Keys.Empty, false);
29
29
  emit Labeled(payoutId, bytes32(0), "payout");
30
30
  }
31
31
 
@@ -33,8 +33,8 @@ abstract contract Payout is CommandBase, PayoutHook {
33
33
  /// @param c Command context; `c.state` must contain BALANCE blocks and `c.request` matching ACCOUNT blocks.
34
34
  /// @return Empty output state.
35
35
  function payout(CommandContext calldata c) external onlyCommand returns (bytes memory) {
36
- (Cur memory state, uint groups, ) = Cursors.init(c.state, 0, 1);
37
- (Cur memory request, ) = Cursors.init(c.request, 0, 1, groups);
36
+ (Cur memory state, uint groups, ) = Cursors.init(c.state, 1);
37
+ (Cur memory request, ) = Cursors.init(c.request, 1, groups);
38
38
 
39
39
  while (state.i < state.len) {
40
40
  (bytes32 asset, bytes32 meta, uint amount) = state.unpackBalance();
@@ -36,7 +36,7 @@ abstract contract Provision is CommandBase, ProvisionHook {
36
36
  uint internal immutable provisionId = commandId(this.provision.selector);
37
37
 
38
38
  constructor() {
39
- emit Command(host, provisionId, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, false, false);
39
+ emit Command(host, provisionId, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, false);
40
40
  emit Labeled(provisionId, bytes32(0), "provision");
41
41
  }
42
42
 
@@ -44,7 +44,7 @@ abstract contract Provision is CommandBase, ProvisionHook {
44
44
  /// @param c Command context; `c.request` must contain ALLOCATION blocks.
45
45
  /// @return CUSTODY block stream matching the provisioned allocations.
46
46
  function provision(CommandContext calldata c) external onlyCommand returns (bytes memory) {
47
- (Cur memory request, uint groups, ) = Cursors.init(c.request, 0, 1);
47
+ (Cur memory request, uint groups, ) = Cursors.init(c.request, 1);
48
48
  Writer memory writer = Writers.allocCustodies(groups);
49
49
 
50
50
  while (request.i < request.len) {
@@ -66,7 +66,7 @@ abstract contract ProvisionPayable is CommandBase, Payable, ProvisionPayableHook
66
66
  uint internal immutable provisionPayableId = commandId(this.provisionPayable.selector);
67
67
 
68
68
  constructor() {
69
- emit Command(host, provisionPayableId, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, false, true);
69
+ emit Command(host, provisionPayableId, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, true);
70
70
  emit Labeled(provisionPayableId, bytes32(0), "provisionPayable");
71
71
  }
72
72
 
@@ -76,7 +76,7 @@ abstract contract ProvisionPayable is CommandBase, Payable, ProvisionPayableHook
76
76
  function provisionPayable(
77
77
  CommandContext calldata c
78
78
  ) external payable onlyCommand returns (bytes memory) {
79
- (Cur memory request, uint groups, ) = Cursors.init(c.request, 0, 1);
79
+ (Cur memory request, uint groups, ) = Cursors.init(c.request, 1);
80
80
  Writer memory writer = Writers.allocCustodies(groups);
81
81
  Budget memory budget = valueBudget();
82
82
 
@@ -28,7 +28,7 @@ abstract contract RelayPayable is CommandBase, Payable, DispatchPayableHook {
28
28
  uint internal immutable relayPayableId = commandId(this.relayPayable.selector);
29
29
 
30
30
  constructor() {
31
- emit Command(host, relayPayableId, "1:0:0", Schemas.Relay, Keys.Any, Keys.Empty, false, true);
31
+ emit Command(host, relayPayableId, "1:0:0", Schemas.Relay, Keys.Any, Keys.Empty, true);
32
32
  emit Labeled(relayPayableId, bytes32(0), "relayPayable");
33
33
  }
34
34
 
@@ -36,7 +36,7 @@ abstract contract RelayPayable is CommandBase, Payable, DispatchPayableHook {
36
36
  /// @param c Command context; `c.request` must contain exactly one RELAY block.
37
37
  /// @return output Empty output state.
38
38
  function relayPayable(CommandContext calldata c) external payable onlyCommand returns (bytes memory output) {
39
- (Cur memory request, ) = Cursors.init(c.request, 0, 1, 1);
39
+ (Cur memory request, ) = Cursors.init(c.request, 1, 1);
40
40
  Budget memory budget = valueBudget();
41
41
 
42
42
  (uint chain, uint resources, bytes memory pipe) = request.relayToPipe(c.account, c.state);
@@ -23,7 +23,7 @@ abstract contract Withdraw is CommandBase, WithdrawHook {
23
23
  uint internal immutable withdrawId = commandId(this.withdraw.selector);
24
24
 
25
25
  constructor() {
26
- emit Command(host, withdrawId, "0:1:0", "", Keys.Balance, Keys.Empty, false, false);
26
+ emit Command(host, withdrawId, "0:1:0", "", Keys.Balance, Keys.Empty, false);
27
27
  emit Labeled(withdrawId, bytes32(0), "withdraw");
28
28
  }
29
29
 
@@ -33,7 +33,7 @@ abstract contract Withdraw is CommandBase, WithdrawHook {
33
33
  function withdraw(
34
34
  CommandContext calldata c
35
35
  ) external onlyCommand returns (bytes memory) {
36
- (Cur memory state, , ) = Cursors.init(c.state, 0, 1);
36
+ (Cur memory state, , ) = Cursors.init(c.state, 1);
37
37
 
38
38
  while (state.i < state.len) {
39
39
  (bytes32 asset, bytes32 meta, uint amount) = state.unpackBalance();
@@ -21,7 +21,7 @@ abstract contract AllowAssets is CommandBase, AdminEvent, AllowAssetsHook {
21
21
  uint internal immutable allowAssetsId = commandId(this.allowAssets.selector);
22
22
 
23
23
  constructor() {
24
- emit Admin(host, allowAssetsId, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false, false);
24
+ emit Admin(host, allowAssetsId, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false);
25
25
  emit Labeled(allowAssetsId, bytes32(0), "allowAssets");
26
26
  }
27
27
 
@@ -31,7 +31,7 @@ abstract contract AllowAssets is CommandBase, AdminEvent, AllowAssetsHook {
31
31
  function allowAssets(
32
32
  CommandContext calldata c
33
33
  ) external onlyAdmin(c.account) returns (bytes memory) {
34
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
34
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
35
35
 
36
36
  while (request.i < request.len) {
37
37
  (bytes32 asset, bytes32 meta) = request.unpackAsset();
@@ -25,7 +25,7 @@ abstract contract Allowance is CommandBase, AdminEvent, AllowanceHook {
25
25
  uint internal immutable allowanceId = commandId(this.allowance.selector);
26
26
 
27
27
  constructor() {
28
- emit Admin(host, allowanceId, "1:0:0", Schemas.Allowance, Keys.Empty, Keys.Empty, false, false);
28
+ emit Admin(host, allowanceId, "1:0:0", Schemas.Allowance, Keys.Empty, Keys.Empty, false);
29
29
  emit Labeled(allowanceId, bytes32(0), "allowance");
30
30
  }
31
31
 
@@ -33,7 +33,7 @@ abstract contract Allowance is CommandBase, AdminEvent, AllowanceHook {
33
33
  /// @param c Admin command context; `c.request` must contain ALLOWANCE blocks.
34
34
  /// @return Empty output state.
35
35
  function allowance(CommandContext calldata c) external onlyAdmin(c.account) returns (bytes memory) {
36
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
36
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
37
37
 
38
38
  while (request.i < request.len) {
39
39
  (uint peer, bytes32 asset, bytes32 meta, uint amount) = request.unpackAllowance();
@@ -14,7 +14,7 @@ abstract contract Appoint is CommandBase, AdminEvent {
14
14
  uint internal immutable appointId = commandId(this.appoint.selector);
15
15
 
16
16
  constructor() {
17
- emit Admin(host, appointId, "1:0:0", Schemas.Account, Keys.Empty, Keys.Empty, false, false);
17
+ emit Admin(host, appointId, "1:0:0", Schemas.Account, Keys.Empty, Keys.Empty, false);
18
18
  emit Labeled(appointId, bytes32(0), "appoint");
19
19
  }
20
20
 
@@ -24,7 +24,7 @@ abstract contract Appoint is CommandBase, AdminEvent {
24
24
  function appoint(
25
25
  CommandContext calldata c
26
26
  ) external onlyAdmin(c.account) returns (bytes memory) {
27
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
27
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
28
28
 
29
29
  while (request.i < request.len) {
30
30
  bytes32 account = request.unpackAccount();
@@ -14,7 +14,7 @@ abstract contract Authorize is CommandBase, AdminEvent {
14
14
  uint internal immutable authorizeId = commandId(this.authorize.selector);
15
15
 
16
16
  constructor() {
17
- emit Admin(host, authorizeId, "1:0:0", Schemas.Node, Keys.Empty, Keys.Empty, false, false);
17
+ emit Admin(host, authorizeId, "1:0:0", Schemas.Node, Keys.Empty, Keys.Empty, false);
18
18
  emit Labeled(authorizeId, bytes32(0), "authorize");
19
19
  }
20
20
 
@@ -24,7 +24,7 @@ abstract contract Authorize is CommandBase, AdminEvent {
24
24
  function authorize(
25
25
  CommandContext calldata c
26
26
  ) external onlyAdmin(c.account) returns (bytes memory) {
27
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
27
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
28
28
 
29
29
  while (request.i < request.len) {
30
30
  uint node = request.unpackNode();
@@ -21,7 +21,7 @@ abstract contract DenyAssets is CommandBase, AdminEvent, DenyAssetsHook {
21
21
  uint internal immutable denyAssetsId = commandId(this.denyAssets.selector);
22
22
 
23
23
  constructor() {
24
- emit Admin(host, denyAssetsId, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false, false);
24
+ emit Admin(host, denyAssetsId, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false);
25
25
  emit Labeled(denyAssetsId, bytes32(0), "denyAssets");
26
26
  }
27
27
 
@@ -31,7 +31,7 @@ abstract contract DenyAssets is CommandBase, AdminEvent, DenyAssetsHook {
31
31
  function denyAssets(
32
32
  CommandContext calldata c
33
33
  ) external onlyAdmin(c.account) returns (bytes memory) {
34
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
34
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
35
35
 
36
36
  while (request.i < request.len) {
37
37
  (bytes32 asset, bytes32 meta) = request.unpackAsset();
@@ -20,7 +20,7 @@ abstract contract Destroy is CommandBase, AdminEvent, DestroyHook {
20
20
  uint internal immutable destroyId = commandId(this.destroy.selector);
21
21
 
22
22
  constructor(string memory input) {
23
- emit Admin(host, destroyId, "1:0:0", input, Keys.Empty, Keys.Empty, false, false);
23
+ emit Admin(host, destroyId, "1:0:0", input, Keys.Empty, Keys.Empty, false);
24
24
  emit Labeled(destroyId, bytes32(0), "destroy");
25
25
  }
26
26
 
@@ -14,7 +14,7 @@ abstract contract Dismiss is CommandBase, AdminEvent {
14
14
  uint internal immutable dismissId = commandId(this.dismiss.selector);
15
15
 
16
16
  constructor() {
17
- emit Admin(host, dismissId, "1:0:0", Schemas.Account, Keys.Empty, Keys.Empty, false, false);
17
+ emit Admin(host, dismissId, "1:0:0", Schemas.Account, Keys.Empty, Keys.Empty, false);
18
18
  emit Labeled(dismissId, bytes32(0), "dismiss");
19
19
  }
20
20
 
@@ -24,7 +24,7 @@ abstract contract Dismiss is CommandBase, AdminEvent {
24
24
  function dismiss(
25
25
  CommandContext calldata c
26
26
  ) external onlyAdmin(c.account) returns (bytes memory) {
27
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
27
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
28
28
 
29
29
  while (request.i < request.len) {
30
30
  bytes32 account = request.unpackAccount();
@@ -19,7 +19,7 @@ abstract contract ExecutePayable is CommandBase, Payable, AdminEvent {
19
19
  uint internal immutable executePayableId = commandId(this.executePayable.selector);
20
20
 
21
21
  constructor() {
22
- emit Admin(host, executePayableId, "1:0:0", Schemas.Call, Keys.Empty, Keys.Empty, false, true);
22
+ emit Admin(host, executePayableId, "1:0:0", Schemas.Call, Keys.Empty, Keys.Empty, true);
23
23
  emit Labeled(executePayableId, bytes32(0), "executePayable");
24
24
  }
25
25
 
@@ -27,7 +27,7 @@ abstract contract ExecutePayable is CommandBase, Payable, AdminEvent {
27
27
  /// @param c Admin command context; `c.request` must contain CALL blocks.
28
28
  /// @return Empty output state.
29
29
  function executePayable(CommandContext calldata c) external payable onlyAdmin(c.account) returns (bytes memory) {
30
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
30
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
31
31
  Budget memory budget = valueBudget();
32
32
 
33
33
  while (request.i < request.len) {
@@ -20,7 +20,7 @@ abstract contract Init is CommandBase, AdminEvent, InitHook {
20
20
  uint internal immutable initId = commandId(this.init.selector);
21
21
 
22
22
  constructor(string memory input) {
23
- emit Admin(host, initId, "1:0:0", input, Keys.Empty, Keys.Empty, false, false);
23
+ emit Admin(host, initId, "1:0:0", input, Keys.Empty, Keys.Empty, false);
24
24
  emit Labeled(initId, bytes32(0), "init");
25
25
  }
26
26
 
@@ -14,7 +14,7 @@ abstract contract Label is CommandBase, AdminEvent {
14
14
  uint internal immutable labelId = commandId(this.label.selector);
15
15
 
16
16
  constructor() {
17
- emit Admin(host, labelId, "1:0:0", Schemas.Label, Keys.Empty, Keys.Empty, false, false);
17
+ emit Admin(host, labelId, "1:0:0", Schemas.Label, Keys.Empty, Keys.Empty, false);
18
18
  emit Labeled(labelId, bytes32(0), "label");
19
19
  }
20
20
 
@@ -22,7 +22,7 @@ abstract contract Label is CommandBase, AdminEvent {
22
22
  /// @param c Admin command context; `c.request` must contain LABEL blocks.
23
23
  /// @return Empty output state.
24
24
  function label(CommandContext calldata c) external onlyAdmin(c.account) returns (bytes memory) {
25
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
25
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
26
26
 
27
27
  while (request.i < request.len) {
28
28
  (uint id, bytes32 namespace, string memory name) = request.unpackLabel();
@@ -14,7 +14,7 @@ abstract contract Unauthorize is CommandBase, AdminEvent {
14
14
  uint internal immutable unauthorizeId = commandId(this.unauthorize.selector);
15
15
 
16
16
  constructor() {
17
- emit Admin(host, unauthorizeId, "1:0:0", Schemas.Node, Keys.Empty, Keys.Empty, false, false);
17
+ emit Admin(host, unauthorizeId, "1:0:0", Schemas.Node, Keys.Empty, Keys.Empty, false);
18
18
  emit Labeled(unauthorizeId, bytes32(0), "unauthorize");
19
19
  }
20
20
 
@@ -24,7 +24,7 @@ abstract contract Unauthorize is CommandBase, AdminEvent {
24
24
  function unauthorize(
25
25
  CommandContext calldata c
26
26
  ) external onlyAdmin(c.account) returns (bytes memory) {
27
- (Cur memory request, , ) = Cursors.init(c.request, 0, 1);
27
+ (Cur memory request, , ) = Cursors.init(c.request, 1);
28
28
 
29
29
  while (request.i < request.len) {
30
30
  uint node = request.unpackNode();
package/core/Pipeline.sol CHANGED
@@ -42,7 +42,7 @@ abstract contract Pipeline is Payable {
42
42
  bytes calldata steps,
43
43
  Budget memory budget
44
44
  ) internal {
45
- (Cur memory input, , ) = Cursors.init(steps, 0, 1);
45
+ (Cur memory input, , ) = Cursors.init(steps, 1);
46
46
 
47
47
  while (input.i < input.len) {
48
48
  (uint target, uint resources, bytes calldata request) = input.unpackStep();
package/docs/Schema.md CHANGED
@@ -101,6 +101,11 @@ the whole batch and are not counted as per-operation prime blocks.
101
101
  The prime item cannot be optional. If a command needs a per-operation marker with
102
102
  no payload, use a zero-payload block such as `#unit`.
103
103
 
104
+ Command request and state streams currently use a narrower convention than the
105
+ full block grammar: each is a single run of blocks, without additional global
106
+ items. Future protocol surfaces may use the more flexible top-level structure,
107
+ but command discovery metadata should describe only that one-run shape.
108
+
104
109
  ## Aliases
105
110
 
106
111
  Aliases are presentation metadata for tooling. They do not change payload layout
@@ -113,6 +118,53 @@ maybe #account { bytes32 account } as recipient
113
118
 
114
119
  Aliases may be used on any block item, including child blocks and prime items.
115
120
 
121
+ ## Field Paths
122
+
123
+ Field names and aliases may use dotted paths for offchain projection. A dotted
124
+ path does not change the block key, payload bytes, payload length, cursor
125
+ behavior, or any onchain validation. It is metadata only.
126
+
127
+ ```txt
128
+ #dispatch { uint dst.chain, uint dst.resources, #bytes as dst.payload }
129
+ ```
130
+
131
+ This has the same runtime layout as:
132
+
133
+ ```txt
134
+ #dispatch { uint chain, uint resources, #bytes as payload }
135
+ ```
136
+
137
+ Offchain tooling may decode the dotted form into a nested object:
138
+
139
+ ```ts
140
+ {
141
+ dst: {
142
+ chain,
143
+ resources,
144
+ payload
145
+ }
146
+ }
147
+ ```
148
+
149
+ Encoding and decoding must still follow schema declaration order, not object
150
+ property order. Fields with the same path prefix do not need to be contiguous,
151
+ although contiguous fields are easier to read when they represent one logical
152
+ object.
153
+
154
+ Tooling should reject duplicate full paths and prefix/value collisions:
155
+
156
+ ```txt
157
+ uint dst.chain, uint dst.chain // duplicate path
158
+ uint dst, uint dst.chain // prefix/value collision
159
+ ```
160
+
161
+ The same rule applies to block aliases:
162
+
163
+ ```txt
164
+ #call { uint target, uint resources, #bytes as calldata.payload }
165
+ maybe #account { bytes32 account } as recipient.account
166
+ ```
167
+
116
168
  ## Field Types
117
169
 
118
170
  Supported field types are chain-neutral:
@@ -140,10 +192,12 @@ endowment in wei; higher bits are reserved for execution resources such as gas.
140
192
 
141
193
  ## Identifiers
142
194
 
143
- Block names, field names, and aliases use lower camelCase ASCII identifiers:
195
+ Block names use lower camelCase ASCII identifiers. Field names and aliases use
196
+ one or more lower camelCase path segments separated by dots:
144
197
 
145
198
  ```txt
146
199
  [a-z][a-zA-Z0-9]*
200
+ [a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)*
147
201
  ```
148
202
 
149
203
  Invalid examples:
@@ -153,10 +207,13 @@ Amount
153
207
  asset_meta
154
208
  asset-meta
155
209
  0account
210
+ asset.
211
+ .asset
156
212
  ```
157
213
 
158
214
  Reserved words include `maybe`, `many`, `as`, all field type names, and the
159
- reserved block names `bytes`, `data`, and `list`.
215
+ reserved block names `bytes`, `data`, and `list`. For dotted paths, reserved
216
+ words are invalid in any path segment.
160
217
 
161
218
  ## Reserved Blocks
162
219
 
package/events/Admin.sol CHANGED
@@ -6,18 +6,15 @@ import {EventEmitter} from "./Emitter.sol";
6
6
  /// @notice Emitted once per admin command during host deployment to publish its request schema and state keys.
7
7
  abstract contract AdminEvent is EventEmitter {
8
8
  string private constant ABI =
9
- "event Admin(uint indexed host, uint id, bytes32 shape, string request, bytes4 state, bytes4 output, bool postcheck, bool funded)";
9
+ "event Admin(uint indexed host, uint id, bytes32 shape, string request, bytes4 state, bytes4 output, bool funded)";
10
10
 
11
11
  /// @param host Host node ID that owns this admin command.
12
12
  /// @param id Command node ID.
13
13
  /// @param shape Per-operation block counts encoded as `request:state:output`.
14
- /// The request count covers only the input request run. If `postcheck` is true,
15
- /// a constraint run follows the input run, or starts the request when `request`
16
- /// is empty. State globals may follow the state run and are excluded.
14
+ /// Request and state are each a single run of blocks under the current command convention.
17
15
  /// @param request Schema DSL string describing the input request run, or empty if none.
18
16
  /// @param state Block key expected for input state, `Keys.Empty`, or `Keys.Any`.
19
17
  /// @param output Block key produced for output state, or `Keys.Empty`.
20
- /// @param postcheck Whether command output is validated after execution.
21
18
  /// @param funded Whether the command entrypoint accepts nonzero `msg.value`.
22
19
  event Admin(
23
20
  uint indexed host,
@@ -26,7 +23,6 @@ abstract contract AdminEvent is EventEmitter {
26
23
  string request,
27
24
  bytes4 state,
28
25
  bytes4 output,
29
- bool postcheck,
30
26
  bool funded
31
27
  );
32
28
 
@@ -6,18 +6,15 @@ import {EventEmitter} from "./Emitter.sol";
6
6
  /// @notice Emitted once per command during host deployment to publish its request schema and state keys.
7
7
  abstract contract CommandEvent is EventEmitter {
8
8
  string private constant ABI =
9
- "event Command(uint indexed host, uint id, bytes32 shape, string request, bytes4 state, bytes4 output, bool postcheck, bool funded)";
9
+ "event Command(uint indexed host, uint id, bytes32 shape, string request, bytes4 state, bytes4 output, bool funded)";
10
10
 
11
11
  /// @param host Host node ID that owns this command.
12
12
  /// @param id Command node ID.
13
13
  /// @param shape Per-operation block counts encoded as `request:state:output`.
14
- /// The request count covers only the input request run. If `postcheck` is true,
15
- /// a constraint run follows the input run, or starts the request when `request`
16
- /// is empty. State globals may follow the state run and are excluded.
14
+ /// Request and state are each a single run of blocks under the current command convention.
17
15
  /// @param request Schema string describing the input request run, or empty if none.
18
16
  /// @param state Block key expected for input state, `Keys.Empty`, or `Keys.Any`.
19
17
  /// @param output Block key produced for output state, or `Keys.Empty`.
20
- /// @param postcheck Whether command output is validated after execution.
21
18
  /// @param funded Whether the command entrypoint accepts nonzero `msg.value`.
22
19
  event Command(
23
20
  uint indexed host,
@@ -26,7 +23,6 @@ abstract contract CommandEvent is EventEmitter {
26
23
  string request,
27
24
  bytes4 state,
28
25
  bytes4 output,
29
- bool postcheck,
30
26
  bool funded
31
27
  );
32
28
 
@@ -0,0 +1,19 @@
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 a commander is announced for a chain/domain.
7
+ abstract contract CommanderEvent is EventEmitter {
8
+ string private constant ABI = "event Commander(uint indexed host, uint chain, bytes32 native, bytes32 admin)";
9
+
10
+ /// @param host Commander host node ID for the chain.
11
+ /// @param chain Chain/domain node ID.
12
+ /// @param native Native asset ID for the chain.
13
+ /// @param admin Admin account for the commander host on the chain.
14
+ event Commander(uint indexed host, uint chain, bytes32 native, bytes32 admin);
15
+
16
+ constructor() {
17
+ emit EventAbi(ABI);
18
+ }
19
+ }
@@ -3,14 +3,17 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import {EventEmitter} from "./Emitter.sol";
5
5
 
6
- /// @notice Emitted to attach a human-readable namespaced label to a node ID.
6
+ /// @notice Emitted to attach a human-readable namespaced label to an entity.
7
+ /// @dev Labels are claims by the emitting contract. Any contract may emit a
8
+ /// label for any entity, so off-chain indexers must decide which emitters are
9
+ /// trusted for each labeled entity or namespace.
7
10
  abstract contract LabeledEvent is EventEmitter {
8
- string private constant ABI = "event Labeled(uint indexed id, bytes32 namespace, string name)";
11
+ string private constant ABI = "event Labeled(uint indexed entity, bytes32 namespace, string name)";
9
12
 
10
- /// @param id Node or capability ID being labeled.
13
+ /// @param entity Entity being labeled.
11
14
  /// @param namespace Label namespace.
12
15
  /// @param name Human-readable name within the namespace.
13
- event Labeled(uint indexed id, bytes32 namespace, string name);
16
+ event Labeled(uint indexed entity, bytes32 namespace, string name);
14
17
 
15
18
  constructor() {
16
19
  emit EventAbi(ABI);
@@ -0,0 +1,18 @@
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 a host announces a route to another chain/domain.
7
+ abstract contract RouteEvent is EventEmitter {
8
+ string private constant ABI = "event Route(uint indexed host, uint chain, uint context)";
9
+
10
+ /// @param host Host node ID that owns the route.
11
+ /// @param chain Destination chain/domain node ID.
12
+ /// @param context Route context identifier.
13
+ event Route(uint indexed host, uint chain, uint context);
14
+
15
+ constructor() {
16
+ emit EventAbi(ABI);
17
+ }
18
+ }
package/guards/Revoke.sol CHANGED
@@ -18,7 +18,7 @@ abstract contract Revoke is GuardBase {
18
18
  }
19
19
 
20
20
  function revoke(bytes calldata request) external onlyGuardian {
21
- (Cur memory input, , ) = Cursors.init(request, 0, 1);
21
+ (Cur memory input, , ) = Cursors.init(request, 1);
22
22
 
23
23
  while (input.i < input.len) {
24
24
  uint node = input.unpackNode();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootzero/contracts",
3
- "version": "1.2.0",
3
+ "version": "1.4.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",
@@ -7,10 +7,14 @@ import { Cursors, Cur, Schemas } from "../Cursors.sol";
7
7
 
8
8
  using Cursors for Cur;
9
9
 
10
+ interface IPeerAllowAssets {
11
+ function peerAllowAssets(bytes calldata request) external returns (bytes memory);
12
+ }
13
+
10
14
  /// @title PeerAllowAssets
11
15
  /// @notice Peer that permits a list of (asset, meta) pairs on behalf of a peer host.
12
16
  /// Each ASSET block in the request calls `allowAsset`. Restricted to trusted peers.
13
- abstract contract PeerAllowAssets is PeerBase, AllowAssetsHook {
17
+ abstract contract PeerAllowAssets is PeerBase, AllowAssetsHook, IPeerAllowAssets {
14
18
  uint internal immutable peerAllowAssetsId = peerId(this.peerAllowAssets.selector);
15
19
 
16
20
  constructor() {
@@ -22,7 +26,7 @@ abstract contract PeerAllowAssets is PeerBase, AllowAssetsHook {
22
26
  /// @param request ASSET block stream supplied by the trusted peer.
23
27
  /// @return Empty response bytes.
24
28
  function peerAllowAssets(bytes calldata request) external onlyPeer returns (bytes memory) {
25
- (Cur memory assets, , ) = Cursors.init(request, 0, 1);
29
+ (Cur memory assets, , ) = Cursors.init(request, 1);
26
30
 
27
31
  while (assets.i < assets.len) {
28
32
  (bytes32 asset, bytes32 meta) = assets.unpackAsset();
@@ -7,11 +7,15 @@ import {Cursors, Cur, Schemas} from "../Cursors.sol";
7
7
 
8
8
  using Cursors for Cur;
9
9
 
10
+ interface IPeerAllowance {
11
+ function peerAllowance(bytes calldata request) external returns (bytes memory);
12
+ }
13
+
10
14
  /// @title PeerAllowance
11
15
  /// @notice Peer that lets a trusted peer host request or refresh its own allowance.
12
16
  /// Each AMOUNT block in the request is scoped to the peer host and passed to the
13
17
  /// shared allowance hook as a host-scoped allowance. Restricted to trusted peers.
14
- abstract contract PeerAllowance is PeerBase, AllowanceHook {
18
+ abstract contract PeerAllowance is PeerBase, AllowanceHook, IPeerAllowance {
15
19
  uint internal immutable peerAllowanceId = peerId(this.peerAllowance.selector);
16
20
 
17
21
  constructor() {
@@ -23,7 +27,7 @@ abstract contract PeerAllowance is PeerBase, AllowanceHook {
23
27
  /// @param request AMOUNT block stream requested by the trusted peer.
24
28
  /// @return Empty response bytes.
25
29
  function peerAllowance(bytes calldata request) external onlyPeer returns (bytes memory) {
26
- (Cur memory amounts, , ) = Cursors.init(request, 0, 1);
30
+ (Cur memory amounts, , ) = Cursors.init(request, 1);
27
31
  uint peer = caller();
28
32
 
29
33
  while (amounts.i < amounts.len) {
@@ -6,6 +6,10 @@ import {Cursors, Cur, Schemas} from "../Cursors.sol";
6
6
 
7
7
  using Cursors for Cur;
8
8
 
9
+ interface IPeerBalancePull {
10
+ function peerBalancePull(bytes calldata request) external returns (bytes memory);
11
+ }
12
+
9
13
  abstract contract BalancePullHook {
10
14
  /// @notice Override to process one incoming balance-based pull request from a peer host.
11
15
  /// @param peer Peer host node ID for this request.
@@ -19,7 +23,7 @@ abstract contract BalancePullHook {
19
23
  /// @notice Peer that pulls requested balances from a peer host into this one.
20
24
  /// Each BALANCE block in the request calls `balancePull(peer, asset, meta, amount)`.
21
25
  /// Restricted to trusted peers.
22
- abstract contract PeerBalancePull is PeerBase, BalancePullHook {
26
+ abstract contract PeerBalancePull is PeerBase, BalancePullHook, IPeerBalancePull {
23
27
  uint internal immutable peerBalancePullId = peerId(this.peerBalancePull.selector);
24
28
 
25
29
  constructor() {
@@ -31,7 +35,7 @@ abstract contract PeerBalancePull is PeerBase, BalancePullHook {
31
35
  /// @param request BALANCE block stream requested by the trusted peer.
32
36
  /// @return Empty response bytes.
33
37
  function peerBalancePull(bytes calldata request) external onlyPeer returns (bytes memory) {
34
- (Cur memory input, , ) = Cursors.init(request, 0, 1);
38
+ (Cur memory input, , ) = Cursors.init(request, 1);
35
39
  uint peer = caller();
36
40
 
37
41
  while (input.i < input.len) {