Overview
S Balance
0 S
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
IRMLens
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 20000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {Utils} from "./Utils.sol"; import {IFactory} from "../BaseFactory/interfaces/IFactory.sol"; import {IRMLinearKink} from "evk/InterestRateModels/IRMLinearKink.sol"; import {IRMAdaptiveCurve} from "../IRM/IRMAdaptiveCurve.sol"; import "./LensTypes.sol"; contract IRMLens is Utils { address public immutable kinkIRMFactory; address public immutable adaptiveCurveIRMFactory; constructor(address _kinkIRMFactory, address _adaptiveCurveIRMFactory) { kinkIRMFactory = _kinkIRMFactory; adaptiveCurveIRMFactory = _adaptiveCurveIRMFactory; } function getInterestRateModelInfo(address irm) public view returns (InterestRateModelDetailedInfo memory) { InterestRateModelDetailedInfo memory result; if (irm == address(0)) { return result; } result.interestRateModel = irm; if (IFactory(kinkIRMFactory).isValidDeployment(irm)) { result.interestRateModelType = InterestRateModelType.KINK; result.interestRateModelParams = abi.encode( KinkIRMInfo({ baseRate: IRMLinearKink(irm).baseRate(), slope1: IRMLinearKink(irm).slope1(), slope2: IRMLinearKink(irm).slope2(), kink: IRMLinearKink(irm).kink() }) ); } else if (IFactory(adaptiveCurveIRMFactory).isValidDeployment(irm)) { result.interestRateModelType = InterestRateModelType.ADAPTIVE_CURVE; result.interestRateModelParams = abi.encode( AdaptiveCurveIRMInfo({ targetUtilization: IRMAdaptiveCurve(irm).TARGET_UTILIZATION(), initialRateAtTarget: IRMAdaptiveCurve(irm).INITIAL_RATE_AT_TARGET(), minRateAtTarget: IRMAdaptiveCurve(irm).MIN_RATE_AT_TARGET(), maxRateAtTarget: IRMAdaptiveCurve(irm).MAX_RATE_AT_TARGET(), curveSteepness: IRMAdaptiveCurve(irm).CURVE_STEEPNESS(), adjustmentSpeed: IRMAdaptiveCurve(irm).ADJUSTMENT_SPEED() }) ); } return result; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IEVault} from "evk/EVault/IEVault.sol"; import {RPow} from "evk/EVault/shared/lib/RPow.sol"; abstract contract Utils { uint256 internal constant SECONDS_PER_YEAR = 365.2425 * 86400; uint256 internal constant ONE = 1e27; uint256 internal constant CONFIG_SCALE = 1e4; uint256 internal constant TTL_HS_ACCURACY = ONE / 1e4; int256 internal constant TTL_COMPUTATION_MIN = 0; int256 internal constant TTL_COMPUTATION_MAX = 400 * 1 days; int256 public constant TTL_INFINITY = type(int256).max; int256 public constant TTL_MORE_THAN_ONE_YEAR = type(int256).max - 1; int256 public constant TTL_LIQUIDATION = -1; int256 public constant TTL_ERROR = -2; function getWETHAddress() internal view returns (address) { if (block.chainid == 1) { return 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; } else if ( block.chainid == 10 || block.chainid == 8453 || block.chainid == 1923 || block.chainid == 57073 || block.chainid == 60808 ) { return 0x4200000000000000000000000000000000000006; } else if (block.chainid == 137) { return 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619; } else if (block.chainid == 146) { return 0x50c42dEAcD8Fc9773493ED674b675bE577f2634b; } else if (block.chainid == 42161) { return 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1; } else if (block.chainid == 43114) { return 0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB; } else { // test networks if (block.chainid == 10143 || block.chainid == 80084) { return address(0); } } revert("getWETHAddress: Unsupported chain"); } function _strEq(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } /// @dev for tokens like MKR which return bytes32 on name() or symbol() function _getStringOrBytes32(address contractAddress, bytes4 selector) internal view returns (string memory) { (bool success, bytes memory result) = contractAddress.staticcall(abi.encodeWithSelector(selector)); return (success && result.length != 0) ? result.length == 32 ? string(abi.encodePacked(result)) : abi.decode(result, (string)) : ""; } function _getDecimals(address contractAddress) internal view returns (uint8) { (bool success, bytes memory data) = contractAddress.staticcall(abi.encodeCall(IEVault(contractAddress).decimals, ())); return success && data.length >= 32 ? abi.decode(data, (uint8)) : 18; } function _computeAPYs(uint256 borrowSPY, uint256 cash, uint256 borrows, uint256 interestFee) internal pure returns (uint256 borrowAPY, uint256 supplyAPY) { uint256 totalAssets = cash + borrows; bool overflow; (borrowAPY, overflow) = RPow.rpow(borrowSPY + ONE, SECONDS_PER_YEAR, ONE); if (overflow) return (0, 0); borrowAPY -= ONE; supplyAPY = totalAssets == 0 ? 0 : borrowAPY * borrows * (CONFIG_SCALE - interestFee) / totalAssets / CONFIG_SCALE; } struct CollateralInfo { uint256 borrowSPY; uint256 borrows; uint256 totalAssets; uint256 interestFee; uint256 borrowInterest; } function _calculateTimeToLiquidation( address liabilityVault, uint256 liabilityValue, address[] memory collaterals, uint256[] memory collateralValues ) internal view returns (int256) { // if there's no liability, time to liquidation is infinite if (liabilityValue == 0) return TTL_INFINITY; // get borrow interest rate uint256 liabilitySPY; { (bool success, bytes memory data) = liabilityVault.staticcall(abi.encodeCall(IEVault(liabilityVault).interestRate, ())); if (success && data.length >= 32) { liabilitySPY = abi.decode(data, (uint256)); } } // get individual collateral interest rates and total collateral value CollateralInfo[] memory collateralInfos = new CollateralInfo[](collaterals.length); uint256 collateralValue; for (uint256 i = 0; i < collaterals.length; ++i) { address collateral = collaterals[i]; (bool success, bytes memory data) = collateral.staticcall(abi.encodeCall(IEVault(collateral).interestRate, ())); if (success && data.length >= 32) { collateralInfos[i].borrowSPY = abi.decode(data, (uint256)); } (success, data) = collateral.staticcall(abi.encodeCall(IEVault(collateral).totalBorrows, ())); if (success && data.length >= 32) { collateralInfos[i].borrows = abi.decode(data, (uint256)); } (success, data) = collateral.staticcall(abi.encodeCall(IEVault(collateral).cash, ())); if (success && data.length >= 32) { collateralInfos[i].totalAssets = abi.decode(data, (uint256)) + collateralInfos[i].borrows; } (success, data) = collateral.staticcall(abi.encodeCall(IEVault(collateral).interestFee, ())); if (success && data.length >= 32) { collateralInfos[i].interestFee = abi.decode(data, (uint256)); } collateralValue += collateralValues[i]; } // if liability is greater than or equal to collateral, the account is eligible for liquidation right away if (liabilityValue >= collateralValue) return TTL_LIQUIDATION; // if there's no borrow interest rate, time to liquidation is infinite if (liabilitySPY == 0) return TTL_INFINITY; int256 minTTL = TTL_COMPUTATION_MIN; int256 maxTTL = TTL_COMPUTATION_MAX; int256 ttl; // calculate time to liquidation using binary search while (true) { ttl = minTTL + (maxTTL - minTTL) / 2; // break if the search range is too small if (maxTTL <= minTTL + 1 days) break; if (ttl < 1 days) break; // calculate the liability interest accrued uint256 liabilityInterest; if (liabilitySPY > 0) { (uint256 multiplier, bool overflow) = RPow.rpow(liabilitySPY + ONE, uint256(ttl), ONE); if (overflow) return TTL_ERROR; liabilityInterest = liabilityValue * multiplier / ONE - liabilityValue; } // calculate the collaterals interest accrued uint256 collateralInterest; for (uint256 i = 0; i < collaterals.length; ++i) { if (collateralInfos[i].borrowSPY == 0 || collateralInfos[i].totalAssets == 0) continue; (uint256 multiplier, bool overflow) = RPow.rpow(collateralInfos[i].borrowSPY + ONE, uint256(ttl), ONE); if (overflow) return TTL_ERROR; collateralInfos[i].borrowInterest = collateralValues[i] * multiplier / ONE - collateralValues[i]; collateralInterest += collateralInfos[i].borrowInterest * collateralInfos[i].borrows * (CONFIG_SCALE - collateralInfos[i].interestFee) / collateralInfos[i].totalAssets / CONFIG_SCALE; } // calculate the health factor uint256 hs = (collateralValue + collateralInterest) * ONE / (liabilityValue + liabilityInterest); // if the collateral interest accrues fater than the liability interest, the account should never be // liquidated if (collateralInterest >= liabilityInterest) return TTL_INFINITY; // if the health factor is within the acceptable range, return the time to liquidation if (hs >= ONE && hs - ONE <= TTL_HS_ACCURACY) break; if (hs < ONE && ONE - hs <= TTL_HS_ACCURACY) break; // adjust the search range if (hs >= ONE) minTTL = ttl + 1 days; else maxTTL = ttl - 1 days; } return ttl > int256(SECONDS_PER_YEAR) ? TTL_MORE_THAN_ONE_YEAR : int256(ttl) / 1 days; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title IFactory /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice A minimal factory interface for deploying contracts. interface IFactory { struct DeploymentInfo { /// @notice The sender of the deployment call. address deployer; /// @notice The timestamp when the contract was deployed. uint96 deployedAt; } /// @notice An instance of a contract was deployed. /// @param deployedContract The deployment address of the contract. /// @param deployer The sender of the deployment call. /// @param deployedAt The deployment timestamp of the contract. event ContractDeployed(address indexed deployedContract, address indexed deployer, uint256 deployedAt); /// @notice Error thrown when the query is incorrect. error Factory_BadQuery(); /// @notice Contracts deployed by the factory. function getDeploymentInfo(address contractAddress) external view returns (address deployer, uint96 deployedAt); /// @notice Checks if the deployment at the given address is valid. /// @param contractAddress The address of the contract to check. /// @return True if the deployment is valid, false otherwise. function isValidDeployment(address contractAddress) external view returns (bool); /// @notice Returns the number of contracts deployed by the factory. /// @return The number of deployed contracts. function getDeploymentsListLength() external view returns (uint256); /// @notice Returns a slice of the list of deployments. /// @param start The starting index of the slice. /// @param end The ending index of the slice (exclusive). /// @return list An array of addresses of the deployed contracts in the specified range. function getDeploymentsListSlice(uint256 start, uint256 end) external view returns (address[] memory list); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./IIRM.sol"; /// @title IRMLinearKink /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Implementation of an interest rate model, where interest rate grows linearly with utilization, and spikes /// after reaching kink contract IRMLinearKink is IIRM { /// @notice Base interest rate applied when utilization is equal zero uint256 public immutable baseRate; /// @notice Slope of the function before the kink uint256 public immutable slope1; /// @notice Slope of the function after the kink uint256 public immutable slope2; /// @notice Utilization at which the slope of the interest rate function changes. In type(uint32).max scale. uint256 public immutable kink; constructor(uint256 baseRate_, uint256 slope1_, uint256 slope2_, uint32 kink_) { baseRate = baseRate_; slope1 = slope1_; slope2 = slope2_; kink = kink_; } /// @inheritdoc IIRM function computeInterestRate(address vault, uint256 cash, uint256 borrows) external view override returns (uint256) { if (msg.sender != vault) revert E_IRMUpdateUnauthorized(); return computeInterestRateInternal(vault, cash, borrows); } /// @inheritdoc IIRM function computeInterestRateView(address vault, uint256 cash, uint256 borrows) external view override returns (uint256) { return computeInterestRateInternal(vault, cash, borrows); } function computeInterestRateInternal(address, uint256 cash, uint256 borrows) internal view returns (uint256) { uint256 totalAssets = cash + borrows; uint32 utilization = totalAssets == 0 ? 0 // empty pool arbitrarily given utilization of 0 : uint32(borrows * type(uint32).max / totalAssets); uint256 ir = baseRate; if (utilization <= kink) { ir += utilization * slope1; } else { ir += kink * slope1; uint256 utilizationOverKink; unchecked { utilizationOverKink = utilization - kink; } ir += slope2 * utilizationOverKink; } return ir; } }
// SPDX-License-Identifier: MIT // Copyright (c) 2023 Morpho Association pragma solidity ^0.8.0; import {IIRM} from "evk/InterestRateModels/IIRM.sol"; import {ExpLib} from "./lib/ExpLib.sol"; /// @title IRMAdaptiveCurve /// @custom:contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/). /// @author Adapted from Morpho Labs (https://github.com/morpho-org/morpho-blue-irm/). /// @notice A Linear Kink IRM that adjusts the rate at target utilization based on time spent above/below it. /// @dev This implementation intentionally leaves variables names, units and ExpLib unchanged from original. /// Returned rates are extended to RAY per second to be compatible with the EVK. contract IRMAdaptiveCurve is IIRM { /// @dev Unit for internal precision. int256 internal constant WAD = 1e18; /// @dev Unit for internal precision. int256 internal constant YEAR = int256(365.2425 days); /// @notice The name of the IRM. string public constant name = "IRMAdaptiveCurve"; /// @notice The utilization rate targeted by the model. /// @dev In WAD units. int256 public immutable TARGET_UTILIZATION; /// @notice The initial interest rate at target utilization. /// @dev In WAD per second units. /// When the IRM is initialized for a vault this is the rate at target utilization that is assigned. int256 public immutable INITIAL_RATE_AT_TARGET; /// @notice The minimum interest rate at target utilization that the model can adjust to. /// @dev In WAD per second units. int256 public immutable MIN_RATE_AT_TARGET; /// @notice The maximum interest rate at target utilization that the model can adjust to. /// @dev In WAD per second units. int256 public immutable MAX_RATE_AT_TARGET; /// @notice The steepness of the interest rate line. /// @dev In WAD units. int256 public immutable CURVE_STEEPNESS; /// @notice The speed at which the rate at target is adjusted up or down. /// @dev In WAD per second units. /// For example, with `2e18 / 24 hours` the model will 2x `rateAtTarget` if the vault is fully utilized for a day. int256 public immutable ADJUSTMENT_SPEED; /// @notice Internal cached state of the interest rate model. struct IRState { /// @dev The current rate at target utilization. uint144 rateAtTarget; /// @dev The previous utilization rate of the vault. int64 lastUtilization; /// @dev The timestamp of the last update to the model. uint48 lastUpdate; } /// @notice Get the internal cached state of a vault's irm. mapping(address => IRState) internal irState; error InvalidParams(); /// @notice Deploy IRMAdaptiveCurve. /// @param _TARGET_UTILIZATION The utilization rate targeted by the interest rate model. /// @param _INITIAL_RATE_AT_TARGET The initial interest rate at target utilization. /// @param _MIN_RATE_AT_TARGET The minimum interest rate at target utilization that the model can adjust to. /// @param _MAX_RATE_AT_TARGET The maximum interest rate at target utilization that the model can adjust to. /// @param _CURVE_STEEPNESS The steepness of the interest rate line. /// @param _ADJUSTMENT_SPEED The speed at which the rate at target utilization is adjusted up or down. constructor( int256 _TARGET_UTILIZATION, int256 _INITIAL_RATE_AT_TARGET, int256 _MIN_RATE_AT_TARGET, int256 _MAX_RATE_AT_TARGET, int256 _CURVE_STEEPNESS, int256 _ADJUSTMENT_SPEED ) { // Validate parameters. if (_TARGET_UTILIZATION <= 0 || _TARGET_UTILIZATION > 1e18) { revert InvalidParams(); } if (_INITIAL_RATE_AT_TARGET < _MIN_RATE_AT_TARGET || _INITIAL_RATE_AT_TARGET > _MAX_RATE_AT_TARGET) { revert InvalidParams(); } if (_MIN_RATE_AT_TARGET < 0.001e18 / YEAR || _MIN_RATE_AT_TARGET > 10e18 / YEAR) { revert InvalidParams(); } if (_MAX_RATE_AT_TARGET < 0.001e18 / YEAR || _MAX_RATE_AT_TARGET > 10e18 / YEAR) { revert InvalidParams(); } if (_CURVE_STEEPNESS < 1.01e18 || _CURVE_STEEPNESS > 100e18) { revert InvalidParams(); } if (_ADJUSTMENT_SPEED < 2e18 / YEAR || _ADJUSTMENT_SPEED > 1000e18 / YEAR) { revert InvalidParams(); } TARGET_UTILIZATION = _TARGET_UTILIZATION; INITIAL_RATE_AT_TARGET = _INITIAL_RATE_AT_TARGET; MIN_RATE_AT_TARGET = _MIN_RATE_AT_TARGET; MAX_RATE_AT_TARGET = _MAX_RATE_AT_TARGET; CURVE_STEEPNESS = _CURVE_STEEPNESS; ADJUSTMENT_SPEED = _ADJUSTMENT_SPEED; } /// @inheritdoc IIRM function computeInterestRate(address vault, uint256 cash, uint256 borrows) external returns (uint256) { if (msg.sender != vault) revert E_IRMUpdateUnauthorized(); int256 utilization = _calcUtilization(cash, borrows); // If this is the first call then use the current utilization instead of the lastUtilization from storage. int256 lastUtilization = irState[vault].lastUpdate == 0 ? utilization : irState[vault].lastUtilization; (uint256 rate, uint256 rateAtTarget) = computeInterestRateInternal(vault, lastUtilization); irState[vault] = IRState(uint144(rateAtTarget), int64(utilization), uint48(block.timestamp)); return rate * 1e9; // Extend rate to RAY/sec for EVK. } /// @inheritdoc IIRM function computeInterestRateView(address vault, uint256 cash, uint256 borrows) external view returns (uint256) { int256 utilization = _calcUtilization(cash, borrows); (uint256 rate,) = computeInterestRateInternal(vault, utilization); return rate * 1e9; // Extend rate to RAY/sec for EVK. } /// @notice Perform computation of the new rate at target without mutating state. /// @param vault Address of the vault to compute the new interest rate for. /// @param cash Amount of assets held directly by the vault. /// @param borrows Amount of assets lent out to borrowers by the vault. /// @return The new rate at target utilization in RAY units. function computeRateAtTargetView(address vault, uint256 cash, uint256 borrows) external view returns (uint256) { int256 utilization = _calcUtilization(cash, borrows); (, uint256 rateAtTarget) = computeInterestRateInternal(vault, utilization); return rateAtTarget * 1e9; // Extend rate to RAY/sec for EVK. } /// @notice Get the timestamp of the last update for a vault. /// @param vault Address of the vault to get the last update timestamp for. /// @return The last update timestamp. function getLastUpdateTimestamp(address vault) external view returns (uint256) { return irState[vault].lastUpdate; } /// @notice Compute the new interest rate and rate at target utilization of a vault. /// @param vault Address of the vault to compute the new interest rate for. /// @return The new interest rate at current utilization. /// @return The new interest rate at target utilization. function computeInterestRateInternal(address vault, int256 utilization) internal view returns (uint256, uint256) { // Calculate the normalized distance between current utilization and target utilization. // `err` is normalized to [-1, +1] where -1 is 0% util, 0 is at target and +1 is 100% util. int256 errNormFactor = utilization > TARGET_UTILIZATION ? WAD - TARGET_UTILIZATION : TARGET_UTILIZATION; int256 err = (utilization - TARGET_UTILIZATION) * WAD / errNormFactor; IRState memory state = irState[vault]; int256 startRateAtTarget = int256(uint256(state.rateAtTarget)); int256 endRateAtTarget; if (startRateAtTarget == 0) { // First interaction. endRateAtTarget = INITIAL_RATE_AT_TARGET; } else { // The speed is assumed constant between two updates, but it is in fact not constant because of interest. // So the rate is always underestimated. int256 speed = ADJUSTMENT_SPEED * err / WAD; // Calculate the adaptation parameter. int256 elapsed = int256(block.timestamp - state.lastUpdate); int256 linearAdaptation = speed * elapsed; if (linearAdaptation == 0) { endRateAtTarget = startRateAtTarget; } else { endRateAtTarget = _newRateAtTarget(startRateAtTarget, linearAdaptation); } } return (uint256(_curve(endRateAtTarget, err)), uint256(endRateAtTarget)); } /// @notice Calculate the interest rate according to the linear kink model. /// @param rateAtTarget The current interest rate at target utilization. /// @param err The distance between the current utilization and the target utilization, normalized to `[-1, +1]`. /// @dev rate = ((1-1/C)*err + 1) * rateAtTarget if err < 0 /// (C-1)*err + 1) * rateAtTarget else. /// @return The new interest rate at current utilization. function _curve(int256 rateAtTarget, int256 err) internal view returns (int256) { // Non negative because 1 - 1/C >= 0, C - 1 >= 0. int256 coeff = err < 0 ? WAD - WAD * WAD / CURVE_STEEPNESS : CURVE_STEEPNESS - WAD; // Non negative if rateAtTarget >= 0 because if err < 0, coeff <= 1. return ((coeff * err / WAD) + WAD) * rateAtTarget / WAD; } /// @notice Calculate the new interest rate at target utilization by applying an adaptation. /// @param startRateAtTarget The current interest rate at target utilization. /// @param linearAdaptation The adaptation parameter, used as a power of `e`. /// @dev Applies exponential growth/decay to the current interest rate at target utilization. /// Formula: `rateAtTarget = startRateAtTarget * e^linearAdaptation` bounded to min and max. /// @return The new interest rate at target utilization. function _newRateAtTarget(int256 startRateAtTarget, int256 linearAdaptation) internal view returns (int256) { int256 rateAtTarget = startRateAtTarget * ExpLib.wExp(linearAdaptation) / WAD; if (rateAtTarget < MIN_RATE_AT_TARGET) return MIN_RATE_AT_TARGET; if (rateAtTarget > MAX_RATE_AT_TARGET) return MAX_RATE_AT_TARGET; return rateAtTarget; } /// @notice Calculate the utilization rate, given cash and borrows from the vault. /// @param cash Amount of assets held directly by the vault. /// @param borrows Amount of assets lent out to borrowers by the vault. /// @return The utilization rate in WAD. function _calcUtilization(uint256 cash, uint256 borrows) internal pure returns (int256) { int256 totalAssets = int256(cash + borrows); if (totalAssets == 0) return 0; return int256(borrows) * WAD / totalAssets; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; struct AccountInfo { EVCAccountInfo evcAccountInfo; VaultAccountInfo vaultAccountInfo; AccountRewardInfo accountRewardInfo; } struct AccountMultipleVaultsInfo { EVCAccountInfo evcAccountInfo; VaultAccountInfo[] vaultAccountInfo; AccountRewardInfo[] accountRewardInfo; } struct EVCAccountInfo { uint256 timestamp; address evc; address account; bytes19 addressPrefix; address owner; bool isLockdownMode; bool isPermitDisabledMode; uint256 lastAccountStatusCheckTimestamp; address[] enabledControllers; address[] enabledCollaterals; } struct VaultAccountInfo { uint256 timestamp; address account; address vault; address asset; uint256 assetsAccount; uint256 shares; uint256 assets; uint256 borrowed; uint256 assetAllowanceVault; uint256 assetAllowanceVaultPermit2; uint256 assetAllowanceExpirationVaultPermit2; uint256 assetAllowancePermit2; bool balanceForwarderEnabled; bool isController; bool isCollateral; AccountLiquidityInfo liquidityInfo; } struct AccountLiquidityInfo { bool queryFailure; bytes queryFailureReason; int256 timeToLiquidation; uint256 liabilityValue; uint256 collateralValueBorrowing; uint256 collateralValueLiquidation; uint256 collateralValueRaw; CollateralLiquidityInfo[] collateralLiquidityBorrowingInfo; CollateralLiquidityInfo[] collateralLiquidityLiquidationInfo; CollateralLiquidityInfo[] collateralLiquidityRawInfo; } struct CollateralLiquidityInfo { address collateral; uint256 collateralValue; } struct VaultInfoFull { uint256 timestamp; address vault; string vaultName; string vaultSymbol; uint256 vaultDecimals; address asset; string assetName; string assetSymbol; uint256 assetDecimals; address unitOfAccount; string unitOfAccountName; string unitOfAccountSymbol; uint256 unitOfAccountDecimals; uint256 totalShares; uint256 totalCash; uint256 totalBorrowed; uint256 totalAssets; uint256 accumulatedFeesShares; uint256 accumulatedFeesAssets; address governorFeeReceiver; address protocolFeeReceiver; uint256 protocolFeeShare; uint256 interestFee; uint256 hookedOperations; uint256 configFlags; uint256 supplyCap; uint256 borrowCap; uint256 maxLiquidationDiscount; uint256 liquidationCoolOffTime; address dToken; address oracle; address interestRateModel; address hookTarget; address evc; address protocolConfig; address balanceTracker; address permit2; address creator; address governorAdmin; VaultInterestRateModelInfo irmInfo; LTVInfo[] collateralLTVInfo; AssetPriceInfo liabilityPriceInfo; AssetPriceInfo[] collateralPriceInfo; OracleDetailedInfo oracleInfo; AssetPriceInfo backupAssetPriceInfo; OracleDetailedInfo backupAssetOracleInfo; } struct LTVInfo { address collateral; uint256 borrowLTV; uint256 liquidationLTV; uint256 initialLiquidationLTV; uint256 targetTimestamp; uint256 rampDuration; } struct AssetPriceInfo { bool queryFailure; bytes queryFailureReason; uint256 timestamp; address oracle; address asset; address unitOfAccount; uint256 amountIn; uint256 amountOutMid; uint256 amountOutBid; uint256 amountOutAsk; } struct VaultInterestRateModelInfo { bool queryFailure; bytes queryFailureReason; address vault; address interestRateModel; InterestRateInfo[] interestRateInfo; InterestRateModelDetailedInfo interestRateModelInfo; } struct InterestRateInfo { uint256 cash; uint256 borrows; uint256 borrowSPY; uint256 borrowAPY; uint256 supplyAPY; } enum InterestRateModelType { UNKNOWN, KINK, ADAPTIVE_CURVE } struct InterestRateModelDetailedInfo { address interestRateModel; InterestRateModelType interestRateModelType; bytes interestRateModelParams; } struct KinkIRMInfo { uint256 baseRate; uint256 slope1; uint256 slope2; uint256 kink; } struct AdaptiveCurveIRMInfo { int256 targetUtilization; int256 initialRateAtTarget; int256 minRateAtTarget; int256 maxRateAtTarget; int256 curveSteepness; int256 adjustmentSpeed; } struct AccountRewardInfo { uint256 timestamp; address account; address vault; address balanceTracker; bool balanceForwarderEnabled; uint256 balance; EnabledRewardInfo[] enabledRewardsInfo; } struct EnabledRewardInfo { address reward; uint256 earnedReward; uint256 earnedRewardRecentIgnored; } struct VaultRewardInfo { uint256 timestamp; address vault; address reward; string rewardName; string rewardSymbol; uint8 rewardDecimals; address balanceTracker; uint256 epochDuration; uint256 currentEpoch; uint256 totalRewardedEligible; uint256 totalRewardRegistered; uint256 totalRewardClaimed; RewardAmountInfo[] epochInfoPrevious; RewardAmountInfo[] epochInfoUpcoming; } struct RewardAmountInfo { uint256 epoch; uint256 epochStart; uint256 epochEnd; uint256 rewardAmount; } struct OracleDetailedInfo { address oracle; string name; bytes oracleInfo; } struct EulerRouterInfo { address governor; address fallbackOracle; OracleDetailedInfo fallbackOracleInfo; address[] bases; address[] quotes; address[][] resolvedAssets; address[] resolvedOracles; OracleDetailedInfo[] resolvedOraclesInfo; } struct ChainlinkOracleInfo { address base; address quote; address feed; string feedDescription; uint256 maxStaleness; } struct ChainlinkInfrequentOracleInfo { address base; address quote; address feed; string feedDescription; uint256 maxStaleness; } struct ChronicleOracleInfo { address base; address quote; address feed; uint256 maxStaleness; } struct LidoOracleInfo { address base; address quote; } struct LidoFundamentalOracleInfo { address base; address quote; } struct PythOracleInfo { address pyth; address base; address quote; bytes32 feedId; uint256 maxStaleness; uint256 maxConfWidth; } struct RedstoneCoreOracleInfo { address base; address quote; bytes32 feedId; uint8 feedDecimals; uint256 maxStaleness; uint208 cachePrice; uint48 cachePriceTimestamp; } struct UniswapV3OracleInfo { address tokenA; address tokenB; address pool; uint24 fee; uint32 twapWindow; } struct FixedRateOracleInfo { address base; address quote; uint256 rate; } struct RateProviderOracleInfo { address base; address quote; address rateProvider; } struct PendleProviderOracleInfo { address base; address quote; address pendleMarket; uint32 twapWindow; } struct SwaapSafeguardProviderOracleInfo { address base; address quote; bytes32 poolId; } struct CrossAdapterInfo { address base; address cross; address quote; address oracleBaseCross; address oracleCrossQuote; OracleDetailedInfo oracleBaseCrossInfo; OracleDetailedInfo oracleCrossQuoteInfo; } struct EulerEarnVaultInfoFull { uint256 timestamp; address vault; string vaultName; string vaultSymbol; uint256 vaultDecimals; address asset; string assetName; string assetSymbol; uint256 assetDecimals; uint256 totalShares; uint256 totalAssets; uint256 totalAssetsDeposited; uint256 totalAssetsAllocated; uint256 totalAssetsAllocatable; uint256 totalAllocationPoints; uint256 interestAccrued; uint256 lastInterestUpdate; uint256 interestSmearEnd; uint256 interestLeft; uint256 lastHarvestTimestamp; uint256 interestSmearingPeriod; uint256 performanceFee; address feeReceiver; uint256 hookedOperations; address hookTarget; address evc; address balanceTracker; address permit2; bool isHarvestCoolDownCheckOn; EulerEarnVaultAccessControlInfo accessControlInfo; EulerEarnVaultStrategyInfo[] strategies; AssetPriceInfo backupAssetPriceInfo; OracleDetailedInfo backupAssetOracleInfo; } struct EulerEarnVaultAccessControlInfo { address[] defaultAdmins; address[] guardianAdmins; address[] strategyOperatorAdmins; address[] eulerEarnManagerAdmins; address[] withdrawalQueueManagerAdmins; address[] rebalancerAdmins; address[] guardians; address[] strategyOperators; address[] eulerEarnManagers; address[] withdrawalQueueManagers; address[] rebalancers; } struct EulerEarnVaultStrategyInfo { address strategy; uint256 assetsAllocated; uint256 allocationPoints; uint256 allocationCap; bool isInEmergency; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; import {IVault as IEVCVault} from "ethereum-vault-connector/interfaces/IVault.sol"; // Full interface of EVault and all it's modules /// @title IInitialize /// @notice Interface of the initialization module of EVault interface IInitialize { /// @notice Initialization of the newly deployed proxy contract /// @param proxyCreator Account which created the proxy or should be the initial governor function initialize(address proxyCreator) external; } /// @title IERC20 /// @notice Interface of the EVault's Initialize module interface IERC20 { /// @notice Vault share token (eToken) name, ie "Euler Vault: DAI" /// @return The name of the eToken function name() external view returns (string memory); /// @notice Vault share token (eToken) symbol, ie "eDAI" /// @return The symbol of the eToken function symbol() external view returns (string memory); /// @notice Decimals, the same as the asset's or 18 if the asset doesn't implement `decimals()` /// @return The decimals of the eToken function decimals() external view returns (uint8); /// @notice Sum of all eToken balances /// @return The total supply of the eToken function totalSupply() external view returns (uint256); /// @notice Balance of a particular account, in eTokens /// @param account Address to query /// @return The balance of the account function balanceOf(address account) external view returns (uint256); /// @notice Retrieve the current allowance /// @param holder The account holding the eTokens /// @param spender Trusted address /// @return The allowance from holder for spender function allowance(address holder, address spender) external view returns (uint256); /// @notice Transfer eTokens to another address /// @param to Recipient account /// @param amount In shares. /// @return True if transfer succeeded function transfer(address to, uint256 amount) external returns (bool); /// @notice Transfer eTokens from one address to another /// @param from This address must've approved the to address /// @param to Recipient account /// @param amount In shares /// @return True if transfer succeeded function transferFrom(address from, address to, uint256 amount) external returns (bool); /// @notice Allow spender to access an amount of your eTokens /// @param spender Trusted address /// @param amount Use max uint for "infinite" allowance /// @return True if approval succeeded function approve(address spender, uint256 amount) external returns (bool); } /// @title IToken /// @notice Interface of the EVault's Token module interface IToken is IERC20 { /// @notice Transfer the full eToken balance of an address to another /// @param from This address must've approved the to address /// @param to Recipient account /// @return True if transfer succeeded function transferFromMax(address from, address to) external returns (bool); } /// @title IERC4626 /// @notice Interface of an ERC4626 vault interface IERC4626 { /// @notice Vault's underlying asset /// @return The vault's underlying asset function asset() external view returns (address); /// @notice Total amount of managed assets, cash and borrows /// @return The total amount of assets function totalAssets() external view returns (uint256); /// @notice Calculate amount of assets corresponding to the requested shares amount /// @param shares Amount of shares to convert /// @return The amount of assets function convertToAssets(uint256 shares) external view returns (uint256); /// @notice Calculate amount of shares corresponding to the requested assets amount /// @param assets Amount of assets to convert /// @return The amount of shares function convertToShares(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of assets a user can deposit /// @param account Address to query /// @return The max amount of assets the account can deposit function maxDeposit(address account) external view returns (uint256); /// @notice Calculate an amount of shares that would be created by depositing assets /// @param assets Amount of assets deposited /// @return Amount of shares received function previewDeposit(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of shares a user can mint /// @param account Address to query /// @return The max amount of shares the account can mint function maxMint(address account) external view returns (uint256); /// @notice Calculate an amount of assets that would be required to mint requested amount of shares /// @param shares Amount of shares to be minted /// @return Required amount of assets function previewMint(uint256 shares) external view returns (uint256); /// @notice Fetch the maximum amount of assets a user is allowed to withdraw /// @param owner Account holding the shares /// @return The maximum amount of assets the owner is allowed to withdraw function maxWithdraw(address owner) external view returns (uint256); /// @notice Calculate the amount of shares that will be burned when withdrawing requested amount of assets /// @param assets Amount of assets withdrawn /// @return Amount of shares burned function previewWithdraw(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of shares a user is allowed to redeem for assets /// @param owner Account holding the shares /// @return The maximum amount of shares the owner is allowed to redeem function maxRedeem(address owner) external view returns (uint256); /// @notice Calculate the amount of assets that will be transferred when redeeming requested amount of shares /// @param shares Amount of shares redeemed /// @return Amount of assets transferred function previewRedeem(uint256 shares) external view returns (uint256); /// @notice Transfer requested amount of underlying tokens from sender to the vault pool in return for shares /// @param amount Amount of assets to deposit (use max uint256 for full underlying token balance) /// @param receiver An account to receive the shares /// @return Amount of shares minted /// @dev Deposit will round down the amount of assets that are converted to shares. To prevent losses consider using /// mint instead. function deposit(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer underlying tokens from sender to the vault pool in return for requested amount of shares /// @param amount Amount of shares to be minted /// @param receiver An account to receive the shares /// @return Amount of assets deposited function mint(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer requested amount of underlying tokens from the vault and decrease account's shares balance /// @param amount Amount of assets to withdraw /// @param receiver Account to receive the withdrawn assets /// @param owner Account holding the shares to burn /// @return Amount of shares burned function withdraw(uint256 amount, address receiver, address owner) external returns (uint256); /// @notice Burn requested shares and transfer corresponding underlying tokens from the vault to the receiver /// @param amount Amount of shares to burn (use max uint256 to burn full owner balance) /// @param receiver Account to receive the withdrawn assets /// @param owner Account holding the shares to burn. /// @return Amount of assets transferred function redeem(uint256 amount, address receiver, address owner) external returns (uint256); } /// @title IVault /// @notice Interface of the EVault's Vault module interface IVault is IERC4626 { /// @notice Balance of the fees accumulator, in shares /// @return The accumulated fees in shares function accumulatedFees() external view returns (uint256); /// @notice Balance of the fees accumulator, in underlying units /// @return The accumulated fees in asset units function accumulatedFeesAssets() external view returns (uint256); /// @notice Address of the original vault creator /// @return The address of the creator function creator() external view returns (address); /// @notice Creates shares for the receiver, from excess asset balances of the vault (not accounted for in `cash`) /// @param amount Amount of assets to claim (use max uint256 to claim all available assets) /// @param receiver An account to receive the shares /// @return Amount of shares minted /// @dev Could be used as an alternative deposit flow in certain scenarios. E.g. swap directly to the vault, call /// `skim` to claim deposit. function skim(uint256 amount, address receiver) external returns (uint256); } /// @title IBorrowing /// @notice Interface of the EVault's Borrowing module interface IBorrowing { /// @notice Sum of all outstanding debts, in underlying units (increases as interest is accrued) /// @return The total borrows in asset units function totalBorrows() external view returns (uint256); /// @notice Sum of all outstanding debts, in underlying units scaled up by shifting /// INTERNAL_DEBT_PRECISION_SHIFT bits /// @return The total borrows in internal debt precision function totalBorrowsExact() external view returns (uint256); /// @notice Balance of vault assets as tracked by deposits/withdrawals and borrows/repays /// @return The amount of assets the vault tracks as current direct holdings function cash() external view returns (uint256); /// @notice Debt owed by a particular account, in underlying units /// @param account Address to query /// @return The debt of the account in asset units function debtOf(address account) external view returns (uint256); /// @notice Debt owed by a particular account, in underlying units scaled up by shifting /// INTERNAL_DEBT_PRECISION_SHIFT bits /// @param account Address to query /// @return The debt of the account in internal precision function debtOfExact(address account) external view returns (uint256); /// @notice Retrieves the current interest rate for an asset /// @return The interest rate in yield-per-second, scaled by 10**27 function interestRate() external view returns (uint256); /// @notice Retrieves the current interest rate accumulator for an asset /// @return An opaque accumulator that increases as interest is accrued function interestAccumulator() external view returns (uint256); /// @notice Returns an address of the sidecar DToken /// @return The address of the DToken function dToken() external view returns (address); /// @notice Transfer underlying tokens from the vault to the sender, and increase sender's debt /// @param amount Amount of assets to borrow (use max uint256 for all available tokens) /// @param receiver Account receiving the borrowed tokens /// @return Amount of assets borrowed function borrow(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer underlying tokens from the sender to the vault, and decrease receiver's debt /// @param amount Amount of debt to repay in assets (use max uint256 for full debt) /// @param receiver Account holding the debt to be repaid /// @return Amount of assets repaid function repay(uint256 amount, address receiver) external returns (uint256); /// @notice Pay off liability with shares ("self-repay") /// @param amount In asset units (use max uint256 to repay the debt in full or up to the available deposit) /// @param receiver Account to remove debt from by burning sender's shares /// @return shares Amount of shares burned /// @return debt Amount of debt removed in assets /// @dev Equivalent to withdrawing and repaying, but no assets are needed to be present in the vault /// @dev Contrary to a regular `repay`, if account is unhealthy, the repay amount must bring the account back to /// health, or the operation will revert during account status check function repayWithShares(uint256 amount, address receiver) external returns (uint256 shares, uint256 debt); /// @notice Take over debt from another account /// @param amount Amount of debt in asset units (use max uint256 for all the account's debt) /// @param from Account to pull the debt from /// @dev Due to internal debt precision accounting, the liability reported on either or both accounts after /// calling `pullDebt` may not match the `amount` requested precisely function pullDebt(uint256 amount, address from) external; /// @notice Request a flash-loan. A onFlashLoan() callback in msg.sender will be invoked, which must repay the loan /// to the main Euler address prior to returning. /// @param amount In asset units /// @param data Passed through to the onFlashLoan() callback, so contracts don't need to store transient data in /// storage function flashLoan(uint256 amount, bytes calldata data) external; /// @notice Updates interest accumulator and totalBorrows, credits reserves, re-targets interest rate, and logs /// vault status function touch() external; } /// @title ILiquidation /// @notice Interface of the EVault's Liquidation module interface ILiquidation { /// @notice Checks to see if a liquidation would be profitable, without actually doing anything /// @param liquidator Address that will initiate the liquidation /// @param violator Address that may be in collateral violation /// @param collateral Collateral which is to be seized /// @return maxRepay Max amount of debt that can be repaid, in asset units /// @return maxYield Yield in collateral corresponding to max allowed amount of debt to be repaid, in collateral /// balance (shares for vaults) function checkLiquidation(address liquidator, address violator, address collateral) external view returns (uint256 maxRepay, uint256 maxYield); /// @notice Attempts to perform a liquidation /// @param violator Address that may be in collateral violation /// @param collateral Collateral which is to be seized /// @param repayAssets The amount of underlying debt to be transferred from violator to sender, in asset units (use /// max uint256 to repay the maximum possible amount). Meant as slippage check together with `minYieldBalance` /// @param minYieldBalance The minimum acceptable amount of collateral to be transferred from violator to sender, in /// collateral balance units (shares for vaults). Meant as slippage check together with `repayAssets` /// @dev If `repayAssets` is set to max uint256 it is assumed the caller will perform their own slippage checks to /// make sure they are not taking on too much debt. This option is mainly meant for smart contract liquidators function liquidate(address violator, address collateral, uint256 repayAssets, uint256 minYieldBalance) external; } /// @title IRiskManager /// @notice Interface of the EVault's RiskManager module interface IRiskManager is IEVCVault { /// @notice Retrieve account's total liquidity /// @param account Account holding debt in this vault /// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status /// check mode, where different LTV values might apply. /// @return collateralValue Total risk adjusted value of all collaterals in unit of account /// @return liabilityValue Value of debt in unit of account function accountLiquidity(address account, bool liquidation) external view returns (uint256 collateralValue, uint256 liabilityValue); /// @notice Retrieve account's liquidity per collateral /// @param account Account holding debt in this vault /// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status /// check mode, where different LTV values might apply. /// @return collaterals Array of collaterals enabled /// @return collateralValues Array of risk adjusted collateral values corresponding to items in collaterals array. /// In unit of account /// @return liabilityValue Value of debt in unit of account function accountLiquidityFull(address account, bool liquidation) external view returns (address[] memory collaterals, uint256[] memory collateralValues, uint256 liabilityValue); /// @notice Release control of the account on EVC if no outstanding debt is present function disableController() external; /// @notice Checks the status of an account and reverts if account is not healthy /// @param account The address of the account to be checked /// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when /// account status is valid, or revert otherwise. /// @dev Only callable by EVC during status checks function checkAccountStatus(address account, address[] calldata collaterals) external view returns (bytes4); /// @notice Checks the status of the vault and reverts if caps are exceeded /// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when /// account status is valid, or revert otherwise. /// @dev Only callable by EVC during status checks function checkVaultStatus() external returns (bytes4); } /// @title IBalanceForwarder /// @notice Interface of the EVault's BalanceForwarder module interface IBalanceForwarder { /// @notice Retrieve the address of rewards contract, tracking changes in account's balances /// @return The balance tracker address function balanceTrackerAddress() external view returns (address); /// @notice Retrieves boolean indicating if the account opted in to forward balance changes to the rewards contract /// @param account Address to query /// @return True if balance forwarder is enabled function balanceForwarderEnabled(address account) external view returns (bool); /// @notice Enables balance forwarding for the authenticated account /// @dev Only the authenticated account can enable balance forwarding for itself /// @dev Should call the IBalanceTracker hook with the current account's balance function enableBalanceForwarder() external; /// @notice Disables balance forwarding for the authenticated account /// @dev Only the authenticated account can disable balance forwarding for itself /// @dev Should call the IBalanceTracker hook with the account's balance of 0 function disableBalanceForwarder() external; } /// @title IGovernance /// @notice Interface of the EVault's Governance module interface IGovernance { /// @notice Retrieves the address of the governor /// @return The governor address function governorAdmin() external view returns (address); /// @notice Retrieves address of the governance fee receiver /// @return The fee receiver address function feeReceiver() external view returns (address); /// @notice Retrieves the interest fee in effect for the vault /// @return Amount of interest that is redirected as a fee, as a fraction scaled by 1e4 function interestFee() external view returns (uint16); /// @notice Looks up an asset's currently configured interest rate model /// @return Address of the interest rate contract or address zero to indicate 0% interest function interestRateModel() external view returns (address); /// @notice Retrieves the ProtocolConfig address /// @return The protocol config address function protocolConfigAddress() external view returns (address); /// @notice Retrieves the protocol fee share /// @return A percentage share of fees accrued belonging to the protocol, in 1e4 scale function protocolFeeShare() external view returns (uint256); /// @notice Retrieves the address which will receive protocol's fees /// @notice The protocol fee receiver address function protocolFeeReceiver() external view returns (address); /// @notice Retrieves supply and borrow caps in AmountCap format /// @return supplyCap The supply cap in AmountCap format /// @return borrowCap The borrow cap in AmountCap format function caps() external view returns (uint16 supplyCap, uint16 borrowCap); /// @notice Retrieves the borrow LTV of the collateral, which is used to determine if the account is healthy during /// account status checks. /// @param collateral The address of the collateral to query /// @return Borrowing LTV in 1e4 scale function LTVBorrow(address collateral) external view returns (uint16); /// @notice Retrieves the current liquidation LTV, which is used to determine if the account is eligible for /// liquidation /// @param collateral The address of the collateral to query /// @return Liquidation LTV in 1e4 scale function LTVLiquidation(address collateral) external view returns (uint16); /// @notice Retrieves LTV configuration for the collateral /// @param collateral Collateral asset /// @return borrowLTV The current value of borrow LTV for originating positions /// @return liquidationLTV The value of fully converged liquidation LTV /// @return initialLiquidationLTV The initial value of the liquidation LTV, when the ramp began /// @return targetTimestamp The timestamp when the liquidation LTV is considered fully converged /// @return rampDuration The time it takes for the liquidation LTV to converge from the initial value to the fully /// converged value function LTVFull(address collateral) external view returns ( uint16 borrowLTV, uint16 liquidationLTV, uint16 initialLiquidationLTV, uint48 targetTimestamp, uint32 rampDuration ); /// @notice Retrieves a list of collaterals with configured LTVs /// @return List of asset collaterals /// @dev Returned assets could have the ltv disabled (set to zero) function LTVList() external view returns (address[] memory); /// @notice Retrieves the maximum liquidation discount /// @return The maximum liquidation discount in 1e4 scale /// @dev The default value, which is zero, is deliberately bad, as it means there would be no incentive to liquidate /// unhealthy users. The vault creator must take care to properly select the limit, given the underlying and /// collaterals used. function maxLiquidationDiscount() external view returns (uint16); /// @notice Retrieves liquidation cool-off time, which must elapse after successful account status check before /// account can be liquidated /// @return The liquidation cool off time in seconds function liquidationCoolOffTime() external view returns (uint16); /// @notice Retrieves a hook target and a bitmask indicating which operations call the hook target /// @return hookTarget Address of the hook target contract /// @return hookedOps Bitmask with operations that should call the hooks. See Constants.sol for a list of operations function hookConfig() external view returns (address hookTarget, uint32 hookedOps); /// @notice Retrieves a bitmask indicating enabled config flags /// @return Bitmask with config flags enabled function configFlags() external view returns (uint32); /// @notice Address of EthereumVaultConnector contract /// @return The EVC address function EVC() external view returns (address); /// @notice Retrieves a reference asset used for liquidity calculations /// @return The address of the reference asset function unitOfAccount() external view returns (address); /// @notice Retrieves the address of the oracle contract /// @return The address of the oracle function oracle() external view returns (address); /// @notice Retrieves the Permit2 contract address /// @return The address of the Permit2 contract function permit2Address() external view returns (address); /// @notice Splits accrued fees balance according to protocol fee share and transfers shares to the governor fee /// receiver and protocol fee receiver function convertFees() external; /// @notice Set a new governor address /// @param newGovernorAdmin The new governor address /// @dev Set to zero address to renounce privileges and make the vault non-governed function setGovernorAdmin(address newGovernorAdmin) external; /// @notice Set a new governor fee receiver address /// @param newFeeReceiver The new fee receiver address function setFeeReceiver(address newFeeReceiver) external; /// @notice Set a new LTV config /// @param collateral Address of collateral to set LTV for /// @param borrowLTV New borrow LTV, for assessing account's health during account status checks, in 1e4 scale /// @param liquidationLTV New liquidation LTV after ramp ends in 1e4 scale /// @param rampDuration Ramp duration in seconds function setLTV(address collateral, uint16 borrowLTV, uint16 liquidationLTV, uint32 rampDuration) external; /// @notice Set a new maximum liquidation discount /// @param newDiscount New maximum liquidation discount in 1e4 scale /// @dev If the discount is zero (the default), the liquidators will not be incentivized to liquidate unhealthy /// accounts function setMaxLiquidationDiscount(uint16 newDiscount) external; /// @notice Set a new liquidation cool off time, which must elapse after successful account status check before /// account can be liquidated /// @param newCoolOffTime The new liquidation cool off time in seconds /// @dev Setting cool off time to zero allows liquidating the account in the same block as the last successful /// account status check function setLiquidationCoolOffTime(uint16 newCoolOffTime) external; /// @notice Set a new interest rate model contract /// @param newModel The new IRM address /// @dev If the new model reverts, perhaps due to governor error, the vault will silently use a zero interest /// rate. Governor should make sure the new interest rates are computed as expected. function setInterestRateModel(address newModel) external; /// @notice Set a new hook target and a new bitmap indicating which operations should call the hook target. /// Operations are defined in Constants.sol. /// @param newHookTarget The new hook target address. Use address(0) to simply disable hooked operations /// @param newHookedOps Bitmask with the new hooked operations /// @dev All operations are initially disabled in a newly created vault. The vault creator must set their /// own configuration to make the vault usable function setHookConfig(address newHookTarget, uint32 newHookedOps) external; /// @notice Set new bitmap indicating which config flags should be enabled. Flags are defined in Constants.sol /// @param newConfigFlags Bitmask with the new config flags function setConfigFlags(uint32 newConfigFlags) external; /// @notice Set new supply and borrow caps in AmountCap format /// @param supplyCap The new supply cap in AmountCap fromat /// @param borrowCap The new borrow cap in AmountCap fromat function setCaps(uint16 supplyCap, uint16 borrowCap) external; /// @notice Set a new interest fee /// @param newFee The new interest fee function setInterestFee(uint16 newFee) external; } /// @title IEVault /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Interface of the EVault, an EVC enabled lending vault interface IEVault is IInitialize, IToken, IVault, IBorrowing, ILiquidation, IRiskManager, IBalanceForwarder, IGovernance { /// @notice Fetch address of the `Initialize` module function MODULE_INITIALIZE() external view returns (address); /// @notice Fetch address of the `Token` module function MODULE_TOKEN() external view returns (address); /// @notice Fetch address of the `Vault` module function MODULE_VAULT() external view returns (address); /// @notice Fetch address of the `Borrowing` module function MODULE_BORROWING() external view returns (address); /// @notice Fetch address of the `Liquidation` module function MODULE_LIQUIDATION() external view returns (address); /// @notice Fetch address of the `RiskManager` module function MODULE_RISKMANAGER() external view returns (address); /// @notice Fetch address of the `BalanceForwarder` module function MODULE_BALANCE_FORWARDER() external view returns (address); /// @notice Fetch address of the `Governance` module function MODULE_GOVERNANCE() external view returns (address); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @custom:security-contact [email protected] /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) /// @author Modified by Euler Labs (https://www.eulerlabs.com/) to return an `overflow` bool instead of reverting library RPow { /// @dev If overflow is true, an overflow occurred and the value of z is undefined function rpow(uint256 x, uint256 n, uint256 scalar) internal pure returns (uint256 z, bool overflow) { /// @solidity memory-safe-assembly assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Bail if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { overflow := 1 break } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Bail if xx + half overflowed. if lt(xxRound, xx) { overflow := 1 break } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Bail if x is non-zero. if iszero(iszero(x)) { overflow := 1 break } } // Round to the nearest number. let zxRound := add(zx, half) // Bail if zx + half overflowed. if lt(zxRound, zx) { overflow := 1 break } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title IIRM /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Interface of the interest rate model contracts used by EVault interface IIRM { error E_IRMUpdateUnauthorized(); /// @notice Perform potentially state mutating computation of the new interest rate /// @param vault Address of the vault to compute the new interest rate for /// @param cash Amount of assets held directly by the vault /// @param borrows Amount of assets lent out to borrowers by the vault /// @return Then new interest rate in second percent yield (SPY), scaled by 1e27 function computeInterestRate(address vault, uint256 cash, uint256 borrows) external returns (uint256); /// @notice Perform computation of the new interest rate without mutating state /// @param vault Address of the vault to compute the new interest rate for /// @param cash Amount of assets held directly by the vault /// @param borrows Amount of assets lent out to borrowers by the vault /// @return Then new interest rate in second percent yield (SPY), scaled by 1e27 function computeInterestRateView(address vault, uint256 cash, uint256 borrows) external view returns (uint256); }
// SPDX-License-Identifier: MIT // Copyright (c) 2023 Morpho Association pragma solidity ^0.8.0; /// @title ExpLib /// @custom:contact [email protected] /// @author Adapted from Morpho Labs /// (https://github.com/morpho-org/morpho-blue-irm/blob/a824ce06a53f45f12d0ffedb51abd756896b29fa/src/adaptive-curve-irm/libraries/ExpLib.sol) /// @notice Library to approximate the exponential function. library ExpLib { int256 internal constant WAD = 1e18; /// @dev ln(2). int256 internal constant LN_2_INT = 0.693147180559945309e18; /// @dev ln(1e-18). int256 internal constant LN_WEI_INT = -41.446531673892822312e18; /// @dev Above this bound, `wExp` is clipped to avoid overflowing when multiplied with 1e18. /// @dev This upper bound corresponds to: ln(type(int256).max / 1e36) (scaled by WAD, floored). int256 internal constant WEXP_UPPER_BOUND = 93.859467695000404319e18; /// @dev The value of wExp(`WEXP_UPPER_BOUND`). int256 internal constant WEXP_UPPER_VALUE = 57716089161558943949701069502944508345128.422502756744429568e18; /// @dev Returns an approximation of exp. function wExp(int256 x) internal pure returns (int256) { unchecked { // If x < ln(1e-18) then exp(x) < 1e-18 so it is rounded to zero. if (x < LN_WEI_INT) return 0; // `wExp` is clipped to avoid overflowing when multiplied with 1e18. if (x >= WEXP_UPPER_BOUND) return WEXP_UPPER_VALUE; // Decompose x as x = q * ln(2) + r with q an integer and -ln(2)/2 <= r <= ln(2)/2. // q = x / ln(2) rounded half toward zero. int256 roundingAdjustment = (x < 0) ? -(LN_2_INT / 2) : (LN_2_INT / 2); // Safe unchecked because x is bounded. int256 q = (x + roundingAdjustment) / LN_2_INT; // Safe unchecked because |q * ln(2) - x| <= ln(2)/2. int256 r = x - q * LN_2_INT; // Compute e^r with a 2nd-order Taylor polynomial. // Safe unchecked because |r| < 1e18. int256 expR = WAD + r + (r * r) / WAD / 2; // Return e^x = 2^q * e^r. if (q >= 0) return expR << uint256(q); else return expR >> uint256(-q); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title IVault /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice This interface defines the methods for the Vault for the purpose of integration with the Ethereum Vault /// Connector. interface IVault { /// @notice Disables a controller (this vault) for the authenticated account. /// @dev A controller is a vault that has been chosen for an account to have special control over account’s /// balances in the enabled collaterals vaults. User calls this function in order for the vault to disable itself /// for the account if the conditions are met (i.e. user has repaid debt in full). If the conditions are not met, /// the function reverts. function disableController() external; /// @notice Checks the status of an account. /// @dev This function must only deliberately revert if the account status is invalid. If this function reverts due /// to any other reason, it may render the account unusable with possibly no way to recover funds. /// @param account The address of the account to be checked. /// @param collaterals The array of enabled collateral addresses to be considered for the account status check. /// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when /// account status is valid, or revert otherwise. function checkAccountStatus( address account, address[] calldata collaterals ) external view returns (bytes4 magicValue); /// @notice Checks the status of the vault. /// @dev This function must only deliberately revert if the vault status is invalid. If this function reverts due to /// any other reason, it may render some accounts unusable with possibly no way to recover funds. /// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when /// account status is valid, or revert otherwise. function checkVaultStatus() external returns (bytes4 magicValue); }
{ "remappings": [ "lib/euler-price-oracle:@openzeppelin/contracts/=lib/euler-price-oracle/lib/openzeppelin-contracts/contracts/", "lib/native-token-transfers/evm:openzeppelin-contracts/contracts/=lib/native-token-transfers/evm/lib/openzeppelin-contracts/contracts/", "lib/euler-earn:@openzeppelin/=lib/euler-earn/lib/openzeppelin-contracts/", "lib/euler-earn:@openzeppelin-upgradeable/=lib/euler-earn/lib/openzeppelin-contracts-upgradeable/contracts/", "lib/euler-earn:ethereum-vault-connector/=lib/euler-earn/lib/ethereum-vault-connector/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "ethereum-vault-connector/=lib/ethereum-vault-connector/src/", "evc/=lib/ethereum-vault-connector/src/", "evk/=lib/euler-vault-kit/src/", "evk-test/=lib/euler-vault-kit/test/", "euler-price-oracle/=lib/euler-price-oracle/src/", "euler-price-oracle-test/=lib/euler-price-oracle/test/", "fee-flow/=lib/fee-flow/src/", "reward-streams/=lib/reward-streams/src/", "@openzeppelin/=lib/openzeppelin-contracts/contracts/", "euler-earn/=lib/euler-earn/src/", "native-token-transfers/=lib/native-token-transfers/evm/src/", "@openzeppelin-upgradeable/=lib/euler-earn/lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@pendle/core-v2/=lib/euler-price-oracle/lib/pendle-core-v2-public/contracts/", "@pyth/=lib/euler-price-oracle/lib/pyth-sdk-solidity/", "@redstone/evm-connector/=lib/euler-price-oracle/lib/redstone-oracles-monorepo/packages/evm-connector/contracts/", "@solady/=lib/euler-price-oracle/lib/solady/src/", "@uniswap/v3-core/=lib/euler-price-oracle/lib/v3-core/", "@uniswap/v3-periphery/=lib/euler-price-oracle/lib/v3-periphery/", "ERC4626/=lib/euler-earn/lib/properties/lib/ERC4626/contracts/", "crytic-properties/=lib/euler-earn/lib/properties/contracts/", "ds-test/=lib/ethereum-vault-connector/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "euler-vault-kit/=lib/euler-vault-kit/", "forge-gas-snapshot/=lib/euler-vault-kit/lib/permit2/lib/forge-gas-snapshot/src/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/", "layerzero-devtools/=lib/layerzero-devtools/packages/toolbox-foundry/src/", "layerzero-v2/=lib/layerzero-v2/", "openzeppelin/=lib/ethereum-vault-connector/lib/openzeppelin-contracts/contracts/", "pendle-core-v2-public/=lib/euler-price-oracle/lib/pendle-core-v2-public/contracts/", "permit2/=lib/euler-vault-kit/lib/permit2/", "properties/=lib/euler-earn/lib/properties/contracts/", "pyth-sdk-solidity/=lib/euler-price-oracle/lib/pyth-sdk-solidity/", "redstone-oracles-monorepo/=lib/euler-price-oracle/lib/", "solady/=lib/euler-price-oracle/lib/solady/src/", "solidity-bytes-utils/=lib/native-token-transfers/evm/lib/solidity-bytes-utils/contracts/", "solmate/=lib/fee-flow/lib/solmate/src/", "v3-core/=lib/euler-price-oracle/lib/v3-core/contracts/", "v3-periphery/=lib/euler-price-oracle/lib/v3-periphery/contracts/", "wormhole-solidity-sdk/=lib/native-token-transfers/evm/lib/wormhole-solidity-sdk/src/" ], "optimizer": { "enabled": true, "runs": 20000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_kinkIRMFactory","type":"address"},{"internalType":"address","name":"_adaptiveCurveIRMFactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"TTL_ERROR","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TTL_INFINITY","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TTL_LIQUIDATION","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TTL_MORE_THAN_ONE_YEAR","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adaptiveCurveIRMFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"irm","type":"address"}],"name":"getInterestRateModelInfo","outputs":[{"components":[{"internalType":"address","name":"interestRateModel","type":"address"},{"internalType":"enum InterestRateModelType","name":"interestRateModelType","type":"uint8"},{"internalType":"bytes","name":"interestRateModelParams","type":"bytes"}],"internalType":"struct InterestRateModelDetailedInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kinkIRMFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c060405234801561000f575f80fd5b50604051610b9e380380610b9e83398101604081905261002e91610060565b6001600160a01b039182166080521660a052610091565b80516001600160a01b038116811461005b575f80fd5b919050565b5f8060408385031215610071575f80fd5b61007a83610045565b915061008860208401610045565b90509250929050565b60805160a051610ade6100c05f395f8181610113015261056601525f818161015f01526102710152610ade5ff3fe608060405234801561000f575f80fd5b506004361061007a575f3560e01c8063900bb8a611610058578063900bb8a6146100e7578063946ee3511461010e578063f546ff5a1461015a578063f8fb7a7b14610181575f80fd5b80634abee02a1461007e5780636410b7921461009957806372537d9a146100c0575b5f80fd5b6100866101a1565b6040519081526020015b60405180910390f35b6100867ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81565b6100867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6100867f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6101357f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610090565b6101357f000000000000000000000000000000000000000000000000000000000000000081565b61019461018f366004610919565b6101cf565b6040516100909190610953565b6101cc60017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610a27565b81565b60408051606080820183525f80835260208301529181019190915260408051606080820183525f80835260208301529181019190915273ffffffffffffffffffffffffffffffffffffffff83166102265792915050565b73ffffffffffffffffffffffffffffffffffffffff8381168083526040517f6ee0787a00000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000090911690636ee0787a90602401602060405180830381865afa1580156102b8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102dc9190610a72565b1561052157600160208201818152505060405180608001604052808473ffffffffffffffffffffffffffffffffffffffff16631f68f20a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610340573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103649190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663a62b75a86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103d69190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663d0134cb76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610424573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104489190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fd2da3396040518163ffffffff1660e01b8152600401602060405180830381865afa158015610496573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ba9190610a91565b9052604080518251602080830191909152830151818301529082015160608083019190915290910151608082015260a001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152820152610913565b6040517f6ee0787a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f00000000000000000000000000000000000000000000000000000000000000001690636ee0787a90602401602060405180830381865afa1580156105ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105cf9190610a72565b156109135760026020820181815250506040518060c001604052808473ffffffffffffffffffffffffffffffffffffffff16639a1a14d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610633573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106579190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663d91042b56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106c99190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663019ec38b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610717573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073b9190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff166358f5cbad6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610789573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ad9190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fc4c2d546040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107fb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061081f9190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff16635a92fa856040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108919190610a91565b90526040516108e191906020015f60c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528201525b92915050565b5f60208284031215610929575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461094c575f80fd5b9392505050565b5f602080835273ffffffffffffffffffffffffffffffffffffffff84511660208401526020840151600381106109b0577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b80604085015250604084015160608085015280518060808601525f5b818110156109e85782810184015186820160a0015283016109cc565b505f60a0828701015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116860101935050505092915050565b8181035f831280158383131683831282161715610a6b577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5092915050565b5f60208284031215610a82575f80fd5b8151801515811461094c575f80fd5b5f60208284031215610aa1575f80fd5b505191905056fea26469706673582212206efcc3e620e7ee2c4217fe25870db347eac95a1270a085cab87362d8a9cfca5e64736f6c6343000818003300000000000000000000000052e856790779fd4fca34ba52c67cd191338572c000000000000000000000000041ac752453d258d2de4ead3887356a3949c95b25
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061007a575f3560e01c8063900bb8a611610058578063900bb8a6146100e7578063946ee3511461010e578063f546ff5a1461015a578063f8fb7a7b14610181575f80fd5b80634abee02a1461007e5780636410b7921461009957806372537d9a146100c0575b5f80fd5b6100866101a1565b6040519081526020015b60405180910390f35b6100867ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81565b6100867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6100867f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6101357f00000000000000000000000041ac752453d258d2de4ead3887356a3949c95b2581565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610090565b6101357f00000000000000000000000052e856790779fd4fca34ba52c67cd191338572c081565b61019461018f366004610919565b6101cf565b6040516100909190610953565b6101cc60017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610a27565b81565b60408051606080820183525f80835260208301529181019190915260408051606080820183525f80835260208301529181019190915273ffffffffffffffffffffffffffffffffffffffff83166102265792915050565b73ffffffffffffffffffffffffffffffffffffffff8381168083526040517f6ee0787a00000000000000000000000000000000000000000000000000000000815260048101919091527f00000000000000000000000052e856790779fd4fca34ba52c67cd191338572c090911690636ee0787a90602401602060405180830381865afa1580156102b8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102dc9190610a72565b1561052157600160208201818152505060405180608001604052808473ffffffffffffffffffffffffffffffffffffffff16631f68f20a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610340573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103649190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663a62b75a86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103d69190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663d0134cb76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610424573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104489190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fd2da3396040518163ffffffff1660e01b8152600401602060405180830381865afa158015610496573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ba9190610a91565b9052604080518251602080830191909152830151818301529082015160608083019190915290910151608082015260a001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152820152610913565b6040517f6ee0787a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f00000000000000000000000041ac752453d258d2de4ead3887356a3949c95b251690636ee0787a90602401602060405180830381865afa1580156105ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105cf9190610a72565b156109135760026020820181815250506040518060c001604052808473ffffffffffffffffffffffffffffffffffffffff16639a1a14d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610633573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106579190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663d91042b56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106c99190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663019ec38b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610717573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073b9190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff166358f5cbad6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610789573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ad9190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fc4c2d546040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107fb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061081f9190610a91565b81526020018473ffffffffffffffffffffffffffffffffffffffff16635a92fa856040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108919190610a91565b90526040516108e191906020015f60c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528201525b92915050565b5f60208284031215610929575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461094c575f80fd5b9392505050565b5f602080835273ffffffffffffffffffffffffffffffffffffffff84511660208401526020840151600381106109b0577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b80604085015250604084015160608085015280518060808601525f5b818110156109e85782810184015186820160a0015283016109cc565b505f60a0828701015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116860101935050505092915050565b8181035f831280158383131683831282161715610a6b577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5092915050565b5f60208284031215610a82575f80fd5b8151801515811461094c575f80fd5b5f60208284031215610aa1575f80fd5b505191905056fea26469706673582212206efcc3e620e7ee2c4217fe25870db347eac95a1270a085cab87362d8a9cfca5e64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000052e856790779fd4fca34ba52c67cd191338572c000000000000000000000000041ac752453d258d2de4ead3887356a3949c95b25
-----Decoded View---------------
Arg [0] : _kinkIRMFactory (address): 0x52E856790779fD4fCa34bA52C67Cd191338572C0
Arg [1] : _adaptiveCurveIRMFactory (address): 0x41AC752453d258d2de4eAd3887356a3949C95b25
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000052e856790779fd4fca34ba52c67cd191338572c0
Arg [1] : 00000000000000000000000041ac752453d258d2de4ead3887356a3949c95b25
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.