@rootzero/contracts 1.7.0 → 1.9.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/CHANGELOG.md +40 -0
- package/Core.sol +2 -2
- package/Endpoints.sol +15 -14
- package/Events.sol +2 -1
- package/README.md +13 -12
- package/blocks/Cursors.sol +39 -39
- package/blocks/Keys.sol +4 -4
- package/blocks/Schema.sol +8 -7
- package/blocks/Writers.sol +2 -2
- package/commands/Recover.sol +14 -21
- package/commands/Relay.sol +5 -15
- package/commands/admin/Destroy.sol +1 -0
- package/commands/admin/Execute.sol +2 -4
- package/commands/admin/Init.sol +1 -0
- package/core/Access.sol +1 -0
- package/core/Calls.sol +85 -38
- package/core/Payable.sol +1 -1
- package/core/Portal.sol +68 -0
- package/docs/Schema.md +15 -11
- package/events/Dispatch.sol +5 -5
- package/events/Resolved.sol +17 -0
- package/events/Route.sol +5 -5
- package/events/Undelivered.sol +18 -0
- package/guards/Base.sol +0 -11
- package/package.json +1 -1
- package/ports/AllowAssets.sol +1 -5
- package/ports/Allowance.sol +1 -5
- package/ports/Base.sol +0 -11
- package/ports/Credit.sol +1 -5
- package/ports/Debit.sol +1 -5
- package/ports/DenyAssets.sol +1 -5
- package/ports/Dispatch.sol +7 -11
- package/ports/Pipe.sol +1 -5
- package/ports/Redeem.sol +1 -5
- package/ports/Settle.sol +1 -5
- package/queries/Base.sol +0 -11
- package/queries/Positions.sol +1 -0
- package/core/Commitments.sol +0 -19
- package/events/Commitment.sol +0 -19
package/core/Calls.sol
CHANGED
|
@@ -12,7 +12,7 @@ import {Nodes} from "../utils/Nodes.sol";
|
|
|
12
12
|
error FailedCall(address addr, bytes4 selector, bytes err);
|
|
13
13
|
|
|
14
14
|
/// @title NodeCalls
|
|
15
|
-
/// @notice Shared
|
|
15
|
+
/// @notice Shared low-level inter-node call helpers for contracts that can talk to other nodes.
|
|
16
16
|
abstract contract NodeCalls is AccessControl {
|
|
17
17
|
/// @notice Return the host node ID corresponding to the current caller.
|
|
18
18
|
/// @dev Encodes `msg.sender` as a host ID using the local-chain host layout.
|
|
@@ -21,64 +21,111 @@ abstract contract NodeCalls is AccessControl {
|
|
|
21
21
|
return Nodes.toHost(msg.sender);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/// @notice
|
|
25
|
-
///
|
|
26
|
-
/// Reverts with `FailedCall` if the call is unsuccessful.
|
|
27
|
-
/// @param addr Contract address to call.
|
|
24
|
+
/// @notice Try a raw low-level call to another node and return whether it succeeded.
|
|
25
|
+
/// @param node Node ID of the callee.
|
|
28
26
|
/// @param value Native value to forward in wei.
|
|
29
27
|
/// @param data Encoded calldata to send.
|
|
30
|
-
/// @return
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
(success,
|
|
34
|
-
if (!success) revert FailedCall(addr, bytes4(data), out);
|
|
28
|
+
/// @return success True if the low-level call succeeded.
|
|
29
|
+
function tryRawCall(uint node, uint128 value, bytes memory data) internal returns (bool success) {
|
|
30
|
+
address addr = Nodes.addr(node);
|
|
31
|
+
(success, ) = payable(addr).call{value: value}(data);
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
/// @notice
|
|
38
|
-
///
|
|
39
|
-
///
|
|
40
|
-
/// @param addr Contract address to query.
|
|
34
|
+
/// @notice Try a trusted low-level call to another node and return whether it succeeded.
|
|
35
|
+
/// @param node Node ID of the callee.
|
|
36
|
+
/// @param value Native value to forward in wei.
|
|
41
37
|
/// @param data Encoded calldata to send.
|
|
42
|
-
/// @return
|
|
43
|
-
function
|
|
38
|
+
/// @return success True if the low-level call succeeded.
|
|
39
|
+
function tryTrustedCall(uint node, uint128 value, bytes memory data) internal returns (bool success) {
|
|
40
|
+
return tryRawCall(ensureTrusted(node), value, data);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// @notice Make a raw low-level call to another node and revert when it fails.
|
|
44
|
+
/// @param node Node ID of the callee.
|
|
45
|
+
/// @param value Native value to forward in wei.
|
|
46
|
+
/// @param data Encoded calldata to send.
|
|
47
|
+
/// @return out Return data from the successful call.
|
|
48
|
+
function rawCall(uint node, uint128 value, bytes memory data) internal returns (bytes memory out) {
|
|
44
49
|
bool success;
|
|
45
|
-
|
|
50
|
+
address addr = Nodes.addr(node);
|
|
51
|
+
(success, out) = payable(addr).call{value: value}(data);
|
|
46
52
|
if (!success) revert FailedCall(addr, bytes4(data), out);
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
/// @notice Make a trusted call to another node
|
|
50
|
-
///
|
|
51
|
-
/// then issues a low-level call forwarding `value` ETH and `data`.
|
|
52
|
-
/// @param node Node ID of the callee (must be in the authorized set).
|
|
55
|
+
/// @notice Make a trusted low-level call to another node and revert when it fails.
|
|
56
|
+
/// @param node Node ID of the callee.
|
|
53
57
|
/// @param value Native value to forward in wei.
|
|
54
58
|
/// @param data Encoded calldata to send.
|
|
55
59
|
/// @return out Return data from the successful call.
|
|
56
|
-
function
|
|
57
|
-
ensureTrusted(node);
|
|
58
|
-
address addr = Nodes.addr(node);
|
|
59
|
-
return callAddr(addr, value, data);
|
|
60
|
+
function trustedCall(uint node, uint128 value, bytes memory data) internal returns (bytes memory out) {
|
|
61
|
+
return rawCall(ensureTrusted(node), value, data);
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
/// @notice Make a
|
|
63
|
-
///
|
|
64
|
-
/// then issues a low-level `staticcall` with `data`.
|
|
65
|
-
/// @param node Node ID of the callee (must be in the authorized set).
|
|
64
|
+
/// @notice Make a raw low-level read-only query to another node and revert when it fails.
|
|
65
|
+
/// @param node Node ID of the callee.
|
|
66
66
|
/// @param data Encoded calldata to send.
|
|
67
67
|
/// @return out Return data from the successful query.
|
|
68
|
-
function
|
|
69
|
-
|
|
68
|
+
function rawQuery(uint node, bytes memory data) internal view returns (bytes memory out) {
|
|
69
|
+
bool success;
|
|
70
70
|
address addr = Nodes.addr(node);
|
|
71
|
-
|
|
71
|
+
(success, out) = addr.staticcall(data);
|
|
72
|
+
if (!success) revert FailedCall(addr, bytes4(data), out);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// @notice Make a trusted low-level read-only query to another node and revert when it fails.
|
|
76
|
+
/// @param node Node ID of the callee.
|
|
77
|
+
/// @param data Encoded calldata to send.
|
|
78
|
+
/// @return out Return data from the successful query.
|
|
79
|
+
function trustedQuery(uint node, bytes memory data) internal view returns (bytes memory out) {
|
|
80
|
+
return rawQuery(ensureTrusted(node), data);
|
|
72
81
|
}
|
|
82
|
+
}
|
|
73
83
|
|
|
84
|
+
/// @title CommandCalls
|
|
85
|
+
/// @notice Trusted command-call helpers for contracts that route command nodes.
|
|
86
|
+
abstract contract CommandCalls is NodeCalls {
|
|
74
87
|
/// @notice Encode and call a trusted command node.
|
|
75
|
-
/// @param
|
|
88
|
+
/// @param command Command node ID embedding the target selector.
|
|
76
89
|
/// @param value Native value to forward in wei.
|
|
77
|
-
/// @param
|
|
90
|
+
/// @param account Command account identifier.
|
|
91
|
+
/// @param state Current command state block stream.
|
|
92
|
+
/// @param request Command input block stream.
|
|
78
93
|
/// @return Decoded command output block stream.
|
|
79
|
-
function callCommand(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
function callCommand(
|
|
95
|
+
uint command,
|
|
96
|
+
uint128 value,
|
|
97
|
+
bytes32 account,
|
|
98
|
+
bytes memory state,
|
|
99
|
+
bytes calldata request
|
|
100
|
+
) internal returns (bytes memory) {
|
|
101
|
+
bytes4 selector = Nodes.commandSelector(command);
|
|
102
|
+
bytes memory data = abi.encodeWithSelector(selector, CommandContext(account, state, request));
|
|
103
|
+
return abi.decode(trustedCall(command, value, data), (bytes));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// @title PortCalls
|
|
108
|
+
/// @notice Trusted port-call helpers for contracts that route port nodes.
|
|
109
|
+
abstract contract PortCalls is NodeCalls {
|
|
110
|
+
/// @notice Try to encode and call a trusted port node.
|
|
111
|
+
/// @param port Port node ID embedding the target selector.
|
|
112
|
+
/// @param value Native value to forward in wei.
|
|
113
|
+
/// @param input Port input block stream.
|
|
114
|
+
/// @return success True if the low-level port call succeeded.
|
|
115
|
+
function tryCallPort(uint port, uint128 value, bytes calldata input) internal returns (bool success) {
|
|
116
|
+
bytes4 selector = Nodes.portSelector(port);
|
|
117
|
+
bytes memory data = abi.encodeWithSelector(selector, input);
|
|
118
|
+
return tryTrustedCall(port, value, data);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// @notice Encode and call a trusted port node.
|
|
122
|
+
/// @param port Port node ID embedding the target selector.
|
|
123
|
+
/// @param value Native value to forward in wei.
|
|
124
|
+
/// @param input Port input block stream.
|
|
125
|
+
/// @return Decoded port output block stream.
|
|
126
|
+
function callPort(uint port, uint128 value, bytes calldata input) internal returns (bytes memory) {
|
|
127
|
+
bytes4 selector = Nodes.portSelector(port);
|
|
128
|
+
bytes memory data = abi.encodeWithSelector(selector, input);
|
|
129
|
+
return abi.decode(trustedCall(port, value, data), (bytes));
|
|
83
130
|
}
|
|
84
131
|
}
|
package/core/Payable.sol
CHANGED
|
@@ -19,7 +19,7 @@ abstract contract Payable {
|
|
|
19
19
|
/// @notice Deduct the EVM value lane from a packed resource word and return it.
|
|
20
20
|
/// @dev EVM resources use the low 128 bits as native value/endowment.
|
|
21
21
|
/// @param budget Mutable budget to deduct from.
|
|
22
|
-
/// @param resources Packed
|
|
22
|
+
/// @param resources Packed resources.
|
|
23
23
|
/// @return value Native value to forward in wei.
|
|
24
24
|
function useValue(Budget memory budget, uint resources) internal pure returns (uint128 value) {
|
|
25
25
|
value = uint128(resources);
|
package/core/Portal.sol
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {PortCalls} from "./Calls.sol";
|
|
5
|
+
import {ResolvedEvent} from "../events/Resolved.sol";
|
|
6
|
+
import {UndeliveredEvent} from "../events/Undelivered.sol";
|
|
7
|
+
import {Budget} from "../utils/Value.sol";
|
|
8
|
+
|
|
9
|
+
abstract contract RoutePayableHook {
|
|
10
|
+
/// @notice Override to route an encoded payload through `portal`.
|
|
11
|
+
/// @param portal Destination portal identifier, often the destination host ID.
|
|
12
|
+
/// @param resources Chain-specific destination resources. EVM adapters
|
|
13
|
+
/// may interpret this as packed execution gas and destination value.
|
|
14
|
+
/// @param payload Encoded payload ready for the transport layer.
|
|
15
|
+
/// @param budget Source native-value budget available for transport
|
|
16
|
+
/// fees and destination resource funding.
|
|
17
|
+
function route(uint portal, uint resources, bytes memory payload, Budget memory budget) internal virtual;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
abstract contract RecoverHook {
|
|
21
|
+
/// @notice Override to recover a previously undelivered witness through `handler`.
|
|
22
|
+
/// @param handler Port that should attempt recovery.
|
|
23
|
+
/// @param key Recovery lookup key.
|
|
24
|
+
/// @param witness Witness payload used to prove and replay recovery.
|
|
25
|
+
/// @param value Native EVM value assigned to the recovery attempt.
|
|
26
|
+
function recover(uint handler, bytes32 key, bytes calldata witness, uint128 value) internal virtual;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// @title Portal
|
|
30
|
+
/// @notice Base contract for hosts that route payloads through portal adapters.
|
|
31
|
+
abstract contract Portal is PortCalls, RecoverHook, ResolvedEvent, UndeliveredEvent {
|
|
32
|
+
error BadWitness();
|
|
33
|
+
|
|
34
|
+
/// @dev Remote port used to handle messages delivered through this portal.
|
|
35
|
+
uint private immutable port;
|
|
36
|
+
|
|
37
|
+
mapping(bytes32 key => bytes32 digest) internal undelivered;
|
|
38
|
+
|
|
39
|
+
/// @param handler Remote port used to handle messages delivered through this portal.
|
|
40
|
+
constructor(uint handler) {
|
|
41
|
+
port = handler;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// @notice Try to deliver `message` to this portal's handler port.
|
|
45
|
+
/// @dev Records `keccak256(message)` under `key` only when delivery fails.
|
|
46
|
+
/// @param key Delivery/recovery lookup key.
|
|
47
|
+
/// @param message Encoded port input to deliver.
|
|
48
|
+
/// @param value Native EVM value assigned to the delivery attempt.
|
|
49
|
+
function deliver(bytes32 key, bytes calldata message, uint128 value) internal {
|
|
50
|
+
if (tryCallPort(port, value, message)) return;
|
|
51
|
+
bytes32 digest = keccak256(message);
|
|
52
|
+
undelivered[key] = digest;
|
|
53
|
+
emit Undelivered(host, key, digest);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// @notice Recover a previously undelivered witness through `handler`.
|
|
57
|
+
/// @dev The witness must hash to the digest stored under `key`.
|
|
58
|
+
/// @param handler Port that should attempt recovery.
|
|
59
|
+
/// @param key Recovery lookup key.
|
|
60
|
+
/// @param witness Witness payload used to prove and replay recovery.
|
|
61
|
+
/// @param value Native EVM value assigned to the recovery attempt.
|
|
62
|
+
function recover(uint handler, bytes32 key, bytes calldata witness, uint128 value) internal virtual override {
|
|
63
|
+
if (keccak256(witness) != undelivered[key]) revert BadWitness();
|
|
64
|
+
delete undelivered[key];
|
|
65
|
+
callPort(handler, value, witness);
|
|
66
|
+
emit Resolved(host, key);
|
|
67
|
+
}
|
|
68
|
+
}
|
package/docs/Schema.md
CHANGED
|
@@ -120,7 +120,7 @@ Aliases may be used on any block item, including child blocks and prime items.
|
|
|
120
120
|
A child block without an inline body may also be used as a schema reference:
|
|
121
121
|
|
|
122
122
|
```txt
|
|
123
|
-
#
|
|
123
|
+
#recover { uint handler, uint resources, bytes32 key, #bytes as witness }
|
|
124
124
|
```
|
|
125
125
|
|
|
126
126
|
Alias resolution is context-dependent. A consumer may resolve `#context` from the
|
|
@@ -136,13 +136,13 @@ path does not change the block key, payload bytes, payload length, cursor
|
|
|
136
136
|
behavior, or any onchain validation. It is metadata only.
|
|
137
137
|
|
|
138
138
|
```txt
|
|
139
|
-
#dispatch { uint dst.
|
|
139
|
+
#dispatch { uint dst.portal, uint dst.resources, #bytes as dst.payload }
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
This has the same runtime layout as:
|
|
143
143
|
|
|
144
144
|
```txt
|
|
145
|
-
#dispatch { uint
|
|
145
|
+
#dispatch { uint portal, uint resources, #bytes as payload }
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
Offchain tooling may decode the dotted form into a nested object:
|
|
@@ -150,7 +150,7 @@ Offchain tooling may decode the dotted form into a nested object:
|
|
|
150
150
|
```ts
|
|
151
151
|
{
|
|
152
152
|
dst: {
|
|
153
|
-
|
|
153
|
+
portal,
|
|
154
154
|
resources,
|
|
155
155
|
payload
|
|
156
156
|
}
|
|
@@ -165,8 +165,8 @@ object.
|
|
|
165
165
|
Tooling should reject duplicate full paths and prefix/value collisions:
|
|
166
166
|
|
|
167
167
|
```txt
|
|
168
|
-
uint dst.
|
|
169
|
-
uint dst, uint dst.
|
|
168
|
+
uint dst.portal, uint dst.portal // duplicate path
|
|
169
|
+
uint dst, uint dst.portal // prefix/value collision
|
|
170
170
|
```
|
|
171
171
|
|
|
172
172
|
The same rule applies to block aliases:
|
|
@@ -196,10 +196,14 @@ true. `bytesN` values are encoded as exactly `N` bytes with no padding.
|
|
|
196
196
|
|
|
197
197
|
## Chain Resources
|
|
198
198
|
|
|
199
|
-
Fields named `
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
Fields named `portal` are routing identifiers; they are often the destination
|
|
200
|
+
host ID, but a transport adapter may define a different stable handle.
|
|
201
|
+
|
|
202
|
+
Fields named `resources` are chain-specific resource words. A portal adapter
|
|
203
|
+
interprets them for the destination runtime. Different runtimes may pack these
|
|
204
|
+
words differently, but a given runtime must use one stable format everywhere.
|
|
205
|
+
For EVM chains, the low 128 bits are native value / endowment in wei; higher
|
|
206
|
+
bits are reserved for execution resources such as gas.
|
|
203
207
|
|
|
204
208
|
## Protocol IDs
|
|
205
209
|
|
|
@@ -282,7 +286,7 @@ Common protocol schemas live in `contracts/blocks/Schema.sol`:
|
|
|
282
286
|
#call { uint target, uint resources, #bytes as payload }
|
|
283
287
|
#step { uint target, uint resources, #bytes as request }
|
|
284
288
|
#context { bytes32 account, #bytes as state, #bytes as request }
|
|
285
|
-
#
|
|
289
|
+
#recover { uint handler, uint resources, bytes32 key, #bytes as witness }
|
|
286
290
|
#auth { uint cid, uint deadline, #bytes as proof }
|
|
287
291
|
```
|
|
288
292
|
|
package/events/Dispatch.sol
CHANGED
|
@@ -5,14 +5,14 @@ import {EventEmitter} from "./Emitter.sol";
|
|
|
5
5
|
|
|
6
6
|
/// @notice Emitted when a host records an outbound dispatch reference.
|
|
7
7
|
abstract contract DispatchEvent is EventEmitter {
|
|
8
|
-
string private constant ABI = "event Dispatch(uint indexed host, uint
|
|
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
|
|
12
|
-
/// @param resources Chain-
|
|
11
|
+
/// @param portal Destination portal identifier, often the destination host ID.
|
|
12
|
+
/// @param resources Chain-specific resources assigned to the dispatch.
|
|
13
|
+
/// @param key Dispatch correlation or recovery lookup key.
|
|
13
14
|
/// @param digest Digest of the dispatched payload or canonical envelope.
|
|
14
|
-
|
|
15
|
-
event Dispatch(uint indexed host, uint chain, uint resources, bytes32 digest, bytes32 ref);
|
|
15
|
+
event Dispatch(uint indexed host, uint portal, uint resources, bytes32 key, bytes32 digest);
|
|
16
16
|
|
|
17
17
|
constructor() {
|
|
18
18
|
emit EventAbi(ABI);
|
|
@@ -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
|
@@ -3,14 +3,14 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {EventEmitter} from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
/// @notice Emitted when a host
|
|
6
|
+
/// @notice Emitted when a host updates a portal route.
|
|
7
7
|
abstract contract RouteEvent is EventEmitter {
|
|
8
|
-
string private constant ABI = "event Route(uint indexed host, uint
|
|
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
|
|
12
|
-
/// @param
|
|
13
|
-
event Route(uint indexed host, uint
|
|
11
|
+
/// @param portal Destination portal identifier, often the destination host ID.
|
|
12
|
+
/// @param status Route status. Zero means inactive; nonzero means active.
|
|
13
|
+
event Route(uint indexed host, uint portal, uint status);
|
|
14
14
|
|
|
15
15
|
constructor() {
|
|
16
16
|
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 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
|
+
}
|
package/guards/Base.sol
CHANGED
|
@@ -6,17 +6,6 @@ import {GuardEvent} from "../events/Guard.sol";
|
|
|
6
6
|
import {LabeledEvent} from "../events/Labeled.sol";
|
|
7
7
|
import {Nodes} from "../utils/Nodes.sol";
|
|
8
8
|
|
|
9
|
-
/// @notice ABI-encode a guard action call from a target guard ID and request block stream.
|
|
10
|
-
/// @dev Derives the function selector from `target` via `Nodes.guardSelector(target)`.
|
|
11
|
-
/// Reverts if `target` is not a valid guard ID.
|
|
12
|
-
/// @param target Destination guard action node ID embedding the target selector.
|
|
13
|
-
/// @param request Input block stream for the guard invocation.
|
|
14
|
-
/// @return ABI-encoded calldata for the guard action entry point.
|
|
15
|
-
function encodeGuardCall(uint target, bytes calldata request) pure returns (bytes memory) {
|
|
16
|
-
bytes4 selector = Nodes.guardSelector(target);
|
|
17
|
-
return abi.encodeWithSelector(selector, request);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
9
|
/// @title GuardBase
|
|
21
10
|
/// @notice Abstract base for guardian-only direct host actions.
|
|
22
11
|
/// Guard actions are non-payable direct calls with no command context, state, or response.
|
package/package.json
CHANGED
package/ports/AllowAssets.sol
CHANGED
|
@@ -7,14 +7,10 @@ import { Cursors, Cur, Schemas } from "../Cursors.sol";
|
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
10
|
-
interface IPortAllowAssets {
|
|
11
|
-
function portAllowAssets(bytes calldata data) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
10
|
/// @title PortAllowAssets
|
|
15
11
|
/// @notice Port that permits a list of assets on behalf of a peer host.
|
|
16
12
|
/// Each ASSET block in the request calls `allowAsset`. Restricted to trusted peers.
|
|
17
|
-
abstract contract PortAllowAssets is PortBase, AllowAssetsHook
|
|
13
|
+
abstract contract PortAllowAssets is PortBase, AllowAssetsHook {
|
|
18
14
|
uint internal immutable portAllowAssetsId = portId(this.portAllowAssets.selector);
|
|
19
15
|
|
|
20
16
|
constructor() {
|
package/ports/Allowance.sol
CHANGED
|
@@ -7,15 +7,11 @@ import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
10
|
-
interface IPortAllowance {
|
|
11
|
-
function portAllowance(bytes calldata data) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
10
|
/// @title PortAllowance
|
|
15
11
|
/// @notice Port that lets a trusted peer host request or refresh its own allowance.
|
|
16
12
|
/// Each AMOUNT block in the request is scoped to the peer host and passed to the
|
|
17
13
|
/// shared allowance hook as a host-scoped allowance. Restricted to trusted peers.
|
|
18
|
-
abstract contract PortAllowance is PortBase, AllowanceHook
|
|
14
|
+
abstract contract PortAllowance is PortBase, AllowanceHook {
|
|
19
15
|
uint internal immutable portAllowanceId = portId(this.portAllowance.selector);
|
|
20
16
|
|
|
21
17
|
constructor() {
|
package/ports/Base.sol
CHANGED
|
@@ -6,17 +6,6 @@ import { PortEvent } from "../events/Port.sol";
|
|
|
6
6
|
import { LabeledEvent } from "../events/Labeled.sol";
|
|
7
7
|
import { Nodes } from "../utils/Nodes.sol";
|
|
8
8
|
|
|
9
|
-
/// @notice ABI-encode a port call from a target port ID and data block stream.
|
|
10
|
-
/// @dev Derives the function selector from `target` via `Nodes.portSelector(target)`.
|
|
11
|
-
/// Reverts if `target` is not a valid port ID.
|
|
12
|
-
/// @param target Destination port node ID embedding the target selector.
|
|
13
|
-
/// @param data Input block stream for the port invocation.
|
|
14
|
-
/// @return ABI-encoded calldata for the port entry point.
|
|
15
|
-
function encodePortCall(uint target, bytes calldata data) pure returns (bytes memory) {
|
|
16
|
-
bytes4 selector = Nodes.portSelector(target);
|
|
17
|
-
return abi.encodeWithSelector(selector, data);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
9
|
/// @title PortBase
|
|
21
10
|
/// @notice Abstract base for peer-facing rootzero ports.
|
|
22
11
|
/// Ports handle inter-host operations between cooperating hosts.
|
package/ports/Credit.sol
CHANGED
|
@@ -7,14 +7,10 @@ import { Cursors, Cur, Forms } from "../Cursors.sol";
|
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
10
|
-
interface IPortCreditAccount {
|
|
11
|
-
function portCreditAccount(bytes calldata data) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
10
|
/// @title PortCreditAccount
|
|
15
11
|
/// @notice Port that lets a trusted peer credit supplied accounts directly.
|
|
16
12
|
/// Each ACCOUNT_AMOUNT block calls `creditAccount` for its account.
|
|
17
|
-
abstract contract PortCreditAccount is PortBase, CreditAccountHook
|
|
13
|
+
abstract contract PortCreditAccount is PortBase, CreditAccountHook {
|
|
18
14
|
uint internal immutable portCreditAccountId = portId(this.portCreditAccount.selector);
|
|
19
15
|
|
|
20
16
|
constructor() {
|
package/ports/Debit.sol
CHANGED
|
@@ -7,14 +7,10 @@ import { Cursors, Cur, Forms } from "../Cursors.sol";
|
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
10
|
-
interface IPortDebitAccount {
|
|
11
|
-
function portDebitAccount(bytes calldata data) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
10
|
/// @title PortDebitAccount
|
|
15
11
|
/// @notice Port that lets a trusted peer debit supplied accounts directly.
|
|
16
12
|
/// Each ACCOUNT_AMOUNT block calls `debitAccount` for its account.
|
|
17
|
-
abstract contract PortDebitAccount is PortBase, DebitAccountHook
|
|
13
|
+
abstract contract PortDebitAccount is PortBase, DebitAccountHook {
|
|
18
14
|
uint internal immutable portDebitAccountId = portId(this.portDebitAccount.selector);
|
|
19
15
|
|
|
20
16
|
constructor() {
|
package/ports/DenyAssets.sol
CHANGED
|
@@ -7,14 +7,10 @@ import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
10
|
-
interface IPortDenyAssets {
|
|
11
|
-
function portDenyAssets(bytes calldata data) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
10
|
/// @title PortDenyAssets
|
|
15
11
|
/// @notice Port that blocks a list of assets on behalf of a peer host.
|
|
16
12
|
/// Each ASSET block in the request calls `denyAsset`. Restricted to trusted peers.
|
|
17
|
-
abstract contract PortDenyAssets is PortBase, DenyAssetsHook
|
|
13
|
+
abstract contract PortDenyAssets is PortBase, DenyAssetsHook {
|
|
18
14
|
uint internal immutable portDenyAssetsId = portId(this.portDenyAssets.selector);
|
|
19
15
|
|
|
20
16
|
constructor() {
|
package/ports/Dispatch.sol
CHANGED
|
@@ -3,19 +3,15 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { PortBase } from "./Base.sol";
|
|
5
5
|
import { Payable } from "../core/Payable.sol";
|
|
6
|
+
import { RoutePayableHook } from "../core/Portal.sol";
|
|
6
7
|
import { Cursors, Cur, Schemas } from "../Cursors.sol";
|
|
7
|
-
import { DispatchPayableHook } from "../commands/Relay.sol";
|
|
8
8
|
import { Budget } from "../utils/Value.sol";
|
|
9
9
|
|
|
10
10
|
using Cursors for Cur;
|
|
11
11
|
|
|
12
|
-
interface IPortDispatchPayable {
|
|
13
|
-
function portDispatchPayable(bytes calldata data) external payable returns (bytes memory);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
12
|
/// @title PortDispatchPayable
|
|
17
|
-
/// @notice Port endpoint that forwards DISPATCH blocks to a host-defined
|
|
18
|
-
abstract contract PortDispatchPayable is PortBase, Payable,
|
|
13
|
+
/// @notice Port endpoint that forwards DISPATCH blocks to a host-defined route hook.
|
|
14
|
+
abstract contract PortDispatchPayable is PortBase, Payable, RoutePayableHook {
|
|
19
15
|
uint internal immutable portDispatchPayableId = portId(this.portDispatchPayable.selector);
|
|
20
16
|
|
|
21
17
|
constructor() {
|
|
@@ -23,8 +19,8 @@ abstract contract PortDispatchPayable is PortBase, Payable, DispatchPayableHook,
|
|
|
23
19
|
emit Labeled(portDispatchPayableId, bytes32(0), "portDispatchPayable");
|
|
24
20
|
}
|
|
25
21
|
|
|
26
|
-
/// @notice Forward peer-supplied dispatches to the host-defined
|
|
27
|
-
/// @dev
|
|
22
|
+
/// @notice Forward peer-supplied dispatches to the host-defined route hook.
|
|
23
|
+
/// @dev Route hooks receive the shared top-level source value
|
|
28
24
|
/// budget. Any `msg.value` not spent by the hook remains on this host.
|
|
29
25
|
/// @param data DISPATCH block stream supplied by the trusted peer.
|
|
30
26
|
/// @return output Empty response bytes.
|
|
@@ -33,8 +29,8 @@ abstract contract PortDispatchPayable is PortBase, Payable, DispatchPayableHook,
|
|
|
33
29
|
Budget memory budget = openValue();
|
|
34
30
|
|
|
35
31
|
while (input.i < input.len) {
|
|
36
|
-
(uint
|
|
37
|
-
|
|
32
|
+
(uint portal, uint resources, bytes calldata payload) = input.unpackDispatch();
|
|
33
|
+
route(portal, resources, bytes(payload), budget);
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
input.complete();
|
package/ports/Pipe.sol
CHANGED
|
@@ -8,14 +8,10 @@ import {Budget} from "../utils/Value.sol";
|
|
|
8
8
|
|
|
9
9
|
using Cursors for Cur;
|
|
10
10
|
|
|
11
|
-
interface IPortPipePayable {
|
|
12
|
-
function portPipePayable(bytes calldata data) external payable returns (bytes memory);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
11
|
/// @title PortPipePayable
|
|
16
12
|
/// @notice Port that consumes CONTEXT blocks and executes each request as a step stream.
|
|
17
13
|
/// Each context's request bytes are passed to the shared pipeline.
|
|
18
|
-
abstract contract PortPipePayable is PortBase, Pipeline
|
|
14
|
+
abstract contract PortPipePayable is PortBase, Pipeline {
|
|
19
15
|
uint internal immutable portPipePayableId = portId(this.portPipePayable.selector);
|
|
20
16
|
|
|
21
17
|
constructor() {
|
package/ports/Redeem.sol
CHANGED
|
@@ -6,10 +6,6 @@ import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
|
6
6
|
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
9
|
-
interface IPortRedeemBalance {
|
|
10
|
-
function portRedeemBalance(bytes calldata data) external returns (bytes memory);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
9
|
abstract contract RedeemBalanceHook {
|
|
14
10
|
/// @notice Override to redeem one balance claim from a peer host into local assets.
|
|
15
11
|
/// @param peer Peer host node ID for this request.
|
|
@@ -22,7 +18,7 @@ abstract contract RedeemBalanceHook {
|
|
|
22
18
|
/// @notice Port that redeems balance state from a peer host into local assets.
|
|
23
19
|
/// Each BALANCE block in the request calls `redeemBalance(peer, asset, amount)`.
|
|
24
20
|
/// Restricted to trusted peers.
|
|
25
|
-
abstract contract PortRedeemBalance is PortBase, RedeemBalanceHook
|
|
21
|
+
abstract contract PortRedeemBalance is PortBase, RedeemBalanceHook {
|
|
26
22
|
uint internal immutable portRedeemBalanceId = portId(this.portRedeemBalance.selector);
|
|
27
23
|
|
|
28
24
|
constructor() {
|
package/ports/Settle.sol
CHANGED
|
@@ -8,14 +8,10 @@ import { Cursors, Cur, Schemas } from "../Cursors.sol";
|
|
|
8
8
|
|
|
9
9
|
using Cursors for Cur;
|
|
10
10
|
|
|
11
|
-
interface IPortSettle {
|
|
12
|
-
function portSettle(bytes calldata data) external returns (bytes memory);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
11
|
/// @title PortSettle
|
|
16
12
|
/// @notice Port that consumes peer-supplied TRANSACTION blocks through debit and credit hooks.
|
|
17
13
|
/// Each TRANSACTION block calls `debitAccount` for `from` and `creditAccount` for `to`.
|
|
18
|
-
abstract contract PortSettle is PortBase, DebitAccountHook, CreditAccountHook
|
|
14
|
+
abstract contract PortSettle is PortBase, DebitAccountHook, CreditAccountHook {
|
|
19
15
|
uint internal immutable portSettleId = portId(this.portSettle.selector);
|
|
20
16
|
|
|
21
17
|
constructor() {
|
package/queries/Base.sol
CHANGED
|
@@ -6,17 +6,6 @@ import { LabeledEvent } from "../events/Labeled.sol";
|
|
|
6
6
|
import { QueryEvent } from "../events/Query.sol";
|
|
7
7
|
import { Nodes } from "../utils/Nodes.sol";
|
|
8
8
|
|
|
9
|
-
/// @notice ABI-encode a query call from a target query ID and request block stream.
|
|
10
|
-
/// @dev Derives the function selector from `target` via `Nodes.querySelector(target)`.
|
|
11
|
-
/// Reverts if `target` is not a valid query ID.
|
|
12
|
-
/// @param target Destination query node ID embedding the target selector.
|
|
13
|
-
/// @param request Input block stream for the query invocation.
|
|
14
|
-
/// @return ABI-encoded calldata for the query entry point.
|
|
15
|
-
function encodeQueryCall(uint target, bytes calldata request) pure returns (bytes memory) {
|
|
16
|
-
bytes4 selector = Nodes.querySelector(target);
|
|
17
|
-
return abi.encodeWithSelector(selector, request);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
9
|
/// @title QueryBase
|
|
21
10
|
/// @notice Abstract base for rootzero query contracts.
|
|
22
11
|
/// Queries are view-only entry points that consume a block-stream request and
|