@rootzero/contracts 1.20.0 → 1.22.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 (59) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/Codec.sol +1 -1
  3. package/Commands.sol +1 -0
  4. package/Endpoints.sol +1 -0
  5. package/Events.sol +2 -2
  6. package/README.md +25 -15
  7. package/annotations/Schema.sol +35 -2
  8. package/codec/Blocks.sol +64 -2
  9. package/codec/Decoders.sol +71 -9
  10. package/codec/Descriptors.sol +28 -28
  11. package/codec/Readers.sol +39 -0
  12. package/codec/Schema.sol +45 -36
  13. package/codec/Specs.sol +9 -27
  14. package/codec/Writers.sol +8 -0
  15. package/commands/Allocate.sol +1 -1
  16. package/commands/Base.sol +3 -8
  17. package/commands/Burn.sol +1 -1
  18. package/commands/Credit.sol +1 -1
  19. package/commands/Debit.sol +1 -1
  20. package/commands/Deposit.sol +3 -10
  21. package/commands/Payout.sol +1 -1
  22. package/commands/Provision.sol +3 -3
  23. package/commands/Recover.sol +3 -3
  24. package/commands/Relay.sol +5 -4
  25. package/commands/Repay.sol +3 -3
  26. package/commands/Settle.sol +3 -3
  27. package/commands/Withdraw.sol +1 -1
  28. package/commands/admin/AllowAssets.sol +2 -2
  29. package/commands/admin/Allowance.sol +2 -2
  30. package/commands/admin/Annotate.sol +2 -2
  31. package/commands/admin/Appoint.sol +2 -2
  32. package/commands/admin/Authorize.sol +2 -2
  33. package/commands/admin/Base.sol +1 -1
  34. package/commands/admin/DenyAssets.sol +2 -8
  35. package/commands/admin/Dismiss.sol +2 -2
  36. package/commands/admin/Execute.sol +2 -2
  37. package/commands/admin/Unauthorize.sol +2 -2
  38. package/core/Host.sol +7 -10
  39. package/core/Portal.sol +11 -8
  40. package/events/Dispatch.sol +1 -1
  41. package/events/Relay.sol +1 -1
  42. package/events/Resolved.sol +17 -0
  43. package/events/Route.sol +1 -1
  44. package/events/Unresolved.sol +18 -0
  45. package/execution/Execution.sol +92 -5
  46. package/package.json +2 -3
  47. package/ports/AllowAssets.sol +1 -1
  48. package/ports/Allowance.sol +1 -1
  49. package/ports/Base.sol +3 -3
  50. package/ports/Credit.sol +1 -1
  51. package/ports/Debit.sol +1 -1
  52. package/ports/DenyAssets.sol +1 -1
  53. package/ports/Dispatch.sol +4 -2
  54. package/ports/Pipe.sol +2 -1
  55. package/ports/Post.sol +1 -1
  56. package/ports/Redeem.sol +1 -1
  57. package/docs/Schema.md +0 -403
  58. package/events/Recovered.sol +0 -17
  59. package/events/Undelivered.sol +0 -18
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import {CommandBase, Execution, Executions, Lanes, Specs} from "../Base.sol";
4
+ import {CommandBase, Execution, Executions, Flags, Lanes, Specs} from "../Base.sol";
5
5
  import {NodeAccess} from "../../core/Access.sol";
6
6
 
7
7
  /// @title AdminBase
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import { AdminBase, Execution, Executions, Lanes, Specs } from "./Base.sol";
4
+ import {AdminBase, Execution, Executions, Flags, Lanes, Specs} from "./Base.sol";
5
5
  using Executions for Execution;
6
6
 
7
7
  /// @notice Hook implemented by hosts that deny assets.
@@ -19,7 +19,7 @@ abstract contract DenyAssets is AdminBase, DenyAssetsHook {
19
19
  uint private immutable descriptor;
20
20
 
21
21
  constructor() {
22
- (, descriptor) = command("denyAssets", Specs.Empty, Specs.Asset, Specs.Empty, 0, false, true);
22
+ (, descriptor) = command("denyAssets", Specs.Empty, Specs.Asset, Specs.Empty, 0, Flags.Admin);
23
23
  }
24
24
 
25
25
  /// @notice Deny each ASSET block in the admin input.
@@ -41,9 +41,3 @@ abstract contract DenyAssets is AdminBase, DenyAssetsHook {
41
41
  return close(exec, account);
42
42
  }
43
43
  }
44
-
45
-
46
-
47
-
48
-
49
-
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import { AdminBase, Execution, Executions, Lanes, Specs } from "./Base.sol";
4
+ import { AdminBase, Execution, Executions, Flags, Lanes, Specs } from "./Base.sol";
5
5
  import { GuardianAccess } from "../../core/Access.sol";
6
6
  using Executions for Execution;
7
7
 
@@ -13,7 +13,7 @@ abstract contract Dismiss is GuardianAccess, AdminBase {
13
13
  uint private immutable descriptor;
14
14
 
15
15
  constructor() {
16
- (, descriptor) = command("dismiss", Specs.Empty, Specs.Account, Specs.Empty, 0, false, true);
16
+ (, descriptor) = command("dismiss", Specs.Empty, Specs.Account, Specs.Empty, 0, Flags.Admin);
17
17
  }
18
18
 
19
19
  /// @notice Dismiss each user ACCOUNT block in the admin input from guardian status.
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import {AdminBase, Execution, Executions, Lanes, Specs} from "./Base.sol";
4
+ import {AdminBase, Execution, Executions, Flags, Lanes, Specs} from "./Base.sol";
5
5
  import {RawNodeCalls} from "../../core/Calls.sol";
6
6
 
7
7
  using Executions for Execution;
@@ -15,7 +15,7 @@ abstract contract ExecutePayable is RawNodeCalls, AdminBase {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
18
- (, descriptor) = command("executePayable", Specs.Empty, Specs.Call, Specs.Empty, 0, true, true);
18
+ (, descriptor) = command("executePayable", Specs.Empty, Specs.Call, Specs.Empty, 0, Flags.AdminFunded);
19
19
  }
20
20
 
21
21
  /// @notice Execute each CALL block in the admin input.
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import {AdminBase, Execution, Executions, Lanes, Specs} from "./Base.sol";
4
+ import {AdminBase, Execution, Executions, Flags, Lanes, Specs} from "./Base.sol";
5
5
  using Executions for Execution;
6
6
 
7
7
  /// @title Unauthorize
@@ -13,7 +13,7 @@ abstract contract Unauthorize is AdminBase {
13
13
  uint private immutable id;
14
14
 
15
15
  constructor() {
16
- (id, descriptor) = command("unauthorize", Specs.Empty, Specs.Node, Specs.Empty, 0, false, true);
16
+ (id, descriptor) = command("unauthorize", Specs.Empty, Specs.Node, Specs.Empty, 0, Flags.Admin);
17
17
  }
18
18
 
19
19
  /// @notice Return the registered UNAUTHORIZE command ID.
package/core/Host.sol CHANGED
@@ -61,16 +61,19 @@ abstract contract CommandHost is CommanderAccess, CallerAccess, HostIntroduction
61
61
  function enforceCaller(address caller) internal view virtual override returns (address) {
62
62
  return enforceCommander(caller);
63
63
  }
64
-
65
64
  }
66
65
 
67
66
  /// @title Admins
68
67
  /// @notice Optional bundle of the default host administration commands.
69
- abstract contract Admins is Annotate, ExecutePayable, Authorize, Unauthorize {}
68
+ abstract contract Admins is Annotate, ExecutePayable, Authorize, Unauthorize {
69
+
70
+ }
70
71
 
71
72
  /// @title Guardians
72
73
  /// @notice Optional bundle for guardian management and the default revoke guard.
73
- abstract contract Guardians is Appoint, Dismiss, Revoke {}
74
+ abstract contract Guardians is Appoint, Dismiss, Revoke {
75
+
76
+ }
74
77
 
75
78
  /// @title Host
76
79
  /// @notice Abstract base contract for rootzero host implementations.
@@ -78,13 +81,7 @@ abstract contract Guardians is Appoint, Dismiss, Revoke {}
78
81
  /// guardian management, the default guardian revoke action, and
79
82
  /// optionally introduces itself to a commander host at deployment.
80
83
  /// Accepts native ETH payments via the `receive` function.
81
- abstract contract Host is
82
- Admins,
83
- Guardians,
84
- HostIntroduction,
85
- IntroductionEvent,
86
- IHostIntroduction
87
- {
84
+ abstract contract Host is Admins, Guardians, HostIntroduction, IntroductionEvent, IHostIntroduction {
88
85
  /// @param cmdr Commander address; used by the composed access capabilities.
89
86
  /// If `cmdr` is a deployed contract, the host calls `introduce`
90
87
  /// on it during construction.
package/core/Portal.sol CHANGED
@@ -2,13 +2,16 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortCalls} from "./Calls.sol";
5
+ import {NodeAccess} from "./Access.sol";
6
+ import {ResolvedEvent} from "../events/Resolved.sol";
7
+ import {UnresolvedEvent} from "../events/Unresolved.sol";
5
8
 
6
9
  /// @title Portal
7
10
  /// @notice Base contract for hosts that route payloads through portal adapters.
8
- abstract contract Portal is PortCalls {
11
+ abstract contract Portal is PortCalls, NodeAccess, UnresolvedEvent, ResolvedEvent {
9
12
  error BadWitness();
10
13
 
11
- mapping(bytes32 key => bytes32 digest) internal undelivered;
14
+ mapping(bytes32 key => bytes32 digest) internal unresolved;
12
15
 
13
16
  /// @notice Try to forward `message` to `port`.
14
17
  /// @dev Records and returns `keccak256(message)` under `key` only when forwarding fails.
@@ -21,19 +24,19 @@ abstract contract Portal is PortCalls {
21
24
  if (tryCallPort(port, value, message)) return bytes32(0);
22
25
 
23
26
  miss = keccak256(message);
24
- undelivered[key] = miss;
27
+ unresolved[key] = miss;
25
28
  }
26
29
 
27
- /// @notice Retry a previously undelivered witness through `port`.
30
+ /// @notice Resolve a previously unresolved witness through `port`.
28
31
  /// @dev The witness must hash to the digest stored under `key`.
29
32
  /// @param port Port that should attempt recovery.
30
33
  /// @param key Recovery lookup key.
31
34
  /// @param witness Witness payload used to prove and replay recovery.
32
- /// @param value Native EVM value assigned to the recovery attempt.
33
- function retry(uint port, bytes32 key, bytes calldata witness, uint128 value) internal virtual {
34
- if (undelivered[key] != keccak256(witness)) revert BadWitness();
35
+ /// @param value Native EVM value assigned to the resolution attempt.
36
+ function resolve(uint port, bytes32 key, bytes calldata witness, uint128 value) internal virtual {
37
+ if (unresolved[key] != keccak256(witness)) revert BadWitness();
35
38
 
36
- delete undelivered[key];
39
+ delete unresolved[key];
37
40
  callPort(port, value, witness);
38
41
  }
39
42
  }
@@ -8,7 +8,7 @@ abstract contract DispatchEvent is EventEmitter {
8
8
  string private constant ABI = "event Dispatch(uint indexed host, uint portal, uint resources, bytes32 key, bytes32 digest)";
9
9
 
10
10
  /// @param host Host node ID that owns the dispatch.
11
- /// @param portal Destination portal identifier, often the destination host ID.
11
+ /// @param portal Destination portal implementation's host ID.
12
12
  /// @param resources Chain-specific resources assigned to the dispatch.
13
13
  /// @param key Dispatch correlation or recovery lookup key.
14
14
  /// @param digest Digest of the dispatched payload or canonical envelope.
package/events/Relay.sol CHANGED
@@ -8,7 +8,7 @@ abstract contract RelayEvent is EventEmitter {
8
8
  string private constant ABI = "event Relay(bytes32 indexed account, uint portal, uint resources, bytes32 key, bytes32 digest)";
9
9
 
10
10
  /// @param account Account that owns the relayed context.
11
- /// @param portal Destination portal identifier, often the destination host ID.
11
+ /// @param portal Destination portal implementation's host ID.
12
12
  /// @param resources Chain-specific resources assigned to the relay.
13
13
  /// @param key Relay correlation or recovery lookup key.
14
14
  /// @param digest Digest of the relayed payload or canonical envelope.
@@ -0,0 +1,17 @@
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 resolves a previously recorded key.
7
+ abstract contract ResolvedEvent is EventEmitter {
8
+ string private constant ABI = "event Resolved(uint indexed host, bytes32 key)";
9
+
10
+ /// @param host Host node ID that owns the resolved key.
11
+ /// @param key Resolution lookup key.
12
+ event Resolved(uint indexed host, bytes32 key);
13
+
14
+ constructor() {
15
+ emit EventAbi(ABI);
16
+ }
17
+ }
package/events/Route.sol CHANGED
@@ -8,7 +8,7 @@ abstract contract RouteEvent is EventEmitter {
8
8
  string private constant ABI = "event Route(uint indexed host, uint portal, uint status)";
9
9
 
10
10
  /// @param host Host node ID that owns the route.
11
- /// @param portal Destination portal identifier, often the destination host ID.
11
+ /// @param portal Destination portal implementation's host ID.
12
12
  /// @param status Route status. Zero means inactive; nonzero means active.
13
13
  event Route(uint indexed host, uint portal, uint status);
14
14
 
@@ -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 records a portal message awaiting resolution.
7
+ abstract contract UnresolvedEvent is EventEmitter {
8
+ string private constant ABI = "event Unresolved(uint indexed host, bytes32 key, bytes32 digest)";
9
+
10
+ /// @param host Host node ID that owns the unresolved message.
11
+ /// @param key Resolution lookup key.
12
+ /// @param digest Digest of the unresolved message.
13
+ event Unresolved(uint indexed host, bytes32 key, bytes32 digest);
14
+
15
+ constructor() {
16
+ emit EventAbi(ABI);
17
+ }
18
+ }
@@ -187,6 +187,25 @@ library Executions {
187
187
  return exec.decoders.any();
188
188
  }
189
189
 
190
+ /// @notice Return a decoder lane's current absolute calldata position.
191
+ /// @param exec Execution whose decoder is inspected.
192
+ /// @param lane Decoder lane to select.
193
+ /// @return Current absolute calldata position of the selected lane.
194
+ function absolute(Execution memory exec, uint8 lane) internal pure returns (uint) {
195
+ return exec.decoders.select(lane).absolute();
196
+ }
197
+
198
+ /// @notice Return whether the next block on `lane` has `key` and an empty payload.
199
+ /// @param exec Execution whose decoder is inspected without advancing.
200
+ /// @param lane Decoder lane to inspect.
201
+ /// @param key Expected block key.
202
+ /// @return Whether a complete matching empty block header occurs next.
203
+ function isEmpty(Execution memory exec, uint8 lane, bytes4 key) internal pure returns (bool) {
204
+ uint cur = exec.decoders.select(lane);
205
+ (uint i, uint offset, uint len) = cur.decode();
206
+ return Blocks.isEmpty(offset + i, offset + len, key);
207
+ }
208
+
190
209
  /// @notice Validate and consume the next block from an execution decoder lane.
191
210
  /// @param exec Execution whose selected decoder cursor is advanced over the complete block.
192
211
  /// @param lane Execution decoder lane to select.
@@ -199,6 +218,20 @@ library Executions {
199
218
  exec.decoders = cur.seekAbs(end);
200
219
  }
201
220
 
221
+ /// @notice Consume a matching empty block from an execution decoder lane when present.
222
+ /// @param exec Execution whose selected decoder advances only for a matching empty block.
223
+ /// @param lane Decoder lane to consume.
224
+ /// @param key Expected block key.
225
+ /// @return Whether an empty block was consumed.
226
+ function tryConsumeEmpty(Execution memory exec, uint8 lane, bytes4 key) internal pure returns (bool) {
227
+ uint cur = exec.decoders.select(lane);
228
+ (uint i, uint offset, uint size) = cur.decode();
229
+ (bytes4 current, uint len) = Blocks.peek(offset + i, offset + size);
230
+ if (current != key || len != 0) return false;
231
+ exec.decoders = cur.seek(i + Sizes.Header);
232
+ return true;
233
+ }
234
+
202
235
  /// @notice Validate and enter the payload of the next block in an execution decoder lane.
203
236
  /// @dev The selected lane remains in its existing frame so callers can decode
204
237
  /// child blocks in place. Callers should prove complete payload consumption
@@ -209,9 +242,48 @@ library Executions {
209
242
  /// @return abs Absolute position of the first payload byte.
210
243
  /// @return end Absolute position immediately after the payload.
211
244
  function enter(Execution memory exec, uint8 lane, uint spec) internal pure returns (uint abs, uint end) {
245
+ return enter(exec, lane, spec, 0);
246
+ }
247
+
248
+ /// @notice Validate a parent block and advance over a fixed payload prefix.
249
+ /// @dev `amount` is relative to the payload start and cannot exceed the
250
+ /// current parent payload. The returned `abs` remains the payload start.
251
+ /// @param exec Execution whose selected decoder advances over the header and fixed prefix.
252
+ /// @param lane Execution decoder lane to select.
253
+ /// @param spec Expected parent block specification.
254
+ /// @param amount Number of initial payload bytes to advance over.
255
+ /// @return abs Absolute position of the first payload byte.
256
+ /// @return end Absolute position immediately after the payload.
257
+ function enter(
258
+ Execution memory exec,
259
+ uint8 lane,
260
+ uint spec,
261
+ uint amount
262
+ ) internal pure returns (uint abs, uint end) {
212
263
  uint cur = exec.decoders.select(lane);
213
264
  (abs, end) = Blocks.expect(cur.absolute(), spec);
214
- exec.decoders = cur.seekAbs(abs);
265
+ if (amount > end - abs) revert Blocks.InvalidBlock();
266
+ exec.decoders = cur.seekAbs(abs + amount);
267
+ }
268
+
269
+ /// @notice Advance an execution decoder lane by a raw byte count.
270
+ /// @dev No block header or schema is validated.
271
+ /// @param exec Execution whose selected decoder cursor is advanced.
272
+ /// @param lane Decoder lane to select.
273
+ /// @param amount Number of bytes to advance.
274
+ function advance(Execution memory exec, uint8 lane, uint amount) internal pure {
275
+ uint cur = exec.decoders.select(lane);
276
+ exec.decoders = cur.advance(amount);
277
+ }
278
+
279
+ /// @notice Take a raw byte range from an execution decoder lane.
280
+ /// @dev No block header or schema is validated.
281
+ /// @param exec Execution whose selected decoder cursor is advanced.
282
+ /// @param lane Decoder lane to select.
283
+ /// @param amount Number of bytes to take.
284
+ /// @return abs Absolute position of the first taken byte.
285
+ function take(Execution memory exec, uint8 lane, uint amount) internal pure returns (uint abs) {
286
+ (exec.decoders, abs) = exec.decoders.consume(lane, amount);
215
287
  }
216
288
 
217
289
  /// @notice Require the active execution decoder to be at absolute position `abs`.
@@ -227,7 +299,16 @@ library Executions {
227
299
  /// @param lane Decoder lane containing the LIST block.
228
300
  /// @return items Cursor over the nested list items.
229
301
  function list(Execution memory exec, uint8 lane) internal pure returns (Cur memory items) {
230
- (uint abs, uint end) = consume(exec, lane, Specs.List);
302
+ return list(exec, Specs.List, lane);
303
+ }
304
+
305
+ /// @notice Consume a list block described by `spec` and return a cursor scoped to its payload.
306
+ /// @param exec Execution whose decoder is advanced.
307
+ /// @param spec Custom list block specification.
308
+ /// @param lane Decoder lane containing the list block.
309
+ /// @return items Cursor over the nested list items.
310
+ function list(Execution memory exec, uint spec, uint8 lane) internal pure returns (Cur memory items) {
311
+ (uint abs, uint end) = consume(exec, lane, spec);
231
312
  items.state = Cursors.create(abs, end - abs, 0, 0, 0);
232
313
  }
233
314
 
@@ -237,9 +318,7 @@ library Executions {
237
318
 
238
319
  /// @dev Return the next raw calldata word from `lane` and advance by `size` bytes.
239
320
  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);
321
+ value = Blocks.read32(take(exec, lane, size));
243
322
  }
244
323
 
245
324
  /// @notice Return the next raw byte from a decoder lane and advance it by one byte.
@@ -797,6 +876,14 @@ library Executions {
797
876
  return reserve(exec, size, size);
798
877
  }
799
878
 
879
+ /// @notice Append an empty block to execution output.
880
+ /// @param exec Execution receiving the block.
881
+ /// @param key Block key.
882
+ function outputEmpty(Execution memory exec, bytes4 key) internal pure {
883
+ uint i = reserve(exec, Sizes.Header);
884
+ Blocks.writeEmpty(exec.output, i, key);
885
+ }
886
+
800
887
  /// @notice Append an ACCOUNT block to execution output.
801
888
  /// @param exec Execution receiving the block.
802
889
  /// @param account Account identifier to encode.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootzero/contracts",
3
- "version": "1.20.0",
3
+ "version": "1.22.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",
@@ -9,8 +9,7 @@
9
9
  "**/*.sol",
10
10
  "README.md",
11
11
  "CHANGELOG.md",
12
- "LICENSE",
13
- "docs/Schema.md"
12
+ "LICENSE"
14
13
  ],
15
14
  "publishConfig": {
16
15
  "access": "public"
@@ -15,7 +15,7 @@ abstract contract AllowAssetsPort is PortBase, AllowAssetsHook {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
18
- (, descriptor) = port("portAllowAssets", Specs.Asset, Specs.Empty, false);
18
+ (, descriptor) = port("portAllowAssets", Specs.Asset, Specs.Empty, 0);
19
19
  }
20
20
 
21
21
  /// @notice Execute the allow-assets peer call.
@@ -16,7 +16,7 @@ abstract contract AllowancePort is PortBase, AllowanceHook {
16
16
  uint private immutable descriptor;
17
17
 
18
18
  constructor() {
19
- (, descriptor) = port("portAllowance", Specs.Amount, Specs.Empty, false);
19
+ (, descriptor) = port("portAllowance", Specs.Amount, Specs.Empty, 0);
20
20
  }
21
21
 
22
22
  /// @notice Execute the allowance port call.
package/ports/Base.sol CHANGED
@@ -32,16 +32,16 @@ abstract contract PortBase is NodeCalls, NodeAccess, InputEndpointBase {
32
32
  /// match the Solidity port function name used by the canonical ABI.
33
33
  /// @param input Input block specification.
34
34
  /// @param output Output block specification.
35
- /// @param funded Whether the port accepts nonzero native value.
35
+ /// @param flags Packed port behavior flags.
36
36
  /// @return id Port node ID.
37
37
  /// @return descriptor Packed endpoint lane metadata and flags.
38
38
  function port(
39
39
  string memory name,
40
40
  uint input,
41
41
  uint output,
42
- bool funded
42
+ uint8 flags
43
43
  ) internal returns (uint id, uint descriptor) {
44
- descriptor = Descriptors.create(Specs.Empty, input, output, 0, funded ? Descriptors.Funded : 0);
44
+ descriptor = Descriptors.create(Specs.Empty, input, output, 0, flags);
45
45
  return port(name, descriptor);
46
46
  }
47
47
 
package/ports/Credit.sol CHANGED
@@ -15,7 +15,7 @@ abstract contract CreditAccountPort is PortBase, CreditAccountHook {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
18
- (, descriptor) = port("portCreditAccount", Specs.AccountAmount, Specs.Empty, false);
18
+ (, descriptor) = port("portCreditAccount", Specs.AccountAmount, Specs.Empty, 0);
19
19
  }
20
20
 
21
21
  /// @notice Execute the port-credit call.
package/ports/Debit.sol CHANGED
@@ -15,7 +15,7 @@ abstract contract DebitAccountPort is PortBase, DebitAccountHook {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
18
- (, descriptor) = port("portDebitAccount", Specs.AccountAmount, Specs.Empty, false);
18
+ (, descriptor) = port("portDebitAccount", Specs.AccountAmount, Specs.Empty, 0);
19
19
  }
20
20
 
21
21
  /// @notice Execute the port-debit call.
@@ -15,7 +15,7 @@ abstract contract DenyAssetsPort is PortBase, DenyAssetsHook {
15
15
  uint private immutable descriptor;
16
16
 
17
17
  constructor() {
18
- (, descriptor) = port("portDenyAssets", Specs.Asset, Specs.Empty, false);
18
+ (, descriptor) = port("portDenyAssets", Specs.Asset, Specs.Empty, 0);
19
19
  }
20
20
 
21
21
  /// @notice Execute the deny-assets peer call.
@@ -2,6 +2,7 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
+ import {Flags} from "../codec/Descriptors.sol";
5
6
  import {Specs} from "../Codec.sol";
6
7
  import {Execution, Executions, Lanes} from "../execution/Execution.sol";
7
8
 
@@ -10,7 +11,8 @@ using Executions for Execution;
10
11
  /// @notice Hook implemented by hosts that forward funded dispatch payloads.
11
12
  abstract contract DispatchPayableHook {
12
13
  /// @notice Override to dispatch an encoded payload to `portal`.
13
- /// @param portal Destination portal identifier, often the destination host ID.
14
+ /// @param portal Destination portal implementation's host ID. Implementations
15
+ /// may validate or resolve it for their transport.
14
16
  /// @param resources Chain-specific destination resources. EVM adapters
15
17
  /// may interpret this as packed execution gas and destination value.
16
18
  /// @param payload Encoded payload ready for the transport layer.
@@ -25,7 +27,7 @@ abstract contract DispatchPayablePort is PortBase, DispatchPayableHook {
25
27
  uint private immutable descriptor;
26
28
 
27
29
  constructor() {
28
- (, descriptor) = port("portDispatchPayable", Specs.Dispatch, Specs.Empty, true);
30
+ (, descriptor) = port("portDispatchPayable", Specs.Dispatch, Specs.Empty, Flags.Funded);
29
31
  }
30
32
 
31
33
  /// @notice Forward peer-supplied dispatches to the host-defined dispatch hook.
package/ports/Pipe.sol CHANGED
@@ -2,6 +2,7 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
+ import {Flags} from "../codec/Descriptors.sol";
5
6
  import {Pipeline} from "../core/Pipeline.sol";
6
7
  import {Specs} from "../Codec.sol";
7
8
  import {Execution, Executions, Lanes} from "../execution/Execution.sol";
@@ -16,7 +17,7 @@ abstract contract PipePayablePort is PortBase, Pipeline {
16
17
  uint private immutable descriptor;
17
18
 
18
19
  constructor() {
19
- (, descriptor) = port("portPipePayable", Specs.Context, Specs.Empty, true);
20
+ (, descriptor) = port("portPipePayable", Specs.Context, Specs.Empty, Flags.Funded);
20
21
  }
21
22
 
22
23
  /// @notice Execute peer-supplied contexts through the shared payable pipe.
package/ports/Post.sol CHANGED
@@ -18,7 +18,7 @@ abstract contract PostPort is PortBase, PostHook, Action {
18
18
 
19
19
  constructor() {
20
20
  uint id;
21
- (id, descriptor) = port("portPost", Specs.Transaction, Specs.Empty, false);
21
+ (id, descriptor) = port("portPost", Specs.Transaction, Specs.Empty, 0);
22
22
  action(id, Actions.Post);
23
23
  }
24
24
 
package/ports/Redeem.sol CHANGED
@@ -24,7 +24,7 @@ abstract contract RedeemBalancePort is PortBase, RedeemBalanceHook {
24
24
  uint private immutable descriptor;
25
25
 
26
26
  constructor() {
27
- (, descriptor) = port("portRedeemBalance", Specs.Balance, Specs.Empty, false);
27
+ (, descriptor) = port("portRedeemBalance", Specs.Balance, Specs.Empty, 0);
28
28
  }
29
29
 
30
30
  /// @notice Execute the balance redemption port call.