Description:
Smart contract deployed on Ethereum.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.10;
// src/contracts/InterestRateModel.sol
/**
* @title Compound's InterestRateModel Interface
* @author Compound
*/
abstract contract InterestRateModel {
/// @notice Indicator that this is an InterestRateModel contract (for inspection)
bool public constant isInterestRateModel = true;
/**
* @notice Calculates the current borrow interest rate per block
* @param cash The total amount of cash the market has
* @param borrows The total amount of borrows the market has outstanding
* @param reserves The total amount of reserves the market has
* @return The borrow rate per block (as a percentage, and scaled by 1e18)
*/
function getBorrowRate(uint cash, uint borrows, uint reserves) virtual external view returns (uint);
/**
* @notice Calculates the current supply interest rate per block
* @param cash The total amount of cash the market has
* @param borrows The total amount of borrows the market has outstanding
* @param reserves The total amount of reserves the market has
* @param reserveFactorMantissa The current reserve factor the market has
* @return The supply rate per block (as a percentage, and scaled by 1e18)
*/
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual external view returns (uint);
}
// src/contracts/BaseJumpRateModelV2.sol
/**
* @title Logic for Compound's JumpRateModel Contract V2.
* @author Compound (modified by Dharma Labs, refactored by Arr00)
* @notice Version 2 modifies Version 1 by enabling updateable parameters.
*/
abstract contract BaseJumpRateModelV2 is InterestRateModel {
event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock, uint jumpMultiplierPerBlock, uint kink);
uint256 private constant BASE = 1e18;
/**
* @notice The address of the owner, i.e. the Timelock contract, which can update parameters directly
*/
address public owner;
/**
* @notice The approximate number of blocks per year that is assumed by the interest rate model (assuming 12s blocks)
*/
uint public constant blocksPerYear = 2628000;
/**
* @notice The multiplier of utilization rate that gives the slope of the interest rate
*/
uint public multiplierPerBlock;
/**
* @notice The base interest rate which is the y-intercept when utilization rate is 0
*/
uint public baseRatePerBlock;
/**
* @notice The multiplierPerBlock after hitting a specified utilization point
*/
uint public jumpMultiplierPerBlock;
/**
* @notice The utilization point at which the jump multiplier is applied
*/
uint public kink;
/**
* @notice Construct an interest rate model
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE)
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE)
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point
* @param kink_ The utilization point at which the jump multiplier is applied
* @param owner_ The address of the owner, i.e. the Timelock contract (which has the ability to update parameters directly)
*/
constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) internal {
owner = owner_;
updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);
}
/**
* @notice Update the parameters of the interest rate model (only callable by owner, i.e. Timelock)
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE)
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE)
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point
* @param kink_ The utilization point at which the jump multiplier is applied
*/
function updateJumpRateModel(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) virtual external {
require(msg.sender == owner, "only the owner may call this function.");
updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);
}
/**
* @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)`
* @param cash The amount of cash in the market
* @param borrows The amount of borrows in the market
* @param reserves The amount of reserves in the market (currently unused)
* @return The utilization rate as a mantissa between [0, BASE]
*/
function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) {
// Utilization rate is 0 when there are no borrows
if (borrows == 0) {
return 0;
}
return borrows * BASE / (cash + borrows - reserves);
}
/**
* @notice Calculates the current borrow rate per block, with the error code expected by the market
* @param cash The amount of cash in the market
* @param borrows The amount of borrows in the market
* @param reserves The amount of reserves in the market
* @return The borrow rate percentage per block as a mantissa (scaled by BASE)
*/
function getBorrowRateInternal(uint cash, uint borrows, uint reserves) internal view returns (uint) {
uint util = utilizationRate(cash, borrows, reserves);
if (util <= kink) {
return ((util * multiplierPerBlock) / BASE) + baseRatePerBlock;
} else {
uint normalRate = ((kink * multiplierPerBlock) / BASE) + baseRatePerBlock;
uint excessUtil = util - kink;
return ((excessUtil * jumpMultiplierPerBlock) / BASE) + normalRate;
}
}
/**
* @notice Calculates the current supply rate per block
* @param cash The amount of cash in the market
* @param borrows The amount of borrows in the market
* @param reserves The amount of reserves in the market
* @param reserveFactorMantissa The current reserve factor for the market
* @return The supply rate percentage per block as a mantissa (scaled by BASE)
*/
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual override public view returns (uint) {
uint oneMinusReserveFactor = BASE - reserveFactorMantissa;
uint borrowRate = getBorrowRateInternal(cash, borrows, reserves);
uint rateToPool = borrowRate * oneMinusReserveFactor / BASE;
return utilizationRate(cash, borrows, reserves) * rateToPool / BASE;
}
/**
* @notice Internal function to update the parameters of the interest rate model
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE)
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE)
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point
* @param kink_ The utilization point at which the jump multiplier is applied
*/
function updateJumpRateModelInternal(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) internal {
baseRatePerBlock = baseRatePerYear / blocksPerYear;
multiplierPerBlock = (multiplierPerYear * BASE) / (blocksPerYear * kink_);
jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;
kink = kink_;
emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);
}
}
// src/contracts/JumpRateModelV2.sol
/**
* @title Compound's JumpRateModel Contract V2 for V2 cTokens
* @author Arr00
* @notice Supports only for V2 cTokens
*/
contract JumpRateModelV2 is InterestRateModel, BaseJumpRateModelV2 {
/**
* @notice Calculates the current borrow rate per block
* @param cash The amount of cash in the market
* @param borrows The amount of borrows in the market
* @param reserves The amount of reserves in the market
* @return The borrow rate percentage per block as a mantissa (scaled by 1e18)
*/
function getBorrowRate(uint cash, uint borrows, uint reserves) override external view returns (uint) {
return getBorrowRateInternal(cash, borrows, reserves);
}
constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_)
BaseJumpRateModelV2(baseRatePerYear,multiplierPerYear,jumpMultiplierPerYear,kink_,owner_) public {}
}
Submitted on: 2025-10-29 20:29:01
Comments
Log in to comment.
No comments yet.