@rootzero/contracts 1.13.0 → 1.15.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 +87 -3
- package/Codec.sol +21 -0
- package/Commands.sol +14 -0
- package/Core.sol +8 -6
- package/Endpoints.sol +2 -7
- package/Events.sol +1 -2
- package/README.md +70 -37
- package/Utils.sol +2 -4
- package/annotations/Action.sol +17 -0
- package/annotations/Label.sol +23 -0
- package/annotations/Schema.sol +53 -0
- package/codec/Blocks.sol +1643 -0
- package/codec/Buffers.sol +165 -0
- package/codec/Decoders.sol +570 -0
- package/codec/Descriptors.sol +124 -0
- package/{blocks → codec}/Keys.sol +10 -18
- package/codec/Readers.sol +114 -0
- package/{blocks → codec}/Schema.sol +43 -80
- package/codec/Specs.sol +240 -0
- package/codec/Writers.sol +485 -0
- package/commands/Allocate.sol +21 -20
- package/commands/Base.sol +83 -45
- package/commands/Burn.sol +23 -14
- package/commands/Credit.sol +21 -20
- package/commands/Debit.sol +25 -28
- package/commands/Deposit.sol +41 -36
- package/commands/Payout.sol +26 -16
- package/commands/Provision.sol +37 -38
- package/commands/Recover.sol +20 -19
- package/commands/Relay.sol +24 -22
- package/commands/Withdraw.sol +20 -19
- package/commands/admin/AllowAssets.sol +19 -16
- package/commands/admin/Allowance.sol +18 -13
- package/commands/admin/Annotate.sol +36 -0
- package/commands/admin/Appoint.sol +19 -16
- package/commands/admin/Authorize.sol +23 -14
- package/commands/admin/Base.sol +9 -2
- package/commands/admin/DenyAssets.sol +19 -16
- package/commands/admin/Dismiss.sol +19 -16
- package/commands/admin/Execute.sol +21 -19
- package/commands/admin/Unauthorize.sol +23 -14
- package/core/Access.sol +91 -49
- package/core/Calls.sol +30 -33
- package/core/Endpoint.sol +46 -143
- package/core/Host.sol +63 -21
- package/core/Pipeline.sol +16 -15
- package/core/Types.sol +1 -1
- package/docs/Schema.md +48 -31
- package/events/Annotation.sol +24 -0
- package/events/Endpoint.sol +2 -2
- package/events/Guardian.sol +2 -2
- package/events/Introduction.sol +3 -2
- package/execution/Budget.sol +40 -0
- package/execution/Execution.sol +1104 -0
- package/guards/Base.sol +11 -12
- package/guards/Revoke.sol +11 -9
- package/package.json +1 -1
- package/ports/AllowAssets.sol +12 -15
- package/ports/Allowance.sol +11 -9
- package/ports/Base.sol +35 -16
- package/ports/Credit.sol +11 -9
- package/ports/Debit.sol +11 -9
- package/ports/DenyAssets.sol +10 -13
- package/ports/Dispatch.sol +13 -15
- package/ports/Pipe.sol +14 -12
- package/ports/Redeem.sol +12 -9
- package/ports/Settle.sol +16 -10
- package/queries/Assets.sol +15 -15
- package/queries/Balances.sol +17 -17
- package/queries/Base.sol +26 -12
- package/utils/Accounts.sol +0 -23
- package/utils/Actions.sol +1 -0
- package/utils/Cursors.sol +367 -0
- package/utils/Lanes.sol +14 -0
- package/utils/Layout.sol +0 -2
- package/utils/Selectors.sol +2 -2
- package/utils/Utils.sol +46 -0
- package/Cursors.sol +0 -16
- package/blocks/Cursors.sol +0 -1529
- package/blocks/Writers.sol +0 -1036
- package/commands/admin/Label.sol +0 -32
- package/commands/admin/Schemas.sol +0 -32
- package/core/Payable.sol +0 -53
- package/events/Labeled.sol +0 -21
- package/events/Schema.sol +0 -23
- package/utils/Value.sol +0 -43
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import { AdminBase,
|
|
5
|
-
|
|
6
|
-
using Cursors for Cur;
|
|
4
|
+
import { AdminBase, Execution, Executions, Lanes, Specs } from "./Base.sol";
|
|
5
|
+
using Executions for Execution;
|
|
7
6
|
|
|
7
|
+
/// @notice Hook implemented by hosts that deny assets.
|
|
8
8
|
abstract contract DenyAssetsHook {
|
|
9
9
|
/// @dev Override to deny a single asset.
|
|
10
|
-
/// Called once per ASSET block in the
|
|
10
|
+
/// Called once per ASSET block in the input.
|
|
11
11
|
/// @param asset Asset identifier.
|
|
12
12
|
function denyAsset(bytes32 asset) internal virtual;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/// @title DenyAssets
|
|
16
16
|
/// @notice Admin command that blocks a list of assets via a virtual hook.
|
|
17
|
-
/// Each ASSET block in the
|
|
17
|
+
/// Each ASSET block in the input calls `denyAsset`. Only callable by the admin account.
|
|
18
18
|
abstract contract DenyAssets is AdminBase, DenyAssetsHook {
|
|
19
|
-
|
|
19
|
+
uint private immutable descriptor;
|
|
20
20
|
|
|
21
21
|
constructor() {
|
|
22
|
-
(, descriptor) = command("denyAssets",
|
|
22
|
+
(, descriptor) = command("denyAssets", Specs.Empty, Specs.Asset, Specs.Empty, 0, false, true);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/// @notice Deny each ASSET block in the admin
|
|
26
|
-
/// @param
|
|
25
|
+
/// @notice Deny each ASSET block in the admin input.
|
|
26
|
+
/// @param input ASSET block stream.
|
|
27
27
|
/// @return Empty output state.
|
|
28
28
|
/// @return Empty transaction stream.
|
|
29
29
|
function denyAssets(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
bytes32 account,
|
|
31
|
+
bytes calldata,
|
|
32
|
+
bytes calldata input
|
|
33
|
+
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
34
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
35
|
+
|
|
36
|
+
while (exec.more()) {
|
|
37
|
+
bytes32 asset = exec.unpackAsset(Lanes.Input);
|
|
36
38
|
denyAsset(asset);
|
|
37
39
|
}
|
|
38
|
-
|
|
40
|
+
|
|
41
|
+
return close(exec, account);
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
|
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import { AdminBase,
|
|
5
|
-
import {
|
|
6
|
-
using
|
|
4
|
+
import { AdminBase, Execution, Executions, Lanes, Specs } from "./Base.sol";
|
|
5
|
+
import { GuardianAccess } from "../../core/Access.sol";
|
|
6
|
+
using Executions for Execution;
|
|
7
7
|
|
|
8
8
|
/// @title Dismiss
|
|
9
9
|
/// @notice Admin command that revokes guardian status from a list of account IDs.
|
|
10
|
-
/// Each ACCOUNT block in the
|
|
10
|
+
/// Each USER ACCOUNT block in the input loses the guardian role on the host.
|
|
11
11
|
/// Only callable by the admin account.
|
|
12
|
-
abstract contract Dismiss is AdminBase {
|
|
13
|
-
|
|
12
|
+
abstract contract Dismiss is GuardianAccess, AdminBase {
|
|
13
|
+
uint private immutable descriptor;
|
|
14
14
|
|
|
15
15
|
constructor() {
|
|
16
|
-
(, descriptor) = command("dismiss",
|
|
16
|
+
(, descriptor) = command("dismiss", Specs.Empty, Specs.Account, Specs.Empty, 0, false, true);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/// @notice Dismiss each ACCOUNT block in the admin
|
|
20
|
-
/// @param
|
|
19
|
+
/// @notice Dismiss each user ACCOUNT block in the admin input from guardian status.
|
|
20
|
+
/// @param input ACCOUNT block stream.
|
|
21
21
|
/// @return Empty output state.
|
|
22
22
|
/// @return Empty transaction stream.
|
|
23
23
|
function dismiss(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
bytes32 account,
|
|
25
|
+
bytes calldata,
|
|
26
|
+
bytes calldata input
|
|
27
|
+
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
28
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
27
29
|
|
|
28
|
-
while (
|
|
29
|
-
bytes32
|
|
30
|
-
setGuardian(
|
|
30
|
+
while (exec.more()) {
|
|
31
|
+
bytes32 guardian = exec.unpackAccount(Lanes.Input);
|
|
32
|
+
setGuardian(guardian, false);
|
|
31
33
|
}
|
|
32
|
-
|
|
34
|
+
|
|
35
|
+
return close(exec, account);
|
|
33
36
|
}
|
|
34
37
|
}
|
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AdminBase,
|
|
5
|
-
import {
|
|
6
|
-
import {Cursors, Cur} from "../../Cursors.sol";
|
|
7
|
-
import {Budget} from "../../utils/Value.sol";
|
|
4
|
+
import {AdminBase, Execution, Executions, Lanes, Specs} from "./Base.sol";
|
|
5
|
+
import {RawNodeCalls} from "../../core/Calls.sol";
|
|
8
6
|
|
|
9
|
-
using
|
|
7
|
+
using Executions for Execution;
|
|
10
8
|
|
|
11
9
|
/// @title ExecutePayable
|
|
12
10
|
/// @notice Admin command that forwards raw calldata to one or more target nodes.
|
|
13
11
|
/// Each CALL block specifies a target node ID, packed resources, and raw calldata payload.
|
|
14
12
|
/// Only callable by the admin account.
|
|
15
|
-
/// Unspent top-level `msg.value`
|
|
16
|
-
abstract contract ExecutePayable is
|
|
17
|
-
|
|
13
|
+
/// Unspent top-level `msg.value` is returned as a refund transaction.
|
|
14
|
+
abstract contract ExecutePayable is RawNodeCalls, AdminBase {
|
|
15
|
+
uint private immutable descriptor;
|
|
18
16
|
|
|
19
17
|
constructor() {
|
|
20
|
-
(, descriptor) = command("executePayable",
|
|
18
|
+
(, descriptor) = command("executePayable", Specs.Empty, Specs.Call, Specs.Empty, 0, true, true);
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
/// @notice Execute each CALL block in the admin
|
|
24
|
-
/// @param
|
|
21
|
+
/// @notice Execute each CALL block in the admin input.
|
|
22
|
+
/// @param input CALL block stream.
|
|
25
23
|
/// @return Empty output state.
|
|
26
|
-
/// @return
|
|
27
|
-
function executePayable(
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
/// @return Remaining native value as a refund transaction stream.
|
|
25
|
+
function executePayable(
|
|
26
|
+
bytes32 account,
|
|
27
|
+
bytes calldata,
|
|
28
|
+
bytes calldata input
|
|
29
|
+
) external payable onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
30
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
30
31
|
|
|
31
|
-
while (
|
|
32
|
-
(uint target, uint resources, bytes calldata data) =
|
|
33
|
-
rawCall(target, useValue(
|
|
32
|
+
while (exec.more()) {
|
|
33
|
+
(uint target, uint resources, bytes calldata data) = exec.unpackCall(Lanes.Input);
|
|
34
|
+
rawCall(target, exec.useValue(resources), data);
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
|
|
37
|
+
return close(exec, account);
|
|
36
38
|
}
|
|
37
39
|
}
|
|
@@ -1,33 +1,42 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AdminBase,
|
|
5
|
-
|
|
6
|
-
using Cursors for Cur;
|
|
4
|
+
import {AdminBase, Execution, Executions, Lanes, Specs} from "./Base.sol";
|
|
5
|
+
using Executions for Execution;
|
|
7
6
|
|
|
8
7
|
/// @title Unauthorize
|
|
9
8
|
/// @notice Admin command that revokes authorization from a list of node IDs.
|
|
10
|
-
/// Each NODE block in the
|
|
9
|
+
/// Each NODE block in the input is deauthorized on the host.
|
|
11
10
|
/// Only callable by the admin account.
|
|
12
11
|
abstract contract Unauthorize is AdminBase {
|
|
13
|
-
|
|
14
|
-
uint
|
|
12
|
+
uint private immutable descriptor;
|
|
13
|
+
uint private immutable id;
|
|
15
14
|
|
|
16
15
|
constructor() {
|
|
17
|
-
(
|
|
16
|
+
(id, descriptor) = command("unauthorize", Specs.Empty, Specs.Node, Specs.Empty, 0, false, true);
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
/// @notice
|
|
21
|
-
|
|
19
|
+
/// @notice Return the registered UNAUTHORIZE command ID.
|
|
20
|
+
function unauthorizeId() internal view returns (uint) {
|
|
21
|
+
return id;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// @notice Unauthorize each NODE block in the admin input.
|
|
25
|
+
/// @param input NODE block stream.
|
|
22
26
|
/// @return Empty output state.
|
|
23
27
|
/// @return Empty transaction stream.
|
|
24
|
-
function unauthorize(
|
|
25
|
-
|
|
28
|
+
function unauthorize(
|
|
29
|
+
bytes32 account,
|
|
30
|
+
bytes calldata,
|
|
31
|
+
bytes calldata input
|
|
32
|
+
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
33
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
26
34
|
|
|
27
|
-
while (
|
|
28
|
-
uint node =
|
|
35
|
+
while (exec.more()) {
|
|
36
|
+
uint node = exec.unpackNode(Lanes.Input);
|
|
29
37
|
setNode(node, false);
|
|
30
38
|
}
|
|
31
|
-
|
|
39
|
+
|
|
40
|
+
return close(exec, account);
|
|
32
41
|
}
|
|
33
42
|
}
|
package/core/Access.sol
CHANGED
|
@@ -8,34 +8,75 @@ import {Accounts} from "../utils/Accounts.sol";
|
|
|
8
8
|
import {Nodes} from "../utils/Nodes.sol";
|
|
9
9
|
import {addrOr} from "../utils/Utils.sol";
|
|
10
10
|
|
|
11
|
-
/// @
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/// mapping of externally trusted node IDs. Inbound trust is host-based:
|
|
15
|
-
/// trusted hosts, the commander, and this contract itself may interact
|
|
16
|
-
/// with the host through the guarded command and peer entrypoints.
|
|
17
|
-
abstract contract AccessControl is Runtime, NodeEvent, GuardianEvent {
|
|
18
|
-
/// @dev Trusted commander address. All calls from this address are implicitly trusted.
|
|
19
|
-
/// Defaults to `address(this)` when no external commander is provided.
|
|
20
|
-
address internal immutable commander;
|
|
21
|
-
/// @dev Admin account ID derived from the commander address at construction time.
|
|
22
|
-
bytes32 internal immutable admin;
|
|
11
|
+
/// @dev Thrown when a caller, account, or node lacks required access.
|
|
12
|
+
error AccessDenied();
|
|
13
|
+
error CommanderNotAllowed();
|
|
23
14
|
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
/// @title CallerAccess
|
|
16
|
+
/// @notice Authorization capability required by command entrypoints.
|
|
17
|
+
abstract contract CallerAccess is Runtime {
|
|
18
|
+
/// @notice Assert that `caller` may invoke a command and return it.
|
|
19
|
+
function enforceCaller(address caller) internal view virtual returns (address);
|
|
20
|
+
}
|
|
26
21
|
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
/// @title TrustAccess
|
|
23
|
+
/// @notice Authorization capability required by trusted outbound node calls.
|
|
24
|
+
abstract contract TrustAccess {
|
|
25
|
+
/// @notice Assert that `node` is trusted and return it.
|
|
26
|
+
function ensureTrusted(uint node) internal view virtual returns (uint);
|
|
27
|
+
}
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/// @title CommanderAccess
|
|
30
|
+
/// @notice Minimal commander-based access control shared by host access policies.
|
|
31
|
+
abstract contract CommanderAccess is Runtime {
|
|
32
|
+
/// @dev Trusted commander address.
|
|
33
|
+
/// Defaults to `address(this)` when no external commander is provided.
|
|
34
|
+
address internal immutable commander;
|
|
32
35
|
|
|
33
36
|
/// @param cmdr Commander address, or zero to make this contract self-managed.
|
|
34
37
|
constructor(address cmdr) {
|
|
35
38
|
commander = addrOr(cmdr, address(this));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// @notice Assert that `caller` is the commander and return it.
|
|
42
|
+
/// @param caller Address to validate.
|
|
43
|
+
/// @return The same `caller` value if it is the commander.
|
|
44
|
+
function enforceCommander(address caller) internal view returns (address) {
|
|
45
|
+
if (caller == address(0) || caller != commander) {
|
|
46
|
+
revert AccessDenied();
|
|
47
|
+
}
|
|
48
|
+
return caller;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// @title AdminAccess
|
|
54
|
+
/// @notice Commander access with the admin account derived from the commander.
|
|
55
|
+
abstract contract AdminAccess is CommanderAccess {
|
|
56
|
+
/// @dev Admin account ID derived from the commander address at construction time.
|
|
57
|
+
bytes32 internal immutable admin;
|
|
58
|
+
|
|
59
|
+
constructor() {
|
|
36
60
|
admin = Accounts.toAdmin(commander);
|
|
37
61
|
}
|
|
38
62
|
|
|
63
|
+
/// @notice Assert that `account` is the admin account and `caller` is the commander.
|
|
64
|
+
function enforceAdmin(bytes32 account, address caller) internal view returns (bytes32) {
|
|
65
|
+
if (account != admin) revert AccessDenied();
|
|
66
|
+
enforceCommander(caller);
|
|
67
|
+
return account;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/// @title NodeAccess
|
|
72
|
+
/// @notice Admin access extended with externally trusted node IDs.
|
|
73
|
+
/// Inbound trust is host-based:
|
|
74
|
+
/// trusted hosts, the commander, and this contract itself may interact
|
|
75
|
+
/// with the host through the guarded command and peer entrypoints.
|
|
76
|
+
abstract contract NodeAccess is AdminAccess, TrustAccess, NodeEvent {
|
|
77
|
+
/// @dev Mapping from node ID to trust status.
|
|
78
|
+
mapping(uint node => bool) internal nodes;
|
|
79
|
+
|
|
39
80
|
/// @notice Set authorization status for a node.
|
|
40
81
|
/// @param node Node ID to update.
|
|
41
82
|
/// @param active True to authorize the node, false to revoke it.
|
|
@@ -44,58 +85,59 @@ abstract contract AccessControl is Runtime, NodeEvent, GuardianEvent {
|
|
|
44
85
|
emit Node(host, node, active);
|
|
45
86
|
}
|
|
46
87
|
|
|
47
|
-
/// @notice Set guardian status for an account.
|
|
48
|
-
/// @param account Guardian account ID to update.
|
|
49
|
-
/// @param active True to enable the guardian, false to revoke it.
|
|
50
|
-
function setGuardian(bytes32 account, bool active) internal {
|
|
51
|
-
Accounts.guardian(account);
|
|
52
|
-
guardians[account] = active;
|
|
53
|
-
emit Guardian(host, account, active);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/// @notice Return true if `addr` is an active guardian.
|
|
57
|
-
/// @param addr EVM address to check as a guardian account.
|
|
58
|
-
function isGuardian(address addr) internal view returns (bool) {
|
|
59
|
-
return guardians[Accounts.toGuardian(addr)];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
88
|
/// @notice Return true if `caller` is an implicitly trusted address.
|
|
63
89
|
/// Trusted callers: the commander, this contract itself, or any address
|
|
64
90
|
/// whose host ID has been explicitly authorized.
|
|
65
91
|
/// @param caller Address to check.
|
|
66
|
-
function
|
|
92
|
+
function isTrustedCaller(address caller) internal view returns (bool) {
|
|
67
93
|
return caller == commander || caller == address(this) || nodes[Nodes.toHost(caller)];
|
|
68
94
|
}
|
|
69
95
|
|
|
70
96
|
/// @notice Assert that `node` is in the trusted set and return it.
|
|
71
97
|
/// @param node Node ID to validate.
|
|
72
98
|
/// @return The same `node` value if trusted.
|
|
73
|
-
function ensureTrusted(uint node) internal view returns (uint) {
|
|
99
|
+
function ensureTrusted(uint node) internal view override returns (uint) {
|
|
74
100
|
if (node == 0 || !nodes[node]) {
|
|
75
101
|
revert AccessDenied();
|
|
76
102
|
}
|
|
77
103
|
return node;
|
|
78
104
|
}
|
|
79
105
|
|
|
80
|
-
/// @notice Assert that `caller` is trusted
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
function enforceCaller(address caller) internal view returns (address) {
|
|
85
|
-
if (caller == address(0) || !isTrusted(caller)) {
|
|
106
|
+
/// @notice Assert that `caller` is a trusted peer other than the commander.
|
|
107
|
+
function enforcePeer(address caller) internal view returns (address) {
|
|
108
|
+
if (caller == commander) revert CommanderNotAllowed();
|
|
109
|
+
if (caller == address(0) || !isTrustedCaller(caller)) {
|
|
86
110
|
revert AccessDenied();
|
|
87
111
|
}
|
|
88
112
|
return caller;
|
|
89
113
|
}
|
|
90
114
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/// @title GuardianAccess
|
|
118
|
+
/// @notice Node access extended with guardian identity and authorization.
|
|
119
|
+
abstract contract GuardianAccess is NodeAccess, GuardianEvent {
|
|
120
|
+
/// @dev Mapping from user account ID to guardian status.
|
|
121
|
+
mapping(bytes32 account => bool) internal guardians;
|
|
122
|
+
|
|
123
|
+
/// @notice Set guardian status for an account.
|
|
124
|
+
/// @param account User account ID whose guardian role is updated.
|
|
125
|
+
/// @param active True to enable the guardian, false to revoke it.
|
|
126
|
+
function setGuardian(bytes32 account, bool active) internal {
|
|
127
|
+
account = Accounts.user(account);
|
|
128
|
+
guardians[account] = active;
|
|
129
|
+
emit Guardian(host, account, active);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/// @notice Return true if `addr` is an active guardian.
|
|
133
|
+
/// @param addr EVM address to check for the guardian role.
|
|
134
|
+
function isGuardian(address addr) internal view returns (bool) {
|
|
135
|
+
return guardians[Accounts.toUser(addr)];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/// @notice Assert that `caller` is an active guardian and return it.
|
|
139
|
+
function enforceGuardian(address caller) internal view returns (address) {
|
|
140
|
+
if (caller == address(0) || !isGuardian(caller)) revert AccessDenied();
|
|
99
141
|
return caller;
|
|
100
142
|
}
|
|
101
143
|
}
|
package/core/Calls.sol
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {CommandContext} from "../commands/Base.sol";
|
|
4
|
+
import {TrustAccess} from "./Access.sol";
|
|
6
5
|
import {Nodes} from "../utils/Nodes.sol";
|
|
7
6
|
|
|
8
7
|
/// @dev Emitted when a trusted inter-node call fails.
|
|
@@ -11,16 +10,9 @@ import {Nodes} from "../utils/Nodes.sol";
|
|
|
11
10
|
/// @param err Revert data returned by the failed call.
|
|
12
11
|
error FailedCall(address addr, bytes4 selector, bytes err);
|
|
13
12
|
|
|
14
|
-
/// @title
|
|
15
|
-
/// @notice
|
|
16
|
-
abstract contract
|
|
17
|
-
/// @notice Return the host node ID corresponding to the current caller.
|
|
18
|
-
/// @dev Encodes `msg.sender` as a host ID using the local-chain host layout.
|
|
19
|
-
/// @return Host node ID for `msg.sender`.
|
|
20
|
-
function caller() internal view returns (uint) {
|
|
21
|
-
return Nodes.toHost(msg.sender);
|
|
22
|
-
}
|
|
23
|
-
|
|
13
|
+
/// @title RawNodeCalls
|
|
14
|
+
/// @notice Low-level inter-node call helpers without target authorization.
|
|
15
|
+
abstract contract RawNodeCalls {
|
|
24
16
|
/// @notice Try a raw low-level call to another node and return whether it succeeded.
|
|
25
17
|
/// @param node Node ID of the callee.
|
|
26
18
|
/// @param value Native value to forward in wei.
|
|
@@ -31,15 +23,6 @@ abstract contract NodeCalls is AccessControl {
|
|
|
31
23
|
(success, ) = payable(addr).call{value: value}(data);
|
|
32
24
|
}
|
|
33
25
|
|
|
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.
|
|
37
|
-
/// @param data Encoded calldata to send.
|
|
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
26
|
/// @notice Make a raw low-level call to another node and revert when it fails.
|
|
44
27
|
/// @param node Node ID of the callee.
|
|
45
28
|
/// @param value Native value to forward in wei.
|
|
@@ -52,15 +35,6 @@ abstract contract NodeCalls is AccessControl {
|
|
|
52
35
|
if (!success) revert FailedCall(addr, bytes4(data), out);
|
|
53
36
|
}
|
|
54
37
|
|
|
55
|
-
/// @notice Make a trusted low-level call to another node and revert when it fails.
|
|
56
|
-
/// @param node Node ID of the callee.
|
|
57
|
-
/// @param value Native value to forward in wei.
|
|
58
|
-
/// @param data Encoded calldata to send.
|
|
59
|
-
/// @return out Return data from the successful call.
|
|
60
|
-
function trustedCall(uint node, uint128 value, bytes memory data) internal returns (bytes memory out) {
|
|
61
|
-
return rawCall(ensureTrusted(node), value, data);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
38
|
/// @notice Make a raw low-level read-only query to another node and revert when it fails.
|
|
65
39
|
/// @param node Node ID of the callee.
|
|
66
40
|
/// @param data Encoded calldata to send.
|
|
@@ -72,6 +46,29 @@ abstract contract NodeCalls is AccessControl {
|
|
|
72
46
|
if (!success) revert FailedCall(addr, bytes4(data), out);
|
|
73
47
|
}
|
|
74
48
|
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// @title NodeCalls
|
|
52
|
+
/// @notice Trusted low-level inter-node calls backed by a host-provided node policy.
|
|
53
|
+
abstract contract NodeCalls is RawNodeCalls, TrustAccess {
|
|
54
|
+
/// @notice Try a trusted low-level call to another node and return whether it succeeded.
|
|
55
|
+
/// @param node Node ID of the callee.
|
|
56
|
+
/// @param value Native value to forward in wei.
|
|
57
|
+
/// @param data Encoded calldata to send.
|
|
58
|
+
/// @return success True if the low-level call succeeded.
|
|
59
|
+
function tryTrustedCall(uint node, uint128 value, bytes memory data) internal returns (bool success) {
|
|
60
|
+
return tryRawCall(ensureTrusted(node), value, data);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// @notice Make a trusted low-level call to another node and revert when it fails.
|
|
64
|
+
/// @param node Node ID of the callee.
|
|
65
|
+
/// @param value Native value to forward in wei.
|
|
66
|
+
/// @param data Encoded calldata to send.
|
|
67
|
+
/// @return out Return data from the successful call.
|
|
68
|
+
function trustedCall(uint node, uint128 value, bytes memory data) internal returns (bytes memory out) {
|
|
69
|
+
return rawCall(ensureTrusted(node), value, data);
|
|
70
|
+
}
|
|
71
|
+
|
|
75
72
|
/// @notice Make a trusted low-level read-only query to another node and revert when it fails.
|
|
76
73
|
/// @param node Node ID of the callee.
|
|
77
74
|
/// @param data Encoded calldata to send.
|
|
@@ -89,7 +86,7 @@ abstract contract CommandCalls is NodeCalls {
|
|
|
89
86
|
/// @param value Native value to forward in wei.
|
|
90
87
|
/// @param account Command account identifier.
|
|
91
88
|
/// @param state Current command state block stream.
|
|
92
|
-
/// @param
|
|
89
|
+
/// @param input Command input block stream.
|
|
93
90
|
/// @return nextState Decoded command output state block stream.
|
|
94
91
|
/// @return transactions Decoded command transaction block stream.
|
|
95
92
|
function callCommand(
|
|
@@ -97,10 +94,10 @@ abstract contract CommandCalls is NodeCalls {
|
|
|
97
94
|
uint128 value,
|
|
98
95
|
bytes32 account,
|
|
99
96
|
bytes memory state,
|
|
100
|
-
bytes calldata
|
|
97
|
+
bytes calldata input
|
|
101
98
|
) internal returns (bytes memory nextState, bytes memory transactions) {
|
|
102
99
|
bytes4 selector = Nodes.commandSelector(command);
|
|
103
|
-
bytes memory data = abi.encodeWithSelector(selector,
|
|
100
|
+
bytes memory data = abi.encodeWithSelector(selector, account, state, input);
|
|
104
101
|
return abi.decode(trustedCall(command, value, data), (bytes, bytes));
|
|
105
102
|
}
|
|
106
103
|
}
|