@rootzero/contracts 1.19.0 → 1.21.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 (57) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/Codec.sol +1 -1
  3. package/Commands.sol +1 -0
  4. package/Endpoints.sol +5 -4
  5. package/Events.sol +3 -2
  6. package/README.md +18 -12
  7. package/Utils.sol +0 -1
  8. package/codec/Decoders.sol +9 -1
  9. package/codec/Descriptors.sol +28 -28
  10. package/codec/Schema.sol +5 -5
  11. package/codec/Specs.sol +9 -27
  12. package/commands/Allocate.sol +1 -1
  13. package/commands/Base.sol +4 -10
  14. package/commands/Burn.sol +1 -1
  15. package/commands/Credit.sol +3 -3
  16. package/commands/Debit.sol +3 -3
  17. package/commands/Deposit.sol +3 -10
  18. package/commands/Payout.sol +1 -1
  19. package/commands/Provision.sol +3 -3
  20. package/commands/Recover.sol +3 -3
  21. package/commands/Relay.sol +20 -15
  22. package/commands/Repay.sol +3 -3
  23. package/commands/Settle.sol +5 -5
  24. package/commands/Withdraw.sol +1 -1
  25. package/commands/admin/AllowAssets.sol +2 -2
  26. package/commands/admin/Allowance.sol +2 -2
  27. package/commands/admin/Annotate.sol +2 -2
  28. package/commands/admin/Appoint.sol +2 -2
  29. package/commands/admin/Authorize.sol +2 -2
  30. package/commands/admin/Base.sol +1 -1
  31. package/commands/admin/DenyAssets.sol +2 -8
  32. package/commands/admin/Dismiss.sol +2 -2
  33. package/commands/admin/Execute.sol +2 -2
  34. package/commands/admin/Unauthorize.sol +2 -2
  35. package/core/Portal.sol +11 -8
  36. package/docs/Schema.md +53 -29
  37. package/events/Relay.sol +20 -0
  38. package/events/Resolved.sol +17 -0
  39. package/events/Unresolved.sol +18 -0
  40. package/execution/Execution.sol +10 -1
  41. package/guards/Base.sol +1 -2
  42. package/package.json +1 -1
  43. package/ports/AllowAssets.sol +1 -1
  44. package/ports/Allowance.sol +1 -1
  45. package/ports/Base.sol +4 -5
  46. package/ports/Credit.sol +1 -1
  47. package/ports/Debit.sol +1 -1
  48. package/ports/DenyAssets.sol +1 -1
  49. package/ports/Dispatch.sol +19 -7
  50. package/ports/Pipe.sol +2 -1
  51. package/ports/Post.sol +1 -1
  52. package/ports/Redeem.sol +1 -1
  53. package/queries/Base.sol +1 -2
  54. package/utils/Nodes.sol +21 -16
  55. package/events/Recovered.sol +0 -17
  56. package/events/Undelivered.sol +0 -18
  57. package/utils/Selectors.sol +0 -49
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.19.0",
3
+ "version": "1.21.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",
@@ -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
@@ -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
@@ -33,16 +32,16 @@ abstract contract PortBase is NodeCalls, NodeAccess, InputEndpointBase {
33
32
  /// match the Solidity port function name used by the canonical ABI.
34
33
  /// @param input Input block specification.
35
34
  /// @param output Output block specification.
36
- /// @param funded Whether the port accepts nonzero native value.
35
+ /// @param flags Packed port behavior flags.
37
36
  /// @return id Port node ID.
38
37
  /// @return descriptor Packed endpoint lane metadata and flags.
39
38
  function port(
40
39
  string memory name,
41
40
  uint input,
42
41
  uint output,
43
- bool funded
42
+ uint8 flags
44
43
  ) internal returns (uint id, uint descriptor) {
45
- descriptor = Descriptors.create(Specs.Empty, input, output, 0, funded ? Descriptors.Funded : 0);
44
+ descriptor = Descriptors.create(Specs.Empty, input, output, 0, flags);
46
45
  return port(name, descriptor);
47
46
  }
48
47
 
@@ -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
@@ -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,23 +2,35 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
- import {RelayPayableHook} from "../commands/Relay.sol";
5
+ import {Flags} from "../codec/Descriptors.sol";
6
6
  import {Specs} from "../Codec.sol";
7
7
  import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
8
 
9
9
  using Executions for Execution;
10
10
 
11
+ /// @notice Hook implemented by hosts that forward funded dispatch payloads.
12
+ abstract contract DispatchPayableHook {
13
+ /// @notice Override to dispatch an encoded payload to `portal`.
14
+ /// @param portal Destination portal identifier, often the destination host ID.
15
+ /// @param resources Chain-specific destination resources. EVM adapters
16
+ /// may interpret this as packed execution gas and destination value.
17
+ /// @param payload Encoded payload ready for the transport layer.
18
+ /// @param funds Execution used for source value available for transport fees
19
+ /// and destination resource funding.
20
+ function dispatchTo(uint portal, uint resources, bytes memory payload, Execution memory funds) internal virtual;
21
+ }
22
+
11
23
  /// @title DispatchPayablePort
12
- /// @notice Port endpoint that forwards DISPATCH blocks to a host-defined relay hook.
13
- abstract contract DispatchPayablePort is PortBase, RelayPayableHook {
24
+ /// @notice Port endpoint that forwards DISPATCH blocks to a host-defined dispatch hook.
25
+ abstract contract DispatchPayablePort is PortBase, DispatchPayableHook {
14
26
  uint private immutable descriptor;
15
27
 
16
28
  constructor() {
17
- (, descriptor) = port("portDispatchPayable", Specs.Dispatch, Specs.Empty, true);
29
+ (, descriptor) = port("portDispatchPayable", Specs.Dispatch, Specs.Empty, Flags.Funded);
18
30
  }
19
31
 
20
- /// @notice Forward peer-supplied dispatches to the host-defined relay hook.
21
- /// @dev Relay hooks receive the shared top-level source value
32
+ /// @notice Forward peer-supplied dispatches to the host-defined dispatch hook.
33
+ /// @dev Dispatch hooks receive the shared top-level source value
22
34
  /// budget. Any `msg.value` not spent by the hook remains on this host.
23
35
  /// @param data DISPATCH block stream supplied by the trusted peer.
24
36
  /// @return Empty response bytes.
@@ -27,7 +39,7 @@ abstract contract DispatchPayablePort is PortBase, RelayPayableHook {
27
39
 
28
40
  while (exec.more()) {
29
41
  (uint portal, uint resources, bytes calldata payload) = exec.unpackDispatch(Lanes.Input);
30
- relayTo(portal, resources, payload, exec);
42
+ dispatchTo(portal, resources, payload, exec);
31
43
  }
32
44
 
33
45
  return "";
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.
package/queries/Base.sol CHANGED
@@ -5,7 +5,6 @@ import { InputEndpointBase } from "../core/Endpoint.sol";
5
5
  import { Descriptors } from "../codec/Descriptors.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 QueryBase
11
10
  /// @notice Abstract base for rootzero query contracts.
@@ -39,7 +38,7 @@ abstract contract QueryBase is InputEndpointBase {
39
38
  string memory name,
40
39
  uint descriptor
41
40
  ) internal returns (uint id, uint published) {
42
- id = Nodes.toQuery(Selectors.query(name), address(this));
41
+ id = Nodes.toQuery(name, address(this));
43
42
  published = endpoint(id, name, descriptor);
44
43
  }
45
44
  }
package/utils/Nodes.sol CHANGED
@@ -192,40 +192,45 @@ library Nodes {
192
192
  return toLocalBase(Host) | uint(uint160(target));
193
193
  }
194
194
 
195
- /// @notice Build a chain-local command ID for the given selector and contract.
196
- /// @param selector 4-byte ABI selector of the command entry point.
195
+ /// @notice Build a chain-local command ID for the given endpoint name and contract.
196
+ /// @param name Command function name.
197
197
  /// @param target Command contract address.
198
198
  /// @return node Command node ID embedding both the selector and address.
199
- function toCommand(bytes4 selector, address target) internal view returns (uint node) {
199
+ function toCommand(string memory name, address target) internal view returns (uint node) {
200
200
  node = toLocalBase(Command) | uint(uint160(target));
201
- node |= uint(uint32(selector)) << 160;
201
+ node |= uint(uint32(toSelector(name, "(bytes32,bytes,bytes)"))) << 160;
202
202
  }
203
203
 
204
- /// @notice Build a chain-local port ID for the given selector and contract.
205
- /// @param selector 4-byte ABI selector of the port entry point.
204
+ /// @notice Build a chain-local port ID for the given endpoint name and contract.
205
+ /// @param name Port function name.
206
206
  /// @param target Port contract address.
207
207
  /// @return node Port node ID embedding both the selector and address.
208
- function toPort(bytes4 selector, address target) internal view returns (uint node) {
208
+ function toPort(string memory name, address target) internal view returns (uint node) {
209
209
  node = toLocalBase(Port) | uint(uint160(target));
210
- node |= uint(uint32(selector)) << 160;
210
+ node |= uint(uint32(toSelector(name, "(bytes)"))) << 160;
211
211
  }
212
212
 
213
- /// @notice Build a chain-local query ID for the given selector and contract.
214
- /// @param selector 4-byte ABI selector of the query entry point.
213
+ /// @notice Build a chain-local query ID for the given endpoint name and contract.
214
+ /// @param name Query function name.
215
215
  /// @param target Query contract address.
216
216
  /// @return node Query node ID embedding both the selector and address.
217
- function toQuery(bytes4 selector, address target) internal view returns (uint node) {
217
+ function toQuery(string memory name, address target) internal view returns (uint node) {
218
218
  node = toLocalBase(Query) | uint(uint160(target));
219
- node |= uint(uint32(selector)) << 160;
219
+ node |= uint(uint32(toSelector(name, "(bytes)"))) << 160;
220
220
  }
221
221
 
222
- /// @notice Build a chain-local guard action ID for the given selector and contract.
223
- /// @param selector 4-byte ABI selector of the guard action entry point.
222
+ /// @notice Build a chain-local guard action ID for the given endpoint name and contract.
223
+ /// @param name Guard action function name.
224
224
  /// @param target Guard action contract address.
225
225
  /// @return node Guard action node ID embedding both the selector and address.
226
- function toGuard(bytes4 selector, address target) internal view returns (uint node) {
226
+ function toGuard(string memory name, address target) internal view returns (uint node) {
227
227
  node = toLocalBase(Guard) | uint(uint160(target));
228
- node |= uint(uint32(selector)) << 160;
228
+ node |= uint(uint32(toSelector(name, "(bytes)"))) << 160;
229
+ }
230
+
231
+ /// @dev Derive an ABI selector from an endpoint name and argument signature.
232
+ function toSelector(string memory name, string memory args) private pure returns (bytes4) {
233
+ return bytes4(keccak256(bytes(string.concat(name, args))));
229
234
  }
230
235
 
231
236
  /// @notice Derive an opaque node ID from a keccak preimage.
@@ -1,17 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import {EventEmitter} from "./Emitter.sol";
5
-
6
- /// @notice Emitted when a host recovers a previously recorded key.
7
- abstract contract RecoveredEvent is EventEmitter {
8
- string private constant ABI = "event Recovered(uint indexed host, bytes32 key)";
9
-
10
- /// @param host Host node ID that owns the recovered key.
11
- /// @param key Recovery lookup key.
12
- event Recovered(uint indexed host, bytes32 key);
13
-
14
- constructor() {
15
- emit EventAbi(ABI);
16
- }
17
- }
@@ -1,18 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import {EventEmitter} from "./Emitter.sol";
5
-
6
- /// @notice Emitted when a host records an undelivered portal message.
7
- abstract contract UndeliveredEvent is EventEmitter {
8
- string private constant ABI = "event Undelivered(uint indexed host, bytes32 key, bytes32 digest)";
9
-
10
- /// @param host Host node ID that owns the undelivered message.
11
- /// @param key Delivery lookup key.
12
- /// @param digest Digest of the undelivered message.
13
- event Undelivered(uint indexed host, bytes32 key, bytes32 digest);
14
-
15
- constructor() {
16
- emit EventAbi(ABI);
17
- }
18
- }
@@ -1,49 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- /// @title Selectors
5
- /// @notice Canonical ABI selector derivation for rootzero endpoint types.
6
- library Selectors {
7
- /// @notice Derive the ABI selector for a command entrypoint.
8
- /// @param name Command function name.
9
- /// @return Selector for `name(bytes32,bytes,bytes)`.
10
- function command(string memory name) internal pure returns (bytes4) {
11
- return derive(name, "(bytes32,bytes,bytes)");
12
- }
13
-
14
- /// @notice Derive the ABI selector for a port entrypoint.
15
- /// @param name Port function name.
16
- /// @return Selector for `name(bytes)`.
17
- function port(string memory name) internal pure returns (bytes4) {
18
- return direct(name);
19
- }
20
-
21
- /// @notice Derive the ABI selector for a query entrypoint.
22
- /// @param name Query function name.
23
- /// @return Selector for `name(bytes)`.
24
- function query(string memory name) internal pure returns (bytes4) {
25
- return direct(name);
26
- }
27
-
28
- /// @notice Derive the ABI selector for a guard action entrypoint.
29
- /// @param name Guard action function name.
30
- /// @return Selector for `name(bytes)`.
31
- function guard(string memory name) internal pure returns (bytes4) {
32
- return direct(name);
33
- }
34
-
35
- /// @dev Derive a direct endpoint selector with a single `bytes` argument.
36
- /// @param name Endpoint function name.
37
- /// @return Selector for `name(bytes)`.
38
- function direct(string memory name) private pure returns (bytes4) {
39
- return derive(name, "(bytes)");
40
- }
41
-
42
- /// @dev Derive an ABI selector from a function name and argument signature suffix.
43
- /// @param name Function name.
44
- /// @param args Parenthesized ABI argument signature.
45
- /// @return First four bytes of the function signature hash.
46
- function derive(string memory name, string memory args) private pure returns (bytes4) {
47
- return bytes4(keccak256(bytes(string.concat(name, args))));
48
- }
49
- }