feat: update morpho libraries

This commit is contained in:
Shriya Tyagi 2024-01-10 20:36:26 +04:00
parent 6d46b8fb48
commit 19dd322655
8 changed files with 47 additions and 34 deletions

View File

@ -8,11 +8,12 @@ import {MarketParams, Market} from "./IMorpho.sol";
/// @custom:contact security@morpho.org
/// @notice Interface that Interest Rate Models (IRMs) used by Morpho must implement.
interface IIrm {
/// @notice Returns the borrow rate of the market `marketParams`.
/// @notice Returns the borrow rate per second (scaled by WAD) of the market `marketParams`.
/// @dev Assumes that `market` corresponds to `marketParams`.
function borrowRate(MarketParams memory marketParams, Market memory market) external returns (uint256);
/// @notice Returns the borrow rate of the market `marketParams` without modifying any storage.
/// @notice Returns the borrow rate per second (scaled by WAD) of the market `marketParams` without modifying any
/// storage.
/// @dev Assumes that `market` corresponds to `marketParams`.
function borrowRateView(MarketParams memory marketParams, Market memory market) external view returns (uint256);
}

View File

@ -70,7 +70,7 @@ interface IMorphoBase {
/// @notice Whether the `lltv` is enabled.
function isLltvEnabled(uint256 lltv) external view returns (bool);
/// @notice Whether `authorized` is authorized to modify `authorizer`'s positions.
/// @notice Whether `authorized` is authorized to modify `authorizer`'s position on all markets.
/// @dev Anyone is authorized to modify their own positions, regardless of this variable.
function isAuthorized(address authorizer, address authorized) external view returns (bool);
@ -91,6 +91,7 @@ interface IMorphoBase {
function enableLltv(uint256 lltv) external;
/// @notice Sets the `newFee` for the given market `marketParams`.
/// @param newFee The new fee, scaled by WAD.
/// @dev Warning: The recipient can be the zero address.
function setFee(MarketParams memory marketParams, uint256 newFee) external;
@ -129,12 +130,12 @@ interface IMorphoBase {
/// @notice Supplies `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's
/// `onMorphoSupply` function with the given `data`.
/// @dev Either `assets` or `shares` should be zero. Most usecases should rely on `assets` as an input so the caller
/// is guaranteed to have `assets` tokens pulled from their balance, but the possibility to mint a specific amount
/// of shares is given for full compatibility and precision.
/// @dev If the supply of a market gets depleted, the supply share price instantly resets to
/// `VIRTUAL_ASSETS`:`VIRTUAL_SHARES`.
/// @dev Either `assets` or `shares` should be zero. Most use cases should rely on `assets` as an input so the
/// caller is guaranteed to have `assets` tokens pulled from their balance, but the possibility to mint a specific
/// amount of shares is given for full compatibility and precision.
/// @dev Supplying a large amount can revert for overflow.
/// @dev Supplying an amount of shares may lead to supply more or fewer assets than expected due to slippage.
/// Consider using the `assets` parameter to avoid this.
/// @param marketParams The market to supply assets to.
/// @param assets The amount of assets to supply.
/// @param shares The amount of shares to mint.
@ -150,7 +151,7 @@ interface IMorphoBase {
bytes memory data
) external returns (uint256 assetsSupplied, uint256 sharesSupplied);
/// @notice Withdraws `assets` or `shares` on behalf of `onBehalf` to `receiver`.
/// @notice Withdraws `assets` or `shares` on behalf of `onBehalf` and sends the assets to `receiver`.
/// @dev Either `assets` or `shares` should be zero. To withdraw max, pass the `shares`'s balance of `onBehalf`.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Withdrawing an amount corresponding to more shares than supplied will revert for underflow.
@ -171,14 +172,14 @@ interface IMorphoBase {
address receiver
) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);
/// @notice Borrows `assets` or `shares` on behalf of `onBehalf` to `receiver`.
/// @dev Either `assets` or `shares` should be zero. Most usecases should rely on `assets` as an input so the caller
/// is guaranteed to borrow `assets` of tokens, but the possibility to mint a specific amount of shares is given for
/// full compatibility and precision.
/// @dev If the borrow of a market gets depleted, the borrow share price instantly resets to
/// `VIRTUAL_ASSETS`:`VIRTUAL_SHARES`.
/// @notice Borrows `assets` or `shares` on behalf of `onBehalf` and sends the assets to `receiver`.
/// @dev Either `assets` or `shares` should be zero. Most use cases should rely on `assets` as an input so the
/// caller is guaranteed to borrow `assets` of tokens, but the possibility to mint a specific amount of shares is
/// given for full compatibility and precision.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Borrowing a large amount can revert for overflow.
/// @dev Borrowing an amount of shares may lead to borrow fewer assets than expected due to slippage.
/// Consider using the `assets` parameter to avoid this.
/// @param marketParams The market to borrow assets from.
/// @param assets The amount of assets to borrow.
/// @param shares The amount of shares to mint.
@ -200,6 +201,7 @@ interface IMorphoBase {
/// @dev Repaying an amount corresponding to more shares than borrowed will revert for underflow.
/// @dev It is advised to use the `shares` input when repaying the full position to avoid reverts due to conversion
/// roundings between shares and assets.
/// @dev An attacker can front-run a repay with a small repay making the transaction revert for underflow.
/// @param marketParams The market to repay assets to.
/// @param assets The amount of assets to repay.
/// @param shares The amount of shares to burn.
@ -226,7 +228,7 @@ interface IMorphoBase {
function supplyCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, bytes memory data)
external;
/// @notice Withdraws `assets` of collateral on behalf of `onBehalf` to `receiver`.
/// @notice Withdraws `assets` of collateral on behalf of `onBehalf` and sends the assets to `receiver`.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Withdrawing an amount corresponding to more collateral than supplied will revert for underflow.
/// @param marketParams The market to withdraw collateral from.
@ -242,6 +244,7 @@ interface IMorphoBase {
/// @dev Either `seizedAssets` or `repaidShares` should be zero.
/// @dev Seizing more than the collateral balance will underflow and revert without any error message.
/// @dev Repaying more than the borrow balance will underflow and revert without any error message.
/// @dev An attacker can front-run a liquidation with a small repay making the transaction revert for underflow.
/// @param marketParams The market of the position.
/// @param borrower The owner of the position.
/// @param seizedAssets The amount of collateral to seize.

View File

@ -27,6 +27,9 @@ library ErrorsLib {
/// @notice Thrown when the market is already created.
string internal constant MARKET_ALREADY_CREATED = "market already created";
/// @notice Thrown when a token to transfer doesn't have code.
string internal constant NO_CODE = "no code";
/// @notice Thrown when the market is not created.
string internal constant MARKET_NOT_CREATED = "market not created";

View File

@ -35,9 +35,10 @@ library EventsLib {
event CreateMarket(Id indexed id, MarketParams marketParams);
/// @notice Emitted on supply of assets.
/// @dev Warning: `feeRecipient` receives some shares during interest accrual without any supply event emitted.
/// @param id The market id.
/// @param caller The caller.
/// @param onBehalf The address that received the supply.
/// @param onBehalf The owner of the modified position.
/// @param assets The amount of assets supplied.
/// @param shares The amount of shares minted.
event Supply(Id indexed id, address indexed caller, address indexed onBehalf, uint256 assets, uint256 shares);
@ -45,7 +46,7 @@ library EventsLib {
/// @notice Emitted on withdrawal of assets.
/// @param id The market id.
/// @param caller The caller.
/// @param onBehalf The address from which the assets were withdrawn.
/// @param onBehalf The owner of the modified position.
/// @param receiver The address that received the withdrawn assets.
/// @param assets The amount of assets withdrawn.
/// @param shares The amount of shares burned.
@ -61,7 +62,7 @@ library EventsLib {
/// @notice Emitted on borrow of assets.
/// @param id The market id.
/// @param caller The caller.
/// @param onBehalf The address from which the assets were borrowed.
/// @param onBehalf The owner of the modified position.
/// @param receiver The address that received the borrowed assets.
/// @param assets The amount of assets borrowed.
/// @param shares The amount of shares minted.
@ -77,7 +78,7 @@ library EventsLib {
/// @notice Emitted on repayment of assets.
/// @param id The market id.
/// @param caller The caller.
/// @param onBehalf The address for which the assets were repaid.
/// @param onBehalf The owner of the modified position.
/// @param assets The amount of assets repaid. May be 1 over the corresponding market's `totalBorrowAssets`.
/// @param shares The amount of shares burned.
event Repay(Id indexed id, address indexed caller, address indexed onBehalf, uint256 assets, uint256 shares);
@ -85,14 +86,14 @@ library EventsLib {
/// @notice Emitted on supply of collateral.
/// @param id The market id.
/// @param caller The caller.
/// @param onBehalf The address that received the collateral.
/// @param onBehalf The owner of the modified position.
/// @param assets The amount of collateral supplied.
event SupplyCollateral(Id indexed id, address indexed caller, address indexed onBehalf, uint256 assets);
/// @notice Emitted on withdrawal of collateral.
/// @param id The market id.
/// @param caller The caller.
/// @param onBehalf The address from which the collateral was withdrawn.
/// @param onBehalf The owner of the modified position.
/// @param receiver The address that received the withdrawn collateral.
/// @param assets The amount of collateral withdrawn.
event WithdrawCollateral(
@ -106,7 +107,8 @@ library EventsLib {
/// @param repaidAssets The amount of assets repaid. May be 1 over the corresponding market's `totalBorrowAssets`.
/// @param repaidShares The amount of shares burned.
/// @param seizedAssets The amount of collateral seized.
/// @param badDebtShares The amount of shares minted as bad debt.
/// @param badDebtAssets The amount of assets of bad debt realized.
/// @param badDebtShares The amount of borrow shares of bad debt realized.
event Liquidate(
Id indexed id,
address indexed caller,
@ -114,6 +116,7 @@ library EventsLib {
uint256 repaidAssets,
uint256 repaidShares,
uint256 seizedAssets,
uint256 badDebtAssets,
uint256 badDebtShares
);

View File

@ -15,18 +15,19 @@ interface IERC20Internal {
/// @custom:contact security@morpho.org
/// @notice Library to manage transfers of tokens, even if calls to the transfer or transferFrom functions are not
/// returning a boolean.
/// @dev It is the responsibility of the market creator to make sure that the address of the token has non-zero code.
library SafeTransferLib {
/// @dev Warning: It does not revert on `token` with no code.
function safeTransfer(IERC20 token, address to, uint256 value) internal {
require(address(token).code.length > 0, ErrorsLib.NO_CODE);
(bool success, bytes memory returndata) =
address(token).call(abi.encodeCall(IERC20Internal.transfer, (to, value)));
require(success, ErrorsLib.TRANSFER_REVERTED);
require(returndata.length == 0 || abi.decode(returndata, (bool)), ErrorsLib.TRANSFER_RETURNED_FALSE);
}
/// @dev Warning: It does not revert on `token` with no code.
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
require(address(token).code.length > 0, ErrorsLib.NO_CODE);
(bool success, bytes memory returndata) =
address(token).call(abi.encodeCall(IERC20Internal.transferFrom, (from, to, value)));
require(success, ErrorsLib.TRANSFER_FROM_REVERTED);

View File

@ -14,6 +14,9 @@ library SharesMathLib {
/// @dev The number of virtual shares has been chosen low enough to prevent overflows, and high enough to ensure
/// high precision computations.
/// @dev Virtual shares can never be redeemed for the assets they are entitled to, but it is assumed the share price
/// stays low enough not to inflate these assets to a significant value.
/// @dev Warning: The assets to which virtual borrow shares are entitled behave like unrealizable bad debt.
uint256 internal constant VIRTUAL_SHARES = 1e6;
/// @dev A number of virtual assets of 1 enforces a conversion rate between shares and assets when a market is

View File

@ -29,7 +29,7 @@ library UtilsLib {
return uint128(x);
}
/// @dev Returns max(x - y, 0).
/// @dev Returns max(0, x - y).
function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := mul(gt(x, y), sub(x, y))

View File

@ -36,13 +36,12 @@ library MorphoBalancesLib {
returns (uint256, uint256, uint256, uint256)
{
Id id = marketParams.id();
Market memory market = morpho.market(id);
uint256 elapsed = block.timestamp - market.lastUpdate;
// Skipped if elapsed == 0 of if totalBorrowAssets == 0 because interest would be null.
if (elapsed != 0 && market.totalBorrowAssets != 0) {
// Skipped if elapsed == 0 or totalBorrowAssets == 0 because interest would be null, or if irm == address(0).
if (elapsed != 0 && market.totalBorrowAssets != 0 && marketParams.irm != address(0)) {
uint256 borrowRate = IIrm(marketParams.irm).borrowRateView(marketParams, market);
uint256 interest = market.totalBorrowAssets.wMulDown(borrowRate.wTaylorCompounded(elapsed));
market.totalBorrowAssets += interest.toUint128();
@ -90,8 +89,8 @@ library MorphoBalancesLib {
/// @notice Returns the expected supply assets balance of `user` on a market after having accrued interest.
/// @dev Warning: Wrong for `feeRecipient` because their supply shares increase is not taken into account.
/// @dev Warning: Withdrawing a supply position using the expected assets balance can lead to a revert due to
/// conversion roundings between shares and assets.
/// @dev Warning: Withdrawing using the expected supply assets can lead to a revert due to conversion roundings from
/// assets to shares.
function expectedSupplyAssets(IMorpho morpho, MarketParams memory marketParams, address user)
internal
view
@ -105,8 +104,8 @@ library MorphoBalancesLib {
}
/// @notice Returns the expected borrow assets balance of `user` on a market after having accrued interest.
/// @dev Warning: repaying a borrow position using the expected assets balance can lead to a revert due to
/// conversion roundings between shares and assets.
/// @dev Warning: The expected balance is rounded up, so it may be greater than the market's expected total borrow
/// assets.
function expectedBorrowAssets(IMorpho morpho, MarketParams memory marketParams, address user)
internal
view