@rootzero/contracts 1.25.0 → 1.26.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 +101 -0
- package/Codec.sol +1 -2
- package/Endpoints.sol +2 -0
- package/README.md +61 -51
- package/Utils.sol +2 -1
- package/codec/Blocks.sol +276 -88
- package/codec/Buffers.sol +24 -20
- package/codec/Decoders.sol +35 -37
- package/codec/Descriptors.sol +75 -72
- package/codec/Keys.sol +5 -1
- package/codec/Schema.sol +5 -1
- package/codec/Specs.sol +19 -9
- package/codec/Writers.sol +14 -19
- package/commands/Allocate.sol +8 -7
- package/commands/Base.sol +14 -49
- package/commands/Bootstrap.sol +95 -0
- package/commands/Burn.sol +7 -7
- package/commands/Cashout.sol +85 -0
- package/commands/Credit.sol +18 -16
- package/commands/Debit.sol +23 -19
- package/commands/Deposit.sol +13 -13
- package/commands/Payout.sol +8 -8
- package/commands/Provision.sol +13 -13
- package/commands/Recover.sol +7 -7
- package/commands/Relay.sol +22 -23
- package/commands/Repay.sol +36 -34
- package/commands/Settle.sol +24 -22
- package/commands/Withdraw.sol +7 -7
- package/commands/admin/AllowAssets.sol +7 -7
- package/commands/admin/Allowance.sol +7 -7
- package/commands/admin/Annotate.sol +7 -7
- package/commands/admin/Appoint.sol +7 -7
- package/commands/admin/Authorize.sol +7 -7
- package/commands/admin/Base.sol +5 -8
- package/commands/admin/DenyAssets.sol +7 -7
- package/commands/admin/Dismiss.sol +7 -7
- package/commands/admin/Execute.sol +8 -8
- package/commands/admin/Unauthorize.sol +7 -7
- package/core/Calls.sol +3 -3
- package/core/Endpoint.sol +7 -7
- package/core/Pipeline.sol +19 -20
- package/execution/Budget.sol +2 -3
- package/execution/Execution.sol +271 -509
- package/guards/Base.sol +1 -1
- package/guards/Revoke.sol +7 -7
- package/package.json +1 -1
- package/ports/Allowance.sol +3 -3
- package/ports/Assets.sol +7 -7
- package/ports/Base.sol +1 -1
- package/ports/Credit.sol +3 -3
- package/ports/Debit.sol +3 -3
- package/ports/Dispatch.sol +3 -3
- package/ports/Pipe.sol +3 -3
- package/ports/Post.sol +3 -3
- package/ports/Redeem.sol +3 -3
- package/queries/Assets.sol +3 -3
- package/queries/Balances.sol +3 -3
- package/queries/Base.sol +1 -1
- package/utils/Accounts.sol +1 -3
- package/utils/Actions.sol +2 -0
- package/utils/Assets.sol +1 -10
- package/utils/Cursors.sol +60 -116
- package/utils/Errors.sol +50 -0
- package/utils/Ids.sol +2 -5
- package/utils/Lanes.sol +0 -2
- package/utils/Nodes.sol +1 -3
- package/utils/Utils.sol +2 -9
- package/codec/Readers.sol +0 -190
package/commands/Allocate.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 {Execution, Executions, CommandBase, HostAmount,
|
|
4
|
+
import {Execution, Executions, CommandBase, HostAmount, Specs} from "./Base.sol";
|
|
5
5
|
|
|
6
6
|
using Executions for Execution;
|
|
7
7
|
|
|
@@ -24,24 +24,25 @@ abstract contract Allocate is CommandBase, AllocateHook {
|
|
|
24
24
|
uint private immutable descriptor;
|
|
25
25
|
|
|
26
26
|
constructor() {
|
|
27
|
-
(, descriptor) = command("allocate", Specs.Balance, Specs.Node, Specs.Custody, 0
|
|
27
|
+
(, descriptor) = command("allocate", Specs.Balance, Specs.Node, Specs.Custody, 0);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/// @notice Allocate BALANCE state blocks to matching NODE input blocks.
|
|
31
31
|
/// @param context Command context carrying BALANCE state and matching NODE input.
|
|
32
32
|
/// @return CUSTODY block stream matching the allocated balances.
|
|
33
|
-
/// @return
|
|
33
|
+
/// @return Zero native budget credit.
|
|
34
34
|
function allocate(
|
|
35
35
|
bytes calldata context
|
|
36
|
-
) external onlyCommand returns (bytes memory,
|
|
37
|
-
Execution memory exec = openCommand(context, descriptor
|
|
36
|
+
) external onlyCommand returns (bytes memory, uint) {
|
|
37
|
+
Execution memory exec = openCommand(context, descriptor);
|
|
38
38
|
|
|
39
39
|
while (exec.more()) {
|
|
40
|
-
|
|
40
|
+
uint host = exec.oninput().unpackNode();
|
|
41
|
+
HostAmount memory custody = exec.onstate().unpackBalanceForHost(host);
|
|
41
42
|
allocate(exec.account, custody);
|
|
42
43
|
exec.outputCustody(custody);
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
return
|
|
46
|
+
return exec.close();
|
|
46
47
|
}
|
|
47
48
|
}
|
package/commands/Base.sol
CHANGED
|
@@ -6,19 +6,17 @@ import {EndpointBase} from "../core/Endpoint.sol";
|
|
|
6
6
|
import {Blocks} from "../codec/Blocks.sol";
|
|
7
7
|
import {Specs} from "../codec/Specs.sol";
|
|
8
8
|
import {HostAmount, Position} from "../core/Types.sol";
|
|
9
|
-
import {Execution, Executions
|
|
10
|
-
import {ReceivedEvent} from "../events/Received.sol";
|
|
11
|
-
import {Actions} from "../utils/Actions.sol";
|
|
9
|
+
import {Execution, Executions} from "../execution/Execution.sol";
|
|
12
10
|
import {Descriptors, Flags} from "../codec/Descriptors.sol";
|
|
13
11
|
import {Nodes} from "../utils/Nodes.sol";
|
|
14
|
-
import {Cursors} from "../utils/Cursors.sol";
|
|
15
12
|
|
|
16
13
|
using Executions for Execution;
|
|
14
|
+
using Descriptors for uint;
|
|
17
15
|
|
|
18
16
|
/// @title CommandBase
|
|
19
17
|
/// @notice Abstract base for all rootzero command contracts.
|
|
20
18
|
/// Provides access control modifiers and command endpoint metadata helpers.
|
|
21
|
-
abstract contract CommandBase is CallerAccess, EndpointBase
|
|
19
|
+
abstract contract CommandBase is CallerAccess, EndpointBase {
|
|
22
20
|
/// @dev Thrown when `onlyActive` finds that `deadline` has already passed.
|
|
23
21
|
error Expired();
|
|
24
22
|
/// @dev Thrown when a non-funded internal command receives native value.
|
|
@@ -43,7 +41,6 @@ abstract contract CommandBase is CallerAccess, EndpointBase, ReceivedEvent {
|
|
|
43
41
|
/// @param state State block specification.
|
|
44
42
|
/// @param input Input block specification.
|
|
45
43
|
/// @param output Output block specification.
|
|
46
|
-
/// @param transactions Number of transaction blocks produced per batch, or zero for none.
|
|
47
44
|
/// @param flags Packed command behavior flags.
|
|
48
45
|
/// @return id Command node ID.
|
|
49
46
|
/// @return descriptor Packed endpoint lane metadata and flags.
|
|
@@ -52,10 +49,9 @@ abstract contract CommandBase is CallerAccess, EndpointBase, ReceivedEvent {
|
|
|
52
49
|
uint state,
|
|
53
50
|
uint input,
|
|
54
51
|
uint output,
|
|
55
|
-
uint8 transactions,
|
|
56
52
|
uint8 flags
|
|
57
53
|
) internal returns (uint id, uint descriptor) {
|
|
58
|
-
descriptor = Descriptors.create(state, input, output,
|
|
54
|
+
descriptor = Descriptors.create(state, input, output, flags);
|
|
59
55
|
return command(name, descriptor);
|
|
60
56
|
}
|
|
61
57
|
|
|
@@ -70,55 +66,24 @@ abstract contract CommandBase is CallerAccess, EndpointBase, ReceivedEvent {
|
|
|
70
66
|
published = endpoint(id, name, descriptor);
|
|
71
67
|
}
|
|
72
68
|
|
|
73
|
-
/// @notice Decode
|
|
69
|
+
/// @notice Decode one command context and open bounded state and input lanes.
|
|
74
70
|
/// @dev Rejects empty input, trailing bytes, and additional context blocks.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
/// The command's decode and loop implementation defines lane semantics.
|
|
72
|
+
/// Closing requires both lanes to have been consumed completely.
|
|
73
|
+
/// @param context Exactly one CONTEXT block carrying the account, state, and input.
|
|
74
|
+
/// @param descriptor Packed command endpoint descriptor.
|
|
75
|
+
/// @return exec Execution with a resizable output writer initialized from its descriptor hint.
|
|
76
|
+
function openCommand(bytes calldata context, uint descriptor) internal view returns (Execution memory exec) {
|
|
78
77
|
uint abs;
|
|
79
78
|
assembly ("memory-safe") {
|
|
80
79
|
abs := context.offset
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
uint end;
|
|
84
|
-
(account, state, input, end) = Blocks.unpackContext(abs);
|
|
82
|
+
(bytes32 account, bytes calldata state, bytes calldata input, uint end) = Blocks.unpackContext(abs);
|
|
85
83
|
if (end != abs + context.length) revert Blocks.InvalidBlock();
|
|
86
|
-
}
|
|
87
84
|
|
|
88
|
-
|
|
89
|
-
/// Batches are derived from the input and state lanes. A non-empty stream for
|
|
90
|
-
/// a lane whose descriptor has zero stride reverts instead of being ignored.
|
|
91
|
-
/// Commands must account for the complete validated state by consuming it,
|
|
92
|
-
/// transforming and returning it, forwarding it intact, or reverting.
|
|
93
|
-
/// @param context Exactly one CONTEXT block carrying the account, state, and input.
|
|
94
|
-
/// @param descriptor Packed command endpoint descriptor.
|
|
95
|
-
/// @param batches Required batch count, or zero to reconcile the lane counts.
|
|
96
|
-
/// @return exec Execution with its output buffer metadata initialized for the reconciled batch count.
|
|
97
|
-
function openCommand(
|
|
98
|
-
bytes calldata context,
|
|
99
|
-
uint descriptor,
|
|
100
|
-
uint batches
|
|
101
|
-
) internal view returns (Execution memory exec) {
|
|
102
|
-
(bytes32 account, bytes calldata state, bytes calldata input) = unpackCommandContext(context);
|
|
103
|
-
exec = Executions.open(state, input, descriptor, batches);
|
|
85
|
+
(exec.decoders, exec.writer) = descriptor.open(state, input);
|
|
104
86
|
exec.account = account;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
/// @notice Close a command execution and refund unspent value to its account.
|
|
108
|
-
/// @param exec Command execution to close.
|
|
109
|
-
/// @return output Final encoded output block stream.
|
|
110
|
-
/// @return transactions Final encoded transaction block stream.
|
|
111
|
-
function closeCommand(
|
|
112
|
-
Execution memory exec
|
|
113
|
-
) internal returns (bytes memory output, bytes memory transactions) {
|
|
114
|
-
if (exec.budget == 0 && Cursors.initial(exec.writers)) return ("", "");
|
|
115
|
-
|
|
116
|
-
output = close(exec);
|
|
117
|
-
uint amount = exec.refundValue(exec.account, nativeAsset);
|
|
118
|
-
if (amount != 0) {
|
|
119
|
-
emit Received(exec.account, nativeAsset, amount, Actions.Refund, 0);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
transactions = exec.finishTransactions();
|
|
87
|
+
exec.budget = msg.value;
|
|
123
88
|
}
|
|
124
89
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {Execution, Executions, CommandBase, Specs} from "./Base.sol";
|
|
5
|
+
import {Blocks} from "../codec/Blocks.sol";
|
|
6
|
+
import {Sizes} from "../codec/Specs.sol";
|
|
7
|
+
import {Cursors} from "../utils/Cursors.sol";
|
|
8
|
+
import {DebitAccountHook} from "../core/Settlement.sol";
|
|
9
|
+
|
|
10
|
+
using Executions for Execution;
|
|
11
|
+
|
|
12
|
+
/// @notice Hook implemented by hosts that source bootstrap pipeline budget.
|
|
13
|
+
abstract contract BootstrapBudgetHook {
|
|
14
|
+
/// @notice Source native-value budget for `account` during bootstrap.
|
|
15
|
+
/// Called once per BOOTSTRAP input block.
|
|
16
|
+
/// @dev Implementations must revert unless the contribution can be made available.
|
|
17
|
+
/// A zero amount is valid and may return immediately without changing state.
|
|
18
|
+
/// @param account Account funding the pipeline.
|
|
19
|
+
/// @param amount Native value added to the pipeline budget.
|
|
20
|
+
function bootstrapBudget(bytes32 account, uint amount) internal virtual;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// @title Bootstrap
|
|
24
|
+
/// @notice Command that atomically starts a pipeline with BALANCE state and native-value budget.
|
|
25
|
+
abstract contract Bootstrap is CommandBase, DebitAccountHook, BootstrapBudgetHook {
|
|
26
|
+
uint private immutable descriptor;
|
|
27
|
+
uint private immutable id;
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
(id, descriptor) = command("bootstrap", Specs.Empty, Specs.Bootstrap, Specs.Balance, 0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// @notice Return the registered BOOTSTRAP command ID.
|
|
34
|
+
function bootstrapId() internal view returns (uint) {
|
|
35
|
+
return id;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// @notice Source initial balances and budget contributions for a pipeline.
|
|
39
|
+
/// @param context Command context carrying a BOOTSTRAP input stream.
|
|
40
|
+
/// @return output One BALANCE block per BOOTSTRAP input.
|
|
41
|
+
/// @return credit Sum of trusted native value contributed by every input.
|
|
42
|
+
function bootstrap(
|
|
43
|
+
bytes calldata context
|
|
44
|
+
) external onlyCommand returns (bytes memory output, uint credit) {
|
|
45
|
+
Execution memory exec = openCommand(context, descriptor);
|
|
46
|
+
|
|
47
|
+
while (exec.more()) {
|
|
48
|
+
(bytes32 asset, uint amount, uint budget) = exec.unpackBootstrap();
|
|
49
|
+
debitAccount(exec.account, asset, amount);
|
|
50
|
+
bootstrapBudget(exec.account, budget);
|
|
51
|
+
exec.outputBalance(asset, amount);
|
|
52
|
+
credit += budget;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return exec.close(credit);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// @title BootstrapInternal
|
|
60
|
+
/// @notice Extends bootstrap with optimized local pipeline dispatch.
|
|
61
|
+
abstract contract BootstrapInternal is Bootstrap {
|
|
62
|
+
/// @notice Execute bootstrap directly against a calldata BOOTSTRAP stream.
|
|
63
|
+
/// @param account Account funding the pipeline.
|
|
64
|
+
/// @param state Empty pipeline state required by the command schema.
|
|
65
|
+
/// @param input BOOTSTRAP block stream.
|
|
66
|
+
/// @param value Native value assigned to this command; must be zero.
|
|
67
|
+
/// @return output One BALANCE block per BOOTSTRAP input.
|
|
68
|
+
/// @return credit Sum of the sourced budget contributions.
|
|
69
|
+
function executeBootstrap(
|
|
70
|
+
bytes32 account,
|
|
71
|
+
bytes memory state,
|
|
72
|
+
bytes calldata input,
|
|
73
|
+
uint128 value
|
|
74
|
+
) internal returns (bytes memory output, uint credit) {
|
|
75
|
+
if (value != 0) revert ValueNotAllowed();
|
|
76
|
+
if (state.length != 0) revert Executions.ZeroStride();
|
|
77
|
+
if (input.length % Sizes.Bootstrap != 0) revert Blocks.InvalidBlock();
|
|
78
|
+
|
|
79
|
+
(uint abs, uint end) = Cursors.bounds(input);
|
|
80
|
+
output = new bytes(input.length / Sizes.Bootstrap * Sizes.Balance);
|
|
81
|
+
uint i;
|
|
82
|
+
|
|
83
|
+
while (abs < end) {
|
|
84
|
+
(bytes32 asset, uint amount, uint budget) = Blocks.unpackBootstrap(abs);
|
|
85
|
+
debitAccount(account, asset, amount);
|
|
86
|
+
bootstrapBudget(account, budget);
|
|
87
|
+
Blocks.writeBalance(output, i, asset, amount);
|
|
88
|
+
credit += budget;
|
|
89
|
+
unchecked {
|
|
90
|
+
abs += Sizes.Bootstrap;
|
|
91
|
+
i += Sizes.Balance;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
package/commands/Burn.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 { Execution, Executions, CommandBase,
|
|
4
|
+
import { Execution, Executions, CommandBase, Specs } from "./Base.sol";
|
|
5
5
|
import {Action} from "../annotations/Action.sol";
|
|
6
6
|
import {Actions} from "../utils/Actions.sol";
|
|
7
7
|
using Executions for Execution;
|
|
@@ -25,25 +25,25 @@ abstract contract Burn is CommandBase, BurnHook, Action {
|
|
|
25
25
|
|
|
26
26
|
constructor() {
|
|
27
27
|
uint id;
|
|
28
|
-
(id, descriptor) = command("burn", Specs.Balance, Specs.Empty, Specs.Empty, 0
|
|
28
|
+
(id, descriptor) = command("burn", Specs.Balance, Specs.Empty, Specs.Empty, 0);
|
|
29
29
|
action(id, Actions.Burn);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/// @notice Burn each BALANCE block from the command state.
|
|
33
33
|
/// @param context Command context carrying the BALANCE state stream.
|
|
34
34
|
/// @return Empty output state.
|
|
35
|
-
/// @return
|
|
35
|
+
/// @return Zero native budget credit.
|
|
36
36
|
function burn(
|
|
37
37
|
bytes calldata context
|
|
38
|
-
) external onlyCommand returns (bytes memory,
|
|
39
|
-
Execution memory exec = openCommand(context, descriptor
|
|
38
|
+
) external onlyCommand returns (bytes memory, uint) {
|
|
39
|
+
Execution memory exec = openCommand(context, descriptor);
|
|
40
40
|
|
|
41
41
|
while (exec.more()) {
|
|
42
|
-
(bytes32 asset, uint amount) = exec.unpackBalance(
|
|
42
|
+
(bytes32 asset, uint amount) = exec.unpackBalance();
|
|
43
43
|
burn(exec.account, asset, amount);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
return
|
|
46
|
+
return exec.close();
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {Execution, Executions, CommandBase, Specs} from "./Base.sol";
|
|
5
|
+
import {Blocks} from "../codec/Blocks.sol";
|
|
6
|
+
import {Sizes} from "../codec/Specs.sol";
|
|
7
|
+
import {Cursors} from "../utils/Cursors.sol";
|
|
8
|
+
import {Action} from "../annotations/Action.sol";
|
|
9
|
+
import {Actions} from "../utils/Actions.sol";
|
|
10
|
+
|
|
11
|
+
using Executions for Execution;
|
|
12
|
+
|
|
13
|
+
/// @notice Hook implemented by hosts that withdraw native assets from accounts.
|
|
14
|
+
abstract contract CashoutHook {
|
|
15
|
+
/// @notice Withdraw an exact native-asset amount from `account`.
|
|
16
|
+
/// Called once per CASHOUT input block.
|
|
17
|
+
/// @dev Implementations must revert when the requested amount cannot be withdrawn.
|
|
18
|
+
/// @param account Account whose native asset is withdrawn.
|
|
19
|
+
/// @param amount Native-asset amount to withdraw.
|
|
20
|
+
function cashout(bytes32 account, uint amount) internal virtual;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// @title Cashout
|
|
24
|
+
/// @notice Command that withdraws requested native-asset amounts from its account.
|
|
25
|
+
abstract contract Cashout is CommandBase, CashoutHook, Action {
|
|
26
|
+
uint private immutable descriptor;
|
|
27
|
+
uint private immutable id;
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
(id, descriptor) = command("cashout", Specs.Empty, Specs.Cashout, Specs.Empty, 0);
|
|
31
|
+
action(id, Actions.Cashout);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// @notice Return the registered CASHOUT command ID.
|
|
35
|
+
function cashoutId() internal view returns (uint) {
|
|
36
|
+
return id;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// @notice Withdraw native-asset amounts from the command account.
|
|
40
|
+
/// @param context Command context carrying a CASHOUT input stream.
|
|
41
|
+
/// @return output Empty output state.
|
|
42
|
+
/// @return credit Zero native budget credit.
|
|
43
|
+
function cashout(
|
|
44
|
+
bytes calldata context
|
|
45
|
+
) external onlyCommand returns (bytes memory output, uint credit) {
|
|
46
|
+
Execution memory exec = openCommand(context, descriptor);
|
|
47
|
+
|
|
48
|
+
while (exec.more()) {
|
|
49
|
+
cashout(exec.account, exec.unpackCashout());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return exec.close();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// @title CashoutInternal
|
|
57
|
+
/// @notice Extends cashout with optimized local pipeline dispatch.
|
|
58
|
+
abstract contract CashoutInternal is Cashout {
|
|
59
|
+
/// @notice Execute cashout directly against a calldata CASHOUT stream.
|
|
60
|
+
/// @param account Account whose native asset is withdrawn.
|
|
61
|
+
/// @param state Empty pipeline state required by the command schema.
|
|
62
|
+
/// @param input CASHOUT block stream.
|
|
63
|
+
/// @param value Native value assigned to this command; must be zero.
|
|
64
|
+
/// @return output Empty output state.
|
|
65
|
+
/// @return credit Zero native budget credit.
|
|
66
|
+
function executeCashout(
|
|
67
|
+
bytes32 account,
|
|
68
|
+
bytes memory state,
|
|
69
|
+
bytes calldata input,
|
|
70
|
+
uint128 value
|
|
71
|
+
) internal returns (bytes memory, uint) {
|
|
72
|
+
if (value != 0) revert ValueNotAllowed();
|
|
73
|
+
if (state.length != 0) revert Executions.ZeroStride();
|
|
74
|
+
if (input.length % Sizes.Cashout != 0) revert Blocks.InvalidBlock();
|
|
75
|
+
|
|
76
|
+
(uint abs, uint end) = Cursors.bounds(input);
|
|
77
|
+
while (abs < end) {
|
|
78
|
+
cashout(account, Blocks.unpackCashout(abs));
|
|
79
|
+
unchecked {
|
|
80
|
+
abs += Sizes.Cashout;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return ("", 0);
|
|
84
|
+
}
|
|
85
|
+
}
|
package/commands/Credit.sol
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {Execution, Executions, CommandBase,
|
|
4
|
+
import {Execution, Executions, CommandBase, Specs} from "./Base.sol";
|
|
5
5
|
import {CreditAccountHook} from "../core/Settlement.sol";
|
|
6
|
-
import {Blocks} from "../codec/Blocks.sol";
|
|
7
|
-
import {
|
|
6
|
+
import {Blocks, Memory} from "../codec/Blocks.sol";
|
|
7
|
+
import {Sizes} from "../codec/Specs.sol";
|
|
8
8
|
|
|
9
9
|
using Executions for Execution;
|
|
10
|
-
using Readers for Reader;
|
|
11
10
|
|
|
12
11
|
/// @title CreditAccount
|
|
13
12
|
/// @notice Command that delivers BALANCE state blocks to an account via a virtual hook.
|
|
@@ -17,7 +16,7 @@ abstract contract CreditAccount is CommandBase, CreditAccountHook {
|
|
|
17
16
|
uint private immutable id;
|
|
18
17
|
|
|
19
18
|
constructor() {
|
|
20
|
-
(id, descriptor) = command("creditAccount", Specs.Balance, Specs.Empty, Specs.Empty, 0
|
|
19
|
+
(id, descriptor) = command("creditAccount", Specs.Balance, Specs.Empty, Specs.Empty, 0);
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
/// @notice Return the registered CREDIT_ACCOUNT command ID.
|
|
@@ -28,18 +27,18 @@ abstract contract CreditAccount is CommandBase, CreditAccountHook {
|
|
|
28
27
|
/// @notice Credit each BALANCE block from the command state to the command account.
|
|
29
28
|
/// @param context Command context carrying the BALANCE state stream.
|
|
30
29
|
/// @return Empty output state.
|
|
31
|
-
/// @return
|
|
30
|
+
/// @return Zero native budget credit.
|
|
32
31
|
function creditAccount(
|
|
33
32
|
bytes calldata context
|
|
34
|
-
) external onlyCommand returns (bytes memory,
|
|
35
|
-
Execution memory exec = openCommand(context, descriptor
|
|
33
|
+
) external onlyCommand returns (bytes memory, uint) {
|
|
34
|
+
Execution memory exec = openCommand(context, descriptor);
|
|
36
35
|
|
|
37
36
|
while (exec.more()) {
|
|
38
|
-
(bytes32 asset, uint amount) = exec.unpackBalance(
|
|
37
|
+
(bytes32 asset, uint amount) = exec.unpackBalance();
|
|
39
38
|
creditAccount(exec.account, asset, amount);
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
return
|
|
41
|
+
return exec.close();
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
|
|
@@ -54,23 +53,26 @@ abstract contract CreditAccountInternal is CreditAccount {
|
|
|
54
53
|
/// @param input Empty input required by the command schema.
|
|
55
54
|
/// @param value Native value assigned to the command; must be zero.
|
|
56
55
|
/// @return output Empty output state.
|
|
57
|
-
/// @return
|
|
56
|
+
/// @return credit Zero native budget credit.
|
|
58
57
|
function executeCreditAccount(
|
|
59
58
|
bytes32 account,
|
|
60
59
|
bytes memory state,
|
|
61
60
|
bytes calldata input,
|
|
62
61
|
uint128 value
|
|
63
|
-
) internal returns (bytes memory,
|
|
62
|
+
) internal returns (bytes memory, uint) {
|
|
64
63
|
if (value != 0) revert ValueNotAllowed();
|
|
65
64
|
if (input.length != 0) revert Executions.ZeroStride();
|
|
66
65
|
if (state.length == 0) revert Blocks.EmptyRun();
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
while (
|
|
70
|
-
(bytes32 asset, uint amount) =
|
|
67
|
+
(uint abs, uint end) = Memory.bounds(state, Sizes.Balance);
|
|
68
|
+
while (abs < end) {
|
|
69
|
+
(bytes32 asset, uint amount) = Memory.unpackBalance(abs);
|
|
71
70
|
creditAccount(account, asset, amount);
|
|
71
|
+
unchecked {
|
|
72
|
+
abs += Sizes.Balance;
|
|
73
|
+
}
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
return ("",
|
|
76
|
+
return ("", 0);
|
|
75
77
|
}
|
|
76
78
|
}
|
package/commands/Debit.sol
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {Execution, Executions, CommandBase,
|
|
4
|
+
import {Execution, Executions, CommandBase, Specs} from "./Base.sol";
|
|
5
5
|
import {DebitAccountHook} from "../core/Settlement.sol";
|
|
6
6
|
import {Blocks} from "../codec/Blocks.sol";
|
|
7
7
|
import {Sizes} from "../codec/Specs.sol";
|
|
8
|
-
import {
|
|
9
|
-
import {Cur} from "../utils/Cursors.sol";
|
|
8
|
+
import {Cursors} from "../utils/Cursors.sol";
|
|
10
9
|
|
|
11
10
|
using Executions for Execution;
|
|
12
|
-
using Decoders for Cur;
|
|
13
11
|
|
|
14
12
|
/// @title DebitAccount
|
|
15
13
|
/// @notice Command that deducts AMOUNT blocks from an account and emits matching BALANCE state.
|
|
@@ -20,7 +18,7 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
|
|
|
20
18
|
uint private immutable id;
|
|
21
19
|
|
|
22
20
|
constructor() {
|
|
23
|
-
(id, descriptor) = command("debitAccount", Specs.Empty, Specs.Amount, Specs.Balance, 0
|
|
21
|
+
(id, descriptor) = command("debitAccount", Specs.Empty, Specs.Amount, Specs.Balance, 0);
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
/// @notice Return the registered DEBIT_ACCOUNT command ID.
|
|
@@ -31,26 +29,26 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
|
|
|
31
29
|
/// @notice Debit AMOUNT input blocks from the command account and output matching BALANCE blocks.
|
|
32
30
|
/// @param context Command context carrying the AMOUNT input stream.
|
|
33
31
|
/// @return BALANCE block stream matching the debited amounts.
|
|
34
|
-
/// @return
|
|
32
|
+
/// @return Zero native budget credit.
|
|
35
33
|
function debitAccount(
|
|
36
34
|
bytes calldata context
|
|
37
|
-
) external onlyCommand returns (bytes memory,
|
|
38
|
-
Execution memory exec = openCommand(context, descriptor
|
|
35
|
+
) external onlyCommand returns (bytes memory, uint) {
|
|
36
|
+
Execution memory exec = openCommand(context, descriptor);
|
|
39
37
|
|
|
40
38
|
while (exec.more()) {
|
|
41
|
-
(bytes32 asset, uint amount) = exec.unpackAmount(
|
|
39
|
+
(bytes32 asset, uint amount) = exec.unpackAmount();
|
|
42
40
|
debitAccount(exec.account, asset, amount);
|
|
43
41
|
exec.outputBalance(asset, amount);
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
return
|
|
44
|
+
return exec.close();
|
|
47
45
|
}
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
/// @title DebitAccountInternal
|
|
51
|
-
/// @notice Extends the advertised debit-account command with
|
|
49
|
+
/// @notice Extends the advertised debit-account command with optimized pipeline dispatch.
|
|
52
50
|
/// @dev This adapter is not a separate command. It uses the command ID and account hook
|
|
53
|
-
/// inherited from `DebitAccount` while
|
|
51
|
+
/// inherited from `DebitAccount` while decoding its fixed-stride input directly from calldata.
|
|
54
52
|
abstract contract DebitAccountInternal is DebitAccount {
|
|
55
53
|
/// @notice Execute the inherited debit-account command from an internal pipeline.
|
|
56
54
|
/// @param account Account whose funds are debited.
|
|
@@ -58,26 +56,32 @@ abstract contract DebitAccountInternal is DebitAccount {
|
|
|
58
56
|
/// @param input AMOUNT block stream.
|
|
59
57
|
/// @param value Native value assigned to the command; must be zero.
|
|
60
58
|
/// @return output BALANCE block stream matching the debited amounts.
|
|
61
|
-
/// @return
|
|
59
|
+
/// @return credit Zero native budget credit.
|
|
62
60
|
function executeDebitAccount(
|
|
63
61
|
bytes32 account,
|
|
64
62
|
bytes memory state,
|
|
65
63
|
bytes calldata input,
|
|
66
64
|
uint128 value
|
|
67
|
-
) internal returns (bytes memory,
|
|
65
|
+
) internal returns (bytes memory, uint) {
|
|
68
66
|
if (value != 0) revert ValueNotAllowed();
|
|
69
67
|
if (state.length != 0) revert Executions.ZeroStride();
|
|
70
|
-
|
|
68
|
+
if (input.length == 0) revert Blocks.EmptyRun();
|
|
69
|
+
if (input.length % Sizes.Amount != 0) revert Blocks.InvalidBlock();
|
|
70
|
+
|
|
71
|
+
(uint abs, uint end) = Cursors.bounds(input);
|
|
71
72
|
bytes memory output = new bytes(input.length);
|
|
72
73
|
uint i;
|
|
73
74
|
|
|
74
|
-
while (
|
|
75
|
-
(bytes32 asset, uint amount) =
|
|
75
|
+
while (abs < end) {
|
|
76
|
+
(bytes32 asset, uint amount) = Blocks.unpackAmount(abs);
|
|
76
77
|
debitAccount(account, asset, amount);
|
|
77
78
|
Blocks.writeBalance(output, i, asset, amount);
|
|
78
|
-
|
|
79
|
+
unchecked {
|
|
80
|
+
abs += Sizes.Amount;
|
|
81
|
+
i += Sizes.Balance;
|
|
82
|
+
}
|
|
79
83
|
}
|
|
80
84
|
|
|
81
|
-
return (output,
|
|
85
|
+
return (output, 0);
|
|
82
86
|
}
|
|
83
87
|
}
|
package/commands/Deposit.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 {Execution, Executions, CommandBase, Flags,
|
|
4
|
+
import {Execution, Executions, CommandBase, Flags, Specs} from "./Base.sol";
|
|
5
5
|
import {Action} from "../annotations/Action.sol";
|
|
6
6
|
import {Actions} from "../utils/Actions.sol";
|
|
7
7
|
|
|
@@ -39,26 +39,26 @@ abstract contract Deposit is CommandBase, DepositHook, Action {
|
|
|
39
39
|
|
|
40
40
|
constructor() {
|
|
41
41
|
uint id;
|
|
42
|
-
(id, descriptor) = command("deposit", Specs.Empty, Specs.Amount, Specs.Balance, 0
|
|
42
|
+
(id, descriptor) = command("deposit", Specs.Empty, Specs.Amount, Specs.Balance, 0);
|
|
43
43
|
action(id, Actions.Deposit);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/// @notice Deposit AMOUNT input blocks into the command account and output matching BALANCE blocks.
|
|
47
47
|
/// @param context Command context carrying the AMOUNT input stream.
|
|
48
48
|
/// @return BALANCE block stream matching the deposited amounts.
|
|
49
|
-
/// @return
|
|
49
|
+
/// @return Zero native budget credit.
|
|
50
50
|
function deposit(
|
|
51
51
|
bytes calldata context
|
|
52
|
-
) external onlyCommand returns (bytes memory,
|
|
53
|
-
Execution memory exec = openCommand(context, descriptor
|
|
52
|
+
) external onlyCommand returns (bytes memory, uint) {
|
|
53
|
+
Execution memory exec = openCommand(context, descriptor);
|
|
54
54
|
|
|
55
55
|
while (exec.more()) {
|
|
56
|
-
(bytes32 asset, uint amount) = exec.unpackAmount(
|
|
56
|
+
(bytes32 asset, uint amount) = exec.unpackAmount();
|
|
57
57
|
deposit(exec.account, asset, amount);
|
|
58
58
|
exec.outputBalance(asset, amount);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
return
|
|
61
|
+
return exec.close();
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -70,25 +70,25 @@ abstract contract DepositPayable is CommandBase, DepositPayableHook, Action {
|
|
|
70
70
|
|
|
71
71
|
constructor() {
|
|
72
72
|
uint id;
|
|
73
|
-
(id, descriptor) = command("depositPayable", Specs.Empty, Specs.Amount, Specs.Balance,
|
|
73
|
+
(id, descriptor) = command("depositPayable", Specs.Empty, Specs.Amount, Specs.Balance, Flags.Funded);
|
|
74
74
|
action(id, Actions.Deposit);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/// @notice Deposit AMOUNT input blocks with access to a mutable native-value budget.
|
|
78
78
|
/// @param context Command context carrying the AMOUNT input stream.
|
|
79
79
|
/// @return BALANCE block stream matching the deposited amounts.
|
|
80
|
-
/// @return
|
|
80
|
+
/// @return Native value to add to the caller's budget.
|
|
81
81
|
function depositPayable(
|
|
82
82
|
bytes calldata context
|
|
83
|
-
) external payable onlyCommand returns (bytes memory,
|
|
84
|
-
Execution memory exec = openCommand(context, descriptor
|
|
83
|
+
) external payable onlyCommand returns (bytes memory, uint) {
|
|
84
|
+
Execution memory exec = openCommand(context, descriptor);
|
|
85
85
|
|
|
86
86
|
while (exec.more()) {
|
|
87
|
-
(bytes32 asset, uint amount) = exec.unpackAmount(
|
|
87
|
+
(bytes32 asset, uint amount) = exec.unpackAmount();
|
|
88
88
|
deposit(exec.account, asset, amount, exec);
|
|
89
89
|
exec.outputBalance(asset, amount);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
return
|
|
92
|
+
return exec.close();
|
|
93
93
|
}
|
|
94
94
|
}
|