@rootzero/contracts 0.9.5 → 0.9.7
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 → Endpoints.sol} +24 -9
- package/Events.sol +8 -7
- package/README.md +2 -3
- package/blocks/Cursors.sol +10 -14
- package/blocks/Keys.sol +3 -3
- package/blocks/Schema.sol +4 -4
- package/blocks/Writers.sol +17 -20
- package/commands/Base.sol +1 -9
- package/commands/admin/Appoint.sol +35 -0
- package/commands/admin/Authorize.sol +1 -1
- package/commands/admin/Dismiss.sol +35 -0
- package/commands/admin/Unauthorize.sol +1 -1
- package/core/Access.sol +35 -27
- package/core/Host.sol +6 -3
- package/docs/Schema.md +2 -2
- package/events/Admin.sol +3 -3
- package/events/Asset.sol +8 -7
- package/events/Balance.sol +2 -2
- package/events/Collateral.sol +2 -2
- package/events/Command.sol +3 -3
- package/events/Contexts.sol +12 -0
- package/events/Debt.sol +2 -2
- package/events/Guard.sol +19 -0
- package/events/Guardian.sol +18 -0
- package/events/Introduction.sol +2 -2
- package/events/Node.sol +18 -0
- package/events/Peer.sol +13 -8
- package/events/Position.sol +4 -4
- package/events/Query.sol +2 -2
- package/events/Received.sol +20 -0
- package/events/Rooted.sol +2 -2
- package/events/Spent.sol +20 -0
- package/guards/Base.sol +35 -0
- package/guards/Revoke.sol +31 -0
- package/package.json +1 -1
- package/peer/Pipe.sol +8 -8
- package/queries/Assets.sol +16 -16
- package/utils/Accounts.sol +49 -2
- package/utils/Assets.sol +2 -0
- package/utils/Ids.sol +57 -18
- package/utils/Layout.sol +6 -2
- package/Queries.sol +0 -10
- package/events/Access.sol +0 -21
- package/events/Deposit.sol +0 -22
- package/events/Listing.sol +0 -22
- package/events/Swap.sol +0 -20
- package/events/Withdraw.sol +0 -22
package/events/Balance.sol
CHANGED
|
@@ -3,10 +3,10 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI = "event Balance(bytes32 indexed account, bytes32 asset, bytes32 meta, uint balance, int change, uint access)";
|
|
7
|
-
|
|
8
6
|
/// @notice Emitted when an account balance changes.
|
|
9
7
|
abstract contract BalanceEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Balance(bytes32 indexed account, bytes32 asset, bytes32 meta, uint balance, int change, uint access)";
|
|
9
|
+
|
|
10
10
|
/// @param account Account identifier whose balance changed.
|
|
11
11
|
/// @param asset Asset identifier.
|
|
12
12
|
/// @param meta Asset metadata slot.
|
package/events/Collateral.sol
CHANGED
|
@@ -3,11 +3,11 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI = "event Collateral(bytes32 indexed account, bytes32 asset, bytes32 meta, uint amount, uint access)";
|
|
7
|
-
|
|
8
6
|
/// @notice Emitted when an account's collateral position changes.
|
|
9
7
|
/// Off-chain indexers should query the access command to retrieve the precise collateral details.
|
|
10
8
|
abstract contract CollateralEvent is EventEmitter {
|
|
9
|
+
string private constant ABI = "event Collateral(bytes32 indexed account, bytes32 asset, bytes32 meta, uint amount, uint access)";
|
|
10
|
+
|
|
11
11
|
/// @param account Account identifier that holds the collateral.
|
|
12
12
|
/// @param asset Asset identifier of the collateral.
|
|
13
13
|
/// @param meta Asset metadata slot.
|
package/events/Command.sol
CHANGED
|
@@ -3,11 +3,11 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI =
|
|
7
|
-
"event Command(uint indexed host, uint id, string name, bytes32 shape, string request, bytes4 state, bytes4 output, bool acceptsValue)";
|
|
8
|
-
|
|
9
6
|
/// @notice Emitted once per command during host deployment to publish its request schema and state keys.
|
|
10
7
|
abstract contract CommandEvent is EventEmitter {
|
|
8
|
+
string private constant ABI =
|
|
9
|
+
"event Command(uint indexed host, uint id, string name, bytes32 shape, string request, bytes4 state, bytes4 output, bool acceptsValue)";
|
|
10
|
+
|
|
11
11
|
/// @param host Host node ID that owns this command.
|
|
12
12
|
/// @param id Command node ID.
|
|
13
13
|
/// @param name Human-readable command name.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
/// @notice Standard context codes for generic asset activity events.
|
|
5
|
+
library Contexts {
|
|
6
|
+
uint constant Deposit = 1;
|
|
7
|
+
uint constant Withdraw = 2;
|
|
8
|
+
uint constant Fee = 3;
|
|
9
|
+
uint constant Mint = 4;
|
|
10
|
+
uint constant Burn = 5;
|
|
11
|
+
uint constant Swap = 6;
|
|
12
|
+
}
|
package/events/Debt.sol
CHANGED
|
@@ -3,11 +3,11 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI = "event Debt(bytes32 indexed account, bytes32 asset, bytes32 meta, uint amount, uint mode, uint access)";
|
|
7
|
-
|
|
8
6
|
/// @notice Emitted when an account's debt position changes.
|
|
9
7
|
/// Off-chain indexers should query the access command to retrieve precise debt details.
|
|
10
8
|
abstract contract DebtEvent is EventEmitter {
|
|
9
|
+
string private constant ABI = "event Debt(bytes32 indexed account, bytes32 asset, bytes32 meta, uint amount, uint mode, uint access)";
|
|
10
|
+
|
|
11
11
|
/// @param account Account identifier that holds the debt.
|
|
12
12
|
/// @param asset Asset identifier of the debt.
|
|
13
13
|
/// @param meta Asset metadata slot.
|
package/events/Guard.sol
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
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 once per guard action during host deployment to publish its request schema.
|
|
7
|
+
abstract contract GuardEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Guard(uint indexed host, uint id, string name, string request)";
|
|
9
|
+
|
|
10
|
+
/// @param host Host node ID that owns this guard action.
|
|
11
|
+
/// @param id Guard action node ID.
|
|
12
|
+
/// @param name Human-readable guard action name.
|
|
13
|
+
/// @param request Schema DSL string describing the guard action request shape.
|
|
14
|
+
event Guard(uint indexed host, uint id, string name, string request);
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
emit EventAbi(ABI);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import { EventEmitter } from "./Emitter.sol";
|
|
5
|
+
|
|
6
|
+
/// @notice Emitted when a guardian account status changes on a host.
|
|
7
|
+
abstract contract GuardianEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Guardian(uint indexed host, bytes32 account, bool active)";
|
|
9
|
+
|
|
10
|
+
/// @param host Host node ID where the guardian change occurred.
|
|
11
|
+
/// @param account Guardian account ID.
|
|
12
|
+
/// @param active True if the guardian is enabled, false if revoked.
|
|
13
|
+
event Guardian(uint indexed host, bytes32 account, bool active);
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
emit EventAbi(ABI);
|
|
17
|
+
}
|
|
18
|
+
}
|
package/events/Introduction.sol
CHANGED
|
@@ -3,10 +3,10 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI = "event Introduction(uint indexed host, uint blocknum, uint16 version, string namespace)";
|
|
7
|
-
|
|
8
6
|
/// @notice Emitted when a host introduces itself to another host.
|
|
9
7
|
abstract contract IntroductionEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Introduction(uint indexed host, uint blocknum, uint16 version, string namespace)";
|
|
9
|
+
|
|
10
10
|
/// @param host Host node ID of the introducing contract.
|
|
11
11
|
/// @param blocknum Block number at which the host was deployed.
|
|
12
12
|
/// @param version Protocol version the host implements.
|
package/events/Node.sol
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import { EventEmitter } from "./Emitter.sol";
|
|
5
|
+
|
|
6
|
+
/// @notice Emitted when a node's authorization status changes on a host.
|
|
7
|
+
abstract contract NodeEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Node(uint indexed host, uint node, bool active)";
|
|
9
|
+
|
|
10
|
+
/// @param host Host node ID where the authorization change occurred.
|
|
11
|
+
/// @param node Node ID that was authorized or revoked.
|
|
12
|
+
/// @param active True if the node is authorized, false if revoked.
|
|
13
|
+
event Node(uint indexed host, uint node, bool active);
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
emit EventAbi(ABI);
|
|
17
|
+
}
|
|
18
|
+
}
|
package/events/Peer.sol
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
string constant ABI =
|
|
7
|
-
"event Peer(uint indexed host, uint id, string name, bytes32 shape, string request, string response, bool acceptsValue)";
|
|
4
|
+
import {EventEmitter} from "./Emitter.sol";
|
|
8
5
|
|
|
9
6
|
/// @notice Emitted once per peer during host deployment to publish its request and response schemas.
|
|
10
7
|
abstract contract PeerEvent is EventEmitter {
|
|
8
|
+
string private constant ABI =
|
|
9
|
+
"event Peer(uint indexed host, uint id, string name, bytes32 shape, string request, string response, bool acceptsValue)";
|
|
10
|
+
|
|
11
11
|
/// @param host Host node ID that owns this peer.
|
|
12
12
|
/// @param id Peer node ID.
|
|
13
13
|
/// @param name Human-readable peer name.
|
|
@@ -15,12 +15,17 @@ abstract contract PeerEvent is EventEmitter {
|
|
|
15
15
|
/// @param request Schema DSL string describing the peer request shape.
|
|
16
16
|
/// @param response Schema DSL string describing the peer response shape.
|
|
17
17
|
/// @param acceptsValue Whether the peer entrypoint accepts nonzero `msg.value`.
|
|
18
|
-
event Peer(
|
|
18
|
+
event Peer(
|
|
19
|
+
uint indexed host,
|
|
20
|
+
uint id,
|
|
21
|
+
string name,
|
|
22
|
+
bytes32 shape,
|
|
23
|
+
string request,
|
|
24
|
+
string response,
|
|
25
|
+
bool acceptsValue
|
|
26
|
+
);
|
|
19
27
|
|
|
20
28
|
constructor() {
|
|
21
29
|
emit EventAbi(ABI);
|
|
22
30
|
}
|
|
23
31
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
package/events/Position.sol
CHANGED
|
@@ -3,17 +3,17 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {EventEmitter} from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI = "event AssetPosition(bytes32 indexed account, bytes32 asset, bytes32 meta, uint value, uint queryId)";
|
|
7
|
-
|
|
8
6
|
/// @notice Emitted when the reported value of an asset-backed position changes or is observed.
|
|
9
7
|
/// A value of 0 should be interpreted as a closed position.
|
|
10
|
-
abstract contract
|
|
8
|
+
abstract contract PositionEvent is EventEmitter {
|
|
9
|
+
string private constant ABI = "event Position(bytes32 indexed account, bytes32 asset, bytes32 meta, uint value, uint queryId)";
|
|
10
|
+
|
|
11
11
|
/// @param account Account identifier that owns or is associated with the position.
|
|
12
12
|
/// @param asset Asset identifier for the asset class.
|
|
13
13
|
/// @param meta Asset metadata slot carrying the position context.
|
|
14
14
|
/// @param value Context-specific position value; 0 indicates a closed position.
|
|
15
15
|
/// @param queryId Query ID associated with the position lookup or reporting context.
|
|
16
|
-
event
|
|
16
|
+
event Position(bytes32 indexed account, bytes32 asset, bytes32 meta, uint value, uint queryId);
|
|
17
17
|
|
|
18
18
|
constructor() {
|
|
19
19
|
emit EventAbi(ABI);
|
package/events/Query.sol
CHANGED
|
@@ -3,10 +3,10 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {EventEmitter} from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI = "event Query(uint indexed host, uint id, string name, bytes32 shape, string request, string response)";
|
|
7
|
-
|
|
8
6
|
/// @notice Emitted once per query during host deployment to publish its request and response schemas.
|
|
9
7
|
abstract contract QueryEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Query(uint indexed host, uint id, string name, bytes32 shape, string request, string response)";
|
|
9
|
+
|
|
10
10
|
/// @param host Host node ID that owns this query.
|
|
11
11
|
/// @param id Query node ID.
|
|
12
12
|
/// @param name Human-readable query name.
|
|
@@ -0,0 +1,20 @@
|
|
|
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 account receives an asset in a protocol operation.
|
|
7
|
+
abstract contract ReceivedEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Received(bytes32 indexed account, bytes32 asset, bytes32 meta, uint amount, uint context)";
|
|
9
|
+
|
|
10
|
+
/// @param account Account identifier that received the asset.
|
|
11
|
+
/// @param asset Asset identifier.
|
|
12
|
+
/// @param meta Asset metadata slot.
|
|
13
|
+
/// @param amount Amount received.
|
|
14
|
+
/// @param context Operation context identifier associated with this receipt.
|
|
15
|
+
event Received(bytes32 indexed account, bytes32 asset, bytes32 meta, uint amount, uint context);
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
emit EventAbi(ABI);
|
|
19
|
+
}
|
|
20
|
+
}
|
package/events/Rooted.sol
CHANGED
|
@@ -3,10 +3,10 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from "./Emitter.sol";
|
|
5
5
|
|
|
6
|
-
string constant ABI = "event Rooted(bytes32 indexed account, uint deadline, uint value)";
|
|
7
|
-
|
|
8
6
|
/// @notice Emitted for root-level protocol actions (e.g. governance or protocol-wide operations).
|
|
9
7
|
abstract contract RootedEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Rooted(bytes32 indexed account, uint deadline, uint value)";
|
|
9
|
+
|
|
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.
|
package/events/Spent.sol
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
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 account spends an asset in a protocol operation.
|
|
7
|
+
abstract contract SpentEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Spent(bytes32 indexed account, bytes32 asset, bytes32 meta, uint amount, uint context)";
|
|
9
|
+
|
|
10
|
+
/// @param account Account identifier that spent the asset.
|
|
11
|
+
/// @param asset Asset identifier.
|
|
12
|
+
/// @param meta Asset metadata slot.
|
|
13
|
+
/// @param amount Amount spent.
|
|
14
|
+
/// @param context Operation context identifier associated with this spend.
|
|
15
|
+
event Spent(bytes32 indexed account, bytes32 asset, bytes32 meta, uint amount, uint context);
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
emit EventAbi(ABI);
|
|
19
|
+
}
|
|
20
|
+
}
|
package/guards/Base.sol
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {AccessControl} from "../core/Access.sol";
|
|
5
|
+
import {GuardEvent} from "../events/Guard.sol";
|
|
6
|
+
import {Ids, Selectors} from "../utils/Ids.sol";
|
|
7
|
+
|
|
8
|
+
/// @notice ABI-encode a guard action call from a target guard ID and request block stream.
|
|
9
|
+
/// @dev Derives the function selector from `target` via `Ids.guardSelector(target)`.
|
|
10
|
+
/// Reverts if `target` is not a valid guard ID.
|
|
11
|
+
/// @param target Destination guard action node ID embedding the target selector.
|
|
12
|
+
/// @param request Input block stream for the guard invocation.
|
|
13
|
+
/// @return ABI-encoded calldata for the guard action entry point.
|
|
14
|
+
function encodeGuardCall(uint target, bytes calldata request) pure returns (bytes memory) {
|
|
15
|
+
bytes4 selector = Ids.guardSelector(target);
|
|
16
|
+
return abi.encodeWithSelector(selector, request);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/// @title GuardBase
|
|
20
|
+
/// @notice Abstract base for guardian-only direct host actions.
|
|
21
|
+
/// Guard actions are non-payable direct calls with no command context, state, or response.
|
|
22
|
+
abstract contract GuardBase is AccessControl, GuardEvent {
|
|
23
|
+
/// @dev Restrict execution to active guardian addresses.
|
|
24
|
+
modifier onlyGuardian() {
|
|
25
|
+
if (!isGuardian(msg.sender)) revert AccessDenied();
|
|
26
|
+
_;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// @notice Derive the deterministic node ID for a named guard action on this contract.
|
|
30
|
+
/// @param name Guard action function name (without argument list).
|
|
31
|
+
/// @return Guard action node ID.
|
|
32
|
+
function guardId(string memory name) internal view returns (uint) {
|
|
33
|
+
return Ids.toGuard(Selectors.guard(name), address(this));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {GuardBase} from "./Base.sol";
|
|
5
|
+
import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
6
|
+
using Cursors for Cur;
|
|
7
|
+
|
|
8
|
+
/// @title Revoke
|
|
9
|
+
/// @notice Guardian action that quickly revokes authorization from a list of node IDs.
|
|
10
|
+
/// Each NODE block in the request is deauthorized on the host.
|
|
11
|
+
/// Only callable by active guardian addresses.
|
|
12
|
+
abstract contract Revoke is GuardBase {
|
|
13
|
+
string private constant NAME = "revoke";
|
|
14
|
+
|
|
15
|
+
uint internal immutable revokeId = guardId(NAME);
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
emit Guard(host, revokeId, NAME, Schemas.Node);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function revoke(bytes calldata request) external onlyGuardian {
|
|
22
|
+
(Cur memory input, ) = cursor(request, 1);
|
|
23
|
+
|
|
24
|
+
while (input.i < input.bound) {
|
|
25
|
+
uint node = input.unpackNode();
|
|
26
|
+
setNode(node, false);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
input.close();
|
|
30
|
+
}
|
|
31
|
+
}
|
package/package.json
CHANGED
package/peer/Pipe.sol
CHANGED
|
@@ -9,26 +9,26 @@ import {Budget} from "../utils/Value.sol";
|
|
|
9
9
|
using Cursors for Cur;
|
|
10
10
|
|
|
11
11
|
/// @title PeerPipePayable
|
|
12
|
-
/// @notice Peer that consumes
|
|
13
|
-
/// Each
|
|
14
|
-
///
|
|
12
|
+
/// @notice Peer that consumes PIPE blocks and executes each context request as a STEP stream.
|
|
13
|
+
/// Each PIPE block carries a value budget plus a CONTEXT block; the nested
|
|
14
|
+
/// context request is passed to the shared pipeline as the step stream.
|
|
15
15
|
abstract contract PeerPipePayable is PeerBase, Pipeline {
|
|
16
16
|
string private constant NAME = "peerPipePayable";
|
|
17
17
|
uint internal immutable peerPipePayableId = peerId(NAME);
|
|
18
18
|
|
|
19
19
|
constructor() {
|
|
20
|
-
emit Peer(host, peerPipePayableId, NAME, "1:0", Schemas.
|
|
20
|
+
emit Peer(host, peerPipePayableId, NAME, "1:0", Schemas.Pipe, "", true);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/// @notice Execute peer-supplied
|
|
24
|
-
/// @dev Each
|
|
25
|
-
/// `msg.value` not assigned to a
|
|
23
|
+
/// @notice Execute peer-supplied pipes through the shared payable pipe.
|
|
24
|
+
/// @dev Each pipe receives its own explicit value sub-budget. Any top-level
|
|
25
|
+
/// `msg.value` not assigned to a pipe remains on this host.
|
|
26
26
|
function peerPipePayable(bytes calldata request) external payable onlyPeer returns (bytes memory) {
|
|
27
27
|
(Cur memory input, ) = cursor(request, 1);
|
|
28
28
|
Budget memory budget = valueBudget();
|
|
29
29
|
|
|
30
30
|
while (input.i < input.bound) {
|
|
31
|
-
(
|
|
31
|
+
(uint value, bytes32 account, bytes calldata state, bytes calldata steps) = input.unpackPipe();
|
|
32
32
|
pipe(account, state, steps, allocateValue(budget, value));
|
|
33
33
|
}
|
|
34
34
|
|
package/queries/Assets.sol
CHANGED
|
@@ -8,38 +8,38 @@ import {QueryBase} from "./Base.sol";
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
using Writers for Writer;
|
|
10
10
|
|
|
11
|
-
abstract contract
|
|
12
|
-
/// @notice Resolve
|
|
13
|
-
/// Concrete implementations define the
|
|
11
|
+
abstract contract AssetStatusHook {
|
|
12
|
+
/// @notice Resolve support status for one asset tuple.
|
|
13
|
+
/// Concrete implementations define the support policy and optional context codes.
|
|
14
14
|
/// @param asset Requested asset identifier.
|
|
15
15
|
/// @param meta Requested asset metadata slot.
|
|
16
|
-
/// @return
|
|
17
|
-
function
|
|
16
|
+
/// @return status Asset support status. Zero means unsupported; nonzero means supported.
|
|
17
|
+
function assetStatus(bytes32 asset, bytes32 meta) internal view virtual returns (uint status);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
/// @title
|
|
21
|
-
/// @notice Rootzero query that checks
|
|
20
|
+
/// @title AssetStatus
|
|
21
|
+
/// @notice Rootzero query that checks support status for one or more `(asset, meta)` tuples.
|
|
22
22
|
/// The request is a run of `ASSET` blocks.
|
|
23
23
|
/// The response returns one `STATUS` form block per query entry, preserving request order.
|
|
24
|
-
abstract contract
|
|
25
|
-
string private constant NAME = "
|
|
26
|
-
uint public immutable
|
|
24
|
+
abstract contract AssetStatus is QueryBase, AssetStatusHook {
|
|
25
|
+
string private constant NAME = "assetStatus";
|
|
26
|
+
uint public immutable assetStatusId = queryId(NAME);
|
|
27
27
|
|
|
28
28
|
constructor() {
|
|
29
|
-
emit Query(host,
|
|
29
|
+
emit Query(host, assetStatusId, NAME, "1:1", Schemas.Asset, Forms.Status);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/// @notice Resolve
|
|
32
|
+
/// @notice Resolve asset support status for a run of requested `(asset, meta)` tuples.
|
|
33
33
|
/// @param request Block-stream request consisting of `#asset { bytes32 asset, bytes32 meta }` blocks.
|
|
34
|
-
/// @return Block-stream response containing one `#status {
|
|
35
|
-
function
|
|
34
|
+
/// @return Block-stream response containing one `#status { uint code }` per asset block.
|
|
35
|
+
function assetStatus(bytes calldata request) external view returns (bytes memory) {
|
|
36
36
|
(Cur memory query, uint groups) = cursor(request, 1);
|
|
37
37
|
Writer memory response = Writers.allocStatuses(groups);
|
|
38
38
|
|
|
39
39
|
while (query.i < query.bound) {
|
|
40
40
|
(bytes32 asset, bytes32 meta) = query.unpackAsset();
|
|
41
|
-
|
|
42
|
-
response.appendStatus(
|
|
41
|
+
uint status = assetStatus(asset, meta);
|
|
42
|
+
response.appendStatus(status);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
query.close();
|
package/utils/Accounts.sol
CHANGED
|
@@ -8,8 +8,9 @@ import {isFamily, toLocalBase, toUnspecifiedBase} from "./Utils.sol";
|
|
|
8
8
|
/// @notice Encoding and decoding helpers for 256-bit account identifiers.
|
|
9
9
|
///
|
|
10
10
|
/// Account IDs embed a 4-byte type tag in bits [255:224]:
|
|
11
|
-
/// - `Admin`
|
|
12
|
-
/// - `
|
|
11
|
+
/// - `Admin` — chain-local EVM address in bits [191:32]
|
|
12
|
+
/// - `Guardian` — chain-local EVM address in bits [191:32]
|
|
13
|
+
/// - `User` — chain-agnostic EVM address in bits [191:32]
|
|
13
14
|
library Accounts {
|
|
14
15
|
/// @dev Thrown when an account ID does not belong to the EVM family.
|
|
15
16
|
error InvalidAccount();
|
|
@@ -18,6 +19,8 @@ library Accounts {
|
|
|
18
19
|
uint24 constant Family = (uint24(Layout.Evm32) << 8) | uint24(Layout.Account);
|
|
19
20
|
/// @dev Full 4-byte type prefix for admin accounts (chain-local EVM address).
|
|
20
21
|
uint32 constant Admin = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Admin);
|
|
22
|
+
/// @dev Full 4-byte type prefix for guardian accounts (chain-local EVM address).
|
|
23
|
+
uint32 constant Guardian = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Guardian);
|
|
21
24
|
/// @dev Full 4-byte type prefix for user accounts (chain-agnostic EVM address).
|
|
22
25
|
uint32 constant User = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.User);
|
|
23
26
|
/// @dev Full 4-byte type prefix for keccak accounts (opaque 28-byte hash).
|
|
@@ -40,6 +43,11 @@ library Accounts {
|
|
|
40
43
|
return prefix(account) == Admin;
|
|
41
44
|
}
|
|
42
45
|
|
|
46
|
+
/// @notice Return true if `account` is a guardian account.
|
|
47
|
+
function isGuardian(bytes32 account) internal pure returns (bool) {
|
|
48
|
+
return prefix(account) == Guardian;
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
/// @notice Return true if `account` is a user account.
|
|
44
52
|
function isUser(bytes32 account) internal pure returns (bool) {
|
|
45
53
|
return prefix(account) == User;
|
|
@@ -49,6 +57,38 @@ library Accounts {
|
|
|
49
57
|
return prefix(account) == Keccak;
|
|
50
58
|
}
|
|
51
59
|
|
|
60
|
+
/// @notice Assert that `input` is an admin account and return it unchanged.
|
|
61
|
+
/// @param input Account identifier to validate.
|
|
62
|
+
/// @return account The same `input` if it is an admin account.
|
|
63
|
+
function admin(bytes32 input) internal pure returns (bytes32 account) {
|
|
64
|
+
if (!isAdmin(input)) revert InvalidAccount();
|
|
65
|
+
return input;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// @notice Assert that `input` is a guardian account and return it unchanged.
|
|
69
|
+
/// @param input Account identifier to validate.
|
|
70
|
+
/// @return account The same `input` if it is a guardian account.
|
|
71
|
+
function guardian(bytes32 input) internal pure returns (bytes32 account) {
|
|
72
|
+
if (!isGuardian(input)) revert InvalidAccount();
|
|
73
|
+
return input;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// @notice Assert that `input` is a user account and return it unchanged.
|
|
77
|
+
/// @param input Account identifier to validate.
|
|
78
|
+
/// @return account The same `input` if it is a user account.
|
|
79
|
+
function user(bytes32 input) internal pure returns (bytes32 account) {
|
|
80
|
+
if (!isUser(input)) revert InvalidAccount();
|
|
81
|
+
return input;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/// @notice Assert that `input` is a keccak account and return it unchanged.
|
|
85
|
+
/// @param input Account identifier to validate.
|
|
86
|
+
/// @return account The same `input` if it is a keccak account.
|
|
87
|
+
function keccak(bytes32 input) internal pure returns (bytes32 account) {
|
|
88
|
+
if (!isKeccak(input)) revert InvalidAccount();
|
|
89
|
+
return input;
|
|
90
|
+
}
|
|
91
|
+
|
|
52
92
|
/// @notice Encode an EVM address as a chain-local admin account ID.
|
|
53
93
|
/// @param addr EVM address to embed.
|
|
54
94
|
/// @return Admin account ID bound to the current chain.
|
|
@@ -56,6 +96,13 @@ library Accounts {
|
|
|
56
96
|
return bytes32(toLocalBase(Admin) | (uint(uint160(addr)) << 32));
|
|
57
97
|
}
|
|
58
98
|
|
|
99
|
+
/// @notice Encode an EVM address as a chain-local guardian account ID.
|
|
100
|
+
/// @param addr EVM address to embed.
|
|
101
|
+
/// @return Guardian account ID bound to the current chain.
|
|
102
|
+
function toGuardian(address addr) internal view returns (bytes32) {
|
|
103
|
+
return bytes32(toLocalBase(Guardian) | (uint(uint160(addr)) << 32));
|
|
104
|
+
}
|
|
105
|
+
|
|
59
106
|
/// @notice Encode an EVM address as a chain-agnostic user account ID.
|
|
60
107
|
/// @param addr EVM address to embed.
|
|
61
108
|
/// @return User account ID without a chain binding.
|
package/utils/Assets.sol
CHANGED
|
@@ -17,6 +17,8 @@ import {matchesBase, toLocalBase} from "./Utils.sol";
|
|
|
17
17
|
library Assets {
|
|
18
18
|
/// @dev Thrown when an asset ID does not match the expected type or chain.
|
|
19
19
|
error InvalidAsset();
|
|
20
|
+
/// @dev Thrown when an asset is not authorized for the requested operation.
|
|
21
|
+
error UnauthorizedAsset();
|
|
20
22
|
|
|
21
23
|
/// @dev Full 4-byte type prefix for the native value asset.
|
|
22
24
|
uint32 constant Value = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Value);
|