@rootzero/contracts 0.9.1 → 0.9.2
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/Commands.sol +16 -16
- package/Events.sol +3 -3
- package/Utils.sol +1 -1
- package/commands/Base.sol +0 -19
- package/commands/Pipe.sol +15 -10
- package/commands/Provision.sol +2 -2
- package/commands/{control → admin}/AllowAssets.sol +4 -4
- package/commands/{control → admin}/Allowance.sol +8 -8
- package/commands/{control → admin}/Authorize.sol +4 -4
- package/commands/{control → admin}/DenyAssets.sol +4 -4
- package/commands/{control → admin}/Destroy.sol +4 -4
- package/commands/{control → admin}/Execute.sol +4 -4
- package/commands/{control → admin}/Init.sol +4 -4
- package/commands/{control → admin}/Unauthorize.sol +4 -4
- package/core/Access.sol +2 -2
- package/core/Calls.sol +16 -2
- package/core/Host.sol +4 -4
- package/core/Types.sol +1 -1
- package/events/{Control.sol → Admin.sol} +5 -5
- package/events/Peer.sol +24 -0
- package/events/{RootZero.sol → Piped.sol} +3 -3
- package/package.json +1 -1
- package/peer/AllowAssets.sol +38 -0
- package/peer/Allowance.sol +35 -0
- package/peer/AssetPull.sol +43 -0
- package/peer/Base.sol +40 -0
- package/peer/DenyAssets.sol +38 -0
- package/peer/Settle.sol +32 -0
- package/queries/Assets.sol +1 -2
- package/queries/Balances.sol +1 -2
- package/queries/Positions.sol +1 -2
- package/utils/Accounts.sol +8 -0
- package/utils/Ids.sol +35 -30
- package/utils/Layout.sol +3 -3
- package/utils/Utils.sol +2 -2
- package/events/Remote.sol +0 -24
- package/remote/AllowAssets.sol +0 -39
- package/remote/Allowance.sol +0 -36
- package/remote/AssetPull.sol +0 -44
- package/remote/Base.sol +0 -40
- package/remote/DenyAssets.sol +0 -39
- package/remote/Settle.sol +0 -33
package/Commands.sol
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
// Aggregator: re-exports command,
|
|
4
|
+
// Aggregator: re-exports command, admin, and peer abstractions.
|
|
5
5
|
// Import this file to inherit from the full rootzero command surface without managing individual paths.
|
|
6
6
|
|
|
7
|
-
import { CommandBase, CommandContext, CommandPayable
|
|
7
|
+
import { CommandBase, CommandContext, CommandPayable } from "./commands/Base.sol";
|
|
8
8
|
import { Keys } from "./blocks/Keys.sol";
|
|
9
9
|
import { Burn, BurnHook } from "./commands/Burn.sol";
|
|
10
10
|
import { CreditAccount, CreditAccountHook } from "./commands/Credit.sol";
|
|
@@ -14,20 +14,20 @@ import { PipePayable, PipePayableHook } from "./commands/Pipe.sol";
|
|
|
14
14
|
import { Provision, ProvisionHook, ProvisionPayable, ProvisionPayableHook } from "./commands/Provision.sol";
|
|
15
15
|
import { Transfer, TransferHook } from "./commands/Transfer.sol";
|
|
16
16
|
import { Withdraw, WithdrawHook } from "./commands/Withdraw.sol";
|
|
17
|
-
import { AllowAssets, AllowAssetsHook } from "./commands/
|
|
18
|
-
import { Destroy, DestroyHook } from "./commands/
|
|
19
|
-
import { ExecutePayable } from "./commands/
|
|
20
|
-
import { Authorize } from "./commands/
|
|
21
|
-
import { DenyAssets, DenyAssetsHook } from "./commands/
|
|
22
|
-
import { Init, InitHook } from "./commands/
|
|
23
|
-
import { Allowance, AllowanceHook } from "./commands/
|
|
24
|
-
import { Unauthorize } from "./commands/
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
17
|
+
import { AllowAssets, AllowAssetsHook } from "./commands/admin/AllowAssets.sol";
|
|
18
|
+
import { Destroy, DestroyHook } from "./commands/admin/Destroy.sol";
|
|
19
|
+
import { ExecutePayable } from "./commands/admin/Execute.sol";
|
|
20
|
+
import { Authorize } from "./commands/admin/Authorize.sol";
|
|
21
|
+
import { DenyAssets, DenyAssetsHook } from "./commands/admin/DenyAssets.sol";
|
|
22
|
+
import { Init, InitHook } from "./commands/admin/Init.sol";
|
|
23
|
+
import { Allowance, AllowanceHook } from "./commands/admin/Allowance.sol";
|
|
24
|
+
import { Unauthorize } from "./commands/admin/Unauthorize.sol";
|
|
25
|
+
import { PeerBase, encodePeerCall } from "./peer/Base.sol";
|
|
26
|
+
import { PeerAllowance } from "./peer/Allowance.sol";
|
|
27
|
+
import { PeerAssetPull, AssetPullHook } from "./peer/AssetPull.sol";
|
|
28
|
+
import { PeerAllowAssets } from "./peer/AllowAssets.sol";
|
|
29
|
+
import { PeerDenyAssets } from "./peer/DenyAssets.sol";
|
|
30
|
+
import { PeerSettle } from "./peer/Settle.sol";
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
package/Events.sol
CHANGED
|
@@ -5,7 +5,7 @@ pragma solidity ^0.8.33;
|
|
|
5
5
|
// Import this file to get access to every event emitter in one import.
|
|
6
6
|
|
|
7
7
|
import { AccessEvent } from "./events/Access.sol";
|
|
8
|
-
import {
|
|
8
|
+
import { AdminEvent } from "./events/Admin.sol";
|
|
9
9
|
import { AssetEvent } from "./events/Asset.sol";
|
|
10
10
|
import { BalanceEvent } from "./events/Balance.sol";
|
|
11
11
|
import { CollateralEvent } from "./events/Collateral.sol";
|
|
@@ -17,9 +17,9 @@ import { EventEmitter } from "./events/Emitter.sol";
|
|
|
17
17
|
import { GovernedEvent } from "./events/Governed.sol";
|
|
18
18
|
import { HostAnnouncedEvent } from "./events/Host.sol";
|
|
19
19
|
import { ListingEvent } from "./events/Listing.sol";
|
|
20
|
-
import {
|
|
20
|
+
import { PeerEvent } from "./events/Peer.sol";
|
|
21
21
|
import { QueryEvent } from "./events/Query.sol";
|
|
22
|
-
import {
|
|
22
|
+
import { PipedEvent } from "./events/Piped.sol";
|
|
23
23
|
import { SwapEvent } from "./events/Swap.sol";
|
|
24
24
|
import { WithdrawalEvent } from "./events/Withdraw.sol";
|
|
25
25
|
|
package/Utils.sol
CHANGED
|
@@ -11,7 +11,7 @@ import { ECDSA } from "./utils/ECDSA.sol";
|
|
|
11
11
|
import { Ids, Selectors } from "./utils/Ids.sol";
|
|
12
12
|
import { Layout } from "./utils/Layout.sol";
|
|
13
13
|
import { Schemas } from "./blocks/Schema.sol";
|
|
14
|
-
import { addrOr, applyBps, beforeBps, bytes32ToInt, bytes32ToString, divisible, hash32, intToBytes32, isFamily,
|
|
14
|
+
import { addrOr, applyBps, beforeBps, bytes32ToInt, bytes32ToString, divisible, hash32, intToBytes32, isFamily, isLocalChain, isLocalFamily, matchesBase, MAX_BPS, max8, max16, max24, max32, max40, max64, max96, max128, max160, NotDivisible, retryTicket, toLocalBase, toLocalFamily, toUnspecifiedBase, ValueOverflow } from "./utils/Utils.sol";
|
|
15
15
|
import { Budget, Values } from "./utils/Value.sol";
|
|
16
16
|
|
|
17
17
|
|
package/commands/Base.sol
CHANGED
|
@@ -18,25 +18,6 @@ struct CommandContext {
|
|
|
18
18
|
bytes request;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/// @notice ABI-encode a command call from a command ID and execution context.
|
|
22
|
-
/// @dev Derives the function selector from `cid` via `Ids.commandSelector(cid)`.
|
|
23
|
-
/// Reverts if `cid` is not a valid command ID.
|
|
24
|
-
/// @param cid Command node ID embedding the target selector.
|
|
25
|
-
/// @param account Caller account identifier for the command context.
|
|
26
|
-
/// @param state Current state block stream passed to the command.
|
|
27
|
-
/// @param request Input block stream for the command invocation.
|
|
28
|
-
/// @return ABI-encoded calldata for the command entry point.
|
|
29
|
-
function encodeCommandCall(
|
|
30
|
-
uint cid,
|
|
31
|
-
bytes32 account,
|
|
32
|
-
bytes memory state,
|
|
33
|
-
bytes calldata request
|
|
34
|
-
) pure returns (bytes memory) {
|
|
35
|
-
bytes4 selector = Ids.commandSelector(cid);
|
|
36
|
-
CommandContext memory ctx = CommandContext(account, state, request);
|
|
37
|
-
return abi.encodeWithSelector(selector, ctx);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
21
|
/// @title CommandBase
|
|
41
22
|
/// @notice Abstract base for all rootzero command contracts.
|
|
42
23
|
/// Provides access control modifiers, event emission, and the `commandId`
|
package/commands/Pipe.sol
CHANGED
|
@@ -9,8 +9,17 @@ import {Budget, Values} from "../utils/Value.sol";
|
|
|
9
9
|
using Cursors for Cur;
|
|
10
10
|
|
|
11
11
|
abstract contract PipePayableHook {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/// @notice Override to dispatch one piped command step.
|
|
13
|
+
/// Called once per STEP block. The returned bytes become the state passed to
|
|
14
|
+
/// the next step.
|
|
15
|
+
/// @param id Command node ID to invoke or handle.
|
|
16
|
+
/// @param account Account identifier for the piped command context.
|
|
17
|
+
/// @param state Current threaded state block stream.
|
|
18
|
+
/// @param request Step request block stream.
|
|
19
|
+
/// @param value Native value assigned to this step.
|
|
20
|
+
/// @return Updated state block stream for the next step.
|
|
21
|
+
function dispatchCommand(
|
|
22
|
+
uint id,
|
|
14
23
|
bytes32 account,
|
|
15
24
|
bytes memory state,
|
|
16
25
|
bytes calldata request,
|
|
@@ -20,7 +29,7 @@ abstract contract PipePayableHook {
|
|
|
20
29
|
|
|
21
30
|
/// @title PipePayable
|
|
22
31
|
/// @notice Command that sequences multiple sub-command STEP invocations in a single transaction.
|
|
23
|
-
/// Each STEP block carries a
|
|
32
|
+
/// Each STEP block carries a command node, native value to forward, and an embedded request.
|
|
24
33
|
/// State threads through the steps: each step's output becomes the next step's state.
|
|
25
34
|
/// Admin accounts are not permitted to use `pipePayable`.
|
|
26
35
|
abstract contract PipePayable is CommandPayable, PipePayableHook {
|
|
@@ -43,7 +52,7 @@ abstract contract PipePayable is CommandPayable, PipePayableHook {
|
|
|
43
52
|
while (input.i < input.bound) {
|
|
44
53
|
(uint target, uint value, bytes calldata request) = input.unpackStep();
|
|
45
54
|
uint spend = Values.use(budget, value);
|
|
46
|
-
state =
|
|
55
|
+
state = dispatchCommand(target, account, state, request, spend);
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
settleValue(account, budget);
|
|
@@ -52,11 +61,7 @@ abstract contract PipePayable is CommandPayable, PipePayableHook {
|
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
/// @notice Execute the pipePayable command.
|
|
55
|
-
function pipePayable(
|
|
56
|
-
|
|
57
|
-
) external payable onlyCommand(c.account) returns (bytes memory) {
|
|
58
|
-
if (Accounts.isAdmin(c.account)) revert Accounts.InvalidAccount();
|
|
59
|
-
Budget memory budget = Values.fromMsg();
|
|
60
|
-
return pipe(c.account, c.state, c.request, budget);
|
|
64
|
+
function pipePayable(CommandContext calldata c) external payable onlyCommand(c.account) returns (bytes memory) {
|
|
65
|
+
return pipe(Accounts.ensureNotAdmin(c.account), c.state, c.request, Values.fromMsg());
|
|
61
66
|
}
|
|
62
67
|
}
|
package/commands/Provision.sol
CHANGED
|
@@ -29,7 +29,7 @@ abstract contract ProvisionPayableHook {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/// @title Provision
|
|
32
|
-
/// @notice Command that provisions assets to
|
|
32
|
+
/// @notice Command that provisions assets to peer hosts from ALLOCATION request blocks.
|
|
33
33
|
/// Each request block supplies the target host plus an asset amount; the output is a CUSTODY state stream.
|
|
34
34
|
abstract contract Provision is CommandBase, ProvisionHook {
|
|
35
35
|
string private constant NAME = "provision";
|
|
@@ -55,7 +55,7 @@ abstract contract Provision is CommandBase, ProvisionHook {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/// @title ProvisionPayable
|
|
58
|
-
/// @notice Command that provisions assets to
|
|
58
|
+
/// @notice Command that provisions assets to peer hosts from ALLOCATION request blocks.
|
|
59
59
|
/// Each request block supplies the target host plus an asset amount; the output is a CUSTODY state stream.
|
|
60
60
|
/// The hook receives a mutable native-value budget drawn from `msg.value`.
|
|
61
61
|
abstract contract ProvisionPayable is CommandPayable, ProvisionPayableHook {
|
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { CommandBase, CommandContext, Keys } from "../Base.sol";
|
|
5
5
|
import { Cursors, Cur, Schemas } from "../../Cursors.sol";
|
|
6
|
-
import {
|
|
6
|
+
import { AdminEvent } from "../../events/Admin.sol";
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
9
9
|
abstract contract AllowAssetsHook {
|
|
@@ -13,15 +13,15 @@ abstract contract AllowAssetsHook {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/// @title AllowAssets
|
|
16
|
-
/// @notice
|
|
16
|
+
/// @notice Admin command that permits a list of (asset, meta) pairs via a virtual hook.
|
|
17
17
|
/// Each ASSET block in the request calls `allowAsset`. Only callable by the admin account.
|
|
18
|
-
abstract contract AllowAssets is CommandBase,
|
|
18
|
+
abstract contract AllowAssets is CommandBase, AdminEvent, AllowAssetsHook {
|
|
19
19
|
string private constant NAME = "allowAssets";
|
|
20
20
|
|
|
21
21
|
uint internal immutable allowAssetsId = commandId(NAME);
|
|
22
22
|
|
|
23
23
|
constructor() {
|
|
24
|
-
emit
|
|
24
|
+
emit Admin(host, allowAssetsId, NAME, Schemas.Asset, Keys.Empty, Keys.Empty, false);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function allowAssets(
|
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {CommandBase, CommandContext, Keys} from "../Base.sol";
|
|
5
5
|
import {Cursors, Cur, Schemas} from "../../Cursors.sol";
|
|
6
|
-
import {
|
|
6
|
+
import {AdminEvent} from "../../events/Admin.sol";
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
9
9
|
abstract contract AllowanceHook {
|
|
@@ -11,30 +11,30 @@ abstract contract AllowanceHook {
|
|
|
11
11
|
/// Called once per ALLOWANCE block in the request. Implementations decide
|
|
12
12
|
/// how the allowance is represented, e.g. ERC-20 approval, an internal cap,
|
|
13
13
|
/// or another host-specific authorization record.
|
|
14
|
-
/// @param
|
|
14
|
+
/// @param peer Host node receiving the allowed cap.
|
|
15
15
|
/// @param asset Asset identifier.
|
|
16
16
|
/// @param meta Asset metadata slot.
|
|
17
17
|
/// @param amount Allowed cap amount.
|
|
18
|
-
function allowance(uint
|
|
18
|
+
function allowance(uint peer, bytes32 asset, bytes32 meta, uint amount) internal virtual;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/// @title Allowance
|
|
22
|
-
/// @notice
|
|
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
|
-
abstract contract Allowance is CommandBase,
|
|
24
|
+
abstract contract Allowance is CommandBase, AdminEvent, AllowanceHook {
|
|
25
25
|
string private constant NAME = "allowance";
|
|
26
26
|
uint internal immutable allowanceId = commandId(NAME);
|
|
27
27
|
|
|
28
28
|
constructor() {
|
|
29
|
-
emit
|
|
29
|
+
emit Admin(host, allowanceId, NAME, Schemas.Allowance, Keys.Empty, Keys.Empty, false);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function allowance(CommandContext calldata c) external onlyAdmin(c.account) returns (bytes memory) {
|
|
33
33
|
(Cur memory request, , ) = cursor(c.request, 1);
|
|
34
34
|
|
|
35
35
|
while (request.i < request.bound) {
|
|
36
|
-
(uint
|
|
37
|
-
allowance(
|
|
36
|
+
(uint peer, bytes32 asset, bytes32 meta, uint amount) = request.unpackAllowance();
|
|
37
|
+
allowance(peer, asset, meta, amount);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
request.complete();
|
|
@@ -3,20 +3,20 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { CommandBase, CommandContext, Keys } from "../Base.sol";
|
|
5
5
|
import { Cursors, Cur, Schemas } from "../../Cursors.sol";
|
|
6
|
-
import {
|
|
6
|
+
import { AdminEvent } from "../../events/Admin.sol";
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
9
9
|
/// @title Authorize
|
|
10
|
-
/// @notice
|
|
10
|
+
/// @notice Admin command that grants authorization to a list of node IDs.
|
|
11
11
|
/// Each NODE block in the request is authorized on the host.
|
|
12
12
|
/// Only callable by the admin account.
|
|
13
|
-
abstract contract Authorize is CommandBase,
|
|
13
|
+
abstract contract Authorize is CommandBase, AdminEvent {
|
|
14
14
|
string private constant NAME = "authorize";
|
|
15
15
|
|
|
16
16
|
uint internal immutable authorizeId = commandId(NAME);
|
|
17
17
|
|
|
18
18
|
constructor() {
|
|
19
|
-
emit
|
|
19
|
+
emit Admin(host, authorizeId, NAME, Schemas.Node, Keys.Empty, Keys.Empty, false);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function authorize(
|
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { CommandBase, CommandContext, Keys } from "../Base.sol";
|
|
5
5
|
import { Cursors, Cur, Schemas } from "../../Cursors.sol";
|
|
6
|
-
import {
|
|
6
|
+
import { AdminEvent } from "../../events/Admin.sol";
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
9
9
|
abstract contract DenyAssetsHook {
|
|
@@ -13,15 +13,15 @@ abstract contract DenyAssetsHook {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/// @title DenyAssets
|
|
16
|
-
/// @notice
|
|
16
|
+
/// @notice Admin command that blocks a list of (asset, meta) pairs via a virtual hook.
|
|
17
17
|
/// Each ASSET block in the request calls `denyAsset`. Only callable by the admin account.
|
|
18
|
-
abstract contract DenyAssets is CommandBase,
|
|
18
|
+
abstract contract DenyAssets is CommandBase, AdminEvent, DenyAssetsHook {
|
|
19
19
|
string private constant NAME = "denyAssets";
|
|
20
20
|
|
|
21
21
|
uint internal immutable denyAssetsId = commandId(NAME);
|
|
22
22
|
|
|
23
23
|
constructor() {
|
|
24
|
-
emit
|
|
24
|
+
emit Admin(host, denyAssetsId, NAME, Schemas.Asset, Keys.Empty, Keys.Empty, false);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function denyAssets(
|
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { CommandBase, CommandContext, Keys } from "../Base.sol";
|
|
5
5
|
import { Cursors, Cur } from "../../Cursors.sol";
|
|
6
|
-
import {
|
|
6
|
+
import { AdminEvent } from "../../events/Admin.sol";
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
@@ -14,15 +14,15 @@ abstract contract DestroyHook {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/// @title Destroy
|
|
17
|
-
/// @notice
|
|
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
|
-
abstract contract Destroy is CommandBase,
|
|
19
|
+
abstract contract Destroy is CommandBase, AdminEvent, DestroyHook {
|
|
20
20
|
string private constant NAME = "destroy";
|
|
21
21
|
|
|
22
22
|
uint internal immutable destroyId = commandId(NAME);
|
|
23
23
|
|
|
24
24
|
constructor(string memory input) {
|
|
25
|
-
emit
|
|
25
|
+
emit Admin(host, destroyId, NAME, input, Keys.Empty, Keys.Empty, false);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function destroy(
|
|
@@ -3,23 +3,23 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {CommandContext, CommandPayable, Keys} from "../Base.sol";
|
|
5
5
|
import {Cursors, Cur, Schemas} from "../../Cursors.sol";
|
|
6
|
-
import {
|
|
6
|
+
import {AdminEvent} from "../../events/Admin.sol";
|
|
7
7
|
import {Budget, Values} from "../../utils/Value.sol";
|
|
8
8
|
import {Ids} from "../../utils/Ids.sol";
|
|
9
9
|
|
|
10
10
|
using Cursors for Cur;
|
|
11
11
|
|
|
12
12
|
/// @title ExecutePayable
|
|
13
|
-
/// @notice
|
|
13
|
+
/// @notice Admin command that forwards raw calldata to one or more target nodes.
|
|
14
14
|
/// Each CALL block specifies a target node ID, native value, and raw calldata payload.
|
|
15
15
|
/// Only callable by the admin account.
|
|
16
|
-
abstract contract ExecutePayable is CommandPayable,
|
|
16
|
+
abstract contract ExecutePayable is CommandPayable, AdminEvent {
|
|
17
17
|
string private constant NAME = "executePayable";
|
|
18
18
|
|
|
19
19
|
uint internal immutable executePayableId = commandId(NAME);
|
|
20
20
|
|
|
21
21
|
constructor() {
|
|
22
|
-
emit
|
|
22
|
+
emit Admin(host, executePayableId, NAME, Schemas.Call, Keys.Empty, Keys.Empty, true);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
function executePayable(CommandContext calldata c) external payable onlyAdmin(c.account) returns (bytes memory) {
|
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { CommandBase, CommandContext, Keys } from "../Base.sol";
|
|
5
5
|
import { Cursors, Cur } from "../../Cursors.sol";
|
|
6
|
-
import {
|
|
6
|
+
import { AdminEvent } from "../../events/Admin.sol";
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
@@ -14,15 +14,15 @@ abstract contract InitHook {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/// @title Init
|
|
17
|
-
/// @notice
|
|
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
|
-
abstract contract Init is CommandBase,
|
|
19
|
+
abstract contract Init is CommandBase, AdminEvent, InitHook {
|
|
20
20
|
string private constant NAME = "init";
|
|
21
21
|
|
|
22
22
|
uint internal immutable initId = commandId(NAME);
|
|
23
23
|
|
|
24
24
|
constructor(string memory input) {
|
|
25
|
-
emit
|
|
25
|
+
emit Admin(host, initId, NAME, input, Keys.Empty, Keys.Empty, false);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function init(
|
|
@@ -3,20 +3,20 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { CommandBase, CommandContext, Keys } from "../Base.sol";
|
|
5
5
|
import { Cursors, Cur, Schemas } from "../../Cursors.sol";
|
|
6
|
-
import {
|
|
6
|
+
import { AdminEvent } from "../../events/Admin.sol";
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
9
9
|
/// @title Unauthorize
|
|
10
|
-
/// @notice
|
|
10
|
+
/// @notice Admin command that revokes authorization from a list of node IDs.
|
|
11
11
|
/// Each NODE block in the request is deauthorized on the host.
|
|
12
12
|
/// Only callable by the admin account.
|
|
13
|
-
abstract contract Unauthorize is CommandBase,
|
|
13
|
+
abstract contract Unauthorize is CommandBase, AdminEvent {
|
|
14
14
|
string private constant NAME = "unauthorize";
|
|
15
15
|
|
|
16
16
|
uint internal immutable unauthorizeId = commandId(NAME);
|
|
17
17
|
|
|
18
18
|
constructor() {
|
|
19
|
-
emit
|
|
19
|
+
emit Admin(host, unauthorizeId, NAME, Schemas.Node, Keys.Empty, Keys.Empty, false);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function unauthorize(
|
package/core/Access.sol
CHANGED
|
@@ -12,7 +12,7 @@ import {addrOr} from "../utils/Utils.sol";
|
|
|
12
12
|
/// Tracks an immutable trusted commander, the host's own node ID, and a
|
|
13
13
|
/// mapping of externally trusted node IDs. Inbound trust is host-based:
|
|
14
14
|
/// trusted hosts, the commander, and this contract itself may interact
|
|
15
|
-
/// with the host through the guarded command and
|
|
15
|
+
/// with the host through the guarded command and peer entrypoints.
|
|
16
16
|
abstract contract AccessControl is RootZeroContext, AccessEvent {
|
|
17
17
|
/// @dev Trusted commander address. All calls from this address are implicitly trusted.
|
|
18
18
|
/// Defaults to `address(this)` when no external commander is provided.
|
|
@@ -69,7 +69,7 @@ abstract contract AccessControl is RootZeroContext, AccessEvent {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/// @notice Assert that `caller` is trusted and return it.
|
|
72
|
-
/// Used by command and
|
|
72
|
+
/// Used by command and peer modifiers to gate execution to authorized senders.
|
|
73
73
|
/// @param caller Address to validate.
|
|
74
74
|
/// @return The same `caller` value if trusted.
|
|
75
75
|
function enforceCaller(address caller) internal view returns (address) {
|
package/core/Calls.sol
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {AccessControl} from "./Access.sol";
|
|
5
|
+
import {CommandContext} from "../commands/Base.sol";
|
|
5
6
|
import {Ids} from "../utils/Ids.sol";
|
|
6
7
|
|
|
7
8
|
/// @dev Emitted when a trusted inter-node call fails.
|
|
@@ -53,7 +54,8 @@ abstract contract NodeCalls is AccessControl {
|
|
|
53
54
|
/// @param data Encoded calldata to send.
|
|
54
55
|
/// @return out Return data from the successful call.
|
|
55
56
|
function callTo(uint node, uint value, bytes memory data) internal returns (bytes memory out) {
|
|
56
|
-
|
|
57
|
+
ensureTrusted(node);
|
|
58
|
+
address addr = Ids.nodeAddr(node);
|
|
57
59
|
return callAddr(addr, value, data);
|
|
58
60
|
}
|
|
59
61
|
|
|
@@ -64,7 +66,19 @@ abstract contract NodeCalls is AccessControl {
|
|
|
64
66
|
/// @param data Encoded calldata to send.
|
|
65
67
|
/// @return out Return data from the successful query.
|
|
66
68
|
function queryTo(uint node, bytes memory data) internal view returns (bytes memory out) {
|
|
67
|
-
|
|
69
|
+
ensureTrusted(node);
|
|
70
|
+
address addr = Ids.nodeAddr(node);
|
|
68
71
|
return queryAddr(addr, data);
|
|
69
72
|
}
|
|
73
|
+
|
|
74
|
+
/// @notice Encode and call a trusted command node.
|
|
75
|
+
/// @param ctx Command execution context.
|
|
76
|
+
/// @param cid Command node ID embedding the target selector.
|
|
77
|
+
/// @param value Native value to forward in wei.
|
|
78
|
+
/// @return Decoded command output block stream.
|
|
79
|
+
function callCommand(CommandContext memory ctx, uint cid, uint value) internal returns (bytes memory) {
|
|
80
|
+
bytes4 selector = Ids.commandSelector(cid);
|
|
81
|
+
bytes memory data = abi.encodeWithSelector(selector, ctx);
|
|
82
|
+
return abi.decode(callTo(cid, value, data), (bytes));
|
|
83
|
+
}
|
|
70
84
|
}
|
package/core/Host.sol
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {AccessControl} from "./Access.sol";
|
|
5
|
-
import {Authorize} from "../commands/
|
|
6
|
-
import {Unauthorize} from "../commands/
|
|
7
|
-
import {ExecutePayable} from "../commands/
|
|
5
|
+
import {Authorize} from "../commands/admin/Authorize.sol";
|
|
6
|
+
import {Unauthorize} from "../commands/admin/Unauthorize.sol";
|
|
7
|
+
import {ExecutePayable} from "../commands/admin/Execute.sol";
|
|
8
8
|
import {HostAnnouncedEvent} from "../events/Host.sol";
|
|
9
9
|
import {IHostDiscovery} from "../interfaces/IHostDiscovery.sol";
|
|
10
10
|
import {Ids} from "../utils/Ids.sol";
|
|
@@ -25,7 +25,7 @@ abstract contract HostDiscovery is HostAnnouncedEvent, IHostDiscovery {
|
|
|
25
25
|
|
|
26
26
|
/// @title Host
|
|
27
27
|
/// @notice Abstract base contract for rootzero host implementations.
|
|
28
|
-
/// Inherits
|
|
28
|
+
/// Inherits admin command support (authorize, unauthorize, executePayable) and
|
|
29
29
|
/// optionally announces itself to a discovery contract at deployment.
|
|
30
30
|
/// Accepts native ETH payments via the `receive` function.
|
|
31
31
|
abstract contract Host is Authorize, Unauthorize, ExecutePayable {
|
package/core/Types.sol
CHANGED
|
@@ -71,7 +71,7 @@ struct HostAccountAmount {
|
|
|
71
71
|
uint amount;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
/// @notice Transfer payload used by transaction blocks and
|
|
74
|
+
/// @notice Transfer payload used by transaction blocks and peer settlement.
|
|
75
75
|
struct Tx {
|
|
76
76
|
/// @dev Sender account identifier.
|
|
77
77
|
bytes32 from;
|
|
@@ -4,18 +4,18 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
import { EventEmitter } from "./Emitter.sol";
|
|
5
5
|
|
|
6
6
|
string constant ABI =
|
|
7
|
-
"event
|
|
7
|
+
"event Admin(uint indexed host, uint id, string name, string request, bytes4 state, bytes4 output, bool acceptsValue)";
|
|
8
8
|
|
|
9
|
-
/// @notice Emitted once per
|
|
10
|
-
abstract contract
|
|
11
|
-
/// @param host Host node ID that owns this
|
|
9
|
+
/// @notice Emitted once per admin command during host deployment to publish its request schema and state keys.
|
|
10
|
+
abstract contract AdminEvent is EventEmitter {
|
|
11
|
+
/// @param host Host node ID that owns this admin command.
|
|
12
12
|
/// @param id Command node ID.
|
|
13
13
|
/// @param name Human-readable command name.
|
|
14
14
|
/// @param request Schema DSL string describing the request shape.
|
|
15
15
|
/// @param state Block key expected for input state, or `Keys.Empty`.
|
|
16
16
|
/// @param output Block key produced for output state, or `Keys.Empty`.
|
|
17
17
|
/// @param acceptsValue Whether the command entrypoint accepts nonzero `msg.value`.
|
|
18
|
-
event
|
|
18
|
+
event Admin(
|
|
19
19
|
uint indexed host,
|
|
20
20
|
uint id,
|
|
21
21
|
string name,
|
package/events/Peer.sol
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import { EventEmitter } from "./Emitter.sol";
|
|
5
|
+
|
|
6
|
+
string constant ABI =
|
|
7
|
+
"event Peer(uint indexed host, uint id, string name, string request, bool acceptsValue)";
|
|
8
|
+
|
|
9
|
+
/// @notice Emitted once per peer during host deployment to publish its request schema.
|
|
10
|
+
abstract contract PeerEvent is EventEmitter {
|
|
11
|
+
/// @param host Host node ID that owns this peer.
|
|
12
|
+
/// @param id Peer node ID.
|
|
13
|
+
/// @param name Human-readable peer name.
|
|
14
|
+
/// @param request Schema DSL string describing the peer request shape.
|
|
15
|
+
/// @param acceptsValue Whether the peer entrypoint accepts nonzero `msg.value`.
|
|
16
|
+
event Peer(uint indexed host, uint id, string name, string request, bool acceptsValue);
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
emit EventAbi(ABI);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
@@ -3,14 +3,14 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI = "event
|
|
6
|
+
string constant ABI = "event Piped(bytes32 indexed account, uint deadline, uint value)";
|
|
7
7
|
|
|
8
8
|
/// @notice Emitted for root-level protocol actions (e.g. governance or protocol-wide operations).
|
|
9
|
-
abstract contract
|
|
9
|
+
abstract contract PipedEvent is EventEmitter {
|
|
10
10
|
/// @param account Account identifier associated with the action.
|
|
11
11
|
/// @param deadline Expiry timestamp of the action.
|
|
12
12
|
/// @param value Native value associated with the action.
|
|
13
|
-
event
|
|
13
|
+
event Piped(bytes32 indexed account, uint deadline, uint value);
|
|
14
14
|
|
|
15
15
|
constructor() {
|
|
16
16
|
emit EventAbi(ABI);
|
package/package.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import { PeerBase } from "./Base.sol";
|
|
5
|
+
import { AllowAssetsHook } from "../commands/admin/AllowAssets.sol";
|
|
6
|
+
import { Cursors, Cur, Schemas } from "../Cursors.sol";
|
|
7
|
+
|
|
8
|
+
using Cursors for Cur;
|
|
9
|
+
|
|
10
|
+
/// @title PeerAllowAssets
|
|
11
|
+
/// @notice Peer that permits a list of (asset, meta) pairs on behalf of a peer host.
|
|
12
|
+
/// Each ASSET block in the request calls `allowAsset`. Restricted to trusted peers.
|
|
13
|
+
abstract contract PeerAllowAssets is PeerBase, AllowAssetsHook {
|
|
14
|
+
string private constant NAME = "peerAllowAssets";
|
|
15
|
+
uint internal immutable peerAllowAssetsId = peerId(NAME);
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
emit Peer(host, peerAllowAssetsId, NAME, Schemas.Asset, false);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// @notice Execute the allow-assets peer call.
|
|
22
|
+
function peerAllowAssets(bytes calldata request) external onlyPeer returns (bytes memory) {
|
|
23
|
+
(Cur memory assets, , ) = cursor(request, 1);
|
|
24
|
+
|
|
25
|
+
while (assets.i < assets.bound) {
|
|
26
|
+
(bytes32 asset, bytes32 meta) = assets.unpackAsset();
|
|
27
|
+
allowAsset(asset, meta);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
assets.complete();
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|