Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
13096629 | 34 hrs ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
MorphoMarketV1Adapter
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 100000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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; } }
// 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 [email protected] /// @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); }
// 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 [email protected] /// @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); } }
// 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 [email protected] /// @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) } } }
// 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 abdicated(bytes4 selector) external view returns (bool); function executableAt(bytes memory data) 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 abdicate(bytes4 selector) 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); }
// 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); }
// 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; }
// 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()); } }
// 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 [email protected] /// @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); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; uint256 constant WAD = 1e18; /// @title MathLib /// @author Morpho Labs /// @custom:contact [email protected] /// @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; } }
// 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 [email protected] /// @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)) } } }
// 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 [email protected] /// @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; } }
// 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 [email protected] /// @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); } }
// 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); }
// 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); }
// 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); }
// SPDX-License-Identifier: GPL-2.0-or-later // Copyright (c) 2025 Morpho Association pragma solidity ^0.8.0; library ErrorsLib { error Abdicated(); 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(); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; /// @title ErrorsLib /// @author Morpho Labs /// @custom:contact [email protected] /// @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"; }
// 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 [email protected] /// @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; uint256 internal constant SUPPLY_SHARES_OFFSET = 0; uint256 internal constant BORROW_SHARES_AND_COLLATERAL_OFFSET = 1; uint256 internal constant TOTAL_SUPPLY_ASSETS_AND_SHARES_OFFSET = 0; uint256 internal constant TOTAL_BORROW_ASSETS_AND_SHARES_OFFSET = 1; uint256 internal constant LAST_UPDATE_AND_FEE_OFFSET = 2; /* GETTERS */ function ownerSlot() internal pure returns (bytes32) { return bytes32(OWNER_SLOT); } function feeRecipientSlot() internal pure returns (bytes32) { return bytes32(FEE_RECIPIENT_SLOT); } function positionSupplySharesSlot(Id id, address user) internal pure returns (bytes32) { return bytes32( uint256(keccak256(abi.encode(user, keccak256(abi.encode(id, POSITION_SLOT))))) + SUPPLY_SHARES_OFFSET ); } function positionBorrowSharesAndCollateralSlot(Id id, address user) internal pure returns (bytes32) { return bytes32( uint256(keccak256(abi.encode(user, keccak256(abi.encode(id, POSITION_SLOT))))) + BORROW_SHARES_AND_COLLATERAL_OFFSET ); } function marketTotalSupplyAssetsAndSharesSlot(Id id) internal pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + TOTAL_SUPPLY_ASSETS_AND_SHARES_OFFSET); } function marketTotalBorrowAssetsAndSharesSlot(Id id) internal pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + TOTAL_BORROW_ASSETS_AND_SHARES_OFFSET); } function marketLastUpdateAndFeeSlot(Id id) internal pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + LAST_UPDATE_AND_FEE_OFFSET); } function isIrmEnabledSlot(address irm) internal pure returns (bytes32) { return keccak256(abi.encode(irm, IS_IRM_ENABLED_SLOT)); } function isLltvEnabledSlot(uint256 lltv) internal pure returns (bytes32) { return keccak256(abi.encode(lltv, IS_LLTV_ENABLED_SLOT)); } function isAuthorizedSlot(address authorizer, address authorizee) internal pure returns (bytes32) { return keccak256(abi.encode(authorizee, keccak256(abi.encode(authorizer, IS_AUTHORIZED_SLOT)))); } function nonceSlot(address authorizer) internal pure returns (bytes32) { return keccak256(abi.encode(authorizer, NONCE_SLOT)); } function idToLoanTokenSlot(Id id) internal pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + LOAN_TOKEN_OFFSET); } function idToCollateralTokenSlot(Id id) internal pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + COLLATERAL_TOKEN_OFFSET); } function idToOracleSlot(Id id) internal pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + ORACLE_OFFSET); } function idToIrmSlot(Id id) internal pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + IRM_OFFSET); } function idToLltvSlot(Id id) internal pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + LLTV_OFFSET); } }
{ "remappings": [ "solmate/=lib/bundler3/lib/permit2/lib/solmate/", "@openzeppelin/contracts/=lib/metamorpho-1.1/lib/openzeppelin-contracts/contracts/", "bundler3/=lib/bundler3/", "ds-test/=lib/metamorpho-1.1/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/metamorpho-1.1/lib/erc4626-tests/", "forge-gas-snapshot/=lib/bundler3/lib/permit2/lib/forge-gas-snapshot/src/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/morpho-blue/lib/halmos-cheatcodes/src/", "metamorpho-1.1/=lib/metamorpho-1.1/", "metamorpho-v1.1/=lib/vault-v2/lib/metamorpho-v1.1/", "metamorpho/=lib/vault-v2/lib/metamorpho/", "morpho-blue-irm/=lib/morpho-blue-irm/src/", "morpho-blue-oracles/=lib/morpho-blue-oracles/src/", "morpho-blue/=lib/morpho-blue/", "murky/=lib/universal-rewards-distributor/lib/murky/src/", "openzeppelin-contracts/=lib/metamorpho-1.1/lib/openzeppelin-contracts/", "openzeppelin/=lib/universal-rewards-distributor/lib/openzeppelin-contracts/contracts/", "permit2/=lib/bundler3/lib/permit2/", "pre-liquidation/=lib/pre-liquidation/src/", "public-allocator/=lib/public-allocator/src/", "safe-smart-account/=lib/safe-smart-account/", "universal-rewards-distributor/=lib/universal-rewards-distributor/src/", "vault-v2-adapter-registries/=lib/vault-v2-adapter-registries/src/", "vault-v2/=lib/vault-v2/" ], "optimizer": { "enabled": true, "runs": 100000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": true }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_parentVault","type":"address"},{"internalType":"address","name":"_morpho","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApproveReturnedFalse","type":"error"},{"inputs":[],"name":"ApproveReverted","type":"error"},{"inputs":[],"name":"LoanAssetMismatch","type":"error"},{"inputs":[],"name":"NoCode","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"TransferReturnedFalse","type":"error"},{"inputs":[],"name":"TransferReverted","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newSkimRecipient","type":"address"}],"name":"SetSkimRecipient","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"Skim","type":"event"},{"inputs":[],"name":"adapterId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"bytes4","name":"","type":"bytes4"},{"internalType":"address","name":"","type":"address"}],"name":"allocate","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"},{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"loanToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"irm","type":"address"},{"internalType":"uint256","name":"lltv","type":"uint256"}],"internalType":"struct MarketParams","name":"marketParams","type":"tuple"}],"name":"allocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"bytes4","name":"","type":"bytes4"},{"internalType":"address","name":"","type":"address"}],"name":"deallocate","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"},{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"loanToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"irm","type":"address"},{"internalType":"uint256","name":"lltv","type":"uint256"}],"internalType":"struct MarketParams","name":"marketParams","type":"tuple"}],"name":"ids","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketParamsList","outputs":[{"internalType":"address","name":"loanToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"irm","type":"address"},{"internalType":"uint256","name":"lltv","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketParamsListLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"morpho","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"parentVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"realAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newSkimRecipient","type":"address"}],"name":"setSkimRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"skimRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
61012080604052346101ac57604081612445803803809161002082856101c3565b8339810103126101ac5761003f6020610038836101fa565b92016101fa565b3360805260a082905260e08190526040516338d52e0f60e01b81529091906020816004816001600160a01b0386165afa9081156101b8575f91610171575b506100e7926100d69160c05260405160208101906040825260046060820152637468697360e01b6080820152306040820152608081526100be60a0826101c3565b5190206101005260c0516001600160a01b031661020e565b60c0516001600160a01b031661020e565b60405161214590816103008239608051816101ae015260a0518181816105f501528181610a6301528181610b8a01528181610d9701526113d6015260c05181818161064a015281816109750152610bdf015260e05181818161010b01528181610551015281816106a1015281816107d30152610d0a0152610100518181816104e301526114620152f35b90506020813d6020116101b0575b8161018c602093836101c3565b810103126101ac576100e7926101a46100d6926101fa565b91509261007d565b5f80fd5b3d915061017f565b6040513d5f823e3d90fd5b601f909101601f19168101906001600160401b038211908210176101e657604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036101ac57565b90813b156102f0575f91829182604051602081019263095ea7b360e01b845260018060a01b0316602482015281196044820152604481526102506064826101c3565b51925af13d156102e8573d906001600160401b0382116101e65760405191610282601f8201601f1916602001846101c3565b82523d5f602084013e5b156102d95780519081159182156102b6575b5050156102a757565b631f55ddd960e21b5f5260045ffd5b81925090602091810103126101ac576020015180151581036101ac575f8061029e565b637cceae2560e01b5f5260045ffd5b60609061028c565b633c11a9c560e21b5f5260045ffdfe6080806040526004361015610012575f80fd5b5f3560e01c9081630fe3653614610d4f575080631eadd77814610b615780632b30997b146109e9578063388af5b51461099957806338d52e0f1461092b5780633e351242146108565780634e45f1ff146105b957806356c07573146105065780635fb86b01146104ae57806399ee14c31461048e578063b045ff5b14610453578063bc25cf77146101d2578063c45a015514610164578063cc3802bf146101335763d8fbc833146100c1575f80fd5b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5f80fd5b3461012f5761016061014c61014736611012565b611445565b604051918291602083526020830190610f7a565b0390f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461012f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57610209610e7f565b73ffffffffffffffffffffffffffffffffffffffff5f541680330361042b5773ffffffffffffffffffffffffffffffffffffffff821691604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481875afa928315610420575f936103ec575b50813b156103c4575f9182918260405160208101927fa9059cbb0000000000000000000000000000000000000000000000000000000084526024820152866044820152604481526102d6606482610e04565b51925af13d156103bc573d906102eb82610e45565b916102f96040519384610e04565b82523d5f602084013e5b15610394578051908115918215610371575b5050156103495760207f5e99aaf6d3588fb2497fde044168e8c046704a3223559cfe107f8f94b42cefdd91604051908152a2005b7f2f0470fc000000000000000000000000000000000000000000000000000000005f5260045ffd5b819250906020918101031261012f5760200151801515810361012f578380610315565b7face2a47e000000000000000000000000000000000000000000000000000000005f5260045ffd5b606090610303565b7ff046a714000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d602011610418575b8161040860209383610e04565b8101031261012f57519184610284565b3d91506103fb565b6040513d5f823e3d90fd5b7fea8e4eb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f576020600154604051908152f35b3461012f5760206104a66104a136611012565b611348565b604051908152f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f575f5f9060015473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165b81841061058457602083604051908152f35b90916105af6001916105a961059887610fc9565b506105a330916111c2565b86611530565b90611256565b9301929190610572565b3461012f576105dd6105ca36610ea2565b5050919060208082518301019101611105565b9073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361042b5773ffffffffffffffffffffffffffffffffffffffff82511673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000160361082e57806106e8575b506106d861068282611348565b6106d26106c6308573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611530565b93610147858483611b5e565b9261117d565b9061016060405192839283610fad565b604051907f5c2bea4900000000000000000000000000000000000000000000000000000000825261079c60048301846080809173ffffffffffffffffffffffffffffffffffffffff815116845273ffffffffffffffffffffffffffffffffffffffff602082015116602085015273ffffffffffffffffffffffffffffffffffffffff604082015116604085015273ffffffffffffffffffffffffffffffffffffffff60608201511660608501520151910152565b60a48201525f60c48201523060e482015230610104820152604081610124815f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156104205715610675576108219060403d604011610827575b6108198183610e04565b810190611167565b50610675565b503d61080f565b7f58ec95f2000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461012f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f5760043560015481101561012f5761089d60a091610fc9565b5073ffffffffffffffffffffffffffffffffffffffff8154169073ffffffffffffffffffffffffffffffffffffffff6001820154169073ffffffffffffffffffffffffffffffffffffffff600282015416600473ffffffffffffffffffffffffffffffffffffffff600384015416920154926040519485526020850152604084015260608301526080820152f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b3461012f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57610a20610e7f565b6040517f8da5cb5b00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa8015610420575f90610b14575b73ffffffffffffffffffffffffffffffffffffffff915016330361042b5773ffffffffffffffffffffffffffffffffffffffff16807fffffffffffffffffffffffff00000000000000000000000000000000000000005f5416175f557f2e7908865670e21b9779422cadf5f1cba271a62bb95c71eaaf615c0a1c48ebee5f80a2005b506020813d602011610b59575b81610b2e60209383610e04565b8101031261012f57610b5473ffffffffffffffffffffffffffffffffffffffff916110e4565b610a92565b3d9150610b21565b3461012f57610b726105ca36610ea2565b9073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361042b5773ffffffffffffffffffffffffffffffffffffffff82511673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000160361082e5780610c1657506106d861068282611348565b604051907fa99aad89000000000000000000000000000000000000000000000000000000008252610cca60048301846080809173ffffffffffffffffffffffffffffffffffffffff815116845273ffffffffffffffffffffffffffffffffffffffff602082015116602085015273ffffffffffffffffffffffffffffffffffffffff604082015116604085015273ffffffffffffffffffffffffffffffffffffffff60608201511660608501520151910152565b60a48201525f60c48201523060e48201526101206101048201525f610124820152604081610144815f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156104205715610675576108219060403d604011610827576108198183610e04565b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b60a0810190811067ffffffffffffffff821117610dd757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610dd757604052565b67ffffffffffffffff8111610dd757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361012f57565b60807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261012f5760043567ffffffffffffffff811161012f578160238201121561012f57806004013590610ef882610e45565b92610f066040519485610e04565b8284526024838301011161012f57815f92602460209301838601378301015290602435906044357fffffffff000000000000000000000000000000000000000000000000000000008116810361012f579060643573ffffffffffffffffffffffffffffffffffffffff8116810361012f5790565b90602080835192838152019201905f5b818110610f975750505090565b8251845260209384019390920191600101610f8a565b929190610fc4602091604086526040860190610f7a565b930152565b600154811015610fe55760015f52600560205f20910201905f90565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a091011261012f5760405161104881610dbb565b60043573ffffffffffffffffffffffffffffffffffffffff8116810361012f57815260243573ffffffffffffffffffffffffffffffffffffffff8116810361012f57602082015260443573ffffffffffffffffffffffffffffffffffffffff8116810361012f57604082015260643573ffffffffffffffffffffffffffffffffffffffff8116810361012f576060820152608435608082015290565b519073ffffffffffffffffffffffffffffffffffffffff8216820361012f57565b908160a091031261012f5760806040519161111f83610dbb565b611128816110e4565b8352611136602082016110e4565b6020840152611147604082016110e4565b6040840152611158606082016110e4565b60608401520151608082015290565b919082604091031261012f576020825192015190565b81810392915f13801582851316918412161761119557565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b906040516111cf81610dbb565b60806004829473ffffffffffffffffffffffffffffffffffffffff815416845273ffffffffffffffffffffffffffffffffffffffff600182015416602085015273ffffffffffffffffffffffffffffffffffffffff600282015416604085015273ffffffffffffffffffffffffffffffffffffffff60038201541660608501520154910152565b9190820180921161119557565b91604061134692949360e08152601160e08201527f746869732f6d61726b6574506172616d7300000000000000000000000000000061010082015273ffffffffffffffffffffffffffffffffffffffff61012082019616602082015201906080809173ffffffffffffffffffffffffffffffffffffffff815116845273ffffffffffffffffffffffffffffffffffffffff602082015116602085015273ffffffffffffffffffffffffffffffffffffffff604082015116604085015273ffffffffffffffffffffffffffffffffffffffff60608201511660608501520151910152565b565b60405161138a8161135e60208201943086611263565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610e04565b519020604051907fc69507dd000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115610420575f91611409575090565b90506020813d602011611430575b8161142460209383610e04565b8101031261012f575190565b3d9150611417565b805115610fe55760200190565b60405190611454608083610e04565b6003825260603660208401377f000000000000000000000000000000000000000000000000000000000000000061148a83611438565b5273ffffffffffffffffffffffffffffffffffffffff602082015116604051602081019160408352600f60608301527f636f6c6c61746572616c546f6b656e000000000000000000000000000000000060808301526040820152608081526114f360a082610e04565b519020825160011015610fe557604083015260405161151b8161135e60208201943086611263565b519020815160021015610fe557606082015290565b909160a08320604051602081019182526002604082015260408152611556606082610e04565b5190206040519073ffffffffffffffffffffffffffffffffffffffff602083019316835260408201526040815261158e606082610e04565b5190209161162e5f73ffffffffffffffffffffffffffffffffffffffff6040948551966115bb8789610e04565b600188527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087013660208a01376115f188611438565b5216948451809381927f7784c685000000000000000000000000000000000000000000000000000000008352602060048401526024830190610f7a565b0381875afa8015611b47575f90611aa9575b61164a9150611438565b519160c060a0832060248351809781937f5c60e39a00000000000000000000000000000000000000000000000000000000835260048301525afa938415611a9f575f946119f1575b5060808401906116b56fffffffffffffffffffffffffffffffff83511642611b51565b801515806119d3575b806119b0575b611716575b505050506fffffffffffffffffffffffffffffffff60208184511693015116906001830180931161119557620f42408201809211611195576117139261170e91612013565b612101565b90565b60608401805183517f8c00bf6b000000000000000000000000000000000000000000000000000000008152865173ffffffffffffffffffffffffffffffffffffffff9081166004830152602088015181166024830152604088015181166044830152925183166064820152608090960151608487015216906fffffffffffffffffffffffffffffffff87511660a486015260208701946fffffffffffffffffffffffffffffffff86511660c48201526fffffffffffffffffffffffffffffffff848901958187511660e48401528160608b01511661010484015251166101248201526020816101648160a08c01966fffffffffffffffffffffffffffffffff8851166101448301525afa9384156119a757505f93611971575b5061189b6fffffffffffffffffffffffffffffffff9361189561185f670de0b6b3a7640000948789511693612013565b611890671bc16d674ec800006118758380612013565b046729a2241af62c00006118898483612013565b0492611256565b611256565b90612013565b0492826118b36118aa86612026565b82845116611fe1565b169052816118cc6118c385612026565b82895116611fe1565b168652511690816118de575b806116c9565b670de0b6b3a7640000916118f191612013565b0461190f816fffffffffffffffffffffffffffffffff865116611b51565b6fffffffffffffffffffffffffffffffff83511691620f424083018093116111955760018201809211611195576119616119669261170e6fffffffffffffffffffffffffffffffff956118aa94612013565b612026565b1690525f80806118d8565b92506020833d60201161199f575b8161198c60209383610e04565b8101031261012f5791519161189b61182f565b3d915061197f565b513d5f823e3d90fd5b5073ffffffffffffffffffffffffffffffffffffffff60608501511615156116c4565b506fffffffffffffffffffffffffffffffff828701511615156116be565b90935060c0813d60c011611a97575b81611a0d60c09383610e04565b8101031261012f5783519060c0820182811067ffffffffffffffff821117610dd757611a8b9160a0918752611a4181611fc4565b8452611a4f60208201611fc4565b6020850152611a5f878201611fc4565b87850152611a6f60608201611fc4565b6060850152611a8060808201611fc4565b608085015201611fc4565b60a0820152925f611692565b3d9150611a00565b50513d5f823e3d90fd5b503d805f833e611ab98183610e04565b81019060208183031261012f5780519067ffffffffffffffff821161012f57019080601f8301121561012f5781519167ffffffffffffffff8311610dd7578260051b906020820193611b0d87519586610e04565b845260208085019282010192831161012f57602001905b828210611b375750505061164a90611640565b8151815260209182019101611b24565b83513d5f823e3d90fd5b9190820391821161119557565b91901590811580611fbc575b15611e1557505060a090205f5b60015480821015611e10578260a0611b97611b9185610fc9565b506111c2565b2014611ba65750600101611b77565b9091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811161119557611bdf611be691610fc9565b5091610fc9565b919091611c4f57808203611ca8575b50506001548015611c7b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611c2b81610fc9565b611c4f576004815f8093558260018201558260028201558260038201550155600155565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b60048173ffffffffffffffffffffffffffffffffffffffff8083945416167fffffffffffffffffffffffff000000000000000000000000000000000000000085541617845573ffffffffffffffffffffffffffffffffffffffff60018201541673ffffffffffffffffffffffffffffffffffffffff6001860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905573ffffffffffffffffffffffffffffffffffffffff60028201541673ffffffffffffffffffffffffffffffffffffffff6002860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905573ffffffffffffffffffffffffffffffffffffffff60038201541673ffffffffffffffffffffffffffffffffffffffff6003860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905501549101555f80611bf5565b505050565b81611fb2575b50611e235750565b60015468010000000000000000811015610dd757806001611e479201600155610fc9565b919091611c4f5760808173ffffffffffffffffffffffffffffffffffffffff806004945116167fffffffffffffffffffffffff000000000000000000000000000000000000000085541617845573ffffffffffffffffffffffffffffffffffffffff60208201511673ffffffffffffffffffffffffffffffffffffffff6001860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905573ffffffffffffffffffffffffffffffffffffffff60408201511673ffffffffffffffffffffffffffffffffffffffff6002860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905573ffffffffffffffffffffffffffffffffffffffff60608201511673ffffffffffffffffffffffffffffffffffffffff6003860191167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790550151910155565b905015155f611e1b565b508015611b6a565b51906fffffffffffffffffffffffffffffffff8216820361012f57565b906fffffffffffffffffffffffffffffffff809116911601906fffffffffffffffffffffffffffffffff821161119557565b8181029291811591840414171561119557565b604051612034604082610e04565b6014815260208101907f6d61782075696e7431323820657863656564656400000000000000000000000082526fffffffffffffffffffffffffffffffff831161208e5750506fffffffffffffffffffffffffffffffff1690565b6044907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6040519485937f08c379a0000000000000000000000000000000000000000000000000000000008552602060048601525180918160248701528686015e5f85828601015201168101030190fd5b811561210b570490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffdfea164736f6c634300081c000a00000000000000000000000089202ac5577e4cadee1a327a0b9c1dabbbd07e5e0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080806040526004361015610012575f80fd5b5f3560e01c9081630fe3653614610d4f575080631eadd77814610b615780632b30997b146109e9578063388af5b51461099957806338d52e0f1461092b5780633e351242146108565780634e45f1ff146105b957806356c07573146105065780635fb86b01146104ae57806399ee14c31461048e578063b045ff5b14610453578063bc25cf77146101d2578063c45a015514610164578063cc3802bf146101335763d8fbc833146100c1575f80fd5b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5f80fd5b3461012f5761016061014c61014736611012565b611445565b604051918291602083526020830190610f7a565b0390f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e6be3a3a27fb45c6aba2d1833eea48e8788538e168152f35b3461012f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57610209610e7f565b73ffffffffffffffffffffffffffffffffffffffff5f541680330361042b5773ffffffffffffffffffffffffffffffffffffffff821691604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481875afa928315610420575f936103ec575b50813b156103c4575f9182918260405160208101927fa9059cbb0000000000000000000000000000000000000000000000000000000084526024820152866044820152604481526102d6606482610e04565b51925af13d156103bc573d906102eb82610e45565b916102f96040519384610e04565b82523d5f602084013e5b15610394578051908115918215610371575b5050156103495760207f5e99aaf6d3588fb2497fde044168e8c046704a3223559cfe107f8f94b42cefdd91604051908152a2005b7f2f0470fc000000000000000000000000000000000000000000000000000000005f5260045ffd5b819250906020918101031261012f5760200151801515810361012f578380610315565b7face2a47e000000000000000000000000000000000000000000000000000000005f5260045ffd5b606090610303565b7ff046a714000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d602011610418575b8161040860209383610e04565b8101031261012f57519184610284565b3d91506103fb565b6040513d5f823e3d90fd5b7fea8e4eb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f576020600154604051908152f35b3461012f5760206104a66104a136611012565b611348565b604051908152f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f5760206040517f5d03dd8ec93cb29b5d554c85db40cc04fec82307a2f036ab4f9c5020618d62c58152f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f575f5f9060015473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165b81841061058457602083604051908152f35b90916105af6001916105a961059887610fc9565b506105a330916111c2565b86611530565b90611256565b9301929190610572565b3461012f576105dd6105ca36610ea2565b5050919060208082518301019101611105565b9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000089202ac5577e4cadee1a327a0b9c1dabbbd07e5e16330361042b5773ffffffffffffffffffffffffffffffffffffffff82511673ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e1e289900f526c52642a92eb65af73c4b7ab885f160361082e57806106e8575b506106d861068282611348565b6106d26106c6308573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611530565b93610147858483611b5e565b9261117d565b9061016060405192839283610fad565b604051907f5c2bea4900000000000000000000000000000000000000000000000000000000825261079c60048301846080809173ffffffffffffffffffffffffffffffffffffffff815116845273ffffffffffffffffffffffffffffffffffffffff602082015116602085015273ffffffffffffffffffffffffffffffffffffffff604082015116604085015273ffffffffffffffffffffffffffffffffffffffff60608201511660608501520151910152565b60a48201525f60c48201523060e482015230610104820152604081610124815f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156104205715610675576108219060403d604011610827575b6108198183610e04565b810190611167565b50610675565b503d61080f565b7f58ec95f2000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461012f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f5760043560015481101561012f5761089d60a091610fc9565b5073ffffffffffffffffffffffffffffffffffffffff8154169073ffffffffffffffffffffffffffffffffffffffff6001820154169073ffffffffffffffffffffffffffffffffffffffff600282015416600473ffffffffffffffffffffffffffffffffffffffff600384015416920154926040519485526020850152604084015260608301526080820152f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e1e289900f526c52642a92eb65af73c4b7ab885f168152f35b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b3461012f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f57610a20610e7f565b6040517f8da5cb5b00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000089202ac5577e4cadee1a327a0b9c1dabbbd07e5e165afa8015610420575f90610b14575b73ffffffffffffffffffffffffffffffffffffffff915016330361042b5773ffffffffffffffffffffffffffffffffffffffff16807fffffffffffffffffffffffff00000000000000000000000000000000000000005f5416175f557f2e7908865670e21b9779422cadf5f1cba271a62bb95c71eaaf615c0a1c48ebee5f80a2005b506020813d602011610b59575b81610b2e60209383610e04565b8101031261012f57610b5473ffffffffffffffffffffffffffffffffffffffff916110e4565b610a92565b3d9150610b21565b3461012f57610b726105ca36610ea2565b9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000089202ac5577e4cadee1a327a0b9c1dabbbd07e5e16330361042b5773ffffffffffffffffffffffffffffffffffffffff82511673ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e1e289900f526c52642a92eb65af73c4b7ab885f160361082e5780610c1657506106d861068282611348565b604051907fa99aad89000000000000000000000000000000000000000000000000000000008252610cca60048301846080809173ffffffffffffffffffffffffffffffffffffffff815116845273ffffffffffffffffffffffffffffffffffffffff602082015116602085015273ffffffffffffffffffffffffffffffffffffffff604082015116604085015273ffffffffffffffffffffffffffffffffffffffff60608201511660608501520151910152565b60a48201525f60c48201523060e48201526101206101048201525f610124820152604081610144815f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af180156104205715610675576108219060403d604011610827576108198183610e04565b3461012f575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012f5760209073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000089202ac5577e4cadee1a327a0b9c1dabbbd07e5e168152f35b60a0810190811067ffffffffffffffff821117610dd757604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610dd757604052565b67ffffffffffffffff8111610dd757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361012f57565b60807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261012f5760043567ffffffffffffffff811161012f578160238201121561012f57806004013590610ef882610e45565b92610f066040519485610e04565b8284526024838301011161012f57815f92602460209301838601378301015290602435906044357fffffffff000000000000000000000000000000000000000000000000000000008116810361012f579060643573ffffffffffffffffffffffffffffffffffffffff8116810361012f5790565b90602080835192838152019201905f5b818110610f975750505090565b8251845260209384019390920191600101610f8a565b929190610fc4602091604086526040860190610f7a565b930152565b600154811015610fe55760015f52600560205f20910201905f90565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a091011261012f5760405161104881610dbb565b60043573ffffffffffffffffffffffffffffffffffffffff8116810361012f57815260243573ffffffffffffffffffffffffffffffffffffffff8116810361012f57602082015260443573ffffffffffffffffffffffffffffffffffffffff8116810361012f57604082015260643573ffffffffffffffffffffffffffffffffffffffff8116810361012f576060820152608435608082015290565b519073ffffffffffffffffffffffffffffffffffffffff8216820361012f57565b908160a091031261012f5760806040519161111f83610dbb565b611128816110e4565b8352611136602082016110e4565b6020840152611147604082016110e4565b6040840152611158606082016110e4565b60608401520151608082015290565b919082604091031261012f576020825192015190565b81810392915f13801582851316918412161761119557565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b906040516111cf81610dbb565b60806004829473ffffffffffffffffffffffffffffffffffffffff815416845273ffffffffffffffffffffffffffffffffffffffff600182015416602085015273ffffffffffffffffffffffffffffffffffffffff600282015416604085015273ffffffffffffffffffffffffffffffffffffffff60038201541660608501520154910152565b9190820180921161119557565b91604061134692949360e08152601160e08201527f746869732f6d61726b6574506172616d7300000000000000000000000000000061010082015273ffffffffffffffffffffffffffffffffffffffff61012082019616602082015201906080809173ffffffffffffffffffffffffffffffffffffffff815116845273ffffffffffffffffffffffffffffffffffffffff602082015116602085015273ffffffffffffffffffffffffffffffffffffffff604082015116604085015273ffffffffffffffffffffffffffffffffffffffff60608201511660608501520151910152565b565b60405161138a8161135e60208201943086611263565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610e04565b519020604051907fc69507dd000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000089202ac5577e4cadee1a327a0b9c1dabbbd07e5e165afa908115610420575f91611409575090565b90506020813d602011611430575b8161142460209383610e04565b8101031261012f575190565b3d9150611417565b805115610fe55760200190565b60405190611454608083610e04565b6003825260603660208401377f5d03dd8ec93cb29b5d554c85db40cc04fec82307a2f036ab4f9c5020618d62c561148a83611438565b5273ffffffffffffffffffffffffffffffffffffffff602082015116604051602081019160408352600f60608301527f636f6c6c61746572616c546f6b656e000000000000000000000000000000000060808301526040820152608081526114f360a082610e04565b519020825160011015610fe557604083015260405161151b8161135e60208201943086611263565b519020815160021015610fe557606082015290565b909160a08320604051602081019182526002604082015260408152611556606082610e04565b5190206040519073ffffffffffffffffffffffffffffffffffffffff602083019316835260408201526040815261158e606082610e04565b5190209161162e5f73ffffffffffffffffffffffffffffffffffffffff6040948551966115bb8789610e04565b600188527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087013660208a01376115f188611438565b5216948451809381927f7784c685000000000000000000000000000000000000000000000000000000008352602060048401526024830190610f7a565b0381875afa8015611b47575f90611aa9575b61164a9150611438565b519160c060a0832060248351809781937f5c60e39a00000000000000000000000000000000000000000000000000000000835260048301525afa938415611a9f575f946119f1575b5060808401906116b56fffffffffffffffffffffffffffffffff83511642611b51565b801515806119d3575b806119b0575b611716575b505050506fffffffffffffffffffffffffffffffff60208184511693015116906001830180931161119557620f42408201809211611195576117139261170e91612013565b612101565b90565b60608401805183517f8c00bf6b000000000000000000000000000000000000000000000000000000008152865173ffffffffffffffffffffffffffffffffffffffff9081166004830152602088015181166024830152604088015181166044830152925183166064820152608090960151608487015216906fffffffffffffffffffffffffffffffff87511660a486015260208701946fffffffffffffffffffffffffffffffff86511660c48201526fffffffffffffffffffffffffffffffff848901958187511660e48401528160608b01511661010484015251166101248201526020816101648160a08c01966fffffffffffffffffffffffffffffffff8851166101448301525afa9384156119a757505f93611971575b5061189b6fffffffffffffffffffffffffffffffff9361189561185f670de0b6b3a7640000948789511693612013565b611890671bc16d674ec800006118758380612013565b046729a2241af62c00006118898483612013565b0492611256565b611256565b90612013565b0492826118b36118aa86612026565b82845116611fe1565b169052816118cc6118c385612026565b82895116611fe1565b168652511690816118de575b806116c9565b670de0b6b3a7640000916118f191612013565b0461190f816fffffffffffffffffffffffffffffffff865116611b51565b6fffffffffffffffffffffffffffffffff83511691620f424083018093116111955760018201809211611195576119616119669261170e6fffffffffffffffffffffffffffffffff956118aa94612013565b612026565b1690525f80806118d8565b92506020833d60201161199f575b8161198c60209383610e04565b8101031261012f5791519161189b61182f565b3d915061197f565b513d5f823e3d90fd5b5073ffffffffffffffffffffffffffffffffffffffff60608501511615156116c4565b506fffffffffffffffffffffffffffffffff828701511615156116be565b90935060c0813d60c011611a97575b81611a0d60c09383610e04565b8101031261012f5783519060c0820182811067ffffffffffffffff821117610dd757611a8b9160a0918752611a4181611fc4565b8452611a4f60208201611fc4565b6020850152611a5f878201611fc4565b87850152611a6f60608201611fc4565b6060850152611a8060808201611fc4565b608085015201611fc4565b60a0820152925f611692565b3d9150611a00565b50513d5f823e3d90fd5b503d805f833e611ab98183610e04565b81019060208183031261012f5780519067ffffffffffffffff821161012f57019080601f8301121561012f5781519167ffffffffffffffff8311610dd7578260051b906020820193611b0d87519586610e04565b845260208085019282010192831161012f57602001905b828210611b375750505061164a90611640565b8151815260209182019101611b24565b83513d5f823e3d90fd5b9190820391821161119557565b91901590811580611fbc575b15611e1557505060a090205f5b60015480821015611e10578260a0611b97611b9185610fc9565b506111c2565b2014611ba65750600101611b77565b9091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811161119557611bdf611be691610fc9565b5091610fc9565b919091611c4f57808203611ca8575b50506001548015611c7b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611c2b81610fc9565b611c4f576004815f8093558260018201558260028201558260038201550155600155565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b60048173ffffffffffffffffffffffffffffffffffffffff8083945416167fffffffffffffffffffffffff000000000000000000000000000000000000000085541617845573ffffffffffffffffffffffffffffffffffffffff60018201541673ffffffffffffffffffffffffffffffffffffffff6001860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905573ffffffffffffffffffffffffffffffffffffffff60028201541673ffffffffffffffffffffffffffffffffffffffff6002860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905573ffffffffffffffffffffffffffffffffffffffff60038201541673ffffffffffffffffffffffffffffffffffffffff6003860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905501549101555f80611bf5565b505050565b81611fb2575b50611e235750565b60015468010000000000000000811015610dd757806001611e479201600155610fc9565b919091611c4f5760808173ffffffffffffffffffffffffffffffffffffffff806004945116167fffffffffffffffffffffffff000000000000000000000000000000000000000085541617845573ffffffffffffffffffffffffffffffffffffffff60208201511673ffffffffffffffffffffffffffffffffffffffff6001860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905573ffffffffffffffffffffffffffffffffffffffff60408201511673ffffffffffffffffffffffffffffffffffffffff6002860191167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905573ffffffffffffffffffffffffffffffffffffffff60608201511673ffffffffffffffffffffffffffffffffffffffff6003860191167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790550151910155565b905015155f611e1b565b508015611b6a565b51906fffffffffffffffffffffffffffffffff8216820361012f57565b906fffffffffffffffffffffffffffffffff809116911601906fffffffffffffffffffffffffffffffff821161119557565b8181029291811591840414171561119557565b604051612034604082610e04565b6014815260208101907f6d61782075696e7431323820657863656564656400000000000000000000000082526fffffffffffffffffffffffffffffffff831161208e5750506fffffffffffffffffffffffffffffffff1690565b6044907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6040519485937f08c379a0000000000000000000000000000000000000000000000000000000008552602060048601525180918160248701528686015e5f85828601015201168101030190fd5b811561210b570490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffdfea164736f6c634300081c000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000089202ac5577e4cadee1a327a0b9c1dabbbd07e5e0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _parentVault (address): 0x89202AC5577E4Cadee1A327A0b9C1dABbbD07e5E
Arg [1] : _morpho (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000089202ac5577e4cadee1a327a0b9c1dabbbd07e5e
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading

Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.