diff --git a/packages/inter-protocol/README.md b/packages/inter-protocol/README.md index 6edecdfaafb..12286634539 100644 --- a/packages/inter-protocol/README.md +++ b/packages/inter-protocol/README.md @@ -21,7 +21,7 @@ The above states are robust to system restarts and upgrades. This is accomplishe Debts are denominated in µIST. (1 million µIST = 1 IST) Each interest charging period (say daily) the actual debts in all vaults are affected. Materializing that across all vaults would be O(n) writes. Instead, to make charging interest O(1) we virtualize the debt that a vault owes to be a function of stable vault attributes and values that change in the vault manager when it charges interest. Specifically, -- a compoundedStabilityFee value on the manager that keeps track of interest accrual since its launch +- a compoundedInterest value on the manager that keeps track of interest accrual since its launch - a debtSnapshot on the vault by which one can calculate the actual debt To maintain that the keys of vaults to liquidate are stable requires that its keys are also time-independent so they're recorded as a "normalized collateralization ratio", with the actual collateral divided by the normalized debt. diff --git a/packages/inter-protocol/docs/governance.md b/packages/inter-protocol/docs/governance.md index 8295fe82bf7..9d8671ea80f 100644 --- a/packages/inter-protocol/docs/governance.md +++ b/packages/inter-protocol/docs/governance.md @@ -51,7 +51,7 @@ the Inter Protocol Whitepaper, v0.8. | Governance Key | Type | WP? | | ------------------ | :---------------- | --- | | DebtLimit | Amount | Yes | -| StabilityFee | Ratio | Yes | +| InterestRate | Ratio | Yes | | LiquidationPadding | Ratio | | | LiquidationMargin | Ratio | Yes | | LiquidationPenalty | Ratio | Yes | @@ -60,7 +60,7 @@ the Inter Protocol Whitepaper, v0.8. From Inter Protocol Whitepaper, v0.8: >Governance determines the approved collateral types: the crypto assets that can be used as collateral in vaults. In addition, it sets and manages the parameters associated with each collateral type based on the risk of the asset. These include the total debt limit, the collateralization ratio, the stability fee, and the liquidation penalty. -Note that the "stability fee" described in the Whitepaper comprises both StabilityFee and MintFee. +Note that the "stability fee" described in the Whitepaper comprises both InterestRate and MintFee. ### Parity Stability Mechanism (PSM) diff --git a/packages/inter-protocol/scripts/add-collateral-core.js b/packages/inter-protocol/scripts/add-collateral-core.js index 6e4caf3d218..bad11ee1c15 100644 --- a/packages/inter-protocol/scripts/add-collateral-core.js +++ b/packages/inter-protocol/scripts/add-collateral-core.js @@ -10,7 +10,7 @@ export const defaultProposalBuilder = async ( { publishRef, install: install0, wrapInstall }, { debtLimitValue = undefined, - stabilityFeeValue = undefined, + interestRateValue = undefined, interchainAssetOptions = /** @type {object} */ ({}), } = {}, { env = process.env } = {}, @@ -38,7 +38,7 @@ export const defaultProposalBuilder = async ( getManifestForAddAssetToVault.name, { debtLimitValue: debtLimitValue && BigInt(debtLimitValue), - stabilityFeeValue: stabilityFeeValue && BigInt(stabilityFeeValue), + interestRateValue: interestRateValue && BigInt(interestRateValue), interchainAssetOptions: { denom, issuerBoardId, diff --git a/packages/inter-protocol/src/interest-math.js b/packages/inter-protocol/src/interest-math.js index 6a03929ed28..0322e813ecd 100644 --- a/packages/inter-protocol/src/interest-math.js +++ b/packages/inter-protocol/src/interest-math.js @@ -9,39 +9,39 @@ import { } from '@agoric/zoe/src/contractSupport/ratio.js'; /** - * @param {Ratio} currentCompoundedStabilityFee as coefficient - * @param {Ratio} previousCompoundedStabilityFee as coefficient + * @param {Ratio} currentCompoundedInterest as coefficient + * @param {Ratio} previousCompoundedInterest as coefficient * @returns {Ratio} additional compounding since the previous */ const calculateRelativeCompounding = ( - currentCompoundedStabilityFee, - previousCompoundedStabilityFee, + currentCompoundedInterest, + previousCompoundedInterest, ) => { // divide compounded interest by the snapshot return multiplyRatios( - currentCompoundedStabilityFee, - invertRatio(previousCompoundedStabilityFee), + currentCompoundedInterest, + invertRatio(previousCompoundedInterest), ); }; /** * @param {Amount<'nat'>} debtSnapshot - * @param {Ratio} stabilityFeeSnapshot as coefficient - * @param {Ratio} currentCompoundedStabilityFee as coefficient + * @param {Ratio} interestSnapshot as coefficient + * @param {Ratio} currentCompoundedInterest as coefficient * @returns {Amount<'nat'>} */ export const calculateCurrentDebt = ( debtSnapshot, - stabilityFeeSnapshot, - currentCompoundedStabilityFee, + interestSnapshot, + currentCompoundedInterest, ) => { - if (ratiosSame(stabilityFeeSnapshot, currentCompoundedStabilityFee)) { + if (ratiosSame(interestSnapshot, currentCompoundedInterest)) { return debtSnapshot; } const interestSinceSnapshot = calculateRelativeCompounding( - currentCompoundedStabilityFee, - stabilityFeeSnapshot, + currentCompoundedInterest, + interestSnapshot, ); return multiplyBy(debtSnapshot, interestSinceSnapshot); diff --git a/packages/inter-protocol/src/interest.js b/packages/inter-protocol/src/interest.js index 8163302fe61..1edd1e851ad 100644 --- a/packages/inter-protocol/src/interest.js +++ b/packages/inter-protocol/src/interest.js @@ -56,8 +56,8 @@ export const makeInterestCalculator = ( * @type {Calculate} */ const calculate = (debtStatus, currentTime) => { - const { newDebt, latestStabilityFeeUpdate } = debtStatus; - let newRecent = latestStabilityFeeUpdate; + const { newDebt, latestInterestUpdate } = debtStatus; + let newRecent = latestInterestUpdate; let growingInterest = debtStatus.interest; let growingDebt = newDebt; while ( @@ -77,7 +77,7 @@ export const makeInterestCalculator = ( growingDebt += newInterest; } return { - latestStabilityFeeUpdate: newRecent, + latestInterestUpdate: newRecent, interest: growingInterest, newDebt: growingDebt, }; @@ -92,9 +92,9 @@ export const makeInterestCalculator = ( * @type {Calculate} */ const calculateReportingPeriod = (debtStatus, currentTime) => { - const { latestStabilityFeeUpdate } = debtStatus; + const { latestInterestUpdate } = debtStatus; const overshoot = TimeMath.modRelRel( - TimeMath.subtractAbsAbs(currentTime, latestStabilityFeeUpdate), + TimeMath.subtractAbsAbs(currentTime, latestInterestUpdate), recordingPeriod, ); return calculate( @@ -110,20 +110,20 @@ export const makeInterestCalculator = ( }; /** - * compoundedStabilityFee *= (new debt) / (prior total debt) + * compoundedInterest *= (new debt) / (prior total debt) * - * @param {Ratio} priorCompoundedStabilityFee + * @param {Ratio} priorCompoundedInterest * @param {NatValue} priorDebt * @param {NatValue} newDebt */ -export const calculateCompoundedStabilityFee = ( - priorCompoundedStabilityFee, +export const calculateCompoundedInterest = ( + priorCompoundedInterest, priorDebt, newDebt, ) => { - const brand = priorCompoundedStabilityFee.numerator.brand; + const brand = priorCompoundedInterest.numerator.brand; const compounded = multiplyRatios( - priorCompoundedStabilityFee, + priorCompoundedInterest, makeRatio(newDebt, brand, priorDebt, brand), ); return quantize(compounded, COMPOUNDED_INTEREST_DENOMINATOR); @@ -143,8 +143,7 @@ const validatedBrand = (mint, debt) => { }; /** - * Charge interest accrued between `latestStabilityFeeUpdate` and - * `accruedUntil`. + * Charge interest accrued between `latestInterestUpdate` and `accruedUntil`. * * @param {{ * mint: ZCFMint<'nat'>; @@ -153,19 +152,19 @@ const validatedBrand = (mint, debt) => { * seatAllocationKeyword: Keyword; * }} powers * @param {{ - * stabilityFee: Ratio; + * interestRate: Ratio; * chargingPeriod: RelativeTime; * recordingPeriod: RelativeTime; * }} params * @param {{ - * latestStabilityFeeUpdate: Timestamp; - * compoundedStabilityFee: Ratio; + * latestInterestUpdate: Timestamp; + * compoundedInterest: Ratio; * totalDebt: Amount<'nat'>; * }} prior * @param {Timestamp} accruedUntil * @returns {{ - * compoundedStabilityFee: Ratio; - * latestStabilityFeeUpdate: Timestamp; + * compoundedInterest: Ratio; + * latestInterestUpdate: Timestamp; * totalDebt: Amount<'nat'>; * }} */ @@ -173,7 +172,7 @@ export const chargeInterest = (powers, params, prior, accruedUntil) => { const brand = validatedBrand(powers.mint, prior.totalDebt); const interestCalculator = makeInterestCalculator( - params.stabilityFee, + params.interestRate, params.chargingPeriod, params.recordingPeriod, ); @@ -181,7 +180,7 @@ export const chargeInterest = (powers, params, prior, accruedUntil) => { // calculate delta of accrued debt const debtStatus = interestCalculator.calculateReportingPeriod( { - latestStabilityFeeUpdate: prior.latestStabilityFeeUpdate, + latestInterestUpdate: prior.latestInterestUpdate, newDebt: prior.totalDebt.value, interest: 0n, // XXX this is always zero, doesn't need to be an option }, @@ -192,8 +191,8 @@ export const chargeInterest = (powers, params, prior, accruedUntil) => { // done if none if (interestAccrued === 0n) { return { - compoundedStabilityFee: prior.compoundedStabilityFee, - latestStabilityFeeUpdate: debtStatus.latestStabilityFeeUpdate, + compoundedInterest: prior.compoundedInterest, + latestInterestUpdate: debtStatus.latestInterestUpdate, totalDebt: prior.totalDebt, }; } @@ -203,8 +202,8 @@ export const chargeInterest = (powers, params, prior, accruedUntil) => { // testing with small numbers there's 5 digits of precision, and with large // numbers the ratios tend towards ample precision. // TODO adopt banker's rounding https://github.com/Agoric/agoric-sdk/issues/4573 - const compoundedStabilityFee = calculateCompoundedStabilityFee( - prior.compoundedStabilityFee, + const compoundedInterest = calculateCompoundedInterest( + prior.compoundedInterest, prior.totalDebt.value, debtStatus.newDebt, ); @@ -225,8 +224,8 @@ export const chargeInterest = (powers, params, prior, accruedUntil) => { ); return { - compoundedStabilityFee, - latestStabilityFeeUpdate: debtStatus.latestStabilityFeeUpdate, + compoundedInterest, + latestInterestUpdate: debtStatus.latestInterestUpdate, totalDebt, }; }; diff --git a/packages/inter-protocol/src/proposals/addAssetToVault.js b/packages/inter-protocol/src/proposals/addAssetToVault.js index de26cec8903..a0dc7415440 100644 --- a/packages/inter-protocol/src/proposals/addAssetToVault.js +++ b/packages/inter-protocol/src/proposals/addAssetToVault.js @@ -212,7 +212,7 @@ export const registerScaledPriceAuthority = async ( * @param {object} config.options * @param {InterchainAssetOptions} config.options.interchainAssetOptions * @param {bigint | number | string} config.options.debtLimitValue - * @param {bigint} config.options.stabilityFeeValue + * @param {bigint} config.options.interestRateValue */ export const addAssetToVault = async ( { @@ -228,7 +228,7 @@ export const addAssetToVault = async ( debtLimitValue = 1_000n * 1_000_000n, // Default to a safe value. Production will likely set this through governance. // Allow setting through bootstrap to simplify testing. - stabilityFeeValue = 1n, + interestRateValue = 1n, interchainAssetOptions, }, }, @@ -250,7 +250,7 @@ export const addAssetToVault = async ( const vaultFactoryCreator = E.get(vaultFactoryKit).creatorFacet; await E(vaultFactoryCreator).addVaultType(interchainIssuer, oracleBrand, { debtLimit: AmountMath.make(stable, BigInt(debtLimitValue)), - stabilityFee: makeRatio(stabilityFeeValue, stable), + interestRate: makeRatio(interestRateValue, stable), // The rest of these we use safe defaults. // In production they will be governed by the Econ Committee. // Product deployments are also expected to have a low debtLimitValue at the outset, @@ -268,7 +268,7 @@ export const getManifestForAddAssetToVault = ( { restoreRef }, { debtLimitValue, - stabilityFeeValue, + interestRateValue, interchainAssetOptions, scaledPriceAuthorityRef, }, @@ -341,7 +341,7 @@ export const getManifestForAddAssetToVault = ( options: { debtLimitValue, interchainAssetOptions, - stabilityFeeValue, + interestRateValue, }, }; }; diff --git a/packages/inter-protocol/src/vaultFactory/params.js b/packages/inter-protocol/src/vaultFactory/params.js index 3106d23113c..ce883dffd32 100644 --- a/packages/inter-protocol/src/vaultFactory/params.js +++ b/packages/inter-protocol/src/vaultFactory/params.js @@ -21,7 +21,7 @@ export const DEBT_LIMIT_KEY = 'DebtLimit'; export const LIQUIDATION_MARGIN_KEY = 'LiquidationMargin'; export const LIQUIDATION_PADDING_KEY = 'LiquidationPadding'; export const LIQUIDATION_PENALTY_KEY = 'LiquidationPenalty'; -export const STABILITY_FEE_KEY = 'StabilityFee'; +export const INTEREST_RATE_KEY = 'InterestRate'; export const MINT_FEE_KEY = 'MintFee'; export const MIN_INITIAL_DEBT_KEY = 'MinInitialDebt'; export const SHORTFALL_INVITATION_KEY = 'ShortfallInvitation'; @@ -93,7 +93,7 @@ export const makeVaultParamManager = ( publisherKit, { debtLimit, - stabilityFee, + interestRate, liquidationMargin, liquidationPadding = zeroRatio(liquidationMargin), liquidationPenalty, @@ -102,7 +102,7 @@ export const makeVaultParamManager = ( ) => makeParamManagerSync(publisherKit, { [DEBT_LIMIT_KEY]: [ParamTypes.AMOUNT, debtLimit], - [STABILITY_FEE_KEY]: [ParamTypes.RATIO, stabilityFee], + [INTEREST_RATE_KEY]: [ParamTypes.RATIO, interestRate], [LIQUIDATION_PADDING_KEY]: [ParamTypes.RATIO, liquidationPadding], [LIQUIDATION_MARGIN_KEY]: [ParamTypes.RATIO, liquidationMargin], [LIQUIDATION_PENALTY_KEY]: [ParamTypes.RATIO, liquidationPenalty], @@ -114,7 +114,7 @@ export const vaultParamPattern = M.splitRecord( { liquidationMargin: ratioPattern, liquidationPenalty: ratioPattern, - stabilityFee: ratioPattern, + interestRate: ratioPattern, mintFee: ratioPattern, debtLimit: amountPattern, }, diff --git a/packages/inter-protocol/src/vaultFactory/storeUtils.js b/packages/inter-protocol/src/vaultFactory/storeUtils.js index 8471ba87d88..d1daf1abcc1 100644 --- a/packages/inter-protocol/src/vaultFactory/storeUtils.js +++ b/packages/inter-protocol/src/vaultFactory/storeUtils.js @@ -127,15 +127,15 @@ harden(fromVaultKey); * For use by `normalizedCollRatioKey` and tests. * * @param {PriceQuote} quote - * @param {Ratio} compoundedStabilityFee + * @param {Ratio} compoundedInterest * @param {Ratio} margin * @returns {number} */ -export const normalizedCollRatio = (quote, compoundedStabilityFee, margin) => { +export const normalizedCollRatio = (quote, compoundedInterest, margin) => { const amountIn = getAmountIn(quote).value; const amountOut = getAmountOut(quote).value; - const interestNumerator = compoundedStabilityFee.numerator.value; - const interestBase = compoundedStabilityFee.denominator.value; + const interestNumerator = compoundedInterest.numerator.value; + const interestBase = compoundedInterest.denominator.value; const numerator = multiply( margin.numerator.value, multiply(amountIn, interestNumerator), @@ -155,17 +155,13 @@ harden(normalizedCollRatio); * out the numerator and the denominator, and divide only once. * * @param {PriceQuote} quote - * @param {Ratio} compoundedStabilityFee + * @param {Ratio} compoundedInterest * @param {Ratio} margin * @returns {string} lexically sortable string in which highest * debt-to-collateral is earliest */ -export const normalizedCollRatioKey = ( - quote, - compoundedStabilityFee, - margin, -) => { - const collRatio = normalizedCollRatio(quote, compoundedStabilityFee, margin); +export const normalizedCollRatioKey = (quote, compoundedInterest, margin) => { + const collRatio = normalizedCollRatio(quote, compoundedInterest, margin); return `${encodeNumber(collRatio)}:`; }; harden(normalizedCollRatioKey); diff --git a/packages/inter-protocol/src/vaultFactory/types.js b/packages/inter-protocol/src/vaultFactory/types.js index b5ebf12a6ee..ecde8bf4f24 100644 --- a/packages/inter-protocol/src/vaultFactory/types.js +++ b/packages/inter-protocol/src/vaultFactory/types.js @@ -36,7 +36,7 @@ * liquidated to satisfy the debt. * @property {Ratio} liquidationPenalty - penalty charged upon liquidation as * proportion of debt - * @property {Ratio} stabilityFee - annual interest rate charged on debt + * @property {Ratio} interestRate - annual interest rate charged on debt * positions * @property {Ratio} mintFee - The fee (in BasisPoints) charged when creating or * increasing a debt position. @@ -87,7 +87,7 @@ * @property {() => Ratio} getLiquidationMargin * @property {() => Ratio} getMintFee * @property {() => Promise} getCollateralQuote - * @property {() => Ratio} getStabilityFee - The annual interest rate on a debt + * @property {() => Ratio} getInterestRate - The annual interest rate on a debt * position * @property {() => RelativeTime} getChargingPeriod - The period (in seconds) at * which interest is charged to the debt position. @@ -119,8 +119,8 @@ /** * @typedef {object} DebtStatus - * @property {Timestamp} latestStabilityFeeUpdate - * @property {NatValue} interest interest accrued since latestStabilityFeeUpdate + * @property {Timestamp} latestInterestUpdate + * @property {NatValue} interest interest accrued since latestInterestUpdate * @property {NatValue} newDebt total including principal and interest */ diff --git a/packages/inter-protocol/src/vaultFactory/vault.js b/packages/inter-protocol/src/vaultFactory/vault.js index 39d2fcc6d6b..9877f4c9f1f 100644 --- a/packages/inter-protocol/src/vaultFactory/vault.js +++ b/packages/inter-protocol/src/vaultFactory/vault.js @@ -77,8 +77,8 @@ const validTransitions = { * * @typedef {object} VaultNotification * @property {Amount<'nat'>} locked Amount of Collateral locked - * @property {{ debt: Amount<'nat'>; stabilityFee: Ratio }} debtSnapshot 'debt' - * at the point the compounded stabilityFee was 'stabilityFee' + * @property {{ debt: Amount<'nat'>; interest: Ratio }} debtSnapshot 'debt' at + * the point the compounded interest was 'interest' * @property {HolderPhase} vaultState */ @@ -92,7 +92,7 @@ const validTransitions = { * @property {() => Brand<'nat'>} getDebtBrand * @property {MintAndTransfer} mintAndTransfer * @property {(amount: Amount, seat: ZCFSeat) => void} burn - * @property {() => Ratio} getCompoundedStabilityFee + * @property {() => Ratio} getCompoundedInterest * @property {( * oldDebt: import('./storeUtils.js').NormalizedDebt, * oldCollateral: Amount<'nat'>, @@ -117,7 +117,7 @@ const validTransitions = { * changed. * * @typedef {{ - * stabilityFeeSnapshot: Ratio; + * interestSnapshot: Ratio; * phase: VaultPhase; * debtSnapshot: Amount<'nat'>; * outerUpdater: @@ -147,7 +147,7 @@ const VaultStateShape = harden({ phase: M.any(), storageNode: M.any(), vaultSeat: M.any(), - stabilityFeeSnapshot: M.any(), + interestSnapshot: M.any(), debtSnapshot: M.any(), }); @@ -189,7 +189,7 @@ export const prepareVault = (baggage, makeRecorderKit, zcf) => { vaultSeat: zcf.makeEmptySeatKit().zcfSeat, // Two values from the same moment - stabilityFeeSnapshot: manager.getCompoundedStabilityFee(), + interestSnapshot: manager.getCompoundedInterest(), debtSnapshot: AmountMath.makeEmpty(manager.getDebtBrand()), }); }, @@ -273,8 +273,7 @@ export const prepareVault = (baggage, makeRecorderKit, zcf) => { // update local state state.debtSnapshot = newDebt; - state.stabilityFeeSnapshot = - state.manager.getCompoundedStabilityFee(); + state.interestSnapshot = state.manager.getCompoundedInterest(); }, /** @@ -339,11 +338,10 @@ export const prepareVault = (baggage, makeRecorderKit, zcf) => { getStateSnapshot(newPhase) { const { state, facets } = this; - const { debtSnapshot: debt, stabilityFeeSnapshot: stabilityFee } = - state; + const { debtSnapshot: debt, interestSnapshot: interest } = state; /** @type {VaultNotification} */ return harden({ - debtSnapshot: { debt, stabilityFee }, + debtSnapshot: { debt, interest }, locked: facets.self.getCollateralAmount(), // newPhase param is so that makeTransferInvitation can finish without setting the vault's phase // TODO refactor https://github.com/Agoric/agoric-sdk/issues/4415 @@ -788,7 +786,7 @@ export const prepareVault = (baggage, makeRecorderKit, zcf) => { helper.updateDebtSnapshot(self.getCurrentDebt()); const { debtSnapshot: debt, - stabilityFeeSnapshot: stabilityFee, + interestSnapshot: interest, phase, } = state; if (outerUpdater) { @@ -798,7 +796,7 @@ export const prepareVault = (baggage, makeRecorderKit, zcf) => { state.outerUpdater = null; } const transferState = { - debtSnapshot: { debt, stabilityFee }, + debtSnapshot: { debt, interest }, locked: self.getCollateralAmount(), vaultState: phase, }; @@ -839,8 +837,8 @@ export const prepareVault = (baggage, makeRecorderKit, zcf) => { const { state } = this; return calculateCurrentDebt( state.debtSnapshot, - state.stabilityFeeSnapshot, - state.manager.getCompoundedStabilityFee(), + state.interestSnapshot, + state.manager.getCompoundedInterest(), ); }, @@ -858,10 +856,7 @@ export const prepareVault = (baggage, makeRecorderKit, zcf) => { getNormalizedDebt() { const { state } = this; // @ts-expect-error cast - return reverseInterest( - state.debtSnapshot, - state.stabilityFeeSnapshot, - ); + return reverseInterest(state.debtSnapshot, state.interestSnapshot); }, }, }, diff --git a/packages/inter-protocol/src/vaultFactory/vaultManager.js b/packages/inter-protocol/src/vaultFactory/vaultManager.js index 5a20cee3f50..198588c0da8 100644 --- a/packages/inter-protocol/src/vaultFactory/vaultManager.js +++ b/packages/inter-protocol/src/vaultFactory/vaultManager.js @@ -106,16 +106,16 @@ const trace = makeTracer('VM'); /** * @typedef {{ - * compoundedStabilityFee: Ratio; - * stabilityFee: Ratio; - * latestStabilityFeeUpdate: Timestamp; + * compoundedInterest: Ratio; + * interestRate: Ratio; + * latestInterestUpdate: Timestamp; * }} AssetState * * @typedef {{ * getChargingPeriod: () => RelativeTime; * getRecordingPeriod: () => RelativeTime; * getDebtLimit: () => Amount<'nat'>; - * getStabilityFee: () => Ratio; + * getInterestRate: () => Ratio; * getLiquidationPadding: () => Ratio; * getLiquidationMargin: () => Ratio; * getLiquidationPenalty: () => Ratio; @@ -149,8 +149,8 @@ const trace = makeTracer('VM'); /** * @typedef {{ - * compoundedStabilityFee: Ratio; - * latestStabilityFeeUpdate: Timestamp; + * compoundedInterest: Ratio; + * latestInterestUpdate: Timestamp; * numLiquidationsCompleted: number; * numLiquidationsAborted: number; * totalCollateral: Amount<'nat'>; @@ -242,8 +242,8 @@ export const prepareVaultManagerKit = ( return harden({ ...params, ...immutable, - compoundedStabilityFee: makeRatio(100n, debtBrand), // starts at 1.0, no interest - latestStabilityFeeUpdate: startTimeStamp, + compoundedInterest: makeRatio(100n, debtBrand), // starts at 1.0, no interest + latestInterestUpdate: startTimeStamp, numLiquidationsCompleted: 0, numLiquidationsAborted: 0, totalCollateral: zeroCollateral, @@ -267,7 +267,7 @@ export const prepareVaultManagerKit = ( makeVaultInvitation: M.call().returns(M.promise()), getPublicTopics: M.call().returns(TopicsRecordShape), getQuotes: M.call().returns(NotifierShape), - getCompoundedStabilityFee: M.call().returns(RatioShape), + getCompoundedInterest: M.call().returns(RatioShape), }), helper: M.interface( 'helper', @@ -288,7 +288,7 @@ export const prepareVaultManagerKit = ( getAssetSubscriber: M.call().returns(SubscriberShape), getCollateralBrand: M.call().returns(BrandShape), getDebtBrand: M.call().returns(BrandShape), - getCompoundedStabilityFee: M.call().returns(RatioShape), + getCompoundedInterest: M.call().returns(RatioShape), scopeDescription: M.call(M.string()).returns(M.string()), handleBalanceChange: M.call( AmountShape, @@ -331,8 +331,8 @@ export const prepareVaultManagerKit = ( const ephemera = collateralEphemera(this.state.collateralBrand); return ephemera.storedQuotesNotifier; }, - getCompoundedStabilityFee() { - return this.state.compoundedStabilityFee; + getCompoundedInterest() { + return this.state.compoundedInterest; }, getPublicTopics() { const { assetTopicKit, metricsTopicKit } = this.state; @@ -427,9 +427,9 @@ export const prepareVaultManagerKit = ( updateTime, }); - const stabilityFee = factoryPowers + const interestRate = factoryPowers .getGovernedParams(collateralBrand) - .getStabilityFee(); + .getInterestRate(); // Update state with the results of charging interest @@ -441,7 +441,7 @@ export const prepareVaultManagerKit = ( seatAllocationKeyword: 'Minted', }, { - stabilityFee, + interestRate, chargingPeriod: factoryPowers .getGovernedParams(collateralBrand) .getChargingPeriod(), @@ -450,15 +450,15 @@ export const prepareVaultManagerKit = ( .getRecordingPeriod(), }, { - latestStabilityFeeUpdate: state.latestStabilityFeeUpdate, - compoundedStabilityFee: state.compoundedStabilityFee, + latestInterestUpdate: state.latestInterestUpdate, + compoundedInterest: state.compoundedInterest, totalDebt: state.totalDebt, }, updateTime, ); - state.compoundedStabilityFee = changes.compoundedStabilityFee; - state.latestStabilityFeeUpdate = changes.latestStabilityFeeUpdate; + state.compoundedInterest = changes.compoundedInterest; + state.latestInterestUpdate = changes.latestInterestUpdate; state.totalDebt = changes.totalDebt; return facets.helper.assetNotify(); @@ -466,14 +466,14 @@ export const prepareVaultManagerKit = ( assetNotify() { const { state } = this; const { collateralBrand, assetTopicKit } = state; - const stabilityFee = factoryPowers + const interestRate = factoryPowers .getGovernedParams(collateralBrand) - .getStabilityFee(); + .getInterestRate(); /** @type {AssetState} */ const payload = harden({ - compoundedStabilityFee: state.compoundedStabilityFee, - stabilityFee, - latestStabilityFeeUpdate: state.latestStabilityFeeUpdate, + compoundedInterest: state.compoundedInterest, + interestRate, + latestInterestUpdate: state.latestInterestUpdate, }); return assetTopicKit.recorder.write(payload); }, @@ -853,8 +853,8 @@ export const prepareVaultManagerKit = ( return `${descriptionScope}: ${base}`; }, /** coefficient on existing debt to calculate new debt */ - getCompoundedStabilityFee() { - return this.state.compoundedStabilityFee; + getCompoundedInterest() { + return this.state.compoundedInterest; }, /** * Called by a vault when its balances change. @@ -1060,7 +1060,7 @@ export const prepareVaultManagerKit = ( const { self, helper } = facets; const { collateralBrand, - compoundedStabilityFee, + compoundedInterest, debtBrand, liquidatingVaults, lockedQuote, @@ -1089,7 +1089,7 @@ export const prepareVaultManagerKit = ( zcf, { quote: lockedQuote, - interest: compoundedStabilityFee, + interest: compoundedInterest, margin: liqMargin, }, prioritizedVaults, @@ -1174,11 +1174,11 @@ export const prepareVaultManagerKit = ( helper.start(); void state.assetTopicKit.recorder.write( harden({ - compoundedStabilityFee: state.compoundedStabilityFee, - stabilityFee: factoryPowers + compoundedInterest: state.compoundedInterest, + interestRate: factoryPowers .getGovernedParams(state.collateralBrand) - .getStabilityFee(), - latestStabilityFeeUpdate: state.latestStabilityFeeUpdate, + .getInterestRate(), + latestInterestUpdate: state.latestInterestUpdate, }), ); diff --git a/packages/inter-protocol/test/test-interest-labeled.js b/packages/inter-protocol/test/test-interest-labeled.js index 54c3b5e80d8..ac63dbac354 100644 --- a/packages/inter-protocol/test/test-interest-labeled.js +++ b/packages/inter-protocol/test/test-interest-labeled.js @@ -50,12 +50,12 @@ test('too soon', async t => { ); const debtStatus = { newDebt: 1000n, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; // no interest because the charging period hasn't elapsed t.deepEqual(calculator.calculate(debtStatus, 12n), { - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, newDebt: 1000n, }); @@ -67,12 +67,12 @@ test('basic charge 1 period', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 0n, + latestInterestUpdate: 0n, interest: 0n, }; // 7n is daily interest of 2.5% APR on 100k. Compounding is in the noise. t.deepEqual(calculator.calculate(debtStatus, dayN(1n)), { - latestStabilityFeeUpdate: dayN(1n), + latestInterestUpdate: dayN(1n), interest: 7n, newDebt: 100007n, }); @@ -84,13 +84,13 @@ test('basic 2 charge periods', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: dayN(1n), + latestInterestUpdate: dayN(1n), interest: 0n, }; // 14n is 2x daily (from day 1 to day 3) interest of 2.5% APR on 100k. // Compounding is in the noise. t.deepEqual(calculator.calculate(debtStatus, dayN(3n)), { - latestStabilityFeeUpdate: dayN(3n), + latestInterestUpdate: dayN(3n), interest: 14n, newDebt: 100014n, }); @@ -102,14 +102,14 @@ test('partial periods', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; // just less than three days gets two days of interest (7n/day) t.deepEqual( calculator.calculate(debtStatus, TimeMath.subtractAbsRel(dayN(3n), 1n)), { - latestStabilityFeeUpdate: TimeMath.addAbsRel(dayN(2n), 10n), + latestInterestUpdate: TimeMath.addAbsRel(dayN(2n), 10n), interest: 14n, newDebt: 100014n, }, @@ -122,7 +122,7 @@ test('reportingPeriod: partial', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; @@ -130,7 +130,7 @@ test('reportingPeriod: partial', async t => { t.deepEqual( calculator.calculateReportingPeriod(debtStatus, fromZero(ONE_MONTH)), { - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, newDebt: HUNDRED_THOUSAND, }, @@ -142,7 +142,7 @@ test('reportingPeriod: partial', async t => { fromZero(TimeMath.addRelRel(ONE_DAY, ONE_MONTH)), ), { - latestStabilityFeeUpdate: TimeMath.addAbsRel(10n, ONE_MONTH), + latestInterestUpdate: TimeMath.addAbsRel(10n, ONE_MONTH), interest: 210n, newDebt: 100210n, }, @@ -155,7 +155,7 @@ test('reportingPeriod: longer', async t => { const calculator = makeInterestCalculator(annualRate, ONE_MONTH, ONE_DAY); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; // charge monthly, record daily. 2.5% APR compounded monthly rate is 204 BP. @@ -166,7 +166,7 @@ test('reportingPeriod: longer', async t => { fromZero(TimeMath.addRelRel(ONE_DAY, ONE_MONTH)), ), { - latestStabilityFeeUpdate: TimeMath.addAbsRel(10n, ONE_MONTH), + latestInterestUpdate: TimeMath.addAbsRel(10n, ONE_MONTH), interest: 204n, newDebt: 100204n, }, diff --git a/packages/inter-protocol/test/test-interest-math.js b/packages/inter-protocol/test/test-interest-math.js index f6168752590..b4656de60c4 100644 --- a/packages/inter-protocol/test/test-interest-math.js +++ b/packages/inter-protocol/test/test-interest-math.js @@ -14,13 +14,13 @@ const brand = makeIssuerKit('foo').brand; function checkDebt(t, [debt, interest, compounded], result) { /** @type {Amount<'nat'>} */ const debtSnapshot = AmountMath.make(brand, debt); - const stabilityFeeSnapshot = makeRatio(100n + interest, brand); - const currentCompoundedStabilityFee = makeRatio(100n + compounded, brand); + const interestSnapshot = makeRatio(100n + interest, brand); + const currentCompoundedInterest = makeRatio(100n + compounded, brand); t.is( calculateCurrentDebt( debtSnapshot, - stabilityFeeSnapshot, - currentCompoundedStabilityFee, + interestSnapshot, + currentCompoundedInterest, ).value, result, ); diff --git a/packages/inter-protocol/test/test-interest.js b/packages/inter-protocol/test/test-interest.js index cb05f91ea5b..91370248038 100644 --- a/packages/inter-protocol/test/test-interest.js +++ b/packages/inter-protocol/test/test-interest.js @@ -9,7 +9,7 @@ import { import { Far } from '@endo/marshal'; import { makeIssuerRecord } from '@agoric/zoe/src/issuerRecord.js'; import { - calculateCompoundedStabilityFee, + calculateCompoundedInterest, chargeInterest, makeInterestCalculator, SECONDS_PER_YEAR, @@ -34,12 +34,12 @@ test('too soon', async t => { ); const debtStatus = { newDebt: 1000n, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; // no interest because the charging period hasn't elapsed t.deepEqual(calculator.calculate(debtStatus, 12n), { - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, newDebt: 1000n, }); @@ -51,12 +51,12 @@ test('basic charge 1 period', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 0n, + latestInterestUpdate: 0n, interest: 0n, }; // 7n is daily interest of 2.5% APR on 100k. Compounding is in the noise. t.deepEqual(calculator.calculate(debtStatus, ONE_DAY), { - latestStabilityFeeUpdate: ONE_DAY, + latestInterestUpdate: ONE_DAY, interest: 7n, newDebt: 100007n, }); @@ -68,13 +68,13 @@ test('basic 2 charge periods', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: ONE_DAY, + latestInterestUpdate: ONE_DAY, interest: 0n, }; // 14n is 2x daily (from day 1 to day 3) interest of 2.5% APR on 100k. // Compounding is in the noise. t.deepEqual(calculator.calculate(debtStatus, ONE_DAY * 3n), { - latestStabilityFeeUpdate: ONE_DAY * 3n, + latestInterestUpdate: ONE_DAY * 3n, interest: 14n, newDebt: 100014n, }); @@ -86,12 +86,12 @@ test('partial periods', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; // just less than three days gets two days of interest (7n/day) t.deepEqual(calculator.calculate(debtStatus, ONE_DAY * 3n - 1n), { - latestStabilityFeeUpdate: 10n + ONE_DAY * 2n, + latestInterestUpdate: 10n + ONE_DAY * 2n, interest: 14n, newDebt: 100014n, }); @@ -103,13 +103,13 @@ test('reportingPeriod: partial', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; // charge at reporting period intervals t.deepEqual(calculator.calculateReportingPeriod(debtStatus, ONE_MONTH), { - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, newDebt: HUNDRED_THOUSAND, }); @@ -117,7 +117,7 @@ test('reportingPeriod: partial', async t => { t.deepEqual( calculator.calculateReportingPeriod(debtStatus, ONE_DAY + ONE_MONTH), { - latestStabilityFeeUpdate: 10n + ONE_MONTH, + latestInterestUpdate: 10n + ONE_MONTH, interest: 210n, newDebt: 100210n, }, @@ -130,7 +130,7 @@ test('reportingPeriod: longer', async t => { const calculator = makeInterestCalculator(annualRate, ONE_MONTH, ONE_DAY); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; // charge monthly, record daily. 2.5% APR compounded monthly rate is 204 BP. @@ -138,7 +138,7 @@ test('reportingPeriod: longer', async t => { t.deepEqual( calculator.calculateReportingPeriod(debtStatus, ONE_MONTH + ONE_DAY), { - latestStabilityFeeUpdate: ONE_MONTH + 10n, + latestInterestUpdate: ONE_MONTH + 10n, interest: 204n, newDebt: 100204n, }, @@ -151,18 +151,18 @@ test('start charging later', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 16n, + latestInterestUpdate: 16n, interest: 0n, }; // from a baseline of 16n, we don't charge interest until the timer gets to // ONE_DAY plus 16n. t.deepEqual(calculator.calculate(debtStatus, ONE_DAY), { - latestStabilityFeeUpdate: 16n, + latestInterestUpdate: 16n, interest: 0n, newDebt: HUNDRED_THOUSAND, }); t.deepEqual(calculator.calculate(debtStatus, ONE_DAY + 16n), { - latestStabilityFeeUpdate: ONE_DAY + 16n, + latestInterestUpdate: ONE_DAY + 16n, interest: 7n, newDebt: 100007n, }); @@ -174,7 +174,7 @@ test('simple compounding', async t => { const calculator = makeInterestCalculator(annualRate, ONE_DAY, ONE_MONTH); const debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; // 30 days of 7n interest per day. Compounding is in the noise. @@ -182,7 +182,7 @@ test('simple compounding', async t => { t.deepEqual( calculator.calculateReportingPeriod(debtStatus, ONE_MONTH + ONE_DAY), { - latestStabilityFeeUpdate: ONE_MONTH + 10n, + latestInterestUpdate: ONE_MONTH + 10n, interest: 210n, newDebt: 100210n, }, @@ -195,11 +195,11 @@ test('reportingPeriod shorter than charging', async t => { const calculator = makeInterestCalculator(annualRate, ONE_MONTH, ONE_DAY); let debtStatus = { newDebt: HUNDRED_THOUSAND, - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, }; const afterOneMonth = { - latestStabilityFeeUpdate: 10n, + latestInterestUpdate: 10n, interest: 0n, newDebt: HUNDRED_THOUSAND, }; @@ -210,7 +210,7 @@ test('reportingPeriod shorter than charging', async t => { t.deepEqual(calculator.calculate(debtStatus, 17n * ONE_DAY), afterOneMonth); t.deepEqual(calculator.calculate(debtStatus, 29n * ONE_DAY), afterOneMonth); t.deepEqual(calculator.calculate(debtStatus, ONE_MONTH + 10n), { - latestStabilityFeeUpdate: ONE_MONTH + 10n, + latestInterestUpdate: ONE_MONTH + 10n, interest: 204n, newDebt: 100204n, }); @@ -218,10 +218,10 @@ test('reportingPeriod shorter than charging', async t => { debtStatus = { newDebt: 100204n, interest: 204n, - latestStabilityFeeUpdate: ONE_MONTH, + latestInterestUpdate: ONE_MONTH, }; const afterTwoMonths = { - latestStabilityFeeUpdate: ONE_MONTH, + latestInterestUpdate: ONE_MONTH, interest: 204n, newDebt: 100204n, }; @@ -231,7 +231,7 @@ test('reportingPeriod shorter than charging', async t => { t.deepEqual(calculator.calculate(debtStatus, 50n * ONE_DAY), afterTwoMonths); t.deepEqual(calculator.calculate(debtStatus, 59n * ONE_DAY), afterTwoMonths); t.deepEqual(calculator.calculate(debtStatus, 60n * ONE_DAY), { - latestStabilityFeeUpdate: 2n * ONE_MONTH, + latestInterestUpdate: 2n * ONE_MONTH, interest: 408n, newDebt: 100408n, }); @@ -242,12 +242,12 @@ test('reportingPeriod shorter than charging; start day boundary', async t => { const annualRate = makeRatio(250n, brand, BASIS_POINTS); const calculator = makeInterestCalculator(annualRate, ONE_MONTH, ONE_DAY); const startOneDay = { - latestStabilityFeeUpdate: ONE_DAY, + latestInterestUpdate: ONE_DAY, newDebt: HUNDRED_THOUSAND, interest: 0n, }; const afterOneDay = { - latestStabilityFeeUpdate: ONE_DAY, + latestInterestUpdate: ONE_DAY, interest: 0n, newDebt: HUNDRED_THOUSAND, }; @@ -259,7 +259,7 @@ test('reportingPeriod shorter than charging; start day boundary', async t => { t.deepEqual(calculator.calculate(startOneDay, 29n * ONE_DAY), afterOneDay); const afterAMonth = { - latestStabilityFeeUpdate: ONE_MONTH + ONE_DAY, + latestInterestUpdate: ONE_MONTH + ONE_DAY, interest: 204n, newDebt: 100204n, }; @@ -275,12 +275,12 @@ test('reportingPeriod shorter than charging; start not even days', async t => { const annualRate = makeRatio(250n, brand, BASIS_POINTS); const calculator = makeInterestCalculator(annualRate, ONE_MONTH, ONE_DAY); const startPartialDay = { - latestStabilityFeeUpdate: 20n, + latestInterestUpdate: 20n, newDebt: 101000n, interest: 0n, }; const afterOneMonth = { - latestStabilityFeeUpdate: 20n, + latestInterestUpdate: 20n, interest: 0n, newDebt: 101000n, }; @@ -291,7 +291,7 @@ test('reportingPeriod shorter than charging; start not even days', async t => { ); // interest not charged until ONE_MONTH + 20n t.deepEqual(calculator.calculate(startPartialDay, ONE_MONTH + 20n), { - latestStabilityFeeUpdate: 20n + ONE_MONTH, + latestInterestUpdate: 20n + ONE_MONTH, interest: 206n, newDebt: 101206n, }); @@ -308,21 +308,21 @@ test('basic charge large numbers, compounding', async t => { const debtStatus = { newDebt: TEN_MILLION, interest: 0n, - latestStabilityFeeUpdate: START_TIME, + latestInterestUpdate: START_TIME, }; t.deepEqual(calculator.calculate(debtStatus, START_TIME), { - latestStabilityFeeUpdate: START_TIME, + latestInterestUpdate: START_TIME, interest: 0n, newDebt: TEN_MILLION, }); t.deepEqual(calculator.calculate(debtStatus, START_TIME + 1n), { - latestStabilityFeeUpdate: START_TIME, + latestInterestUpdate: START_TIME, interest: 0n, newDebt: TEN_MILLION, }); // 677n is one day's interest on TEN_MILLION at 2.5% APR, rounded up. t.deepEqual(calculator.calculate(debtStatus, START_TIME + ONE_DAY), { - latestStabilityFeeUpdate: START_TIME + ONE_DAY, + latestInterestUpdate: START_TIME + ONE_DAY, interest: 677n, newDebt: 10000677n, }); @@ -330,14 +330,14 @@ test('basic charge large numbers, compounding', async t => { t.deepEqual( calculator.calculate(debtStatus, START_TIME + ONE_DAY + ONE_DAY), { - latestStabilityFeeUpdate: START_TIME + ONE_DAY + ONE_DAY, + latestInterestUpdate: START_TIME + ONE_DAY + ONE_DAY, interest: 1354n, newDebt: 10001354n, }, ); // Notice that interest compounds 30 days * 677 = 20310 < 20329 t.deepEqual(calculator.calculate(debtStatus, START_TIME + ONE_MONTH), { - latestStabilityFeeUpdate: START_TIME + ONE_MONTH, + latestInterestUpdate: START_TIME + ONE_MONTH, interest: 20329n, newDebt: 10020329n, }); @@ -355,18 +355,18 @@ test('basic charge reasonable numbers monthly', async t => { const debtStatus = { newDebt: TEN_MILLION, interest: 0n, - latestStabilityFeeUpdate: START_TIME, + latestInterestUpdate: START_TIME, }; // don't charge, since a month hasn't elapsed t.deepEqual(calculator.calculateReportingPeriod(debtStatus, START_TIME), { - latestStabilityFeeUpdate: START_TIME, + latestInterestUpdate: START_TIME, interest: 0n, newDebt: TEN_MILLION, }); t.deepEqual( calculator.calculateReportingPeriod(debtStatus, START_TIME + 1n), { - latestStabilityFeeUpdate: START_TIME, + latestInterestUpdate: START_TIME, interest: 0n, newDebt: TEN_MILLION, }, @@ -374,7 +374,7 @@ test('basic charge reasonable numbers monthly', async t => { t.deepEqual( calculator.calculateReportingPeriod(debtStatus, START_TIME + ONE_DAY), { - latestStabilityFeeUpdate: START_TIME, + latestInterestUpdate: START_TIME, interest: 0n, newDebt: TEN_MILLION, }, @@ -385,7 +385,7 @@ test('basic charge reasonable numbers monthly', async t => { START_TIME + ONE_DAY + ONE_DAY, ), { - latestStabilityFeeUpdate: START_TIME, + latestInterestUpdate: START_TIME, interest: 0n, newDebt: TEN_MILLION, }, @@ -395,7 +395,7 @@ test('basic charge reasonable numbers monthly', async t => { t.deepEqual( calculator.calculateReportingPeriod(debtStatus, START_TIME + ONE_MONTH), { - latestStabilityFeeUpdate: START_TIME + ONE_MONTH, + latestInterestUpdate: START_TIME + ONE_MONTH, interest: 20329n, newDebt: 10020329n, }, @@ -406,7 +406,7 @@ test('basic charge reasonable numbers monthly', async t => { t.deepEqual( calculator.calculateReportingPeriod(debtStatus, START_TIME + HALF_YEAR), { - latestStabilityFeeUpdate: START_TIME + HALF_YEAR, + latestInterestUpdate: START_TIME + HALF_YEAR, interest: 122601n, newDebt: 10122601n, }, @@ -415,16 +415,16 @@ test('basic charge reasonable numbers monthly', async t => { t.deepEqual( calculator.calculateReportingPeriod(debtStatus, START_TIME + ONE_YEAR), { - latestStabilityFeeUpdate: START_TIME + ONE_YEAR, + latestInterestUpdate: START_TIME + ONE_YEAR, interest: 246705n, newDebt: 10246705n, }, ); }); -test('calculateCompoundedStabilityFee on zero debt', t => { +test('calculateCompoundedInterest on zero debt', t => { t.throws(() => - calculateCompoundedStabilityFee( + calculateCompoundedInterest( makeRatio(0n, mockBrand, 1n, mockBrand), 0n, 100n, @@ -435,7 +435,7 @@ test('calculateCompoundedStabilityFee on zero debt', t => { // -illions const M = 1_000_000n; -test('calculateCompoundedStabilityFee', t => { +test('calculateCompoundedInterest', t => { /** @type {[bigint, bigint, bigint, number, bigint, number][]} */ const cases = [ [250n, BASIS_POINTS, M, 1, 1025000n, 10], // 2.5% APR over 1 year yields 2.5% @@ -455,15 +455,15 @@ test('calculateCompoundedStabilityFee', t => { const apr = makeRatio(rateNum, mockBrand, rateDen, mockBrand); const aprf = Number(rateNum) / Number(rateDen); - let compoundedStabilityFee = makeRatio(1n, mockBrand, 1n, mockBrand); + let compoundedInterest = makeRatio(1n, mockBrand, 1n, mockBrand); let compoundedFloat = 1.0; let totalDebt = startingDebt; for (let i = 0; i < charges; i += 1) { compoundedFloat *= 1 + aprf; const delta = ceilMultiplyBy(AmountMath.make(mockBrand, totalDebt), apr); - compoundedStabilityFee = calculateCompoundedStabilityFee( - compoundedStabilityFee, + compoundedInterest = calculateCompoundedInterest( + compoundedInterest, totalDebt, totalDebt + delta.value, ); @@ -472,8 +472,8 @@ test('calculateCompoundedStabilityFee', t => { t.is( compoundedFloat.toPrecision(floatMatch), ( - Number(compoundedStabilityFee.numerator.value) / - Number(compoundedStabilityFee.denominator.value) + Number(compoundedInterest.numerator.value) / + Number(compoundedInterest.denominator.value) ).toPrecision(floatMatch), `For ${startingDebt} at (${rateNum}/${rateDen})^${charges}, expected compounded ratio to match ${compoundedFloat}`, ); @@ -492,7 +492,7 @@ test('calculateCompoundedStabilityFee', t => { test('chargeInterest when no time elapsed', async t => { const { brand, issuer } = makeIssuerKit('ducats'); - const stabilityFee = makeRatio(250n, brand, BASIS_POINTS); + const interestRate = makeRatio(250n, brand, BASIS_POINTS); const now = BigInt(Date.now().toFixed()); /** @type {any} */ @@ -503,18 +503,18 @@ test('chargeInterest when no time elapsed', async t => { }, }; const params = { - stabilityFee, + interestRate, chargingPeriod: ONE_DAY, recordingPeriod: ONE_DAY, }; const prior = { - latestStabilityFeeUpdate: now, - compoundedStabilityFee: makeRatio(100n, brand), + latestInterestUpdate: now, + compoundedInterest: makeRatio(100n, brand), /** @type {Amount<'nat'>} */ totalDebt: AmountMath.make(brand, 10_000n), }; const results = chargeInterest(powers, params, prior, now); - t.deepEqual(results.compoundedStabilityFee, prior.compoundedStabilityFee); - t.is(results.latestStabilityFeeUpdate, now); + t.deepEqual(results.compoundedInterest, prior.compoundedInterest); + t.is(results.latestInterestUpdate, now); t.deepEqual(results.totalDebt, prior.totalDebt); }); diff --git a/packages/inter-protocol/test/vaultFactory/driver.js b/packages/inter-protocol/test/vaultFactory/driver.js index f8e1d3e0e71..d35a87e2bf8 100644 --- a/packages/inter-protocol/test/vaultFactory/driver.js +++ b/packages/inter-protocol/test/vaultFactory/driver.js @@ -66,7 +66,7 @@ const defaultParamValues = debt => // penalty upon liquidation as proportion of debt liquidationPenalty: debt.makeRatio(10n), // periodic interest rate (per charging period) - stabilityFee: debt.makeRatio(100n, BASIS_POINTS), + interestRate: debt.makeRatio(100n, BASIS_POINTS), // charge to create or increase loan balance mintFee: debt.makeRatio(500n, BASIS_POINTS), // NB: liquidationPadding defaults to zero in contract diff --git a/packages/inter-protocol/test/vaultFactory/interestSupport.js b/packages/inter-protocol/test/vaultFactory/interestSupport.js index 804a5307e92..56640d403a7 100644 --- a/packages/inter-protocol/test/vaultFactory/interestSupport.js +++ b/packages/inter-protocol/test/vaultFactory/interestSupport.js @@ -6,13 +6,13 @@ import { import { Far } from '@endo/marshal'; import { reverseInterest } from '../../src/interest-math.js'; -export const makeCompoundedStabilityFeeProvider = brand => { - let compoundedStabilityFee = makeRatio(100n, brand); +export const makeCompoundedInterestProvider = brand => { + let compoundedInterest = makeRatio(100n, brand); return { - getCompoundedStabilityFee: () => compoundedStabilityFee, + getCompoundedInterest: () => compoundedInterest, chargeHundredPercentInterest: () => { - compoundedStabilityFee = makeRatio( - compoundedStabilityFee.numerator.value * 2n, + compoundedInterest = makeRatio( + compoundedInterest.numerator.value * 2n, brand, ); }, @@ -30,11 +30,11 @@ export const makeFakeVault = ( vaultId, initDebt, initCollateral = AmountMath.make(initDebt.brand, 100n), - manager = makeCompoundedStabilityFeeProvider(initDebt.brand), + manager = makeCompoundedInterestProvider(initDebt.brand), ) => { let normalizedDebt = reverseInterest( initDebt, - manager.getCompoundedStabilityFee(), + manager.getCompoundedInterest(), ); let collateral = initCollateral; const fakeSeat = {}; @@ -42,11 +42,11 @@ export const makeFakeVault = ( getCollateralAmount: () => collateral, getNormalizedDebt: () => normalizedDebt, getCurrentDebt: () => - floorMultiplyBy(normalizedDebt, manager.getCompoundedStabilityFee()), + floorMultiplyBy(normalizedDebt, manager.getCompoundedInterest()), setDebt: newDebt => (normalizedDebt = reverseInterest( newDebt, - manager.getCompoundedStabilityFee(), + manager.getCompoundedInterest(), )), setCollateral: newCollateral => (collateral = newCollateral), getIdInManager: () => vaultId, diff --git a/packages/inter-protocol/test/vaultFactory/snapshots/test-vaultFactory.js.md b/packages/inter-protocol/test/vaultFactory/snapshots/test-vaultFactory.js.md index 03c50af779c..aed2a1c4ec3 100644 --- a/packages/inter-protocol/test/vaultFactory/snapshots/test-vaultFactory.js.md +++ b/packages/inter-protocol/test/vaultFactory/snapshots/test-vaultFactory.js.md @@ -69,7 +69,7 @@ Generated by [AVA](https://avajs.dev). [ 'published.vaultFactory.managers.manager0', { - compoundedStabilityFee: { + compoundedInterest: { denominator: { brand: Object @Alleged: IST brand {}, value: 100000000000000000000n, @@ -79,11 +79,7 @@ Generated by [AVA](https://avajs.dev). value: 101967213114754098360n, }, }, - latestStabilityFeeUpdate: { - absValue: 3024000n, - timerBrand: Object @Alleged: timerBrand {}, - }, - stabilityFee: { + interestRate: { denominator: { brand: Object @Alleged: IST brand {}, value: 100n, @@ -93,6 +89,10 @@ Generated by [AVA](https://avajs.dev). value: 20n, }, }, + latestInterestUpdate: { + absValue: 3024000n, + timerBrand: Object @Alleged: timerBrand {}, + }, }, ], [ @@ -106,6 +106,19 @@ Generated by [AVA](https://avajs.dev). value: 1000000n, }, }, + InterestRate: { + type: 'ratio', + value: { + denominator: { + brand: Object @Alleged: IST brand {}, + value: 100n, + }, + numerator: { + brand: Object @Alleged: IST brand {}, + value: 20n, + }, + }, + }, LiquidationMargin: { type: 'ratio', value: { @@ -158,19 +171,6 @@ Generated by [AVA](https://avajs.dev). }, }, }, - StabilityFee: { - type: 'ratio', - value: { - denominator: { - brand: Object @Alleged: IST brand {}, - value: 100n, - }, - numerator: { - brand: Object @Alleged: IST brand {}, - value: 20n, - }, - }, - }, }, }, ], @@ -254,7 +254,7 @@ Generated by [AVA](https://avajs.dev). brand: Object @Alleged: IST brand {}, value: 473n, }, - stabilityFee: { + interest: { denominator: { brand: Object @Alleged: IST brand {}, value: 100n, @@ -280,7 +280,7 @@ Generated by [AVA](https://avajs.dev). brand: Object @Alleged: IST brand {}, value: 473n, }, - stabilityFee: { + interest: { denominator: { brand: Object @Alleged: IST brand {}, value: 100n, @@ -306,7 +306,7 @@ Generated by [AVA](https://avajs.dev). brand: Object @Alleged: IST brand {}, value: 53n, }, - stabilityFee: { + interest: { denominator: { brand: Object @Alleged: IST brand {}, value: 100n, @@ -332,7 +332,7 @@ Generated by [AVA](https://avajs.dev). brand: Object @Alleged: IST brand {}, value: 53n, }, - stabilityFee: { + interest: { denominator: { brand: Object @Alleged: IST brand {}, value: 100n, @@ -358,7 +358,7 @@ Generated by [AVA](https://avajs.dev). brand: Object @Alleged: IST brand {}, value: 473n, }, - stabilityFee: { + interest: { denominator: { brand: Object @Alleged: IST brand {}, value: 100n, @@ -384,7 +384,7 @@ Generated by [AVA](https://avajs.dev). brand: Object @Alleged: IST brand {}, value: 53n, }, - stabilityFee: { + interest: { denominator: { brand: Object @Alleged: IST brand {}, value: 100000000000000000000n, @@ -410,7 +410,7 @@ Generated by [AVA](https://avajs.dev). brand: Object @Alleged: IST brand {}, value: 0n, }, - stabilityFee: { + interest: { denominator: { brand: Object @Alleged: IST brand {}, value: 100000000000000000000n, diff --git a/packages/inter-protocol/test/vaultFactory/snapshots/test-vaultFactory.js.snap b/packages/inter-protocol/test/vaultFactory/snapshots/test-vaultFactory.js.snap index 2866104c107..21a5482e71a 100644 Binary files a/packages/inter-protocol/test/vaultFactory/snapshots/test-vaultFactory.js.snap and b/packages/inter-protocol/test/vaultFactory/snapshots/test-vaultFactory.js.snap differ diff --git a/packages/inter-protocol/test/vaultFactory/test-collatRatio.js b/packages/inter-protocol/test/vaultFactory/test-collatRatio.js index 19b025aa760..fb67b32629e 100644 --- a/packages/inter-protocol/test/vaultFactory/test-collatRatio.js +++ b/packages/inter-protocol/test/vaultFactory/test-collatRatio.js @@ -21,7 +21,7 @@ test('normalizedCollRatio grows with coll margin', t => { /** @type {PriceQuote} */ // @ts-expect-error fake for tests. const quote = makeFakeQuote(minted.make(5n), collateral.make(20n)); - const compoundedStabilityFee = makeRatioFromAmounts( + const compoundedInterest = makeRatioFromAmounts( minted.make(1n), collateral.make(1n), ); @@ -36,13 +36,13 @@ test('normalizedCollRatio grows with coll margin', t => { const lowRate = normalizedCollRatio( quote, - compoundedStabilityFee, + compoundedInterest, lowCollateralizationMargin, ); t.deepEqual(lowRate, (105 * 5) / (20 * 100)); const highRate = normalizedCollRatio( quote, - compoundedStabilityFee, + compoundedInterest, highCollateralizationMargin, ); t.deepEqual(highRate, (150 * 5) / (20 * 100)); @@ -78,19 +78,15 @@ test('CollRatio grows with price', t => { // @ts-expect-error fake for tests. const highQuote = makeFakeQuote(minted.make(15n), collateral.make(20n)); - const compoundedStabilityFee = makeRatioFromAmounts( + const compoundedInterest = makeRatioFromAmounts( minted.make(12n), collateral.make(10n), ); const margin = makeRatioFromAmounts(minted.make(105n), collateral.make(100n)); - const lowRate = normalizedCollRatio(lowQuote, compoundedStabilityFee, margin); + const lowRate = normalizedCollRatio(lowQuote, compoundedInterest, margin); t.deepEqual(lowRate, (105 * 5 * 12) / (20 * 100 * 10)); - const highRate = normalizedCollRatio( - highQuote, - compoundedStabilityFee, - margin, - ); + const highRate = normalizedCollRatio(highQuote, compoundedInterest, margin); t.deepEqual(highRate, (105 * 15 * 12) / (20 * 100 * 10)); t.true(highRate > lowRate); }); diff --git a/packages/inter-protocol/test/vaultFactory/test-prioritizedVaults.js b/packages/inter-protocol/test/vaultFactory/test-prioritizedVaults.js index 4c77dae694d..0b211427545 100644 --- a/packages/inter-protocol/test/vaultFactory/test-prioritizedVaults.js +++ b/packages/inter-protocol/test/vaultFactory/test-prioritizedVaults.js @@ -13,7 +13,7 @@ import { makePrioritizedVaults, } from '../../src/vaultFactory/prioritizedVaults.js'; import { - makeCompoundedStabilityFeeProvider, + makeCompoundedInterestProvider, makeFakeVault, } from './interestSupport.js'; @@ -196,7 +196,7 @@ test('stable ordering as interest accrues', async t => { const vaults = makePrioritizedVaults(store); const fakeVaultID1 = 'id-fakeVault1'; - const m = makeCompoundedStabilityFeeProvider(stableBrand); + const m = makeCompoundedInterestProvider(stableBrand); // ACTUAL DEBTS AFTER 100% DAILY INTEREST // day 0 diff --git a/packages/inter-protocol/test/vaultFactory/test-storage.js b/packages/inter-protocol/test/vaultFactory/test-storage.js index 1eab6d1b75b..c5652f6e577 100644 --- a/packages/inter-protocol/test/vaultFactory/test-storage.js +++ b/packages/inter-protocol/test/vaultFactory/test-storage.js @@ -45,7 +45,7 @@ test.only('storage keys', async t => { managerA, 'asset', 'mockChainStorageRoot.vaultFactory.managers.manager0', - ['compoundedStabilityFee', 'latestStabilityFeeUpdate', 'stabilityFee'], + ['compoundedInterest', 'interestRate', 'latestInterestUpdate'], ); await assertTopicPathData( t, diff --git a/packages/inter-protocol/test/vaultFactory/test-vault-interest.js b/packages/inter-protocol/test/vaultFactory/test-vault-interest.js index 9db316064cc..ce2c938f430 100644 --- a/packages/inter-protocol/test/vaultFactory/test-vault-interest.js +++ b/packages/inter-protocol/test/vaultFactory/test-vault-interest.js @@ -23,7 +23,7 @@ const trace = makeTracer('TestVaultInterest', false); * @property {IssuerKit} collateralKit * @property {Vault} vault * @property {Function} advanceRecordingPeriod - * @property {Function} setStabilityFee + * @property {Function} setInterestRate */ let testJig; /** @param {TestContext} jig */ @@ -137,7 +137,7 @@ test('charges', async t => { AmountMath.make(stableBrand, startingDebt - normalizedPaybackValue), ); - testJig.setStabilityFee(25n); + testJig.setInterestRate(25n); for (const [i, charge] of [22n, 27n, 34n].entries()) { // XXX https://github.com/Agoric/agoric-sdk/issues/5527 diff --git a/packages/inter-protocol/test/vaultFactory/test-vault.js b/packages/inter-protocol/test/vaultFactory/test-vault.js index 4d4fba3bda3..9cdeb7fae50 100644 --- a/packages/inter-protocol/test/vaultFactory/test-vault.js +++ b/packages/inter-protocol/test/vaultFactory/test-vault.js @@ -23,7 +23,7 @@ const trace = makeTracer('TestVault', false); * @property {IssuerKit} collateralKit * @property {Vault} vault * @property {Function} advanceRecordingPeriod - * @property {Function} setStabilityFee + * @property {Function} setInterestRate */ let testJig; /** @param {TestContext} jig */ diff --git a/packages/inter-protocol/test/vaultFactory/test-vaultFactory.js b/packages/inter-protocol/test/vaultFactory/test-vaultFactory.js index 85758e664cd..80bc0cb63dc 100644 --- a/packages/inter-protocol/test/vaultFactory/test-vaultFactory.js +++ b/packages/inter-protocol/test/vaultFactory/test-vaultFactory.js @@ -384,7 +384,7 @@ test('interest on multiple vaults', async t => { const { zoe, aeth, run, rates: defaultRates } = t.context; const rates = { ...defaultRates, - stabilityFee: makeRatio(5n, run.brand), + interestRate: makeRatio(5n, run.brand), }; t.context.rates = rates; // charging period is 1 week. Clock ticks by days @@ -498,24 +498,24 @@ test('interest on multiple vaults', async t => { const aliceUpdate = await E(aliceNotifier).getUpdateSince(); const bobUpdate = await E(bobNotifier).getUpdateSince(); - // 160n is initial fee. stabilityFee is ~3n/week. compounding is in the noise. + // 160n is initial fee. interest is ~3n/week. compounding is in the noise. const bobAddedDebt = 160n + 3n; t.deepEqual( calculateCurrentDebt( bobUpdate.value.debtSnapshot.debt, - bobUpdate.value.debtSnapshot.stabilityFee, - assetUpdate.value.compoundedStabilityFee, + bobUpdate.value.debtSnapshot.interest, + assetUpdate.value.compoundedInterest, ), run.make(3200n + bobAddedDebt), ); - // 236 is the initial fee. stabilityFee is ~4n/week + // 236 is the initial fee. Interest is ~4n/week const aliceAddedDebt = 236n + 4n; t.deepEqual( calculateCurrentDebt( aliceUpdate.value.debtSnapshot.debt, - aliceUpdate.value.debtSnapshot.stabilityFee, - assetUpdate.value.compoundedStabilityFee, + aliceUpdate.value.debtSnapshot.interest, + assetUpdate.value.compoundedInterest, ), run.make(4700n + aliceAddedDebt), `should have collected ${aliceAddedDebt}`, @@ -523,7 +523,7 @@ test('interest on multiple vaults', async t => { // but no change to the snapshot t.deepEqual(aliceUpdate.value.debtSnapshot, { debt: run.make(4935n), - stabilityFee: makeRatio(100n, run.brand, 100n), + interest: makeRatio(100n, run.brand, 100n), }); const rewardAllocation = await E(vaultFactory).getRewardAllocation(); @@ -531,7 +531,7 @@ test('interest on multiple vaults', async t => { t.is( rewardAllocation.Minted.value, rewardRunCount, - // reward includes 5% fees on two loans plus 1% stabilityFee three times on each + // reward includes 5% fees on two loans plus 1% interest three times on each `Should be ${rewardRunCount}, was ${rewardAllocation.Minted.value}`, ); @@ -552,7 +552,7 @@ test('interest on multiple vaults', async t => { // Advance another 7 days, past one charging and recording period await manualTimer.tickN(8); - // open a vault when manager's stabilityFee already compounded + // open a vault when manager's interest already compounded const wantedRun = 1_000n; /** @type {UserSeat} */ const danVaultSeat = await E(zoe).offer( @@ -640,7 +640,7 @@ test('adjust balances', async t => { t.deepEqual(aliceUpdate.value.debtSnapshot.debt, debtLevel); t.deepEqual(aliceUpdate.value.debtSnapshot, { debt: run.make(5250n), - stabilityFee: makeRatio(100n, run.brand), + interest: makeRatio(100n, run.brand), }); // increase collateral 1 ///////////////////////////////////// (give both) @@ -737,7 +737,7 @@ test('adjust balances', async t => { t.deepEqual(aliceUpdate.value.debtSnapshot.debt, debtLevel); t.deepEqual(aliceUpdate.value.debtSnapshot, { debt: run.make(5253n), - stabilityFee: run.makeRatio(100n), + interest: run.makeRatio(100n), }); // reduce collateral ///////////////////////////////////// (want both) @@ -898,12 +898,12 @@ test('adjust balances - withdraw RUN', async t => { t.deepEqual(aliceUpdate.value.debtSnapshot.debt, debtLevel); }); -test('adjust balances after stabilityFee charges', async t => { +test('adjust balances after interest charges', async t => { const OPEN1 = 450n; const AMPLE = 100_000n; const { aeth, run } = t.context; - // charge stabilityFee on every tick + // charge interest on every tick const manualTimer = buildManualTimer(trace, 0n, { timeStep: SECONDS_PER_DAY, }); @@ -913,7 +913,7 @@ test('adjust balances after stabilityFee charges', async t => { }; t.context.rates = { ...t.context.rates, - stabilityFee: run.makeRatio(20n), + interestRate: run.makeRatio(20n), }; const services = await setupServices( @@ -940,7 +940,7 @@ test('adjust balances after stabilityFee charges', async t => { ); const { vault } = await E(vaultSeat).getOfferResult(); - trace('1. Charge stabilityFee'); + trace('1. Charge interest'); await manualTimer.tick(); await manualTimer.tick(); @@ -1031,7 +1031,7 @@ test('transfer vault', async t => { customDetails: { debtSnapshot: { debt: debtAmount, - stabilityFee: aliceFinish.value.debtSnapshot.stabilityFee, + interest: aliceFinish.value.debtSnapshot.interest, }, locked: collateralAmount, vaultState: 'active', @@ -1226,7 +1226,7 @@ test('collect fees from vault', async t => { recordingPeriod: SECONDS_PER_WEEK, }; - // charge stabilityFee on every tick + // charge interest on every tick const manualTimer = buildManualTimer(t.log, 0n, { timeStep: SECONDS_PER_WEEK, eventLoopIteration, @@ -1529,7 +1529,7 @@ test('debt too small - MinInitialDebt', async t => { * allow. * * Attempts to adjust balances on vaults beyond the debt limit fail. In other - * words, minting for anything other than charging stabilityFee fails. + * words, minting for anything other than charging interest fails. */ test('excessive debt on collateral type - debtLimit', async t => { const { zoe, aeth, run } = t.context; @@ -1613,7 +1613,7 @@ test('addVaultType: extra, unexpected params', async t => { const params = { ...defaultParamValues(aeth.brand), shoeSize: 10 }; const extraParams = { ...params, shoeSize: 10 }; - const { stabilityFee: _1, ...missingParams } = { + const { interestRate: _1, ...missingParams } = { ...defaultParamValues(aeth.brand), shoeSize: 10, }; @@ -1623,7 +1623,7 @@ test('addVaultType: extra, unexpected params', async t => { E(vaultFactory).addVaultType(chit.issuer, 'Chit', missingParams), { message: - /initialParamValues: .* - Must have missing properties \["stabilityFee"\]/, + /initialParamValues: .* - Must have missing properties \["interestRate"\]/, }, ); @@ -1689,7 +1689,7 @@ test('manager notifiers, with snapshot', async t => { }; t.context.rates = { ...t.context.rates, - stabilityFee: run.makeRatio(20n), + interestRate: run.makeRatio(20n), }; const services = await setupServices( @@ -1825,7 +1825,7 @@ test('manager notifiers, with snapshot', async t => { ); ({ vault } = await E(vaultSeat).getOfferResult()); - trace('6. Loan stabilityFee'); + trace('6. Loan interest'); vaultSeat = await E(services.zoe).offer( await E(E(vfPublic).getCollateralManager(aeth.brand)).makeVaultInvitation(), harden({ @@ -1846,9 +1846,9 @@ test('manager notifiers, with snapshot', async t => { }); m.addDebt(DEBT2); await manualTimer.tickN(5); - const stabilityFeeAccrued = (await E(vault).getCurrentDebt()).value - DEBT1; - m.addDebt(stabilityFeeAccrued); - t.is(stabilityFeeAccrued, 9n); + const interestAccrued = (await E(vault).getCurrentDebt()).value - DEBT1; + m.addDebt(interestAccrued); + t.is(interestAccrued, 9n); trace('7. make another loan to trigger a publish'); vaultSeat = await E(services.zoe).offer( @@ -2014,15 +2014,15 @@ test('governance publisher', async t => { // can't deepEqual because of non-literal objects so check keys and then partial shapes t.deepEqual(Object.keys(current), [ 'DebtLimit', + 'InterestRate', 'LiquidationMargin', 'LiquidationPadding', 'LiquidationPenalty', 'MintFee', - 'StabilityFee', ]); t.like(current, { DebtLimit: { type: 'amount' }, - StabilityFee: { type: 'ratio' }, + InterestRate: { type: 'ratio' }, LiquidationMargin: { type: 'ratio' }, LiquidationPadding: { type: 'ratio' }, LiquidationPenalty: { type: 'ratio' }, diff --git a/packages/inter-protocol/test/vaultFactory/test-vaultLiquidation.js b/packages/inter-protocol/test/vaultFactory/test-vaultLiquidation.js index 0ec78f100f0..a79d2b96068 100644 --- a/packages/inter-protocol/test/vaultFactory/test-vaultLiquidation.js +++ b/packages/inter-protocol/test/vaultFactory/test-vaultLiquidation.js @@ -426,7 +426,7 @@ test('price drop', async t => { t.is(notification.value.vaultState, Phase.ACTIVE); t.deepEqual((await notification.value).debtSnapshot, { debt: AmountMath.add(wantMinted, fee), - stabilityFee: makeRatio(100n, run.brand), + interest: makeRatio(100n, run.brand), }); const { Minted: lentAmount } = await E(vaultSeat).getFinalAllocation(); t.truthy(AmountMath.isEqual(lentAmount, wantMinted), 'received 470 Minted'); @@ -663,7 +663,7 @@ test('liquidate two loans', async t => { const rates = harden({ ...defaultRates, // charge 40% interest / year - stabilityFee: run.makeRatio(40n), + interestRate: run.makeRatio(40n), liquidationMargin: run.makeRatio(103n), }); t.context.rates = rates; @@ -1014,7 +1014,7 @@ test('sell goods at auction', async t => { const rates = harden({ ...defaultRates, // charge 200% interest - stabilityFee: run.makeRatio(200n), + interestRate: run.makeRatio(200n), liquidationMargin: run.makeRatio(103n), }); t.context.rates = rates; @@ -1433,7 +1433,7 @@ test('Auction sells all collateral w/shortfall', async t => { const rates = harden({ ...defaultRates, // charge 40% interest / year - stabilityFee: run.makeRatio(40n), + interestRate: run.makeRatio(40n), liquidationMargin: run.makeRatio(130n), }); t.context.rates = rates; @@ -1653,7 +1653,7 @@ test('liquidation Margin matters', async t => { const rates = harden({ ...defaultRates, - stabilityFee: run.makeRatio(0n), + interestRate: run.makeRatio(0n), liquidationMargin: run.makeRatio(150n), }); t.context.rates = rates; @@ -1757,7 +1757,7 @@ test('reinstate vault', async t => { const rates = harden({ ...defaultRates, - stabilityFee: run.makeRatio(0n), + interestRate: run.makeRatio(0n), liquidationMargin: run.makeRatio(150n), }); t.context.rates = rates; @@ -2633,7 +2633,7 @@ test('refund to one of two loans', async t => { t.is(aliceNotification.value.vaultState, Phase.ACTIVE); t.deepEqual((await aliceNotification.value).debtSnapshot, { debt: AmountMath.add(aliceWantMinted, aliceFee), - stabilityFee: makeRatio(100n, run.brand), + interest: makeRatio(100n, run.brand), }); const { Minted: lentAmount } = await E(aliceVaultSeat).getFinalAllocation(); t.truthy(AmountMath.isEqual(lentAmount, aliceWantMinted)); diff --git a/packages/inter-protocol/test/vaultFactory/vault-contract-wrapper.js b/packages/inter-protocol/test/vaultFactory/vault-contract-wrapper.js index ff1e1f83e92..d79d9b5a16b 100644 --- a/packages/inter-protocol/test/vaultFactory/vault-contract-wrapper.js +++ b/packages/inter-protocol/test/vaultFactory/vault-contract-wrapper.js @@ -59,7 +59,7 @@ export async function start(zcf, privateArgs, baggage) { let vaultCounter = 0; let currentInterest = makeRatio(5n, stableBrand); // 5% - let compoundedStabilityFee = makeRatio(100n, stableBrand); // starts at 1.0, no interest + let compoundedInterest = makeRatio(100n, stableBrand); // starts at 1.0, no interest const { zcfSeat: mintSeat } = zcf.makeEmptySeatKit(); @@ -136,7 +136,7 @@ export async function start(zcf, privateArgs, baggage) { getMintFee() { return makeRatio(500n, stableBrand, BASIS_POINTS); }, - getStabilityFee() { + getInterestRate() { return currentInterest; }, getChargingPeriod() { @@ -166,7 +166,7 @@ export async function start(zcf, privateArgs, baggage) { getCollateralQuote() { return Promise.reject(Error('Not implemented')); }, - getCompoundedStabilityFee: () => compoundedStabilityFee, + getCompoundedInterest: () => compoundedInterest, scopeDescription: base => `VCW: ${base}`, handleBalanceChange: () => { console.warn('mock handleBalanceChange does nothing'); @@ -195,13 +195,13 @@ export async function start(zcf, privateArgs, baggage) { 100n + currentInterest.numerator.value, currentInterest.numerator.brand, ); - compoundedStabilityFee = multiplyRatios( - compoundedStabilityFee, + compoundedInterest = multiplyRatios( + compoundedInterest, currentInterestAsMultiplicand, ); }; - const setStabilityFee = percent => { + const setInterestRate = percent => { currentInterest = makeRatio(percent, stableBrand); }; @@ -209,7 +209,7 @@ export async function start(zcf, privateArgs, baggage) { advanceRecordingPeriod, collateralKit, stableMint, - setStabilityFee, + setInterestRate, vault, })); diff --git a/packages/inter-protocol/test/vaultFactory/vaultFactoryUtils.js b/packages/inter-protocol/test/vaultFactory/vaultFactoryUtils.js index a08fc43a591..16592960c9f 100644 --- a/packages/inter-protocol/test/vaultFactory/vaultFactoryUtils.js +++ b/packages/inter-protocol/test/vaultFactory/vaultFactoryUtils.js @@ -50,7 +50,7 @@ export const defaultParamValues = debtBrand => // penalty upon liquidation as proportion of debt liquidationPenalty: makeRatio(10n, debtBrand), // periodic interest rate (per charging period) - stabilityFee: makeRatio(100n, debtBrand, BASIS_POINTS), + interestRate: makeRatio(100n, debtBrand, BASIS_POINTS), // charge to create or increase loan balance mintFee: makeRatio(500n, debtBrand, BASIS_POINTS), // NB: liquidationPadding defaults to zero in contract diff --git a/packages/vats/decentral-itest-vaults-config.json b/packages/vats/decentral-itest-vaults-config.json index dd2b21a47df..fc8158160bb 100644 --- a/packages/vats/decentral-itest-vaults-config.json +++ b/packages/vats/decentral-itest-vaults-config.json @@ -22,7 +22,7 @@ "entrypoint": "defaultProposalBuilder", "args": [ { - "stabilityFeeValue": 1000, + "interestRateValue": 1000, "interchainAssetOptions": { "denom": "ibc/toyatom", "decimalPlaces": 6, diff --git a/packages/vats/src/core/demoIssuers.js b/packages/vats/src/core/demoIssuers.js index 9843da16c22..9829982797c 100644 --- a/packages/vats/src/core/demoIssuers.js +++ b/packages/vats/src/core/demoIssuers.js @@ -86,7 +86,7 @@ const defaultConfig = /** @type {const} */ ({ initialMargin: [150n, PCT], liquidationMargin: [125n, PCT], liquidationPenalty: [10n, PCT], - stabilityFee: [250n, BASIS], + interestRate: [250n, BASIS], mintFee: [1n, BASIS], }); @@ -100,7 +100,7 @@ const defaultConfig = /** @type {const} */ ({ * initialMargin: Rational; * liquidationMargin: Rational; * liquidationPenalty: Rational; - * stabilityFee: Rational; + * interestRate: Rational; * mintFee: Rational; * liquidationPadding?: Rational; * }; @@ -451,7 +451,7 @@ export const poolRates = (issuerName, record, kits, central) => { initialMargin: toRatio(config.initialMargin, central.brand), liquidationMargin: toRatio(config.liquidationMargin, central.brand), liquidationPenalty: toRatio(config.liquidationPenalty, central.brand), - stabilityFee: toRatio(config.stabilityFee, central.brand), + interestRate: toRatio(config.interestRate, central.brand), mintFee: toRatio(config.mintFee, central.brand), // XXX not relevant to AMM pools but poolRates is also used for addVaultType liquidationPadding: diff --git a/packages/vats/test/bootstrapTests/liquidation.js b/packages/vats/test/bootstrapTests/liquidation.js index d19e48f4f66..d3cd30ba99d 100644 --- a/packages/vats/test/bootstrapTests/liquidation.js +++ b/packages/vats/test/bootstrapTests/liquidation.js @@ -146,7 +146,7 @@ export const makeLiquidationTestContext = async t => { t.like(readLatest(`${managerPath}.governance`), { current: { DebtLimit: { value: { value: DebtLimitValue } }, - StabilityFee: { + InterestRate: { type: 'ratio', value: { numerator: { value: 1n }, denominator: { value: 100n } }, }, diff --git a/packages/vats/test/test-demoAMM.js b/packages/vats/test/test-demoAMM.js index 3b7861545d0..1d9b3fb4303 100644 --- a/packages/vats/test/test-demoAMM.js +++ b/packages/vats/test/test-demoAMM.js @@ -63,8 +63,8 @@ test('poolRates: spot check WETH', t => { t.is(decimal(initialValue, DecimalPlaces.WETH), '1_000_000'); t.is((AMMDemoState.WETH.config || {}).collateralValue, 1_000_000n); - t.is(showBrand(rates.stabilityFee.numerator.brand), Stable.symbol); - t.is(showAmount(rates.stabilityFee.numerator), '0.00025 IST'); + t.is(showBrand(rates.interestRate.numerator.brand), Stable.symbol); + t.is(showAmount(rates.interestRate.numerator), '0.00025 IST'); const showRatio = ({ numerator, denominator }) => numerator.brand === denominator.brand @@ -79,7 +79,7 @@ test('poolRates: spot check WETH', t => { initialPrice: '3_286.01 IST / 1 WETH', initialMargin: '1.5', liquidationMargin: '1.25', - stabilityFee: '0.025', + interestRate: '0.025', mintFee: '0.0001', }; Object.entries(expected).forEach(([prop, val]) =>