@raac/rpc 2.0.0-beta.20 → 2.0.0-beta.22

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.
@@ -47,6 +47,7 @@ import { findContract } from "./contracts/findContract";
47
47
  import { decodeCall } from "./contracts/decodeCall";
48
48
  import { resolveName, resolveNames } from "./contracts/resolveName";
49
49
  import { getTokenMetadata } from "./contracts/getTokenMetadata";
50
+ import { resolveTokenInfo } from "./contracts/resolveTokenInfo";
50
51
  import getLatestPrice from "./contracts/housePrices/getLatestPrice";
51
52
  import setOracle from "./contracts/housePrices/setOracle";
52
53
  import tick from "./minter/tick";
@@ -139,7 +140,7 @@ import getRoles from "./contracts/getRoles";
139
140
  import getTreasuryState from "./contracts/treasury/getState";
140
141
  import getComplianceStatuses from "./contracts/complianceRegistry/getStatuses";
141
142
  import getStabilityPoolAdminState from "./pools/stabilityPool/getAdminState";
142
- import { readLiquidationContext, readLiquidationTarget, quoteLiquidation, suggestSplit, simulateWithSplit, minSharesOut } from "./pools/stabilityPool/liquidation";
143
+ import { readLiquidationContext, readLiquidationTarget, planLiquidation, curveQuote, largestClearingFloor, toleranceNeeded, priceImpact, valueAtNav, sharesAtNav, minSharesOut, DEFAULT_PLAN_PARAMS } from "./pools/stabilityPool/liquidation";
143
144
  import { getEmissionSchedule, getSchedulePosition, getEmissionPerSecondForWeek, getMintingWeekForTimestamp } from "./minter/emissionSchedule";
144
145
  import getRWAVaultRegisteredAdapters from "./pools/rwaVault/getRegisteredAdapters";
145
146
  import getRWAVaultSeedStatus from "./pools/rwaVault/getSeedStatus";
@@ -441,6 +442,7 @@ declare class RPCLibrary {
441
442
  resolveName: typeof resolveName;
442
443
  resolveNames: typeof resolveNames;
443
444
  getTokenMetadata: typeof getTokenMetadata;
445
+ resolveTokenInfo: typeof resolveTokenInfo;
444
446
  feeCollector: {
445
447
  claimRewardFromPool: typeof claimRewardFromPool;
446
448
  getState: typeof getFeeCollectorState;
@@ -705,10 +707,15 @@ declare class RPCLibrary {
705
707
  liquidation: {
706
708
  getContext: typeof readLiquidationContext;
707
709
  getTarget: typeof readLiquidationTarget;
708
- quote: typeof quoteLiquidation;
709
- suggestSplit: typeof suggestSplit;
710
- simulateWithSplit: typeof simulateWithSplit;
710
+ plan: typeof planLiquidation;
711
+ curveQuote: typeof curveQuote;
712
+ largestClearingFloor: typeof largestClearingFloor;
713
+ toleranceNeeded: typeof toleranceNeeded;
714
+ priceImpact: typeof priceImpact;
715
+ valueAtNav: typeof valueAtNav;
716
+ sharesAtNav: typeof sharesAtNav;
711
717
  minSharesOut: typeof minSharesOut;
718
+ DEFAULT_PLAN_PARAMS: typeof DEFAULT_PLAN_PARAMS;
712
719
  };
713
720
  };
714
721
  lendingPool: {
@@ -3,12 +3,10 @@ import { ChainId } from "../../../configs/chains";
3
3
  import { TokenAmount } from "../../../utils/amount";
4
4
  export interface UserGaugeTokenState {
5
5
  address: string;
6
- /** From the token registry; undefined when the registry does not list the token. */
6
+ /** From the token registry, or read from the token when the registry does not list it; undefined if it has none. */
7
7
  symbol?: string;
8
- /** From the token registry; 18 when the registry does not list the token. */
8
+ /** From the token registry, or read from the token when the registry does not list it. */
9
9
  decimals: number;
10
- /** Wallet balance, in this token's base units. */
11
- balance: TokenAmount;
12
10
  /** Allowance to `spender`, in this token's base units. */
13
11
  allowance: TokenAmount;
14
12
  /** The contract that pulls the token: the gauge for the staking token, the wrapper for the underlying. */
@@ -23,13 +21,14 @@ export interface UserGaugeState {
23
21
  underlying: UserGaugeTokenState | null;
24
22
  }
25
23
  /**
26
- * What a wallet needs to stake in, wrap for, or unstake from a gauge: its stake, its balance of the staking token and its
27
- * allowance to the gauge, and for a wrapped gauge its balance of the underlying and allowance to the wrapper.
24
+ * What a wallet needs to stake in, wrap for, or unstake from a gauge: its stake, its allowance of the staking token to the
25
+ * gauge, and for a wrapped gauge its allowance of the underlying to the wrapper. Read the wallet's token balances with
26
+ * `wallet.assets.getBalance`.
28
27
  *
29
28
  * @param chainId - The chain/network to use.
30
29
  * @param gaugeAddressOrId - Address of the gauge contract or its config ID.
31
30
  * @param user - The wallet.
32
31
  * @param provider - Optional ethers.js Provider instance.
33
- * @returns The wallet's gauge state. Every amount carries its own token's registry decimals and symbol.
32
+ * @returns The wallet's gauge state. Every amount carries its own token's decimals and symbol.
34
33
  */
35
34
  export declare const getUserGaugeState: (chainId: ChainId, gaugeAddressOrId: string, user: string, provider?: Provider) => Promise<UserGaugeState>;
@@ -1,10 +1,8 @@
1
1
  import { Provider } from "ethers";
2
2
  import { ChainId } from "../../configs/chains";
3
3
  import { TokenAmount, ScaledValue } from "../../utils/amount";
4
+ /** A wallet's open redeem request and allowances to the vault. Token balances, shares included, come from `wallet.assets.getBalance`. */
4
5
  export interface PsmVaultUserInfo {
5
- shareBalance: TokenAmount;
6
- savingsTokenBalance: TokenAmount;
7
- baseAssetBalance: TokenAmount;
8
6
  redeemRequest: {
9
7
  shares: TokenAmount;
10
8
  exitTime: number;
@@ -0,0 +1,18 @@
1
+ import { Provider } from "ethers";
2
+ import { ChainId } from "../configs/chains";
3
+ import { TokenInfo } from "../utils/amount";
4
+ /**
5
+ * A token's decimals and symbol for any address: the chain config registry first, then the token itself for an address
6
+ * the registry does not list. An on-chain read happens once per chain and token; a failed read is not remembered, so
7
+ * the next call tries again.
8
+ *
9
+ * Use this wherever a method takes a token address it cannot know in advance. Methods that take an asset key keep
10
+ * using `toTokenAmount`, which reads only the registry.
11
+ *
12
+ * @param chainId The chain id.
13
+ * @param idOrAddress An asset key from the registry, or a token contract address, any casing.
14
+ * @param provider Optional ethers.js Provider instance.
15
+ * @returns The token's decimals, and its symbol when it has one: a token without a readable `symbol()` gets none.
16
+ * @throws If an asset key is not in the registry, or an unlisted token has no readable `decimals()`.
17
+ */
18
+ export declare const resolveTokenInfo: (chainId: ChainId, idOrAddress: string, provider?: Provider) => Promise<TokenInfo>;
@@ -6,8 +6,6 @@ export interface YearnVaultUserInfo {
6
6
  shares: TokenAmount;
7
7
  /** What `shares` redeem for now, in the vault asset. */
8
8
  assets: TokenAmount;
9
- /** Wallet balance of the vault asset. */
10
- assetBalance: TokenAmount;
11
9
  /** Vault asset allowance to the vault, which `deposit` and `mint` pull from. */
12
10
  assetAllowance: TokenAmount;
13
11
  /** Most the user can deposit now, in the vault asset. */
@@ -18,12 +16,13 @@ export interface YearnVaultUserInfo {
18
16
  maxRedeem: TokenAmount;
19
17
  }
20
18
  /**
21
- * Gets a user's position in a Yearn V3 vault, plus their vault asset balance and allowance.
19
+ * Gets a user's position in a Yearn V3 vault, plus their vault asset allowance. Read the wallet's asset balance with
20
+ * `wallet.assets.getBalance`.
22
21
  *
23
22
  * @param chainId - The chain/network to use.
24
23
  * @param vaultAddressOrId - The vault's key in the chain config's `yearn` section (e.g. "spmusd"), or its address.
25
24
  * @param account - Address of the user.
26
25
  * @param provider - Optional ethers.js Provider instance.
27
- * @returns The user's shares, their asset value, balances, allowance and limits, in base units.
26
+ * @returns The user's shares, their asset value, allowance and limits, in base units.
28
27
  */
29
28
  export declare function getUserInfo(chainId: ChainId, vaultAddressOrId: string, account: string, provider?: Provider): Promise<YearnVaultUserInfo>;
@@ -1,13 +1,14 @@
1
1
  /**
2
- * Liquidation simulation for StabilityPool.liquidateBorrower, mirroring LiquidationStrategyProxy:
2
+ * Planning StabilityPool.liquidateBorrower, mirroring LiquidationStrategyProxy:
3
3
  * 1. the seized collateral is deposited into the RWAVault for vault-token shares, unless it already is the vault token;
4
4
  * 2. the stability pool's whole vault-token balance (the proxy runs under delegatecall) is split by BPS into
5
- * mint (treasury fee), burn, swap and liquidity (fee collector);
6
- * 3. only the swap slice becomes crvUSD, through LiquidationSwap and its Curve pool;
7
- * 3b. LiquidationSwap reverts when slippage protection is on and get_dy falls below pricePerShare / oracle price
8
- * less its tolerance, which is the case when Curve trades below the vault's value;
9
- * 4. the crvUSD must cover the position's debt; any shortfall is withdrawn from the LendingPool with the pool's
10
- * rTokens, so stability pool depositors pay it, and the call reverts (InsufficientBalance) if they hold too few.
5
+ * mint (treasury), burn, swap and liquidity (fee collector);
6
+ * 3. the swap slice is sold on Curve through LiquidationSwap, whose floor is the vault's NAV less a tolerance;
7
+ * 4. the reserve asset the pool then holds (swap proceeds plus whatever it held before) repays the debt; a shortfall
8
+ * is drawn from the pool's rTokens through the LendingPool, and the call reverts (InsufficientBalance) if too few.
9
+ *
10
+ * The plan sizes the swap on Curve's get_dy and values every other leg at NAV. Any gap between the swap and the debt
11
+ * is reserve asset the Treasury sends to the pool beforehand, and the unsold vault tokens go to the Treasury for it.
11
12
  */
12
13
  import { type Provider } from "ethers";
13
14
  import { ChainId } from "../../configs/chains/index";
@@ -21,29 +22,71 @@ export interface LiquidationSplit {
21
22
  export declare const SPLIT_KEYS: readonly ["mintBps", "burnBps", "swapBps", "liquidityBps"];
22
23
  export declare const splitTotal: (s: LiquidationSplit) => bigint;
23
24
  export declare const sameSplit: (a: LiquidationSplit, b: LiquidationSplit) => boolean;
24
- /** The stability pool's liquidation route, read once per review. */
25
+ /** The stability pool's liquidation route and everything on chain that decides how a liquidation can go, at one block. */
25
26
  export interface LiquidationContext {
26
27
  stabilityPool: string;
28
+ lendingPool: string;
27
29
  liquidationSwap: string;
28
30
  liquidityPool: string;
29
31
  rwaVault: string;
32
+ treasury: string;
33
+ feeCollector: string;
30
34
  vaultToken: string;
31
35
  vaultSymbol: string;
36
+ /** The reserve asset the debt is in (crvUSD or pmUSD) and the pool's rToken for it. */
37
+ reserveAsset: string;
38
+ rToken: string;
32
39
  iIn: bigint;
33
40
  iOut: bigint;
34
41
  split: LiquidationSplit;
35
42
  /** Vault tokens already in the stability pool; the split divides these too. */
36
43
  poolVaultTokens: bigint;
37
- /** rTokens the stability pool holds, which is the most a swap shortfall can draw from the LendingPool. */
44
+ /** Reserve asset the stability pool holds; the proxy counts it toward the debt before drawing on rTokens. */
45
+ poolReserve: bigint;
46
+ /** rTokens the stability pool holds, which is the most a shortfall can draw from the LendingPool. */
38
47
  rTokens: bigint;
39
- /** LendingPool grace period, in seconds, before an insured position can be finalized. */
40
- gracePeriod: number;
41
- /** LiquidationSwap's own floor: null when protection is off, else pricePerShare / oracle price less its tolerance. */
42
- slippage: {
43
- bps: bigint;
48
+ /** What depositors are owed; above the rTokens held, the pool is under-backed by the difference. */
49
+ deTokenSupply: bigint;
50
+ /** Reserve asset the LendingPool can pay out now: the rToken contract's buffer plus what its yield vault lets it withdraw (null when that read is unavailable). */
51
+ idleCash: {
52
+ buffer: bigint;
53
+ vaultWithdrawable: bigint | null;
54
+ };
55
+ /** The LendingPool's accounting the buffer rebalance after repayment works from: total liquidity, the buffer ratio it keeps, and the smallest rebalance it bothers with. */
56
+ lendingPoolLiquidity: {
57
+ total: bigint;
58
+ bufferRatioBps: bigint;
59
+ minRebalance: bigint;
60
+ };
61
+ /** Curve: get_dy for one vault token, the reserve asset side's balance, and the pool's current fee in bps. */
62
+ curve: {
63
+ spot: bigint;
64
+ depth: bigint;
65
+ feeBps: bigint;
66
+ };
67
+ /** NAV: the vault's price per share in USD and the oracle's USD price of the reserve asset, both 1e18; `priceTimestamp` when the oracle reports one. */
68
+ nav: {
44
69
  pricePerShare: bigint;
45
70
  oraclePrice: bigint;
46
- } | null;
71
+ priceTimestamp: number | null;
72
+ };
73
+ /** Vault tokens in existence: the burn leg runs before the swap and raises the price per share the floor is computed from. */
74
+ vaultTokenSupply: bigint;
75
+ /** LiquidationSwap's floor: when on, the swap must return at least NAV less `bps`. `owner` can change it. */
76
+ floor: {
77
+ enabled: boolean;
78
+ bps: bigint;
79
+ owner: string;
80
+ };
81
+ /** The liquidity leg reverts while the FeeCollector is paused or its fee type is not registered. */
82
+ feeCollectorState: {
83
+ paused: boolean;
84
+ liquidityFeeTypeRegistered: boolean;
85
+ };
86
+ /** The Treasury leg deposits vault tokens into the Treasury contract, which must list them. */
87
+ treasurySupportsVaultToken: boolean;
88
+ /** LendingPool grace period, in seconds, before an insured position can be finalized. */
89
+ gracePeriod: number;
47
90
  }
48
91
  /** Everything liquidateBorrower needs for one position, plus its state on chain. */
49
92
  export interface LiquidationTarget {
@@ -57,56 +100,127 @@ export interface LiquidationTarget {
57
100
  /** The collateral already is the vault token, so no RWAVault deposit happens. */
58
101
  isVaultToken: boolean;
59
102
  collateralValue: bigint;
103
+ /** Vault tokens this liquidation adds: shares minted for the collateral, or the collateral itself. */
104
+ sharesFromCollateral: bigint;
60
105
  /** getPositionScaledDebt: the debt with accrued interest, which is what the liquidation repays. */
61
106
  debt: bigint;
62
107
  isUnderLiquidation: boolean;
63
108
  isInsured: boolean;
64
109
  liquidationStartTime: number;
65
110
  }
66
- export interface LiquidationQuote {
67
- split: LiquidationSplit;
68
- /** Vault tokens this liquidation adds: shares minted for the collateral, or the collateral itself. */
69
- sharesFromCollateral: bigint;
70
- /** sharesFromCollateral plus the pool's existing balance: what the split divides. */
111
+ /** The operator's policy, all in basis points. */
112
+ export interface PlanParams {
113
+ /** Share burned. */
114
+ burnBps: bigint;
115
+ /** The Treasury's base fee, before any gap it funds. */
116
+ treasuryBps: bigint;
117
+ /** The most the liquidity leg gets once the Treasury funds a gap; without a gap it takes the whole remainder. */
118
+ liquidityCapBps: bigint;
119
+ /** The swap stops growing once its realised rate falls this far below Curve's spot rate. */
120
+ impactCapBps: bigint;
121
+ /** The highest floor tolerance the plan may propose setting on LiquidationSwap. */
122
+ toleranceCeilingBps: bigint;
123
+ /** Added to the tolerance the swap needs when one is proposed, against drift between the quote and execution; the swap is sized so that needed plus cushion stays under the ceiling. */
124
+ toleranceCushionBps: bigint;
125
+ /** Added to the debt, since it accrues until the transaction executes. */
126
+ marginBps: bigint;
127
+ }
128
+ export declare const DEFAULT_PLAN_PARAMS: PlanParams;
129
+ /** DeFi sells on Curve as much as the debt needs; OTC sells nothing and the Treasury funds the whole debt. */
130
+ export type PlanMode = "defi" | "otc";
131
+ /** What stopped the swap growing: the debt is covered, the impact cap, the floor at the tolerance ceiling, the whole balance, or the mode. */
132
+ export type SwapBound = "debt" | "impact" | "floor" | "balance" | "mode";
133
+ export type PlanRoute = "covered" | "partial" | "otc";
134
+ export interface LiquidationPlan {
135
+ mode: PlanMode;
136
+ params: PlanParams;
137
+ /** What the split divides: the shares for the collateral plus the pool's existing vault tokens. */
71
138
  totalVaultTokens: bigint;
139
+ /** The debt plus the margin. */
140
+ required: bigint;
141
+ /** `required` less the reserve asset the pool already holds: what the swap and the Treasury must bring. */
142
+ toCover: bigint;
72
143
  swapAmount: bigint;
73
- /** get_dy from the deployed Curve pool; null when the quote reverted. */
74
- swapOut: bigint | null;
75
- /** LiquidationSwap's minimum output for swapAmount; null when its slippage protection is off. */
76
- minSwapOut: bigint | null;
77
- /** Debt the swap does not cover, drawn from depositors' rTokens; the whole debt when the quote reverted. */
78
- shortfall: bigint;
79
- coversDebt: boolean;
80
- /** The collateral is worth less than the debt, so depositors lose whatever the split. */
81
- badDebt: bigint;
82
- /** get_dy for the whole balance: the most any split can recover. */
83
- maxSwapOut: bigint | null;
84
- /** How far the realised swap rate falls below the spot rate, in basis points. */
85
- priceImpactBps: bigint | null;
86
- /** The crvUSD side of the Curve pool; the swap can never return more. */
87
- poolReserveOut: bigint | null;
88
- }
89
- export interface SuggestedSplit extends LiquidationSplit {
90
- projectedOut: bigint;
91
- /** No split covers the debt; this is the best effort (100% swap). */
92
- bestEffort: boolean;
144
+ /** get_dy for `swapAmount`. */
145
+ swapOut: bigint;
146
+ /** How far the swap's realised rate falls below Curve's spot rate. */
147
+ priceImpactBps: bigint;
148
+ /** The floor tolerance this swap needs: get_dy against NAV as it stands after the burn leg. */
149
+ toleranceNeededBps: bigint;
150
+ /** The tolerance to set on LiquidationSwap before the swap, the need plus the cushion; null when the current one suffices or nothing is swapped. */
151
+ proposedToleranceBps: bigint | null;
152
+ bound: SwapBound;
153
+ /** The largest swap at the tolerance on chain, at the ceiling less the cushion, and under the impact cap. */
154
+ ceilings: {
155
+ atCurrent: bigint;
156
+ atCeiling: bigint;
157
+ underImpact: bigint;
158
+ };
159
+ split: LiquidationSplit;
160
+ /** Each leg in vault tokens, computed the way the proxy does. */
161
+ legs: {
162
+ swap: bigint;
163
+ burn: bigint;
164
+ treasury: bigint;
165
+ liquidity: bigint;
166
+ };
167
+ /** Reserve asset the Treasury must send to the stability pool before the liquidation. */
168
+ gap: bigint;
169
+ /** The Treasury's vault tokens at NAV, and that less the gap it funds: negative means a loss. */
170
+ treasuryValue: bigint;
171
+ treasuryNet: bigint;
172
+ /** The liquidity leg was held to the cap, or set to zero because the FeeCollector would revert. */
173
+ liquidityCapped: boolean;
174
+ liquidityDisabled: boolean;
175
+ route: PlanRoute;
176
+ /**
177
+ * The alternative for a gap: the pool's rTokens cover it through the LendingPool. Feasible when the pool holds
178
+ * enough rTokens and the LendingPool enough idle cash; null when the idle cash is unknown. `inject` is the reserve
179
+ * asset to send to the rToken contract so the withdrawal clears when the idle cash falls short.
180
+ */
181
+ absorb: {
182
+ feasible: boolean | null;
183
+ rTokensAfter: bigint;
184
+ inject: bigint;
185
+ };
186
+ /**
187
+ * The LendingPool rebalances its buffer when the debt is written off, before the repayment reaches it, so it wants
188
+ * `shortage` more in the buffer and takes it from the yield vault. A build that rebalances strictly (Sepolia)
189
+ * reverts when the vault cannot give that much; `inject` is the reserve asset to send to the rToken contract first:
190
+ * the whole shortage, since harvesting yield inside the rebalance lowers what the vault then allows.
191
+ */
192
+ rebalance: {
193
+ shortage: bigint;
194
+ feasible: boolean | null;
195
+ inject: bigint;
196
+ };
93
197
  }
94
- /** Reads the stability pool's liquidation route, split, balances and the LendingPool grace period. */
198
+ /** get_dy for an amount of vault tokens; null when Curve reverts. */
199
+ export type Quote = (amount: bigint) => Promise<bigint | null>;
200
+ /** Reads the stability pool's liquidation route, balances, Curve, NAV, floor and leg prerequisites at one block. */
95
201
  export declare function readLiquidationContext(chainId: ChainId, provider: Provider): Promise<LiquidationContext>;
96
202
  /** Assembles liquidateBorrower's arguments and the position's state for one position id ("user:adapter:key"). */
97
203
  export declare function readLiquidationTarget(chainId: ChainId, provider: Provider, ctx: LiquidationContext, positionId: string): Promise<LiquidationTarget>;
98
- /** Prices the liquidation with `split`, using the deployed Curve pool's get_dy rather than the vault's oracle price. */
99
- export declare function quoteLiquidation(provider: Provider, ctx: LiquidationContext, target: LiquidationTarget, split: LiquidationSplit): Promise<LiquidationQuote>;
204
+ /** get_dy on the context's Curve pool. */
205
+ export declare const curveQuote: (provider: Provider, ctx: LiquidationContext) => Quote;
206
+ /** Reserve asset that `shares` vault tokens are worth at NAV, as LiquidationSwap computes its expected output. */
207
+ export declare const valueAtNav: (ctx: Pick<LiquidationContext, "nav">, shares: bigint) => bigint;
208
+ /** Vault tokens worth `value` of reserve asset at NAV, rounded up. */
209
+ export declare const sharesAtNav: (ctx: Pick<LiquidationContext, "nav">, value: bigint) => bigint;
100
210
  /**
101
- * The smallest swap share whose get_dy still covers the debt plus `bufferBps`, with the rest given back to mint,
102
- * burn and liquidity in their current proportion. get_dy grows with dx, so a binary search over BPS is sound.
211
+ * The floor tolerance a swap of `amount` returning `out` needs: how far `out` falls below NAV, in bps, rounded up.
212
+ * The proxy burns the burn leg before it swaps, which lifts the vault's price per share by the burned share of the
213
+ * supply, so the floor LiquidationSwap applies is computed on that higher NAV; `burned` accounts for it.
103
214
  */
104
- export declare function suggestSplit(provider: Provider, ctx: LiquidationContext, target: LiquidationTarget, quote: LiquidationQuote, bufferBps?: bigint): Promise<SuggestedSplit | null>;
105
- /** minSharesOut for the RWAVault deposit: previewDeposit less `slippageBps`. Zero when nothing is deposited. */
106
- export declare const minSharesOut: (target: LiquidationTarget, quote: LiquidationQuote, slippageBps: bigint) => bigint;
215
+ export declare function toleranceNeeded(ctx: Pick<LiquidationContext, "nav" | "vaultTokenSupply">, amount: bigint, out: bigint, burned?: bigint): bigint;
216
+ /** How far the realised rate of a swap falls below Curve's spot rate, in bps. */
217
+ export declare function priceImpact(ctx: Pick<LiquidationContext, "curve">, amount: bigint, out: bigint): bigint;
218
+ /** The largest swap share (bps) whose output clears the floor at `toleranceBps` once `burned` vault tokens are gone; the whole balance when the floor is off. */
219
+ export declare function largestClearingFloor(ctx: Pick<LiquidationContext, "nav" | "floor" | "vaultTokenSupply">, quote: Quote, total: bigint, toleranceBps: bigint, burned?: bigint): Promise<bigint>;
107
220
  /**
108
- * Simulates liquidateBorrower from `sender` with the split overridden in storage (an eth_call state override), so a
109
- * split change in the same batch is simulated rather than only checked. Returns null when the RPC or the storage
110
- * layout cannot be used; otherwise the revert reason, or "" when it succeeds.
221
+ * Sizes the swap, derives the split and says what the Treasury must send. `quote` is Curve's get_dy, so a test can
222
+ * pass a synthetic curve. In "otc" mode nothing is swapped and the Treasury funds the whole uncovered debt.
111
223
  */
112
- export declare function simulateWithSplit(provider: Provider, ctx: LiquidationContext, sender: string, data: string, split: LiquidationSplit): Promise<string | null>;
224
+ export declare function planLiquidation(ctx: LiquidationContext, target: LiquidationTarget, quote: Quote, params?: PlanParams, mode?: PlanMode): Promise<LiquidationPlan>;
225
+ /** minSharesOut for the RWAVault deposit: previewDeposit less `slippageBps`. Zero when nothing is deposited. */
226
+ export declare const minSharesOut: (target: LiquidationTarget, slippageBps: bigint) => bigint;
@@ -607,6 +607,63 @@ declare const ABIS: {
607
607
  type: string;
608
608
  anonymous?: undefined;
609
609
  })[];
610
+ liquidationswap: ({
611
+ inputs: {
612
+ internalType: string;
613
+ name: string;
614
+ type: string;
615
+ }[];
616
+ stateMutability: string;
617
+ type: string;
618
+ name?: undefined;
619
+ anonymous?: undefined;
620
+ outputs?: undefined;
621
+ } | {
622
+ inputs: {
623
+ internalType: string;
624
+ name: string;
625
+ type: string;
626
+ }[];
627
+ name: string;
628
+ type: string;
629
+ stateMutability?: undefined;
630
+ anonymous?: undefined;
631
+ outputs?: undefined;
632
+ } | {
633
+ anonymous: boolean;
634
+ inputs: {
635
+ indexed: boolean;
636
+ internalType: string;
637
+ name: string;
638
+ type: string;
639
+ }[];
640
+ name: string;
641
+ type: string;
642
+ stateMutability?: undefined;
643
+ outputs?: undefined;
644
+ } | {
645
+ inputs: any[];
646
+ name: string;
647
+ outputs: {
648
+ internalType: string;
649
+ name: string;
650
+ type: string;
651
+ }[];
652
+ stateMutability: string;
653
+ type: string;
654
+ anonymous?: undefined;
655
+ } | {
656
+ inputs: {
657
+ internalType: string;
658
+ name: string;
659
+ type: string;
660
+ }[];
661
+ name: string;
662
+ outputs: any[];
663
+ stateMutability: string;
664
+ type: string;
665
+ anonymous?: undefined;
666
+ })[];
610
667
  raacminter: ({
611
668
  inputs: {
612
669
  internalType: string;
@@ -3109,6 +3166,62 @@ declare const getABI: (name: keyof typeof ABIS) => any[] | ({
3109
3166
  type: string;
3110
3167
  stateMutability?: undefined;
3111
3168
  outputs?: undefined;
3169
+ } | {
3170
+ inputs: any[];
3171
+ name: string;
3172
+ outputs: {
3173
+ internalType: string;
3174
+ name: string;
3175
+ type: string;
3176
+ }[];
3177
+ stateMutability: string;
3178
+ type: string;
3179
+ anonymous?: undefined;
3180
+ } | {
3181
+ inputs: {
3182
+ internalType: string;
3183
+ name: string;
3184
+ type: string;
3185
+ }[];
3186
+ name: string;
3187
+ outputs: any[];
3188
+ stateMutability: string;
3189
+ type: string;
3190
+ anonymous?: undefined;
3191
+ })[] | ({
3192
+ inputs: {
3193
+ internalType: string;
3194
+ name: string;
3195
+ type: string;
3196
+ }[];
3197
+ stateMutability: string;
3198
+ type: string;
3199
+ name?: undefined;
3200
+ anonymous?: undefined;
3201
+ outputs?: undefined;
3202
+ } | {
3203
+ inputs: {
3204
+ internalType: string;
3205
+ name: string;
3206
+ type: string;
3207
+ }[];
3208
+ name: string;
3209
+ type: string;
3210
+ stateMutability?: undefined;
3211
+ anonymous?: undefined;
3212
+ outputs?: undefined;
3213
+ } | {
3214
+ anonymous: boolean;
3215
+ inputs: {
3216
+ indexed: boolean;
3217
+ internalType: string;
3218
+ name: string;
3219
+ type: string;
3220
+ }[];
3221
+ name: string;
3222
+ type: string;
3223
+ stateMutability?: undefined;
3224
+ outputs?: undefined;
3112
3225
  } | {
3113
3226
  inputs: {
3114
3227
  internalType: string;
@@ -3,13 +3,14 @@ import { AssetType } from "../../utils/artifacts";
3
3
  import { ChainId } from "../../configs/chains/index";
4
4
  import { TokenAmount } from "../../utils/amount";
5
5
  /**
6
- * Reads a wallet's balance of a configured asset or native ETH.
6
+ * Reads a wallet's balance of a configured asset, any ERC20 by address, or native ETH.
7
7
  * @param chainId The chain id.
8
- * @param assetId The asset key in the chain config, or `"eth"` for native ETH.
8
+ * @param assetIdOrAddress The asset key in the chain config, an ERC20 contract address, or `"eth"` for native ETH.
9
9
  * @param address The wallet address.
10
10
  * @param provider The provider to read with.
11
11
  * @returns The balance in base units with decimals and symbol from the token registry (`"ETH"` and 18 for native ETH).
12
- * @throws If the asset is not deployed on the chain, or the read fails.
12
+ * A token address the registry does not list takes its decimals and symbol from the token, read once per chain.
13
+ * @throws If the asset key is not deployed on the chain, or the read fails.
13
14
  */
14
- declare function getBalance(chainId: ChainId, assetId: AssetType, address: string, provider: Provider): Promise<TokenAmount>;
15
+ declare function getBalance(chainId: ChainId, assetIdOrAddress: AssetType, address: string, provider: Provider): Promise<TokenAmount>;
15
16
  export default getBalance;
@@ -11,6 +11,7 @@ const veRAACToken_json_1 = __importDefault(require("../artifacts/core/tokens/veR
11
11
  const RToken_json_1 = __importDefault(require("../artifacts/core/tokens/RToken.sol/RToken.json")); // assert { type: "json" };
12
12
  const LendingPool_json_1 = __importDefault(require("../artifacts/core/pools/LendingPool/LendingPool.sol/LendingPool.json")); // assert { type: "json" };
13
13
  const StabilityPool_json_1 = __importDefault(require("../artifacts/core/pools/StabilityPool/StabilityPool.sol/StabilityPool.json")); // assert { type: "json" };
14
+ const LiquidationSwap_json_1 = __importDefault(require("../artifacts/core/pools/StabilityPool/LiquidationSwap.sol/LiquidationSwap.json")); // assert { type: "json" };
14
15
  // import LiquidityPoolArtifact from "../artifacts/LiquidityPool/LiquidityPool.sol/LiquidityPool.json"; // assert { type: "json" };
15
16
  const RAACNFT_json_1 = __importDefault(require("../artifacts/core/tokens/RAACNFT.sol/RAACNFT.json")); // assert { type: "json" };
16
17
  const DEToken_json_1 = __importDefault(require("../artifacts/core/tokens/DEToken.sol/DEToken.json")); // assert { type: "json" };
@@ -112,6 +113,7 @@ const ABIS = {
112
113
  // Pools
113
114
  lendingpool: RAACLENDINGPOOL_ABI,
114
115
  stabilitypool: RAACSTABILITYPOOL_ABI,
116
+ liquidationswap: LiquidationSwap_json_1.default.abi,
115
117
  // liquiditypool: LIQUIDITYPOOL_ABI,
116
118
  raacminter: RAACMINTER_ABI,
117
119
  // contracts
@@ -3,30 +3,41 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ethers_1 = require("ethers");
4
4
  const contracts_1 = require("../../utils/contracts");
5
5
  const amount_1 = require("../../utils/amount");
6
+ const resolveTokenInfo_1 = require("../../contracts/resolveTokenInfo");
6
7
  const _helpers_1 = require("../../assets/_helpers");
7
8
  const rpcError_1 = require("../../utils/rpcError");
8
9
  /**
9
- * Reads a wallet's balance of a configured asset or native ETH.
10
+ * Reads a wallet's balance of a configured asset, any ERC20 by address, or native ETH.
10
11
  * @param chainId The chain id.
11
- * @param assetId The asset key in the chain config, or `"eth"` for native ETH.
12
+ * @param assetIdOrAddress The asset key in the chain config, an ERC20 contract address, or `"eth"` for native ETH.
12
13
  * @param address The wallet address.
13
14
  * @param provider The provider to read with.
14
15
  * @returns The balance in base units with decimals and symbol from the token registry (`"ETH"` and 18 for native ETH).
15
- * @throws If the asset is not deployed on the chain, or the read fails.
16
+ * A token address the registry does not list takes its decimals and symbol from the token, read once per chain.
17
+ * @throws If the asset key is not deployed on the chain, or the read fails.
16
18
  */
17
- async function getBalance(chainId, assetId, address, provider) {
19
+ async function getBalance(chainId, assetIdOrAddress, address, provider) {
18
20
  const BALANCE_OF_ABI = ["function balanceOf(address) view returns (uint256)"];
19
21
  let contractAddress;
20
22
  try {
21
- if (assetId === "eth") {
23
+ if (assetIdOrAddress === "eth") {
22
24
  const balance = await provider.getBalance(address);
23
25
  return (0, amount_1.toAmount)(balance, amount_1.WAD_DECIMALS, "ETH");
24
26
  }
25
- (0, _helpers_1.assertAssetDeployed)(chainId, assetId);
26
- contractAddress = (0, contracts_1.getContractAddress)(chainId, assetId);
27
+ if (ethers_1.ethers.isAddress(assetIdOrAddress)) {
28
+ contractAddress = assetIdOrAddress;
29
+ const contract = new ethers_1.ethers.Contract(contractAddress, BALANCE_OF_ABI, provider);
30
+ const [balance, info] = await Promise.all([
31
+ contract.balanceOf(address),
32
+ (0, resolveTokenInfo_1.resolveTokenInfo)(chainId, contractAddress, provider),
33
+ ]);
34
+ return (0, amount_1.toAmount)(balance, info.decimals, info.symbol);
35
+ }
36
+ (0, _helpers_1.assertAssetDeployed)(chainId, assetIdOrAddress);
37
+ contractAddress = (0, contracts_1.getContractAddress)(chainId, assetIdOrAddress);
27
38
  const contract = new ethers_1.ethers.Contract(contractAddress, BALANCE_OF_ABI, provider);
28
39
  const balance = await contract.balanceOf(address);
29
- return (0, amount_1.toTokenAmount)(chainId, assetId, balance);
40
+ return (0, amount_1.toTokenAmount)(chainId, assetIdOrAddress, balance);
30
41
  }
31
42
  catch (error) {
32
43
  throw (0, rpcError_1.toRpcError)("wallet.getBalance", error, { chainId, address: contractAddress });