@@ -10,16 +10,21 @@ const STEEPNESS = 4
1010const WAD = 1e18
1111const SECONDS_PER_YEAR = 365 * 24 * 3600 // 365-day year, no leap year — matches Morpho convention
1212
13- /**
14- * Adaptive Curve IRM: deviation from target utilisation.
15- * Returns a signed multiplier applied to rateAtTarget.
16- */
17- function _curve ( util : number ) : number {
18- const err = ( util - TARGET_UTIL ) / TARGET_UTIL
19- if ( err < 0 ) {
20- return STEEPNESS * err // below target: linear decrease
13+ /** Normalized distance from target utilization. Range: [-1, +1]. */
14+ function _error ( util : number ) : number {
15+ if ( util > TARGET_UTIL ) {
16+ return ( util - TARGET_UTIL ) / ( 1 - TARGET_UTIL )
17+ }
18+ return ( util - TARGET_UTIL ) / TARGET_UTIL
19+ }
20+
21+ /** IRM rate multiplier at a given utilization. Always positive. */
22+ function _curveMultiplier ( util : number ) : number {
23+ const err = _error ( util )
24+ if ( util <= TARGET_UTIL ) {
25+ return ( 1 - 1 / STEEPNESS ) * err + 1 // 0.75 * err + 1
2126 }
22- return ( STEEPNESS * ( util - TARGET_UTIL ) ) / ( 1 - TARGET_UTIL ) // above target: steeper increase
27+ return ( STEEPNESS - 1 ) * err + 1 // 3 * err + 1
2328}
2429
2530/**
@@ -43,11 +48,13 @@ export function estimateMarketApy(
4348 return { supplyApy : 0 , borrowApy : 0 }
4449 }
4550
46- const util = Math . min ( totalBorrows / supply , 0.9999 ) // clamp to avoid division by zero
51+ let util = Math . min ( totalBorrows / supply , 0.9999 ) // clamp to avoid division by zero
52+ if ( util < 0.0001 ) util = 0
53+
4754 const ratePerSec = rateAtTarget / WAD
48- const borrowRate = ratePerSec * Math . exp ( _curve ( util ) )
49- const borrowApy = Math . exp ( borrowRate * SECONDS_PER_YEAR ) - 1 // continuous compounding
50- const supplyApy = borrowApy * util * ( 1 - fee / WAD ) // supply earns util% minus protocol fee
55+ const borrowRate = ratePerSec * _curveMultiplier ( util )
56+ const borrowApy = Math . max ( 0 , Math . min ( Math . exp ( borrowRate * SECONDS_PER_YEAR ) - 1 , 8.0 ) ) // continuous compounding, clamped to [0, 800%]
57+ const supplyApy = Math . max ( 0 , Math . min ( borrowApy * util * ( 1 - fee / WAD ) , 8.0 ) )
5158
5259 return { supplyApy, borrowApy }
5360}
0 commit comments