@rootzero/contracts 1.28.0 → 1.29.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 CHANGED
@@ -8,6 +8,19 @@ sections are immutable and must continue to describe the tagged release.
8
8
 
9
9
  ## Unreleased
10
10
 
11
+ ## 1.29.0
12
+
13
+ ### Breaking Changes
14
+
15
+ - `ExecuteHook.execute` and the optimized local command helpers now return a
16
+ leading `bool handled`. A local command returned as unhandled is invoked
17
+ through its trusted normal external command entrypoint; handled commands keep
18
+ the optimized internal path and are authorized by the hook implementation.
19
+ - Renamed `CashoutInternal`, `DebitAccountInternal`, `CreditAccountInternal`,
20
+ `SettleInternal`, and `RepayInternal` to `ExecuteCashout`,
21
+ `ExecuteDebitAccount`, `ExecuteCreditAccount`, `ExecuteSettle`, and
22
+ `ExecuteRepay`.
23
+
11
24
  ## 1.28.0
12
25
 
13
26
  ### Breaking Changes
package/Endpoints.sol CHANGED
@@ -14,23 +14,23 @@ import {CommandBase} from "./commands/Base.sol";
14
14
  import {Allocate, AllocateHook} from "./commands/Allocate.sol";
15
15
  import {Burn, BurnHook} from "./commands/Burn.sol";
16
16
  import {Bootstrap} from "./commands/Bootstrap.sol";
17
- import {Cashout, CashoutHook, CashoutInternal} from "./commands/Cashout.sol";
18
- import {CreditAccount, CreditAccountInternal} from "./commands/Credit.sol";
19
- import {DebitAccount, DebitAccountInternal} from "./commands/Debit.sol";
17
+ import {Cashout, CashoutHook, ExecuteCashout} from "./commands/Cashout.sol";
18
+ import {CreditAccount, ExecuteCreditAccount} from "./commands/Credit.sol";
19
+ import {DebitAccount, ExecuteDebitAccount} from "./commands/Debit.sol";
20
20
  import {Deposit, DepositHook, DepositPayable, DepositPayableHook} from "./commands/Deposit.sol";
21
21
  import {Payout, PayoutHook} from "./commands/Payout.sol";
22
22
  import {Provision, ProvisionHook, ProvisionPayable, ProvisionPayableHook} from "./commands/Provision.sol";
23
23
  import {RecoverPayable, RecoverPayableHook} from "./commands/Recover.sol";
24
24
  import {
25
25
  Repay,
26
- RepayInternal,
26
+ ExecuteRepay,
27
27
  RepayPayable,
28
28
  RepayPayableHook,
29
29
  RepayPosition,
30
30
  RepayPositionPayable
31
31
  } from "./commands/Repay.sol";
32
32
  import {RelayPayable, RelayBalancePayable, RelayPayableHook} from "./commands/Relay.sol";
33
- import {Settle, SettlePayable, SettlePayableHook, SettleInternal} from "./commands/Settle.sol";
33
+ import {Settle, SettlePayable, SettlePayableHook, ExecuteSettle} from "./commands/Settle.sol";
34
34
  import {Withdraw, WithdrawHook} from "./commands/Withdraw.sol";
35
35
 
36
36
  // Admin commands
package/README.md CHANGED
@@ -388,13 +388,17 @@ while (cur.more()) {
388
388
  (bytes4 selector, address target) = unpackCommand(cmd);
389
389
  if (budget < value) revert InsufficientValue();
390
390
  unchecked { budget -= value; }
391
+ bool handled;
392
+ bytes memory output;
391
393
  uint credit;
392
394
  if (target == address(this)) {
393
- (state, credit) = execute(cmd, account, state, input, value);
394
- } else {
395
+ (handled, output, credit) = execute(cmd, account, state, input, value);
396
+ }
397
+ if (!handled) {
395
398
  ensureTrusted(cmd);
396
- (state, credit) = rawCommandCall(selector, target, value, account, state, input);
399
+ (output, credit) = rawCommandCall(selector, target, value, account, state, input);
397
400
  }
401
+ state = output;
398
402
  budget += credit;
399
403
  }
400
404
  if (state.length != 0) revert UnexpectedState();
@@ -414,15 +418,18 @@ parameters. A `resources` word is never itself native value; EVM adapters use
414
418
  `useResourceValue` to extract its low 128-bit value lane before spending it.
415
419
 
416
420
  Hosts that implement a pipeline locally can inherit `Bootstrap`,
417
- `CashoutInternal`, `DebitAccountInternal`, `CreditAccountInternal`,
418
- `SettleInternal`, and
419
- `RepayInternal` to register canonical command metadata while routing
421
+ `ExecuteCashout`, `ExecuteDebitAccount`, `ExecuteCreditAccount`,
422
+ `ExecuteSettle`, and
423
+ `ExecuteRepay` to register canonical command metadata while executing
420
424
  their local command IDs through `executeBootstrap`, `executeCashout`,
421
425
  `executeDebitAccount`, `executeCreditAccount`, `executeSettle`, and
422
426
  `executeRepay`. The bootstrap, cashout, and debit adapters decode fixed-stride
423
427
  calldata input directly; the other three
424
- decode memory-backed pipeline state. All avoid an external self-call. Pass the
425
- step value into each adapter. Bootstrap is pipeline-local rather than an
428
+ decode memory-backed pipeline state. All return `handled = true` and avoid an
429
+ external self-call. The host's `execute` hook must authorize a command before
430
+ returning true. Returning `handled = false` delegates a local command to its
431
+ trusted normal external entrypoint. Pass the step value into each adapter.
432
+ Bootstrap is pipeline-local rather than an
426
433
  externally callable command and may consume value for native-asset balance;
427
434
  the other five reject nonzero value because those commands are non-funded.
428
435
 
@@ -52,6 +52,7 @@ abstract contract Bootstrap is CommandBase, DebitAccountHook {
52
52
  /// @param state Empty pipeline state required by the command schema.
53
53
  /// @param input BOOTSTRAP block stream.
54
54
  /// @param value Native value available to fund native-asset balances.
55
+ /// @return handled Always true because this helper executed the command.
55
56
  /// @return output One BALANCE block per BOOTSTRAP input.
56
57
  /// @return credit Sourced budget contributions plus unused assigned value.
57
58
  function executeBootstrap(
@@ -59,7 +60,7 @@ abstract contract Bootstrap is CommandBase, DebitAccountHook {
59
60
  bytes memory state,
60
61
  bytes calldata input,
61
62
  uint value
62
- ) internal returns (bytes memory output, uint credit) {
63
+ ) internal returns (bool handled, bytes memory output, uint credit) {
63
64
  if (state.length != 0) revert UnexpectedState();
64
65
  if (input.length % Sizes.Bootstrap != 0) revert Blocks.InvalidBlock();
65
66
 
@@ -77,5 +78,6 @@ abstract contract Bootstrap is CommandBase, DebitAccountHook {
77
78
  i += Sizes.Balance;
78
79
  }
79
80
  }
81
+ handled = true;
80
82
  }
81
83
  }
@@ -54,14 +54,15 @@ abstract contract Cashout is CommandBase, CashoutHook, Action {
54
54
  }
55
55
  }
56
56
 
57
- /// @title CashoutInternal
58
- /// @notice Extends cashout with optimized local pipeline dispatch.
59
- abstract contract CashoutInternal is Cashout {
57
+ /// @title ExecuteCashout
58
+ /// @notice Extends cashout with optimized local pipeline execution.
59
+ abstract contract ExecuteCashout is Cashout {
60
60
  /// @notice Execute cashout directly against a calldata CASHOUT stream.
61
61
  /// @param account Account whose native asset is withdrawn.
62
62
  /// @param state Empty pipeline state required by the command schema.
63
63
  /// @param input CASHOUT block stream.
64
64
  /// @param value Native value assigned to this command; must be zero.
65
+ /// @return handled Always true because this helper executed the command.
65
66
  /// @return output Empty output state.
66
67
  /// @return credit Zero native budget credit.
67
68
  function executeCashout(
@@ -69,7 +70,7 @@ abstract contract CashoutInternal is Cashout {
69
70
  bytes memory state,
70
71
  bytes calldata input,
71
72
  uint value
72
- ) internal returns (bytes memory, uint) {
73
+ ) internal returns (bool handled, bytes memory output, uint credit) {
73
74
  if (value != 0) revert ValueNotAllowed();
74
75
  if (state.length != 0) revert UnexpectedState();
75
76
  if (input.length % Sizes.Cashout != 0) revert Blocks.InvalidBlock();
@@ -81,6 +82,6 @@ abstract contract CashoutInternal is Cashout {
81
82
  abs += Sizes.Cashout;
82
83
  }
83
84
  }
84
- return ("", 0);
85
+ return (true, "", 0);
85
86
  }
86
87
  }
@@ -43,16 +43,17 @@ abstract contract CreditAccount is CommandBase, CreditAccountHook {
43
43
  }
44
44
  }
45
45
 
46
- /// @title CreditAccountInternal
47
- /// @notice Extends the advertised credit-account command with memory-state pipeline dispatch.
46
+ /// @title ExecuteCreditAccount
47
+ /// @notice Extends the advertised credit-account command with memory-state pipeline execution.
48
48
  /// @dev This adapter is not a separate command. It uses the command ID and account hook
49
49
  /// inherited from `CreditAccount` while accepting the state location used by `Pipeline`.
50
- abstract contract CreditAccountInternal is CreditAccount {
50
+ abstract contract ExecuteCreditAccount is CreditAccount {
51
51
  /// @notice Execute the inherited credit-account command from an internal pipeline.
52
52
  /// @param account Account credited by each balance.
53
53
  /// @param state BALANCE block stream held in pipeline memory.
54
54
  /// @param input Empty input required by the command schema.
55
55
  /// @param value Native value assigned to the command; must be zero.
56
+ /// @return handled Always true because this helper executed the command.
56
57
  /// @return output Empty output state.
57
58
  /// @return credit Zero native budget credit.
58
59
  function executeCreditAccount(
@@ -60,7 +61,7 @@ abstract contract CreditAccountInternal is CreditAccount {
60
61
  bytes memory state,
61
62
  bytes calldata input,
62
63
  uint value
63
- ) internal returns (bytes memory, uint) {
64
+ ) internal returns (bool handled, bytes memory output, uint credit) {
64
65
  if (value != 0) revert ValueNotAllowed();
65
66
  if (input.length != 0) revert UnexpectedInput();
66
67
  if (state.length == 0) revert Blocks.EmptyRun();
@@ -74,6 +75,6 @@ abstract contract CreditAccountInternal is CreditAccount {
74
75
  }
75
76
  }
76
77
 
77
- return ("", 0);
78
+ return (true, "", 0);
78
79
  }
79
80
  }
@@ -46,16 +46,17 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
46
46
  }
47
47
  }
48
48
 
49
- /// @title DebitAccountInternal
50
- /// @notice Extends the advertised debit-account command with optimized pipeline dispatch.
49
+ /// @title ExecuteDebitAccount
50
+ /// @notice Extends the advertised debit-account command with optimized pipeline execution.
51
51
  /// @dev This adapter is not a separate command. It uses the command ID and account hook
52
52
  /// inherited from `DebitAccount` while decoding its fixed-stride input directly from calldata.
53
- abstract contract DebitAccountInternal is DebitAccount {
53
+ abstract contract ExecuteDebitAccount is DebitAccount {
54
54
  /// @notice Execute the inherited debit-account command from an internal pipeline.
55
55
  /// @param account Account whose funds are debited.
56
56
  /// @param state Empty pipeline state required by the command schema.
57
57
  /// @param input AMOUNT block stream.
58
58
  /// @param value Native value assigned to the command; must be zero.
59
+ /// @return handled Always true because this helper executed the command.
59
60
  /// @return output BALANCE block stream matching the debited amounts.
60
61
  /// @return credit Zero native budget credit.
61
62
  function executeDebitAccount(
@@ -63,14 +64,14 @@ abstract contract DebitAccountInternal is DebitAccount {
63
64
  bytes memory state,
64
65
  bytes calldata input,
65
66
  uint value
66
- ) internal returns (bytes memory, uint) {
67
+ ) internal returns (bool handled, bytes memory output, uint credit) {
67
68
  if (value != 0) revert ValueNotAllowed();
68
69
  if (state.length != 0) revert UnexpectedState();
69
70
  if (input.length == 0) revert Blocks.EmptyRun();
70
71
  if (input.length % Sizes.Amount != 0) revert Blocks.InvalidBlock();
71
72
 
72
73
  (uint abs, uint end) = Cursors.bounds(input);
73
- bytes memory output = new bytes(input.length);
74
+ output = new bytes(input.length);
74
75
  uint i;
75
76
 
76
77
  while (abs < end) {
@@ -83,6 +84,6 @@ abstract contract DebitAccountInternal is DebitAccount {
83
84
  }
84
85
  }
85
86
 
86
- return (output, 0);
87
+ return (true, output, 0);
87
88
  }
88
89
  }
@@ -146,16 +146,17 @@ abstract contract RepayPositionPayable is CommandBase, RepayPayableHook, Action
146
146
  }
147
147
  }
148
148
 
149
- /// @title RepayInternal
150
- /// @notice Extends the advertised repay command with memory-state pipeline dispatch.
149
+ /// @title ExecuteRepay
150
+ /// @notice Extends the advertised repay command with memory-state pipeline execution.
151
151
  /// @dev This adapter is not a separate command. It uses the command ID and repayment hook
152
152
  /// inherited from `Repay` while accepting the state location used by `Pipeline`.
153
- abstract contract RepayInternal is Repay {
153
+ abstract contract ExecuteRepay is Repay {
154
154
  /// @notice Execute the inherited repay command from an internal pipeline.
155
155
  /// @param account Account whose liabilities are repaid.
156
156
  /// @param state DEBT block stream held in pipeline memory.
157
157
  /// @param input Empty input required by the command schema.
158
158
  /// @param value Native value assigned to the command; must be zero.
159
+ /// @return handled Always true because this helper executed the command.
159
160
  /// @return output Empty output state.
160
161
  /// @return credit Zero native budget credit.
161
162
  function executeRepay(
@@ -163,7 +164,7 @@ abstract contract RepayInternal is Repay {
163
164
  bytes memory state,
164
165
  bytes calldata input,
165
166
  uint value
166
- ) internal returns (bytes memory, uint) {
167
+ ) internal returns (bool handled, bytes memory output, uint credit) {
167
168
  if (value != 0) revert ValueNotAllowed();
168
169
  if (input.length != 0) revert UnexpectedInput();
169
170
  if (state.length == 0) revert Blocks.EmptyRun();
@@ -177,6 +178,6 @@ abstract contract RepayInternal is Repay {
177
178
  }
178
179
  }
179
180
 
180
- return ("", 0);
181
+ return (true, "", 0);
181
182
  }
182
183
  }
@@ -93,16 +93,17 @@ abstract contract SettlePayable is CommandBase, SettlePayableHook, Action {
93
93
  }
94
94
  }
95
95
 
96
- /// @title SettleInternal
97
- /// @notice Extends the advertised settle command with memory-state pipeline dispatch.
96
+ /// @title ExecuteSettle
97
+ /// @notice Extends the advertised settle command with memory-state pipeline execution.
98
98
  /// @dev This adapter is not a separate command. It uses the command ID and settlement hook
99
99
  /// inherited from `Settle` while accepting the state location used by `Pipeline`.
100
- abstract contract SettleInternal is Settle {
100
+ abstract contract ExecuteSettle is Settle {
101
101
  /// @notice Execute the inherited settle command from an internal pipeline.
102
102
  /// @param account Account for which each position is settled.
103
103
  /// @param state POSITION block stream held in pipeline memory.
104
104
  /// @param input Empty input required by the command schema.
105
105
  /// @param value Native value assigned to the command; must be zero.
106
+ /// @return handled Always true because this helper executed the command.
106
107
  /// @return output Empty output state.
107
108
  /// @return credit Zero native budget credit.
108
109
  function executeSettle(
@@ -110,7 +111,7 @@ abstract contract SettleInternal is Settle {
110
111
  bytes memory state,
111
112
  bytes calldata input,
112
113
  uint value
113
- ) internal returns (bytes memory, uint) {
114
+ ) internal returns (bool handled, bytes memory output, uint credit) {
114
115
  if (value != 0) revert ValueNotAllowed();
115
116
  if (input.length != 0) revert UnexpectedInput();
116
117
  if (state.length == 0) revert Blocks.EmptyRun();
@@ -124,6 +125,6 @@ abstract contract SettleInternal is Settle {
124
125
  }
125
126
  }
126
127
 
127
- return ("", 0);
128
+ return (true, "", 0);
128
129
  }
129
130
  }
package/core/Pipeline.sol CHANGED
@@ -21,15 +21,17 @@ abstract contract PipeHook {
21
21
 
22
22
  /// @notice Hook implemented by pipeline hosts that execute host-local commands.
23
23
  abstract contract ExecuteHook {
24
- /// @notice Execute one command whose node ID targets the current host.
25
- /// @dev Implementations must revert for unsupported local command IDs.
24
+ /// @notice Try to execute one command whose node ID targets the current host.
25
+ /// @dev Implementations returning `handled = true` are responsible for
26
+ /// authorizing the command. Return false without side effects to delegate to
27
+ /// the trusted normal external entrypoint. Implementations may revert instead.
26
28
  function execute(
27
29
  uint cmd,
28
30
  bytes32 account,
29
31
  bytes memory state,
30
32
  bytes calldata input,
31
33
  uint value
32
- ) internal virtual returns (bytes memory output, uint credit);
34
+ ) internal virtual returns (bool handled, bytes memory output, uint credit);
33
35
  }
34
36
 
35
37
  /// @title Pipeline
@@ -43,7 +45,11 @@ abstract contract Pipeline is TrustAccess, PipeHook, ExecuteHook {
43
45
  uint value
44
46
  ) private returns (bytes memory output, uint credit) {
45
47
  (bytes4 selector, address target) = unpackCommand(cmd);
46
- if (target == address(this)) return execute(cmd, account, state, input, value);
48
+ if (target == address(this)) {
49
+ bool handled;
50
+ (handled, output, credit) = execute(cmd, account, state, input, value);
51
+ if (handled) return (output, credit);
52
+ }
47
53
  ensureTrusted(cmd);
48
54
  return rawCommandCall(selector, target, value, account, state, input);
49
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootzero/contracts",
3
- "version": "1.28.0",
3
+ "version": "1.29.0",
4
4
  "description": "Solidity contracts and protocol building blocks for rootzero hosts and commands.",
5
5
  "private": false,
6
6
  "license": "GPL-3.0-only",