@rootzero/contracts 0.9.8 → 1.0.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/Core.sol +1 -1
- package/Endpoints.sol +3 -1
- package/Events.sol +2 -0
- package/README.md +19 -18
- package/blocks/Cursors.sol +152 -162
- package/blocks/Keys.sol +10 -6
- package/blocks/Schema.sol +17 -9
- package/blocks/Writers.sol +4 -4
- package/commands/Burn.sol +7 -4
- package/commands/Credit.sol +9 -9
- package/commands/Debit.sol +7 -4
- package/commands/Deposit.sol +14 -8
- package/commands/Payout.sol +49 -0
- package/commands/Provision.sol +14 -8
- package/commands/Relay.sol +58 -0
- package/commands/Withdraw.sol +10 -9
- package/commands/admin/AllowAssets.sol +9 -4
- package/commands/admin/Allowance.sol +7 -4
- package/commands/admin/Appoint.sol +7 -4
- package/commands/admin/Authorize.sol +7 -4
- package/commands/admin/DenyAssets.sol +9 -4
- package/commands/admin/Destroy.sol +5 -3
- package/commands/admin/Dismiss.sol +7 -4
- package/commands/admin/Execute.sol +8 -5
- package/commands/admin/Init.sol +5 -3
- package/commands/admin/Unauthorize.sol +7 -4
- package/core/Host.sol +10 -1
- package/core/Pipeline.sol +4 -3
- package/core/Runtime.sol +3 -36
- package/core/Types.sol +1 -1
- package/docs/Schema.md +0 -1
- package/events/Admin.sol +11 -8
- package/events/Chain.sol +20 -0
- package/events/Command.sol +11 -8
- package/events/Peer.sol +5 -5
- package/events/Query.sol +2 -4
- package/events/Transfer.sol +22 -0
- package/guards/Revoke.sol +3 -3
- package/package.json +1 -1
- package/peer/AllowAssets.sol +5 -3
- package/peer/Allowance.sol +5 -3
- package/peer/BalancePull.sol +5 -3
- package/peer/DenyAssets.sol +5 -3
- package/peer/Dispatch.sol +51 -0
- package/peer/Pipe.sol +7 -5
- package/peer/Settle.sol +13 -8
- package/queries/Assets.sol +3 -3
- package/queries/Balances.sol +3 -3
- package/queries/Positions.sol +3 -3
- package/utils/Accounts.sol +6 -31
- package/utils/Actions.sol +11 -9
- package/utils/Assets.sol +21 -21
- package/utils/Ids.sol +12 -2
- package/utils/Layout.sol +21 -17
- package/utils/Utils.sol +2 -2
- package/commands/Transfer.sol +0 -54
package/blocks/Schema.sol
CHANGED
|
@@ -11,8 +11,11 @@ pragma solidity ^0.8.33;
|
|
|
11
11
|
// - a block without braces has no payload, e.g. `#unit`
|
|
12
12
|
// - commas separate siblings at every level
|
|
13
13
|
// - braces define parent-child boundaries
|
|
14
|
-
// -
|
|
15
|
-
// -
|
|
14
|
+
// - command requests start with the input run when the request schema is non-empty
|
|
15
|
+
// - postcheck command requests include a constraint run after the input run; if the
|
|
16
|
+
// request schema is empty, the constraint run starts the request
|
|
17
|
+
// - command state starts with the active state run; trailing state globals may follow
|
|
18
|
+
// - run items may repeat at top level for batching
|
|
16
19
|
// - `maybe #x { ... }` marks an optional block item
|
|
17
20
|
// - `many #x { ... }` emits one generic list block containing repeated `#x` items
|
|
18
21
|
// - fixed fields are packed in declaration order
|
|
@@ -30,8 +33,8 @@ pragma solidity ^0.8.33;
|
|
|
30
33
|
// - while a balance or custody is in-flight as pipeline state, it is not simultaneously persisted
|
|
31
34
|
// in another ledger/store by this protocol
|
|
32
35
|
// - commands must preserve, transform, settle, or intentionally consume pipeline state
|
|
33
|
-
// - request blocks such as `amount(...)`, `allocation(...)`, `allowance(...)
|
|
34
|
-
//
|
|
36
|
+
// - request blocks such as `amount(...)`, `allocation(...)`, and `allowance(...)`
|
|
37
|
+
// express intent, constraints, or references
|
|
35
38
|
// - request and value/response blocks are not live state
|
|
36
39
|
//
|
|
37
40
|
// Signed blocks:
|
|
@@ -50,19 +53,20 @@ library Schemas {
|
|
|
50
53
|
string constant Node = "#node { uint id }";
|
|
51
54
|
string constant Account = "#account { bytes32 account }";
|
|
52
55
|
string constant Asset = "#asset { bytes32 asset, bytes32 meta }";
|
|
53
|
-
string constant Balance = "#balance { bytes32 asset, bytes32 meta, uint amount }";
|
|
54
56
|
string constant Amount = "#amount { bytes32 asset, bytes32 meta, uint amount }";
|
|
55
|
-
string constant
|
|
56
|
-
string constant
|
|
57
|
+
string constant Balance = "#balance { bytes32 asset, bytes32 meta, uint amount }";
|
|
58
|
+
string constant BalanceLimit = "#balanceLimit { bytes32 asset, bytes32 meta, uint min, uint max }";
|
|
57
59
|
string constant Custody = "#custody { uint host, bytes32 asset, bytes32 meta, uint amount }";
|
|
58
|
-
string constant
|
|
60
|
+
string constant CustodyLimit = "#custodyLimit { uint host, bytes32 asset, bytes32 meta, uint min, uint max }";
|
|
59
61
|
string constant Allocation = "#allocation { uint host, bytes32 asset, bytes32 meta, uint amount }";
|
|
60
62
|
string constant Allowance = "#allowance { uint host, bytes32 asset, bytes32 meta, uint amount }";
|
|
61
63
|
string constant Transaction = "#transaction { bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount }";
|
|
62
64
|
string constant Context = "#context { bytes32 account, #bytes as state, #bytes as request }";
|
|
63
|
-
string constant Pipe = "#pipe { uint value, #context { bytes32 account, #bytes as state, #bytes as
|
|
65
|
+
string constant Pipe = "#pipe { uint value, #context { bytes32 account, #bytes as state, #bytes as steps } }";
|
|
64
66
|
string constant Call = "#call { uint target, uint value, #bytes as payload }";
|
|
65
67
|
string constant Step = "#step { uint target, uint value, #bytes as request }";
|
|
68
|
+
string constant Relay = "#relay { uint chain, uint endowment, #bytes as steps }";
|
|
69
|
+
string constant Dispatch = "#dispatch { uint chain, uint endowment, #bytes as payload }";
|
|
66
70
|
string constant Bounty = "#bounty { uint amount, bytes32 relayer }";
|
|
67
71
|
string constant Fee = "#fee { uint amount }";
|
|
68
72
|
string constant Auth = "#auth { uint cid, uint deadline, #bytes as proof }";
|
|
@@ -113,12 +117,16 @@ library Sizes {
|
|
|
113
117
|
uint constant Amount = B96;
|
|
114
118
|
/// @dev BALANCE block: 8 header + 32 asset + 32 meta + 32 amount = 104 bytes
|
|
115
119
|
uint constant Balance = B96;
|
|
120
|
+
/// @dev BALANCE_LIMIT block: 8 header + 32 asset + 32 meta + 32 min + 32 max = 136 bytes
|
|
121
|
+
uint constant BalanceLimit = B128;
|
|
116
122
|
/// @dev FEE block: 8 header + 32 amount = 40 bytes
|
|
117
123
|
uint constant Fee = B32;
|
|
118
124
|
/// @dev BOUNTY block: 8 header + 32 amount + 32 relayer = 72 bytes
|
|
119
125
|
uint constant Bounty = B64;
|
|
120
126
|
/// @dev ALLOCATION/CUSTODY block: 8 header + 32 host + 32 asset + 32 meta + 32 amount = 136 bytes
|
|
121
127
|
uint constant HostAmount = B128;
|
|
128
|
+
/// @dev CUSTODY_LIMIT block: 8 header + 32 host + 32 asset + 32 meta + 32 min + 32 max = 168 bytes
|
|
129
|
+
uint constant CustodyLimit = B160;
|
|
122
130
|
/// @dev TRANSACTION block: 8 header + 32 from + 32 to + 32 asset + 32 meta + 32 amount = 168 bytes
|
|
123
131
|
uint constant Transaction = B160;
|
|
124
132
|
}
|
package/blocks/Writers.sol
CHANGED
|
@@ -894,16 +894,16 @@ library Writers {
|
|
|
894
894
|
/// @param value Native value assigned to the pipe.
|
|
895
895
|
/// @param account Command account identifier.
|
|
896
896
|
/// @param state Raw nested state payload.
|
|
897
|
-
/// @param
|
|
897
|
+
/// @param steps Raw nested step payload.
|
|
898
898
|
function appendPipe(
|
|
899
899
|
Writer memory writer,
|
|
900
900
|
uint value,
|
|
901
901
|
bytes32 account,
|
|
902
902
|
bytes memory state,
|
|
903
|
-
bytes memory
|
|
903
|
+
bytes memory steps
|
|
904
904
|
) internal pure {
|
|
905
905
|
uint i = writer.i;
|
|
906
|
-
uint len = 64 + 3 * Sizes.Header + state.length +
|
|
906
|
+
uint len = 64 + 3 * Sizes.Header + state.length + steps.length;
|
|
907
907
|
uint next = i + Sizes.Header + len;
|
|
908
908
|
i = reserve(writer, next, next);
|
|
909
909
|
|
|
@@ -912,7 +912,7 @@ library Writers {
|
|
|
912
912
|
mstore(add(p, 0x08), value)
|
|
913
913
|
}
|
|
914
914
|
|
|
915
|
-
writeBlock32BytesBytes(writer.dst, i + Sizes.Header + 32, Keys.Context, account, state,
|
|
915
|
+
writeBlock32BytesBytes(writer.dst, i + Sizes.Header + 32, Keys.Context, account, state, steps);
|
|
916
916
|
}
|
|
917
917
|
|
|
918
918
|
/// @notice Append a STATUS form block.
|
package/commands/Burn.sol
CHANGED
|
@@ -25,18 +25,21 @@ abstract contract Burn is CommandBase, BurnHook {
|
|
|
25
25
|
uint internal immutable burnId = commandId(NAME);
|
|
26
26
|
|
|
27
27
|
constructor() {
|
|
28
|
-
emit Command(host, burnId, NAME, "0:1:0", "", Keys.Balance, Keys.Empty, false);
|
|
28
|
+
emit Command(host, burnId, NAME, "0:1:0", "", Keys.Balance, Keys.Empty, false, false);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/// @notice Burn each BALANCE block from the command state.
|
|
32
|
+
/// @param c Command context; `c.state` must contain BALANCE blocks.
|
|
33
|
+
/// @return Empty output state.
|
|
31
34
|
function burn(CommandContext calldata c) external onlyCommand returns (bytes memory) {
|
|
32
|
-
(Cur memory state, ) =
|
|
35
|
+
(Cur memory state, , ) = Cursors.init(c.state, 0, 1);
|
|
33
36
|
|
|
34
|
-
while (state.i < state.
|
|
37
|
+
while (state.i < state.len) {
|
|
35
38
|
(bytes32 asset, bytes32 meta, uint amount) = state.unpackBalance();
|
|
36
39
|
burn(c.account, asset, meta, amount);
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
state.
|
|
42
|
+
state.complete();
|
|
40
43
|
return "";
|
|
41
44
|
}
|
|
42
45
|
}
|
package/commands/Credit.sol
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import { CommandBase, CommandContext, Keys } from "./Base.sol";
|
|
5
|
-
import { Cursors, Cur
|
|
5
|
+
import { Cursors, Cur } from "../Cursors.sol";
|
|
6
6
|
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
@@ -19,29 +19,29 @@ abstract contract CreditAccountHook {
|
|
|
19
19
|
/// @title CreditAccount
|
|
20
20
|
/// @notice Command that delivers BALANCE state blocks to an account via a virtual hook.
|
|
21
21
|
/// Use for internally recording credits that have already been settled externally.
|
|
22
|
-
/// An optional ACCOUNT block in the request overrides the default `c.account` destination.
|
|
23
22
|
abstract contract CreditAccount is CommandBase, CreditAccountHook {
|
|
24
23
|
string private constant NAME = "creditAccount";
|
|
25
|
-
string private constant REQUEST = string.concat(Schemas.Unit, ", maybe ", Schemas.Account);
|
|
26
24
|
|
|
27
25
|
uint internal immutable creditAccountId = commandId(NAME);
|
|
28
26
|
|
|
29
27
|
constructor() {
|
|
30
|
-
emit Command(host, creditAccountId, NAME, "0:1:0",
|
|
28
|
+
emit Command(host, creditAccountId, NAME, "0:1:0", "", Keys.Balance, Keys.Empty, false, false);
|
|
31
29
|
}
|
|
32
30
|
|
|
31
|
+
/// @notice Credit each BALANCE block from the command state to the command account.
|
|
32
|
+
/// @param c Command context; `c.state` must contain BALANCE blocks.
|
|
33
|
+
/// @return Empty output state.
|
|
33
34
|
function creditAccount(
|
|
34
35
|
CommandContext calldata c
|
|
35
36
|
) external onlyCommand returns (bytes memory) {
|
|
36
|
-
(Cur memory state, ) =
|
|
37
|
-
bytes32 to = Cursors.resolveAccount(c.request, c.account);
|
|
37
|
+
(Cur memory state, , ) = Cursors.init(c.state, 0, 1);
|
|
38
38
|
|
|
39
|
-
while (state.i < state.
|
|
39
|
+
while (state.i < state.len) {
|
|
40
40
|
(bytes32 asset, bytes32 meta, uint amount) = state.unpackBalance();
|
|
41
|
-
creditAccount(
|
|
41
|
+
creditAccount(c.account, asset, meta, amount);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
state.
|
|
44
|
+
state.complete();
|
|
45
45
|
return "";
|
|
46
46
|
}
|
|
47
47
|
}
|
package/commands/Debit.sol
CHANGED
|
@@ -27,26 +27,29 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
|
|
|
27
27
|
uint internal immutable debitAccountId = commandId(NAME);
|
|
28
28
|
|
|
29
29
|
constructor() {
|
|
30
|
-
emit Command(host, debitAccountId, NAME, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false);
|
|
30
|
+
emit Command(host, debitAccountId, NAME, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false, false);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/// @notice Override to customize request parsing or batching for debits.
|
|
34
34
|
/// The default implementation iterates AMOUNT blocks, calls
|
|
35
35
|
/// `debitAccount`, and emits matching BALANCE blocks.
|
|
36
36
|
function debitAccount(bytes32 account, bytes calldata request) internal virtual returns (bytes memory) {
|
|
37
|
-
(Cur memory input, uint groups) =
|
|
37
|
+
(Cur memory input, uint groups, ) = Cursors.init(request, 0, 1);
|
|
38
38
|
Writer memory writer = Writers.allocBalances(groups);
|
|
39
39
|
|
|
40
|
-
while (input.i < input.
|
|
40
|
+
while (input.i < input.len) {
|
|
41
41
|
(bytes32 asset, bytes32 meta, uint amount) = input.unpackAmount();
|
|
42
42
|
debitAccount(account, asset, meta, amount);
|
|
43
43
|
writer.appendBalance(asset, meta, amount);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
input.
|
|
46
|
+
input.complete();
|
|
47
47
|
return writer.finish();
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/// @notice Debit AMOUNT request blocks from the command account and output matching BALANCE blocks.
|
|
51
|
+
/// @param c Command context; `c.request` must contain AMOUNT blocks.
|
|
52
|
+
/// @return BALANCE block stream matching the debited amounts.
|
|
50
53
|
function debitAccount(
|
|
51
54
|
CommandContext calldata c
|
|
52
55
|
) external onlyCommand returns (bytes memory) {
|
package/commands/Deposit.sol
CHANGED
|
@@ -42,22 +42,25 @@ abstract contract Deposit is CommandBase, DepositHook {
|
|
|
42
42
|
uint internal immutable depositId = commandId(NAME);
|
|
43
43
|
|
|
44
44
|
constructor() {
|
|
45
|
-
emit Command(host, depositId, NAME, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false);
|
|
45
|
+
emit Command(host, depositId, NAME, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false, false);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/// @notice Deposit AMOUNT request blocks into the command account and output matching BALANCE blocks.
|
|
49
|
+
/// @param c Command context; `c.request` must contain AMOUNT blocks.
|
|
50
|
+
/// @return BALANCE block stream matching the deposited amounts.
|
|
48
51
|
function deposit(
|
|
49
52
|
CommandContext calldata c
|
|
50
53
|
) external onlyCommand returns (bytes memory) {
|
|
51
|
-
(Cur memory request, uint groups) =
|
|
54
|
+
(Cur memory request, uint groups, ) = Cursors.init(c.request, 0, 1);
|
|
52
55
|
Writer memory writer = Writers.allocBalances(groups);
|
|
53
56
|
|
|
54
|
-
while (request.i < request.
|
|
57
|
+
while (request.i < request.len) {
|
|
55
58
|
(bytes32 asset, bytes32 meta, uint amount) = request.unpackAmount();
|
|
56
59
|
deposit(c.account, asset, meta, amount);
|
|
57
60
|
writer.appendBalance(asset, meta, amount);
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
request.
|
|
63
|
+
request.complete();
|
|
61
64
|
return writer.finish();
|
|
62
65
|
}
|
|
63
66
|
}
|
|
@@ -71,24 +74,27 @@ abstract contract DepositPayable is CommandBase, Payable, DepositPayableHook {
|
|
|
71
74
|
uint internal immutable depositPayableId = commandId(NAME);
|
|
72
75
|
|
|
73
76
|
constructor() {
|
|
74
|
-
emit Command(host, depositPayableId, NAME, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, true);
|
|
77
|
+
emit Command(host, depositPayableId, NAME, "1:0:1", Schemas.Amount, Keys.Empty, Keys.Balance, false, true);
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
/// @notice Deposit AMOUNT request blocks with access to a mutable native-value budget.
|
|
81
|
+
/// @param c Command context; `c.request` must contain AMOUNT blocks.
|
|
82
|
+
/// @return BALANCE block stream matching the deposited amounts.
|
|
77
83
|
function depositPayable(
|
|
78
84
|
CommandContext calldata c
|
|
79
85
|
) external payable onlyCommand returns (bytes memory) {
|
|
80
|
-
(Cur memory request, uint groups) =
|
|
86
|
+
(Cur memory request, uint groups, ) = Cursors.init(c.request, 0, 1);
|
|
81
87
|
Writer memory writer = Writers.allocBalances(groups);
|
|
82
88
|
Budget memory budget = valueBudget();
|
|
83
89
|
|
|
84
|
-
while (request.i < request.
|
|
90
|
+
while (request.i < request.len) {
|
|
85
91
|
(bytes32 asset, bytes32 meta, uint amount) = request.unpackAmount();
|
|
86
92
|
deposit(c.account, asset, meta, amount, budget);
|
|
87
93
|
writer.appendBalance(asset, meta, amount);
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
settleValue(c.account, budget);
|
|
91
|
-
request.
|
|
97
|
+
request.complete();
|
|
92
98
|
return writer.finish();
|
|
93
99
|
}
|
|
94
100
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {CommandContext, CommandBase, Keys} from "./Base.sol";
|
|
5
|
+
import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
6
|
+
import {Accounts} from "../utils/Accounts.sol";
|
|
7
|
+
|
|
8
|
+
using Cursors for Cur;
|
|
9
|
+
|
|
10
|
+
abstract contract PayoutHook {
|
|
11
|
+
/// @notice Override to pay `amount` from `account` to `to`.
|
|
12
|
+
/// Called once per paired BALANCE state block and ACCOUNT request block.
|
|
13
|
+
/// @param account Source account identifier.
|
|
14
|
+
/// @param to Destination account identifier.
|
|
15
|
+
/// @param asset Asset identifier.
|
|
16
|
+
/// @param meta Asset metadata slot.
|
|
17
|
+
/// @param amount Amount to pay out.
|
|
18
|
+
function payout(bytes32 account, bytes32 to, bytes32 asset, bytes32 meta, uint amount) internal virtual;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// @title Payout
|
|
22
|
+
/// @notice Command that sinks BALANCE state blocks to matching ACCOUNT request blocks.
|
|
23
|
+
/// Each BALANCE block is paired with one ACCOUNT block at the same position.
|
|
24
|
+
abstract contract Payout is CommandBase, PayoutHook {
|
|
25
|
+
string private constant NAME = "payout";
|
|
26
|
+
|
|
27
|
+
uint internal immutable payoutId = commandId(NAME);
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
emit Command(host, payoutId, NAME, "1:1:0", Schemas.Account, Keys.Balance, Keys.Empty, false, false);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// @notice Pay out BALANCE state blocks to matching ACCOUNT request blocks.
|
|
34
|
+
/// @param c Command context; `c.state` must contain BALANCE blocks and `c.request` matching ACCOUNT blocks.
|
|
35
|
+
/// @return Empty output state.
|
|
36
|
+
function payout(CommandContext calldata c) external onlyCommand returns (bytes memory) {
|
|
37
|
+
(Cur memory state, uint groups, ) = Cursors.init(c.state, 0, 1);
|
|
38
|
+
(Cur memory request, ) = Cursors.init(c.request, 0, 1, groups);
|
|
39
|
+
|
|
40
|
+
while (state.i < state.len) {
|
|
41
|
+
(bytes32 asset, bytes32 meta, uint amount) = state.unpackBalance();
|
|
42
|
+
bytes32 to = Accounts.ensure(request.unpackAccount());
|
|
43
|
+
payout(c.account, to, asset, meta, amount);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
state.complete();
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
}
|
package/commands/Provision.sol
CHANGED
|
@@ -38,20 +38,23 @@ abstract contract Provision is CommandBase, ProvisionHook {
|
|
|
38
38
|
uint internal immutable provisionId = commandId(NAME);
|
|
39
39
|
|
|
40
40
|
constructor() {
|
|
41
|
-
emit Command(host, provisionId, NAME, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, false);
|
|
41
|
+
emit Command(host, provisionId, NAME, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, false, false);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/// @notice Provision ALLOCATION request blocks and output matching CUSTODY state blocks.
|
|
45
|
+
/// @param c Command context; `c.request` must contain ALLOCATION blocks.
|
|
46
|
+
/// @return CUSTODY block stream matching the provisioned allocations.
|
|
44
47
|
function provision(CommandContext calldata c) external onlyCommand returns (bytes memory) {
|
|
45
|
-
(Cur memory request, uint groups) =
|
|
48
|
+
(Cur memory request, uint groups, ) = Cursors.init(c.request, 0, 1);
|
|
46
49
|
Writer memory writer = Writers.allocCustodies(groups);
|
|
47
50
|
|
|
48
|
-
while (request.i < request.
|
|
51
|
+
while (request.i < request.len) {
|
|
49
52
|
HostAmount memory allocation = request.unpackAllocationValue();
|
|
50
53
|
provision(c.account, allocation);
|
|
51
54
|
writer.appendCustody(allocation);
|
|
52
55
|
}
|
|
53
56
|
|
|
54
|
-
request.
|
|
57
|
+
request.complete();
|
|
55
58
|
return writer.finish();
|
|
56
59
|
}
|
|
57
60
|
}
|
|
@@ -66,24 +69,27 @@ abstract contract ProvisionPayable is CommandBase, Payable, ProvisionPayableHook
|
|
|
66
69
|
uint internal immutable provisionPayableId = commandId(NAME);
|
|
67
70
|
|
|
68
71
|
constructor() {
|
|
69
|
-
emit Command(host, provisionPayableId, NAME, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, true);
|
|
72
|
+
emit Command(host, provisionPayableId, NAME, "1:0:1", Schemas.Allocation, Keys.Empty, Keys.Custody, false, true);
|
|
70
73
|
}
|
|
71
74
|
|
|
75
|
+
/// @notice Provision ALLOCATION request blocks with access to a mutable native-value budget.
|
|
76
|
+
/// @param c Command context; `c.request` must contain ALLOCATION blocks.
|
|
77
|
+
/// @return CUSTODY block stream matching the provisioned allocations.
|
|
72
78
|
function provisionPayable(
|
|
73
79
|
CommandContext calldata c
|
|
74
80
|
) external payable onlyCommand returns (bytes memory) {
|
|
75
|
-
(Cur memory request, uint groups) =
|
|
81
|
+
(Cur memory request, uint groups, ) = Cursors.init(c.request, 0, 1);
|
|
76
82
|
Writer memory writer = Writers.allocCustodies(groups);
|
|
77
83
|
Budget memory budget = valueBudget();
|
|
78
84
|
|
|
79
|
-
while (request.i < request.
|
|
85
|
+
while (request.i < request.len) {
|
|
80
86
|
HostAmount memory allocation = request.unpackAllocationValue();
|
|
81
87
|
provision(c.account, allocation, budget);
|
|
82
88
|
writer.appendCustody(allocation);
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
settleValue(c.account, budget);
|
|
86
|
-
request.
|
|
92
|
+
request.complete();
|
|
87
93
|
return writer.finish();
|
|
88
94
|
}
|
|
89
95
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {CommandBase, CommandContext, Keys} from "./Base.sol";
|
|
5
|
+
import {Payable} from "../core/Payable.sol";
|
|
6
|
+
import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
7
|
+
import {Budget} from "../utils/Value.sol";
|
|
8
|
+
|
|
9
|
+
using Cursors for Cur;
|
|
10
|
+
|
|
11
|
+
abstract contract RelayPayableHook {
|
|
12
|
+
/// @notice Override to relay `steps` to `chain` with the current account and state.
|
|
13
|
+
/// @param chain Destination chain node ID.
|
|
14
|
+
/// @param endowment Native value requested for the destination pipe. The hook
|
|
15
|
+
/// decides how much source-chain budget must be spent to fund this value on
|
|
16
|
+
/// the destination chain.
|
|
17
|
+
/// @param account Command account identifier.
|
|
18
|
+
/// @param state Current command state block stream.
|
|
19
|
+
/// @param steps Embedded destination step block stream.
|
|
20
|
+
/// @param budget Source-chain native-value budget available for transport
|
|
21
|
+
/// fees and destination endowment funding.
|
|
22
|
+
function relay(
|
|
23
|
+
uint chain,
|
|
24
|
+
uint endowment,
|
|
25
|
+
bytes32 account,
|
|
26
|
+
bytes calldata state,
|
|
27
|
+
bytes calldata steps,
|
|
28
|
+
Budget memory budget
|
|
29
|
+
) internal virtual;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// @title RelayPayable
|
|
33
|
+
/// @notice Command that forwards one RELAY block to a host-defined relay hook.
|
|
34
|
+
/// Reverts unless the request contains exactly one RELAY block, preventing
|
|
35
|
+
/// the same state from being duplicated across multiple relays.
|
|
36
|
+
/// Produces no output state.
|
|
37
|
+
abstract contract RelayPayable is CommandBase, Payable, RelayPayableHook {
|
|
38
|
+
string private constant NAME = "relayPayable";
|
|
39
|
+
|
|
40
|
+
uint internal immutable relayPayableId = commandId(NAME);
|
|
41
|
+
|
|
42
|
+
constructor() {
|
|
43
|
+
emit Command(host, relayPayableId, NAME, "1:0:0", Schemas.Relay, Keys.Any, Keys.Empty, false, true);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// @notice Relay one RELAY request block with the command account and current state.
|
|
47
|
+
/// @param c Command context; `c.request` must contain exactly one RELAY block.
|
|
48
|
+
/// @return output Empty output state.
|
|
49
|
+
function relayPayable(CommandContext calldata c) external payable onlyCommand returns (bytes memory output) {
|
|
50
|
+
(Cur memory request, ) = Cursors.init(c.request, 0, 1, 1);
|
|
51
|
+
Budget memory budget = valueBudget();
|
|
52
|
+
|
|
53
|
+
(uint chain, uint endowment, bytes calldata steps) = request.unpackRelay();
|
|
54
|
+
relay(chain, endowment, c.account, c.state, steps, budget);
|
|
55
|
+
request.complete();
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
}
|
package/commands/Withdraw.sol
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import { CommandContext, CommandBase, Keys } from "./Base.sol";
|
|
5
|
-
import { Cursors, Cur
|
|
5
|
+
import { Cursors, Cur } from "../Cursors.sol";
|
|
6
6
|
using Cursors for Cur;
|
|
7
7
|
|
|
8
8
|
abstract contract WithdrawHook {
|
|
9
9
|
/// @notice Override to send funds to `account`.
|
|
10
10
|
/// Called once per BALANCE block in state.
|
|
11
|
-
/// @param account Destination account identifier
|
|
11
|
+
/// @param account Destination account identifier.
|
|
12
12
|
/// @param asset Asset identifier.
|
|
13
13
|
/// @param meta Asset metadata slot.
|
|
14
14
|
/// @param amount Amount to deliver.
|
|
@@ -21,26 +21,27 @@ abstract contract WithdrawHook {
|
|
|
21
21
|
/// For internal balance credits, use `creditAccount` instead.
|
|
22
22
|
abstract contract Withdraw is CommandBase, WithdrawHook {
|
|
23
23
|
string private constant NAME = "withdraw";
|
|
24
|
-
string private constant REQUEST = string.concat(Schemas.Unit, ", maybe ", Schemas.Account);
|
|
25
24
|
|
|
26
25
|
uint internal immutable withdrawId = commandId(NAME);
|
|
27
26
|
|
|
28
27
|
constructor() {
|
|
29
|
-
emit Command(host, withdrawId, NAME, "0:1:0",
|
|
28
|
+
emit Command(host, withdrawId, NAME, "0:1:0", "", Keys.Balance, Keys.Empty, false, false);
|
|
30
29
|
}
|
|
31
30
|
|
|
31
|
+
/// @notice Withdraw each BALANCE block from the command state to the command account.
|
|
32
|
+
/// @param c Command context; `c.state` must contain BALANCE blocks.
|
|
33
|
+
/// @return Empty output state.
|
|
32
34
|
function withdraw(
|
|
33
35
|
CommandContext calldata c
|
|
34
36
|
) external onlyCommand returns (bytes memory) {
|
|
35
|
-
(Cur memory state, ) =
|
|
36
|
-
bytes32 to = Cursors.resolveAccount(c.request, c.account);
|
|
37
|
+
(Cur memory state, , ) = Cursors.init(c.state, 0, 1);
|
|
37
38
|
|
|
38
|
-
while (state.i < state.
|
|
39
|
+
while (state.i < state.len) {
|
|
39
40
|
(bytes32 asset, bytes32 meta, uint amount) = state.unpackBalance();
|
|
40
|
-
withdraw(
|
|
41
|
+
withdraw(c.account, asset, meta, amount);
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
state.
|
|
44
|
+
state.complete();
|
|
44
45
|
return "";
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -9,6 +9,8 @@ using Cursors for Cur;
|
|
|
9
9
|
abstract contract AllowAssetsHook {
|
|
10
10
|
/// @dev Override to allow a single asset/meta pair.
|
|
11
11
|
/// Called once per ASSET block in the request.
|
|
12
|
+
/// @param asset Asset identifier.
|
|
13
|
+
/// @param meta Asset metadata slot.
|
|
12
14
|
function allowAsset(bytes32 asset, bytes32 meta) internal virtual;
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -21,20 +23,23 @@ abstract contract AllowAssets is CommandBase, AdminEvent, AllowAssetsHook {
|
|
|
21
23
|
uint internal immutable allowAssetsId = commandId(NAME);
|
|
22
24
|
|
|
23
25
|
constructor() {
|
|
24
|
-
emit Admin(host, allowAssetsId, NAME, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false);
|
|
26
|
+
emit Admin(host, allowAssetsId, NAME, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false, false);
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
/// @notice Allow each ASSET block in the admin request.
|
|
30
|
+
/// @param c Admin command context; `c.request` must contain ASSET blocks.
|
|
31
|
+
/// @return Empty output state.
|
|
27
32
|
function allowAssets(
|
|
28
33
|
CommandContext calldata c
|
|
29
34
|
) external onlyAdmin(c.account) returns (bytes memory) {
|
|
30
|
-
(Cur memory request, ) =
|
|
35
|
+
(Cur memory request, , ) = Cursors.init(c.request, 0, 1);
|
|
31
36
|
|
|
32
|
-
while (request.i < request.
|
|
37
|
+
while (request.i < request.len) {
|
|
33
38
|
(bytes32 asset, bytes32 meta) = request.unpackAsset();
|
|
34
39
|
allowAsset(asset, meta);
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
request.
|
|
42
|
+
request.complete();
|
|
38
43
|
return "";
|
|
39
44
|
}
|
|
40
45
|
}
|
|
@@ -26,18 +26,21 @@ abstract contract Allowance is CommandBase, AdminEvent, AllowanceHook {
|
|
|
26
26
|
uint internal immutable allowanceId = commandId(NAME);
|
|
27
27
|
|
|
28
28
|
constructor() {
|
|
29
|
-
emit Admin(host, allowanceId, NAME, "1:0:0", Schemas.Allowance, Keys.Empty, Keys.Empty, false);
|
|
29
|
+
emit Admin(host, allowanceId, NAME, "1:0:0", Schemas.Allowance, Keys.Empty, Keys.Empty, false, false);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/// @notice Apply each ALLOWANCE block in the admin request.
|
|
33
|
+
/// @param c Admin command context; `c.request` must contain ALLOWANCE blocks.
|
|
34
|
+
/// @return Empty output state.
|
|
32
35
|
function allowance(CommandContext calldata c) external onlyAdmin(c.account) returns (bytes memory) {
|
|
33
|
-
(Cur memory request, ) =
|
|
36
|
+
(Cur memory request, , ) = Cursors.init(c.request, 0, 1);
|
|
34
37
|
|
|
35
|
-
while (request.i < request.
|
|
38
|
+
while (request.i < request.len) {
|
|
36
39
|
(uint peer, bytes32 asset, bytes32 meta, uint amount) = request.unpackAllowance();
|
|
37
40
|
allowance(peer, asset, meta, amount);
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
request.
|
|
43
|
+
request.complete();
|
|
41
44
|
return "";
|
|
42
45
|
}
|
|
43
46
|
}
|
|
@@ -16,20 +16,23 @@ abstract contract Appoint is CommandBase, AdminEvent {
|
|
|
16
16
|
uint internal immutable appointId = commandId(NAME);
|
|
17
17
|
|
|
18
18
|
constructor() {
|
|
19
|
-
emit Admin(host, appointId, NAME, "1:0:0", Schemas.Account, Keys.Empty, Keys.Empty, false);
|
|
19
|
+
emit Admin(host, appointId, NAME, "1:0:0", Schemas.Account, Keys.Empty, Keys.Empty, false, false);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/// @notice Appoint each ACCOUNT block in the admin request as a guardian.
|
|
23
|
+
/// @param c Admin command context; `c.request` must contain ACCOUNT blocks.
|
|
24
|
+
/// @return Empty output state.
|
|
22
25
|
function appoint(
|
|
23
26
|
CommandContext calldata c
|
|
24
27
|
) external onlyAdmin(c.account) returns (bytes memory) {
|
|
25
|
-
(Cur memory request, ) =
|
|
28
|
+
(Cur memory request, , ) = Cursors.init(c.request, 0, 1);
|
|
26
29
|
|
|
27
|
-
while (request.i < request.
|
|
30
|
+
while (request.i < request.len) {
|
|
28
31
|
bytes32 account = request.unpackAccount();
|
|
29
32
|
setGuardian(account, true);
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
request.
|
|
35
|
+
request.complete();
|
|
33
36
|
return "";
|
|
34
37
|
}
|
|
35
38
|
}
|
|
@@ -16,20 +16,23 @@ abstract contract Authorize is CommandBase, AdminEvent {
|
|
|
16
16
|
uint internal immutable authorizeId = commandId(NAME);
|
|
17
17
|
|
|
18
18
|
constructor() {
|
|
19
|
-
emit Admin(host, authorizeId, NAME, "1:0:0", Schemas.Node, Keys.Empty, Keys.Empty, false);
|
|
19
|
+
emit Admin(host, authorizeId, NAME, "1:0:0", Schemas.Node, Keys.Empty, Keys.Empty, false, false);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/// @notice Authorize each NODE block in the admin request.
|
|
23
|
+
/// @param c Admin command context; `c.request` must contain NODE blocks.
|
|
24
|
+
/// @return Empty output state.
|
|
22
25
|
function authorize(
|
|
23
26
|
CommandContext calldata c
|
|
24
27
|
) external onlyAdmin(c.account) returns (bytes memory) {
|
|
25
|
-
(Cur memory request, ) =
|
|
28
|
+
(Cur memory request, , ) = Cursors.init(c.request, 0, 1);
|
|
26
29
|
|
|
27
|
-
while (request.i < request.
|
|
30
|
+
while (request.i < request.len) {
|
|
28
31
|
uint node = request.unpackNode();
|
|
29
32
|
setNode(node, true);
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
request.
|
|
35
|
+
request.complete();
|
|
33
36
|
return "";
|
|
34
37
|
}
|
|
35
38
|
}
|
|
@@ -9,6 +9,8 @@ using Cursors for Cur;
|
|
|
9
9
|
abstract contract DenyAssetsHook {
|
|
10
10
|
/// @dev Override to deny a single asset/meta pair.
|
|
11
11
|
/// Called once per ASSET block in the request.
|
|
12
|
+
/// @param asset Asset identifier.
|
|
13
|
+
/// @param meta Asset metadata slot.
|
|
12
14
|
function denyAsset(bytes32 asset, bytes32 meta) internal virtual;
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -21,20 +23,23 @@ abstract contract DenyAssets is CommandBase, AdminEvent, DenyAssetsHook {
|
|
|
21
23
|
uint internal immutable denyAssetsId = commandId(NAME);
|
|
22
24
|
|
|
23
25
|
constructor() {
|
|
24
|
-
emit Admin(host, denyAssetsId, NAME, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false);
|
|
26
|
+
emit Admin(host, denyAssetsId, NAME, "1:0:0", Schemas.Asset, Keys.Empty, Keys.Empty, false, false);
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
/// @notice Deny each ASSET block in the admin request.
|
|
30
|
+
/// @param c Admin command context; `c.request` must contain ASSET blocks.
|
|
31
|
+
/// @return Empty output state.
|
|
27
32
|
function denyAssets(
|
|
28
33
|
CommandContext calldata c
|
|
29
34
|
) external onlyAdmin(c.account) returns (bytes memory) {
|
|
30
|
-
(Cur memory request, ) =
|
|
35
|
+
(Cur memory request, , ) = Cursors.init(c.request, 0, 1);
|
|
31
36
|
|
|
32
|
-
while (request.i < request.
|
|
37
|
+
while (request.i < request.len) {
|
|
33
38
|
(bytes32 asset, bytes32 meta) = request.unpackAsset();
|
|
34
39
|
denyAsset(asset, meta);
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
request.
|
|
42
|
+
request.complete();
|
|
38
43
|
return "";
|
|
39
44
|
}
|
|
40
45
|
}
|