@rootzero/contracts 1.18.0 → 1.20.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/codec/Writers.sol CHANGED
@@ -22,6 +22,7 @@ struct Writer {
22
22
  /// then lazily allocates and writes binary-encoded blocks sequentially.
23
23
  /// Physical allocation is rounded up to whole 32-byte words for scratch space,
24
24
  /// while the writer cursor length tracks logical capacity. Call `finish` to trim the buffer.
25
+ /// `append*` helpers consume memory inputs; `copy*` helpers consume calldata inputs.
25
26
  library Writers {
26
27
  // -------------------------------------------------------------------------
27
28
  // Initialization helpers
@@ -497,6 +498,107 @@ library Writers {
497
498
  Blocks.writeSchema(writer.dst, i, spec, body, name);
498
499
  }
499
500
 
501
+ // -------------------------------------------------------------------------
502
+ // Calldata copy helpers
503
+ // -------------------------------------------------------------------------
504
+
505
+ /// @notice Append arbitrary calldata bytes to the writer.
506
+ /// @param writer Destination writer; `i` is advanced by `data.length`.
507
+ /// @param data Calldata bytes to append.
508
+ function copy(Writer memory writer, bytes calldata data) internal pure {
509
+ uint i = reserve(writer, data.length, data.length);
510
+ Buffers.copy(writer.dst, i, data);
511
+ }
512
+
513
+ /// @notice Append a custom block by copying its payload from calldata.
514
+ function copyBlock(Writer memory writer, uint spec, bytes calldata data) internal pure {
515
+ Specs.validate(spec, data.length);
516
+ uint size = Sizes.Header + data.length;
517
+ uint i = reserve(writer, size);
518
+ Blocks.copy(writer.dst, i, Specs.key(spec), data);
519
+ }
520
+
521
+ /// @notice Append a LIST block by copying its payload from calldata.
522
+ function copyList(Writer memory writer, bytes calldata value) internal pure {
523
+ uint size = Sizes.Header + value.length;
524
+ uint i = reserve(writer, size);
525
+ Blocks.copyList(writer.dst, i, value);
526
+ }
527
+
528
+ /// @notice Append an EVM block by copying its payload from calldata.
529
+ function copyEvm(Writer memory writer, bytes calldata value) internal pure {
530
+ uint size = Sizes.Header + value.length;
531
+ uint i = reserve(writer, size);
532
+ Blocks.copyEvm(writer.dst, i, value);
533
+ }
534
+
535
+ /// @notice Append a BYTES block by copying its payload from calldata.
536
+ function copyBytes(Writer memory writer, bytes calldata value) internal pure {
537
+ uint size = Sizes.Header + value.length;
538
+ uint i = reserve(writer, size);
539
+ Blocks.copyBytes(writer.dst, i, value);
540
+ }
541
+
542
+ /// @notice Append a STRING block by copying its payload from calldata.
543
+ function copyString(Writer memory writer, string calldata value) internal pure {
544
+ uint size = Sizes.Header + bytes(value).length;
545
+ uint i = reserve(writer, size);
546
+ Blocks.copyString(writer.dst, i, value);
547
+ }
548
+
549
+ /// @notice Append a STEP block by copying its nested input from calldata.
550
+ function copyStep(Writer memory writer, uint cmd, uint resources, bytes calldata input) internal pure {
551
+ uint size = Sizes.B64 + Sizes.Header + input.length;
552
+ uint i = reserve(writer, size);
553
+ Blocks.copyStep(writer.dst, i, cmd, resources, input);
554
+ }
555
+
556
+ /// @notice Append a CALL block by copying its nested payload from calldata.
557
+ function copyCall(Writer memory writer, uint target, uint resources, bytes calldata payload) internal pure {
558
+ uint size = Sizes.B64 + Sizes.Header + payload.length;
559
+ uint i = reserve(writer, size);
560
+ Blocks.copyCall(writer.dst, i, target, resources, payload);
561
+ }
562
+
563
+ /// @notice Append a RELAY block by copying its nested input from calldata.
564
+ function copyRelay(Writer memory writer, uint portal, uint resources, bytes calldata input) internal pure {
565
+ uint size = Sizes.B64 + Sizes.Header + input.length;
566
+ uint i = reserve(writer, size);
567
+ Blocks.copyRelay(writer.dst, i, portal, resources, input);
568
+ }
569
+
570
+ /// @notice Append a DISPATCH block by copying its nested payload from calldata.
571
+ function copyDispatch(Writer memory writer, uint portal, uint resources, bytes calldata payload) internal pure {
572
+ uint size = Sizes.B64 + Sizes.Header + payload.length;
573
+ uint i = reserve(writer, size);
574
+ Blocks.copyDispatch(writer.dst, i, portal, resources, payload);
575
+ }
576
+
577
+ /// @notice Append a CONTEXT block by copying its nested streams from calldata.
578
+ function copyContext(
579
+ Writer memory writer,
580
+ bytes32 account,
581
+ bytes calldata state,
582
+ bytes calldata input
583
+ ) internal pure {
584
+ uint size = Sizes.B32 + 2 * Sizes.Header + state.length + input.length;
585
+ uint i = reserve(writer, size);
586
+ Blocks.copyContext(writer.dst, i, account, state, input);
587
+ }
588
+
589
+ /// @notice Append a RECOVER block by copying its nested witness from calldata.
590
+ function copyRecover(
591
+ Writer memory writer,
592
+ uint handler,
593
+ uint resources,
594
+ bytes32 recoverykey,
595
+ bytes calldata witness
596
+ ) internal pure {
597
+ uint size = Sizes.B96 + Sizes.Header + witness.length;
598
+ uint i = reserve(writer, size);
599
+ Blocks.copyRecover(writer.dst, i, handler, resources, recoverykey, witness);
600
+ }
601
+
500
602
  // -------------------------------------------------------------------------
501
603
  // Finalisation
502
604
  // -------------------------------------------------------------------------
package/commands/Base.sol CHANGED
@@ -11,7 +11,6 @@ import {ReceivedEvent} from "../events/Received.sol";
11
11
  import {Actions} from "../utils/Actions.sol";
12
12
  import {Descriptors} from "../codec/Descriptors.sol";
13
13
  import {Nodes} from "../utils/Nodes.sol";
14
- import {Selectors} from "../utils/Selectors.sol";
15
14
  import {Cursors} from "../utils/Cursors.sol";
16
15
 
17
16
  using Executions for Execution;
@@ -72,7 +71,7 @@ abstract contract CommandBase is CallerAccess, EndpointBase, ReceivedEvent {
72
71
  /// @return id Command node ID.
73
72
  /// @return published Published endpoint descriptor.
74
73
  function command(string memory name, uint descriptor) internal returns (uint id, uint published) {
75
- id = Nodes.toCommand(Selectors.command(name), address(this));
74
+ id = Nodes.toCommand(name, address(this));
76
75
  published = endpoint(id, name, descriptor);
77
76
  }
78
77
 
@@ -45,11 +45,11 @@ abstract contract CreditAccount is CommandBase, CreditAccountHook {
45
45
  }
46
46
  }
47
47
 
48
- /// @title InternalCreditAccount
48
+ /// @title CreditAccountInternal
49
49
  /// @notice Extends the advertised credit-account command with memory-state pipeline dispatch.
50
50
  /// @dev This adapter is not a separate command. It uses the command ID and account hook
51
51
  /// inherited from `CreditAccount` while accepting the state location used by `Pipeline`.
52
- abstract contract InternalCreditAccount is CreditAccount {
52
+ abstract contract CreditAccountInternal is CreditAccount {
53
53
  /// @notice Execute the inherited credit-account command from an internal pipeline.
54
54
  /// @param account Account credited by each balance.
55
55
  /// @param state BALANCE block stream held in pipeline memory.
@@ -49,11 +49,11 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
49
49
  }
50
50
  }
51
51
 
52
- /// @title InternalDebitAccount
52
+ /// @title DebitAccountInternal
53
53
  /// @notice Extends the advertised debit-account command with memory-state pipeline dispatch.
54
54
  /// @dev This adapter is not a separate command. It uses the command ID and account hook
55
55
  /// inherited from `DebitAccount` while accepting the state location used by `Pipeline`.
56
- abstract contract InternalDebitAccount is DebitAccount {
56
+ abstract contract DebitAccountInternal is DebitAccount {
57
57
  /// @notice Execute the inherited debit-account command from an internal pipeline.
58
58
  /// @param account Account whose funds are debited.
59
59
  /// @param state Empty pipeline state required by the command schema.
@@ -1,20 +1,29 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import {Blocks, Execution, Executions, CommandBase, Lanes, Specs} from "./Base.sol";
4
+ import {Execution, Executions, CommandBase, Lanes, Specs} from "./Base.sol";
5
5
 
6
6
  using Executions for Execution;
7
7
 
8
- /// @notice Hook implemented by hosts that forward funded relay payloads.
8
+ /// @notice Hook implemented by hosts that relay command contexts.
9
9
  abstract contract RelayPayableHook {
10
- /// @notice Override to relay an encoded payload to `portal`.
10
+ /// @notice Override to relay a command context to `portal`.
11
11
  /// @param portal Destination portal identifier, often the destination host ID.
12
12
  /// @param resources Chain-specific destination resources. EVM adapters
13
13
  /// may interpret this as packed execution gas and destination value.
14
- /// @param payload Encoded payload ready for the transport layer.
14
+ /// @param account Destination command account.
15
+ /// @param state State forwarded into the destination context.
16
+ /// @param input Input forwarded into the destination context.
15
17
  /// @param funds Execution used for source value available for transport fees
16
18
  /// and destination resource funding.
17
- function relayTo(uint portal, uint resources, bytes memory payload, Execution memory funds) internal virtual;
19
+ function relay(
20
+ uint portal,
21
+ uint resources,
22
+ bytes32 account,
23
+ bytes calldata state,
24
+ bytes calldata input,
25
+ Execution memory funds
26
+ ) internal virtual;
18
27
  }
19
28
 
20
29
  /// @title RelayPayable
@@ -33,10 +42,8 @@ abstract contract RelayPayable is CommandBase, RelayPayableHook {
33
42
  bytes calldata input
34
43
  ) external payable onlyCommand returns (bytes memory, bytes memory) {
35
44
  Execution memory exec = openCommand(state, input, descriptor, 1);
36
- (uint portal, uint resources, bytes calldata payload) = exec.unpackRelay(Lanes.Input);
37
- bytes memory context = Blocks.context(account, bytes(state), bytes(payload));
38
-
39
- relayTo(portal, resources, context, exec);
45
+ (uint portal, uint resources, bytes calldata relayInput) = exec.unpackRelay(Lanes.Input);
46
+ relay(portal, resources, account, state, relayInput, exec);
40
47
 
41
48
  return close(exec, account);
42
49
  }
@@ -65,10 +72,8 @@ abstract contract RelayBalancePayable is CommandBase, RelayPayableHook {
65
72
  bytes calldata input
66
73
  ) external payable onlyCommand returns (bytes memory, bytes memory) {
67
74
  Execution memory exec = openCommand(state, input, descriptor, 1);
68
- (uint portal, uint resources, bytes calldata payload) = exec.unpackRelay(Lanes.Input);
69
- bytes memory context = Blocks.context(account, bytes(state), bytes(payload));
70
-
71
- relayTo(portal, resources, context, exec);
75
+ (uint portal, uint resources, bytes calldata relayInput) = exec.unpackRelay(Lanes.Input);
76
+ relay(portal, resources, account, state, relayInput, exec);
72
77
 
73
78
  return close(exec, account);
74
79
  }
@@ -97,11 +97,11 @@ abstract contract SettlePayable is CommandBase, SettlePayableHook, Action {
97
97
  }
98
98
  }
99
99
 
100
- /// @title InternalSettle
100
+ /// @title SettleInternal
101
101
  /// @notice Extends the advertised settle command with memory-state pipeline dispatch.
102
102
  /// @dev This adapter is not a separate command. It uses the command ID and settlement hook
103
103
  /// inherited from `Settle` while accepting the state location used by `Pipeline`.
104
- abstract contract InternalSettle is Settle {
104
+ abstract contract SettleInternal is Settle {
105
105
  /// @notice Execute the inherited settle command from an internal pipeline.
106
106
  /// @param account Account for which each position is settled.
107
107
  /// @param state POSITION block stream held in pipeline memory.
@@ -69,7 +69,7 @@ abstract contract Settlement is PostHook, SettleHook, RepayHook, DebitAccountHoo
69
69
  bytes32 liability,
70
70
  uint debt
71
71
  ) internal virtual override {
72
+ repay(account, liability, debt);
72
73
  if (amount != 0) creditAccount(account, asset, amount);
73
- if (debt != 0) debitAccount(account, liability, debt);
74
74
  }
75
75
  }
package/docs/Schema.md CHANGED
@@ -301,6 +301,11 @@ bytes1 through bytes32
301
301
  `uint` means `uint256`; `int` means `int256`. Other integer widths, unsized
302
302
  `bytes`, `string`, and array syntax are not part of the core schema DSL.
303
303
 
304
+ Restricting fixed bytes to the power-of-two widths `bytes1`, `bytes2`,
305
+ `bytes4`, `bytes8`, `bytes16`, and `bytes32` is under consideration, but has
306
+ not been decided. Until that decision is made, the schema DSL continues to
307
+ allow every `bytesN` width from 1 through 32.
308
+
304
309
  Integers are encoded big-endian. Signed integers use two's-complement encoding
305
310
  for their declared width. `bool` is one byte: `0x00` for false and `0x01` for
306
311
  true. `bytesN` values are encoded as exactly `N` bytes with no padding.
@@ -0,0 +1,20 @@
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 an account records an outbound relay reference.
7
+ abstract contract RelayEvent is EventEmitter {
8
+ string private constant ABI = "event Relay(bytes32 indexed account, uint portal, uint resources, bytes32 key, bytes32 digest)";
9
+
10
+ /// @param account Account that owns the relayed context.
11
+ /// @param portal Destination portal identifier, often the destination host ID.
12
+ /// @param resources Chain-specific resources assigned to the relay.
13
+ /// @param key Relay correlation or recovery lookup key.
14
+ /// @param digest Digest of the relayed payload or canonical envelope.
15
+ event Relay(bytes32 indexed account, uint portal, uint resources, bytes32 key, bytes32 digest);
16
+
17
+ constructor() {
18
+ emit EventAbi(ABI);
19
+ }
20
+ }
@@ -24,6 +24,8 @@ struct Execution {
24
24
 
25
25
  /// @title Executions
26
26
  /// @notice Opening, decoding, output, transaction, and value helpers for executions.
27
+ /// @dev `output*` helpers consume memory inputs; `outputCopy*` helpers copy
28
+ /// calldata inputs directly to the output lane.
27
29
  library Executions {
28
30
  using Cursors for uint;
29
31
 
@@ -197,6 +199,21 @@ library Executions {
197
199
  exec.decoders = cur.seekAbs(end);
198
200
  }
199
201
 
202
+ /// @notice Validate and enter the payload of the next block in an execution decoder lane.
203
+ /// @dev The selected lane remains in its existing frame so callers can decode
204
+ /// child blocks in place. Callers should prove complete payload consumption
205
+ /// with `exec.expectAbs(end)` after decoding the children from the same lane.
206
+ /// @param exec Execution whose selected decoder cursor advances over the block header.
207
+ /// @param lane Execution decoder lane to select.
208
+ /// @param spec Expected parent block specification.
209
+ /// @return abs Absolute position of the first payload byte.
210
+ /// @return end Absolute position immediately after the payload.
211
+ function enter(Execution memory exec, uint8 lane, uint spec) internal pure returns (uint abs, uint end) {
212
+ uint cur = exec.decoders.select(lane);
213
+ (abs, end) = Blocks.expect(cur.absolute(), spec);
214
+ exec.decoders = cur.seekAbs(abs);
215
+ }
216
+
200
217
  /// @notice Require the active execution decoder to be at absolute position `abs`.
201
218
  /// @dev The most recent lane-aware decoder operation determines the active lane.
202
219
  /// @param exec Execution whose active decoder position is validated.
@@ -218,6 +235,46 @@ library Executions {
218
235
  // Fixed-width block decoding
219
236
  // -------------------------------------------------------------------------
220
237
 
238
+ /// @dev Return the next raw calldata word from `lane` and advance by `size` bytes.
239
+ function next(Execution memory exec, uint8 lane, uint size) private pure returns (bytes32 value) {
240
+ uint abs;
241
+ (exec.decoders, abs) = exec.decoders.consume(lane, size);
242
+ value = Blocks.read32(abs);
243
+ }
244
+
245
+ /// @notice Return the next raw byte from a decoder lane and advance it by one byte.
246
+ function next1(Execution memory exec, uint8 lane) internal pure returns (bytes1 value) {
247
+ value = bytes1(next(exec, lane, 1));
248
+ }
249
+
250
+ /// @notice Return the next two raw bytes from a decoder lane and advance it by two bytes.
251
+ function next2(Execution memory exec, uint8 lane) internal pure returns (bytes2 value) {
252
+ value = bytes2(next(exec, lane, 2));
253
+ }
254
+
255
+ /// @notice Return the next four raw bytes from a decoder lane and advance it by four bytes.
256
+ function next4(Execution memory exec, uint8 lane) internal pure returns (bytes4 value) {
257
+ value = bytes4(next(exec, lane, 4));
258
+ }
259
+
260
+ /// @notice Return the next eight raw bytes from a decoder lane and advance it by eight bytes.
261
+ function next8(Execution memory exec, uint8 lane) internal pure returns (bytes8 value) {
262
+ value = bytes8(next(exec, lane, 8));
263
+ }
264
+
265
+ /// @notice Return the next sixteen raw bytes from a decoder lane and advance it by sixteen bytes.
266
+ function next16(Execution memory exec, uint8 lane) internal pure returns (bytes16 value) {
267
+ value = bytes16(next(exec, lane, 16));
268
+ }
269
+
270
+ /// @notice Return the next raw calldata word from a decoder lane and advance it.
271
+ /// @param exec Execution whose selected decoder cursor advances by one word.
272
+ /// @param lane Execution decoder lane to select.
273
+ /// @return value Raw word at the selected lane's previous position.
274
+ function next32(Execution memory exec, uint8 lane) internal pure returns (bytes32 value) {
275
+ value = next(exec, lane, Sizes.Word);
276
+ }
277
+
221
278
  /// @notice Decode one fixed 32-byte payload from `lane`.
222
279
  /// @param exec Execution whose decoder is advanced.
223
280
  /// @param lane Decoder lane to consume.
@@ -1097,6 +1154,99 @@ library Executions {
1097
1154
  Blocks.writeSchema(exec.output, i, spec, body, name);
1098
1155
  }
1099
1156
 
1157
+ // -------------------------------------------------------------------------
1158
+ // Calldata output copy helpers
1159
+ // -------------------------------------------------------------------------
1160
+
1161
+ /// @notice Append a custom block to execution output by copying its payload from calldata.
1162
+ function outputCopyBlock(Execution memory exec, uint spec, bytes calldata data) internal pure {
1163
+ Specs.validate(spec, data.length);
1164
+ uint size = Sizes.Header + data.length;
1165
+ uint i = reserve(exec, size);
1166
+ Blocks.copy(exec.output, i, Specs.key(spec), data);
1167
+ }
1168
+
1169
+ /// @notice Append a LIST block to execution output by copying its payload from calldata.
1170
+ function outputCopyList(Execution memory exec, bytes calldata value) internal pure {
1171
+ uint size = Sizes.Header + value.length;
1172
+ uint i = reserve(exec, size);
1173
+ Blocks.copyList(exec.output, i, value);
1174
+ }
1175
+
1176
+ /// @notice Append an EVM block to execution output by copying its payload from calldata.
1177
+ function outputCopyEvm(Execution memory exec, bytes calldata value) internal pure {
1178
+ uint size = Sizes.Header + value.length;
1179
+ uint i = reserve(exec, size);
1180
+ Blocks.copyEvm(exec.output, i, value);
1181
+ }
1182
+
1183
+ /// @notice Append a BYTES block to execution output by copying its payload from calldata.
1184
+ function outputCopyBytes(Execution memory exec, bytes calldata value) internal pure {
1185
+ uint size = Sizes.Header + value.length;
1186
+ uint i = reserve(exec, size);
1187
+ Blocks.copyBytes(exec.output, i, value);
1188
+ }
1189
+
1190
+ /// @notice Append a STRING block to execution output by copying its payload from calldata.
1191
+ function outputCopyString(Execution memory exec, string calldata value) internal pure {
1192
+ uint size = Sizes.Header + bytes(value).length;
1193
+ uint i = reserve(exec, size);
1194
+ Blocks.copyString(exec.output, i, value);
1195
+ }
1196
+
1197
+ /// @notice Append a STEP block to execution output by copying its nested input from calldata.
1198
+ function outputCopyStep(Execution memory exec, uint cmd, uint resources, bytes calldata input) internal pure {
1199
+ uint size = Sizes.B64 + Sizes.Header + input.length;
1200
+ uint i = reserve(exec, size);
1201
+ Blocks.copyStep(exec.output, i, cmd, resources, input);
1202
+ }
1203
+
1204
+ /// @notice Append a CALL block to execution output by copying its nested payload from calldata.
1205
+ function outputCopyCall(Execution memory exec, uint target, uint resources, bytes calldata payload) internal pure {
1206
+ uint size = Sizes.B64 + Sizes.Header + payload.length;
1207
+ uint i = reserve(exec, size);
1208
+ Blocks.copyCall(exec.output, i, target, resources, payload);
1209
+ }
1210
+
1211
+ /// @notice Append a RELAY block to execution output by copying its nested input from calldata.
1212
+ function outputCopyRelay(Execution memory exec, uint portal, uint resources, bytes calldata input) internal pure {
1213
+ uint size = Sizes.B64 + Sizes.Header + input.length;
1214
+ uint i = reserve(exec, size);
1215
+ Blocks.copyRelay(exec.output, i, portal, resources, input);
1216
+ }
1217
+
1218
+ /// @notice Append a DISPATCH block to execution output by copying its nested payload from calldata.
1219
+ function outputCopyDispatch(Execution memory exec, uint portal, uint resources, bytes calldata payload) internal pure {
1220
+ uint size = Sizes.B64 + Sizes.Header + payload.length;
1221
+ uint i = reserve(exec, size);
1222
+ Blocks.copyDispatch(exec.output, i, portal, resources, payload);
1223
+ }
1224
+
1225
+ /// @notice Append a CONTEXT block to execution output by copying its nested streams from calldata.
1226
+ function outputCopyContext(
1227
+ Execution memory exec,
1228
+ bytes32 account,
1229
+ bytes calldata state,
1230
+ bytes calldata input
1231
+ ) internal pure {
1232
+ uint size = Sizes.B32 + 2 * Sizes.Header + state.length + input.length;
1233
+ uint i = reserve(exec, size);
1234
+ Blocks.copyContext(exec.output, i, account, state, input);
1235
+ }
1236
+
1237
+ /// @notice Append a RECOVER block to execution output by copying its nested witness from calldata.
1238
+ function outputCopyRecover(
1239
+ Execution memory exec,
1240
+ uint handler,
1241
+ uint resources,
1242
+ bytes32 recoverykey,
1243
+ bytes calldata witness
1244
+ ) internal pure {
1245
+ uint size = Sizes.B96 + Sizes.Header + witness.length;
1246
+ uint i = reserve(exec, size);
1247
+ Blocks.copyRecover(exec.output, i, handler, resources, recoverykey, witness);
1248
+ }
1249
+
1100
1250
  // -------------------------------------------------------------------------
1101
1251
  // Value and transaction writing
1102
1252
  // -------------------------------------------------------------------------
package/guards/Base.sol CHANGED
@@ -5,7 +5,6 @@ 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";
8
- import {Selectors} from "../utils/Selectors.sol";
9
8
 
10
9
  /// @title GuardBase
11
10
  /// @notice Abstract base for guardian-only direct host actions.
@@ -27,7 +26,7 @@ abstract contract GuardBase is GuardianAccess, InputEndpointBase {
27
26
  string memory name,
28
27
  uint input
29
28
  ) internal returns (uint id, uint descriptor) {
30
- id = Nodes.toGuard(Selectors.guard(name), address(this));
29
+ id = Nodes.toGuard(name, address(this));
31
30
  descriptor = endpoint(id, name, Specs.Empty, input, Specs.Empty, 0, 0);
32
31
  }
33
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootzero/contracts",
3
- "version": "1.18.0",
3
+ "version": "1.20.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",
@@ -8,10 +8,10 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
8
 
9
9
  using Executions for Execution;
10
10
 
11
- /// @title PortAllowAssets
11
+ /// @title AllowAssetsPort
12
12
  /// @notice Port that permits a list of assets on behalf of a peer host.
13
13
  /// Each ASSET block in the input calls `allowAsset`. Restricted to trusted peers.
14
- abstract contract PortAllowAssets is PortBase, AllowAssetsHook {
14
+ abstract contract AllowAssetsPort is PortBase, AllowAssetsHook {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
@@ -8,11 +8,11 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
8
 
9
9
  using Executions for Execution;
10
10
 
11
- /// @title PortAllowance
11
+ /// @title AllowancePort
12
12
  /// @notice Port that lets a trusted peer host input or refresh its own allowance.
13
13
  /// Each AMOUNT block in the input is scoped to the peer host and passed to the
14
14
  /// shared allowance hook as a host-scoped allowance. Restricted to trusted peers.
15
- abstract contract PortAllowance is PortBase, AllowanceHook {
15
+ abstract contract AllowancePort is PortBase, AllowanceHook {
16
16
  uint private immutable descriptor;
17
17
 
18
18
  constructor() {
package/ports/Base.sol CHANGED
@@ -6,7 +6,6 @@ import { NodeAccess } from "../core/Access.sol";
6
6
  import { Specs } from "../codec/Specs.sol";
7
7
  import { InputEndpointBase } from "../core/Endpoint.sol";
8
8
  import { Nodes } from "../utils/Nodes.sol";
9
- import { Selectors } from "../utils/Selectors.sol";
10
9
  import { Descriptors } from "../codec/Descriptors.sol";
11
10
 
12
11
  /// @title PortBase
@@ -56,7 +55,7 @@ abstract contract PortBase is NodeCalls, NodeAccess, InputEndpointBase {
56
55
  string memory name,
57
56
  uint descriptor
58
57
  ) internal returns (uint id, uint published) {
59
- id = Nodes.toPort(Selectors.port(name), address(this));
58
+ id = Nodes.toPort(name, address(this));
60
59
  published = endpoint(id, name, descriptor);
61
60
  }
62
61
  }
package/ports/Credit.sol CHANGED
@@ -8,10 +8,10 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
8
 
9
9
  using Executions for Execution;
10
10
 
11
- /// @title PortCreditAccount
11
+ /// @title CreditAccountPort
12
12
  /// @notice Port that lets a trusted peer credit supplied accounts directly.
13
13
  /// Each ACCOUNT_AMOUNT block calls `creditAccount` for its account.
14
- abstract contract PortCreditAccount is PortBase, CreditAccountHook {
14
+ abstract contract CreditAccountPort is PortBase, CreditAccountHook {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
package/ports/Debit.sol CHANGED
@@ -8,10 +8,10 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
8
 
9
9
  using Executions for Execution;
10
10
 
11
- /// @title PortDebitAccount
11
+ /// @title DebitAccountPort
12
12
  /// @notice Port that lets a trusted peer debit supplied accounts directly.
13
13
  /// Each ACCOUNT_AMOUNT block calls `debitAccount` for its account.
14
- abstract contract PortDebitAccount is PortBase, DebitAccountHook {
14
+ abstract contract DebitAccountPort is PortBase, DebitAccountHook {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
@@ -8,10 +8,10 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
8
 
9
9
  using Executions for Execution;
10
10
 
11
- /// @title PortDenyAssets
11
+ /// @title DenyAssetsPort
12
12
  /// @notice Port that blocks a list of assets on behalf of a peer host.
13
13
  /// Each ASSET block in the input calls `denyAsset`. Restricted to trusted peers.
14
- abstract contract PortDenyAssets is PortBase, DenyAssetsHook {
14
+ abstract contract DenyAssetsPort is PortBase, DenyAssetsHook {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
@@ -2,23 +2,34 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
- import {RelayPayableHook} from "../commands/Relay.sol";
6
5
  import {Specs} from "../Codec.sol";
7
6
  import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
7
 
9
8
  using Executions for Execution;
10
9
 
11
- /// @title PortDispatchPayable
12
- /// @notice Port endpoint that forwards DISPATCH blocks to a host-defined relay hook.
13
- abstract contract PortDispatchPayable is PortBase, RelayPayableHook {
10
+ /// @notice Hook implemented by hosts that forward funded dispatch payloads.
11
+ abstract contract DispatchPayableHook {
12
+ /// @notice Override to dispatch an encoded payload to `portal`.
13
+ /// @param portal Destination portal identifier, often the destination host ID.
14
+ /// @param resources Chain-specific destination resources. EVM adapters
15
+ /// may interpret this as packed execution gas and destination value.
16
+ /// @param payload Encoded payload ready for the transport layer.
17
+ /// @param funds Execution used for source value available for transport fees
18
+ /// and destination resource funding.
19
+ function dispatchTo(uint portal, uint resources, bytes memory payload, Execution memory funds) internal virtual;
20
+ }
21
+
22
+ /// @title DispatchPayablePort
23
+ /// @notice Port endpoint that forwards DISPATCH blocks to a host-defined dispatch hook.
24
+ abstract contract DispatchPayablePort is PortBase, DispatchPayableHook {
14
25
  uint private immutable descriptor;
15
26
 
16
27
  constructor() {
17
28
  (, descriptor) = port("portDispatchPayable", Specs.Dispatch, Specs.Empty, true);
18
29
  }
19
30
 
20
- /// @notice Forward peer-supplied dispatches to the host-defined relay hook.
21
- /// @dev Relay hooks receive the shared top-level source value
31
+ /// @notice Forward peer-supplied dispatches to the host-defined dispatch hook.
32
+ /// @dev Dispatch hooks receive the shared top-level source value
22
33
  /// budget. Any `msg.value` not spent by the hook remains on this host.
23
34
  /// @param data DISPATCH block stream supplied by the trusted peer.
24
35
  /// @return Empty response bytes.
@@ -27,7 +38,7 @@ abstract contract PortDispatchPayable is PortBase, RelayPayableHook {
27
38
 
28
39
  while (exec.more()) {
29
40
  (uint portal, uint resources, bytes calldata payload) = exec.unpackDispatch(Lanes.Input);
30
- relayTo(portal, resources, bytes(payload), exec);
41
+ dispatchTo(portal, resources, payload, exec);
31
42
  }
32
43
 
33
44
  return "";
package/ports/Pipe.sol CHANGED
@@ -9,10 +9,10 @@ import {Budget} from "../execution/Budget.sol";
9
9
 
10
10
  using Executions for Execution;
11
11
 
12
- /// @title PortPipePayable
12
+ /// @title PipePayablePort
13
13
  /// @notice Port that consumes CONTEXT blocks and executes each input as a step stream.
14
14
  /// Each context's input bytes are passed to the shared pipeline.
15
- abstract contract PortPipePayable is PortBase, Pipeline {
15
+ abstract contract PipePayablePort is PortBase, Pipeline {
16
16
  uint private immutable descriptor;
17
17
 
18
18
  constructor() {