@rootzero/contracts 1.17.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,33 @@
3
3
  Until the protocol reaches integration-stable status, minor versions may include
4
4
  breaking API changes. Breaking changes are called out explicitly.
5
5
 
6
+ ## 1.18.0
7
+
8
+ ### Added
9
+
10
+ - Added the non-funded `repay` and funded `repayPayable` commands. Both consume
11
+ `Position` state, settle only its liability side, and return the released
12
+ asset side as `Balance` state.
13
+ - Added the reusable non-funded `RepayHook` settlement primitive and the
14
+ execution-funded `RepayPayableHook`.
15
+ - Added the opt-in `RevokeAsset` guardian endpoint, which accepts `Asset`
16
+ entries and denies each asset through the existing `DenyAssetsHook`.
17
+
18
+ ### Changed
19
+
20
+ - `Settlement.settle` now delegates its liability leg to the virtual `repay`
21
+ primitive. The default behavior remains a nonzero `debitAccount` call, while
22
+ derived settlement implementations can customize repayment in one place.
23
+ - Exported the repayment commands and hooks and the asset-revocation guard from
24
+ their corresponding public barrels.
25
+
26
+ ### Upgrade Compatibility
27
+
28
+ - Hosts inheriting `Settlement` retain the previous default settlement
29
+ behavior. Hosts that already declare an internal
30
+ `repay(bytes32,bytes32,uint)` function may need to mark it as an override or
31
+ rename it when upgrading.
32
+
6
33
  ## 1.17.0
7
34
 
8
35
  ### Breaking Changes
package/Core.sol CHANGED
@@ -16,7 +16,7 @@ import { CommandCalls, FailedCall, NodeCalls, PortCalls, RawNodeCalls } from "./
16
16
  import { EndpointBase, InputEndpointBase } from "./core/Endpoint.sol";
17
17
  import { Pipeline } from "./core/Pipeline.sol";
18
18
  import { Budget, Budgets } from "./execution/Budget.sol";
19
- import { CreditAccountHook, DebitAccountHook, PostHook, SettleHook, Settlement } from "./core/Settlement.sol";
19
+ import { CreditAccountHook, DebitAccountHook, PostHook, RepayHook, SettleHook, Settlement } from "./core/Settlement.sol";
20
20
  import { Portal } from "./core/Portal.sol";
21
21
  import { AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Position, Tx } from "./core/Types.sol";
22
22
  import { Validator } from "./core/Validator.sol";
package/Endpoints.sol CHANGED
@@ -5,7 +5,7 @@ pragma solidity ^0.8.33;
5
5
  // Import this file to inherit from the full rootzero callable host surface without managing individual paths.
6
6
 
7
7
  // Shared endpoint hooks
8
- import { CreditAccountHook, DebitAccountHook, PostHook, SettleHook } from "./core/Settlement.sol";
8
+ import { CreditAccountHook, DebitAccountHook, PostHook, RepayHook, SettleHook } from "./core/Settlement.sol";
9
9
 
10
10
  // Commands
11
11
  import { CommandBase } from "./commands/Base.sol";
@@ -17,8 +17,14 @@ import { Deposit, DepositHook, DepositPayable, DepositPayableHook } from "./comm
17
17
  import { Payout, PayoutHook } from "./commands/Payout.sol";
18
18
  import { Provision, ProvisionHook, ProvisionPayable, ProvisionPayableHook } from "./commands/Provision.sol";
19
19
  import { RecoverPayable, RecoverPayableHook } from "./commands/Recover.sol";
20
+ import { Repay, RepayPayable, RepayPayableHook } from "./commands/Repay.sol";
20
21
  import { RelayPayable, RelayBalancePayable, RelayPayableHook } from "./commands/Relay.sol";
21
- import { InternalSettle, Settle, SettlePayable, SettlePayableHook } from "./commands/Settle.sol";
22
+ import {
23
+ InternalSettle,
24
+ Settle,
25
+ SettlePayable,
26
+ SettlePayableHook
27
+ } from "./commands/Settle.sol";
22
28
  import { Withdraw, WithdrawHook } from "./commands/Withdraw.sol";
23
29
 
24
30
  // Admin commands
@@ -47,7 +53,7 @@ import { PortPost } from "./ports/Post.sol";
47
53
 
48
54
  // Guard endpoints
49
55
  import { GuardBase } from "./guards/Base.sol";
50
- import { Revoke, RevokeAllowance } from "./guards/Revoke.sol";
56
+ import { Revoke, RevokeAllowance, RevokeAsset } from "./guards/Revoke.sol";
51
57
 
52
58
  // Query endpoints
53
59
  import { QueryBase } from "./queries/Base.sol";
@@ -0,0 +1,83 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Execution, Executions, CommandBase, Lanes, Specs} from "./Base.sol";
5
+ import {RepayHook} from "../core/Settlement.sol";
6
+ import {Action} from "../annotations/Action.sol";
7
+ import {Actions} from "../utils/Actions.sol";
8
+
9
+ using Executions for Execution;
10
+
11
+ /// @notice Hook implemented by hosts that repay position liabilities using native value.
12
+ abstract contract RepayPayableHook {
13
+ /// @notice Override to repay one liability for `account` with a shared value budget.
14
+ /// @param account Account whose liability is being repaid.
15
+ /// @param liability Identifier for the liability side.
16
+ /// @param debt Quantity on the liability side.
17
+ /// @param funds Mutable execution used only for its remaining native-value budget.
18
+ function repay(bytes32 account, bytes32 liability, uint debt, Execution memory funds) internal virtual;
19
+ }
20
+
21
+ /// @title Repay
22
+ /// @notice Command that repays POSITION liabilities and returns their assets as BALANCE state.
23
+ abstract contract Repay is CommandBase, RepayHook, Action {
24
+ uint private immutable descriptor;
25
+
26
+ constructor() {
27
+ uint id;
28
+ (id, descriptor) = command("repay", Specs.Position, Specs.Empty, Specs.Balance, 0, false, false);
29
+ action(id, Actions.Settle);
30
+ }
31
+
32
+ /// @notice Repay each POSITION liability and return its asset as BALANCE state.
33
+ /// @param state POSITION block stream.
34
+ /// @return BALANCE output state containing each released asset side.
35
+ /// @return Empty transaction stream.
36
+ function repay(
37
+ bytes32 account,
38
+ bytes calldata state,
39
+ bytes calldata input
40
+ ) external onlyCommand returns (bytes memory, bytes memory) {
41
+ Execution memory exec = openCommand(state, input, descriptor, 0);
42
+
43
+ while (exec.more()) {
44
+ (bytes32 asset, uint amount, bytes32 liability, uint debt) = exec.unpackPosition(Lanes.State);
45
+ repay(account, liability, debt);
46
+ exec.outputBalance(asset, amount);
47
+ }
48
+
49
+ return close(exec, account);
50
+ }
51
+ }
52
+
53
+ /// @title RepayPayable
54
+ /// @notice Funded command that repays POSITION liabilities and returns their assets as BALANCE state.
55
+ abstract contract RepayPayable is CommandBase, RepayPayableHook, Action {
56
+ uint private immutable descriptor;
57
+
58
+ constructor() {
59
+ uint id;
60
+ (id, descriptor) = command("repayPayable", Specs.Position, Specs.Empty, Specs.Balance, 0, true, false);
61
+ action(id, Actions.Settle);
62
+ }
63
+
64
+ /// @notice Repay each POSITION liability and return its asset as BALANCE state.
65
+ /// @param state POSITION block stream.
66
+ /// @return BALANCE output state containing each released asset side.
67
+ /// @return Remaining native value as a refund transaction stream.
68
+ function repayPayable(
69
+ bytes32 account,
70
+ bytes calldata state,
71
+ bytes calldata input
72
+ ) external payable onlyCommand returns (bytes memory, bytes memory) {
73
+ Execution memory exec = openCommand(state, input, descriptor, 0);
74
+
75
+ while (exec.more()) {
76
+ (bytes32 asset, uint amount, bytes32 liability, uint debt) = exec.unpackPosition(Lanes.State);
77
+ repay(account, liability, debt, exec);
78
+ exec.outputBalance(asset, amount);
79
+ }
80
+
81
+ return close(exec, account);
82
+ }
83
+ }
@@ -28,22 +28,23 @@ abstract contract PostHook {
28
28
  function post(bytes32 from, bytes32 to, bytes32 asset, uint amount) internal virtual;
29
29
  }
30
30
 
31
+ /// @title RepayHook
32
+ /// @notice Hook for repaying one account liability.
33
+ abstract contract RepayHook {
34
+ /// @notice Override to repay `debt` denominated in `liability` for `account`.
35
+ function repay(bytes32 account, bytes32 liability, uint debt) internal virtual;
36
+ }
37
+
31
38
  /// @title SettleHook
32
39
  /// @notice Hook for settling one asset-liability position.
33
40
  abstract contract SettleHook {
34
41
  /// @notice Override to settle one position for `account`.
35
- function settle(
36
- bytes32 account,
37
- bytes32 asset,
38
- uint amount,
39
- bytes32 liability,
40
- uint debt
41
- ) internal virtual;
42
+ function settle(bytes32 account, bytes32 asset, uint amount, bytes32 liability, uint debt) internal virtual;
42
43
  }
43
44
 
44
45
  /// @title Settlement
45
46
  /// @notice Default account-hook implementation for transaction posting and position settlement.
46
- abstract contract Settlement is PostHook, SettleHook, DebitAccountHook, CreditAccountHook {
47
+ abstract contract Settlement is PostHook, SettleHook, RepayHook, DebitAccountHook, CreditAccountHook {
47
48
  /// @notice Post one transaction by debiting its source and crediting its destination.
48
49
  /// Returns without calling either hook when `amount` is zero and skips either
49
50
  /// operation when the corresponding account is zero.
@@ -53,6 +54,12 @@ abstract contract Settlement is PostHook, SettleHook, DebitAccountHook, CreditAc
53
54
  if (to != 0) creditAccount(to, asset, amount);
54
55
  }
55
56
 
57
+ /// @notice Repay one liability by debiting it from the account.
58
+ /// Skips the debit when `debt` is zero.
59
+ function repay(bytes32 account, bytes32 liability, uint debt) internal virtual override {
60
+ if (debt != 0) debitAccount(account, liability, debt);
61
+ }
62
+
56
63
  /// @notice Settle one position by crediting its asset and debiting its liability.
57
64
  /// Skips either operation when its corresponding amount is zero.
58
65
  function settle(
package/guards/Revoke.sol CHANGED
@@ -2,6 +2,7 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {AllowanceHook} from "../commands/admin/Allowance.sol";
5
+ import {DenyAssetsHook} from "../commands/admin/DenyAssets.sol";
5
6
  import {GuardBase} from "./Base.sol";
6
7
  import {Specs} from "../Codec.sol";
7
8
  import {Execution, Executions, Lanes} from "../execution/Execution.sol";
@@ -49,3 +50,24 @@ abstract contract RevokeAllowance is GuardBase, AllowanceHook {
49
50
  }
50
51
  }
51
52
  }
53
+
54
+ /// @title RevokeAsset
55
+ /// @notice Guardian action that denies assets through the host's existing asset hook.
56
+ /// @dev Opt-in guard. Hosts expose it by inheriting this contract and implementing DenyAssetsHook.
57
+ abstract contract RevokeAsset is GuardBase, DenyAssetsHook {
58
+ uint private immutable descriptor;
59
+
60
+ constructor() {
61
+ (, descriptor) = guard("revokeAsset", Specs.Asset);
62
+ }
63
+
64
+ /// @notice Deny every ASSET block in `input` as the active guardian.
65
+ function revokeAsset(bytes calldata input) external onlyGuardian {
66
+ Execution memory exec = openInput(input, descriptor, 0);
67
+
68
+ while (exec.more()) {
69
+ bytes32 asset = exec.unpackAsset(Lanes.Input);
70
+ denyAsset(asset);
71
+ }
72
+ }
73
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootzero/contracts",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "Solidity contracts and protocol building blocks for rootzero hosts and commands.",
5
5
  "private": false,
6
6
  "license": "GPL-3.0-only",