@rootzero/contracts 1.10.0 → 1.12.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 +46 -1
- package/Core.sol +1 -0
- package/Endpoints.sol +2 -3
- package/Events.sol +2 -5
- package/README.md +38 -36
- package/Utils.sol +2 -1
- package/blocks/Cursors.sol +39 -75
- package/blocks/Keys.sol +18 -4
- package/blocks/Schema.sol +53 -47
- package/commands/Base.sol +43 -13
- package/commands/Burn.sol +3 -6
- package/commands/Credit.sol +4 -6
- package/commands/Debit.sol +10 -11
- package/commands/Deposit.sol +19 -23
- package/commands/Payout.sol +6 -10
- package/commands/Provision.sol +19 -23
- package/commands/Recover.sol +7 -9
- package/commands/Relay.sol +10 -11
- package/commands/Withdraw.sol +3 -6
- package/commands/admin/AllowAssets.sol +7 -10
- package/commands/admin/Allowance.sol +7 -10
- package/commands/admin/Appoint.sol +7 -10
- package/commands/admin/Authorize.sol +10 -19
- package/commands/admin/Base.sol +1 -2
- package/commands/admin/DenyAssets.sol +7 -10
- package/commands/admin/Dismiss.sol +7 -10
- package/commands/admin/Execute.sol +7 -10
- package/commands/admin/Label.sol +8 -11
- package/commands/admin/Schemas.sol +31 -0
- package/commands/admin/Unauthorize.sol +10 -19
- package/core/Endpoint.sol +160 -0
- package/core/Host.sol +1 -1
- package/docs/Schema.md +124 -86
- package/events/Endpoint.sol +19 -0
- package/events/Schema.sol +23 -0
- package/guards/Base.sol +17 -8
- package/guards/Revoke.sol +4 -6
- package/package.json +1 -1
- package/ports/AllowAssets.sol +6 -9
- package/ports/Allowance.sol +6 -9
- package/ports/Base.sol +21 -8
- package/ports/Credit.sol +6 -9
- package/ports/Debit.sol +6 -9
- package/ports/DenyAssets.sol +6 -9
- package/ports/Dispatch.sol +6 -9
- package/ports/Pipe.sol +4 -7
- package/ports/Redeem.sol +4 -7
- package/ports/Settle.sol +6 -9
- package/queries/Assets.sol +9 -12
- package/queries/Balances.sol +7 -9
- package/queries/Base.sol +19 -11
- package/utils/Selectors.sol +49 -0
- package/commands/admin/Destroy.sol +0 -43
- package/commands/admin/Init.sol +0 -43
- package/events/Admin.sol +0 -32
- package/events/Command.sol +0 -32
- package/events/Guard.sol +0 -18
- package/events/Port.sol +0 -22
- package/events/Query.sol +0 -20
- package/queries/Positions.sol +0 -54
package/ports/AllowAssets.sol
CHANGED
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { PortBase } from "./Base.sol";
|
|
5
5
|
import { AllowAssetsHook } from "../commands/admin/AllowAssets.sol";
|
|
6
|
-
import { Cursors, Cur,
|
|
6
|
+
import { Cursors, Cur, Keys } from "../Cursors.sol";
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
@@ -11,25 +11,22 @@ using Cursors for Cur;
|
|
|
11
11
|
/// @notice Port that permits a list of assets on behalf of a peer host.
|
|
12
12
|
/// Each ASSET block in the request calls `allowAsset`. Restricted to trusted peers.
|
|
13
13
|
abstract contract PortAllowAssets is PortBase, AllowAssetsHook {
|
|
14
|
-
|
|
14
|
+
bytes32 private immutable descriptor;
|
|
15
15
|
|
|
16
16
|
constructor() {
|
|
17
|
-
|
|
18
|
-
emit Labeled(portAllowAssetsId, bytes32(0), "portAllowAssets");
|
|
17
|
+
(, descriptor) = port("portAllowAssets", Keys.Asset, Keys.Empty, 0, false);
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
/// @notice Execute the allow-assets peer call.
|
|
22
21
|
/// @param data ASSET block stream supplied by the trusted peer.
|
|
23
22
|
/// @return Empty response bytes.
|
|
24
23
|
function portAllowAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
25
|
-
(Cur memory
|
|
24
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
26
25
|
|
|
27
|
-
while (
|
|
28
|
-
bytes32 asset =
|
|
26
|
+
while (input.i < input.len) {
|
|
27
|
+
bytes32 asset = input.unpackAsset();
|
|
29
28
|
allowAsset(asset);
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
assets.complete();
|
|
33
30
|
return "";
|
|
34
31
|
}
|
|
35
32
|
}
|
package/ports/Allowance.sol
CHANGED
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
5
|
import {AllowanceHook} from "../commands/admin/Allowance.sol";
|
|
6
|
-
import {Cursors, Cur,
|
|
6
|
+
import {Cursors, Cur, Keys} from "../Cursors.sol";
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
@@ -12,26 +12,23 @@ using Cursors for Cur;
|
|
|
12
12
|
/// Each AMOUNT block in the request is scoped to the peer host and passed to the
|
|
13
13
|
/// shared allowance hook as a host-scoped allowance. Restricted to trusted peers.
|
|
14
14
|
abstract contract PortAllowance is PortBase, AllowanceHook {
|
|
15
|
-
|
|
15
|
+
bytes32 private immutable descriptor;
|
|
16
16
|
|
|
17
17
|
constructor() {
|
|
18
|
-
|
|
19
|
-
emit Labeled(portAllowanceId, bytes32(0), "portAllowance");
|
|
18
|
+
(, descriptor) = port("portAllowance", Keys.Amount, Keys.Empty, 0, false);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/// @notice Execute the allowance port call.
|
|
23
22
|
/// @param data AMOUNT block stream requested by the trusted peer.
|
|
24
23
|
/// @return Empty response bytes.
|
|
25
24
|
function portAllowance(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
26
|
-
(Cur memory
|
|
25
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
27
26
|
uint peer = caller();
|
|
28
27
|
|
|
29
|
-
while (
|
|
30
|
-
(bytes32 asset, uint amount) =
|
|
28
|
+
while (input.i < input.len) {
|
|
29
|
+
(bytes32 asset, uint amount) = input.unpackAmount();
|
|
31
30
|
allowance(peer, asset, amount);
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
amounts.complete();
|
|
35
32
|
return "";
|
|
36
33
|
}
|
|
37
34
|
}
|
package/ports/Base.sol
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import { NodeCalls } from "../core/Calls.sol";
|
|
5
|
-
import {
|
|
6
|
-
import { LabeledEvent } from "../events/Labeled.sol";
|
|
5
|
+
import { EndpointBase } from "../core/Endpoint.sol";
|
|
7
6
|
import { Nodes } from "../utils/Nodes.sol";
|
|
7
|
+
import { Selectors } from "../utils/Selectors.sol";
|
|
8
8
|
|
|
9
9
|
/// @title PortBase
|
|
10
10
|
/// @notice Abstract base for peer-facing rootzero ports.
|
|
11
11
|
/// Ports handle inter-host operations between cooperating hosts.
|
|
12
12
|
/// Access is restricted to trusted peer callers via `onlyPeer`.
|
|
13
|
-
abstract contract PortBase is NodeCalls,
|
|
13
|
+
abstract contract PortBase is NodeCalls, EndpointBase {
|
|
14
14
|
/// @dev Thrown when the commander attempts to call a port entrypoint directly.
|
|
15
15
|
error CommanderNotAllowed();
|
|
16
16
|
|
|
@@ -21,10 +21,23 @@ abstract contract PortBase is NodeCalls, PortEvent, LabeledEvent {
|
|
|
21
21
|
_;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/// @notice
|
|
25
|
-
/// @param
|
|
26
|
-
/// @
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
/// @notice Publish port metadata and a default label.
|
|
25
|
+
/// @param name Default human-readable port label and selector name.
|
|
26
|
+
/// @param input Packed input lane plus optional group byte.
|
|
27
|
+
/// @param output Packed output lane plus optional group byte.
|
|
28
|
+
/// @param selector Port ABI selector, or zero to derive it from `name`.
|
|
29
|
+
/// @param funded Whether the port accepts nonzero native value.
|
|
30
|
+
/// @return id Port node ID.
|
|
31
|
+
/// @return descriptor Packed endpoint lane metadata and flags.
|
|
32
|
+
function port(
|
|
33
|
+
string memory name,
|
|
34
|
+
bytes9 input,
|
|
35
|
+
bytes9 output,
|
|
36
|
+
bytes4 selector,
|
|
37
|
+
bool funded
|
|
38
|
+
) internal returns (uint id, bytes32 descriptor) {
|
|
39
|
+
selector = selector == bytes4(0) ? Selectors.port(name) : selector;
|
|
40
|
+
id = Nodes.toPort(selector, address(this));
|
|
41
|
+
descriptor = endpoint(id, name, bytes9(0), input, output, funded, false);
|
|
29
42
|
}
|
|
30
43
|
}
|
package/ports/Credit.sol
CHANGED
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { PortBase } from "./Base.sol";
|
|
5
5
|
import { CreditAccountHook } from "../commands/Credit.sol";
|
|
6
|
-
import { Cursors, Cur,
|
|
6
|
+
import { Cursors, Cur, Keys } from "../Cursors.sol";
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
@@ -11,25 +11,22 @@ using Cursors for Cur;
|
|
|
11
11
|
/// @notice Port that lets a trusted peer credit supplied accounts directly.
|
|
12
12
|
/// Each ACCOUNT_AMOUNT block calls `creditAccount` for its account.
|
|
13
13
|
abstract contract PortCreditAccount is PortBase, CreditAccountHook {
|
|
14
|
-
|
|
14
|
+
bytes32 private immutable descriptor;
|
|
15
15
|
|
|
16
16
|
constructor() {
|
|
17
|
-
|
|
18
|
-
emit Labeled(portCreditAccountId, bytes32(0), "portCreditAccount");
|
|
17
|
+
(, descriptor) = port("portCreditAccount", Keys.AccountAmount, Keys.Empty, 0, false);
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
/// @notice Execute the port-credit call.
|
|
22
21
|
/// @param data ACCOUNT_AMOUNT block stream supplied by the trusted peer.
|
|
23
22
|
/// @return Empty response bytes.
|
|
24
23
|
function portCreditAccount(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
25
|
-
(Cur memory
|
|
24
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
26
25
|
|
|
27
|
-
while (
|
|
28
|
-
(bytes32 account, bytes32 asset, uint amount) =
|
|
26
|
+
while (input.i < input.len) {
|
|
27
|
+
(bytes32 account, bytes32 asset, uint amount) = input.unpackAccountAmount();
|
|
29
28
|
creditAccount(account, asset, amount);
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
amounts.complete();
|
|
33
30
|
return "";
|
|
34
31
|
}
|
|
35
32
|
}
|
package/ports/Debit.sol
CHANGED
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import { PortBase } from "./Base.sol";
|
|
5
5
|
import { DebitAccountHook } from "../commands/Debit.sol";
|
|
6
|
-
import { Cursors, Cur,
|
|
6
|
+
import { Cursors, Cur, Keys } from "../Cursors.sol";
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
@@ -11,25 +11,22 @@ using Cursors for Cur;
|
|
|
11
11
|
/// @notice Port that lets a trusted peer debit supplied accounts directly.
|
|
12
12
|
/// Each ACCOUNT_AMOUNT block calls `debitAccount` for its account.
|
|
13
13
|
abstract contract PortDebitAccount is PortBase, DebitAccountHook {
|
|
14
|
-
|
|
14
|
+
bytes32 private immutable descriptor;
|
|
15
15
|
|
|
16
16
|
constructor() {
|
|
17
|
-
|
|
18
|
-
emit Labeled(portDebitAccountId, bytes32(0), "portDebitAccount");
|
|
17
|
+
(, descriptor) = port("portDebitAccount", Keys.AccountAmount, Keys.Empty, 0, false);
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
/// @notice Execute the port-debit call.
|
|
22
21
|
/// @param data ACCOUNT_AMOUNT block stream supplied by the trusted peer.
|
|
23
22
|
/// @return Empty response bytes.
|
|
24
23
|
function portDebitAccount(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
25
|
-
(Cur memory
|
|
24
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
26
25
|
|
|
27
|
-
while (
|
|
28
|
-
(bytes32 account, bytes32 asset, uint amount) =
|
|
26
|
+
while (input.i < input.len) {
|
|
27
|
+
(bytes32 account, bytes32 asset, uint amount) = input.unpackAccountAmount();
|
|
29
28
|
debitAccount(account, asset, amount);
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
amounts.complete();
|
|
33
30
|
return "";
|
|
34
31
|
}
|
|
35
32
|
}
|
package/ports/DenyAssets.sol
CHANGED
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
5
|
import {DenyAssetsHook} from "../commands/admin/DenyAssets.sol";
|
|
6
|
-
import {Cursors, Cur,
|
|
6
|
+
import {Cursors, Cur, Keys} from "../Cursors.sol";
|
|
7
7
|
|
|
8
8
|
using Cursors for Cur;
|
|
9
9
|
|
|
@@ -11,25 +11,22 @@ using Cursors for Cur;
|
|
|
11
11
|
/// @notice Port that blocks a list of assets on behalf of a peer host.
|
|
12
12
|
/// Each ASSET block in the request calls `denyAsset`. Restricted to trusted peers.
|
|
13
13
|
abstract contract PortDenyAssets is PortBase, DenyAssetsHook {
|
|
14
|
-
|
|
14
|
+
bytes32 private immutable descriptor;
|
|
15
15
|
|
|
16
16
|
constructor() {
|
|
17
|
-
|
|
18
|
-
emit Labeled(portDenyAssetsId, bytes32(0), "portDenyAssets");
|
|
17
|
+
(, descriptor) = port("portDenyAssets", Keys.Asset, Keys.Empty, 0, false);
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
/// @notice Execute the deny-assets peer call.
|
|
22
21
|
/// @param data ASSET block stream supplied by the trusted peer.
|
|
23
22
|
/// @return Empty response bytes.
|
|
24
23
|
function portDenyAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
25
|
-
(Cur memory
|
|
24
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
26
25
|
|
|
27
|
-
while (
|
|
28
|
-
bytes32 asset =
|
|
26
|
+
while (input.i < input.len) {
|
|
27
|
+
bytes32 asset = input.unpackAsset();
|
|
29
28
|
denyAsset(asset);
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
assets.complete();
|
|
33
30
|
return "";
|
|
34
31
|
}
|
|
35
32
|
}
|
package/ports/Dispatch.sol
CHANGED
|
@@ -4,7 +4,7 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
import { PortBase } from "./Base.sol";
|
|
5
5
|
import { Payable } from "../core/Payable.sol";
|
|
6
6
|
import { RoutePayableHook } from "../commands/Relay.sol";
|
|
7
|
-
import { Cursors, Cur,
|
|
7
|
+
import { Cursors, Cur, Keys } from "../Cursors.sol";
|
|
8
8
|
import { Budget } from "../utils/Value.sol";
|
|
9
9
|
|
|
10
10
|
using Cursors for Cur;
|
|
@@ -12,28 +12,25 @@ using Cursors for Cur;
|
|
|
12
12
|
/// @title PortDispatchPayable
|
|
13
13
|
/// @notice Port endpoint that forwards DISPATCH blocks to a host-defined route hook.
|
|
14
14
|
abstract contract PortDispatchPayable is PortBase, Payable, RoutePayableHook {
|
|
15
|
-
|
|
15
|
+
bytes32 private immutable descriptor;
|
|
16
16
|
|
|
17
17
|
constructor() {
|
|
18
|
-
|
|
19
|
-
emit Labeled(portDispatchPayableId, bytes32(0), "portDispatchPayable");
|
|
18
|
+
(, descriptor) = port("portDispatchPayable", Keys.Dispatch, Keys.Empty, 0, true);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/// @notice Forward peer-supplied dispatches to the host-defined route hook.
|
|
23
22
|
/// @dev Route hooks receive the shared top-level source value
|
|
24
23
|
/// budget. Any `msg.value` not spent by the hook remains on this host.
|
|
25
24
|
/// @param data DISPATCH block stream supplied by the trusted peer.
|
|
26
|
-
/// @return
|
|
27
|
-
function portDispatchPayable(bytes calldata data) external payable onlyPeer returns (bytes memory
|
|
28
|
-
(Cur memory input, ) =
|
|
25
|
+
/// @return Empty response bytes.
|
|
26
|
+
function portDispatchPayable(bytes calldata data) external payable onlyPeer returns (bytes memory) {
|
|
27
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
29
28
|
Budget memory budget = openValue();
|
|
30
29
|
|
|
31
30
|
while (input.i < input.len) {
|
|
32
31
|
(uint portal, uint resources, bytes calldata payload) = input.unpackDispatch();
|
|
33
32
|
route(portal, resources, bytes(payload), budget);
|
|
34
33
|
}
|
|
35
|
-
|
|
36
|
-
input.complete();
|
|
37
34
|
return "";
|
|
38
35
|
}
|
|
39
36
|
|
package/ports/Pipe.sol
CHANGED
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
5
|
import {Pipeline} from "../core/Pipeline.sol";
|
|
6
|
-
import {Cursors, Cur,
|
|
6
|
+
import {Cursors, Cur, Keys} from "../Cursors.sol";
|
|
7
7
|
import {Budget} from "../utils/Value.sol";
|
|
8
8
|
|
|
9
9
|
using Cursors for Cur;
|
|
@@ -12,11 +12,10 @@ using Cursors for Cur;
|
|
|
12
12
|
/// @notice Port that consumes CONTEXT blocks and executes each request as a step stream.
|
|
13
13
|
/// Each context's request bytes are passed to the shared pipeline.
|
|
14
14
|
abstract contract PortPipePayable is PortBase, Pipeline {
|
|
15
|
-
|
|
15
|
+
bytes32 private immutable descriptor;
|
|
16
16
|
|
|
17
17
|
constructor() {
|
|
18
|
-
|
|
19
|
-
emit Labeled(portPipePayableId, bytes32(0), "portPipePayable");
|
|
18
|
+
(, descriptor) = port("portPipePayable", Keys.Context, Keys.Empty, 0, true);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/// @notice Execute peer-supplied contexts through the shared payable pipe.
|
|
@@ -25,15 +24,13 @@ abstract contract PortPipePayable is PortBase, Pipeline {
|
|
|
25
24
|
/// @param data CONTEXT block stream supplied by the trusted peer.
|
|
26
25
|
/// @return Empty response bytes.
|
|
27
26
|
function portPipePayable(bytes calldata data) external payable onlyPeer returns (bytes memory) {
|
|
28
|
-
(Cur memory input, ) =
|
|
27
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
29
28
|
Budget memory budget = openValue();
|
|
30
29
|
|
|
31
30
|
while (input.i < input.len) {
|
|
32
31
|
(bytes32 account, bytes calldata state, bytes calldata request) = input.unpackContext();
|
|
33
32
|
pipe(account, state, request, budget);
|
|
34
33
|
}
|
|
35
|
-
|
|
36
|
-
input.complete();
|
|
37
34
|
return "";
|
|
38
35
|
}
|
|
39
36
|
}
|
package/ports/Redeem.sol
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
|
-
import {Cursors, Cur,
|
|
5
|
+
import {Cursors, Cur, Keys} from "../Cursors.sol";
|
|
6
6
|
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
@@ -19,26 +19,23 @@ abstract contract RedeemBalanceHook {
|
|
|
19
19
|
/// Each BALANCE block in the request calls `redeemBalance(peer, asset, amount)`.
|
|
20
20
|
/// Restricted to trusted peers.
|
|
21
21
|
abstract contract PortRedeemBalance is PortBase, RedeemBalanceHook {
|
|
22
|
-
|
|
22
|
+
bytes32 private immutable descriptor;
|
|
23
23
|
|
|
24
24
|
constructor() {
|
|
25
|
-
|
|
26
|
-
emit Labeled(portRedeemBalanceId, bytes32(0), "portRedeemBalance");
|
|
25
|
+
(, descriptor) = port("portRedeemBalance", Keys.Balance, Keys.Empty, 0, false);
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
/// @notice Execute the balance redemption port call.
|
|
30
29
|
/// @param data BALANCE block stream supplied by the trusted peer.
|
|
31
30
|
/// @return Empty response bytes.
|
|
32
31
|
function portRedeemBalance(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
33
|
-
(Cur memory input, ) =
|
|
32
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
34
33
|
uint peer = caller();
|
|
35
34
|
|
|
36
35
|
while (input.i < input.len) {
|
|
37
36
|
(bytes32 asset, uint amount) = input.unpackBalance();
|
|
38
37
|
redeemBalance(peer, asset, amount);
|
|
39
38
|
}
|
|
40
|
-
|
|
41
|
-
input.complete();
|
|
42
39
|
return "";
|
|
43
40
|
}
|
|
44
41
|
}
|
package/ports/Settle.sol
CHANGED
|
@@ -4,7 +4,7 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
import { PortBase } from "./Base.sol";
|
|
5
5
|
import { CreditAccountHook } from "../commands/Credit.sol";
|
|
6
6
|
import { DebitAccountHook } from "../commands/Debit.sol";
|
|
7
|
-
import { Cursors, Cur,
|
|
7
|
+
import { Cursors, Cur, Keys } from "../Cursors.sol";
|
|
8
8
|
|
|
9
9
|
using Cursors for Cur;
|
|
10
10
|
|
|
@@ -12,26 +12,23 @@ using Cursors for Cur;
|
|
|
12
12
|
/// @notice Port that consumes peer-supplied TRANSACTION blocks through debit and credit hooks.
|
|
13
13
|
/// Each TRANSACTION block calls `debitAccount` for `from` and `creditAccount` for `to`.
|
|
14
14
|
abstract contract PortSettle is PortBase, DebitAccountHook, CreditAccountHook {
|
|
15
|
-
|
|
15
|
+
bytes32 private immutable descriptor;
|
|
16
16
|
|
|
17
17
|
constructor() {
|
|
18
|
-
|
|
19
|
-
emit Labeled(portSettleId, bytes32(0), "portSettle");
|
|
18
|
+
(, descriptor) = port("portSettle", Keys.Transaction, Keys.Empty, 0, false);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
/// @notice Execute the port-settle call.
|
|
23
22
|
/// @param data TRANSACTION block stream supplied by the trusted peer.
|
|
24
23
|
/// @return Empty response bytes.
|
|
25
24
|
function portSettle(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
26
|
-
(Cur memory
|
|
25
|
+
(Cur memory input, ) = openInput(data, descriptor);
|
|
27
26
|
|
|
28
|
-
while (
|
|
29
|
-
(bytes32 from, bytes32 to, bytes32 asset, uint amount) =
|
|
27
|
+
while (input.i < input.len) {
|
|
28
|
+
(bytes32 from, bytes32 to, bytes32 asset, uint amount) = input.unpackTransaction();
|
|
30
29
|
if (from != 0) debitAccount(from, asset, amount);
|
|
31
30
|
if (to != 0) creditAccount(to, asset, amount);
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
state.complete();
|
|
35
32
|
return "";
|
|
36
33
|
}
|
|
37
34
|
}
|
package/queries/Assets.sol
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {Cur, Cursors, Writer, Writers} from "../Cursors.sol";
|
|
5
|
-
import {Forms, Schemas} from "../blocks/Schema.sol";
|
|
4
|
+
import {Cur, Cursors, Keys, Writer, Writers} from "../Cursors.sol";
|
|
6
5
|
import {QueryBase} from "./Base.sol";
|
|
7
6
|
|
|
8
7
|
using Cursors for Cur;
|
|
@@ -21,27 +20,25 @@ abstract contract AssetStatusHook {
|
|
|
21
20
|
/// The request is a run of `ASSET` blocks.
|
|
22
21
|
/// The response returns one `STATUS` form block per query entry, preserving request order.
|
|
23
22
|
abstract contract AssetStatus is QueryBase, AssetStatusHook {
|
|
24
|
-
|
|
23
|
+
bytes32 private immutable descriptor;
|
|
25
24
|
|
|
26
25
|
constructor() {
|
|
27
|
-
|
|
28
|
-
emit Labeled(assetStatusId, bytes32(0), "assetStatus");
|
|
26
|
+
(, descriptor) = query("assetStatus", Keys.Asset, Keys.Status, 0);
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
/// @notice Resolve asset support status for a run of requested assets.
|
|
32
|
-
/// @param request Block-stream request consisting of
|
|
33
|
-
/// @return Block-stream response containing one
|
|
30
|
+
/// @param request Block-stream request consisting of `asset { bytes32 asset }` blocks.
|
|
31
|
+
/// @return Block-stream response containing one `status { uint code }` form block per asset block.
|
|
34
32
|
function assetStatus(bytes calldata request) external view returns (bytes memory) {
|
|
35
|
-
(Cur memory
|
|
36
|
-
Writer memory response = Writers.allocStatuses(
|
|
33
|
+
(Cur memory input, uint outputs) = openInput(request, descriptor);
|
|
34
|
+
Writer memory response = Writers.allocStatuses(outputs);
|
|
37
35
|
|
|
38
|
-
while (
|
|
39
|
-
bytes32 asset =
|
|
36
|
+
while (input.i < input.len) {
|
|
37
|
+
bytes32 asset = input.unpackAsset();
|
|
40
38
|
uint status = assetStatus(asset);
|
|
41
39
|
response.appendStatus(status);
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
query.complete();
|
|
45
42
|
return response.finish();
|
|
46
43
|
}
|
|
47
44
|
}
|
package/queries/Balances.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {Cur, Cursors,
|
|
4
|
+
import {Cur, Cursors, Keys, Writer, Writers} from "../Cursors.sol";
|
|
5
5
|
import {QueryBase} from "./Base.sol";
|
|
6
6
|
|
|
7
7
|
using Cursors for Cur;
|
|
@@ -21,27 +21,25 @@ abstract contract GetBalancesHook {
|
|
|
21
21
|
/// The request is a run of `ACCOUNT_ASSET` form blocks.
|
|
22
22
|
/// The response returns one `ACCOUNT_AMOUNT` form block per requested position, preserving request order.
|
|
23
23
|
abstract contract GetBalances is QueryBase, GetBalancesHook {
|
|
24
|
-
|
|
24
|
+
bytes32 private immutable descriptor;
|
|
25
25
|
|
|
26
26
|
constructor() {
|
|
27
|
-
|
|
28
|
-
emit Labeled(getBalancesId, bytes32(0), "getBalances");
|
|
27
|
+
(, descriptor) = query("getBalances", Keys.AccountAsset, Keys.AccountAmount, 0);
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
/// @notice Resolve balances for a run of requested `(account, asset)` tuples.
|
|
32
31
|
/// @param request Block-stream request consisting of `accountAsset(account, asset)*`.
|
|
33
32
|
/// @return Block-stream response containing one `accountAmount(account, asset, amount)` block per request block.
|
|
34
33
|
function getBalances(bytes calldata request) external view returns (bytes memory) {
|
|
35
|
-
(Cur memory
|
|
36
|
-
Writer memory response = Writers.allocAccountAmounts(
|
|
34
|
+
(Cur memory input, uint outputs) = openInput(request, descriptor);
|
|
35
|
+
Writer memory response = Writers.allocAccountAmounts(outputs);
|
|
37
36
|
|
|
38
|
-
while (
|
|
39
|
-
(bytes32 account, bytes32 asset) =
|
|
37
|
+
while (input.i < input.len) {
|
|
38
|
+
(bytes32 account, bytes32 asset) = input.unpackAccountAsset();
|
|
40
39
|
uint amount = getBalance(account, asset);
|
|
41
40
|
response.appendAccountAmount(account, asset, amount);
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
query.complete();
|
|
45
43
|
return response.finish();
|
|
46
44
|
}
|
|
47
45
|
}
|
package/queries/Base.sol
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { LabeledEvent } from "../events/Labeled.sol";
|
|
6
|
-
import { QueryEvent } from "../events/Query.sol";
|
|
4
|
+
import { EndpointBase } from "../core/Endpoint.sol";
|
|
7
5
|
import { Nodes } from "../utils/Nodes.sol";
|
|
6
|
+
import { Selectors } from "../utils/Selectors.sol";
|
|
8
7
|
|
|
9
8
|
/// @title QueryBase
|
|
10
9
|
/// @notice Abstract base for rootzero query contracts.
|
|
11
10
|
/// Queries are view-only entry points that consume a block-stream request and
|
|
12
11
|
/// return a block-stream response.
|
|
13
|
-
abstract contract QueryBase is
|
|
12
|
+
abstract contract QueryBase is EndpointBase {
|
|
14
13
|
|
|
15
|
-
/// @notice
|
|
16
|
-
///
|
|
17
|
-
///
|
|
18
|
-
/// @param
|
|
19
|
-
/// @
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
/// @notice Publish query metadata and a default label.
|
|
15
|
+
/// @param name Default human-readable query label and selector name.
|
|
16
|
+
/// @param input Packed input lane plus optional group byte.
|
|
17
|
+
/// @param output Packed output lane plus optional group byte.
|
|
18
|
+
/// @param selector Query ABI selector, or zero to derive it from `name`.
|
|
19
|
+
/// @return id Query node ID.
|
|
20
|
+
/// @return descriptor Packed endpoint lane metadata and flags.
|
|
21
|
+
function query(
|
|
22
|
+
string memory name,
|
|
23
|
+
bytes9 input,
|
|
24
|
+
bytes9 output,
|
|
25
|
+
bytes4 selector
|
|
26
|
+
) internal returns (uint id, bytes32 descriptor) {
|
|
27
|
+
selector = selector == bytes4(0) ? Selectors.query(name) : selector;
|
|
28
|
+
id = Nodes.toQuery(selector, address(this));
|
|
29
|
+
descriptor = endpoint(id, name, bytes9(0), input, output, false, false);
|
|
22
30
|
}
|
|
23
31
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
/// @title Selectors
|
|
5
|
+
/// @notice Canonical ABI selector derivation for rootzero endpoint types.
|
|
6
|
+
library Selectors {
|
|
7
|
+
/// @notice Derive the ABI selector for a command entrypoint.
|
|
8
|
+
/// @param name Command function name.
|
|
9
|
+
/// @return Selector for `name((bytes32,bytes,bytes))`.
|
|
10
|
+
function command(string memory name) internal pure returns (bytes4) {
|
|
11
|
+
return derive(name, "((bytes32,bytes,bytes))");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/// @notice Derive the ABI selector for a port entrypoint.
|
|
15
|
+
/// @param name Port function name.
|
|
16
|
+
/// @return Selector for `name(bytes)`.
|
|
17
|
+
function port(string memory name) internal pure returns (bytes4) {
|
|
18
|
+
return direct(name);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// @notice Derive the ABI selector for a query entrypoint.
|
|
22
|
+
/// @param name Query function name.
|
|
23
|
+
/// @return Selector for `name(bytes)`.
|
|
24
|
+
function query(string memory name) internal pure returns (bytes4) {
|
|
25
|
+
return direct(name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// @notice Derive the ABI selector for a guard action entrypoint.
|
|
29
|
+
/// @param name Guard action function name.
|
|
30
|
+
/// @return Selector for `name(bytes)`.
|
|
31
|
+
function guard(string memory name) internal pure returns (bytes4) {
|
|
32
|
+
return direct(name);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// @dev Derive a direct endpoint selector with a single `bytes` argument.
|
|
36
|
+
/// @param name Endpoint function name.
|
|
37
|
+
/// @return Selector for `name(bytes)`.
|
|
38
|
+
function direct(string memory name) private pure returns (bytes4) {
|
|
39
|
+
return derive(name, "(bytes)");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// @dev Derive an ABI selector from a function name and argument signature suffix.
|
|
43
|
+
/// @param name Function name.
|
|
44
|
+
/// @param args Parenthesized ABI argument signature.
|
|
45
|
+
/// @return First four bytes of the function signature hash.
|
|
46
|
+
function derive(string memory name, string memory args) private pure returns (bytes4) {
|
|
47
|
+
return bytes4(keccak256(bytes(string.concat(name, args))));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import { AdminBase, CommandContext, Keys } from "./Base.sol";
|
|
5
|
-
import { Cursors, Cur } from "../../Cursors.sol";
|
|
6
|
-
|
|
7
|
-
using Cursors for Cur;
|
|
8
|
-
|
|
9
|
-
abstract contract DestroyHook {
|
|
10
|
-
/// @notice Override to run host teardown or destruction logic.
|
|
11
|
-
/// @param input Cursor over the full request byte stream.
|
|
12
|
-
function destroy(Cur memory input) internal virtual;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/// @title Destroy
|
|
16
|
-
/// @notice Admin command that runs host teardown logic via a virtual hook.
|
|
17
|
-
/// The full request is passed to `destroy` as a cursor. Only callable by the admin account.
|
|
18
|
-
abstract contract Destroy is AdminBase, DestroyHook {
|
|
19
|
-
uint internal immutable destroyId = commandId(this.destroy.selector);
|
|
20
|
-
|
|
21
|
-
/// @param input Request schema advertised for destruction input.
|
|
22
|
-
constructor(string memory input) {
|
|
23
|
-
emit Admin(host, destroyId, "1:0:0", input, Keys.Empty, Keys.Empty, false);
|
|
24
|
-
emit Labeled(destroyId, bytes32(0), "destroy");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/// @notice Run host teardown logic over the full admin request.
|
|
28
|
-
/// @param c Admin command context; `c.request` is passed through as a cursor.
|
|
29
|
-
/// @return Empty output state.
|
|
30
|
-
function destroy(
|
|
31
|
-
CommandContext calldata c
|
|
32
|
-
) external onlyAdmin(c.account) returns (bytes memory) {
|
|
33
|
-
destroy(Cursors.open(c.request));
|
|
34
|
-
return "";
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|