Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"lib/vault-v2/src/adapters/MorphoMarketV1AdapterFactory.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity 0.8.28;
import {MorphoMarketV1Adapter} from "./MorphoMarketV1Adapter.sol";
import {IMorphoMarketV1AdapterFactory} from "./interfaces/IMorphoMarketV1AdapterFactory.sol";
contract MorphoMarketV1AdapterFactory is IMorphoMarketV1AdapterFactory {
/* STORAGE */
mapping(address parentVault => mapping(address morpho => address)) public morphoMarketV1Adapter;
mapping(address account => bool) public isMorphoMarketV1Adapter;
/* FUNCTIONS */
function createMorphoMarketV1Adapter(address parentVault, address morpho) external returns (address) {
address _morphoMarketV1Adapter = address(new MorphoMarketV1Adapter{salt: bytes32(0)}(parentVault, morpho));
morphoMarketV1Adapter[parentVault][morpho] = _morphoMarketV1Adapter;
isMorphoMarketV1Adapter[_morphoMarketV1Adapter] = true;
emit CreateMorphoMarketV1Adapter(parentVault, morpho, _morphoMarketV1Adapter);
return _morphoMarketV1Adapter;
}
}
"
},
"lib/vault-v2/src/adapters/MorphoMarketV1Adapter.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity 0.8.28;
import {IMorpho, MarketParams, Id} from "../../lib/morpho-blue/src/interfaces/IMorpho.sol";
import {MorphoBalancesLib} from "../../lib/morpho-blue/src/libraries/periphery/MorphoBalancesLib.sol";
import {MarketParamsLib} from "../../lib/morpho-blue/src/libraries/MarketParamsLib.sol";
import {IVaultV2} from "../interfaces/IVaultV2.sol";
import {IERC20} from "../interfaces/IERC20.sol";
import {IMorphoMarketV1Adapter} from "./interfaces/IMorphoMarketV1Adapter.sol";
import {SafeERC20Lib} from "../libraries/SafeERC20Lib.sol";
/// @dev Morpho Market v1 is also known as Morpho Blue.
/// @dev This adapter must be used with Morpho Market v1 that are protected against inflation attacks with an initial
/// supply. Following resource is relevant: https://docs.openzeppelin.com/contracts/5.x/erc4626#inflation-attack.
/// @dev Must not be used with a Morpho Market v1 with an Irm that can re-enter the parent vault or the adapter.
/// @dev Rounding error losses on supply/withdraw are realizable.
/// @dev If expectedSupplyAssets reverts for a market of the marketParamsList, realAssets will revert and the vault will
/// not be able to accrueInterest.
/// @dev Upon interest accrual, the vault calls realAssets(). If there are too many markets, it could cause issues such
/// as expensive interactions, even DOS, because of the gas.
/// @dev Shouldn't be used alongside another adapter that re-uses the last id (abi.encode("this/marketParams",
/// address(this), marketParams)).
/// @dev Markets get removed from the marketParamsList when the allocation is zero, but it doesn't mean that the adapter
/// has zero shares on the market.
contract MorphoMarketV1Adapter is IMorphoMarketV1Adapter {
using MarketParamsLib for MarketParams;
/* IMMUTABLES */
address public immutable factory;
address public immutable parentVault;
address public immutable asset;
address public immutable morpho;
bytes32 public immutable adapterId;
/* STORAGE */
address public skimRecipient;
MarketParams[] public marketParamsList;
function marketParamsListLength() external view returns (uint256) {
return marketParamsList.length;
}
/* FUNCTIONS */
constructor(address _parentVault, address _morpho) {
factory = msg.sender;
parentVault = _parentVault;
morpho = _morpho;
asset = IVaultV2(_parentVault).asset();
adapterId = keccak256(abi.encode("this", address(this)));
SafeERC20Lib.safeApprove(asset, _morpho, type(uint256).max);
SafeERC20Lib.safeApprove(asset, _parentVault, type(uint256).max);
}
function setSkimRecipient(address newSkimRecipient) external {
require(msg.sender == IVaultV2(parentVault).owner(), NotAuthorized());
skimRecipient = newSkimRecipient;
emit SetSkimRecipient(newSkimRecipient);
}
/// @dev Skims the adapter's balance of `token` and sends it to `skimRecipient`.
/// @dev This is useful to handle rewards that the adapter has earned.
function skim(address token) external {
require(msg.sender == skimRecipient, NotAuthorized());
uint256 balance = IERC20(token).balanceOf(address(this));
SafeERC20Lib.safeTransfer(token, skimRecipient, balance);
emit Skim(token, balance);
}
/// @dev Does not log anything because the ids (logged in the parent vault) are enough.
/// @dev Returns the ids of the allocation and the change in allocation.
function allocate(bytes memory data, uint256 assets, bytes4, address) external returns (bytes32[] memory, int256) {
MarketParams memory marketParams = abi.decode(data, (MarketParams));
require(msg.sender == parentVault, NotAuthorized());
require(marketParams.loanToken == asset, LoanAssetMismatch());
if (assets > 0) IMorpho(morpho).supply(marketParams, assets, 0, address(this), hex"");
uint256 oldAllocation = allocation(marketParams);
uint256 newAllocation = MorphoBalancesLib.expectedSupplyAssets(IMorpho(morpho), marketParams, address(this));
updateList(marketParams, oldAllocation, newAllocation);
// Safe casts because Market v1 bounds the total supply of the underlying token, and allocation is less than the
// max total assets of the vault.
return (ids(marketParams), int256(newAllocation) - int256(oldAllocation));
}
/// @dev Does not log anything because the ids (logged in the parent vault) are enough.
/// @dev Returns the ids of the deallocation and the change in allocation.
function deallocate(bytes memory data, uint256 assets, bytes4, address)
external
returns (bytes32[] memory, int256)
{
MarketParams memory marketParams = abi.decode(data, (MarketParams));
require(msg.sender == parentVault, NotAuthorized());
require(marketParams.loanToken == asset, LoanAssetMismatch());
if (assets > 0) IMorpho(morpho).withdraw(marketParams, assets, 0, address(this), address(this));
uint256 oldAllocation = allocation(marketParams);
uint256 newAllocation = MorphoBalancesLib.expectedSupplyAssets(IMorpho(morpho), marketParams, address(this));
updateList(marketParams, oldAllocation, newAllocation);
// Safe casts because Market v1 bounds the total supply of the underlying token, and allocation is less than the
// max total assets of the vault.
return (ids(marketParams), int256(newAllocation) - int256(oldAllocation));
}
function updateList(MarketParams memory marketParams, uint256 oldAllocation, uint256 newAllocation) internal {
if (oldAllocation > 0 && newAllocation == 0) {
Id marketId = marketParams.id();
for (uint256 i = 0; i < marketParamsList.length; i++) {
if (Id.unwrap(marketParamsList[i].id()) == Id.unwrap(marketId)) {
marketParamsList[i] = marketParamsList[marketParamsList.length - 1];
marketParamsList.pop();
break;
}
}
} else if (oldAllocation == 0 && newAllocation > 0) {
marketParamsList.push(marketParams);
}
}
function allocation(MarketParams memory marketParams) public view returns (uint256) {
return IVaultV2(parentVault).allocation(keccak256(abi.encode("this/marketParams", address(this), marketParams)));
}
/// @dev Returns adapter's ids.
function ids(MarketParams memory marketParams) public view returns (bytes32[] memory) {
bytes32[] memory ids_ = new bytes32[](3);
ids_[0] = adapterId;
ids_[1] = keccak256(abi.encode("collateralToken", marketParams.collateralToken));
ids_[2] = keccak256(abi.encode("this/marketParams", address(this), marketParams));
return ids_;
}
function realAssets() external view returns (uint256) {
uint256 _realAssets = 0;
for (uint256 i = 0; i < marketParamsList.length; i++) {
_realAssets += MorphoBalancesLib.expectedSupplyAssets(IMorpho(morpho), marketParamsList[i], address(this));
}
return _realAssets;
}
}
"
},
"lib/vault-v2/src/adapters/interfaces/IMorphoMarketV1AdapterFactory.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity >=0.5.0;
interface IMorphoMarketV1AdapterFactory {
/* EVENTS */
event CreateMorphoMarketV1Adapter(
address indexed parentVault, address indexed morpho, address indexed morphoMarketV1Adapter
);
/* FUNCTIONS */
function morphoMarketV1Adapter(address parentVault, address morpho) external view returns (address);
function isMorphoMarketV1Adapter(address account) external view returns (bool);
function createMorphoMarketV1Adapter(address parentVault, address morpho) external returns (address);
}
"
},
"lib/vault-v2/lib/morpho-blue/src/interfaces/IMorpho.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
type Id is bytes32;
struct MarketParams {
address loanToken;
address collateralToken;
address oracle;
address irm;
uint256 lltv;
}
/// @dev Warning: For `feeRecipient`, `supplyShares` does not contain the accrued shares since the last interest
/// accrual.
struct Position {
uint256 supplyShares;
uint128 borrowShares;
uint128 collateral;
}
/// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `totalSupplyShares` does not contain the additional shares accrued by `feeRecipient` since the last
/// interest accrual.
struct Market {
uint128 totalSupplyAssets;
uint128 totalSupplyShares;
uint128 totalBorrowAssets;
uint128 totalBorrowShares;
uint128 lastUpdate;
uint128 fee;
}
struct Authorization {
address authorizer;
address authorized;
bool isAuthorized;
uint256 nonce;
uint256 deadline;
}
struct Signature {
uint8 v;
bytes32 r;
bytes32 s;
}
/// @dev This interface is used for factorizing IMorphoStaticTyping and IMorpho.
/// @dev Consider using the IMorpho interface instead of this one.
interface IMorphoBase {
/// @notice The EIP-712 domain separator.
/// @dev Warning: Every EIP-712 signed message based on this domain separator can be reused on chains sharing the
/// same chain id and on forks because the domain separator would be the same.
function DOMAIN_SEPARATOR() external view returns (bytes32);
/// @notice The owner of the contract.
/// @dev It has the power to change the owner.
/// @dev It has the power to set fees on markets and set the fee recipient.
/// @dev It has the power to enable but not disable IRMs and LLTVs.
function owner() external view returns (address);
/// @notice The fee recipient of all markets.
/// @dev The recipient receives the fees of a given market through a supply position on that market.
function feeRecipient() external view returns (address);
/// @notice Whether the `irm` is enabled.
function isIrmEnabled(address irm) external view returns (bool);
/// @notice Whether the `lltv` is enabled.
function isLltvEnabled(uint256 lltv) external view returns (bool);
/// @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);
/// @notice The `authorizer`'s current nonce. Used to prevent replay attacks with EIP-712 signatures.
function nonce(address authorizer) external view returns (uint256);
/// @notice Sets `newOwner` as `owner` of the contract.
/// @dev Warning: No two-step transfer ownership.
/// @dev Warning: The owner can be set to the zero address.
function setOwner(address newOwner) external;
/// @notice Enables `irm` as a possible IRM for market creation.
/// @dev Warning: It is not possible to disable an IRM.
function enableIrm(address irm) external;
/// @notice Enables `lltv` as a possible LLTV for market creation.
/// @dev Warning: It is not possible to disable a LLTV.
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;
/// @notice Sets `newFeeRecipient` as `feeRecipient` of the fee.
/// @dev Warning: If the fee recipient is set to the zero address, fees will accrue there and will be lost.
/// @dev Modifying the fee recipient will allow the new recipient to claim any pending fees not yet accrued. To
/// ensure that the current recipient receives all due fees, accrue interest manually prior to making any changes.
function setFeeRecipient(address newFeeRecipient) external;
/// @notice Creates the market `marketParams`.
/// @dev Here is the list of assumptions on the market's dependencies (tokens, IRM and oracle) that guarantees
/// Morpho behaves as expected:
/// - The token should be ERC-20 compliant, except that it can omit return values on `transfer` and `transferFrom`.
/// - The token balance of Morpho should only decrease on `transfer` and `transferFrom`. In particular, tokens with
/// burn functions are not supported.
/// - The token should not re-enter Morpho on `transfer` nor `transferFrom`.
/// - The token balance of the sender (resp. receiver) should decrease (resp. increase) by exactly the given amount
/// on `transfer` and `transferFrom`. In particular, tokens with fees on transfer are not supported.
/// - The IRM should not re-enter Morpho.
/// - The oracle should return a price with the correct scaling.
/// - The oracle price should not be able to change instantly such that the new price is less than the old price
/// multiplied by LLTV*LIF. In particular, if the loan asset is a vault that can receive donations, the oracle
/// should not price its shares using the AUM.
/// @dev Here is a list of assumptions on the market's dependencies which, if broken, could break Morpho's liveness
/// properties (funds could get stuck):
/// - The token should not revert on `transfer` and `transferFrom` if balances and approvals are right.
/// - The amount of assets supplied and borrowed should not go above ~1e35 (otherwise the computation of
/// `toSharesUp` and `toSharesDown` can overflow).
/// - The IRM should not revert on `borrowRate`.
/// - The IRM should not return a very high borrow rate (otherwise the computation of `interest` in
/// `_accrueInterest` can overflow).
/// - The oracle should not revert `price`.
/// - The oracle should not return a very high price (otherwise the computation of `maxBorrow` in `_isHealthy` or of
/// `assetsRepaid` in `liquidate` can overflow).
/// @dev The borrow share price of a market with less than 1e4 assets borrowed can be decreased by manipulations, to
/// the point where `totalBorrowShares` is very large and borrowing overflows.
function createMarket(MarketParams memory marketParams) external;
/// @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 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.
/// @param onBehalf The address that will own the increased supply position.
/// @param data Arbitrary data to pass to the `onMorphoSupply` callback. Pass empty data if not needed.
/// @return assetsSupplied The amount of assets supplied.
/// @return sharesSupplied The amount of shares minted.
function supply(
MarketParams memory marketParams,
uint256 assets,
uint256 shares,
address onBehalf,
bytes memory data
) external returns (uint256 assetsSupplied, uint256 sharesSupplied);
/// @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.
/// @dev It is advised to use the `shares` input when withdrawing the full position to avoid reverts due to
/// conversion roundings between shares and assets.
/// @param marketParams The market to withdraw assets from.
/// @param assets The amount of assets to withdraw.
/// @param shares The amount of shares to burn.
/// @param onBehalf The address of the owner of the supply position.
/// @param receiver The address that will receive the withdrawn assets.
/// @return assetsWithdrawn The amount of assets withdrawn.
/// @return sharesWithdrawn The amount of shares burned.
function withdraw(
MarketParams memory marketParams,
uint256 assets,
uint256 shares,
address onBehalf,
address receiver
) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);
/// @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.
/// @param onBehalf The address that will own the increased borrow position.
/// @param receiver The address that will receive the borrowed assets.
/// @return assetsBorrowed The amount of assets borrowed.
/// @return sharesBorrowed The amount of shares minted.
function borrow(
MarketParams memory marketParams,
uint256 assets,
uint256 shares,
address onBehalf,
address receiver
) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed);
/// @notice Repays `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's
/// `onMorphoRepay` function with the given `data`.
/// @dev Either `assets` or `shares` should be zero. To repay max, pass the `shares`'s balance of `onBehalf`.
/// @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.
/// @param onBehalf The address of the owner of the debt position.
/// @param data Arbitrary data to pass to the `onMorphoRepay` callback. Pass empty data if not needed.
/// @return assetsRepaid The amount of assets repaid.
/// @return sharesRepaid The amount of shares burned.
function repay(
MarketParams memory marketParams,
uint256 assets,
uint256 shares,
address onBehalf,
bytes memory data
) external returns (uint256 assetsRepaid, uint256 sharesRepaid);
/// @notice Supplies `assets` of collateral on behalf of `onBehalf`, optionally calling back the caller's
/// `onMorphoSupplyCollateral` function with the given `data`.
/// @dev Interest are not accrued since it's not required and it saves gas.
/// @dev Supplying a large amount can revert for overflow.
/// @param marketParams The market to supply collateral to.
/// @param assets The amount of collateral to supply.
/// @param onBehalf The address that will own the increased collateral position.
/// @param data Arbitrary data to pass to the `onMorphoSupplyCollateral` callback. Pass empty data if not needed.
function supplyCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, bytes memory data)
external;
/// @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.
/// @param assets The amount of collateral to withdraw.
/// @param onBehalf The address of the owner of the collateral position.
/// @param receiver The address that will receive the collateral assets.
function withdrawCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, address receiver)
external;
/// @notice Liquidates the given `repaidShares` of debt asset or seize the given `seizedAssets` of collateral on the
/// given market `marketParams` of the given `borrower`'s position, optionally calling back the caller's
/// `onMorphoLiquidate` function with the given `data`.
/// @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.
/// @param repaidShares The amount of shares to repay.
/// @param data Arbitrary data to pass to the `onMorphoLiquidate` callback. Pass empty data if not needed.
/// @return The amount of assets seized.
/// @return The amount of assets repaid.
function liquidate(
MarketParams memory marketParams,
address borrower,
uint256 seizedAssets,
uint256 repaidShares,
bytes memory data
) external returns (uint256, uint256);
/// @notice Executes a flash loan.
/// @dev Flash loans have access to the whole balance of the contract (the liquidity and deposited collateral of all
/// markets combined, plus donations).
/// @dev Warning: Not ERC-3156 compliant but compatibility is easily reached:
/// - `flashFee` is zero.
/// - `maxFlashLoan` is the token's balance of this contract.
/// - The receiver of `assets` is the caller.
/// @param token The token to flash loan.
/// @param assets The amount of assets to flash loan.
/// @param data Arbitrary data to pass to the `onMorphoFlashLoan` callback.
function flashLoan(address token, uint256 assets, bytes calldata data) external;
/// @notice Sets the authorization for `authorized` to manage `msg.sender`'s positions.
/// @param authorized The authorized address.
/// @param newIsAuthorized The new authorization status.
function setAuthorization(address authorized, bool newIsAuthorized) external;
/// @notice Sets the authorization for `authorization.authorized` to manage `authorization.authorizer`'s positions.
/// @dev Warning: Reverts if the signature has already been submitted.
/// @dev The signature is malleable, but it has no impact on the security here.
/// @dev The nonce is passed as argument to be able to revert with a different error message.
/// @param authorization The `Authorization` struct.
/// @param signature The signature.
function setAuthorizationWithSig(Authorization calldata authorization, Signature calldata signature) external;
/// @notice Accrues interest for the given market `marketParams`.
function accrueInterest(MarketParams memory marketParams) external;
/// @notice Returns the data stored on the different `slots`.
function extSloads(bytes32[] memory slots) external view returns (bytes32[] memory);
}
/// @dev This interface is inherited by Morpho so that function signatures are checked by the compiler.
/// @dev Consider using the IMorpho interface instead of this one.
interface IMorphoStaticTyping is IMorphoBase {
/// @notice The state of the position of `user` on the market corresponding to `id`.
/// @dev Warning: For `feeRecipient`, `supplyShares` does not contain the accrued shares since the last interest
/// accrual.
function position(Id id, address user)
external
view
returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral);
/// @notice The state of the market corresponding to `id`.
/// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `totalSupplyShares` does not contain the accrued shares by `feeRecipient` since the last interest
/// accrual.
function market(Id id)
external
view
returns (
uint128 totalSupplyAssets,
uint128 totalSupplyShares,
uint128 totalBorrowAssets,
uint128 totalBorrowShares,
uint128 lastUpdate,
uint128 fee
);
/// @notice The market params corresponding to `id`.
/// @dev This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer
/// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.
function idToMarketParams(Id id)
external
view
returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv);
}
/// @title IMorpho
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @dev Use this interface for Morpho to have access to all the functions with the appropriate function signatures.
interface IMorpho is IMorphoBase {
/// @notice The state of the position of `user` on the market corresponding to `id`.
/// @dev Warning: For `feeRecipient`, `p.supplyShares` does not contain the accrued shares since the last interest
/// accrual.
function position(Id id, address user) external view returns (Position memory p);
/// @notice The state of the market corresponding to `id`.
/// @dev Warning: `m.totalSupplyAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `m.totalBorrowAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `m.totalSupplyShares` does not contain the accrued shares by `feeRecipient` since the last
/// interest accrual.
function market(Id id) external view returns (Market memory m);
/// @notice The market params corresponding to `id`.
/// @dev This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer
/// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.
function idToMarketParams(Id id) external view returns (MarketParams memory);
}
"
},
"lib/vault-v2/lib/morpho-blue/src/libraries/periphery/MorphoBalancesLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {Id, MarketParams, Market, IMorpho} from "../../interfaces/IMorpho.sol";
import {IIrm} from "../../interfaces/IIrm.sol";
import {MathLib} from "../MathLib.sol";
import {UtilsLib} from "../UtilsLib.sol";
import {MorphoLib} from "./MorphoLib.sol";
import {SharesMathLib} from "../SharesMathLib.sol";
import {MarketParamsLib} from "../MarketParamsLib.sol";
/// @title MorphoBalancesLib
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Helper library exposing getters with the expected value after interest accrual.
/// @dev This library is not used in Morpho itself and is intended to be used by integrators.
/// @dev The getter to retrieve the expected total borrow shares is not exposed because interest accrual does not apply
/// to it. The value can be queried directly on Morpho using `totalBorrowShares`.
library MorphoBalancesLib {
using MathLib for uint256;
using MathLib for uint128;
using UtilsLib for uint256;
using MorphoLib for IMorpho;
using SharesMathLib for uint256;
using MarketParamsLib for MarketParams;
/// @notice Returns the expected market balances of a market after having accrued interest.
/// @return The expected total supply assets.
/// @return The expected total supply shares.
/// @return The expected total borrow assets.
/// @return The expected total borrow shares.
function expectedMarketBalances(IMorpho morpho, MarketParams memory marketParams)
internal
view
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 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();
market.totalSupplyAssets += interest.toUint128();
if (market.fee != 0) {
uint256 feeAmount = interest.wMulDown(market.fee);
// The fee amount is subtracted from the total supply in this calculation to compensate for the fact
// that total supply is already updated.
uint256 feeShares =
feeAmount.toSharesDown(market.totalSupplyAssets - feeAmount, market.totalSupplyShares);
market.totalSupplyShares += feeShares.toUint128();
}
}
return (market.totalSupplyAssets, market.totalSupplyShares, market.totalBorrowAssets, market.totalBorrowShares);
}
/// @notice Returns the expected total supply assets of a market after having accrued interest.
function expectedTotalSupplyAssets(IMorpho morpho, MarketParams memory marketParams)
internal
view
returns (uint256 totalSupplyAssets)
{
(totalSupplyAssets,,,) = expectedMarketBalances(morpho, marketParams);
}
/// @notice Returns the expected total borrow assets of a market after having accrued interest.
function expectedTotalBorrowAssets(IMorpho morpho, MarketParams memory marketParams)
internal
view
returns (uint256 totalBorrowAssets)
{
(,, totalBorrowAssets,) = expectedMarketBalances(morpho, marketParams);
}
/// @notice Returns the expected total supply shares of a market after having accrued interest.
function expectedTotalSupplyShares(IMorpho morpho, MarketParams memory marketParams)
internal
view
returns (uint256 totalSupplyShares)
{
(, totalSupplyShares,,) = expectedMarketBalances(morpho, marketParams);
}
/// @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 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
returns (uint256)
{
Id id = marketParams.id();
uint256 supplyShares = morpho.supplyShares(id, user);
(uint256 totalSupplyAssets, uint256 totalSupplyShares,,) = expectedMarketBalances(morpho, marketParams);
return supplyShares.toAssetsDown(totalSupplyAssets, totalSupplyShares);
}
/// @notice Returns the expected borrow assets balance of `user` on a market after having accrued interest.
/// @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
returns (uint256)
{
Id id = marketParams.id();
uint256 borrowShares = morpho.borrowShares(id, user);
(,, uint256 totalBorrowAssets, uint256 totalBorrowShares) = expectedMarketBalances(morpho, marketParams);
return borrowShares.toAssetsUp(totalBorrowAssets, totalBorrowShares);
}
}
"
},
"lib/vault-v2/lib/morpho-blue/src/libraries/MarketParamsLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {Id, MarketParams} from "../interfaces/IMorpho.sol";
/// @title MarketParamsLib
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Library to convert a market to its id.
library MarketParamsLib {
/// @notice The length of the data used to compute the id of a market.
/// @dev The length is 5 * 32 because `MarketParams` has 5 variables of 32 bytes each.
uint256 internal constant MARKET_PARAMS_BYTES_LENGTH = 5 * 32;
/// @notice Returns the id of the market `marketParams`.
function id(MarketParams memory marketParams) internal pure returns (Id marketParamsId) {
assembly ("memory-safe") {
marketParamsId := keccak256(marketParams, MARKET_PARAMS_BYTES_LENGTH)
}
}
}
"
},
"lib/vault-v2/src/interfaces/IVaultV2.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity >=0.5.0;
import {IERC20} from "./IERC20.sol";
import {IERC4626} from "./IERC4626.sol";
import {IERC2612} from "./IERC2612.sol";
struct Caps {
uint256 allocation;
uint128 absoluteCap;
uint128 relativeCap;
}
interface IVaultV2 is IERC4626, IERC2612 {
// State variables
function virtualShares() external view returns (uint256);
function owner() external view returns (address);
function curator() external view returns (address);
function receiveSharesGate() external view returns (address);
function sendSharesGate() external view returns (address);
function receiveAssetsGate() external view returns (address);
function sendAssetsGate() external view returns (address);
function adapterRegistry() external view returns (address);
function isSentinel(address account) external view returns (bool);
function isAllocator(address account) external view returns (bool);
function firstTotalAssets() external view returns (uint256);
function _totalAssets() external view returns (uint128);
function lastUpdate() external view returns (uint64);
function maxRate() external view returns (uint64);
function adapters(uint256 index) external view returns (address);
function adaptersLength() external view returns (uint256);
function isAdapter(address account) external view returns (bool);
function allocation(bytes32 id) external view returns (uint256);
function absoluteCap(bytes32 id) external view returns (uint256);
function relativeCap(bytes32 id) external view returns (uint256);
function forceDeallocatePenalty(address adapter) external view returns (uint256);
function liquidityAdapter() external view returns (address);
function liquidityData() external view returns (bytes memory);
function timelock(bytes4 selector) external view returns (uint256);
function executableAt(bytes memory data) external view returns (uint256);
function pendingCount(bytes4 selector) external view returns (uint256);
function performanceFee() external view returns (uint96);
function performanceFeeRecipient() external view returns (address);
function managementFee() external view returns (uint96);
function managementFeeRecipient() external view returns (address);
// Gating
function canSendShares(address account) external view returns (bool);
function canReceiveShares(address account) external view returns (bool);
function canSendAssets(address account) external view returns (bool);
function canReceiveAssets(address account) external view returns (bool);
// Multicall
function multicall(bytes[] memory data) external;
// Owner functions
function setOwner(address newOwner) external;
function setCurator(address newCurator) external;
function setIsSentinel(address account, bool isSentinel) external;
function setName(string memory newName) external;
function setSymbol(string memory newSymbol) external;
// Timelocks for curator functions
function submit(bytes memory data) external;
function revoke(bytes memory data) external;
// Curator functions
function setIsAllocator(address account, bool newIsAllocator) external;
function setReceiveSharesGate(address newReceiveSharesGate) external;
function setSendSharesGate(address newSendSharesGate) external;
function setReceiveAssetsGate(address newReceiveAssetsGate) external;
function setSendAssetsGate(address newSendAssetsGate) external;
function setAdapterRegistry(address newAdapterRegistry) external;
function addAdapter(address account) external;
function removeAdapter(address account) external;
function increaseTimelock(bytes4 selector, uint256 newDuration) external;
function decreaseTimelock(bytes4 selector, uint256 newDuration) external;
function setPerformanceFee(uint256 newPerformanceFee) external;
function setManagementFee(uint256 newManagementFee) external;
function setPerformanceFeeRecipient(address newPerformanceFeeRecipient) external;
function setManagementFeeRecipient(address newManagementFeeRecipient) external;
function increaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external;
function decreaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external;
function increaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external;
function decreaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external;
function setMaxRate(uint256 newMaxRate) external;
function setForceDeallocatePenalty(address adapter, uint256 newForceDeallocatePenalty) external;
// Allocator functions
function allocate(address adapter, bytes memory data, uint256 assets) external;
function deallocate(address adapter, bytes memory data, uint256 assets) external;
function setLiquidityAdapterAndData(address newLiquidityAdapter, bytes memory newLiquidityData) external;
// Exchange rate
function accrueInterest() external;
function accrueInterestView()
external
view
returns (uint256 newTotalAssets, uint256 performanceFeeShares, uint256 managementFeeShares);
// Force deallocate
function forceDeallocate(address adapter, bytes memory data, uint256 assets, address onBehalf)
external
returns (uint256 penaltyShares);
}
"
},
"lib/vault-v2/src/interfaces/IERC20.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity >=0.5.0;
interface IERC20 {
function decimals() external view returns (uint8);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 shares) external returns (bool success);
function transferFrom(address from, address to, uint256 shares) external returns (bool success);
function approve(address spender, uint256 shares) external returns (bool success);
function allowance(address owner, address spender) external view returns (uint256);
}
"
},
"lib/vault-v2/src/adapters/interfaces/IMorphoMarketV1Adapter.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity >=0.5.0;
import {IAdapter} from "../../interfaces/IAdapter.sol";
import {Id, MarketParams} from "../../../lib/morpho-blue/src/interfaces/IMorpho.sol";
interface IMorphoMarketV1Adapter is IAdapter {
/* EVENTS */
event SetSkimRecipient(address indexed newSkimRecipient);
event Skim(address indexed token, uint256 assets);
/* ERRORS */
error LoanAssetMismatch();
error NotAuthorized();
/* FUNCTIONS */
function factory() external view returns (address);
function parentVault() external view returns (address);
function asset() external view returns (address);
function morpho() external view returns (address);
function adapterId() external view returns (bytes32);
function skimRecipient() external view returns (address);
function marketParamsList(uint256 index) external view returns (address, address, address, address, uint256);
function marketParamsListLength() external view returns (uint256);
function allocation(MarketParams memory marketParams) external view returns (uint256);
function ids(MarketParams memory marketParams) external view returns (bytes32[] memory);
function setSkimRecipient(address newSkimRecipient) external;
function skim(address token) external;
}
"
},
"lib/vault-v2/src/libraries/SafeERC20Lib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity ^0.8.0;
import {IERC20} from "../interfaces/IERC20.sol";
import {ErrorsLib} from "./ErrorsLib.sol";
library SafeERC20Lib {
function safeTransfer(address token, address to, uint256 value) internal {
require(token.code.length > 0, ErrorsLib.NoCode());
(bool success, bytes memory returndata) = token.call(abi.encodeCall(IERC20.transfer, (to, value)));
require(success, ErrorsLib.TransferReverted());
require(returndata.length == 0 || abi.decode(returndata, (bool)), ErrorsLib.TransferReturnedFalse());
}
function safeTransferFrom(address token, address from, address to, uint256 value) internal {
require(token.code.length > 0, ErrorsLib.NoCode());
(bool success, bytes memory returndata) = token.call(abi.encodeCall(IERC20.transferFrom, (from, to, value)));
require(success, ErrorsLib.TransferFromReverted());
require(returndata.length == 0 || abi.decode(returndata, (bool)), ErrorsLib.TransferFromReturnedFalse());
}
function safeApprove(address token, address spender, uint256 value) internal {
require(token.code.length > 0, ErrorsLib.NoCode());
(bool success, bytes memory returndata) = token.call(abi.encodeCall(IERC20.approve, (spender, value)));
require(success, ErrorsLib.ApproveReverted());
require(returndata.length == 0 || abi.decode(returndata, (bool)), ErrorsLib.ApproveReturnedFalse());
}
}
"
},
"lib/vault-v2/lib/morpho-blue/src/interfaces/IIrm.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
import {MarketParams, Market} from "./IMorpho.sol";
/// @title IIrm
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Interface that Interest Rate Models (IRMs) used by Morpho must implement.
interface IIrm {
/// @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 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);
}
"
},
"lib/vault-v2/lib/morpho-blue/src/libraries/MathLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
uint256 constant WAD = 1e18;
/// @title MathLib
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Library to manage fixed-point arithmetic.
library MathLib {
/// @dev Returns (`x` * `y`) / `WAD` rounded down.
function wMulDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, y, WAD);
}
/// @dev Returns (`x` * `WAD`) / `y` rounded down.
function wDivDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, WAD, y);
}
/// @dev Returns (`x` * `WAD`) / `y` rounded up.
function wDivUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, WAD, y);
}
/// @dev Returns (`x` * `y`) / `d` rounded down.
function mulDivDown(uint256 x, uint256 y, uint256 d) internal pure returns (uint256) {
return (x * y) / d;
}
/// @dev Returns (`x` * `y`) / `d` rounded up.
function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256) {
return (x * y + (d - 1)) / d;
}
/// @dev Returns the sum of the first three non-zero terms of a Taylor expansion of e^(nx) - 1, to approximate a
/// continuous compound interest rate.
function wTaylorCompounded(uint256 x, uint256 n) internal pure returns (uint256) {
uint256 firstTerm = x * n;
uint256 secondTerm = mulDivDown(firstTerm, firstTerm, 2 * WAD);
uint256 thirdTerm = mulDivDown(secondTerm, firstTerm, 3 * WAD);
return firstTerm + secondTerm + thirdTerm;
}
}
"
},
"lib/vault-v2/lib/morpho-blue/src/libraries/UtilsLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {ErrorsLib} from "../libraries/ErrorsLib.sol";
/// @title UtilsLib
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Library exposing helpers.
/// @dev Inspired by https://github.com/morpho-org/morpho-utils.
library UtilsLib {
/// @dev Returns true if there is exactly one zero among `x` and `y`.
function exactlyOneZero(uint256 x, uint256 y) internal pure returns (bool z) {
assembly {
z := xor(iszero(x), iszero(y))
}
}
/// @dev Returns the min of `x` and `y`.
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := xor(x, mul(xor(x, y), lt(y, x)))
}
}
/// @dev Returns `x` safely cast to uint128.
function toUint128(uint256 x) internal pure returns (uint128) {
require(x <= type(uint128).max, ErrorsLib.MAX_UINT128_EXCEEDED);
return uint128(x);
}
/// @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))
}
}
}
"
},
"lib/vault-v2/lib/morpho-blue/src/libraries/periphery/MorphoLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {IMorpho, Id} from "../../interfaces/IMorpho.sol";
import {MorphoStorageLib} from "./MorphoStorageLib.sol";
/// @title MorphoLib
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Helper library to access Morpho storage variables.
/// @dev Warning: Supply and borrow getters may return outdated values that do not include accrued interest.
library MorphoLib {
function supplyShares(IMorpho morpho, Id id, address user) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.positionSupplySharesSlot(id, user));
return uint256(morpho.extSloads(slot)[0]);
}
function borrowShares(IMorpho morpho, Id id, address user) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.positionBorrowSharesAndCollateralSlot(id, user));
return uint128(uint256(morpho.extSloads(slot)[0]));
}
function collateral(IMorpho morpho, Id id, address user) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.positionBorrowSharesAndCollateralSlot(id, user));
return uint256(morpho.extSloads(slot)[0] >> 128);
}
function totalSupplyAssets(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketTotalSupplyAssetsAndSharesSlot(id));
return uint128(uint256(morpho.extSloads(slot)[0]));
}
function totalSupplyShares(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketTotalSupplyAssetsAndSharesSlot(id));
return uint256(morpho.extSloads(slot)[0] >> 128);
}
function totalBorrowAssets(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketTotalBorrowAssetsAndSharesSlot(id));
return uint128(uint256(morpho.extSloads(slot)[0]));
}
function totalBorrowShares(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketTotalBorrowAssetsAndSharesSlot(id));
return uint256(morpho.extSloads(slot)[0] >> 128);
}
function lastUpdate(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketLastUpdateAndFeeSlot(id));
return uint128(uint256(morpho.extSloads(slot)[0]));
}
function fee(IMorpho morpho, Id id) internal view returns (uint256) {
bytes32[] memory slot = _array(MorphoStorageLib.marketLastUpdateAndFeeSlot(id));
return uint256(morpho.extSloads(slot)[0] >> 128);
}
function _array(bytes32 x) private pure returns (bytes32[] memory) {
bytes32[] memory res = new bytes32[](1);
res[0] = x;
return res;
}
}
"
},
"lib/vault-v2/lib/morpho-blue/src/libraries/SharesMathLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {MathLib} from "./MathLib.sol";
/// @title SharesMathLib
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Shares management library.
/// @dev This implementation mitigates share price manipulations, using OpenZeppelin's method of virtual shares:
/// https://docs.openzeppelin.com/contracts/4.x/erc4626#inflation-attack.
library SharesMathLib {
using MathLib for uint256;
/// @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
/// empty.
uint256 internal constant VIRTUAL_ASSETS = 1;
/// @dev Calculates the value of `assets` quoted in shares, rounding down.
function toSharesDown(uint256 assets, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {
return assets.mulDivDown(totalShares + VIRTUAL_SHARES, totalAssets + VIRTUAL_ASSETS);
}
/// @dev Calculates the value of `shares` quoted in assets, rounding down.
function toAssetsDown(uint256 shares, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {
return shares.mulDivDown(totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES);
}
/// @dev Calculates the value of `assets` quoted in shares, rounding up.
function toSharesUp(uint256 assets, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {
return assets.mulDivUp(totalShares + VIRTUAL_SHARES, totalAssets + VIRTUAL_ASSETS);
}
/// @dev Calculates the value of `shares` quoted in assets, rounding up.
function toAssetsUp(uint256 shares, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {
return shares.mulDivUp(totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES);
}
}
"
},
"lib/vault-v2/src/interfaces/IERC4626.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity >=0.5.0;
import {IERC20} from "./IERC20.sol";
interface IERC4626 is IERC20 {
function asset() external view returns (address);
function totalAssets() external view returns (uint256);
function convertToAssets(uint256 shares) external view returns (uint256 assets);
function convertToShares(uint256 assets) external view returns (uint256 shares);
function deposit(uint256 assets, address onBehalf) external returns (uint256 shares);
function mint(uint256 shares, address onBehalf) external returns (uint256 assets);
function withdraw(uint256 assets, address onBehalf, address receiver) external returns (uint256 shares);
function redeem(uint256 shares, address onBehalf, address receiver) external returns (uint256 assets);
function previewDeposit(uint256 assets) external view returns (uint256 shares);
function previewMint(uint256 shares) external view returns (uint256 assets);
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
function previewRedeem(uint256 shares) external view returns (uint256 assets);
function maxDeposit(address onBehalf) external view returns (uint256 assets);
function maxMint(address onBehalf) external view returns (uint256 shares);
function maxWithdraw(address onBehalf) external view returns (uint256 assets);
function maxRedeem(address onBehalf) external view returns (uint256 shares);
}
"
},
"lib/vault-v2/src/interfaces/IERC2612.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity >=0.5.0;
interface IERC2612 {
function permit(address owner, address spender, uint256 shares, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
"
},
"lib/vault-v2/src/interfaces/IAdapter.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity >=0.5.0;
/// @dev See VaultV2 NatSpec comments for more details on adapter's spec.
interface IAdapter {
/// @dev Returns the market' ids and the change in assets on this market.
function allocate(bytes memory data, uint256 assets, bytes4 selector, address sender)
external
returns (bytes32[] memory ids, int256 change);
/// @dev Returns the market' ids and the change in assets on this market.
function deallocate(bytes memory data, uint256 assets, bytes4 selector, address sender)
external
returns (bytes32[] memory ids, int256 change);
/// @dev Returns the current value of the investments of the adapter (in underlying asset).
function realAssets() external view returns (uint256 assets);
}
"
},
"lib/vault-v2/src/libraries/ErrorsLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2025 Morpho Association
pragma solidity ^0.8.0;
library ErrorsLib {
error AbsoluteCapExceeded();
error AbsoluteCapNotDecreasing();
error AbsoluteCapNotIncreasing();
error ApproveReturnedFalse();
error ApproveReverted();
error CannotReceiveShares();
error CannotReceiveAssets();
error CannotSendShares();
error CannotSendAssets();
error CapExceeded();
error CastOverflow();
error DataAlreadyPending();
error DataNotTimelocked();
error FeeInvariantBroken();
error FeeTooHigh();
error InvalidSigner();
error MaxRateTooHigh();
error NoCode();
error NotAdapter();
error NotInAdapterRegistry();
error PenaltyTooHigh();
error PermitDeadlineExpired();
error RelativeCapAboveOne();
error RelativeCapExceeded();
error RelativeCapNotDecreasing();
error RelativeCapNotIncreasing();
error AutomaticallyTimelocked();
error TimelockNotDecreasing();
error TimelockNotExpired();
error TimelockNotIncreasing();
error TransferFromReturnedFalse();
error TransferFromReverted();
error TransferReturnedFalse();
error TransferReverted();
error Unauthorized();
error ZeroAbsoluteCap();
error ZeroAddress();
error ZeroAllocation();
}
"
},
"lib/vault-v2/lib/morpho-blue/src/libraries/ErrorsLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
/// @title ErrorsLib
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Library exposing error messages.
library ErrorsLib {
/// @notice Thrown when the caller is not the owner.
string internal constant NOT_OWNER = "not owner";
/// @notice Thrown when the LLTV to enable exceeds the maximum LLTV.
string internal constant MAX_LLTV_EXCEEDED = "max LLTV exceeded";
/// @notice Thrown when the fee to set exceeds the maximum fee.
string internal constant MAX_FEE_EXCEEDED = "max fee exceeded";
/// @notice Thrown when the value is already set.
string internal constant ALREADY_SET = "already set";
/// @notice Thrown when the IRM is not enabled at market creation.
string internal constant IRM_NOT_ENABLED = "IRM not enabled";
/// @notice Thrown when the LLTV is not enabled at market creation.
string internal constant LLTV_NOT_ENABLED = "LLTV not enabled";
/// @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";
/// @notice Thrown when not exactly one of the input amount is zero.
string internal constant INCONSISTENT_INPUT = "inconsistent input";
/// @notice Thrown when zero assets is passed as input.
string internal constant ZERO_ASSETS = "zero assets";
/// @notice Thrown when a zero address is passed as input.
string internal constant ZERO_ADDRESS = "zero address";
/// @notice Thrown when the caller is not authorized to conduct an action.
string internal constant UNAUTHORIZED = "unauthorized";
/// @notice Thrown when the collateral is insufficient to `borrow` or `withdrawCollateral`.
string internal constant INSUFFICIENT_COLLATERAL = "insufficient collateral";
/// @notice Thrown when the liquidity is insufficient to `withdraw` or `borrow`.
string internal constant INSUFFICIENT_LIQUIDITY = "insufficient liquidity";
/// @notice Thrown when the position to liquidate is healthy.
string internal constant HEALTHY_POSITION = "position is healthy";
/// @notice Thrown when the authorization signature is invalid.
string internal constant INVALID_SIGNATURE = "invalid signature";
/// @notice Thrown when the authorization signature is expired.
string internal constant SIGNATURE_EXPIRED = "signature expired";
/// @notice Thrown when the nonce is invalid.
string internal constant INVALID_NONCE = "invalid nonce";
/// @notice Thrown when a token transfer reverted.
string internal constant TRANSFER_REVERTED = "transfer reverted";
/// @notice Thrown when a token transfer returned false.
string internal constant TRANSFER_RETURNED_FALSE = "transfer returned false";
/// @notice Thrown when a token transferFrom reverted.
string internal constant TRANSFER_FROM_REVERTED = "transferFrom reverted";
/// @notice Thrown when a token transferFrom returned false
string internal constant TRANSFER_FROM_RETURNED_FALSE = "transferFrom returned false";
/// @notice Thrown when the maximum uint128 is exceeded.
string internal constant MAX_UINT128_EXCEEDED = "max uint128 exceeded";
}
"
},
"lib/vault-v2/lib/morpho-blue/src/libraries/periphery/MorphoStorageLib.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {Id} from "../../interfaces/IMorpho.sol";
/// @title MorphoStorageLib
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Helper library exposing getters to access Morpho storage variables' slot.
/// @dev This library is not used in Morpho itself and is intended to be used by integrators.
library MorphoStorageLib {
/* SLOTS */
uint256 internal constant OWNER_SLOT = 0;
uint256 internal constant FEE_RECIPIENT_SLOT = 1;
uint256 internal constant POSITION_SLOT = 2;
uint256 internal constant MARKET_SLOT = 3;
uint256 internal constant IS_IRM_ENABLED_SLOT = 4;
uint256 internal constant IS_LLTV_ENABLED_SLOT = 5;
uint256 internal constant IS_AUTHORIZED_SLOT = 6;
uint256 internal constant NONCE_SLOT = 7;
uint256 internal constant ID_TO_MARKET_PARAMS_SLOT = 8;
/* SLOT OFFSETS */
uint256 internal constant LOAN_TOKEN_OFFSET = 0;
uint256 internal constant COLLATERAL_TOKEN_OFFSET = 1;
uint256 internal constant ORACLE_OFFSET = 2;
uint256 internal constant IRM_OFFSET = 3;
uint256 internal constant LLTV_OFFSET = 4;\
Submitted on: 2025-10-04 09:37:18
Comments
Log in to comment.
No comments yet.