@rootzero/contracts 1.21.0 → 1.23.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 +125 -0
- package/Endpoints.sol +2 -3
- package/Events.sol +1 -1
- package/README.md +25 -19
- package/annotations/Action.sol +1 -1
- package/annotations/Label.sol +1 -1
- package/annotations/Schema.sol +36 -3
- package/codec/Blocks.sol +100 -29
- package/codec/Decoders.sol +62 -8
- package/codec/Readers.sol +39 -0
- package/codec/Schema.sol +44 -35
- package/codec/Writers.sol +8 -0
- package/commands/Allocate.sol +5 -8
- package/commands/Base.sol +29 -13
- package/commands/Burn.sol +5 -7
- package/commands/Credit.sol +5 -7
- package/commands/Debit.sol +5 -7
- package/commands/Deposit.sol +10 -14
- package/commands/Payout.sol +5 -8
- package/commands/Provision.sol +10 -14
- package/commands/Recover.sol +4 -6
- package/commands/Relay.sol +16 -22
- package/commands/Repay.sol +10 -14
- package/commands/Settle.sol +10 -14
- package/commands/Withdraw.sol +5 -7
- package/commands/admin/AllowAssets.sol +5 -7
- package/commands/admin/Allowance.sol +5 -7
- package/commands/admin/Annotate.sol +5 -7
- package/commands/admin/Appoint.sol +5 -7
- package/commands/admin/Authorize.sol +5 -7
- package/commands/admin/Base.sol +12 -3
- package/commands/admin/DenyAssets.sol +5 -7
- package/commands/admin/Dismiss.sol +5 -7
- package/commands/admin/Execute.sol +5 -7
- package/commands/admin/Unauthorize.sol +5 -7
- package/core/Calls.sol +72 -3
- package/core/Host.sol +7 -10
- package/core/Portal.sol +2 -2
- package/events/Dispatch.sol +1 -1
- package/events/Positioned.sol +22 -0
- package/events/Relay.sol +1 -1
- package/events/Route.sol +1 -1
- package/execution/Execution.sol +124 -4
- package/package.json +2 -3
- package/ports/Allowance.sol +22 -12
- package/ports/Assets.sol +99 -0
- package/ports/Dispatch.sol +2 -1
- package/utils/Cursors.sol +3 -3
- package/utils/Nodes.sol +1 -1
- package/utils/Utils.sol +31 -31
- package/docs/Schema.md +0 -427
- package/events/Commander.sol +0 -19
- package/ports/AllowAssets.sol +0 -34
- package/ports/DenyAssets.sol +0 -34
|
@@ -16,21 +16,19 @@ abstract contract Annotate is AdminBase {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/// @notice Publish each ANNOTATION block in the admin input.
|
|
19
|
-
/// @param
|
|
19
|
+
/// @param context Admin command context carrying the ANNOTATION input stream.
|
|
20
20
|
/// @return Empty output state.
|
|
21
21
|
/// @return Empty transaction stream.
|
|
22
22
|
function annotate(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
27
|
-
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
23
|
+
bytes calldata context
|
|
24
|
+
) external returns (bytes memory, bytes memory) {
|
|
25
|
+
Execution memory exec = openAdminCommand(context, descriptor, 0);
|
|
28
26
|
|
|
29
27
|
while (exec.more()) {
|
|
30
28
|
(uint entity, bytes calldata data) = exec.unpackAnnotation(Lanes.Input);
|
|
31
29
|
emit Annotation(entity, data);
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
return
|
|
32
|
+
return closeCommand(exec);
|
|
35
33
|
}
|
|
36
34
|
}
|
|
@@ -17,21 +17,19 @@ abstract contract Appoint is GuardianAccess, AdminBase {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/// @notice Appoint each user ACCOUNT block in the admin input as a guardian.
|
|
20
|
-
/// @param
|
|
20
|
+
/// @param context Admin command context carrying the ACCOUNT input stream.
|
|
21
21
|
/// @return Empty output state.
|
|
22
22
|
/// @return Empty transaction stream.
|
|
23
23
|
function appoint(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
28
|
-
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
24
|
+
bytes calldata context
|
|
25
|
+
) external returns (bytes memory, bytes memory) {
|
|
26
|
+
Execution memory exec = openAdminCommand(context, descriptor, 0);
|
|
29
27
|
|
|
30
28
|
while (exec.more()) {
|
|
31
29
|
bytes32 guardian = exec.unpackAccount(Lanes.Input);
|
|
32
30
|
setGuardian(guardian, true);
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
return
|
|
33
|
+
return closeCommand(exec);
|
|
36
34
|
}
|
|
37
35
|
}
|
|
@@ -22,21 +22,19 @@ abstract contract Authorize is AdminBase {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/// @notice Authorize each NODE block in the admin input.
|
|
25
|
-
/// @param
|
|
25
|
+
/// @param context Admin command context carrying the NODE input stream.
|
|
26
26
|
/// @return Empty output state.
|
|
27
27
|
/// @return Empty transaction stream.
|
|
28
28
|
function authorize(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
33
|
-
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
29
|
+
bytes calldata context
|
|
30
|
+
) external returns (bytes memory, bytes memory) {
|
|
31
|
+
Execution memory exec = openAdminCommand(context, descriptor, 0);
|
|
34
32
|
|
|
35
33
|
while (exec.more()) {
|
|
36
34
|
uint node = exec.unpackNode(Lanes.Input);
|
|
37
35
|
setNode(node, true);
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
return
|
|
38
|
+
return closeCommand(exec);
|
|
41
39
|
}
|
|
42
40
|
}
|
package/commands/admin/Base.sol
CHANGED
|
@@ -7,9 +7,18 @@ import {NodeAccess} from "../../core/Access.sol";
|
|
|
7
7
|
/// @title AdminBase
|
|
8
8
|
/// @notice Shared base for admin commands.
|
|
9
9
|
abstract contract AdminBase is NodeAccess, CommandBase {
|
|
10
|
-
/// @
|
|
11
|
-
|
|
10
|
+
/// @notice Decode, authorize, and open one admin command context.
|
|
11
|
+
function openAdminCommand(
|
|
12
|
+
bytes calldata context,
|
|
13
|
+
uint descriptor,
|
|
14
|
+
uint batches
|
|
15
|
+
) internal view returns (Execution memory exec) {
|
|
16
|
+
bytes32 account;
|
|
17
|
+
bytes calldata state;
|
|
18
|
+
bytes calldata input;
|
|
19
|
+
(account, state, input) = unpackCommandContext(context);
|
|
12
20
|
enforceAdmin(account, msg.sender);
|
|
13
|
-
|
|
21
|
+
exec = Executions.open(state, input, descriptor, batches);
|
|
22
|
+
exec.account = account;
|
|
14
23
|
}
|
|
15
24
|
}
|
|
@@ -23,21 +23,19 @@ abstract contract DenyAssets is AdminBase, DenyAssetsHook {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/// @notice Deny each ASSET block in the admin input.
|
|
26
|
-
/// @param
|
|
26
|
+
/// @param context Admin command context carrying the ASSET input stream.
|
|
27
27
|
/// @return Empty output state.
|
|
28
28
|
/// @return Empty transaction stream.
|
|
29
29
|
function denyAssets(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
34
|
-
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
30
|
+
bytes calldata context
|
|
31
|
+
) external returns (bytes memory, bytes memory) {
|
|
32
|
+
Execution memory exec = openAdminCommand(context, descriptor, 0);
|
|
35
33
|
|
|
36
34
|
while (exec.more()) {
|
|
37
35
|
bytes32 asset = exec.unpackAsset(Lanes.Input);
|
|
38
36
|
denyAsset(asset);
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
return
|
|
39
|
+
return closeCommand(exec);
|
|
42
40
|
}
|
|
43
41
|
}
|
|
@@ -17,21 +17,19 @@ abstract contract Dismiss is GuardianAccess, AdminBase {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/// @notice Dismiss each user ACCOUNT block in the admin input from guardian status.
|
|
20
|
-
/// @param
|
|
20
|
+
/// @param context Admin command context carrying the ACCOUNT input stream.
|
|
21
21
|
/// @return Empty output state.
|
|
22
22
|
/// @return Empty transaction stream.
|
|
23
23
|
function dismiss(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
28
|
-
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
24
|
+
bytes calldata context
|
|
25
|
+
) external returns (bytes memory, bytes memory) {
|
|
26
|
+
Execution memory exec = openAdminCommand(context, descriptor, 0);
|
|
29
27
|
|
|
30
28
|
while (exec.more()) {
|
|
31
29
|
bytes32 guardian = exec.unpackAccount(Lanes.Input);
|
|
32
30
|
setGuardian(guardian, false);
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
return
|
|
33
|
+
return closeCommand(exec);
|
|
36
34
|
}
|
|
37
35
|
}
|
|
@@ -19,21 +19,19 @@ abstract contract ExecutePayable is RawNodeCalls, AdminBase {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/// @notice Execute each CALL block in the admin input.
|
|
22
|
-
/// @param
|
|
22
|
+
/// @param context Admin command context carrying the CALL input stream.
|
|
23
23
|
/// @return Empty output state.
|
|
24
24
|
/// @return Remaining native value as a refund transaction stream.
|
|
25
25
|
function executePayable(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
) external payable onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
30
|
-
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
26
|
+
bytes calldata context
|
|
27
|
+
) external payable returns (bytes memory, bytes memory) {
|
|
28
|
+
Execution memory exec = openAdminCommand(context, descriptor, 0);
|
|
31
29
|
|
|
32
30
|
while (exec.more()) {
|
|
33
31
|
(uint target, uint resources, bytes calldata data) = exec.unpackCall(Lanes.Input);
|
|
34
32
|
rawCall(target, exec.useResourceValue(resources), data);
|
|
35
33
|
}
|
|
36
34
|
|
|
37
|
-
return
|
|
35
|
+
return closeCommand(exec);
|
|
38
36
|
}
|
|
39
37
|
}
|
|
@@ -22,21 +22,19 @@ abstract contract Unauthorize is AdminBase {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/// @notice Unauthorize each NODE block in the admin input.
|
|
25
|
-
/// @param
|
|
25
|
+
/// @param context Admin command context carrying the NODE input stream.
|
|
26
26
|
/// @return Empty output state.
|
|
27
27
|
/// @return Empty transaction stream.
|
|
28
28
|
function unauthorize(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
33
|
-
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
29
|
+
bytes calldata context
|
|
30
|
+
) external returns (bytes memory, bytes memory) {
|
|
31
|
+
Execution memory exec = openAdminCommand(context, descriptor, 0);
|
|
34
32
|
|
|
35
33
|
while (exec.more()) {
|
|
36
34
|
uint node = exec.unpackNode(Lanes.Input);
|
|
37
35
|
setNode(node, false);
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
return
|
|
38
|
+
return closeCommand(exec);
|
|
41
39
|
}
|
|
42
40
|
}
|
package/core/Calls.sol
CHANGED
|
@@ -3,6 +3,9 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {TrustAccess} from "./Access.sol";
|
|
5
5
|
import {Nodes} from "../utils/Nodes.sol";
|
|
6
|
+
import {Keys} from "../codec/Keys.sol";
|
|
7
|
+
import {Sizes} from "../codec/Specs.sol";
|
|
8
|
+
import {max32} from "../utils/Utils.sol";
|
|
6
9
|
|
|
7
10
|
/// @dev Emitted when a trusted inter-node call fails.
|
|
8
11
|
/// @param addr Contract address that was called.
|
|
@@ -81,6 +84,50 @@ abstract contract NodeCalls is RawNodeCalls, TrustAccess {
|
|
|
81
84
|
/// @title CommandCalls
|
|
82
85
|
/// @notice Trusted command-call helpers for contracts that route command nodes.
|
|
83
86
|
abstract contract CommandCalls is NodeCalls {
|
|
87
|
+
/// @dev Build `command(bytes)` calldata and its nested CONTEXT block in one allocation.
|
|
88
|
+
/// Threaded state is copied from memory and step input directly from calldata.
|
|
89
|
+
function encodeCommandCall(
|
|
90
|
+
bytes4 selector,
|
|
91
|
+
bytes32 account,
|
|
92
|
+
bytes memory state,
|
|
93
|
+
bytes calldata input
|
|
94
|
+
) internal pure returns (bytes memory data) {
|
|
95
|
+
uint contextLen = max32(Sizes.B32 + 2 * Sizes.Header + state.length + input.length);
|
|
96
|
+
uint paddedContextLen = (contextLen + 31) & ~uint(31);
|
|
97
|
+
uint dataLen = 4 + 64 + paddedContextLen;
|
|
98
|
+
|
|
99
|
+
// Reserve one scratch word because the final eight-byte block header is
|
|
100
|
+
// written with mstore. Exclude that word from the returned calldata.
|
|
101
|
+
data = new bytes(dataLen + 32);
|
|
102
|
+
|
|
103
|
+
uint contextKey = uint32(Keys.Context);
|
|
104
|
+
uint bytesKey = uint32(Keys.Bytes);
|
|
105
|
+
assembly ("memory-safe") {
|
|
106
|
+
mstore(data, dataLen)
|
|
107
|
+
let out := add(data, 0x20)
|
|
108
|
+
|
|
109
|
+
// ABI envelope for command(bytes).
|
|
110
|
+
mstore(out, selector)
|
|
111
|
+
mstore(add(out, 0x04), 0x20)
|
|
112
|
+
mstore(add(out, 0x24), contextLen)
|
|
113
|
+
|
|
114
|
+
// CONTEXT(account, BYTES(state), BYTES(input)).
|
|
115
|
+
let context := add(out, 0x44)
|
|
116
|
+
mstore(context, or(shl(224, contextKey), shl(192, sub(contextLen, 8))))
|
|
117
|
+
mstore(add(context, 0x08), account)
|
|
118
|
+
|
|
119
|
+
let stateBlock := add(context, 0x28)
|
|
120
|
+
let stateLen := mload(state)
|
|
121
|
+
mstore(stateBlock, or(shl(224, bytesKey), shl(192, stateLen)))
|
|
122
|
+
mcopy(add(stateBlock, 0x08), add(state, 0x20), stateLen)
|
|
123
|
+
|
|
124
|
+
let inputBlock := add(add(stateBlock, 0x08), stateLen)
|
|
125
|
+
let inputLen := input.length
|
|
126
|
+
mstore(inputBlock, or(shl(224, bytesKey), shl(192, inputLen)))
|
|
127
|
+
calldatacopy(add(inputBlock, 0x08), input.offset, inputLen)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
84
131
|
/// @notice Encode and call a trusted command node.
|
|
85
132
|
/// @param command Command node ID embedding the target selector.
|
|
86
133
|
/// @param value Native value to forward in wei.
|
|
@@ -97,7 +144,7 @@ abstract contract CommandCalls is NodeCalls {
|
|
|
97
144
|
bytes calldata input
|
|
98
145
|
) internal returns (bytes memory nextState, bytes memory transactions) {
|
|
99
146
|
bytes4 selector = Nodes.commandSelector(command);
|
|
100
|
-
bytes memory data =
|
|
147
|
+
bytes memory data = encodeCommandCall(selector, account, state, input);
|
|
101
148
|
return abi.decode(trustedCall(command, value, data), (bytes, bytes));
|
|
102
149
|
}
|
|
103
150
|
}
|
|
@@ -110,7 +157,18 @@ abstract contract PortCalls is NodeCalls {
|
|
|
110
157
|
/// @param value Native value to forward in wei.
|
|
111
158
|
/// @param input Port input block stream.
|
|
112
159
|
/// @return success True if the low-level port call succeeded.
|
|
113
|
-
function tryCallPort(uint port, uint128 value, bytes
|
|
160
|
+
function tryCallPort(uint port, uint128 value, bytes memory input) internal returns (bool success) {
|
|
161
|
+
bytes4 selector = Nodes.portSelector(port);
|
|
162
|
+
bytes memory data = abi.encodeWithSelector(selector, input);
|
|
163
|
+
return tryTrustedCall(port, value, data);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/// @notice Try to encode and call a trusted port node by copying input from calldata.
|
|
167
|
+
/// @param port Port node ID embedding the target selector.
|
|
168
|
+
/// @param value Native value to forward in wei.
|
|
169
|
+
/// @param input Port input block stream.
|
|
170
|
+
/// @return success True if the low-level port call succeeded.
|
|
171
|
+
function tryCallPortCopy(uint port, uint128 value, bytes calldata input) internal returns (bool success) {
|
|
114
172
|
bytes4 selector = Nodes.portSelector(port);
|
|
115
173
|
bytes memory data = abi.encodeWithSelector(selector, input);
|
|
116
174
|
return tryTrustedCall(port, value, data);
|
|
@@ -121,7 +179,18 @@ abstract contract PortCalls is NodeCalls {
|
|
|
121
179
|
/// @param value Native value to forward in wei.
|
|
122
180
|
/// @param input Port input block stream.
|
|
123
181
|
/// @return Decoded port output block stream.
|
|
124
|
-
function callPort(uint port, uint128 value, bytes
|
|
182
|
+
function callPort(uint port, uint128 value, bytes memory input) internal returns (bytes memory) {
|
|
183
|
+
bytes4 selector = Nodes.portSelector(port);
|
|
184
|
+
bytes memory data = abi.encodeWithSelector(selector, input);
|
|
185
|
+
return abi.decode(trustedCall(port, value, data), (bytes));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/// @notice Encode and call a trusted port node by copying input from calldata.
|
|
189
|
+
/// @param port Port node ID embedding the target selector.
|
|
190
|
+
/// @param value Native value to forward in wei.
|
|
191
|
+
/// @param input Port input block stream.
|
|
192
|
+
/// @return Decoded port output block stream.
|
|
193
|
+
function callPortCopy(uint port, uint128 value, bytes calldata input) internal returns (bytes memory) {
|
|
125
194
|
bytes4 selector = Nodes.portSelector(port);
|
|
126
195
|
bytes memory data = abi.encodeWithSelector(selector, input);
|
|
127
196
|
return abi.decode(trustedCall(port, value, data), (bytes));
|
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
|
@@ -21,7 +21,7 @@ abstract contract Portal is PortCalls, NodeAccess, UnresolvedEvent, ResolvedEven
|
|
|
21
21
|
/// @param value Native EVM value assigned to the forwarding attempt.
|
|
22
22
|
/// @return miss Message digest recorded for recovery when forwarding fails; zero on success.
|
|
23
23
|
function forward(uint port, bytes32 key, bytes calldata message, uint128 value) internal returns (bytes32 miss) {
|
|
24
|
-
if (
|
|
24
|
+
if (tryCallPortCopy(port, value, message)) return bytes32(0);
|
|
25
25
|
|
|
26
26
|
miss = keccak256(message);
|
|
27
27
|
unresolved[key] = miss;
|
|
@@ -37,6 +37,6 @@ abstract contract Portal is PortCalls, NodeAccess, UnresolvedEvent, ResolvedEven
|
|
|
37
37
|
if (unresolved[key] != keccak256(witness)) revert BadWitness();
|
|
38
38
|
|
|
39
39
|
delete unresolved[key];
|
|
40
|
-
|
|
40
|
+
callPortCopy(port, value, witness);
|
|
41
41
|
}
|
|
42
42
|
}
|
package/events/Dispatch.sol
CHANGED
|
@@ -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
|
|
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.
|
|
@@ -0,0 +1,22 @@
|
|
|
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 action produces an account position.
|
|
7
|
+
abstract contract PositionedEvent is EventEmitter {
|
|
8
|
+
string private constant ABI =
|
|
9
|
+
"event Positioned(bytes32 indexed account, bytes32 asset, uint amount, bytes32 liability, uint debt, uint32 action)";
|
|
10
|
+
|
|
11
|
+
/// @param account Account associated with the position.
|
|
12
|
+
/// @param asset Identifier for the asset side.
|
|
13
|
+
/// @param amount Quantity on the asset side.
|
|
14
|
+
/// @param liability Identifier for the liability side.
|
|
15
|
+
/// @param debt Quantity owed on the liability side.
|
|
16
|
+
/// @param action Primary operation hint from `Actions` that produced the position.
|
|
17
|
+
event Positioned(bytes32 indexed account, bytes32 asset, uint amount, bytes32 liability, uint debt, uint32 action);
|
|
18
|
+
|
|
19
|
+
constructor() {
|
|
20
|
+
emit EventAbi(ABI);
|
|
21
|
+
}
|
|
22
|
+
}
|
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
|
|
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.
|
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
|
|
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
|
|
package/execution/Execution.sol
CHANGED
|
@@ -15,6 +15,7 @@ import {max16} from "../utils/Utils.sol";
|
|
|
15
15
|
/// @dev `decoders` contains tagged input and state cursor lanes. Cursor operations
|
|
16
16
|
/// select one logical lane by swapping it into the lower 128 bits.
|
|
17
17
|
struct Execution {
|
|
18
|
+
bytes32 account;
|
|
18
19
|
uint budget;
|
|
19
20
|
uint decoders;
|
|
20
21
|
uint writers;
|
|
@@ -187,6 +188,52 @@ library Executions {
|
|
|
187
188
|
return exec.decoders.any();
|
|
188
189
|
}
|
|
189
190
|
|
|
191
|
+
/// @notice Return a decoder lane's current absolute calldata position.
|
|
192
|
+
/// @param exec Execution whose decoder is inspected.
|
|
193
|
+
/// @param lane Decoder lane to select.
|
|
194
|
+
/// @return Current absolute calldata position of the selected lane.
|
|
195
|
+
function absolute(Execution memory exec, uint8 lane) internal pure returns (uint) {
|
|
196
|
+
return exec.decoders.select(lane).absolute();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/// @dev Return the complete validated calldata source for a decoder lane.
|
|
200
|
+
/// @dev Does not consume or depend on the lane's current position. A lane
|
|
201
|
+
/// absent because its descriptor is EMPTY returns an empty calldata slice.
|
|
202
|
+
/// @param exec Execution whose input or state source is requested.
|
|
203
|
+
/// @param lane Input or state decoder lane.
|
|
204
|
+
/// @return data Complete calldata region represented by the lane.
|
|
205
|
+
function raw(Execution memory exec, uint8 lane) private pure returns (bytes calldata data) {
|
|
206
|
+
if (!exec.decoders.contains(lane)) return msg.data[0:0];
|
|
207
|
+
|
|
208
|
+
uint cur = exec.decoders.select(lane);
|
|
209
|
+
(, uint offset, uint len) = cur.decode();
|
|
210
|
+
if (len > msg.data.length || offset > msg.data.length - len) revert Blocks.MalformedBlocks();
|
|
211
|
+
return msg.data[offset:offset + len];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/// @notice Return the complete validated command state without consuming it.
|
|
215
|
+
/// @dev Remains the complete original state after the state cursor advances.
|
|
216
|
+
function rawState(Execution memory exec) internal pure returns (bytes calldata) {
|
|
217
|
+
return raw(exec, Lanes.State);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/// @notice Return the complete validated endpoint input without consuming it.
|
|
221
|
+
/// @dev Remains the complete original input after the input cursor advances.
|
|
222
|
+
function rawInput(Execution memory exec) internal pure returns (bytes calldata) {
|
|
223
|
+
return raw(exec, Lanes.Input);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/// @notice Return whether the next block on `lane` has `key` and an empty payload.
|
|
227
|
+
/// @param exec Execution whose decoder is inspected without advancing.
|
|
228
|
+
/// @param lane Decoder lane to inspect.
|
|
229
|
+
/// @param key Expected block key.
|
|
230
|
+
/// @return Whether a complete matching empty block header occurs next.
|
|
231
|
+
function isEmpty(Execution memory exec, uint8 lane, bytes4 key) internal pure returns (bool) {
|
|
232
|
+
uint cur = exec.decoders.select(lane);
|
|
233
|
+
(uint i, uint offset, uint len) = cur.decode();
|
|
234
|
+
return Blocks.isEmpty(offset + i, offset + len, key);
|
|
235
|
+
}
|
|
236
|
+
|
|
190
237
|
/// @notice Validate and consume the next block from an execution decoder lane.
|
|
191
238
|
/// @param exec Execution whose selected decoder cursor is advanced over the complete block.
|
|
192
239
|
/// @param lane Execution decoder lane to select.
|
|
@@ -199,6 +246,34 @@ library Executions {
|
|
|
199
246
|
exec.decoders = cur.seekAbs(end);
|
|
200
247
|
}
|
|
201
248
|
|
|
249
|
+
/// @notice Validate and consume one block from a decoder lane, returning its complete encoding.
|
|
250
|
+
/// @param exec Execution whose selected decoder cursor is advanced past the block.
|
|
251
|
+
/// @param lane Execution decoder lane to select.
|
|
252
|
+
/// @param key Expected block key.
|
|
253
|
+
/// @return data Calldata view of the complete block, including its header.
|
|
254
|
+
function takeBlock(
|
|
255
|
+
Execution memory exec,
|
|
256
|
+
uint8 lane,
|
|
257
|
+
bytes4 key
|
|
258
|
+
) internal pure returns (bytes calldata data) {
|
|
259
|
+
(uint abs, uint end) = consume(exec, lane, Specs.create(key, 0, 0, 0));
|
|
260
|
+
data = msg.data[abs - Sizes.Header:end];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/// @notice Consume a matching empty block from an execution decoder lane when present.
|
|
264
|
+
/// @param exec Execution whose selected decoder advances only for a matching empty block.
|
|
265
|
+
/// @param lane Decoder lane to consume.
|
|
266
|
+
/// @param key Expected block key.
|
|
267
|
+
/// @return Whether an empty block was consumed.
|
|
268
|
+
function tryConsumeEmpty(Execution memory exec, uint8 lane, bytes4 key) internal pure returns (bool) {
|
|
269
|
+
uint cur = exec.decoders.select(lane);
|
|
270
|
+
(uint i, uint offset, uint size) = cur.decode();
|
|
271
|
+
(bytes4 current, uint len) = Blocks.peek(offset + i, offset + size);
|
|
272
|
+
if (current != key || len != 0) return false;
|
|
273
|
+
exec.decoders = cur.seek(i + Sizes.Header);
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
|
|
202
277
|
/// @notice Validate and enter the payload of the next block in an execution decoder lane.
|
|
203
278
|
/// @dev The selected lane remains in its existing frame so callers can decode
|
|
204
279
|
/// child blocks in place. Callers should prove complete payload consumption
|
|
@@ -209,9 +284,48 @@ library Executions {
|
|
|
209
284
|
/// @return abs Absolute position of the first payload byte.
|
|
210
285
|
/// @return end Absolute position immediately after the payload.
|
|
211
286
|
function enter(Execution memory exec, uint8 lane, uint spec) internal pure returns (uint abs, uint end) {
|
|
287
|
+
return enter(exec, lane, spec, 0);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/// @notice Validate a parent block and advance over a fixed payload prefix.
|
|
291
|
+
/// @dev `amount` is relative to the payload start and cannot exceed the
|
|
292
|
+
/// current parent payload. The returned `abs` remains the payload start.
|
|
293
|
+
/// @param exec Execution whose selected decoder advances over the header and fixed prefix.
|
|
294
|
+
/// @param lane Execution decoder lane to select.
|
|
295
|
+
/// @param spec Expected parent block specification.
|
|
296
|
+
/// @param amount Number of initial payload bytes to advance over.
|
|
297
|
+
/// @return abs Absolute position of the first payload byte.
|
|
298
|
+
/// @return end Absolute position immediately after the payload.
|
|
299
|
+
function enter(
|
|
300
|
+
Execution memory exec,
|
|
301
|
+
uint8 lane,
|
|
302
|
+
uint spec,
|
|
303
|
+
uint amount
|
|
304
|
+
) internal pure returns (uint abs, uint end) {
|
|
212
305
|
uint cur = exec.decoders.select(lane);
|
|
213
306
|
(abs, end) = Blocks.expect(cur.absolute(), spec);
|
|
214
|
-
|
|
307
|
+
if (amount > end - abs) revert Blocks.InvalidBlock();
|
|
308
|
+
exec.decoders = cur.seekAbs(abs + amount);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/// @notice Advance an execution decoder lane by a raw byte count.
|
|
312
|
+
/// @dev No block header or schema is validated.
|
|
313
|
+
/// @param exec Execution whose selected decoder cursor is advanced.
|
|
314
|
+
/// @param lane Decoder lane to select.
|
|
315
|
+
/// @param amount Number of bytes to advance.
|
|
316
|
+
function advance(Execution memory exec, uint8 lane, uint amount) internal pure {
|
|
317
|
+
uint cur = exec.decoders.select(lane);
|
|
318
|
+
exec.decoders = cur.advance(amount);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/// @notice Take a raw byte range from an execution decoder lane.
|
|
322
|
+
/// @dev No block header or schema is validated.
|
|
323
|
+
/// @param exec Execution whose selected decoder cursor is advanced.
|
|
324
|
+
/// @param lane Decoder lane to select.
|
|
325
|
+
/// @param amount Number of bytes to take.
|
|
326
|
+
/// @return abs Absolute position of the first taken byte.
|
|
327
|
+
function take(Execution memory exec, uint8 lane, uint amount) internal pure returns (uint abs) {
|
|
328
|
+
(exec.decoders, abs) = exec.decoders.consume(lane, amount);
|
|
215
329
|
}
|
|
216
330
|
|
|
217
331
|
/// @notice Require the active execution decoder to be at absolute position `abs`.
|
|
@@ -246,9 +360,7 @@ library Executions {
|
|
|
246
360
|
|
|
247
361
|
/// @dev Return the next raw calldata word from `lane` and advance by `size` bytes.
|
|
248
362
|
function next(Execution memory exec, uint8 lane, uint size) private pure returns (bytes32 value) {
|
|
249
|
-
|
|
250
|
-
(exec.decoders, abs) = exec.decoders.consume(lane, size);
|
|
251
|
-
value = Blocks.read32(abs);
|
|
363
|
+
value = Blocks.read32(take(exec, lane, size));
|
|
252
364
|
}
|
|
253
365
|
|
|
254
366
|
/// @notice Return the next raw byte from a decoder lane and advance it by one byte.
|
|
@@ -806,6 +918,14 @@ library Executions {
|
|
|
806
918
|
return reserve(exec, size, size);
|
|
807
919
|
}
|
|
808
920
|
|
|
921
|
+
/// @notice Append an empty block to execution output.
|
|
922
|
+
/// @param exec Execution receiving the block.
|
|
923
|
+
/// @param key Block key.
|
|
924
|
+
function outputEmpty(Execution memory exec, bytes4 key) internal pure {
|
|
925
|
+
uint i = reserve(exec, Sizes.Header);
|
|
926
|
+
Blocks.writeEmpty(exec.output, i, key);
|
|
927
|
+
}
|
|
928
|
+
|
|
809
929
|
/// @notice Append an ACCOUNT block to execution output.
|
|
810
930
|
/// @param exec Execution receiving the block.
|
|
811
931
|
/// @param account Account identifier to encode.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rootzero/contracts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.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"
|