@rootzero/contracts 1.15.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/Codec.sol +1 -1
  3. package/Commands.sol +1 -1
  4. package/Core.sol +2 -2
  5. package/Endpoints.sol +5 -4
  6. package/Events.sol +0 -1
  7. package/README.md +82 -28
  8. package/codec/Blocks.sol +79 -21
  9. package/codec/Buffers.sol +3 -3
  10. package/codec/Decoders.sol +31 -10
  11. package/codec/Descriptors.sol +0 -1
  12. package/codec/Keys.sol +2 -2
  13. package/codec/Readers.sol +13 -0
  14. package/codec/Schema.sol +5 -1
  15. package/codec/Specs.sol +4 -2
  16. package/codec/Writers.sol +19 -2
  17. package/commands/Base.sol +6 -15
  18. package/commands/Burn.sol +2 -2
  19. package/commands/Credit.sol +35 -3
  20. package/commands/Debit.sol +46 -13
  21. package/commands/Deposit.sol +4 -4
  22. package/commands/Provision.sol +4 -4
  23. package/commands/Recover.sol +15 -8
  24. package/commands/Relay.sol +37 -12
  25. package/commands/Settle.sol +77 -0
  26. package/commands/Withdraw.sol +2 -2
  27. package/commands/admin/AllowAssets.sol +2 -2
  28. package/commands/admin/Allowance.sol +2 -2
  29. package/commands/admin/Annotate.sol +2 -2
  30. package/commands/admin/Appoint.sol +2 -2
  31. package/commands/admin/Authorize.sol +2 -2
  32. package/commands/admin/DenyAssets.sol +2 -2
  33. package/commands/admin/Dismiss.sol +2 -2
  34. package/commands/admin/Execute.sol +3 -3
  35. package/commands/admin/Unauthorize.sol +2 -2
  36. package/core/Endpoint.sol +15 -13
  37. package/core/Pipeline.sol +6 -6
  38. package/core/Settlement.sol +37 -8
  39. package/core/Types.sol +13 -1
  40. package/docs/Schema.md +52 -2
  41. package/execution/Budget.sol +12 -4
  42. package/execution/Execution.sol +85 -11
  43. package/guards/Base.sol +2 -2
  44. package/package.json +1 -1
  45. package/ports/Base.sol +2 -2
  46. package/ports/Dispatch.sol +6 -6
  47. package/ports/{Settle.sol → Post.sol} +10 -10
  48. package/queries/Base.sol +2 -2
  49. package/utils/Actions.sol +1 -0
  50. package/utils/Cursors.sol +16 -30
  51. package/events/Position.sol +0 -22
package/codec/Specs.sol CHANGED
@@ -31,6 +31,8 @@ library Sizes {
31
31
  uint constant HostAmount = B96;
32
32
  /// @dev TRANSACTION block: 8 header + 32 from + 32 to + 32 asset + 32 amount = 136 bytes
33
33
  uint constant Transaction = B128;
34
+ /// @dev POSITION block: 8 header + four-word asset-liability pair = 136 bytes
35
+ uint constant Position = B128;
34
36
  }
35
37
 
36
38
  /// @title Specs
@@ -44,7 +46,6 @@ library Specs {
44
46
  error InvalidSpec();
45
47
  /// @dev A direct specification cannot contain a wrapper block.
46
48
  error InvalidContainer();
47
-
48
49
  uint private constant SizeFields = (uint(1) << 192) | (uint(1) << 160) | (uint(1) << 136);
49
50
 
50
51
  // Reusable field shapes keep public specs readable while remaining valid
@@ -60,12 +61,12 @@ library Specs {
60
61
  uint private constant UnboundedMin104Hint256 = (uint(104) << 192) | (uint(256) << 136);
61
62
 
62
63
  uint constant Empty = uint(bytes32(Keys.Empty));
63
- uint constant Any = uint(bytes32(Keys.Any)) | UnboundedHint128;
64
64
  uint constant Amount = uint(bytes32(Keys.Amount)) | Exact64;
65
65
  uint constant Balance = uint(bytes32(Keys.Balance)) | Exact64;
66
66
  uint constant Allocation = uint(bytes32(Keys.Allocation)) | Exact96;
67
67
  uint constant Allowance = uint(bytes32(Keys.Allowance)) | Exact96;
68
68
  uint constant Custody = uint(bytes32(Keys.Custody)) | Exact96;
69
+ uint constant Position = uint(bytes32(Keys.Position)) | Exact128;
69
70
  uint constant List = uint(bytes32(Keys.List)) | UnboundedHint128;
70
71
  uint constant Evm = uint(bytes32(Keys.Evm)) | UnboundedHint128;
71
72
  uint constant Bytes = uint(bytes32(Keys.Bytes)) | UnboundedHint128;
@@ -237,4 +238,5 @@ library Specs {
237
238
  function group(uint spec, uint8 n) internal pure returns (uint) {
238
239
  return replace8(spec, 128, n);
239
240
  }
241
+
240
242
  }
package/codec/Writers.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, AccountAmount, HostAmount, Tx} from "../core/Types.sol";
4
+ import {AssetAmount, AccountAmount, HostAmount, Position, Tx} from "../core/Types.sol";
5
5
  import {Blocks} from "./Blocks.sol";
6
6
  import {Buffers} from "./Buffers.sol";
7
7
  import {Sizes, Specs} from "./Specs.sol";
@@ -44,7 +44,7 @@ library Writers {
44
44
  (uint capacity, bool growable) = Specs.allocation(spec, groups);
45
45
  if (capacity == 0) return writer;
46
46
 
47
- writer.cur = Buffers.cursor(capacity, groups, growable, 0);
47
+ writer.cur = Buffers.cursor(capacity, Specs.count(spec, groups), growable, 0);
48
48
  }
49
49
 
50
50
  // -------------------------------------------------------------------------
@@ -291,6 +291,23 @@ library Writers {
291
291
  Blocks.writeHostAccountAsset(writer.dst, i, host, account, asset);
292
292
  }
293
293
 
294
+ /// @notice Append a POSITION block.
295
+ function appendPosition(
296
+ Writer memory writer,
297
+ bytes32 asset,
298
+ uint amount,
299
+ bytes32 liability,
300
+ uint debt
301
+ ) internal pure {
302
+ uint i = reserve(writer, Sizes.Position);
303
+ Blocks.writePosition(writer.dst, i, asset, amount, liability, debt);
304
+ }
305
+
306
+ /// @notice Append a structured POSITION value.
307
+ function appendPosition(Writer memory writer, Position memory value) internal pure {
308
+ appendPosition(writer, value.asset, value.amount, value.liability, value.debt);
309
+ }
310
+
294
311
  /// @notice Append a TRANSACTION block.
295
312
  /// @param writer Destination writer.
296
313
  /// @param from Debit account identifier.
package/commands/Base.sol CHANGED
@@ -5,7 +5,7 @@ import {CallerAccess} from "../core/Access.sol";
5
5
  import {EndpointBase} from "../core/Endpoint.sol";
6
6
  import {Blocks} from "../codec/Blocks.sol";
7
7
  import {Specs} from "../codec/Specs.sol";
8
- import {HostAmount} from "../core/Types.sol";
8
+ import {HostAmount, Position} from "../core/Types.sol";
9
9
  import {Execution, Executions, Lanes} from "../execution/Execution.sol";
10
10
  import {ReceivedEvent} from "../events/Received.sol";
11
11
  import {Actions} from "../utils/Actions.sol";
@@ -74,20 +74,11 @@ abstract contract CommandBase is CallerAccess, EndpointBase, ReceivedEvent {
74
74
  published = endpoint(id, name, descriptor);
75
75
  }
76
76
 
77
- /// @notice Open a command state stream and return the expected output block count.
78
- /// @param source State block stream to open.
79
- /// @param descriptor Packed command endpoint descriptor.
80
- /// @param batches Required batch count, or zero to accept the state count.
81
- /// @return exec Execution with its output buffer metadata initialized for the state batch count.
82
- function openState(
83
- bytes calldata source,
84
- uint descriptor,
85
- uint batches
86
- ) internal view returns (Execution memory exec) {
87
- return Executions.openState(source, descriptor, batches);
88
- }
89
-
90
- /// @notice Open a command execution with batches derived from its input and state lanes.
77
+ /// @notice Open and validate both command lanes, including lanes declared EMPTY.
78
+ /// Batches are derived from the input and state lanes. A non-empty stream for
79
+ /// a lane whose descriptor has zero stride reverts instead of being ignored.
80
+ /// Commands must account for the complete validated state by consuming it,
81
+ /// transforming and returning it, forwarding it intact, or reverting.
91
82
  /// @param state Current command state block stream.
92
83
  /// @param input Command input block stream.
93
84
  /// @param descriptor Packed command endpoint descriptor.
package/commands/Burn.sol CHANGED
@@ -36,9 +36,9 @@ abstract contract Burn is CommandBase, BurnHook, Action {
36
36
  function burn(
37
37
  bytes32 account,
38
38
  bytes calldata state,
39
- bytes calldata
39
+ bytes calldata input
40
40
  ) external onlyCommand returns (bytes memory, bytes memory) {
41
- Execution memory exec = openState(state, descriptor, 0);
41
+ Execution memory exec = openCommand(state, input, descriptor, 0);
42
42
 
43
43
  while (exec.more()) {
44
44
  (bytes32 asset, uint amount) = exec.unpackBalance(Lanes.State);
@@ -3,12 +3,15 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import {Execution, Executions, CommandBase, Lanes, Specs} from "./Base.sol";
5
5
  import {CreditAccountHook} from "../core/Settlement.sol";
6
+ import {Blocks} from "../codec/Blocks.sol";
7
+ import {Reader, Readers} from "../codec/Readers.sol";
6
8
 
7
9
  using Executions for Execution;
10
+ using Readers for Reader;
8
11
 
9
12
  /// @title CreditAccount
10
13
  /// @notice Command that delivers BALANCE state blocks to an account via a virtual hook.
11
- /// Use for internally recording credits that have already been settled externally.
14
+ /// Use for internally recording credits that have already been posted externally.
12
15
  abstract contract CreditAccount is CommandBase, CreditAccountHook {
13
16
  uint private immutable descriptor;
14
17
  uint private immutable id;
@@ -29,9 +32,9 @@ abstract contract CreditAccount is CommandBase, CreditAccountHook {
29
32
  function creditAccount(
30
33
  bytes32 account,
31
34
  bytes calldata state,
32
- bytes calldata
35
+ bytes calldata input
33
36
  ) external onlyCommand returns (bytes memory, bytes memory) {
34
- Execution memory exec = openState(state, descriptor, 0);
37
+ Execution memory exec = openCommand(state, input, descriptor, 0);
35
38
 
36
39
  while (exec.more()) {
37
40
  (bytes32 asset, uint amount) = exec.unpackBalance(Lanes.State);
@@ -41,3 +44,32 @@ abstract contract CreditAccount is CommandBase, CreditAccountHook {
41
44
  return close(exec, account);
42
45
  }
43
46
  }
47
+
48
+ /// @title InternalCreditAccount
49
+ /// @notice Extends the advertised credit-account command with memory-state pipeline dispatch.
50
+ /// @dev This adapter is not a separate command. It uses the command ID and account hook
51
+ /// inherited from `CreditAccount` while accepting the state location used by `Pipeline`.
52
+ abstract contract InternalCreditAccount is CreditAccount {
53
+ /// @notice Execute the inherited credit-account command from an internal pipeline.
54
+ /// @param account Account credited by each balance.
55
+ /// @param state BALANCE block stream held in pipeline memory.
56
+ /// @param input Empty input required by the command schema.
57
+ /// @return output Empty output state.
58
+ /// @return transactions Empty transaction stream.
59
+ function executeCreditAccount(
60
+ bytes32 account,
61
+ bytes memory state,
62
+ bytes calldata input
63
+ ) internal returns (bytes memory, bytes memory) {
64
+ if (input.length != 0) revert Executions.ZeroStride();
65
+ if (state.length == 0) revert Blocks.EmptyRun();
66
+
67
+ Reader memory reader = Readers.open(state);
68
+ while (reader.more()) {
69
+ (bytes32 asset, uint amount) = reader.unpackBalance();
70
+ creditAccount(account, asset, amount);
71
+ }
72
+
73
+ return ("", "");
74
+ }
75
+ }
@@ -3,13 +3,18 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import {Execution, Executions, CommandBase, Lanes, Specs} from "./Base.sol";
5
5
  import {DebitAccountHook} from "../core/Settlement.sol";
6
+ import {Blocks} from "../codec/Blocks.sol";
7
+ import {Sizes} from "../codec/Specs.sol";
8
+ import {Decoders} from "../codec/Decoders.sol";
9
+ import {Cur} from "../utils/Cursors.sol";
6
10
 
7
11
  using Executions for Execution;
12
+ using Decoders for Cur;
8
13
 
9
14
  /// @title DebitAccount
10
15
  /// @notice Command that deducts AMOUNT blocks from an account and emits matching BALANCE state.
11
16
  /// Use for internally recording debits. The virtual `debitAccount` hook is called once per
12
- /// AMOUNT block; the default batch implementation handles the full input loop.
17
+ /// AMOUNT block.
13
18
  abstract contract DebitAccount is CommandBase, DebitAccountHook {
14
19
  uint private immutable descriptor;
15
20
  uint private immutable id;
@@ -23,11 +28,16 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
23
28
  return id;
24
29
  }
25
30
 
26
- /// @notice Override to customize input parsing or batching for debits.
27
- /// The default implementation iterates AMOUNT blocks, calls
28
- /// `debitAccount`, and emits matching BALANCE blocks.
29
- function debitAccount(bytes32 account, bytes calldata input) internal virtual returns (bytes memory, bytes memory) {
30
- Execution memory exec = openInput(input, descriptor, 0);
31
+ /// @notice Debit AMOUNT input blocks from the command account and output matching BALANCE blocks.
32
+ /// @param input AMOUNT block stream.
33
+ /// @return BALANCE block stream matching the debited amounts.
34
+ /// @return Empty transaction stream.
35
+ function debitAccount(
36
+ bytes32 account,
37
+ bytes calldata state,
38
+ bytes calldata input
39
+ ) external onlyCommand returns (bytes memory, bytes memory) {
40
+ Execution memory exec = openCommand(state, input, descriptor, 0);
31
41
 
32
42
  while (exec.more()) {
33
43
  (bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
@@ -37,16 +47,39 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
37
47
 
38
48
  return close(exec, account);
39
49
  }
50
+ }
40
51
 
41
- /// @notice Debit AMOUNT input blocks from the command account and output matching BALANCE blocks.
52
+ /// @title InternalDebitAccount
53
+ /// @notice Extends the advertised debit-account command with memory-state pipeline dispatch.
54
+ /// @dev This adapter is not a separate command. It uses the command ID and account hook
55
+ /// inherited from `DebitAccount` while accepting the state location used by `Pipeline`.
56
+ abstract contract InternalDebitAccount is DebitAccount {
57
+ /// @notice Execute the inherited debit-account command from an internal pipeline.
58
+ /// @param account Account whose funds are debited.
59
+ /// @param state Empty pipeline state required by the command schema.
42
60
  /// @param input AMOUNT block stream.
43
- /// @return BALANCE block stream matching the debited amounts.
44
- /// @return Empty transaction stream.
45
- function debitAccount(
61
+ /// @return output BALANCE block stream matching the debited amounts.
62
+ /// @return transactions Empty transaction stream.
63
+ function executeDebitAccount(
46
64
  bytes32 account,
47
- bytes calldata,
65
+ bytes memory state,
48
66
  bytes calldata input
49
- ) external onlyCommand returns (bytes memory, bytes memory) {
50
- return debitAccount(account, input);
67
+ ) internal returns (bytes memory, bytes memory) {
68
+ if (state.length != 0) revert Executions.ZeroStride();
69
+ if (input.length == 0) revert Blocks.EmptyRun();
70
+
71
+ Cur memory cur = Decoders.wrap(input);
72
+ uint count = input.length / Sizes.Amount;
73
+ bytes memory output = new bytes(count * Sizes.Balance);
74
+ uint i;
75
+
76
+ while (cur.more()) {
77
+ (bytes32 asset, uint amount) = cur.unpackAmount();
78
+ debitAccount(account, asset, amount);
79
+ Blocks.writeBalance(output, i, asset, amount);
80
+ i += Sizes.Balance;
81
+ }
82
+
83
+ return (output, "");
51
84
  }
52
85
  }
@@ -49,10 +49,10 @@ abstract contract Deposit is CommandBase, DepositHook, Action {
49
49
  /// @return Empty transaction stream.
50
50
  function deposit(
51
51
  bytes32 account,
52
- bytes calldata,
52
+ bytes calldata state,
53
53
  bytes calldata input
54
54
  ) external onlyCommand returns (bytes memory, bytes memory) {
55
- Execution memory exec = openInput(input, descriptor, 0);
55
+ Execution memory exec = openCommand(state, input, descriptor, 0);
56
56
 
57
57
  while (exec.more()) {
58
58
  (bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
@@ -82,10 +82,10 @@ abstract contract DepositPayable is CommandBase, DepositPayableHook, Action {
82
82
  /// @return Remaining native value as a refund transaction stream.
83
83
  function depositPayable(
84
84
  bytes32 account,
85
- bytes calldata,
85
+ bytes calldata state,
86
86
  bytes calldata input
87
87
  ) external payable onlyCommand returns (bytes memory, bytes memory) {
88
- Execution memory exec = openInput(input, descriptor, 0);
88
+ Execution memory exec = openCommand(state, input, descriptor, 0);
89
89
 
90
90
  while (exec.more()) {
91
91
  (bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
@@ -41,10 +41,10 @@ abstract contract Provision is CommandBase, ProvisionHook {
41
41
  /// @return Empty transaction stream.
42
42
  function provision(
43
43
  bytes32 account,
44
- bytes calldata,
44
+ bytes calldata state,
45
45
  bytes calldata input
46
46
  ) external onlyCommand returns (bytes memory, bytes memory) {
47
- Execution memory exec = openInput(input, descriptor, 0);
47
+ Execution memory exec = openCommand(state, input, descriptor, 0);
48
48
 
49
49
  while (exec.more()) {
50
50
  HostAmount memory allocation = exec.unpackAllocationValue(Lanes.Input);
@@ -73,10 +73,10 @@ abstract contract ProvisionPayable is CommandBase, ProvisionPayableHook {
73
73
  /// @return Remaining native value as a refund transaction stream.
74
74
  function provisionPayable(
75
75
  bytes32 account,
76
- bytes calldata,
76
+ bytes calldata state,
77
77
  bytes calldata input
78
78
  ) external payable onlyCommand returns (bytes memory, bytes memory) {
79
- Execution memory exec = openInput(input, descriptor, 0);
79
+ Execution memory exec = openCommand(state, input, descriptor, 0);
80
80
 
81
81
  while (exec.more()) {
82
82
  HostAmount memory allocation = exec.unpackAllocationValue(Lanes.Input);
@@ -6,21 +6,28 @@ import {Execution, Executions, CommandBase, Lanes, Specs} from "./Base.sol";
6
6
  using Executions for Execution;
7
7
 
8
8
  /// @notice Hook implemented by hosts that recover previously undelivered payloads.
9
- abstract contract RecoverHook {
9
+ abstract contract RecoverPayableHook {
10
10
  /// @notice Override to recover a witness through `handler`.
11
11
  /// @param handler Port that should attempt recovery.
12
+ /// @param resources Chain-specific resources assigned to the recovery attempt.
12
13
  /// @param key Recovery lookup key.
13
14
  /// @param witness Witness payload used to prove and replay recovery.
14
- /// @param value Native EVM value assigned to the recovery attempt.
15
- function recover(uint handler, bytes32 key, bytes calldata witness, uint128 value) internal virtual;
15
+ /// @param funds Shared execution containing the source value budget.
16
+ function recover(
17
+ uint handler,
18
+ uint resources,
19
+ bytes32 key,
20
+ bytes calldata witness,
21
+ Execution memory funds
22
+ ) internal virtual;
16
23
  }
17
24
 
18
25
  /// @title RecoverPayable
19
26
  /// @notice Command that forwards recover input blocks to a virtual hook.
20
27
  /// Recovery is witness-driven: the command account pays and receives leftover
21
- /// value settlement, but the recovered subject is defined by each witness.
28
+ /// value posting, but the recovered subject is defined by each witness.
22
29
  /// Produces no output state.
23
- abstract contract RecoverPayable is CommandBase, RecoverHook {
30
+ abstract contract RecoverPayable is CommandBase, RecoverPayableHook {
24
31
  uint private immutable descriptor;
25
32
 
26
33
  constructor() {
@@ -33,14 +40,14 @@ abstract contract RecoverPayable is CommandBase, RecoverHook {
33
40
  /// @return Remaining native value as a refund transaction stream.
34
41
  function recoverPayable(
35
42
  bytes32 account,
36
- bytes calldata,
43
+ bytes calldata state,
37
44
  bytes calldata input
38
45
  ) external payable onlyCommand returns (bytes memory, bytes memory) {
39
- Execution memory exec = openInput(input, descriptor, 0);
46
+ Execution memory exec = openCommand(state, input, descriptor, 0);
40
47
 
41
48
  while (exec.more()) {
42
49
  (uint handler, uint resources, bytes32 key, bytes calldata witness) = exec.unpackRecover(Lanes.Input);
43
- recover(handler, key, witness, exec.useValue(resources));
50
+ recover(handler, resources, key, witness, exec);
44
51
  }
45
52
 
46
53
  return close(exec, account);
@@ -5,28 +5,53 @@ import {Blocks, Execution, Executions, CommandBase, Lanes, Specs} from "./Base.s
5
5
 
6
6
  using Executions for Execution;
7
7
 
8
- /// @notice Hook implemented by hosts that route funded relay payloads.
9
- abstract contract RoutePayableHook {
10
- /// @notice Override to route an encoded payload through `portal`.
8
+ /// @notice Hook implemented by hosts that forward funded relay payloads.
9
+ abstract contract RelayPayableHook {
10
+ /// @notice Override to relay an encoded payload to `portal`.
11
11
  /// @param portal Destination portal identifier, often the destination host ID.
12
12
  /// @param resources Chain-specific destination resources. EVM adapters
13
13
  /// may interpret this as packed execution gas and destination value.
14
14
  /// @param payload Encoded payload ready for the transport layer.
15
- /// @param funds Execution used only for source value available for transport
16
- /// fees and destination resource funding.
17
- function route(uint portal, uint resources, bytes memory payload, Execution memory funds) internal virtual;
15
+ /// @param funds Execution used for source value available for transport fees
16
+ /// and destination resource funding.
17
+ function relayTo(uint portal, uint resources, bytes memory payload, Execution memory funds) internal virtual;
18
18
  }
19
19
 
20
20
  /// @title RelayPayable
21
- /// @notice Command that forwards one RELAY block to a host-defined relay hook.
21
+ /// @notice Command that forwards one RELAY block without pipeline state.
22
+ abstract contract RelayPayable is CommandBase, RelayPayableHook {
23
+ uint private immutable descriptor;
24
+
25
+ constructor() {
26
+ (, descriptor) = command("relayPayable", Specs.Empty, Specs.Relay, Specs.Empty, 0, true, false);
27
+ }
28
+
29
+ /// @notice Relay one RELAY input block with the command account and empty state.
30
+ function relayPayable(
31
+ bytes32 account,
32
+ bytes calldata state,
33
+ bytes calldata input
34
+ ) external payable onlyCommand returns (bytes memory, bytes memory) {
35
+ Execution memory exec = openCommand(state, input, descriptor, 1);
36
+ (uint portal, uint resources, bytes calldata payload) = exec.unpackRelay(Lanes.Input);
37
+ bytes memory context = Blocks.context(account, bytes(state), bytes(payload));
38
+
39
+ relayTo(portal, resources, context, exec);
40
+
41
+ return close(exec, account);
42
+ }
43
+ }
44
+
45
+ /// @title RelayBalancePayable
46
+ /// @notice Command that forwards required BALANCE state with one RELAY block.
22
47
  /// Reverts unless the input contains exactly one RELAY block, preventing
23
48
  /// the same state from being duplicated across multiple relays.
24
49
  /// Produces no output state.
25
- abstract contract RelayPayable is CommandBase, RoutePayableHook {
50
+ abstract contract RelayBalancePayable is CommandBase, RelayPayableHook {
26
51
  uint private immutable descriptor;
27
52
 
28
53
  constructor() {
29
- (, descriptor) = command("relayPayable", Specs.Any, Specs.Relay, Specs.Empty, 0, true, false);
54
+ (, descriptor) = command("relayBalancePayable", Specs.Balance, Specs.Relay, Specs.Empty, 0, true, false);
30
55
  }
31
56
 
32
57
  /// @notice Relay one RELAY input block with the command account and current state.
@@ -34,16 +59,16 @@ abstract contract RelayPayable is CommandBase, RoutePayableHook {
34
59
  /// @param input Exactly one RELAY block.
35
60
  /// @return Empty output state.
36
61
  /// @return Remaining native value as a refund transaction stream.
37
- function relayPayable(
62
+ function relayBalancePayable(
38
63
  bytes32 account,
39
64
  bytes calldata state,
40
65
  bytes calldata input
41
66
  ) external payable onlyCommand returns (bytes memory, bytes memory) {
42
- Execution memory exec = openInput(input, descriptor, 1);
67
+ Execution memory exec = openCommand(state, input, descriptor, 1);
43
68
  (uint portal, uint resources, bytes calldata payload) = exec.unpackRelay(Lanes.Input);
44
69
  bytes memory context = Blocks.context(account, bytes(state), bytes(payload));
45
70
 
46
- route(portal, resources, context, exec);
71
+ relayTo(portal, resources, context, exec);
47
72
 
48
73
  return close(exec, account);
49
74
  }
@@ -0,0 +1,77 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Execution, Executions, CommandBase, Lanes, Specs} from "./Base.sol";
5
+ import {SettleHook} from "../core/Settlement.sol";
6
+ import {Action} from "../annotations/Action.sol";
7
+ import {Actions} from "../utils/Actions.sol";
8
+ import {Blocks} from "../codec/Blocks.sol";
9
+ import {Reader, Readers} from "../codec/Readers.sol";
10
+
11
+ using Executions for Execution;
12
+ using Readers for Reader;
13
+
14
+ /// @title Settle
15
+ /// @notice Command that consumes POSITION state blocks through a virtual hook.
16
+ abstract contract Settle is CommandBase, SettleHook, Action {
17
+ uint private immutable descriptor;
18
+ uint private immutable id;
19
+
20
+ constructor() {
21
+ (id, descriptor) = command("settle", Specs.Position, Specs.Empty, Specs.Empty, 0, false, false);
22
+ action(id, Actions.Settle);
23
+ }
24
+
25
+ /// @notice Return the registered SETTLE command ID.
26
+ function settleId() internal view returns (uint) {
27
+ return id;
28
+ }
29
+
30
+ /// @notice Settle each POSITION block from the command state.
31
+ /// @param state POSITION block stream.
32
+ /// @return Empty output state.
33
+ /// @return Empty transaction stream.
34
+ function settle(
35
+ bytes32 account,
36
+ bytes calldata state,
37
+ bytes calldata input
38
+ ) external onlyCommand returns (bytes memory, bytes memory) {
39
+ Execution memory exec = openCommand(state, input, descriptor, 0);
40
+
41
+ while (exec.more()) {
42
+ (bytes32 asset, uint amount, bytes32 liability, uint debt) = exec.unpackPosition(Lanes.State);
43
+ settle(account, asset, amount, liability, debt);
44
+ }
45
+
46
+ return close(exec, account);
47
+ }
48
+ }
49
+
50
+ /// @title InternalSettle
51
+ /// @notice Extends the advertised settle command with memory-state pipeline dispatch.
52
+ /// @dev This adapter is not a separate command. It uses the command ID and settlement hook
53
+ /// inherited from `Settle` while accepting the state location used by `Pipeline`.
54
+ abstract contract InternalSettle is Settle {
55
+ /// @notice Execute the inherited settle command from an internal pipeline.
56
+ /// @param account Account for which each position is settled.
57
+ /// @param state POSITION block stream held in pipeline memory.
58
+ /// @param input Empty input required by the command schema.
59
+ /// @return output Empty output state.
60
+ /// @return transactions Empty transaction stream.
61
+ function executeSettle(
62
+ bytes32 account,
63
+ bytes memory state,
64
+ bytes calldata input
65
+ ) internal returns (bytes memory, bytes memory) {
66
+ if (input.length != 0) revert Executions.ZeroStride();
67
+ if (state.length == 0) revert Blocks.EmptyRun();
68
+
69
+ Reader memory reader = Readers.open(state);
70
+ while (reader.more()) {
71
+ (bytes32 asset, uint amount, bytes32 liability, uint debt) = reader.unpackPosition();
72
+ settle(account, asset, amount, liability, debt);
73
+ }
74
+
75
+ return ("", "");
76
+ }
77
+ }
@@ -36,9 +36,9 @@ abstract contract Withdraw is CommandBase, WithdrawHook, Action {
36
36
  function withdraw(
37
37
  bytes32 account,
38
38
  bytes calldata state,
39
- bytes calldata
39
+ bytes calldata input
40
40
  ) external onlyCommand returns (bytes memory, bytes memory) {
41
- Execution memory exec = openState(state, descriptor, 0);
41
+ Execution memory exec = openCommand(state, input, descriptor, 0);
42
42
 
43
43
  while (exec.more()) {
44
44
  (bytes32 asset, uint amount) = exec.unpackBalance(Lanes.State);
@@ -28,10 +28,10 @@ abstract contract AllowAssets is AdminBase, AllowAssetsHook {
28
28
  /// @return Empty transaction stream.
29
29
  function allowAssets(
30
30
  bytes32 account,
31
- bytes calldata,
31
+ bytes calldata state,
32
32
  bytes calldata input
33
33
  ) external onlyAdmin(account) returns (bytes memory, bytes memory) {
34
- Execution memory exec = openInput(input, descriptor, 0);
34
+ Execution memory exec = openCommand(state, input, descriptor, 0);
35
35
 
36
36
  while (exec.more()) {
37
37
  bytes32 asset = exec.unpackAsset(Lanes.Input);
@@ -32,10 +32,10 @@ abstract contract Allowance is AdminBase, AllowanceHook {
32
32
  /// @return Empty transaction stream.
33
33
  function allowance(
34
34
  bytes32 account,
35
- bytes calldata,
35
+ bytes calldata state,
36
36
  bytes calldata input
37
37
  ) external onlyAdmin(account) returns (bytes memory, bytes memory) {
38
- Execution memory exec = openInput(input, descriptor, 0);
38
+ Execution memory exec = openCommand(state, input, descriptor, 0);
39
39
 
40
40
  while (exec.more()) {
41
41
  (uint peer, bytes32 asset, uint amount) = exec.unpackAllowance(Lanes.Input);
@@ -21,10 +21,10 @@ abstract contract Annotate is AdminBase {
21
21
  /// @return Empty transaction stream.
22
22
  function annotate(
23
23
  bytes32 account,
24
- bytes calldata,
24
+ bytes calldata state,
25
25
  bytes calldata input
26
26
  ) external onlyAdmin(account) returns (bytes memory, bytes memory) {
27
- Execution memory exec = openInput(input, descriptor, 0);
27
+ Execution memory exec = openCommand(state, input, descriptor, 0);
28
28
 
29
29
  while (exec.more()) {
30
30
  (uint entity, bytes calldata data) = exec.unpackAnnotation(Lanes.Input);
@@ -22,10 +22,10 @@ abstract contract Appoint is GuardianAccess, AdminBase {
22
22
  /// @return Empty transaction stream.
23
23
  function appoint(
24
24
  bytes32 account,
25
- bytes calldata,
25
+ bytes calldata state,
26
26
  bytes calldata input
27
27
  ) external onlyAdmin(account) returns (bytes memory, bytes memory) {
28
- Execution memory exec = openInput(input, descriptor, 0);
28
+ Execution memory exec = openCommand(state, input, descriptor, 0);
29
29
 
30
30
  while (exec.more()) {
31
31
  bytes32 guardian = exec.unpackAccount(Lanes.Input);
@@ -27,10 +27,10 @@ abstract contract Authorize is AdminBase {
27
27
  /// @return Empty transaction stream.
28
28
  function authorize(
29
29
  bytes32 account,
30
- bytes calldata,
30
+ bytes calldata state,
31
31
  bytes calldata input
32
32
  ) external onlyAdmin(account) returns (bytes memory, bytes memory) {
33
- Execution memory exec = openInput(input, descriptor, 0);
33
+ Execution memory exec = openCommand(state, input, descriptor, 0);
34
34
 
35
35
  while (exec.more()) {
36
36
  uint node = exec.unpackNode(Lanes.Input);
@@ -28,10 +28,10 @@ abstract contract DenyAssets is AdminBase, DenyAssetsHook {
28
28
  /// @return Empty transaction stream.
29
29
  function denyAssets(
30
30
  bytes32 account,
31
- bytes calldata,
31
+ bytes calldata state,
32
32
  bytes calldata input
33
33
  ) external onlyAdmin(account) returns (bytes memory, bytes memory) {
34
- Execution memory exec = openInput(input, descriptor, 0);
34
+ Execution memory exec = openCommand(state, input, descriptor, 0);
35
35
 
36
36
  while (exec.more()) {
37
37
  bytes32 asset = exec.unpackAsset(Lanes.Input);