Skip to content

Commit 0623226

Browse files
authored
Merge branch 'main' into feat/etherlink
2 parents a1a64ec + 1a72c45 commit 0623226

File tree

5 files changed

+244
-133
lines changed

5 files changed

+244
-133
lines changed

packages/blue-sdk/src/market/Market.ts

Lines changed: 97 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,29 @@ export class Market implements IMarket {
165165
* @deprecated There's no such thing as a supply rate in Morpho. Only the supply APY is meaningful.
166166
*/
167167
get supplyRate() {
168-
return MarketUtils.getSupplyRate(this.borrowRate, this);
168+
return MarketUtils.getSupplyRate(this.avgBorrowRate, this);
169+
}
170+
171+
/**
172+
* @deprecated Use `avgBorrowRate` instead.
173+
*/
174+
get borrowRate() {
175+
return this.getAccrualBorrowRates().avgBorrowRate;
176+
}
177+
178+
/**
179+
* Returns the instantaneous rate at which interest accrues for borrowers of this market,
180+
* if `accrueInterest` was called immediately onchain (scaled by WAD).
181+
*
182+
* Even if `accrueInterest` is called immediately onchain,
183+
* the instantaneous rate only corresponds to an intermediary value used to calculate
184+
* the actual average rate experienced by borrowers of this market.
185+
*
186+
* If interested in the instantaneous rate experienced by existing market actors at a specific timestamp,
187+
* use `getEndBorrowRate(timestamp)`, `getBorrowApy(timestamp)`, or `getSupplyApy(timestamp)` instead.
188+
*/
189+
get endBorrowRate() {
190+
return this.getAccrualBorrowRates().endBorrowRate;
169191
}
170192

171193
/**
@@ -174,14 +196,14 @@ export class Market implements IMarket {
174196
* If `accrueInterest` was just called, the average rate equals the instantaneous rate,
175197
* so it is equivalent to `getBorrowRate(lastUpdate)`.
176198
*
177-
* In most cases, `accrueInterest` will not be called immediately onchain, so the
178-
* average rate doesn't correspond to anything "real".
199+
* In most cases, `accrueInterest` will not be called immediately onchain,
200+
* so the average rate is only an intermediary value.
179201
*
180-
* If interested in the instantaneous rate experienced by existing market actors at a specific timestamp,
181-
* use `getBorrowRate(timestamp)`, `getBorrowApy(timestamp)`, or `getSupplyApy(timestamp)` instead.
202+
* If interested in the average rate experienced by existing market actors at a specific timestamp,
203+
* use `getAvgBorrowRate(timestamp)`, `getAvgBorrowApy(timestamp)`, or `getAvgSupplyApy(timestamp)` instead.
182204
*/
183-
get borrowRate() {
184-
return this.getAccrualBorrowRate().avgBorrowRate;
205+
get avgBorrowRate() {
206+
return this.getAccrualBorrowRates().avgBorrowRate;
185207
}
186208

187209
/**
@@ -200,41 +222,45 @@ export class Market implements IMarket {
200222
return this.getBorrowApy();
201223
}
202224

225+
/**
226+
* @deprecated Use `getEndBorrowRate(timestamp)` instead.
227+
*/
228+
public getBorrowRate(timestamp: BigIntish = Time.timestamp()) {
229+
return this.getAccrualBorrowRates(timestamp).endBorrowRate;
230+
}
231+
203232
/**
204233
* Returns the instantaneous rate at which interest accrues for borrowers of this market,
205234
* at the given timestamp, if the state remains unchanged (not accrued) (scaled by WAD).
206235
* It is fundamentally different from the rate at which interest is paid by borrowers to lenders in the case of an interest accrual,
207236
* as in the case of the AdaptiveCurveIRM, the (approximated) average rate since the last update is used instead.
208-
* @param timestamp The timestamp at which to calculate the borrow rate. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow rate).
237+
* @param timestamp The timestamp at which to calculate the borrow rate.
238+
* Must be greater than or equal to `lastUpdate`.
239+
* Defaults to `Time.timestamp()` (returns the current borrow rate).
209240
*/
210-
public getBorrowRate(timestamp: BigIntish = Time.timestamp()) {
211-
if (this.rateAtTarget == null) return 0n;
212-
213-
timestamp = BigInt(timestamp);
214-
215-
const elapsed = timestamp - this.lastUpdate;
216-
if (elapsed < 0n)
217-
throw new BlueErrors.InvalidInterestAccrual(
218-
this.id,
219-
timestamp,
220-
this.lastUpdate,
221-
);
222-
223-
const { endBorrowRate } = AdaptiveCurveIrmLib.getBorrowRate(
224-
this.utilization,
225-
this.rateAtTarget,
226-
elapsed,
227-
);
241+
public getEndBorrowRate(timestamp: BigIntish = Time.timestamp()) {
242+
return this.getAccrualBorrowRates(timestamp).endBorrowRate;
243+
}
228244

229-
return endBorrowRate;
245+
/**
246+
* Returns the average rate at which interest _would_ accrue for borrowers of this market,
247+
* if `accrueInterest` was called at the given timestamp (scaled by WAD).
248+
* @param timestamp The timestamp at which to calculate the average borrow rate.
249+
* Must be greater than or equal to `lastUpdate`.
250+
* Defaults to `Time.timestamp()` (returns the current average borrow rate).
251+
*/
252+
public getAvgBorrowRate(timestamp: BigIntish = Time.timestamp()) {
253+
return this.getAccrualBorrowRates(timestamp).avgBorrowRate;
230254
}
231255

232256
/**
233-
* Returns the rate at which interest accrues for borrowers of this market,
234-
* at the given timestamp, if the state remains unchanged (not accrued) (scaled by WAD).
235-
* @param timestamp The timestamp at which to calculate the accrual borrow rate. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow rate).
257+
* Returns the rates that _would_ apply to interest accrual for borrowers of this market,
258+
* if `accrueInterest` was called at the given timestamp (scaled by WAD).
259+
* @param timestamp The timestamp at which to calculate the accrual borrow rate.
260+
* Must be greater than or equal to `lastUpdate`.
261+
* Defaults to `Time.timestamp()` (returns the current accrual borrow rate).
236262
*/
237-
protected getAccrualBorrowRate(timestamp: BigIntish = Time.timestamp()): {
263+
protected getAccrualBorrowRates(timestamp: BigIntish = Time.timestamp()): {
238264
elapsed: bigint;
239265
avgBorrowRate: bigint;
240266
endBorrowRate: bigint;
@@ -270,18 +296,22 @@ export class Market implements IMarket {
270296
/**
271297
* The market's instantaneous borrow-side Annual Percentage Yield (APY) at the given timestamp,
272298
* if the state remains unchanged (not accrued) (scaled by WAD).
273-
* @param timestamp The timestamp at which to calculate the borrow APY. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow APY).
299+
* @param timestamp The timestamp at which to calculate the borrow APY.
300+
* Must be greater than or equal to `lastUpdate`.
301+
* Defaults to `Time.timestamp()` (returns the current borrow APY).
274302
*/
275303
public getBorrowApy(timestamp: BigIntish = Time.timestamp()) {
276-
const borrowRate = this.getBorrowRate(timestamp);
304+
const borrowRate = this.getEndBorrowRate(timestamp);
277305

278306
return MarketUtils.compoundRate(borrowRate);
279307
}
280308

281309
/**
282310
* The market's instantaneous supply-side Annual Percentage Yield (APY) at the given timestamp,
283311
* if the state remains unchanged (not accrued) (scaled by WAD).
284-
* @param timestamp The timestamp at which to calculate the supply APY. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current supply APY).
312+
* @param timestamp The timestamp at which to calculate the supply APY.
313+
* Must be greater than or equal to `lastUpdate`.
314+
* Defaults to `Time.timestamp()` (returns the current supply APY).
285315
*/
286316
public getSupplyApy(timestamp: BigIntish = Time.timestamp()) {
287317
const borrowApy = this.getBorrowApy(timestamp);
@@ -292,15 +322,46 @@ export class Market implements IMarket {
292322
);
293323
}
294324

325+
/**
326+
* The market's experienced borrow-side Annual Percentage Yield (APY),
327+
* if interest was to be accrued at the given timestamp (scaled by WAD).
328+
* @param timestamp The timestamp at which to calculate the borrow APY.
329+
* Must be greater than or equal to `lastUpdate`.
330+
* Defaults to `Time.timestamp()` (returns the current borrow APY).
331+
*/
332+
public getAvgBorrowApy(timestamp: BigIntish = Time.timestamp()) {
333+
const borrowRate = this.getAvgBorrowRate(timestamp);
334+
335+
return MarketUtils.compoundRate(borrowRate);
336+
}
337+
338+
/**
339+
* The market's experienced supply-side Annual Percentage Yield (APY),
340+
* if interest was to be accrued at the given timestamp (scaled by WAD).
341+
* @param timestamp The timestamp at which to calculate the supply APY.
342+
* Must be greater than or equal to `lastUpdate`.
343+
* Defaults to `Time.timestamp()` (returns the current supply APY).
344+
*/
345+
public getAvgSupplyApy(timestamp: BigIntish = Time.timestamp()) {
346+
const borrowApy = this.getAvgBorrowApy(timestamp);
347+
348+
return MathLib.wMulUp(
349+
MathLib.wMulDown(borrowApy, this.utilization),
350+
MathLib.WAD - this.fee,
351+
);
352+
}
353+
295354
/**
296355
* Returns a new market derived from this market, whose interest has been accrued up to the given timestamp.
297-
* @param timestamp The timestamp at which to accrue interest. Must be greater than or equal to `lastUpdate`. Defaults to `lastUpdate` (returns a copy of the market).
356+
* @param timestamp The timestamp at which to accrue interest.
357+
* Must be greater than or equal to `lastUpdate`.
358+
* Defaults to `lastUpdate` (returns a copy of the market).
298359
*/
299360
public accrueInterest(timestamp: BigIntish = this.lastUpdate) {
300361
timestamp = BigInt(timestamp);
301362

302363
const { elapsed, avgBorrowRate, endRateAtTarget } =
303-
this.getAccrualBorrowRate(timestamp);
364+
this.getAccrualBorrowRates(timestamp);
304365

305366
const { interest, feeShares } = MarketUtils.getAccruedInterest(
306367
avgBorrowRate,

packages/blue-sdk/src/vault/Vault.ts

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Time } from "@morpho-org/morpho-ts";
12
import { type CapacityLimit, CapacityLimitReason } from "../market/index.js";
23
import { MathLib, type RoundingDirection } from "../math/index.js";
34
import { VaultToken } from "../token/index.js";
@@ -270,39 +271,29 @@ export class AccrualVault extends Vault implements IAccrualVault {
270271
}
271272

272273
/**
273-
* The MetaMorpho vault's APY on its assets averaged over its market deposits,
274-
* before deducting the performance fee, at the time of each market's last update (scaled by WAD).
274+
* The MetaMorpho vault's current instantaneous Annual Percentage Yield (APY)
275+
* weighted-averaged over its market deposits, before deducting the performance fee (scaled by WAD).
275276
* If interested in the APY at a specific timestamp, use `getApy(timestamp)` instead.
276277
*/
277278
get apy() {
278-
if (this.totalAssets === 0n) return 0n;
279-
280-
return (
281-
this.allocations
282-
.values()
283-
.reduce(
284-
(total, { position }) =>
285-
total + position.market.supplyApy * position.supplyAssets,
286-
0n,
287-
) / this.totalAssets
288-
);
279+
return this.getApy();
289280
}
290281

291282
/**
292-
* The MetaMorpho vault's APY on its assets averaged over its market deposits,
293-
* after deducting the performance fee, at the time of each market's last update (scaled by WAD).
283+
* The MetaMorpho vault's current instantaneous Annual Percentage Yield (APY)
284+
* weighted-averaged over its market deposits, after deducting the performance fee (scaled by WAD).
294285
* If interested in the APY at a specific timestamp, use `getApy(timestamp)` instead.
295286
*/
296287
get netApy() {
297-
return MathLib.wMulDown(this.apy, MathLib.WAD - this.fee);
288+
return this.getNetApy();
298289
}
299290

300291
/**
301-
* The MetaMorpho vault's APY on its assets averaged over its market deposits,
302-
* before deducting the performance fee, at the given timestamp,
303-
* if the state of all the markets remains unchanged (not accrued) (scaled by WAD).
292+
* The MetaMorpho vault's experienced Annual Percentage Yield (APY)
293+
* weighted-averaged over its market deposits, before deducting the performance fee,
294+
* if interest was to be accrued on each market at the given timestamp (scaled by WAD).
304295
*/
305-
public getApy(timestamp: BigIntish) {
296+
public getApy(timestamp: BigIntish = Time.timestamp()) {
306297
if (this.totalAssets === 0n) return 0n;
307298

308299
return (
@@ -311,18 +302,18 @@ export class AccrualVault extends Vault implements IAccrualVault {
311302
.reduce(
312303
(total, { position }) =>
313304
total +
314-
position.market.getSupplyApy(timestamp) * position.supplyAssets,
305+
position.market.getAvgSupplyApy(timestamp) * position.supplyAssets,
315306
0n,
316307
) / this.totalAssets
317308
);
318309
}
319310

320311
/**
321-
* The MetaMorpho vault's APY on its assets averaged over its market deposits,
322-
* after deducting the performance fee, at the given timestamp,
323-
* if the state of all the markets remains unchanged (not accrued) (scaled by WAD).
312+
* The MetaMorpho vault's experienced Annual Percentage Yield (APY)
313+
* weighted-averaged over its market deposits, after deducting the performance fee,
314+
* if interest was to be accrued on each market at the given timestamp (scaled by WAD).
324315
*/
325-
public getNetApy(timestamp: BigIntish) {
316+
public getNetApy(timestamp: BigIntish = Time.timestamp()) {
326317
return MathLib.wMulDown(this.getApy(timestamp), MathLib.WAD - this.fee);
327318
}
328319

packages/bundler-sdk-viem/src/actions.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ export const encodeOperation = (
623623

624624
const { assets: withdrawnAssets, shares: withdrawnShares } =
625625
market.withdraw(assets, shares);
626-
const minSharePrice = MathLib.mulDivUp(
626+
const minSharePrice = MathLib.mulDivDown(
627627
withdrawnAssets,
628628
MathLib.wToRay(MathLib.WAD - slippage),
629629
withdrawnShares,
@@ -661,7 +661,7 @@ export const encodeOperation = (
661661
assets,
662662
shares,
663663
);
664-
const minSharePrice = MathLib.mulDivUp(
664+
const minSharePrice = MathLib.mulDivDown(
665665
borrowedAssets,
666666
MathLib.wToRay(MathLib.WAD - slippage),
667667
borrowedShares,
@@ -785,7 +785,7 @@ export const encodeOperation = (
785785
const maxSharePrice = MathLib.mulDivUp(
786786
assets,
787787
MathLib.wToRay(MathLib.WAD + slippage),
788-
vault.toShares(assets),
788+
vault.toShares(assets, "Down"),
789789
);
790790
actions.push({
791791
type: "erc4626Deposit",
@@ -799,7 +799,7 @@ export const encodeOperation = (
799799
});
800800
} else {
801801
const maxSharePrice = MathLib.mulDivUp(
802-
vault.toAssets(shares),
802+
vault.toAssets(shares, "Up"),
803803
MathLib.wToRay(MathLib.WAD + slippage),
804804
shares,
805805
);
@@ -835,7 +835,7 @@ export const encodeOperation = (
835835
const minSharePrice = MathLib.mulDivDown(
836836
assets,
837837
MathLib.wToRay(MathLib.WAD - slippage),
838-
vault.toShares(assets),
838+
vault.toShares(assets, "Up"),
839839
);
840840
actions.push({
841841
type: "erc4626Withdraw",
@@ -850,7 +850,7 @@ export const encodeOperation = (
850850
});
851851
} else {
852852
const minSharePrice = MathLib.mulDivDown(
853-
vault.toAssets(shares),
853+
vault.toAssets(shares, "Down"),
854854
MathLib.wToRay(MathLib.WAD - slippage),
855855
shares,
856856
);

0 commit comments

Comments
 (0)