@rootzero/contracts 0.6.2 → 0.7.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 (47) hide show
  1. package/Commands.sol +8 -16
  2. package/Core.sol +4 -2
  3. package/Cursors.sol +2 -2
  4. package/Events.sol +4 -2
  5. package/Queries.sol +10 -0
  6. package/blocks/Cursors.sol +168 -8
  7. package/blocks/Keys.sol +4 -1
  8. package/blocks/Schema.sol +32 -11
  9. package/blocks/Writers.sol +536 -95
  10. package/commands/Base.sol +20 -6
  11. package/commands/Provision.sol +5 -12
  12. package/commands/Stake.sol +1 -84
  13. package/commands/admin/AllowAssets.sol +7 -5
  14. package/commands/admin/DenyAssets.sol +7 -5
  15. package/commands/admin/Relocate.sol +2 -2
  16. package/core/Access.sol +2 -4
  17. package/core/CursorBase.sol +43 -0
  18. package/core/Host.sol +1 -1
  19. package/core/HostBound.sol +14 -0
  20. package/core/Operation.sol +41 -37
  21. package/events/Erc721.sol +20 -0
  22. package/events/Query.sol +20 -0
  23. package/events/Swap.sol +20 -0
  24. package/package.json +1 -1
  25. package/peer/AllowAssets.sol +4 -9
  26. package/peer/AssetPull.sol +41 -0
  27. package/peer/Base.sol +11 -0
  28. package/peer/DenyAssets.sol +4 -9
  29. package/peer/Pull.sol +8 -11
  30. package/peer/Push.sol +6 -3
  31. package/queries/Assets.sol +46 -0
  32. package/queries/Balances.sol +46 -0
  33. package/queries/Base.sol +34 -0
  34. package/queries/Positions.sol +49 -0
  35. package/utils/Ids.sol +68 -1
  36. package/utils/Layout.sol +2 -0
  37. package/commands/Borrow.sol +0 -89
  38. package/commands/Liquidate.sol +0 -99
  39. package/commands/Liquidity.sol +0 -180
  40. package/commands/Mint.sol +0 -54
  41. package/commands/Reclaim.sol +0 -55
  42. package/commands/Redeem.sol +0 -99
  43. package/commands/Repay.sol +0 -99
  44. package/commands/Swap.sol +0 -90
  45. package/commands/Unstake.sol +0 -58
  46. package/events/Quote.sol +0 -21
  47. /package/events/{HostAnnounced.sol → Host.sol} +0 -0
@@ -2,6 +2,7 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PeerBase} from "./Base.sol";
5
+ import {DenyAssetsHook} from "../commands/admin/DenyAssets.sol";
5
6
  import {Cursors, Cur, Schemas} from "../Cursors.sol";
6
7
 
7
8
  using Cursors for Cur;
@@ -10,27 +11,21 @@ string constant NAME = "peerDenyAssets";
10
11
 
11
12
  /// @title PeerDenyAssets
12
13
  /// @notice Peer that blocks a list of (asset, meta) pairs on behalf of a remote host.
13
- /// Each ASSET block in the request calls `peerDenyAsset`. Restricted to trusted peers.
14
- abstract contract PeerDenyAssets is PeerBase {
14
+ /// Each ASSET block in the request calls `denyAsset`. Restricted to trusted peers.
15
+ abstract contract PeerDenyAssets is PeerBase, DenyAssetsHook {
15
16
  uint internal immutable peerDenyAssetsId = peerId(NAME);
16
17
 
17
18
  constructor() {
18
19
  emit Peer(host, NAME, Schemas.Asset, peerDenyAssetsId, false);
19
20
  }
20
21
 
21
- /// @notice Override to block a single (asset, meta) pair.
22
- /// @param asset Asset identifier.
23
- /// @param meta Asset metadata slot.
24
- /// @return True if the asset was newly denied, false if it was already denied.
25
- function peerDenyAsset(bytes32 asset, bytes32 meta) internal virtual returns (bool);
26
-
27
22
  /// @notice Execute the deny-assets peer call.
28
23
  function peerDenyAssets(bytes calldata request) external onlyPeer returns (bytes memory) {
29
24
  (Cur memory assets, , ) = cursor(request, 1);
30
25
 
31
26
  while (assets.i < assets.bound) {
32
27
  (bytes32 asset, bytes32 meta) = assets.unpackAsset();
33
- peerDenyAsset(asset, meta);
28
+ denyAsset(asset, meta);
34
29
  }
35
30
 
36
31
  assets.complete();
package/peer/Pull.sol CHANGED
@@ -1,8 +1,8 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import { PeerBase } from "./Base.sol";
5
- import { Cursors, Cur } from "../Cursors.sol";
4
+ import {PeerBase} from "./Base.sol";
5
+ import {Cursors, Cur} from "../Cursors.sol";
6
6
 
7
7
  string constant NAME = "peerPull";
8
8
 
@@ -10,7 +10,8 @@ using Cursors for Cur;
10
10
 
11
11
  /// @title PeerPull
12
12
  /// @notice Peer that pulls assets from a remote host into this one.
13
- /// Each block in the request is dispatched to `peerPull(Cur)`. Restricted to trusted peers.
13
+ /// Each block in the request is dispatched to `peerPull(peer, input)`, where `peer`
14
+ /// is derived from `msg.sender`. Restricted to trusted peers.
14
15
  abstract contract PeerPull is PeerBase {
15
16
  uint internal immutable peerPullId = peerId(NAME);
16
17
 
@@ -19,24 +20,20 @@ abstract contract PeerPull is PeerBase {
19
20
  }
20
21
 
21
22
  /// @notice Override to process a single incoming block from the pull request.
23
+ /// @param peer Host node ID derived from the caller address.
22
24
  /// @param input Cursor positioned at the current input block; advance it before returning.
23
- function peerPull(Cur memory input) internal virtual;
25
+ function peerPull(uint peer, Cur memory input) internal virtual;
24
26
 
25
27
  /// @notice Execute the pull peer call.
26
28
  function peerPull(bytes calldata request) external onlyPeer returns (bytes memory) {
27
29
  (Cur memory input, , ) = cursor(request, 1);
30
+ uint peer = caller();
28
31
 
29
32
  while (input.i < input.bound) {
30
- peerPull(input);
33
+ peerPull(peer, input);
31
34
  }
32
35
 
33
36
  input.complete();
34
37
  return "";
35
38
  }
36
39
  }
37
-
38
-
39
-
40
-
41
-
42
-
package/peer/Push.sol CHANGED
@@ -10,7 +10,8 @@ using Cursors for Cur;
10
10
 
11
11
  /// @title PeerPush
12
12
  /// @notice Peer that receives assets pushed from a remote host into this one.
13
- /// Each block in the request is dispatched to `peerPush(Cur)`. Restricted to trusted peers.
13
+ /// Each block in the request is dispatched to `peerPush(peer, input)`, where `peer`
14
+ /// is derived from `msg.sender`. Restricted to trusted peers.
14
15
  abstract contract PeerPush is PeerBase {
15
16
  uint internal immutable peerPushId = peerId(NAME);
16
17
 
@@ -19,15 +20,17 @@ abstract contract PeerPush is PeerBase {
19
20
  }
20
21
 
21
22
  /// @notice Override to process a single incoming block from the push request.
23
+ /// @param peer Host node ID derived from the caller address.
22
24
  /// @param input Cursor positioned at the current input block; advance it before returning.
23
- function peerPush(Cur memory input) internal virtual;
25
+ function peerPush(uint peer, Cur memory input) internal virtual;
24
26
 
25
27
  /// @notice Execute the push peer call.
26
28
  function peerPush(bytes calldata request) external onlyPeer returns (bytes memory) {
27
29
  (Cur memory input, , ) = cursor(request, 1);
30
+ uint peer = caller();
28
31
 
29
32
  while (input.i < input.bound) {
30
- peerPush(input);
33
+ peerPush(peer, input);
31
34
  }
32
35
 
33
36
  input.complete();
@@ -0,0 +1,46 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Cur, Cursors, Writer, Writers, Keys} from "../Cursors.sol";
5
+ import {Schemas} from "../blocks/Schema.sol";
6
+ import {QueryBase} from "./Base.sol";
7
+
8
+ using Cursors for Cur;
9
+
10
+ string constant NAME = "isAllowedAsset";
11
+ string constant OUTPUT = "response(uint allowed)";
12
+
13
+ /// @title IsAllowedAsset
14
+ /// @notice Rootzero query that checks whether one or more `(asset, meta)` tuples are allowed.
15
+ /// The request is a run of `ASSET` blocks.
16
+ /// The response returns one `RESPONSE` block per query entry, preserving request order.
17
+ abstract contract IsAllowedAsset is QueryBase {
18
+ uint public immutable isAllowedAssetId = queryId(NAME);
19
+
20
+ constructor() {
21
+ emit Query(host, NAME, Schemas.Asset, OUTPUT, isAllowedAssetId);
22
+ }
23
+
24
+ /// @notice Resolve whether one asset tuple is allowed.
25
+ /// Concrete implementations define the allowlist policy.
26
+ /// @param asset Requested asset identifier.
27
+ /// @param meta Requested asset metadata slot.
28
+ /// @return allowed Whether the asset tuple is allowed.
29
+ function isAllowedAsset(bytes32 asset, bytes32 meta) internal view virtual returns (bool allowed);
30
+
31
+ /// @notice Resolve allowlist status for a run of requested `(asset, meta)` tuples.
32
+ /// @param request Block-stream request consisting of `asset(asset, meta)*`.
33
+ /// @return Block-stream response containing one `response(allowed)` per asset block.
34
+ function isAllowedAsset(bytes calldata request) external view returns (bytes memory) {
35
+ (Cur memory query, uint count, ) = cursor(request, 1);
36
+ Writer memory response = Writers.alloc32s(count);
37
+
38
+ while (query.i < query.bound) {
39
+ (bytes32 asset, bytes32 meta) = query.unpackAsset();
40
+ bool allowed = isAllowedAsset(asset, meta);
41
+ Writers.appendBool(response, Keys.Response, allowed);
42
+ }
43
+
44
+ return query.complete(response);
45
+ }
46
+ }
@@ -0,0 +1,46 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Cur, Cursors, Schemas, Writer, Writers} from "../Cursors.sol";
5
+ import {QueryBase} from "./Base.sol";
6
+
7
+ using Cursors for Cur;
8
+
9
+ string constant NAME = "getBalances";
10
+ string constant INPUT = "query(bytes32 account, bytes32 asset, bytes32 meta)";
11
+
12
+ /// @title GetBalances
13
+ /// @notice Rootzero query that resolves balances for one or more `(account, asset, meta)` tuples.
14
+ /// The request is a run of `QUERY` blocks, each encoding `(bytes32 account, bytes32 asset, bytes32 meta)`.
15
+ /// The response returns one `BALANCE` block per query entry, preserving request order.
16
+ abstract contract GetBalances is QueryBase {
17
+ uint public immutable getBalancesId = queryId(NAME);
18
+
19
+ constructor() {
20
+ emit Query(host, NAME, INPUT, Schemas.Balance, getBalancesId);
21
+ }
22
+
23
+ /// @notice Resolve one account's balance for one supported asset.
24
+ /// Concrete implementations define how assets are resolved.
25
+ /// @param account Account identifier carried by the query payload.
26
+ /// @param asset Requested asset identifier.
27
+ /// @param meta Requested asset metadata slot.
28
+ /// @return amount Current balance in the asset's native units.
29
+ function getBalance(bytes32 account, bytes32 asset, bytes32 meta) internal view virtual returns (uint amount);
30
+
31
+ /// @notice Resolve balances for a run of requested `(account, asset, meta)` tuples.
32
+ /// @param request Block-stream request consisting of `query(account, asset, meta)*`.
33
+ /// @return Block-stream response containing one `balance(asset, meta, amount)` per query block.
34
+ function getBalances(bytes calldata request) external view returns (bytes memory) {
35
+ (Cur memory query, uint count, ) = cursor(request, 1);
36
+ Writer memory response = Writers.allocBalances(count);
37
+
38
+ while (query.i < query.bound) {
39
+ (bytes32 account, bytes32 asset, bytes32 meta) = query.unpackQuery96();
40
+ uint balance = getBalance(account, asset, meta);
41
+ Writers.appendBalance(response, asset, meta, balance);
42
+ }
43
+
44
+ return query.complete(response);
45
+ }
46
+ }
@@ -0,0 +1,34 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { CursorBase } from "../core/CursorBase.sol";
5
+ import { HostBound } from "../core/HostBound.sol";
6
+ import { QueryEvent } from "../events/Query.sol";
7
+ import { Ids, Selectors } from "../utils/Ids.sol";
8
+
9
+ /// @notice ABI-encode a query call from a target query ID and request block stream.
10
+ /// @dev Derives the function selector from `target` via `Ids.querySelector(target)`.
11
+ /// Reverts if `target` is not a valid query ID.
12
+ /// @param target Destination query node ID embedding the target selector.
13
+ /// @param request Input block stream for the query invocation.
14
+ /// @return ABI-encoded calldata for the query entry point.
15
+ function encodeQueryCall(uint target, bytes calldata request) pure returns (bytes memory) {
16
+ bytes4 selector = Ids.querySelector(target);
17
+ return abi.encodeWithSelector(selector, request);
18
+ }
19
+
20
+ /// @title QueryBase
21
+ /// @notice Abstract base for rootzero query contracts.
22
+ /// Queries are view-only entry points that consume a block-stream request and
23
+ /// return a block-stream response.
24
+ abstract contract QueryBase is HostBound, CursorBase, QueryEvent {
25
+
26
+ /// @notice Derive the deterministic node ID for a named query on this contract.
27
+ /// The ID encodes the ABI selector of `name(bytes)` and `address(this)`,
28
+ /// making it unique per (function name, contract address) pair.
29
+ /// @param name Query function name (without argument list).
30
+ /// @return Query node ID.
31
+ function queryId(string memory name) internal view returns (uint) {
32
+ return Ids.toQuery(Selectors.query(name), address(this));
33
+ }
34
+ }
@@ -0,0 +1,49 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Cur, Cursors, Writer, Writers, Keys} from "../Cursors.sol";
5
+ import {Schemas} from "../blocks/Schema.sol";
6
+ import {QueryBase} from "./Base.sol";
7
+
8
+ using Cursors for Cur;
9
+
10
+ string constant NAME = "getAssetPosition";
11
+
12
+ /// @title PositionsQuery
13
+ /// @notice Rootzero query that resolves one dynamic position response for each requested asset tuple.
14
+ /// The request is a run of `ASSET` blocks.
15
+ /// The response returns one dynamic `RESPONSE` block per asset entry, preserving request order.
16
+ abstract contract AssetPosition is QueryBase {
17
+ uint public immutable getAssetPositionId = queryId(NAME);
18
+ uint internal immutable positionResponseSize;
19
+
20
+ constructor(string memory output, uint responseSize) {
21
+ positionResponseSize = responseSize;
22
+ emit Query(host, NAME, Schemas.Asset, output, getAssetPositionId);
23
+ }
24
+
25
+ /// @notice Resolve the position payload for one requested asset tuple.
26
+ /// Concrete implementations must append exactly one `RESPONSE` block whose payload
27
+ /// length matches `positionResponseSize`.
28
+ /// @param asset Requested asset identifier.
29
+ /// @param meta Requested asset metadata slot.
30
+ /// @param response Destination writer for the response stream.
31
+ function appendAssetPosition(bytes32 asset, bytes32 meta, Writer memory response) internal view virtual;
32
+
33
+ /// @notice Resolve positions for a run of requested `(asset, meta)` tuples.
34
+ /// @dev Allocates from the configured fixed response payload length so each hook call
35
+ /// can append one `RESPONSE` block directly into the output stream.
36
+ /// @param request Block-stream request consisting of `asset(asset, meta)*`.
37
+ /// @return Block-stream response containing one `response(bytes data)` block per asset block.
38
+ function getAssetPosition(bytes calldata request) external view returns (bytes memory) {
39
+ (Cur memory query, uint count, ) = cursor(request, 1);
40
+ Writer memory response = Writers.allocBytes(count, positionResponseSize);
41
+
42
+ while (query.i < query.bound) {
43
+ (bytes32 asset, bytes32 meta) = query.unpackAsset();
44
+ appendAssetPosition(asset, meta, response);
45
+ }
46
+
47
+ return query.complete(response);
48
+ }
49
+ }
package/utils/Ids.sol CHANGED
@@ -24,6 +24,8 @@ library Ids {
24
24
  uint32 constant Command = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Command);
25
25
  /// @dev Full 4-byte type prefix for peer nodes.
26
26
  uint32 constant Peer = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Peer);
27
+ /// @dev Full 4-byte type prefix for query nodes.
28
+ uint32 constant Query = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Query);
27
29
 
28
30
  /// @notice Return true if `id` is a host node ID.
29
31
  function isHost(uint id) internal pure returns (bool) {
@@ -40,6 +42,11 @@ library Ids {
40
42
  return uint32(id >> 224) == Peer;
41
43
  }
42
44
 
45
+ /// @notice Return true if `id` is a query node ID.
46
+ function isQuery(uint id) internal pure returns (bool) {
47
+ return uint32(id >> 224) == Query;
48
+ }
49
+
43
50
  /// @notice Assert that `id` is a command ID and return it unchanged.
44
51
  /// @param id Node ID to validate.
45
52
  /// @return cid The same `id` value if it is a command.
@@ -48,6 +55,46 @@ library Ids {
48
55
  return id;
49
56
  }
50
57
 
58
+ /// @notice Assert that `id` is a command ID and return its embedded ABI selector.
59
+ /// @param id Node ID to validate.
60
+ /// @return selector 4-byte command selector stored in bits [191:160].
61
+ function commandSelector(uint id) internal pure returns (bytes4 selector) {
62
+ if (!isCommand(id)) revert InvalidId();
63
+ return bytes4(uint32(id >> 160));
64
+ }
65
+
66
+ /// @notice Assert that `id` is a peer ID and return it unchanged.
67
+ /// @param id Node ID to validate.
68
+ /// @return pid The same `id` value if it is a peer.
69
+ function peer(uint id) internal pure returns (uint pid) {
70
+ if (!isPeer(id)) revert InvalidId();
71
+ return id;
72
+ }
73
+
74
+ /// @notice Assert that `id` is a peer ID and return its embedded ABI selector.
75
+ /// @param id Node ID to validate.
76
+ /// @return selector 4-byte peer selector stored in bits [191:160].
77
+ function peerSelector(uint id) internal pure returns (bytes4 selector) {
78
+ if (!isPeer(id)) revert InvalidId();
79
+ return bytes4(uint32(id >> 160));
80
+ }
81
+
82
+ /// @notice Assert that `id` is a query ID and return it unchanged.
83
+ /// @param id Node ID to validate.
84
+ /// @return qid The same `id` value if it is a query.
85
+ function query(uint id) internal pure returns (uint qid) {
86
+ if (!isQuery(id)) revert InvalidId();
87
+ return id;
88
+ }
89
+
90
+ /// @notice Assert that `id` is a query ID and return its embedded ABI selector.
91
+ /// @param id Node ID to validate.
92
+ /// @return selector 4-byte query selector stored in bits [191:160].
93
+ function querySelector(uint id) internal pure returns (bytes4 selector) {
94
+ if (!isQuery(id)) revert InvalidId();
95
+ return bytes4(uint32(id >> 160));
96
+ }
97
+
51
98
  /// @notice Assert that `id` is the host ID of `target` on the current chain.
52
99
  /// @param id Node ID to validate.
53
100
  /// @param target Expected host contract address.
@@ -84,6 +131,16 @@ library Ids {
84
131
  return id;
85
132
  }
86
133
 
134
+ /// @notice Build a chain-local query ID for the given selector and contract.
135
+ /// @param selector 4-byte ABI selector of the query entry point.
136
+ /// @param target Query contract address.
137
+ /// @return Query node ID embedding both the selector and address.
138
+ function toQuery(bytes4 selector, address target) internal view returns (uint) {
139
+ uint id = toLocalBase(Query) | uint(uint160(target));
140
+ id |= uint(uint32(selector)) << 160;
141
+ return id;
142
+ }
143
+
87
144
  /// @notice Extract the contract address from any local node ID.
88
145
  /// Reverts if `id` does not belong to the local node family.
89
146
  /// @param id Node ID (host, command, or peer).
@@ -104,12 +161,14 @@ library Ids {
104
161
  }
105
162
 
106
163
  /// @title Selectors
107
- /// @notice ABI-selector derivation helpers for command and peer dispatch.
164
+ /// @notice ABI-selector derivation helpers for command, peer, and query dispatch.
108
165
  library Selectors {
109
166
  /// @dev ABI argument encoding for command entry points: `((uint256,bytes32,bytes,bytes))`.
110
167
  string constant CommandArgs = "((uint256,bytes32,bytes,bytes))";
111
168
  /// @dev ABI argument encoding for peer entry points: `(bytes)`.
112
169
  string constant PeerArgs = "(bytes)";
170
+ /// @dev ABI argument encoding for query entry points: `(bytes)`.
171
+ string constant QueryArgs = "(bytes)";
113
172
 
114
173
  /// @notice Derive the 4-byte ABI selector for a named command.
115
174
  /// The selector is `keccak256(name ++ CommandArgs)[0:4]`.
@@ -126,4 +185,12 @@ library Selectors {
126
185
  function peer(string memory name) internal pure returns (bytes4) {
127
186
  return bytes4(keccak256(bytes.concat(bytes(name), bytes(PeerArgs))));
128
187
  }
188
+
189
+ /// @notice Derive the 4-byte ABI selector for a named query.
190
+ /// The selector is `keccak256(name ++ QueryArgs)[0:4]`.
191
+ /// @param name Query function name (without arguments).
192
+ /// @return 4-byte selector.
193
+ function query(string memory name) internal pure returns (bytes4) {
194
+ return bytes4(keccak256(bytes.concat(bytes(name), bytes(QueryArgs))));
195
+ }
129
196
  }
package/utils/Layout.sol CHANGED
@@ -52,6 +52,8 @@ library Layout {
52
52
  uint8 constant Command = 0x02;
53
53
  /// @dev Node is a peer contract.
54
54
  uint8 constant Peer = 0x03;
55
+ /// @dev Node is a query contract.
56
+ uint8 constant Query = 0x04;
55
57
 
56
58
  // -------------------------------------------------------------------------
57
59
  // Asset subtype tags (uint8, fourth byte of the ID type field)
@@ -1,89 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import { CommandContext, CommandBase, State } from "./Base.sol";
5
- import { AssetAmount, HostAmount, Cur, Cursors, Writer, Writers } from "../Cursors.sol";
6
-
7
- string constant BABTB = "borrowAgainstBalanceToBalance";
8
- string constant BACTB = "borrowAgainstCustodyToBalance";
9
-
10
- using Cursors for Cur;
11
- using Writers for Writer;
12
-
13
- /// @title BorrowAgainstCustodyToBalance
14
- /// @notice Command that issues loans against CUSTODY state positions, emitting BALANCE outputs.
15
- abstract contract BorrowAgainstCustodyToBalance is CommandBase {
16
- uint internal immutable borrowAgainstCustodyToBalanceId = commandId(BACTB);
17
-
18
- constructor(string memory input) {
19
- emit Command(host, BACTB, input, borrowAgainstCustodyToBalanceId, State.Custodies, State.Balances, false);
20
- }
21
-
22
- /// @dev Override to borrow against a custody position.
23
- /// `request` is the live auxiliary request cursor for this command;
24
- /// implementations validate and unpack it as needed.
25
- function borrowAgainstCustodyToBalance(
26
- bytes32 account,
27
- HostAmount memory custody,
28
- Cur memory request
29
- ) internal virtual returns (AssetAmount memory);
30
-
31
- function borrowAgainstCustodyToBalance(
32
- CommandContext calldata c
33
- ) external onlyCommand(borrowAgainstCustodyToBalanceId, c.target) returns (bytes memory) {
34
- (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
35
- Cur memory request = cursor(c.request);
36
- Writer memory writer = Writers.allocBalances(stateCount);
37
-
38
- while (state.i < state.bound) {
39
- HostAmount memory custody = state.unpackCustodyValue();
40
- AssetAmount memory out = borrowAgainstCustodyToBalance(c.account, custody, request);
41
- writer.appendNonZeroBalance(out);
42
- }
43
-
44
- return state.complete(writer);
45
- }
46
- }
47
-
48
- /// @title BorrowAgainstBalanceToBalance
49
- /// @notice Command that issues loans against BALANCE state positions, emitting BALANCE outputs.
50
- abstract contract BorrowAgainstBalanceToBalance is CommandBase {
51
- uint internal immutable borrowAgainstBalanceToBalanceId = commandId(BABTB);
52
-
53
- constructor(string memory input) {
54
- emit Command(host, BABTB, input, borrowAgainstBalanceToBalanceId, State.Balances, State.Balances, false);
55
- }
56
-
57
- /// @dev Override to borrow against a balance position.
58
- /// `request` is the live auxiliary request cursor for this command;
59
- /// implementations validate and unpack it as needed.
60
- function borrowAgainstBalanceToBalance(
61
- bytes32 account,
62
- AssetAmount memory balance,
63
- Cur memory request
64
- ) internal virtual returns (AssetAmount memory);
65
-
66
- function borrowAgainstBalanceToBalance(
67
- CommandContext calldata c
68
- ) external onlyCommand(borrowAgainstBalanceToBalanceId, c.target) returns (bytes memory) {
69
- (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
70
- Cur memory request = cursor(c.request);
71
- Writer memory writer = Writers.allocBalances(stateCount);
72
-
73
- while (state.i < state.bound) {
74
- AssetAmount memory balance = state.unpackBalanceValue();
75
- AssetAmount memory out = borrowAgainstBalanceToBalance(c.account, balance, request);
76
- writer.appendNonZeroBalance(out);
77
- }
78
-
79
- return state.complete(writer);
80
- }
81
- }
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
@@ -1,99 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import {CommandContext, CommandBase, State} from "./Base.sol";
5
- import {AssetAmount, HostAmount, Cur, Cursors, Writers, Writer} from "../Cursors.sol";
6
-
7
- string constant LFBTB = "liquidateFromBalanceToBalances";
8
- string constant LFCTB = "liquidateFromCustodyToBalances";
9
-
10
- using Cursors for Cur;
11
- using Writers for Writer;
12
-
13
- /// @title LiquidateFromBalanceToBalances
14
- /// @notice Command that liquidates BALANCE state positions into BALANCE outputs
15
- /// using a virtual hook. The output-to-input ratio is set at construction via `scaledRatio`.
16
- abstract contract LiquidateFromBalanceToBalances is CommandBase {
17
- uint internal immutable liquidateFromBalanceToBalancesId = commandId(LFBTB);
18
- uint private immutable outScale;
19
-
20
- constructor(string memory input, uint scaledRatio) {
21
- outScale = scaledRatio;
22
- emit Command(host, LFBTB, input, liquidateFromBalanceToBalancesId, State.Balances, State.Balances, false);
23
- }
24
-
25
- /// @dev Override to liquidate using a balance repayment amount.
26
- /// `request` may be ignored by implementations that don't need it.
27
- /// Implementations validate and unpack it as needed, and may append
28
- /// BALANCE outputs to `out` within the capacity implied by this command's
29
- /// configured `scaledRatio`.
30
- function liquidateFromBalanceToBalances(
31
- bytes32 account,
32
- AssetAmount memory balance,
33
- Cur memory request,
34
- Writer memory out
35
- ) internal virtual;
36
-
37
- function liquidateFromBalanceToBalances(
38
- CommandContext calldata c
39
- ) external onlyCommand(liquidateFromBalanceToBalancesId, c.target) returns (bytes memory) {
40
- (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
41
- Cur memory request = cursor(c.request);
42
- Writer memory writer = Writers.allocScaledBalances(stateCount, outScale);
43
-
44
- while (state.i < state.bound) {
45
- AssetAmount memory balance = state.unpackBalanceValue();
46
- liquidateFromBalanceToBalances(c.account, balance, request, writer);
47
- }
48
-
49
- return state.complete(writer);
50
- }
51
- }
52
-
53
- /// @title LiquidateFromCustodyToBalances
54
- /// @notice Command that liquidates CUSTODY state positions into BALANCE outputs
55
- /// using a virtual hook. The output-to-input ratio is set at construction via `scaledRatio`.
56
- abstract contract LiquidateFromCustodyToBalances is CommandBase {
57
- uint internal immutable liquidateFromCustodyToBalancesId = commandId(LFCTB);
58
- uint private immutable outScale;
59
-
60
- constructor(string memory input, uint scaledRatio) {
61
- outScale = scaledRatio;
62
- emit Command(host, LFCTB, input, liquidateFromCustodyToBalancesId, State.Custodies, State.Balances, false);
63
- }
64
-
65
- /// @dev Override to liquidate using a custody repayment amount.
66
- /// `request` may be ignored by implementations that don't need it.
67
- /// Implementations validate and unpack it as needed, and may append
68
- /// BALANCE outputs to `out` within the capacity implied by this command's
69
- /// configured `scaledRatio`.
70
- function liquidateFromCustodyToBalances(
71
- bytes32 account,
72
- HostAmount memory custody,
73
- Cur memory request,
74
- Writer memory out
75
- ) internal virtual;
76
-
77
- function liquidateFromCustodyToBalances(
78
- CommandContext calldata c
79
- ) external onlyCommand(liquidateFromCustodyToBalancesId, c.target) returns (bytes memory) {
80
- (Cur memory state, uint stateCount, ) = cursor(c.state, 1);
81
- Cur memory request = cursor(c.request);
82
- Writer memory writer = Writers.allocScaledBalances(stateCount, outScale);
83
-
84
- while (state.i < state.bound) {
85
- HostAmount memory custody = state.unpackCustodyValue();
86
- liquidateFromCustodyToBalances(c.account, custody, request, writer);
87
- }
88
-
89
- return state.complete(writer);
90
- }
91
- }
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-