@rootzero/contracts 1.14.0 → 1.16.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 +100 -0
- package/Codec.sol +1 -1
- package/Commands.sol +1 -1
- package/Core.sol +8 -5
- package/Endpoints.sol +6 -6
- package/Events.sol +1 -3
- package/README.md +118 -35
- package/annotations/Action.sol +17 -0
- package/annotations/Label.sol +23 -0
- package/annotations/Schema.sol +53 -0
- package/codec/Blocks.sol +127 -32
- package/codec/Buffers.sol +3 -3
- package/codec/Decoders.sol +46 -13
- package/codec/Descriptors.sol +0 -1
- package/codec/Keys.sol +8 -4
- package/codec/Readers.sol +13 -0
- package/codec/Schema.sol +12 -3
- package/codec/Specs.sol +28 -4
- package/codec/Writers.sol +21 -6
- package/commands/Base.sol +39 -44
- package/commands/Burn.sol +8 -4
- package/commands/Credit.sol +35 -3
- package/commands/Debit.sol +46 -13
- package/commands/Deposit.sol +14 -8
- package/commands/Payout.sol +6 -2
- package/commands/Provision.sol +4 -4
- package/commands/Recover.sol +15 -8
- package/commands/Relay.sol +37 -12
- package/commands/Settle.sol +77 -0
- package/commands/Withdraw.sol +8 -4
- package/commands/admin/AllowAssets.sol +2 -2
- package/commands/admin/Allowance.sol +2 -2
- package/commands/admin/Annotate.sol +36 -0
- package/commands/admin/Appoint.sol +6 -5
- package/commands/admin/Authorize.sol +2 -2
- package/commands/admin/Base.sol +8 -1
- package/commands/admin/DenyAssets.sol +2 -2
- package/commands/admin/Dismiss.sol +6 -5
- package/commands/admin/Execute.sol +5 -4
- package/commands/admin/Unauthorize.sol +2 -2
- package/core/Access.sol +91 -49
- package/core/Calls.sol +27 -22
- package/core/Endpoint.sol +36 -46
- package/core/Host.sol +63 -21
- package/core/Pipeline.sol +6 -6
- package/core/Settlement.sol +37 -8
- package/core/Types.sol +13 -1
- package/docs/Schema.md +68 -7
- package/events/Annotation.sol +24 -0
- package/events/Guardian.sol +2 -2
- package/events/Introduction.sol +3 -2
- package/execution/Budget.sol +12 -4
- package/execution/Execution.sol +113 -18
- package/guards/Base.sol +4 -4
- package/package.json +1 -1
- package/ports/Base.sol +19 -7
- package/ports/Dispatch.sol +6 -6
- package/ports/{Settle.sol → Post.sol} +13 -9
- package/queries/Base.sol +18 -3
- package/utils/Accounts.sol +0 -23
- package/utils/Actions.sol +1 -0
- package/utils/Cursors.sol +79 -34
- package/utils/Layout.sol +0 -2
- package/commands/admin/Label.sol +0 -36
- package/commands/admin/Schemas.sol +0 -36
- package/events/Labeled.sol +0 -21
- package/events/Position.sol +0 -22
- package/events/Schema.sol +0 -23
package/execution/Execution.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 {AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, Tx} from "../core/Types.sol";
|
|
4
|
+
import {AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, Position, Tx} from "../core/Types.sol";
|
|
5
5
|
import {Blocks} from "../codec/Blocks.sol";
|
|
6
6
|
import {Buffers} from "../codec/Buffers.sol";
|
|
7
7
|
import {Sizes, Specs} from "../codec/Specs.sol";
|
|
@@ -9,6 +9,7 @@ import {Descriptors} from "../codec/Descriptors.sol";
|
|
|
9
9
|
import {Cursors, Cur} from "../utils/Cursors.sol";
|
|
10
10
|
import {Lanes} from "../utils/Lanes.sol";
|
|
11
11
|
import {Budget} from "./Budget.sol";
|
|
12
|
+
import {max16} from "../utils/Utils.sol";
|
|
12
13
|
|
|
13
14
|
/// @notice Mutable state shared across one endpoint execution.
|
|
14
15
|
/// @dev `decoders` contains tagged input and state cursor lanes. Cursor operations
|
|
@@ -28,6 +29,10 @@ library Executions {
|
|
|
28
29
|
|
|
29
30
|
/// @dev Thrown when an execution attempts to spend more value than remains in its budget.
|
|
30
31
|
error InsufficientValue();
|
|
32
|
+
/// @dev Decoder block counts do not form compatible descriptor groups.
|
|
33
|
+
error BadRatio();
|
|
34
|
+
/// @dev A descriptor-empty lane received a non-empty block source.
|
|
35
|
+
error ZeroStride();
|
|
31
36
|
|
|
32
37
|
// -------------------------------------------------------------------------
|
|
33
38
|
// Opening
|
|
@@ -37,15 +42,39 @@ library Executions {
|
|
|
37
42
|
/// @param source Calldata source for the decoder lane.
|
|
38
43
|
/// @param descriptor Packed endpoint descriptor.
|
|
39
44
|
/// @param lane Input or state lane identifier.
|
|
40
|
-
/// @return cur Tagged packed decoder cursor, or zero for an absent lane.
|
|
45
|
+
/// @return cur Tagged packed decoder cursor carrying its raw block count, or zero for an absent lane.
|
|
41
46
|
function openDecoder(bytes calldata source, uint descriptor, uint8 lane) private pure returns (uint cur) {
|
|
42
47
|
uint stride = Descriptors.stride(descriptor, lane);
|
|
43
48
|
(uint abs, uint limit) = Cursors.bounds(source);
|
|
44
49
|
if (stride == 0 && abs == limit) return 0;
|
|
50
|
+
if (stride == 0) revert ZeroStride();
|
|
45
51
|
|
|
46
|
-
bytes4 key =
|
|
47
|
-
(uint
|
|
48
|
-
|
|
52
|
+
bytes4 key = Descriptors.key(descriptor, lane);
|
|
53
|
+
(uint count, uint end) = Blocks.runExact(abs, limit, key);
|
|
54
|
+
if (count == 0) revert Blocks.EmptyRun();
|
|
55
|
+
cur = Cursors.create(abs, end - abs, count, 0, lane);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// @dev Convert one decoder lane's raw block count into descriptor groups.
|
|
59
|
+
function groupCount(uint decoders, uint descriptor, uint8 lane) private pure returns (uint groups) {
|
|
60
|
+
uint stride = Descriptors.stride(descriptor, lane);
|
|
61
|
+
if (stride == 0) return 0;
|
|
62
|
+
|
|
63
|
+
uint count = decoders.select(lane).count();
|
|
64
|
+
if (count % stride != 0) revert BadRatio();
|
|
65
|
+
groups = count / stride;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// @dev Reconcile decoder lane groups once at endpoint execution opening.
|
|
69
|
+
function reconcile(uint decoders, uint descriptor, uint expected) private pure returns (uint groups) {
|
|
70
|
+
uint input = groupCount(decoders, descriptor, Lanes.Input);
|
|
71
|
+
uint state = groupCount(decoders, descriptor, Lanes.State);
|
|
72
|
+
if (input != 0 && state != 0 && input != state) revert BadRatio();
|
|
73
|
+
|
|
74
|
+
groups = input != 0 ? input : state;
|
|
75
|
+
if (groups != 0 && expected != 0 && groups != expected) revert BadRatio();
|
|
76
|
+
if (groups == 0) groups = expected;
|
|
77
|
+
max16(groups);
|
|
49
78
|
}
|
|
50
79
|
|
|
51
80
|
/// @dev Initialize one tagged writer cursor from a descriptor lane.
|
|
@@ -58,7 +87,9 @@ library Executions {
|
|
|
58
87
|
(uint capacity, bool growable) = Descriptors.allocation(descriptor, lane, batches);
|
|
59
88
|
if (capacity == 0) return 0;
|
|
60
89
|
|
|
61
|
-
|
|
90
|
+
uint count = batches * Descriptors.stride(descriptor, lane);
|
|
91
|
+
if (padding != 0) count += padding / Sizes.Transaction;
|
|
92
|
+
cur = Buffers.cursor(capacity + padding, count, growable, lane);
|
|
62
93
|
}
|
|
63
94
|
|
|
64
95
|
/// @dev Open and pair the input and state decoder cursors.
|
|
@@ -91,7 +122,7 @@ library Executions {
|
|
|
91
122
|
function open(uint decoders, uint descriptor, uint batches) private view returns (Execution memory exec) {
|
|
92
123
|
exec.budget = msg.value;
|
|
93
124
|
exec.decoders = decoders;
|
|
94
|
-
batches =
|
|
125
|
+
batches = reconcile(decoders, descriptor, batches);
|
|
95
126
|
exec.writers = writerCursors(descriptor, batches);
|
|
96
127
|
}
|
|
97
128
|
|
|
@@ -166,6 +197,14 @@ library Executions {
|
|
|
166
197
|
exec.decoders = cur.seekAbs(end);
|
|
167
198
|
}
|
|
168
199
|
|
|
200
|
+
/// @notice Require the active execution decoder to be at absolute position `abs`.
|
|
201
|
+
/// @dev The most recent lane-aware decoder operation determines the active lane.
|
|
202
|
+
/// @param exec Execution whose active decoder position is validated.
|
|
203
|
+
/// @param abs Expected absolute position.
|
|
204
|
+
function expectAbs(Execution memory exec, uint abs) internal pure {
|
|
205
|
+
exec.decoders.expectAbs(abs);
|
|
206
|
+
}
|
|
207
|
+
|
|
169
208
|
/// @notice Consume a LIST block and return a cursor scoped to its payload.
|
|
170
209
|
/// @param exec Execution whose decoder is advanced.
|
|
171
210
|
/// @param lane Decoder lane containing the LIST block.
|
|
@@ -286,6 +325,24 @@ library Executions {
|
|
|
286
325
|
(value.asset, value.amount) = unpackBalance(exec, lane);
|
|
287
326
|
}
|
|
288
327
|
|
|
328
|
+
/// @notice Decode and consume one POSITION block from `lane`.
|
|
329
|
+
function unpackPosition(
|
|
330
|
+
Execution memory exec,
|
|
331
|
+
uint8 lane
|
|
332
|
+
) internal pure returns (bytes32 asset, uint amount, bytes32 liability, uint debt) {
|
|
333
|
+
uint abs;
|
|
334
|
+
(exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Position);
|
|
335
|
+
(asset, amount, liability, debt) = Blocks.unpackPosition(abs);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/// @notice Decode one POSITION block into its structured value.
|
|
339
|
+
function unpackPositionValue(
|
|
340
|
+
Execution memory exec,
|
|
341
|
+
uint8 lane
|
|
342
|
+
) internal pure returns (Position memory value) {
|
|
343
|
+
(value.asset, value.amount, value.liability, value.debt) = unpackPosition(exec, lane);
|
|
344
|
+
}
|
|
345
|
+
|
|
289
346
|
/// @notice Decode one BALANCE block and associate it with `host`.
|
|
290
347
|
/// @param exec Execution whose decoder is advanced.
|
|
291
348
|
/// @param lane Decoder lane to consume.
|
|
@@ -520,6 +577,21 @@ library Executions {
|
|
|
520
577
|
exec.decoders = cur.seekAbs(end);
|
|
521
578
|
}
|
|
522
579
|
|
|
580
|
+
/// @notice Decode and consume one ANNOTATION block from `lane`.
|
|
581
|
+
/// @param exec Execution whose decoder is advanced.
|
|
582
|
+
/// @param lane Decoder lane to consume.
|
|
583
|
+
/// @return entity Decoded entity identifier.
|
|
584
|
+
/// @return data Decoded annotation block stream.
|
|
585
|
+
function unpackAnnotation(
|
|
586
|
+
Execution memory exec,
|
|
587
|
+
uint8 lane
|
|
588
|
+
) internal pure returns (uint entity, bytes calldata data) {
|
|
589
|
+
uint cur = exec.decoders.select(lane);
|
|
590
|
+
uint end;
|
|
591
|
+
(entity, data, end) = Blocks.unpackAnnotation(cur.absolute());
|
|
592
|
+
exec.decoders = cur.seekAbs(end);
|
|
593
|
+
}
|
|
594
|
+
|
|
523
595
|
/// @notice Decode and consume one CONTEXT block from `lane`.
|
|
524
596
|
/// @param exec Execution whose decoder is advanced.
|
|
525
597
|
/// @param lane Decoder lane to consume.
|
|
@@ -573,17 +645,16 @@ library Executions {
|
|
|
573
645
|
/// @notice Decode and consume one LABEL block from `lane`.
|
|
574
646
|
/// @param exec Execution whose decoder is advanced.
|
|
575
647
|
/// @param lane Decoder lane to consume.
|
|
576
|
-
/// @return id Decoded node identifier.
|
|
577
648
|
/// @return namespace Decoded label namespace.
|
|
578
649
|
/// @return name Decoded label text.
|
|
579
650
|
function unpackLabel(
|
|
580
651
|
Execution memory exec,
|
|
581
652
|
uint8 lane
|
|
582
|
-
) internal pure returns (
|
|
653
|
+
) internal pure returns (bytes32 namespace, string memory name) {
|
|
583
654
|
uint cur = exec.decoders.select(lane);
|
|
584
655
|
uint abs = cur.absolute();
|
|
585
656
|
uint end;
|
|
586
|
-
(
|
|
657
|
+
(namespace, name, end) = Blocks.unpackLabel(abs);
|
|
587
658
|
exec.decoders = cur.seekAbs(end);
|
|
588
659
|
}
|
|
589
660
|
|
|
@@ -708,6 +779,23 @@ library Executions {
|
|
|
708
779
|
outputBalance(exec, value.asset, value.amount);
|
|
709
780
|
}
|
|
710
781
|
|
|
782
|
+
/// @notice Append a POSITION block to execution output.
|
|
783
|
+
function outputPosition(
|
|
784
|
+
Execution memory exec,
|
|
785
|
+
bytes32 asset,
|
|
786
|
+
uint amount,
|
|
787
|
+
bytes32 liability,
|
|
788
|
+
uint debt
|
|
789
|
+
) internal pure {
|
|
790
|
+
uint i = reserve(exec, Sizes.Position);
|
|
791
|
+
Blocks.writePosition(exec.output, i, asset, amount, liability, debt);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/// @notice Append a structured POSITION value to execution output.
|
|
795
|
+
function outputPosition(Execution memory exec, Position memory value) internal pure {
|
|
796
|
+
outputPosition(exec, value.asset, value.amount, value.liability, value.debt);
|
|
797
|
+
}
|
|
798
|
+
|
|
711
799
|
/// @notice Append an ACCOUNT_ASSET block to execution output.
|
|
712
800
|
/// @param exec Execution receiving the block.
|
|
713
801
|
/// @param account Account identifier to encode.
|
|
@@ -956,13 +1044,12 @@ library Executions {
|
|
|
956
1044
|
|
|
957
1045
|
/// @notice Append a LABEL block to execution output.
|
|
958
1046
|
/// @param exec Execution receiving the block.
|
|
959
|
-
/// @param id Node identifier to encode.
|
|
960
1047
|
/// @param namespace Label namespace to encode.
|
|
961
1048
|
/// @param name Label text to encode.
|
|
962
|
-
function outputLabel(Execution memory exec,
|
|
963
|
-
uint size = Sizes.
|
|
1049
|
+
function outputLabel(Execution memory exec, bytes32 namespace, string memory name) internal pure {
|
|
1050
|
+
uint size = Sizes.B32 + Sizes.Header + bytes(name).length;
|
|
964
1051
|
uint i = reserve(exec, size);
|
|
965
|
-
Blocks.writeLabel(exec.output, i,
|
|
1052
|
+
Blocks.writeLabel(exec.output, i, namespace, name);
|
|
966
1053
|
}
|
|
967
1054
|
|
|
968
1055
|
/// @notice Append a SCHEMA block to execution output.
|
|
@@ -989,15 +1076,23 @@ library Executions {
|
|
|
989
1076
|
exec.budget = 0;
|
|
990
1077
|
}
|
|
991
1078
|
|
|
1079
|
+
/// @notice Deduct an exact native value from the execution budget.
|
|
1080
|
+
/// @param exec Mutable execution whose budget is charged.
|
|
1081
|
+
/// @param value Native value to consume in wei.
|
|
1082
|
+
/// @return The consumed native value.
|
|
1083
|
+
function useValue(Execution memory exec, uint value) internal pure returns (uint) {
|
|
1084
|
+
if (value > exec.budget) revert InsufficientValue();
|
|
1085
|
+
exec.budget -= value;
|
|
1086
|
+
return value;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
992
1089
|
/// @notice Deduct the EVM value lane of `resources` from the execution budget.
|
|
993
1090
|
/// @dev EVM resources use the low 128 bits as native value/endowment.
|
|
994
1091
|
/// @param exec Mutable execution whose budget is charged.
|
|
995
1092
|
/// @param resources Packed resources whose value lane should be spent.
|
|
996
1093
|
/// @return value Native value to forward in wei.
|
|
997
|
-
function
|
|
998
|
-
|
|
999
|
-
if (value > exec.budget) revert InsufficientValue();
|
|
1000
|
-
exec.budget -= value;
|
|
1094
|
+
function useResourceValue(Execution memory exec, uint resources) internal pure returns (uint128) {
|
|
1095
|
+
return uint128(useValue(exec, uint128(resources)));
|
|
1001
1096
|
}
|
|
1002
1097
|
|
|
1003
1098
|
/// @notice Append a deferred transaction to the transaction writer lane.
|
package/guards/Base.sol
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import {InputEndpointBase} from "../core/Endpoint.sol";
|
|
5
|
+
import {GuardianAccess} from "../core/Access.sol";
|
|
6
6
|
import {Specs} from "../codec/Specs.sol";
|
|
7
7
|
import {Nodes} from "../utils/Nodes.sol";
|
|
8
8
|
import {Selectors} from "../utils/Selectors.sol";
|
|
@@ -10,10 +10,10 @@ import {Selectors} from "../utils/Selectors.sol";
|
|
|
10
10
|
/// @title GuardBase
|
|
11
11
|
/// @notice Abstract base for guardian-only direct host actions.
|
|
12
12
|
/// Guard actions are non-payable direct calls with no command context, state, or response.
|
|
13
|
-
abstract contract GuardBase is
|
|
13
|
+
abstract contract GuardBase is GuardianAccess, InputEndpointBase {
|
|
14
14
|
/// @dev Restrict execution to active guardian addresses.
|
|
15
15
|
modifier onlyGuardian() {
|
|
16
|
-
|
|
16
|
+
enforceGuardian(msg.sender);
|
|
17
17
|
_;
|
|
18
18
|
}
|
|
19
19
|
|
package/package.json
CHANGED
package/ports/Base.sol
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import { NodeCalls } from "../core/Calls.sol";
|
|
5
|
+
import { NodeAccess } from "../core/Access.sol";
|
|
5
6
|
import { Specs } from "../codec/Specs.sol";
|
|
6
|
-
import {
|
|
7
|
+
import { InputEndpointBase } from "../core/Endpoint.sol";
|
|
7
8
|
import { Nodes } from "../utils/Nodes.sol";
|
|
8
9
|
import { Selectors } from "../utils/Selectors.sol";
|
|
9
10
|
import { Descriptors } from "../codec/Descriptors.sol";
|
|
@@ -12,14 +13,11 @@ import { Descriptors } from "../codec/Descriptors.sol";
|
|
|
12
13
|
/// @notice Abstract base for peer-facing rootzero ports.
|
|
13
14
|
/// Ports handle inter-host operations between cooperating hosts.
|
|
14
15
|
/// Access is restricted to trusted peer callers via `onlyPeer`.
|
|
15
|
-
abstract contract PortBase is NodeCalls,
|
|
16
|
-
/// @dev Thrown when the commander attempts to call a port entrypoint directly.
|
|
17
|
-
error CommanderNotAllowed();
|
|
16
|
+
abstract contract PortBase is NodeCalls, NodeAccess, InputEndpointBase {
|
|
18
17
|
|
|
19
18
|
/// @dev Restrict execution to trusted callers, excluding the commander.
|
|
20
19
|
modifier onlyPeer() {
|
|
21
|
-
|
|
22
|
-
enforceCaller(msg.sender);
|
|
20
|
+
enforcePeer(msg.sender);
|
|
23
21
|
_;
|
|
24
22
|
}
|
|
25
23
|
|
|
@@ -44,7 +42,21 @@ abstract contract PortBase is NodeCalls, EndpointBase {
|
|
|
44
42
|
uint output,
|
|
45
43
|
bool funded
|
|
46
44
|
) internal returns (uint id, uint descriptor) {
|
|
45
|
+
descriptor = Descriptors.create(Specs.Empty, input, output, 0, funded ? Descriptors.Funded : 0);
|
|
46
|
+
return port(name, descriptor);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// @notice Publish an already constructed port descriptor and default label.
|
|
50
|
+
/// @param name Port entrypoint name and default label. It must exactly
|
|
51
|
+
/// match the Solidity port function name used by the canonical ABI.
|
|
52
|
+
/// @param descriptor Packed port endpoint descriptor.
|
|
53
|
+
/// @return id Port node ID.
|
|
54
|
+
/// @return published Published endpoint descriptor.
|
|
55
|
+
function port(
|
|
56
|
+
string memory name,
|
|
57
|
+
uint descriptor
|
|
58
|
+
) internal returns (uint id, uint published) {
|
|
47
59
|
id = Nodes.toPort(Selectors.port(name), address(this));
|
|
48
|
-
|
|
60
|
+
published = endpoint(id, name, descriptor);
|
|
49
61
|
}
|
|
50
62
|
}
|
package/ports/Dispatch.sol
CHANGED
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
|
-
import {
|
|
5
|
+
import {RelayPayableHook} from "../commands/Relay.sol";
|
|
6
6
|
import {Specs} from "../Codec.sol";
|
|
7
7
|
import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
8
8
|
|
|
9
9
|
using Executions for Execution;
|
|
10
10
|
|
|
11
11
|
/// @title PortDispatchPayable
|
|
12
|
-
/// @notice Port endpoint that forwards DISPATCH blocks to a host-defined
|
|
13
|
-
abstract contract PortDispatchPayable is PortBase,
|
|
12
|
+
/// @notice Port endpoint that forwards DISPATCH blocks to a host-defined relay hook.
|
|
13
|
+
abstract contract PortDispatchPayable is PortBase, RelayPayableHook {
|
|
14
14
|
uint private immutable descriptor;
|
|
15
15
|
|
|
16
16
|
constructor() {
|
|
17
17
|
(, descriptor) = port("portDispatchPayable", Specs.Dispatch, Specs.Empty, true);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
/// @notice Forward peer-supplied dispatches to the host-defined
|
|
21
|
-
/// @dev
|
|
20
|
+
/// @notice Forward peer-supplied dispatches to the host-defined relay hook.
|
|
21
|
+
/// @dev Relay hooks receive the shared top-level source value
|
|
22
22
|
/// budget. Any `msg.value` not spent by the hook remains on this host.
|
|
23
23
|
/// @param data DISPATCH block stream supplied by the trusted peer.
|
|
24
24
|
/// @return Empty response bytes.
|
|
@@ -27,7 +27,7 @@ abstract contract PortDispatchPayable is PortBase, RoutePayableHook {
|
|
|
27
27
|
|
|
28
28
|
while (exec.more()) {
|
|
29
29
|
(uint portal, uint resources, bytes calldata payload) = exec.unpackDispatch(Lanes.Input);
|
|
30
|
-
|
|
30
|
+
relayTo(portal, resources, bytes(payload), exec);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
return "";
|
|
@@ -2,33 +2,37 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
|
-
import {
|
|
5
|
+
import {PostHook} from "../core/Settlement.sol";
|
|
6
6
|
import {Specs} from "../Codec.sol";
|
|
7
7
|
import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
8
|
+
import {Action} from "../annotations/Action.sol";
|
|
9
|
+
import {Actions} from "../utils/Actions.sol";
|
|
8
10
|
|
|
9
11
|
using Executions for Execution;
|
|
10
12
|
|
|
11
|
-
/// @title
|
|
12
|
-
/// @notice Port that
|
|
13
|
+
/// @title PortPost
|
|
14
|
+
/// @notice Port that posts peer-supplied TRANSACTION blocks through debit and credit hooks.
|
|
13
15
|
/// Each TRANSACTION block calls `debitAccount` for `from` and `creditAccount` for `to`.
|
|
14
|
-
abstract contract
|
|
16
|
+
abstract contract PortPost is PortBase, PostHook, Action {
|
|
15
17
|
uint private immutable descriptor;
|
|
16
18
|
|
|
17
19
|
constructor() {
|
|
18
|
-
|
|
20
|
+
uint id;
|
|
21
|
+
(id, descriptor) = port("portPost", Specs.Transaction, Specs.Empty, false);
|
|
22
|
+
action(id, Actions.Post);
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
/// @notice
|
|
25
|
+
/// @notice Post peer-supplied transactions.
|
|
22
26
|
/// @param data TRANSACTION block stream supplied by the trusted peer.
|
|
23
27
|
/// @return Empty response bytes.
|
|
24
|
-
function
|
|
28
|
+
function portPost(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
25
29
|
Execution memory exec = openInput(data, descriptor, 0);
|
|
26
30
|
|
|
27
31
|
while (exec.more()) {
|
|
28
32
|
(bytes32 from, bytes32 to, bytes32 asset, uint amount) = exec.unpackTransaction(Lanes.Input);
|
|
29
|
-
|
|
33
|
+
post(from, to, asset, amount);
|
|
30
34
|
}
|
|
31
|
-
|
|
35
|
+
|
|
32
36
|
return "";
|
|
33
37
|
}
|
|
34
38
|
}
|
package/queries/Base.sol
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { InputEndpointBase } from "../core/Endpoint.sol";
|
|
5
|
+
import { Descriptors } from "../codec/Descriptors.sol";
|
|
5
6
|
import { Specs } from "../codec/Specs.sol";
|
|
6
7
|
import { Nodes } from "../utils/Nodes.sol";
|
|
7
8
|
import { Selectors } from "../utils/Selectors.sol";
|
|
@@ -10,7 +11,7 @@ import { Selectors } from "../utils/Selectors.sol";
|
|
|
10
11
|
/// @notice Abstract base for rootzero query contracts.
|
|
11
12
|
/// Queries are view-only entry points that consume a block-stream input and
|
|
12
13
|
/// return a block-stream response.
|
|
13
|
-
abstract contract QueryBase is
|
|
14
|
+
abstract contract QueryBase is InputEndpointBase {
|
|
14
15
|
|
|
15
16
|
/// @notice Publish query metadata and a default label.
|
|
16
17
|
/// @param name Query entrypoint name and default label. It must exactly
|
|
@@ -24,7 +25,21 @@ abstract contract QueryBase is EndpointBase {
|
|
|
24
25
|
uint input,
|
|
25
26
|
uint output
|
|
26
27
|
) internal returns (uint id, uint descriptor) {
|
|
28
|
+
descriptor = Descriptors.create(Specs.Empty, input, output, 0, 0);
|
|
29
|
+
return query(name, descriptor);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// @notice Publish an already constructed query descriptor and default label.
|
|
33
|
+
/// @param name Query entrypoint name and default label. It must exactly
|
|
34
|
+
/// match the Solidity query function name used by the canonical ABI.
|
|
35
|
+
/// @param descriptor Packed query endpoint descriptor.
|
|
36
|
+
/// @return id Query node ID.
|
|
37
|
+
/// @return published Published endpoint descriptor.
|
|
38
|
+
function query(
|
|
39
|
+
string memory name,
|
|
40
|
+
uint descriptor
|
|
41
|
+
) internal returns (uint id, uint published) {
|
|
27
42
|
id = Nodes.toQuery(Selectors.query(name), address(this));
|
|
28
|
-
|
|
43
|
+
published = endpoint(id, name, descriptor);
|
|
29
44
|
}
|
|
30
45
|
}
|
package/utils/Accounts.sol
CHANGED
|
@@ -10,7 +10,6 @@ import {ensureAddr, isFamily, toLocalBase, toUnspecifiedBase} from "./Utils.sol"
|
|
|
10
10
|
///
|
|
11
11
|
/// Account IDs embed a 4-byte type tag in bits [255:224]:
|
|
12
12
|
/// - `Admin` — chain-local EVM address in bits [191:32]
|
|
13
|
-
/// - `Guardian` — chain-local EVM address in bits [191:32]
|
|
14
13
|
/// - `User` — chain-agnostic EVM address in bits [191:32]
|
|
15
14
|
///
|
|
16
15
|
/// If the first byte is zero, the account is an opaque
|
|
@@ -26,8 +25,6 @@ library Accounts {
|
|
|
26
25
|
uint24 constant Family = (uint24(Layout.Evm) << 8) | uint24(Layout.Account);
|
|
27
26
|
/// @dev Full 4-byte type prefix for admin accounts (chain-local EVM address).
|
|
28
27
|
uint32 constant Admin = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Admin);
|
|
29
|
-
/// @dev Full 4-byte type prefix for guardian accounts (chain-local EVM address).
|
|
30
|
-
uint32 constant Guardian = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Guardian);
|
|
31
28
|
/// @dev Full 4-byte type prefix for user accounts (chain-agnostic EVM address).
|
|
32
29
|
uint32 constant User = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.User);
|
|
33
30
|
|
|
@@ -53,11 +50,6 @@ library Accounts {
|
|
|
53
50
|
return prefix(account) == Admin;
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
/// @notice Return true if `account` is a guardian account.
|
|
57
|
-
function isGuardian(bytes32 account) internal pure returns (bool) {
|
|
58
|
-
return prefix(account) == Guardian;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
53
|
/// @notice Return true if `account` is a user account.
|
|
62
54
|
function isUser(bytes32 account) internal pure returns (bool) {
|
|
63
55
|
return prefix(account) == User;
|
|
@@ -87,14 +79,6 @@ library Accounts {
|
|
|
87
79
|
return value;
|
|
88
80
|
}
|
|
89
81
|
|
|
90
|
-
/// @notice Assert that `value` is a guardian account and return it unchanged.
|
|
91
|
-
/// @param value Account identifier to validate.
|
|
92
|
-
/// @return account The same `value` if it is a guardian account.
|
|
93
|
-
function guardian(bytes32 value) internal pure returns (bytes32 account) {
|
|
94
|
-
if (!isGuardian(value)) revert InvalidAccount();
|
|
95
|
-
return value;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
82
|
/// @notice Assert that `value` is a user account and return it unchanged.
|
|
99
83
|
/// @param value Account identifier to validate.
|
|
100
84
|
/// @return account The same `value` if it is a user account.
|
|
@@ -110,13 +94,6 @@ library Accounts {
|
|
|
110
94
|
return bytes32(toLocalBase(Admin) | (uint(uint160(account)) << 32));
|
|
111
95
|
}
|
|
112
96
|
|
|
113
|
-
/// @notice Encode an EVM address as a chain-local guardian account ID.
|
|
114
|
-
/// @param account EVM address to embed.
|
|
115
|
-
/// @return Guardian account ID bound to the current chain.
|
|
116
|
-
function toGuardian(address account) internal view returns (bytes32) {
|
|
117
|
-
return bytes32(toLocalBase(Guardian) | (uint(uint160(account)) << 32));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
97
|
/// @notice Encode an EVM address as a chain-agnostic user account ID.
|
|
121
98
|
/// @param account EVM address to embed.
|
|
122
99
|
/// @return User account ID without a chain binding.
|