@rootzero/contracts 0.5.0 → 0.6.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 (97) hide show
  1. package/{contracts/Commands.sol → Commands.sol} +7 -5
  2. package/{contracts/Utils.sol → Utils.sol} +2 -2
  3. package/{contracts/commands → commands}/Base.sol +28 -0
  4. package/{contracts/commands → commands}/Borrow.sol +5 -4
  5. package/{contracts/commands → commands}/Burn.sol +3 -2
  6. package/{contracts/commands → commands}/Create.sol +3 -2
  7. package/{contracts/commands → commands}/Credit.sol +3 -2
  8. package/{contracts/commands → commands}/Debit.sol +3 -2
  9. package/commands/Deposit.sol +104 -0
  10. package/{contracts/commands → commands}/Liquidate.sol +5 -4
  11. package/{contracts/commands → commands}/Liquidity.sol +9 -8
  12. package/{contracts/commands → commands}/Mint.sol +3 -2
  13. package/{contracts/commands → commands}/Pipe.sol +17 -20
  14. package/commands/Provision.sol +123 -0
  15. package/{contracts/commands → commands}/Reclaim.sol +3 -2
  16. package/{contracts/commands → commands}/Redeem.sol +5 -4
  17. package/{contracts/commands → commands}/Remove.sol +3 -2
  18. package/{contracts/commands → commands}/Repay.sol +5 -4
  19. package/{contracts/commands → commands}/Settle.sol +3 -2
  20. package/{contracts/commands → commands}/Stake.sol +7 -6
  21. package/{contracts/commands → commands}/Supply.sol +3 -2
  22. package/{contracts/commands → commands}/Swap.sol +5 -4
  23. package/{contracts/commands → commands}/Transfer.sol +3 -2
  24. package/{contracts/commands → commands}/Unstake.sol +3 -2
  25. package/{contracts/commands → commands}/Withdraw.sol +3 -2
  26. package/{contracts/commands → commands}/admin/Allocate.sol +3 -2
  27. package/{contracts/commands → commands}/admin/AllowAssets.sol +3 -2
  28. package/{contracts/commands → commands}/admin/Authorize.sol +3 -2
  29. package/{contracts/commands → commands}/admin/DenyAssets.sol +3 -2
  30. package/{contracts/commands → commands}/admin/Destroy.sol +3 -2
  31. package/{contracts/commands → commands}/admin/Init.sol +3 -2
  32. package/{contracts/commands → commands}/admin/Relocate.sol +13 -9
  33. package/{contracts/commands → commands}/admin/Unauthorize.sol +3 -2
  34. package/{contracts/core → core}/Host.sol +3 -3
  35. package/docs/GETTING_STARTED.md +286 -0
  36. package/{contracts/events → events}/Command.sol +12 -5
  37. package/{contracts/events → events}/Peer.sol +4 -2
  38. package/package.json +17 -33
  39. package/{contracts/peer → peer}/AllowAssets.sol +2 -2
  40. package/{contracts/peer → peer}/DenyAssets.sol +2 -2
  41. package/{contracts/peer → peer}/Pull.sol +2 -2
  42. package/{contracts/peer → peer}/Push.sol +2 -2
  43. package/{contracts/peer → peer}/Settle.sol +2 -2
  44. package/{contracts/utils → utils}/Utils.sol +8 -0
  45. package/{contracts/utils → utils}/Value.sol +15 -6
  46. package/contracts/commands/Deposit.sol +0 -57
  47. package/contracts/commands/Provision.sol +0 -82
  48. package/contracts/test/TestBorrowHost.sol +0 -72
  49. package/contracts/test/TestBurnHost.sol +0 -31
  50. package/contracts/test/TestCreateHost.sol +0 -40
  51. package/contracts/test/TestCursorHelper.sol +0 -191
  52. package/contracts/test/TestDiscovery.sol +0 -9
  53. package/contracts/test/TestECDSA.sol +0 -19
  54. package/contracts/test/TestHost.sol +0 -218
  55. package/contracts/test/TestLiquidityHost.sol +0 -167
  56. package/contracts/test/TestMintHost.sol +0 -50
  57. package/contracts/test/TestOperation.sol +0 -21
  58. package/contracts/test/TestPeerHost.sol +0 -57
  59. package/contracts/test/TestReclaimHost.sol +0 -55
  60. package/contracts/test/TestRejectEther.sol +0 -11
  61. package/contracts/test/TestRemoveHost.sol +0 -40
  62. package/contracts/test/TestSupplyHost.sol +0 -25
  63. package/contracts/test/TestSwapHost.sol +0 -67
  64. package/contracts/test/TestUtils.sol +0 -184
  65. package/contracts/test/TestValidator.sol +0 -13
  66. /package/{contracts/Core.sol → Core.sol} +0 -0
  67. /package/{contracts/Cursors.sol → Cursors.sol} +0 -0
  68. /package/{contracts/Events.sol → Events.sol} +0 -0
  69. /package/{contracts/blocks → blocks}/Cursors.sol +0 -0
  70. /package/{contracts/blocks → blocks}/Keys.sol +0 -0
  71. /package/{contracts/blocks → blocks}/Schema.sol +0 -0
  72. /package/{contracts/blocks → blocks}/Writers.sol +0 -0
  73. /package/{contracts/core → core}/Access.sol +0 -0
  74. /package/{contracts/core → core}/Balances.sol +0 -0
  75. /package/{contracts/core → core}/Operation.sol +0 -0
  76. /package/{contracts/core → core}/Validator.sol +0 -0
  77. /package/{contracts/events → events}/Access.sol +0 -0
  78. /package/{contracts/events → events}/Asset.sol +0 -0
  79. /package/{contracts/events → events}/Balance.sol +0 -0
  80. /package/{contracts/events → events}/Collateral.sol +0 -0
  81. /package/{contracts/events → events}/Debt.sol +0 -0
  82. /package/{contracts/events → events}/Deposit.sol +0 -0
  83. /package/{contracts/events → events}/Emitter.sol +0 -0
  84. /package/{contracts/events → events}/Governed.sol +0 -0
  85. /package/{contracts/events → events}/HostAnnounced.sol +0 -0
  86. /package/{contracts/events → events}/Listing.sol +0 -0
  87. /package/{contracts/events → events}/Quote.sol +0 -0
  88. /package/{contracts/events → events}/RootZero.sol +0 -0
  89. /package/{contracts/events → events}/Withdraw.sol +0 -0
  90. /package/{contracts/interfaces → interfaces}/IHostDiscovery.sol +0 -0
  91. /package/{contracts/peer → peer}/Base.sol +0 -0
  92. /package/{contracts/utils → utils}/Accounts.sol +0 -0
  93. /package/{contracts/utils → utils}/Assets.sol +0 -0
  94. /package/{contracts/utils → utils}/ECDSA.sol +0 -0
  95. /package/{contracts/utils → utils}/Ids.sol +0 -0
  96. /package/{contracts/utils → utils}/Layout.sol +0 -0
  97. /package/{contracts/utils → utils}/State.sol +0 -0
@@ -4,20 +4,20 @@ pragma solidity ^0.8.33;
4
4
  // Aggregator: re-exports all command and peer abstractions.
5
5
  // Import this file to inherit from any command or peer base contract without managing individual paths.
6
6
 
7
- import { CommandBase, CommandContext } from "./commands/Base.sol";
7
+ import { CommandBase, CommandContext, CommandPayable } from "./commands/Base.sol";
8
8
  import { State } from "./utils/State.sol";
9
9
  import { BorrowAgainstBalanceToBalance, BorrowAgainstCustodyToBalance } from "./commands/Borrow.sol";
10
10
  import { Burn } from "./commands/Burn.sol";
11
11
  import { Create } from "./commands/Create.sol";
12
12
  import { CreditAccount } from "./commands/Credit.sol";
13
13
  import { DebitAccount } from "./commands/Debit.sol";
14
- import { Deposit } from "./commands/Deposit.sol";
14
+ import { Deposit, DepositPayable } from "./commands/Deposit.sol";
15
15
  import { Remove } from "./commands/Remove.sol";
16
16
  import { AddLiquidityFromBalancesToBalances, AddLiquidityFromCustodiesToBalances, RemoveLiquidityFromBalanceToBalances, RemoveLiquidityFromCustodyToBalances } from "./commands/Liquidity.sol";
17
17
  import { LiquidateFromBalanceToBalances, LiquidateFromCustodyToBalances } from "./commands/Liquidate.sol";
18
18
  import { MintToBalances } from "./commands/Mint.sol";
19
- import { Pipe } from "./commands/Pipe.sol";
20
- import { Provision, ProvisionFromBalance } from "./commands/Provision.sol";
19
+ import { PipePayable } from "./commands/Pipe.sol";
20
+ import { Provision, ProvisionPayable, ProvisionFromBalance } from "./commands/Provision.sol";
21
21
  import { ReclaimToBalances } from "./commands/Reclaim.sol";
22
22
  import { RedeemFromBalanceToBalances, RedeemFromCustodyToBalances } from "./commands/Redeem.sol";
23
23
  import { RepayFromBalanceToBalances, RepayFromCustodyToBalances } from "./commands/Repay.sol";
@@ -33,7 +33,7 @@ import { Destroy } from "./commands/admin/Destroy.sol";
33
33
  import { Authorize } from "./commands/admin/Authorize.sol";
34
34
  import { DenyAssets } from "./commands/admin/DenyAssets.sol";
35
35
  import { Init } from "./commands/admin/Init.sol";
36
- import { Relocate } from "./commands/admin/Relocate.sol";
36
+ import { RelocatePayable } from "./commands/admin/Relocate.sol";
37
37
  import { Allocate } from "./commands/admin/Allocate.sol";
38
38
  import { Unauthorize } from "./commands/admin/Unauthorize.sol";
39
39
  import { PeerBase } from "./peer/Base.sol";
@@ -41,6 +41,8 @@ import { PeerAllowAssets } from "./peer/AllowAssets.sol";
41
41
  import { PeerDenyAssets } from "./peer/DenyAssets.sol";
42
42
  import { PeerPull } from "./peer/Pull.sol";
43
43
  import { PeerPush } from "./peer/Push.sol";
44
+ import { PeerSettle } from "./peer/Settle.sol";
45
+
44
46
 
45
47
 
46
48
 
@@ -11,8 +11,8 @@ import { ECDSA } from "./utils/ECDSA.sol";
11
11
  import { Ids, Selectors } from "./utils/Ids.sol";
12
12
  import { Layout } from "./utils/Layout.sol";
13
13
  import { Schemas } from "./blocks/Schema.sol";
14
- import { addrOr, applyBps, beforeBps, bytes32ToString, divisible, isFamily, isLocal, isLocalFamily, matchesBase, MAX_BPS, max8, max16, max24, max32, max40, max64, max96, max128, max160, NotDivisible, toLocalBase, toLocalFamily, toUnspecifiedBase, ValueOverflow } from "./utils/Utils.sol";
15
- import { Values } from "./utils/Value.sol";
14
+ import { addrOr, applyBps, beforeBps, bytes32ToString, divisible, isFamily, isLocal, isLocalFamily, matchesBase, MAX_BPS, max8, max16, max24, max32, max40, max64, max96, max128, max160, NotDivisible, retryTicket, toLocalBase, toLocalFamily, toUnspecifiedBase, ValueOverflow } from "./utils/Utils.sol";
15
+ import { Budget, Values } from "./utils/Value.sol";
16
16
 
17
17
 
18
18
 
@@ -6,6 +6,7 @@ import {Cur} from "../Cursors.sol";
6
6
  import {CommandEvent} from "../events/Command.sol";
7
7
  import {State} from "../utils/State.sol";
8
8
  import {Ids, Selectors} from "../utils/Ids.sol";
9
+ import {Budget, Values} from "../utils/Value.sol";
9
10
 
10
11
  /// @notice Execution context passed to every command invocation.
11
12
  struct CommandContext {
@@ -63,3 +64,30 @@ abstract contract CommandBase is OperationBase, CommandEvent {
63
64
  return Ids.toCommand(Selectors.command(name), address(this));
64
65
  }
65
66
  }
67
+
68
+ /// @title CommandPayable
69
+ /// @notice Abstract base for commands that accept native value (`msg.value`).
70
+ /// Provides a shared settlement hook for any unspent value remaining in the
71
+ /// command's mutable budget after execution completes.
72
+ abstract contract CommandPayable is CommandBase {
73
+ /// @dev Thrown when a payable command completes with unspent native value.
74
+ /// Override `settleValue` to implement refund or forwarding behavior instead.
75
+ error UnusedValue(uint remaining);
76
+
77
+ /// @notice Settle any remaining native value after command execution.
78
+ /// The default implementation rejects leftover value by reverting with
79
+ /// `UnusedValue(remaining)`. Override this hook to refund or redirect
80
+ /// unused value for specific payable commands.
81
+ /// @param account Caller's account identifier for the current invocation.
82
+ /// @param budget Mutable native-value budget used during command execution.
83
+ function settleValue(
84
+ bytes32 account,
85
+ Budget memory budget
86
+ ) internal virtual {
87
+ account;
88
+ uint remaining = Values.drain(budget);
89
+ if (remaining != 0) revert UnusedValue(remaining);
90
+ }
91
+ }
92
+
93
+
@@ -16,7 +16,7 @@ abstract contract BorrowAgainstCustodyToBalance is CommandBase {
16
16
  uint internal immutable borrowAgainstCustodyToBalanceId = commandId(BACTB);
17
17
 
18
18
  constructor(string memory input) {
19
- emit Command(host, BACTB, input, borrowAgainstCustodyToBalanceId, State.Custodies, State.Balances);
19
+ emit Command(host, BACTB, input, borrowAgainstCustodyToBalanceId, State.Custodies, State.Balances, false);
20
20
  }
21
21
 
22
22
  /// @dev Override to borrow against a custody position.
@@ -30,7 +30,7 @@ abstract contract BorrowAgainstCustodyToBalance is CommandBase {
30
30
 
31
31
  function borrowAgainstCustodyToBalance(
32
32
  CommandContext calldata c
33
- ) external payable onlyCommand(borrowAgainstCustodyToBalanceId, c.target) returns (bytes memory) {
33
+ ) external onlyCommand(borrowAgainstCustodyToBalanceId, c.target) returns (bytes memory) {
34
34
  (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
35
35
  Cur memory request = cursor(c.request);
36
36
  Writer memory writer = Writers.allocBalances(stateCount);
@@ -51,7 +51,7 @@ abstract contract BorrowAgainstBalanceToBalance is CommandBase {
51
51
  uint internal immutable borrowAgainstBalanceToBalanceId = commandId(BABTB);
52
52
 
53
53
  constructor(string memory input) {
54
- emit Command(host, BABTB, input, borrowAgainstBalanceToBalanceId, State.Balances, State.Balances);
54
+ emit Command(host, BABTB, input, borrowAgainstBalanceToBalanceId, State.Balances, State.Balances, false);
55
55
  }
56
56
 
57
57
  /// @dev Override to borrow against a balance position.
@@ -65,7 +65,7 @@ abstract contract BorrowAgainstBalanceToBalance is CommandBase {
65
65
 
66
66
  function borrowAgainstBalanceToBalance(
67
67
  CommandContext calldata c
68
- ) external payable onlyCommand(borrowAgainstBalanceToBalanceId, c.target) returns (bytes memory) {
68
+ ) external onlyCommand(borrowAgainstBalanceToBalanceId, c.target) returns (bytes memory) {
69
69
  (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
70
70
  Cur memory request = cursor(c.request);
71
71
  Writer memory writer = Writers.allocBalances(stateCount);
@@ -86,3 +86,4 @@ abstract contract BorrowAgainstBalanceToBalance is CommandBase {
86
86
 
87
87
 
88
88
 
89
+
@@ -14,7 +14,7 @@ abstract contract Burn is CommandBase {
14
14
  uint internal immutable burnId = commandId(NAME);
15
15
 
16
16
  constructor() {
17
- emit Command(host, NAME, "", burnId, State.Balances, State.Empty);
17
+ emit Command(host, NAME, "", burnId, State.Balances, State.Empty, false);
18
18
  }
19
19
 
20
20
  /// @notice Override to burn or consume the provided balance amount.
@@ -26,7 +26,7 @@ abstract contract Burn is CommandBase {
26
26
  /// @return Amount actually burned (may differ from `amount` for partial burns).
27
27
  function burn(bytes32 account, bytes32 asset, bytes32 meta, uint amount) internal virtual returns (uint);
28
28
 
29
- function burn(CommandContext calldata c) external payable onlyCommand(burnId, c.target) returns (bytes memory) {
29
+ function burn(CommandContext calldata c) external onlyCommand(burnId, c.target) returns (bytes memory) {
30
30
  (Cur memory state, , ) = cursor(c.state, 1);
31
31
 
32
32
  while (state.i < state.bound) {
@@ -43,3 +43,4 @@ abstract contract Burn is CommandBase {
43
43
 
44
44
 
45
45
 
46
+
@@ -16,14 +16,14 @@ abstract contract Create is CommandBase {
16
16
  uint internal immutable createId = commandId(NAME);
17
17
 
18
18
  constructor(string memory input) {
19
- emit Command(host, NAME, input, createId, State.Empty, State.Empty);
19
+ emit Command(host, NAME, input, createId, State.Empty, State.Empty, false);
20
20
  }
21
21
 
22
22
  /// @dev Override to create or initialize an object described by `input`.
23
23
  /// Called once per top-level request item.
24
24
  function create(bytes32 account, Cur memory input) internal virtual;
25
25
 
26
- function create(CommandContext calldata c) external payable onlyCommand(createId, c.target) returns (bytes memory) {
26
+ function create(CommandContext calldata c) external onlyCommand(createId, c.target) returns (bytes memory) {
27
27
  (Cur memory request, , ) = cursor(c.request, 1);
28
28
 
29
29
  while (request.i < request.bound) {
@@ -39,3 +39,4 @@ abstract contract Create is CommandBase {
39
39
 
40
40
 
41
41
 
42
+
@@ -15,7 +15,7 @@ abstract contract CreditAccount is CommandBase {
15
15
  uint internal immutable creditAccountId = commandId(NAME);
16
16
 
17
17
  constructor() {
18
- emit Command(host, NAME, Schemas.Recipient, creditAccountId, State.Balances, State.Empty);
18
+ emit Command(host, NAME, Schemas.Recipient, creditAccountId, State.Balances, State.Empty, false);
19
19
  }
20
20
 
21
21
  /// @notice Override to credit externally managed funds to `account`.
@@ -28,7 +28,7 @@ abstract contract CreditAccount is CommandBase {
28
28
 
29
29
  function creditAccount(
30
30
  CommandContext calldata c
31
- ) external payable onlyCommand(creditAccountId, c.target) returns (bytes memory) {
31
+ ) external onlyCommand(creditAccountId, c.target) returns (bytes memory) {
32
32
  (Cur memory state, , ) = cursor(c.state, 1);
33
33
  Cur memory request = cursor(c.request);
34
34
  bytes32 to = request.recipientAfter(c.account);
@@ -47,3 +47,4 @@ abstract contract CreditAccount is CommandBase {
47
47
 
48
48
 
49
49
 
50
+
@@ -17,7 +17,7 @@ abstract contract DebitAccount is CommandBase {
17
17
  uint internal immutable debitAccountId = commandId(NAME);
18
18
 
19
19
  constructor() {
20
- emit Command(host, NAME, Schemas.Amount, debitAccountId, State.Empty, State.Balances);
20
+ emit Command(host, NAME, Schemas.Amount, debitAccountId, State.Empty, State.Balances, false);
21
21
  }
22
22
 
23
23
  /// @notice Override to debit externally managed funds from `account`.
@@ -46,7 +46,7 @@ abstract contract DebitAccount is CommandBase {
46
46
 
47
47
  function debitAccount(
48
48
  CommandContext calldata c
49
- ) external payable onlyCommand(debitAccountId, c.target) returns (bytes memory) {
49
+ ) external onlyCommand(debitAccountId, c.target) returns (bytes memory) {
50
50
  return debitAccount(c.account, c.request);
51
51
  }
52
52
  }
@@ -56,3 +56,4 @@ abstract contract DebitAccount is CommandBase {
56
56
 
57
57
 
58
58
 
59
+
@@ -0,0 +1,104 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { CommandContext, CommandBase, CommandPayable, State } from "./Base.sol";
5
+ import { Cursors, Cur, Schemas, Writer, Writers } from "../Cursors.sol";
6
+ import { Budget, Values } from "../utils/Value.sol";
7
+
8
+ string constant DEPOSIT = "deposit";
9
+ string constant DEPOSIT_PAYABLE = "depositPayable";
10
+
11
+ using Cursors for Cur;
12
+ using Writers for Writer;
13
+
14
+ /// @title Deposit
15
+ /// @notice Command that receives externally sourced assets and records them as BALANCE state.
16
+ /// Use `deposit` for assets arriving from outside the protocol (e.g. ERC-20 transfers, ETH).
17
+ /// For internal balance deductions, use `debitAccount` instead.
18
+ abstract contract Deposit is CommandBase {
19
+ uint internal immutable depositId = commandId(DEPOSIT);
20
+
21
+ constructor() {
22
+ emit Command(host, DEPOSIT, Schemas.Amount, depositId, State.Empty, State.Balances, false);
23
+ }
24
+
25
+ /// @notice Override to receive externally sourced funds for `account`.
26
+ /// Called once per AMOUNT block. A matching BALANCE block is appended to the
27
+ /// output after each call.
28
+ /// @param account Recipient account identifier.
29
+ /// @param asset Asset identifier.
30
+ /// @param meta Asset metadata slot.
31
+ /// @param amount Amount received.
32
+ function deposit(
33
+ bytes32 account,
34
+ bytes32 asset,
35
+ bytes32 meta,
36
+ uint amount
37
+ ) internal virtual;
38
+
39
+ function deposit(
40
+ CommandContext calldata c
41
+ ) external onlyCommand(depositId, c.target) returns (bytes memory) {
42
+ (Cur memory request, uint count, ) = cursor(c.request, 1);
43
+ Writer memory writer = Writers.allocBalances(count);
44
+
45
+ while (request.i < request.bound) {
46
+ (bytes32 asset, bytes32 meta, uint amount) = request.unpackAmount();
47
+ deposit(c.account, asset, meta, amount);
48
+ writer.appendBalance(asset, meta, amount);
49
+ }
50
+
51
+ return request.complete(writer);
52
+ }
53
+ }
54
+
55
+ /// @title DepositPayable
56
+ /// @notice Command that receives externally sourced assets and records them as BALANCE state.
57
+ /// Use `depositPayable` when the hook needs tracked access to `msg.value` via a mutable budget.
58
+ abstract contract DepositPayable is CommandPayable {
59
+ uint internal immutable depositPayableId = commandId(DEPOSIT_PAYABLE);
60
+
61
+ constructor() {
62
+ emit Command(host, DEPOSIT_PAYABLE, Schemas.Amount, depositPayableId, State.Empty, State.Balances, true);
63
+ }
64
+
65
+ /// @notice Override to receive externally sourced funds for `account`.
66
+ /// Called once per AMOUNT block. A matching BALANCE block is appended to the
67
+ /// output after each call.
68
+ /// @param account Recipient account identifier.
69
+ /// @param asset Asset identifier.
70
+ /// @param meta Asset metadata slot.
71
+ /// @param amount Amount received.
72
+ /// @param budget Mutable native-value budget drawn from `msg.value`.
73
+ function deposit(
74
+ bytes32 account,
75
+ bytes32 asset,
76
+ bytes32 meta,
77
+ uint amount,
78
+ Budget memory budget
79
+ ) internal virtual;
80
+
81
+ function depositPayable(
82
+ CommandContext calldata c
83
+ ) external payable onlyCommand(depositPayableId, c.target) returns (bytes memory) {
84
+ (Cur memory request, uint count, ) = cursor(c.request, 1);
85
+ Writer memory writer = Writers.allocBalances(count);
86
+ Budget memory budget = Values.fromMsg();
87
+
88
+ while (request.i < request.bound) {
89
+ (bytes32 asset, bytes32 meta, uint amount) = request.unpackAmount();
90
+ deposit(c.account, asset, meta, amount, budget);
91
+ writer.appendBalance(asset, meta, amount);
92
+ }
93
+
94
+ settleValue(c.account, budget);
95
+ return request.complete(writer);
96
+ }
97
+ }
98
+
99
+
100
+
101
+
102
+
103
+
104
+
@@ -19,7 +19,7 @@ abstract contract LiquidateFromBalanceToBalances is CommandBase {
19
19
 
20
20
  constructor(string memory input, uint scaledRatio) {
21
21
  outScale = scaledRatio;
22
- emit Command(host, LFBTB, input, liquidateFromBalanceToBalancesId, State.Balances, State.Balances);
22
+ emit Command(host, LFBTB, input, liquidateFromBalanceToBalancesId, State.Balances, State.Balances, false);
23
23
  }
24
24
 
25
25
  /// @dev Override to liquidate using a balance repayment amount.
@@ -36,7 +36,7 @@ abstract contract LiquidateFromBalanceToBalances is CommandBase {
36
36
 
37
37
  function liquidateFromBalanceToBalances(
38
38
  CommandContext calldata c
39
- ) external payable onlyCommand(liquidateFromBalanceToBalancesId, c.target) returns (bytes memory) {
39
+ ) external onlyCommand(liquidateFromBalanceToBalancesId, c.target) returns (bytes memory) {
40
40
  (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
41
41
  Cur memory request = cursor(c.request);
42
42
  Writer memory writer = Writers.allocScaledBalances(stateCount, outScale);
@@ -59,7 +59,7 @@ abstract contract LiquidateFromCustodyToBalances is CommandBase {
59
59
 
60
60
  constructor(string memory input, uint scaledRatio) {
61
61
  outScale = scaledRatio;
62
- emit Command(host, LFCTB, input, liquidateFromCustodyToBalancesId, State.Custodies, State.Balances);
62
+ emit Command(host, LFCTB, input, liquidateFromCustodyToBalancesId, State.Custodies, State.Balances, false);
63
63
  }
64
64
 
65
65
  /// @dev Override to liquidate using a custody repayment amount.
@@ -76,7 +76,7 @@ abstract contract LiquidateFromCustodyToBalances is CommandBase {
76
76
 
77
77
  function liquidateFromCustodyToBalances(
78
78
  CommandContext calldata c
79
- ) external payable onlyCommand(liquidateFromCustodyToBalancesId, c.target) returns (bytes memory) {
79
+ ) external onlyCommand(liquidateFromCustodyToBalancesId, c.target) returns (bytes memory) {
80
80
  (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
81
81
  Cur memory request = cursor(c.request);
82
82
  Writer memory writer = Writers.allocScaledBalances(stateCount, outScale);
@@ -96,3 +96,4 @@ abstract contract LiquidateFromCustodyToBalances is CommandBase {
96
96
 
97
97
 
98
98
 
99
+
@@ -21,7 +21,7 @@ abstract contract AddLiquidityFromCustodiesToBalances is CommandBase {
21
21
 
22
22
  constructor(string memory input, uint scaledRatio) {
23
23
  outScale = scaledRatio;
24
- emit Command(host, ALFCTB, input, addLiquidityFromCustodiesToBalancesId, State.Custodies, State.Balances);
24
+ emit Command(host, ALFCTB, input, addLiquidityFromCustodiesToBalancesId, State.Custodies, State.Balances, false);
25
25
  }
26
26
 
27
27
  /// @dev Override to add liquidity from the current `custodies` stream
@@ -40,7 +40,7 @@ abstract contract AddLiquidityFromCustodiesToBalances is CommandBase {
40
40
 
41
41
  function addLiquidityFromCustodiesToBalances(
42
42
  CommandContext calldata c
43
- ) external payable onlyCommand(addLiquidityFromCustodiesToBalancesId, c.target) returns (bytes memory) {
43
+ ) external onlyCommand(addLiquidityFromCustodiesToBalancesId, c.target) returns (bytes memory) {
44
44
  (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
45
45
  Cur memory request = cursor(c.request);
46
46
  Writer memory writer = Writers.allocScaledBalances(stateCount, outScale);
@@ -61,7 +61,7 @@ abstract contract RemoveLiquidityFromCustodyToBalances is CommandBase {
61
61
 
62
62
  constructor(string memory input, uint scaledRatio) {
63
63
  outScale = scaledRatio;
64
- emit Command(host, RLFCTB, input, removeLiquidityFromCustodyToBalancesId, State.Custodies, State.Balances);
64
+ emit Command(host, RLFCTB, input, removeLiquidityFromCustodyToBalancesId, State.Custodies, State.Balances, false);
65
65
  }
66
66
 
67
67
  /// @dev Override to remove liquidity from a custody position.
@@ -78,7 +78,7 @@ abstract contract RemoveLiquidityFromCustodyToBalances is CommandBase {
78
78
 
79
79
  function removeLiquidityFromCustodyToBalances(
80
80
  CommandContext calldata c
81
- ) external payable onlyCommand(removeLiquidityFromCustodyToBalancesId, c.target) returns (bytes memory) {
81
+ ) external onlyCommand(removeLiquidityFromCustodyToBalancesId, c.target) returns (bytes memory) {
82
82
  (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
83
83
  Cur memory request = cursor(c.request);
84
84
  Writer memory writer = Writers.allocScaledBalances(stateCount, outScale);
@@ -101,7 +101,7 @@ abstract contract AddLiquidityFromBalancesToBalances is CommandBase {
101
101
 
102
102
  constructor(string memory input, uint scaledRatio) {
103
103
  outScale = scaledRatio;
104
- emit Command(host, ALFBTB, input, addLiquidityFromBalancesToBalancesId, State.Balances, State.Balances);
104
+ emit Command(host, ALFBTB, input, addLiquidityFromBalancesToBalancesId, State.Balances, State.Balances, false);
105
105
  }
106
106
 
107
107
  /// @dev Override to add liquidity from the current `balances` stream
@@ -119,7 +119,7 @@ abstract contract AddLiquidityFromBalancesToBalances is CommandBase {
119
119
 
120
120
  function addLiquidityFromBalancesToBalances(
121
121
  CommandContext calldata c
122
- ) external payable onlyCommand(addLiquidityFromBalancesToBalancesId, c.target) returns (bytes memory) {
122
+ ) external onlyCommand(addLiquidityFromBalancesToBalancesId, c.target) returns (bytes memory) {
123
123
  (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
124
124
  Cur memory request = cursor(c.request);
125
125
  Writer memory writer = Writers.allocScaledBalances(stateCount, outScale);
@@ -140,7 +140,7 @@ abstract contract RemoveLiquidityFromBalanceToBalances is CommandBase {
140
140
 
141
141
  constructor(string memory input, uint scaledRatio) {
142
142
  outScale = scaledRatio;
143
- emit Command(host, RLFBTB, input, removeLiquidityFromBalanceToBalancesId, State.Balances, State.Balances);
143
+ emit Command(host, RLFBTB, input, removeLiquidityFromBalanceToBalancesId, State.Balances, State.Balances, false);
144
144
  }
145
145
 
146
146
  /// @dev Override to remove liquidity from a balance position.
@@ -157,7 +157,7 @@ abstract contract RemoveLiquidityFromBalanceToBalances is CommandBase {
157
157
 
158
158
  function removeLiquidityFromBalanceToBalances(
159
159
  CommandContext calldata c
160
- ) external payable onlyCommand(removeLiquidityFromBalanceToBalancesId, c.target) returns (bytes memory) {
160
+ ) external onlyCommand(removeLiquidityFromBalanceToBalancesId, c.target) returns (bytes memory) {
161
161
  (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
162
162
  Cur memory request = cursor(c.request);
163
163
  Writer memory writer = Writers.allocScaledBalances(stateCount, outScale);
@@ -177,3 +177,4 @@ abstract contract RemoveLiquidityFromBalanceToBalances is CommandBase {
177
177
 
178
178
 
179
179
 
180
+
@@ -19,7 +19,7 @@ abstract contract MintToBalances is CommandBase {
19
19
 
20
20
  constructor(string memory input, uint scaledRatio) {
21
21
  outScale = scaledRatio;
22
- emit Command(host, NAME, input, mintToBalancesId, State.Empty, State.Balances);
22
+ emit Command(host, NAME, input, mintToBalancesId, State.Empty, State.Balances, false);
23
23
  }
24
24
 
25
25
  /// @dev Override to mint balances described by the current `input` stream
@@ -35,7 +35,7 @@ abstract contract MintToBalances is CommandBase {
35
35
 
36
36
  function mintToBalances(
37
37
  CommandContext calldata c
38
- ) external payable onlyCommand(mintToBalancesId, c.target) returns (bytes memory) {
38
+ ) external onlyCommand(mintToBalancesId, c.target) returns (bytes memory) {
39
39
  (Cur memory request, uint count, ) = cursor(c.request, 1);
40
40
  Writer memory writer = Writers.allocScaledBalances(count, outScale);
41
41
 
@@ -51,3 +51,4 @@ abstract contract MintToBalances is CommandBase {
51
51
 
52
52
 
53
53
 
54
+
@@ -1,25 +1,25 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import { CommandBase, CommandContext } from "./Base.sol";
5
- import { Cursors, Cur, Schemas } from "../Cursors.sol";
6
- import { Accounts } from "../utils/Accounts.sol";
7
- import { Values } from "../utils/Value.sol";
4
+ import {CommandBase, CommandContext, CommandPayable} from "./Base.sol";
5
+ import {Cursors, Cur, Schemas} from "../Cursors.sol";
6
+ import {Accounts} from "../utils/Accounts.sol";
7
+ import {Budget, Values} from "../utils/Value.sol";
8
8
 
9
9
  using Cursors for Cur;
10
10
 
11
- string constant NAME = "pipe";
11
+ string constant NAME = "pipePayable";
12
12
 
13
- /// @title Pipe
13
+ /// @title PipePayable
14
14
  /// @notice Command that sequences multiple sub-command STEP invocations in a single transaction.
15
15
  /// Each STEP block carries a target node, native value to forward, and an embedded request.
16
16
  /// State threads through the steps: each step's output becomes the next step's state.
17
- /// Admin accounts are not permitted to use `pipe`.
18
- abstract contract Pipe is CommandBase {
19
- uint internal immutable pipeId = commandId(NAME);
17
+ /// Admin accounts are not permitted to use `pipePayable`.
18
+ abstract contract PipePayable is CommandPayable {
19
+ uint internal immutable pipePayableId = commandId(NAME);
20
20
 
21
21
  constructor() {
22
- emit Command(host, NAME, Schemas.Step, pipeId, 0, 0);
22
+ emit Command(host, NAME, Schemas.Step, pipePayableId, 0, 0, true);
23
23
  }
24
24
 
25
25
  /// @notice Override to execute a single STEP and return the resulting state.
@@ -42,7 +42,7 @@ abstract contract Pipe is CommandBase {
42
42
  bytes32 account,
43
43
  bytes memory state,
44
44
  bytes calldata steps,
45
- Values.Budget memory budget
45
+ Budget memory budget
46
46
  ) internal returns (bytes memory) {
47
47
  (Cur memory input, , ) = cursor(steps, 1);
48
48
 
@@ -52,20 +52,17 @@ abstract contract Pipe is CommandBase {
52
52
  state = dispatchStep(target, account, state, request, spend);
53
53
  }
54
54
 
55
+ settleValue(account, budget);
55
56
  input.complete();
56
57
  return state;
57
58
  }
58
59
 
59
- /// @notice Execute the pipe command.
60
- /// Note: any unused `msg.value` is NOT automatically refunded to the caller.
61
- function pipe(CommandContext calldata c) external payable onlyCommand(pipeId, c.target) returns (bytes memory) {
60
+ /// @notice Execute the pipePayable command.
61
+ function pipePayable(
62
+ CommandContext calldata c
63
+ ) external payable onlyCommand(pipePayableId, c.target) returns (bytes memory) {
62
64
  if (Accounts.isAdmin(c.account)) revert Accounts.InvalidAccount();
63
- Values.Budget memory budget = Values.fromMsg();
65
+ Budget memory budget = Values.fromMsg();
64
66
  return pipe(c.account, c.state, c.request, budget);
65
67
  }
66
68
  }
67
-
68
-
69
-
70
-
71
-
@@ -0,0 +1,123 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CommandContext, CommandBase, CommandPayable, State} from "./Base.sol";
5
+ import {Cursors, Cur, HostAmount, Schemas, Writer, Writers} from "../Cursors.sol";
6
+ import {Budget, Values} from "../utils/Value.sol";
7
+ using Cursors for Cur;
8
+ using Writers for Writer;
9
+
10
+ string constant PROVISION = "provision";
11
+ string constant PP = "provisionPayable";
12
+ string constant PFB = "provisionFromBalance";
13
+
14
+ /// @notice Shared provision hook used by both `Provision` and `ProvisionFromBalance`.
15
+ abstract contract ProvisionHook {
16
+ /// @notice Override to send or provision a custody value.
17
+ /// Called once per provisioned asset. Implementations should perform only the
18
+ /// side effect (e.g. transfer or record); output blocks are written by the caller.
19
+ /// @param account Caller's account identifier.
20
+ /// @param custody Destination host plus asset amount to provision.
21
+ function provision(bytes32 account, HostAmount memory custody) internal virtual;
22
+ }
23
+
24
+ /// @notice Shared provision hook used by `ProvisionPayable`.
25
+ abstract contract ProvisionPayableHook {
26
+ /// @notice Override to send or provision a custody value.
27
+ /// Called once per provisioned asset. Implementations should perform only the
28
+ /// side effect (e.g. transfer or record); output blocks are written by the caller.
29
+ /// @param account Caller's account identifier.
30
+ /// @param custody Destination host plus asset amount to provision.
31
+ /// @param budget Mutable native-value budget drawn from `msg.value`.
32
+ function provision(
33
+ bytes32 account,
34
+ HostAmount memory custody,
35
+ Budget memory budget
36
+ ) internal virtual;
37
+ }
38
+
39
+ /// @title Provision
40
+ /// @notice Command that provisions assets to remote hosts from CUSTODY request blocks.
41
+ /// Each request block supplies the target host plus an asset amount; the output is a CUSTODY state stream.
42
+ abstract contract Provision is CommandBase, ProvisionHook {
43
+ uint internal immutable provisionId = commandId(PROVISION);
44
+
45
+ constructor() {
46
+ emit Command(host, PROVISION, Schemas.Custody, provisionId, State.Empty, State.Custodies, false);
47
+ }
48
+
49
+ function provision(
50
+ CommandContext calldata c
51
+ ) external onlyCommand(provisionId, c.target) returns (bytes memory) {
52
+ (Cur memory request, uint count, ) = cursor(c.request, 1);
53
+ Writer memory writer = Writers.allocCustodies(count);
54
+
55
+ while (request.i < request.bound) {
56
+ HostAmount memory custody = request.unpackCustodyValue();
57
+ provision(c.account, custody);
58
+ writer.appendCustody(custody);
59
+ }
60
+
61
+ return request.complete(writer);
62
+ }
63
+ }
64
+
65
+ /// @title ProvisionPayable
66
+ /// @notice Command that provisions assets to remote hosts from CUSTODY request blocks.
67
+ /// Each request block supplies the target host plus an asset amount; the output is a CUSTODY state stream.
68
+ /// The hook receives a mutable native-value budget drawn from `msg.value`.
69
+ abstract contract ProvisionPayable is CommandPayable, ProvisionPayableHook {
70
+ uint internal immutable provisionPayableId = commandId(PP);
71
+
72
+ constructor() {
73
+ emit Command(host, PP, Schemas.Custody, provisionPayableId, State.Empty, State.Custodies, true);
74
+ }
75
+
76
+ function provisionPayable(
77
+ CommandContext calldata c
78
+ ) external payable onlyCommand(provisionPayableId, c.target) returns (bytes memory) {
79
+ (Cur memory request, uint count, ) = cursor(c.request, 1);
80
+ Writer memory writer = Writers.allocCustodies(count);
81
+ Budget memory budget = Values.fromMsg();
82
+
83
+ while (request.i < request.bound) {
84
+ HostAmount memory custody = request.unpackCustodyValue();
85
+ provision(c.account, custody, budget);
86
+ writer.appendCustody(custody);
87
+ }
88
+
89
+ settleValue(c.account, budget);
90
+ return request.complete(writer);
91
+ }
92
+ }
93
+
94
+ /// @title ProvisionFromBalance
95
+ /// @notice Command that converts BALANCE state into CUSTODY state for a destination host.
96
+ /// The destination node is read from an optional NODE trailing block; reverts if absent.
97
+ abstract contract ProvisionFromBalance is CommandBase, ProvisionHook {
98
+ uint internal immutable provisionFromBalanceId = commandId(PFB);
99
+
100
+ constructor() {
101
+ emit Command(host, PFB, Schemas.Node, provisionFromBalanceId, State.Balances, State.Custodies, false);
102
+ }
103
+
104
+ function provisionFromBalance(
105
+ CommandContext calldata c
106
+ ) external onlyCommand(provisionFromBalanceId, c.target) returns (bytes memory) {
107
+ (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
108
+ Cur memory request = cursor(c.request);
109
+ Writer memory writer = Writers.allocCustodies(stateCount);
110
+ uint toHost = request.nodeAfter(0);
111
+ if (toHost == 0) revert Cursors.ZeroNode();
112
+
113
+ while (state.i < state.bound) {
114
+ (bytes32 asset, bytes32 meta, uint amount) = state.unpackBalance();
115
+ HostAmount memory custody = HostAmount(toHost, asset, meta, amount);
116
+ provision(c.account, custody);
117
+ writer.appendCustody(custody);
118
+ }
119
+
120
+ return state.complete(writer);
121
+ }
122
+ }
123
+