@rootzero/contracts 1.0.1 → 1.2.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 +24 -0
- package/Endpoints.sol +2 -1
- package/Events.sol +1 -0
- package/blocks/Cursors.sol +176 -116
- package/blocks/Keys.sol +11 -7
- package/blocks/Schema.sol +11 -5
- package/blocks/Writers.sol +25 -9
- package/commands/Base.sol +10 -9
- package/commands/Burn.sol +3 -4
- package/commands/Credit.sol +3 -4
- package/commands/Debit.sol +3 -4
- package/commands/Deposit.sol +6 -8
- package/commands/Payout.sol +3 -4
- package/commands/Provision.sol +6 -8
- package/commands/Relay.sol +24 -32
- package/commands/Withdraw.sol +3 -4
- package/commands/admin/AllowAssets.sol +3 -4
- package/commands/admin/Allowance.sol +3 -3
- package/commands/admin/Appoint.sol +3 -4
- package/commands/admin/Authorize.sol +3 -4
- package/commands/admin/DenyAssets.sol +3 -4
- package/commands/admin/Destroy.sol +3 -4
- package/commands/admin/Dismiss.sol +3 -4
- package/commands/admin/Execute.sol +6 -7
- package/commands/admin/Init.sol +3 -4
- package/commands/admin/Label.sol +35 -0
- package/commands/admin/Unauthorize.sol +3 -4
- package/core/Calls.sol +3 -3
- package/core/Host.sol +7 -11
- package/core/Payable.sol +12 -10
- package/core/Pipeline.sol +4 -4
- package/docs/Schema.md +13 -6
- package/events/Admin.sol +2 -4
- package/events/Chain.sol +2 -3
- package/events/Command.sol +2 -4
- package/events/Guard.sol +2 -3
- package/events/Introduction.sol +2 -4
- package/events/Labeled.sol +18 -0
- package/events/Peer.sol +2 -11
- package/events/Query.sol +2 -3
- package/guards/Base.sol +7 -6
- package/guards/Revoke.sol +3 -4
- package/package.json +2 -1
- package/peer/AllowAssets.sol +3 -3
- package/peer/Allowance.sol +3 -3
- package/peer/BalancePull.sol +3 -3
- package/peer/Base.sol +7 -6
- package/peer/DenyAssets.sol +3 -3
- package/peer/Dispatch.sol +13 -23
- package/peer/Pipe.sol +7 -7
- package/peer/Settle.sol +3 -3
- package/queries/Assets.sol +3 -3
- package/queries/Balances.sol +3 -3
- package/queries/Base.sol +9 -8
- package/queries/Positions.sol +3 -4
- package/utils/Value.sol +5 -4
package/commands/Base.sol
CHANGED
|
@@ -3,8 +3,9 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {NodeCalls} from "../core/Calls.sol";
|
|
5
5
|
import {CommandEvent} from "../events/Command.sol";
|
|
6
|
+
import {LabeledEvent} from "../events/Labeled.sol";
|
|
6
7
|
import {Keys} from "../blocks/Keys.sol";
|
|
7
|
-
import {Ids
|
|
8
|
+
import {Ids} from "../utils/Ids.sol";
|
|
8
9
|
|
|
9
10
|
/// @notice Execution context passed to every command invocation.
|
|
10
11
|
struct CommandContext {
|
|
@@ -19,8 +20,8 @@ struct CommandContext {
|
|
|
19
20
|
/// @title CommandBase
|
|
20
21
|
/// @notice Abstract base for all rootzero command contracts.
|
|
21
22
|
/// Provides access control modifiers, event emission, and the `commandId`
|
|
22
|
-
/// helper used to derive stable identifiers for
|
|
23
|
-
abstract contract CommandBase is NodeCalls, CommandEvent {
|
|
23
|
+
/// helper used to derive stable identifiers for command selectors.
|
|
24
|
+
abstract contract CommandBase is NodeCalls, CommandEvent, LabeledEvent {
|
|
24
25
|
/// @dev Thrown when `onlyActive` finds that `deadline` has already passed.
|
|
25
26
|
error Expired();
|
|
26
27
|
|
|
@@ -44,12 +45,12 @@ abstract contract CommandBase is NodeCalls, CommandEvent {
|
|
|
44
45
|
_;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
/// @notice Derive the deterministic node ID for a
|
|
48
|
-
/// The ID encodes the ABI selector
|
|
49
|
-
///
|
|
50
|
-
/// @param
|
|
48
|
+
/// @notice Derive the deterministic node ID for a command selector on this contract.
|
|
49
|
+
/// The ID encodes the ABI selector and `address(this)`, making it unique
|
|
50
|
+
/// per (function selector, contract address) pair.
|
|
51
|
+
/// @param selector Command entrypoint selector.
|
|
51
52
|
/// @return Command node ID.
|
|
52
|
-
function commandId(
|
|
53
|
-
return Ids.toCommand(
|
|
53
|
+
function commandId(bytes4 selector) internal view returns (uint) {
|
|
54
|
+
return Ids.toCommand(selector, address(this));
|
|
54
55
|
}
|
|
55
56
|
}
|
package/commands/Burn.sol
CHANGED
|
@@ -20,12 +20,11 @@ abstract contract BurnHook {
|
|
|
20
20
|
/// @notice Command that irreversibly destroys each BALANCE state block via a virtual hook.
|
|
21
21
|
/// Produces no output state.
|
|
22
22
|
abstract contract Burn is CommandBase, BurnHook {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
uint internal immutable burnId = commandId(NAME);
|
|
23
|
+
uint internal immutable burnId = commandId(this.burn.selector);
|
|
26
24
|
|
|
27
25
|
constructor() {
|
|
28
|
-
emit Command(host, burnId,
|
|
26
|
+
emit Command(host, burnId, "0:1:0", "", Keys.Balance, Keys.Empty, false, false);
|
|
27
|
+
emit Labeled(burnId, bytes32(0), "burn");
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
/// @notice Burn each BALANCE block from the command state.
|
package/commands/Credit.sol
CHANGED
|
@@ -20,12 +20,11 @@ abstract contract CreditAccountHook {
|
|
|
20
20
|
/// @notice Command that delivers BALANCE state blocks to an account via a virtual hook.
|
|
21
21
|
/// Use for internally recording credits that have already been settled externally.
|
|
22
22
|
abstract contract CreditAccount is CommandBase, CreditAccountHook {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
uint internal immutable creditAccountId = commandId(NAME);
|
|
23
|
+
uint internal immutable creditAccountId = commandId(this.creditAccount.selector);
|
|
26
24
|
|
|
27
25
|
constructor() {
|
|
28
|
-
emit Command(host, creditAccountId,
|
|
26
|
+
emit Command(host, creditAccountId, "0:1:0", "", Keys.Balance, Keys.Empty, false, false);
|
|
27
|
+
emit Labeled(creditAccountId, bytes32(0), "creditAccount");
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
/// @notice Credit each BALANCE block from the command state to the command account.
|
package/commands/Debit.sol
CHANGED
|
@@ -22,12 +22,11 @@ abstract contract DebitAccountHook {
|
|
|
22
22
|
/// Use for internally recording debits. The virtual `debitAccount` hook is called once per
|
|
23
23
|
/// AMOUNT block; the default batch implementation handles the full request loop.
|
|
24
24
|
abstract contract DebitAccount is CommandBase, DebitAccountHook {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
uint internal immutable debitAccountId = commandId(NAME);
|
|
25
|
+
uint internal immutable debitAccountId = commandId(this.debitAccount.selector);
|
|
28
26
|
|
|
29
27
|
constructor() {
|
|
30
|
-
emit Command(host, debitAccountId,
|
|
28
|
+
emit Command(host, debitAccountId, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false, false);
|
|
29
|
+
emit Labeled(debitAccountId, bytes32(0), "debitAccount");
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
/// @notice Override to customize request parsing or batching for debits.
|
package/commands/Deposit.sol
CHANGED
|
@@ -37,12 +37,11 @@ abstract contract DepositPayableHook {
|
|
|
37
37
|
/// Use `deposit` for assets arriving from outside the protocol (e.g. ERC-20 transfers, ETH).
|
|
38
38
|
/// For internal balance deductions, use `debitAccount` instead.
|
|
39
39
|
abstract contract Deposit is CommandBase, DepositHook {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
uint internal immutable depositId = commandId(NAME);
|
|
40
|
+
uint internal immutable depositId = commandId(this.deposit.selector);
|
|
43
41
|
|
|
44
42
|
constructor() {
|
|
45
|
-
emit Command(host, depositId,
|
|
43
|
+
emit Command(host, depositId, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false, false);
|
|
44
|
+
emit Labeled(depositId, bytes32(0), "deposit");
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
/// @notice Deposit AMOUNT request blocks into the command account and output matching BALANCE blocks.
|
|
@@ -69,12 +68,11 @@ abstract contract Deposit is CommandBase, DepositHook {
|
|
|
69
68
|
/// @notice Command that receives externally sourced assets and records them as BALANCE state.
|
|
70
69
|
/// Use `depositPayable` when the hook needs tracked access to `msg.value` via a mutable budget.
|
|
71
70
|
abstract contract DepositPayable is CommandBase, Payable, DepositPayableHook {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
uint internal immutable depositPayableId = commandId(NAME);
|
|
71
|
+
uint internal immutable depositPayableId = commandId(this.depositPayable.selector);
|
|
75
72
|
|
|
76
73
|
constructor() {
|
|
77
|
-
emit Command(host, depositPayableId,
|
|
74
|
+
emit Command(host, depositPayableId, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false, true);
|
|
75
|
+
emit Labeled(depositPayableId, bytes32(0), "depositPayable");
|
|
78
76
|
}
|
|
79
77
|
|
|
80
78
|
/// @notice Deposit AMOUNT request blocks with access to a mutable native-value budget.
|
package/commands/Payout.sol
CHANGED
|
@@ -22,12 +22,11 @@ abstract contract PayoutHook {
|
|
|
22
22
|
/// @notice Command that sinks BALANCE state blocks to matching ACCOUNT request blocks.
|
|
23
23
|
/// Each BALANCE block is paired with one ACCOUNT block at the same position.
|
|
24
24
|
abstract contract Payout is CommandBase, PayoutHook {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
uint internal immutable payoutId = commandId(NAME);
|
|
25
|
+
uint internal immutable payoutId = commandId(this.payout.selector);
|
|
28
26
|
|
|
29
27
|
constructor() {
|
|
30
|
-
emit Command(host, payoutId,
|
|
28
|
+
emit Command(host, payoutId, "1:1:0", Schemas.Account, Keys.Balance, Keys.Empty, false, false);
|
|
29
|
+
emit Labeled(payoutId, bytes32(0), "payout");
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
/// @notice Pay out BALANCE state blocks to matching ACCOUNT request blocks.
|
package/commands/Provision.sol
CHANGED
|
@@ -33,12 +33,11 @@ abstract contract ProvisionPayableHook {
|
|
|
33
33
|
/// @notice Command that provisions assets to peer hosts from ALLOCATION request blocks.
|
|
34
34
|
/// Each request block supplies the target host plus an asset amount; the output is a CUSTODY state stream.
|
|
35
35
|
abstract contract Provision is CommandBase, ProvisionHook {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
uint internal immutable provisionId = commandId(NAME);
|
|
36
|
+
uint internal immutable provisionId = commandId(this.provision.selector);
|
|
39
37
|
|
|
40
38
|
constructor() {
|
|
41
|
-
emit Command(host, provisionId,
|
|
39
|
+
emit Command(host, provisionId, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, false, false);
|
|
40
|
+
emit Labeled(provisionId, bytes32(0), "provision");
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
/// @notice Provision ALLOCATION request blocks and output matching CUSTODY state blocks.
|
|
@@ -64,12 +63,11 @@ abstract contract Provision is CommandBase, ProvisionHook {
|
|
|
64
63
|
/// Each request block supplies the target host plus an asset amount; the output is a CUSTODY state stream.
|
|
65
64
|
/// The hook receives a mutable native-value budget drawn from `msg.value`.
|
|
66
65
|
abstract contract ProvisionPayable is CommandBase, Payable, ProvisionPayableHook {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
uint internal immutable provisionPayableId = commandId(NAME);
|
|
66
|
+
uint internal immutable provisionPayableId = commandId(this.provisionPayable.selector);
|
|
70
67
|
|
|
71
68
|
constructor() {
|
|
72
|
-
emit Command(host, provisionPayableId,
|
|
69
|
+
emit Command(host, provisionPayableId, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, false, true);
|
|
70
|
+
emit Labeled(provisionPayableId, bytes32(0), "provisionPayable");
|
|
73
71
|
}
|
|
74
72
|
|
|
75
73
|
/// @notice Provision ALLOCATION request blocks with access to a mutable native-value budget.
|
package/commands/Relay.sol
CHANGED
|
@@ -8,24 +8,15 @@ import {Budget} from "../utils/Value.sol";
|
|
|
8
8
|
|
|
9
9
|
using Cursors for Cur;
|
|
10
10
|
|
|
11
|
-
abstract contract
|
|
12
|
-
/// @notice Override to
|
|
13
|
-
/// @param chain Destination chain node ID.
|
|
14
|
-
/// @param resources Chain-adapter-specific destination resources. EVM adapters
|
|
15
|
-
/// may interpret this as packed execution gas and destination value.
|
|
16
|
-
/// @param
|
|
17
|
-
/// @param
|
|
18
|
-
///
|
|
19
|
-
|
|
20
|
-
/// fees and destination resource funding.
|
|
21
|
-
function relay(
|
|
22
|
-
uint chain,
|
|
23
|
-
uint resources,
|
|
24
|
-
bytes32 account,
|
|
25
|
-
bytes calldata state,
|
|
26
|
-
bytes calldata steps,
|
|
27
|
-
Budget memory budget
|
|
28
|
-
) internal virtual;
|
|
11
|
+
abstract contract DispatchPayableHook {
|
|
12
|
+
/// @notice Override to dispatch an encoded payload to `chain`.
|
|
13
|
+
/// @param chain Destination chain node ID.
|
|
14
|
+
/// @param resources Chain-adapter-specific destination resources. EVM adapters
|
|
15
|
+
/// may interpret this as packed execution gas and destination value.
|
|
16
|
+
/// @param payload Encoded payload ready for the transport layer.
|
|
17
|
+
/// @param budget Source-chain native-value budget available for transport
|
|
18
|
+
/// fees and destination resource funding.
|
|
19
|
+
function dispatch(uint chain, uint resources, bytes memory payload, Budget memory budget) internal virtual;
|
|
29
20
|
}
|
|
30
21
|
|
|
31
22
|
/// @title RelayPayable
|
|
@@ -33,25 +24,26 @@ abstract contract RelayPayableHook {
|
|
|
33
24
|
/// Reverts unless the request contains exactly one RELAY block, preventing
|
|
34
25
|
/// the same state from being duplicated across multiple relays.
|
|
35
26
|
/// Produces no output state.
|
|
36
|
-
abstract contract RelayPayable is CommandBase, Payable,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
uint internal immutable relayPayableId = commandId(NAME);
|
|
27
|
+
abstract contract RelayPayable is CommandBase, Payable, DispatchPayableHook {
|
|
28
|
+
uint internal immutable relayPayableId = commandId(this.relayPayable.selector);
|
|
40
29
|
|
|
41
30
|
constructor() {
|
|
42
|
-
emit Command(host, relayPayableId,
|
|
31
|
+
emit Command(host, relayPayableId, "1:0:0", Schemas.Relay, Keys.Any, Keys.Empty, false, true);
|
|
32
|
+
emit Labeled(relayPayableId, bytes32(0), "relayPayable");
|
|
43
33
|
}
|
|
44
34
|
|
|
45
35
|
/// @notice Relay one RELAY request block with the command account and current state.
|
|
46
36
|
/// @param c Command context; `c.request` must contain exactly one RELAY block.
|
|
47
37
|
/// @return output Empty output state.
|
|
48
38
|
function relayPayable(CommandContext calldata c) external payable onlyCommand returns (bytes memory output) {
|
|
49
|
-
(Cur memory request, ) = Cursors.init(c.request, 0, 1, 1);
|
|
50
|
-
Budget memory budget = valueBudget();
|
|
51
|
-
|
|
52
|
-
(uint chain, uint resources, bytes
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
39
|
+
(Cur memory request, ) = Cursors.init(c.request, 0, 1, 1);
|
|
40
|
+
Budget memory budget = valueBudget();
|
|
41
|
+
|
|
42
|
+
(uint chain, uint resources, bytes memory pipe) = request.relayToPipe(c.account, c.state);
|
|
43
|
+
dispatch(chain, resources, pipe, budget);
|
|
44
|
+
|
|
45
|
+
settleValue(c.account, budget);
|
|
46
|
+
request.complete();
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
}
|
package/commands/Withdraw.sol
CHANGED
|
@@ -20,12 +20,11 @@ abstract contract WithdrawHook {
|
|
|
20
20
|
/// Use `withdraw` for assets being sent outside the protocol (e.g. ERC-20 transfers, ETH sends).
|
|
21
21
|
/// For internal balance credits, use `creditAccount` instead.
|
|
22
22
|
abstract contract Withdraw is CommandBase, WithdrawHook {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
uint internal immutable withdrawId = commandId(NAME);
|
|
23
|
+
uint internal immutable withdrawId = commandId(this.withdraw.selector);
|
|
26
24
|
|
|
27
25
|
constructor() {
|
|
28
|
-
emit Command(host, withdrawId,
|
|
26
|
+
emit Command(host, withdrawId, "0:1:0", "", Keys.Balance, Keys.Empty, false, false);
|
|
27
|
+
emit Labeled(withdrawId, bytes32(0), "withdraw");
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
/// @notice Withdraw each BALANCE block from the command state to the command account.
|
|
@@ -18,12 +18,11 @@ abstract contract AllowAssetsHook {
|
|
|
18
18
|
/// @notice Admin command that permits a list of (asset, meta) pairs via a virtual hook.
|
|
19
19
|
/// Each ASSET block in the request calls `allowAsset`. Only callable by the admin account.
|
|
20
20
|
abstract contract AllowAssets is CommandBase, AdminEvent, AllowAssetsHook {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
uint internal immutable allowAssetsId = commandId(NAME);
|
|
21
|
+
uint internal immutable allowAssetsId = commandId(this.allowAssets.selector);
|
|
24
22
|
|
|
25
23
|
constructor() {
|
|
26
|
-
emit Admin(host, allowAssetsId,
|
|
24
|
+
emit Admin(host, allowAssetsId, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false, false);
|
|
25
|
+
emit Labeled(allowAssetsId, bytes32(0), "allowAssets");
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
/// @notice Allow each ASSET block in the admin request.
|
|
@@ -22,11 +22,11 @@ abstract contract AllowanceHook {
|
|
|
22
22
|
/// @notice Admin command that applies cross-host allowance entries via a virtual hook.
|
|
23
23
|
/// Each ALLOWANCE block grants or updates a host-scoped asset cap. Only callable by the admin account.
|
|
24
24
|
abstract contract Allowance is CommandBase, AdminEvent, AllowanceHook {
|
|
25
|
-
|
|
26
|
-
uint internal immutable allowanceId = commandId(NAME);
|
|
25
|
+
uint internal immutable allowanceId = commandId(this.allowance.selector);
|
|
27
26
|
|
|
28
27
|
constructor() {
|
|
29
|
-
emit Admin(host, allowanceId,
|
|
28
|
+
emit Admin(host, allowanceId, "1:0:0", Schemas.Allowance, Keys.Empty, Keys.Empty, false, false);
|
|
29
|
+
emit Labeled(allowanceId, bytes32(0), "allowance");
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/// @notice Apply each ALLOWANCE block in the admin request.
|
|
@@ -11,12 +11,11 @@ using Cursors for Cur;
|
|
|
11
11
|
/// Each ACCOUNT block in the request is enabled as a guardian on the host.
|
|
12
12
|
/// Only callable by the admin account.
|
|
13
13
|
abstract contract Appoint is CommandBase, AdminEvent {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
uint internal immutable appointId = commandId(NAME);
|
|
14
|
+
uint internal immutable appointId = commandId(this.appoint.selector);
|
|
17
15
|
|
|
18
16
|
constructor() {
|
|
19
|
-
emit Admin(host, appointId,
|
|
17
|
+
emit Admin(host, appointId, "1:0:0", Schemas.Account, Keys.Empty, Keys.Empty, false, false);
|
|
18
|
+
emit Labeled(appointId, bytes32(0), "appoint");
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/// @notice Appoint each ACCOUNT block in the admin request as a guardian.
|
|
@@ -11,12 +11,11 @@ using Cursors for Cur;
|
|
|
11
11
|
/// Each NODE block in the request is authorized on the host.
|
|
12
12
|
/// Only callable by the admin account.
|
|
13
13
|
abstract contract Authorize is CommandBase, AdminEvent {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
uint internal immutable authorizeId = commandId(NAME);
|
|
14
|
+
uint internal immutable authorizeId = commandId(this.authorize.selector);
|
|
17
15
|
|
|
18
16
|
constructor() {
|
|
19
|
-
emit Admin(host, authorizeId,
|
|
17
|
+
emit Admin(host, authorizeId, "1:0:0", Schemas.Node, Keys.Empty, Keys.Empty, false, false);
|
|
18
|
+
emit Labeled(authorizeId, bytes32(0), "authorize");
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/// @notice Authorize each NODE block in the admin request.
|
|
@@ -18,12 +18,11 @@ abstract contract DenyAssetsHook {
|
|
|
18
18
|
/// @notice Admin command that blocks a list of (asset, meta) pairs via a virtual hook.
|
|
19
19
|
/// Each ASSET block in the request calls `denyAsset`. Only callable by the admin account.
|
|
20
20
|
abstract contract DenyAssets is CommandBase, AdminEvent, DenyAssetsHook {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
uint internal immutable denyAssetsId = commandId(NAME);
|
|
21
|
+
uint internal immutable denyAssetsId = commandId(this.denyAssets.selector);
|
|
24
22
|
|
|
25
23
|
constructor() {
|
|
26
|
-
emit Admin(host, denyAssetsId,
|
|
24
|
+
emit Admin(host, denyAssetsId, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false, false);
|
|
25
|
+
emit Labeled(denyAssetsId, bytes32(0), "denyAssets");
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
/// @notice Deny each ASSET block in the admin request.
|
|
@@ -17,12 +17,11 @@ abstract contract DestroyHook {
|
|
|
17
17
|
/// @notice Admin command that runs host teardown logic via a virtual hook.
|
|
18
18
|
/// The full request is passed to `destroy` as a cursor. Only callable by the admin account.
|
|
19
19
|
abstract contract Destroy is CommandBase, AdminEvent, DestroyHook {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
uint internal immutable destroyId = commandId(NAME);
|
|
20
|
+
uint internal immutable destroyId = commandId(this.destroy.selector);
|
|
23
21
|
|
|
24
22
|
constructor(string memory input) {
|
|
25
|
-
emit Admin(host, destroyId,
|
|
23
|
+
emit Admin(host, destroyId, "1:0:0", input, Keys.Empty, Keys.Empty, false, false);
|
|
24
|
+
emit Labeled(destroyId, bytes32(0), "destroy");
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
/// @notice Run host teardown logic over the full admin request.
|
|
@@ -11,12 +11,11 @@ using Cursors for Cur;
|
|
|
11
11
|
/// Each ACCOUNT block in the request is disabled as a guardian on the host.
|
|
12
12
|
/// Only callable by the admin account.
|
|
13
13
|
abstract contract Dismiss is CommandBase, AdminEvent {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
uint internal immutable dismissId = commandId(NAME);
|
|
14
|
+
uint internal immutable dismissId = commandId(this.dismiss.selector);
|
|
17
15
|
|
|
18
16
|
constructor() {
|
|
19
|
-
emit Admin(host, dismissId,
|
|
17
|
+
emit Admin(host, dismissId, "1:0:0", Schemas.Account, Keys.Empty, Keys.Empty, false, false);
|
|
18
|
+
emit Labeled(dismissId, bytes32(0), "dismiss");
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/// @notice Dismiss each ACCOUNT block in the admin request from guardian status.
|
|
@@ -12,16 +12,15 @@ using Cursors for Cur;
|
|
|
12
12
|
|
|
13
13
|
/// @title ExecutePayable
|
|
14
14
|
/// @notice Admin command that forwards raw calldata to one or more target nodes.
|
|
15
|
-
/// Each CALL block specifies a target node ID,
|
|
15
|
+
/// Each CALL block specifies a target node ID, chain resources, and raw calldata payload.
|
|
16
16
|
/// Only callable by the admin account.
|
|
17
17
|
/// Unspent top-level `msg.value` remains on this host.
|
|
18
18
|
abstract contract ExecutePayable is CommandBase, Payable, AdminEvent {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
uint internal immutable executePayableId = commandId(NAME);
|
|
19
|
+
uint internal immutable executePayableId = commandId(this.executePayable.selector);
|
|
22
20
|
|
|
23
21
|
constructor() {
|
|
24
|
-
emit Admin(host, executePayableId,
|
|
22
|
+
emit Admin(host, executePayableId, "1:0:0", Schemas.Call, Keys.Empty, Keys.Empty, false, true);
|
|
23
|
+
emit Labeled(executePayableId, bytes32(0), "executePayable");
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
/// @notice Execute each CALL block in the admin request.
|
|
@@ -32,9 +31,9 @@ abstract contract ExecutePayable is CommandBase, Payable, AdminEvent {
|
|
|
32
31
|
Budget memory budget = valueBudget();
|
|
33
32
|
|
|
34
33
|
while (request.i < request.len) {
|
|
35
|
-
(uint target, uint
|
|
34
|
+
(uint target, uint resources, bytes calldata data) = request.unpackCall();
|
|
36
35
|
address addr = Ids.nodeAddr(target);
|
|
37
|
-
callAddr(addr, useValue(budget,
|
|
36
|
+
callAddr(addr, useValue(budget, resources), data);
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
request.complete();
|
package/commands/admin/Init.sol
CHANGED
|
@@ -17,12 +17,11 @@ abstract contract InitHook {
|
|
|
17
17
|
/// @notice Admin command that runs host initialization logic via a virtual hook.
|
|
18
18
|
/// The full request is passed to `init` as a cursor. Only callable by the admin account.
|
|
19
19
|
abstract contract Init is CommandBase, AdminEvent, InitHook {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
uint internal immutable initId = commandId(NAME);
|
|
20
|
+
uint internal immutable initId = commandId(this.init.selector);
|
|
23
21
|
|
|
24
22
|
constructor(string memory input) {
|
|
25
|
-
emit Admin(host, initId,
|
|
23
|
+
emit Admin(host, initId, "1:0:0", input, Keys.Empty, Keys.Empty, false, false);
|
|
24
|
+
emit Labeled(initId, bytes32(0), "init");
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
/// @notice Run host initialization logic over the full admin request.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {CommandBase, CommandContext, Keys} from "../Base.sol";
|
|
5
|
+
import {Cursors, Cur, Schemas} from "../../Cursors.sol";
|
|
6
|
+
import {AdminEvent} from "../../events/Admin.sol";
|
|
7
|
+
using Cursors for Cur;
|
|
8
|
+
|
|
9
|
+
/// @title Label
|
|
10
|
+
/// @notice Admin command that publishes namespaced labels for node IDs.
|
|
11
|
+
/// Each LABEL block in the request emits one `Labeled` event. Only callable by
|
|
12
|
+
/// the admin account.
|
|
13
|
+
abstract contract Label is CommandBase, AdminEvent {
|
|
14
|
+
uint internal immutable labelId = commandId(this.label.selector);
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
emit Admin(host, labelId, "1:0:0", Schemas.Label, Keys.Empty, Keys.Empty, false, false);
|
|
18
|
+
emit Labeled(labelId, bytes32(0), "label");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// @notice Publish each LABEL block in the admin request.
|
|
22
|
+
/// @param c Admin command context; `c.request` must contain LABEL blocks.
|
|
23
|
+
/// @return Empty output state.
|
|
24
|
+
function label(CommandContext calldata c) external onlyAdmin(c.account) returns (bytes memory) {
|
|
25
|
+
(Cur memory request, , ) = Cursors.init(c.request, 0, 1);
|
|
26
|
+
|
|
27
|
+
while (request.i < request.len) {
|
|
28
|
+
(uint id, bytes32 namespace, string memory name) = request.unpackLabel();
|
|
29
|
+
emit Labeled(id, namespace, name);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
request.complete();
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -11,12 +11,11 @@ using Cursors for Cur;
|
|
|
11
11
|
/// Each NODE block in the request is deauthorized on the host.
|
|
12
12
|
/// Only callable by the admin account.
|
|
13
13
|
abstract contract Unauthorize is CommandBase, AdminEvent {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
uint internal immutable unauthorizeId = commandId(NAME);
|
|
14
|
+
uint internal immutable unauthorizeId = commandId(this.unauthorize.selector);
|
|
17
15
|
|
|
18
16
|
constructor() {
|
|
19
|
-
emit Admin(host, unauthorizeId,
|
|
17
|
+
emit Admin(host, unauthorizeId, "1:0:0", Schemas.Node, Keys.Empty, Keys.Empty, false, false);
|
|
18
|
+
emit Labeled(unauthorizeId, bytes32(0), "unauthorize");
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/// @notice Unauthorize each NODE block in the admin request.
|
package/core/Calls.sol
CHANGED
|
@@ -28,7 +28,7 @@ abstract contract NodeCalls is AccessControl {
|
|
|
28
28
|
/// @param value Native value to forward in wei.
|
|
29
29
|
/// @param data Encoded calldata to send.
|
|
30
30
|
/// @return out Return data from the successful call.
|
|
31
|
-
function callAddr(address addr,
|
|
31
|
+
function callAddr(address addr, uint128 value, bytes memory data) internal returns (bytes memory out) {
|
|
32
32
|
bool success;
|
|
33
33
|
(success, out) = payable(addr).call{value: value}(data);
|
|
34
34
|
if (!success) revert FailedCall(addr, bytes4(data), out);
|
|
@@ -53,7 +53,7 @@ abstract contract NodeCalls is AccessControl {
|
|
|
53
53
|
/// @param value Native value to forward in wei.
|
|
54
54
|
/// @param data Encoded calldata to send.
|
|
55
55
|
/// @return out Return data from the successful call.
|
|
56
|
-
function callTo(uint node,
|
|
56
|
+
function callTo(uint node, uint128 value, bytes memory data) internal returns (bytes memory out) {
|
|
57
57
|
ensureTrusted(node);
|
|
58
58
|
address addr = Ids.nodeAddr(node);
|
|
59
59
|
return callAddr(addr, value, data);
|
|
@@ -76,7 +76,7 @@ abstract contract NodeCalls is AccessControl {
|
|
|
76
76
|
/// @param value Native value to forward in wei.
|
|
77
77
|
/// @param ctx Command execution context.
|
|
78
78
|
/// @return Decoded command output block stream.
|
|
79
|
-
function callCommand(uint id,
|
|
79
|
+
function callCommand(uint id, uint128 value, CommandContext memory ctx) internal returns (bytes memory) {
|
|
80
80
|
bytes4 selector = Ids.commandSelector(id);
|
|
81
81
|
bytes memory data = abi.encodeWithSelector(selector, ctx);
|
|
82
82
|
return abi.decode(callTo(id, value, data), (bytes));
|
package/core/Host.sol
CHANGED
|
@@ -7,6 +7,7 @@ import {Authorize} from "../commands/admin/Authorize.sol";
|
|
|
7
7
|
import {Dismiss} from "../commands/admin/Dismiss.sol";
|
|
8
8
|
import {Unauthorize} from "../commands/admin/Unauthorize.sol";
|
|
9
9
|
import {ExecutePayable} from "../commands/admin/Execute.sol";
|
|
10
|
+
import {Label} from "../commands/admin/Label.sol";
|
|
10
11
|
import {Revoke} from "../guards/Revoke.sol";
|
|
11
12
|
import {IntroductionEvent} from "../events/Introduction.sol";
|
|
12
13
|
import {Ids} from "../utils/Ids.sol";
|
|
@@ -17,9 +18,7 @@ interface IHostIntroduction {
|
|
|
17
18
|
/// @notice Record a host introduction claim.
|
|
18
19
|
/// @param peer Host node ID being introduced.
|
|
19
20
|
/// @param blocknum Block number at which the introduction was made.
|
|
20
|
-
|
|
21
|
-
/// @param namespace Human-readable namespace or label for the host.
|
|
22
|
-
function introduce(uint peer, uint blocknum, uint16 version, string calldata namespace) external;
|
|
21
|
+
function introduce(uint peer, uint blocknum) external;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
/// @title Host
|
|
@@ -34,6 +33,7 @@ abstract contract Host is
|
|
|
34
33
|
Revoke,
|
|
35
34
|
Appoint,
|
|
36
35
|
Dismiss,
|
|
36
|
+
Label,
|
|
37
37
|
ExecutePayable,
|
|
38
38
|
IntroductionEvent,
|
|
39
39
|
IHostIntroduction
|
|
@@ -41,21 +41,17 @@ abstract contract Host is
|
|
|
41
41
|
/// @param cmdr Commander address; passed to `AccessControl`.
|
|
42
42
|
/// If `cmdr` is a deployed contract, the host calls `introduce`
|
|
43
43
|
/// on it during construction.
|
|
44
|
-
|
|
45
|
-
/// @param namespace Human-readable namespace string for the host.
|
|
46
|
-
constructor(address cmdr, uint16 version, string memory namespace) AccessControl(cmdr) {
|
|
44
|
+
constructor(address cmdr) AccessControl(cmdr) {
|
|
47
45
|
if (cmdr == address(0) || cmdr == address(this) || cmdr.code.length == 0) return;
|
|
48
|
-
IHostIntroduction(cmdr).introduce(host, block.number
|
|
46
|
+
IHostIntroduction(cmdr).introduce(host, block.number);
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
/// @notice Record a host introduction claim.
|
|
52
50
|
/// @dev Validates that `peer` matches `msg.sender`; it does not authorize or trust the introduced host.
|
|
53
51
|
/// @param peer Host node ID being introduced.
|
|
54
52
|
/// @param blocknum Block number at which the host was deployed.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
function introduce(uint peer, uint blocknum, uint16 version, string calldata namespace) external {
|
|
58
|
-
emit Introduction(Ids.matchHost(peer, msg.sender), blocknum, version, namespace);
|
|
53
|
+
function introduce(uint peer, uint blocknum) external {
|
|
54
|
+
emit Introduction(Ids.matchHost(peer, msg.sender), blocknum);
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
/// @notice Accept native ETH transfers (e.g. from command value flows).
|
package/core/Payable.sol
CHANGED
|
@@ -18,20 +18,22 @@ abstract contract Payable {
|
|
|
18
18
|
return Budget({remaining: msg.value});
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/// @notice Deduct
|
|
21
|
+
/// @notice Deduct the EVM value lane from a packed resource word and return it.
|
|
22
|
+
/// @dev EVM resources use the low 128 bits as native value/endowment.
|
|
22
23
|
/// @param budget Mutable budget to deduct from.
|
|
23
|
-
/// @param
|
|
24
|
-
/// @return
|
|
25
|
-
function useValue(Budget memory budget, uint
|
|
26
|
-
return Values.use(budget,
|
|
24
|
+
/// @param resources Packed chain resources.
|
|
25
|
+
/// @return value Native value to forward in wei.
|
|
26
|
+
function useValue(Budget memory budget, uint resources) internal pure returns (uint128 value) {
|
|
27
|
+
return Values.use(budget, uint128(resources));
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
/// @notice Deduct
|
|
30
|
+
/// @notice Deduct the EVM value lane from a packed resource word as a new sub-budget.
|
|
31
|
+
/// @dev EVM resources use the low 128 bits as native value/endowment.
|
|
30
32
|
/// @param budget Mutable parent budget to deduct from.
|
|
31
|
-
/// @param
|
|
32
|
-
/// @return A new budget with
|
|
33
|
-
function allocateValue(Budget memory budget, uint
|
|
34
|
-
return Values.allocate(budget,
|
|
33
|
+
/// @param resources Packed chain resources.
|
|
34
|
+
/// @return A new budget with the EVM value lane remaining.
|
|
35
|
+
function allocateValue(Budget memory budget, uint resources) internal pure returns (Budget memory) {
|
|
36
|
+
return Values.allocate(budget, uint128(resources));
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
/// @notice Drains the budget and settles any remaining native value.
|