Interest rate primitives — compounding, discounting, log returns, APR↔APY conversions, and closed-form / iterative yield calculations. Built on top of DeFiMath's exp, ln, expm1, and log1p.
Contract: Rates.sol
| Function | Gas | Description |
|---|---|---|
| compoundInterest | 467 | Continuous compounding: P · e^(r·t) |
| presentValue | 519 | Discounting: FV · e^(−r·t) |
| logReturn | 591 | ln(currentPrice / previousPrice) |
| continuousToDiscrete | 509 | e^apr − 1 (APR → APY) |
| discreteToContinuous | 590 | ln(1 + apy) (APY → APR) |
| yieldToMaturity | 736 | Zero-coupon YTM (closed form) |
| internalRateOfReturn | 17k–49k | IRR via Newton-Raphson (scales with cashflow count) |
npm install defimath-lib
principal, futureValue, price — uint128, 18-decimal fixed-point (1e18 = 1.0).rate, apr, apy — annualized as 18-decimal fixed-point. APR/APY conversions take int256 (signed).timeInterval, timeToMaturity — uint32, seconds.internalRateOfReturn takes parallel cashflows[] and times[] arrays plus an initial guess for Newton-Raphson.internal pure.import "defimath-lib/contracts/finance/Rates.sol";
// Continuous compounding: how much does principal grow in 1 year at 5%?
uint256 fv = DeFiMathRates.compoundInterest(1_000e18, 0.05e18, 365 days);
// Discount a future cashflow back to today.
uint256 pv = DeFiMathRates.presentValue(fv, 0.05e18, 365 days);
// Convert continuous APR (5%) to effective APY.
int256 apy = DeFiMathRates.continuousToDiscrete(int256(0.05e18));compoundInterest and presentValue are exact inverses. Round-tripping a value through both reconstructs the original up to the underlying exp precision (~5e-14).continuousToDiscrete uses expm1; discreteToContinuous uses log1p. Safe to call with small rates without precision loss.yieldToMaturity is closed-form and cheap; internalRateOfReturn is iterative. Use YTM for zero-coupon bonds (a single ln). Use IRR for arbitrary cashflow schedules — but expect 17k–49k gas depending on cashflow count, and supply a reasonable guess to stay within the iteration budget.NoConvergenceError. The solver caps at 50 Newton-Raphson iterations.| Constant | Value |
|---|---|
| MIN_PRINCIPAL | 1e-6 (smallest allowed principal / future value) |
| MAX_PRINCIPAL | 1e15 (largest allowed principal / future value) |
| MAX_TIME_INTERVAL | 2 years (63,072,000 seconds) |
| MAX_RATE | 400% annual (4e18) |
| MAX_CASHFLOWS | 1024 (IRR gas-bomb guard) |
| IRR_MAX_ITER | 50 (Newton-Raphson iteration cap) |
| IRR_TOLERANCE | ~1e-8 convergence threshold |
| Error | Trigger |
|---|---|
| PrincipalLowerBoundError | principal ≤ MIN_PRINCIPAL |
| PrincipalUpperBoundError | principal ≥ MAX_PRINCIPAL |
| RateUpperBoundError | rate ≥ MAX_RATE |
| RateLowerBoundError | Signed-rate conversions below allowed minimum |
| TimeIntervalUpperBoundError | timeInterval ≥ MAX_TIME_INTERVAL |
| PriceLowerBoundError | logReturn when a price is below minimum |
| PriceUpperBoundError | logReturn when a price exceeds maximum |
| ArrayLengthMismatchError | internalRateOfReturn when cashflows[] and times[] differ in length |
| ArrayLengthOutOfBoundsError | Cashflow array too short or too long |
| NoConvergenceError | internalRateOfReturn fails to converge |
| InvalidBondPriceError | yieldToMaturity when price ≥ face value |