Overview
S Balance
S Value
$0.00Cross-Chain Transactions
Loading...
Loading
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 {IRMLinearKinky} from "../IRM/IRMLinearKinky.sol";
import {IRMFixedCyclicalBinary} from "../IRM/IRMFixedCyclicalBinary.sol";
import "./LensTypes.sol";
contract IRMLens is Utils {
address public immutable kinkIRMFactory;
address public immutable adaptiveCurveIRMFactory;
address public immutable kinkyIRMFactory;
address public immutable fixedCyclicalBinaryIRMFactory;
constructor(
address _kinkIRMFactory,
address _adaptiveCurveIRMFactory,
address _kinkyIRMFactory,
address _fixedCyclicalBinaryIRMFactory
) {
kinkIRMFactory = _kinkIRMFactory;
adaptiveCurveIRMFactory = _adaptiveCurveIRMFactory;
kinkyIRMFactory = _kinkyIRMFactory;
fixedCyclicalBinaryIRMFactory = _fixedCyclicalBinaryIRMFactory;
}
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()
})
);
} else if (IFactory(kinkyIRMFactory).isValidDeployment(irm)) {
result.interestRateModelType = InterestRateModelType.KINKY;
result.interestRateModelParams = abi.encode(
KinkyIRMInfo({
baseRate: IRMLinearKinky(irm).baseRate(),
slope: IRMLinearKinky(irm).slope(),
shape: IRMLinearKinky(irm).shape(),
kink: IRMLinearKinky(irm).kink(),
cutoff: IRMLinearKinky(irm).cutoff()
})
);
} else if (IFactory(fixedCyclicalBinaryIRMFactory).isValidDeployment(irm)) {
result.interestRateModelType = InterestRateModelType.FIXED_CYCLICAL_BINARY;
result.interestRateModelParams = abi.encode(
FixedCyclicalBinaryIRMInfo({
primaryRate: IRMFixedCyclicalBinary(irm).primaryRate(),
secondaryRate: IRMFixedCyclicalBinary(irm).secondaryRate(),
primaryDuration: IRMFixedCyclicalBinary(irm).primaryDuration(),
secondaryDuration: IRMFixedCyclicalBinary(irm).secondaryDuration(),
startTimestamp: IRMFixedCyclicalBinary(irm).startTimestamp()
})
);
}
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 == 130 || block.chainid == 8453 || block.chainid == 1923
|| block.chainid == 480 || block.chainid == 57073 || block.chainid == 60808
) {
return 0x4200000000000000000000000000000000000006;
} else if (block.chainid == 56) {
return 0x2170Ed0880ac9A755fd29B2688956BD959F933F8;
} else if (block.chainid == 100) {
return 0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1;
} 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 if (block.chainid == 80094) {
return 0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590;
} else {
// bitcoin-specific and test networks
if (
block.chainid == 30 || block.chainid == 21000000 || block.chainid == 10143 || block.chainid == 80084
|| block.chainid == 2390
) {
return address(0);
}
// hyperEVM
if (block.chainid == 999) {
return address(0);
}
// TAC
if (block.chainid == 239) {
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();
// Do not update state until the first borrow.
if (borrows == 0 && irState[vault].lastUpdate == 0) {
return uint256(_curve(INITIAL_RATE_AT_TARGET, _calcErr(0))) * 1e9;
}
int256 utilization = _calcUtilization(cash, borrows);
(uint256 rate, uint256 rateAtTarget) = computeInterestRateInternal(vault, utilization);
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 normalized distance using previous utilization for curve shifting
int256 lastUtilization = irState[vault].lastUpdate == 0 ? utilization : int256(irState[vault].lastUtilization);
int256 errOld = _calcErr(lastUtilization);
// Calculate normalized distance using current utilization for position on curve
int256 errNew = _calcErr(utilization);
IRState memory state = irState[vault];
int256 startRateAtTarget = int256(uint256(state.rateAtTarget));
int256 endRateAtTarget;
if (startRateAtTarget == 0) {
// First interaction.
endRateAtTarget = INITIAL_RATE_AT_TARGET;
} else {
// Use errOld for curve shifting
int256 speed = ADJUSTMENT_SPEED * errOld / 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);
}
}
// Use errNew for position on curve to get current interest rate
return (uint256(_curve(endRateAtTarget, errNew)), 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 normalized distance between the utilization and target utilization.
/// @param utilization The utilization rate.
/// @return The normalized distance between the utilization and target utilization.
function _calcErr(int256 utilization) internal view returns (int256) {
int256 errNormFactor = utilization > TARGET_UTILIZATION ? WAD - TARGET_UTILIZATION : TARGET_UTILIZATION;
return (utilization - TARGET_UTILIZATION) * WAD / errNormFactor;
}
/// @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;
import {IIRM} from "evk/InterestRateModels/IIRM.sol";
/// @title IRMLinearKinky
/// @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
/// non-linearly after reaching kink
contract IRMLinearKinky 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 slope;
/// @notice Shape parameter for the non-linear part of the curve. Typically between 0 and 100.
uint256 public immutable shape;
/// @notice Utilization at which the slope of the interest rate function changes. In type(uint32).max scale.
uint256 public immutable kink;
/// @notice Interest rate in second percent yield (SPY) at which the interest rate function is capped
uint256 public immutable cutoff;
/// @notice Remaining kink helper constant.
uint256 internal immutable kinkRemaining;
/// @notice Creates a new linear kinky interest rate model
/// @param baseRate_ Base interest rate applied when utilization is equal zero
/// @param slope_ Slope of the function before the kink
/// @param shape_ Shape parameter for the non-linear part of the curve. Typically between 0 and 100
/// @param kink_ Utilization at which the slope of the interest rate function changes. In type(uint32).max scale
/// @param cutoff_ Interest rate in second percent yield (SPY) at which the interest rate function is capped
constructor(uint256 baseRate_, uint256 slope_, uint256 shape_, uint32 kink_, uint256 cutoff_) {
baseRate = baseRate_;
slope = slope_;
shape = shape_;
kink = kink_;
cutoff = cutoff_;
kinkRemaining = type(uint32).max - 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 * slope;
} else {
ir += kink * slope;
uint256 utilizationOverKink;
uint256 utilizationRemaining;
unchecked {
utilizationOverKink = utilization - kink;
utilizationRemaining = type(uint32).max - utilization;
}
if (utilizationRemaining == 0) return cutoff;
uint256 slopeUtilizationOverKink = slope * utilizationOverKink;
ir += slopeUtilizationOverKink * kinkRemaining * (1 + shape) / utilizationRemaining
- slopeUtilizationOverKink * shape;
}
return ir > cutoff ? cutoff : ir;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {IIRM} from "evk/InterestRateModels/IIRM.sol";
/// @title IRMFixedCyclicalBinary
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Implementation of an interest rate model, where interest rate cycles between two fixed values,
contract IRMFixedCyclicalBinary is IIRM {
/// @notice Interest rate applied during the first part of the cycle
uint256 public immutable primaryRate;
/// @notice Interest rate applied during the second part of the cycle
uint256 public immutable secondaryRate;
/// @notice Duration of the primary part of the cycle in seconds
uint256 public immutable primaryDuration;
/// @notice Duration of the secondary part of the cycle in seconds
uint256 public immutable secondaryDuration;
/// @notice Timestamp of the start of the first cycle
uint256 public immutable startTimestamp;
/// @notice Error thrown when start timestamp is in the future
error BadStartTimestamp();
/// @notice Error thrown when duration of either primary or secondary part of the cycle is zero
/// or when the whole cycle duration overflows uint
error BadDuration();
/// @notice Creates a fixed cyclical binary interest rate model
/// @param primaryRate_ Interest rate applied during the first part of the cycle
/// @param secondaryRate_ Interest rate applied during the second part of the cycle
/// @param primaryDuration_ Duration of the primary part of the cycle in seconds
/// @param secondaryDuration_ Duration of the secondary part of the cycle in seconds
/// @param startTimestamp_ Timestamp of the start of the first cycle
constructor(
uint256 primaryRate_,
uint256 secondaryRate_,
uint256 primaryDuration_,
uint256 secondaryDuration_,
uint256 startTimestamp_
) {
if (startTimestamp_ > block.timestamp) revert BadStartTimestamp();
if (
primaryDuration_ == 0 || secondaryDuration_ == 0
|| (type(uint256).max - primaryDuration_ < secondaryDuration_)
) revert BadDuration();
primaryRate = primaryRate_;
secondaryRate = secondaryRate_;
primaryDuration = primaryDuration_;
secondaryDuration = secondaryDuration_;
startTimestamp = startTimestamp_;
}
/// @inheritdoc IIRM
function computeInterestRate(address vault, uint256, uint256) external view override returns (uint256) {
if (msg.sender != vault) revert E_IRMUpdateUnauthorized();
return computeInterestRateInternal();
}
/// @inheritdoc IIRM
function computeInterestRateView(address, uint256, uint256) external view override returns (uint256) {
return computeInterestRateInternal();
}
function computeInterestRateInternal() internal view returns (uint256) {
uint256 timeSinceStart = block.timestamp - startTimestamp;
return timeSinceStart % (primaryDuration + secondaryDuration) <= primaryDuration ? primaryRate : secondaryRate;
}
}// 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 VaultInfoERC4626 {
uint256 timestamp;
address vault;
string vaultName;
string vaultSymbol;
uint256 vaultDecimals;
address asset;
string assetName;
string assetSymbol;
uint256 assetDecimals;
uint256 totalShares;
uint256 totalAssets;
bool isEVault;
}
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,
KINKY,
FIXED_CYCLICAL_BINARY
}
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 KinkyIRMInfo {
uint256 baseRate;
uint256 slope;
uint256 shape;
uint256 kink;
uint256 cutoff;
}
struct FixedCyclicalBinaryIRMInfo {
uint256 primaryRate;
uint256 secondaryRate;
uint256 primaryDuration;
uint256 secondaryDuration;
uint256 startTimestamp;
}
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 OndoOracleInfo {
address base;
address quote;
address rwaOracle;
}
struct PendleProviderOracleInfo {
address base;
address quote;
address pendleMarket;
uint32 twapWindow;
}
struct PendleUniversalOracleInfo {
address base;
address quote;
address pendleMarket;
uint32 twapWindow;
}
struct CurveEMAOracleInfo {
address base;
address quote;
address pool;
uint256 priceOracleIndex;
}
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 lostAssets;
uint256 availableAssets;
uint256 timelock;
uint256 performanceFee;
address feeReceiver;
address owner;
address creator;
address curator;
address guardian;
address evc;
address permit2;
uint256 pendingTimelock;
uint256 pendingTimelockValidAt;
address pendingGuardian;
uint256 pendingGuardianValidAt;
address[] supplyQueue;
EulerEarnVaultStrategyInfo[] strategies;
}
struct EulerEarnVaultStrategyInfo {
address strategy;
uint256 allocatedAssets;
uint256 availableAssets;
uint256 currentAllocationCap;
uint256 pendingAllocationCap;
uint256 pendingAllocationCapValidAt;
uint256 removableAt;
VaultInfoERC4626 info;
}// 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/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/",
"lib/layerzero-devtools/packages/oft-evm/contracts:@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts/contracts/",
"lib/layerzero-devtools/packages/oft-evm-upgradeable/contracts:@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"lib/layerzero-devtools/packages/oapp-evm-upgradeable/contracts:@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@layerzerolabs/oft-evm/=lib/layerzero-devtools/packages/oft-evm/",
"@layerzerolabs/oapp-evm/=lib/layerzero-devtools/packages/oapp-evm/",
"@layerzerolabs/oapp-evm-upgradeable/=lib/layerzero-devtools/packages/oapp-evm-upgradeable/",
"@layerzerolabs/lz-evm-protocol-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/protocol/",
"@layerzerolabs/lz-evm-messagelib-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/messagelib/",
"@layerzerolabs/lz-evm-oapp-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/oapp/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"lib/fee-flow/src:solmate/=lib/fee-flow/lib/solmate/src/",
"lib/fee-flow/utils:solmate/=lib/fee-flow/lib/solmate/utils/",
"lib/fee-flow/tokens:solmate/=lib/fee-flow/lib/solmate/tokens/",
"lib/euler-swap:solmate/=lib/euler-swap/lib/euler-vault-kit/lib/permit2/lib/solmate/",
"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/contracts/=lib/openzeppelin-contracts/contracts/",
"euler-earn/=lib/euler-earn/src/",
"layerzero/oft-evm/=lib/layerzero-devtools/packages/oft-evm/contracts/",
"layerzero/oft-evm-upgradeable/=lib/layerzero-devtools/packages/oft-evm-upgradeable/contracts/",
"solidity-bytes-utils/=lib/solidity-bytes-utils/",
"@ensdomains/=lib/euler-swap/lib/v4-periphery/lib/v4-core/node_modules/@ensdomains/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/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/",
"@uniswap/v4-core/=lib/euler-swap/lib/v4-periphery/lib/v4-core/",
"ds-test/=lib/ethereum-vault-connector/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"euler-swap/=lib/euler-swap/",
"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/",
"hardhat/=lib/euler-swap/lib/v4-periphery/lib/v4-core/node_modules/hardhat/",
"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/",
"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/",
"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/",
"v4-core/=lib/euler-swap/lib/v4-periphery/lib/v4-core/src/",
"v4-periphery/=lib/euler-swap/lib/v4-periphery/"
],
"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
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_kinkIRMFactory","type":"address"},{"internalType":"address","name":"_adaptiveCurveIRMFactory","type":"address"},{"internalType":"address","name":"_kinkyIRMFactory","type":"address"},{"internalType":"address","name":"_fixedCyclicalBinaryIRMFactory","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":[],"name":"fixedCyclicalBinaryIRMFactory","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"},{"inputs":[],"name":"kinkyIRMFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
61010060405234801562000011575f80fd5b50604051620012c7380380620012c7833981016040819052620000349162000073565b6001600160a01b0393841660805291831660a052821660c0521660e052620000cd565b80516001600160a01b03811681146200006e575f80fd5b919050565b5f805f806080858703121562000087575f80fd5b620000928562000057565b9350620000a26020860162000057565b9250620000b26040860162000057565b9150620000c26060860162000057565b905092959194509250565b60805160a05160c05160e0516111ab6200011c5f395f818160c30152610caa01525f81816101ab015261099a01525f818161018401526105da01525f81816101d201526102e401526111ab5ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c8063900bb8a611610072578063ee29dfc311610058578063ee29dfc3146101a6578063f546ff5a146101cd578063f8fb7a7b146101f4575f80fd5b8063900bb8a614610158578063946ee3511461017f575f80fd5b80634abee02a146100a35780635cfd4528146100be5780636410b7921461010a57806372537d9a14610131575b5f80fd5b6100ab610214565b6040519081526020015b60405180910390f35b6100e57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b6100ab7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81565b6100ab7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6100ab7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6100e57f000000000000000000000000000000000000000000000000000000000000000081565b6100e57f000000000000000000000000000000000000000000000000000000000000000081565b6100e57f000000000000000000000000000000000000000000000000000000000000000081565b610207610202366004610fad565b610242565b6040516100b59190610fe7565b61023f60017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6110bb565b81565b60408051606080820183525f80835260208301529181019190915260408051606080820183525f80835260208301529181019190915273ffffffffffffffffffffffffffffffffffffffff83166102995792915050565b73ffffffffffffffffffffffffffffffffffffffff8381168083526040517f6ee0787a00000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000090911690636ee0787a90602401602060405180830381865afa15801561032b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061034f9190611106565b1561059557600160208201818152505060405180608001604052808473ffffffffffffffffffffffffffffffffffffffff16631f68f20a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103d79190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663a62b75a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610425573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104499190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663d0134cb76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610497573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104bb9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fd2da3396040518163ffffffff1660e01b8152600401602060405180830381865afa158015610509573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061052d9190611125565b9052604080518251602080830191909152830151818301529082015160608083019190915290910151608082015260a0015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152820152610fa7565b6040517f6ee0787a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f00000000000000000000000000000000000000000000000000000000000000001690636ee0787a90602401602060405180830381865afa15801561061f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106439190611106565b156109555760026020820181815250506040518060c001604052808473ffffffffffffffffffffffffffffffffffffffff16639a1a14d96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106cb9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663d91042b56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610719573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073d9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663019ec38b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561078b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107af9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff166358f5cbad6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108219190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fc4c2d546040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108939190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff16635a92fa856040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109059190611125565b905260405161055f91906020015f60c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6040517f6ee0787a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f00000000000000000000000000000000000000000000000000000000000000001690636ee0787a90602401602060405180830381865afa1580156109df573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a039190611106565b15610c655760036020820181815250506040518060a001604052808473ffffffffffffffffffffffffffffffffffffffff16631f68f20a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a67573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8b9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff166383caf2756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ad9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610afd9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff16630f7514a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b4b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6f9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fd2da3396040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be19190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff166354b02ba46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c2f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c539190611125565b905260405161055f919060200161113c565b6040517f6ee0787a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f00000000000000000000000000000000000000000000000000000000000000001690636ee0787a90602401602060405180830381865afa158015610cef573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d139190611106565b15610fa75760046020820181815250506040518060a001604052808473ffffffffffffffffffffffffffffffffffffffff1663fd4796c26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d9b9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663438895f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610de9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e0d9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663b8caceb16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e5b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e7f9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff16634c15a12d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ecd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef19190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663e6fd48bc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f3f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f639190611125565b9052604051610f75919060200161113c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528201525b92915050565b5f60208284031215610fbd575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610fe0575f80fd5b9392505050565b5f602080835273ffffffffffffffffffffffffffffffffffffffff8451166020840152602084015160058110611044577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b80604085015250604084015160608085015280518060808601525f5b8181101561107c5782810184015186820160a001528301611060565b505f60a0828701015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116860101935050505092915050565b8181035f8312801583831316838312821617156110ff577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5092915050565b5f60208284031215611116575f80fd5b81518015158114610fe0575f80fd5b5f60208284031215611135575f80fd5b5051919050565b60a08101610fa782848051825260208101516020830152604081015160408301526060810151606083015260808101516080830152505056fea264697066735822122074d0201d3cb138234d2d3a11e5a593b92f2d28e4d21c088c3df0bab3a1e13f6864736f6c6343000818003300000000000000000000000052e856790779fd4fca34ba52c67cd191338572c00000000000000000000000001515a13551fdf554203f2a86021e0370a08a8d94000000000000000000000000d10aa71e7baec97c397829bedb5a3504546fe1490000000000000000000000005d403c8ad3300b0cb689ea243336f4d39d0e4dae
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061009f575f3560e01c8063900bb8a611610072578063ee29dfc311610058578063ee29dfc3146101a6578063f546ff5a146101cd578063f8fb7a7b146101f4575f80fd5b8063900bb8a614610158578063946ee3511461017f575f80fd5b80634abee02a146100a35780635cfd4528146100be5780636410b7921461010a57806372537d9a14610131575b5f80fd5b6100ab610214565b6040519081526020015b60405180910390f35b6100e57f0000000000000000000000005d403c8ad3300b0cb689ea243336f4d39d0e4dae81565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b6100ab7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81565b6100ab7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6100ab7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6100e57f0000000000000000000000001515a13551fdf554203f2a86021e0370a08a8d9481565b6100e57f000000000000000000000000d10aa71e7baec97c397829bedb5a3504546fe14981565b6100e57f00000000000000000000000052e856790779fd4fca34ba52c67cd191338572c081565b610207610202366004610fad565b610242565b6040516100b59190610fe7565b61023f60017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6110bb565b81565b60408051606080820183525f80835260208301529181019190915260408051606080820183525f80835260208301529181019190915273ffffffffffffffffffffffffffffffffffffffff83166102995792915050565b73ffffffffffffffffffffffffffffffffffffffff8381168083526040517f6ee0787a00000000000000000000000000000000000000000000000000000000815260048101919091527f00000000000000000000000052e856790779fd4fca34ba52c67cd191338572c090911690636ee0787a90602401602060405180830381865afa15801561032b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061034f9190611106565b1561059557600160208201818152505060405180608001604052808473ffffffffffffffffffffffffffffffffffffffff16631f68f20a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103d79190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663a62b75a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610425573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104499190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663d0134cb76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610497573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104bb9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fd2da3396040518163ffffffff1660e01b8152600401602060405180830381865afa158015610509573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061052d9190611125565b9052604080518251602080830191909152830151818301529082015160608083019190915290910151608082015260a0015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152820152610fa7565b6040517f6ee0787a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f0000000000000000000000001515a13551fdf554203f2a86021e0370a08a8d941690636ee0787a90602401602060405180830381865afa15801561061f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106439190611106565b156109555760026020820181815250506040518060c001604052808473ffffffffffffffffffffffffffffffffffffffff16639a1a14d96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106cb9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663d91042b56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610719573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073d9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663019ec38b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561078b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107af9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff166358f5cbad6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108219190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fc4c2d546040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108939190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff16635a92fa856040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109059190611125565b905260405161055f91906020015f60c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6040517f6ee0787a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f000000000000000000000000d10aa71e7baec97c397829bedb5a3504546fe1491690636ee0787a90602401602060405180830381865afa1580156109df573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a039190611106565b15610c655760036020820181815250506040518060a001604052808473ffffffffffffffffffffffffffffffffffffffff16631f68f20a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a67573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8b9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff166383caf2756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ad9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610afd9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff16630f7514a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b4b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6f9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663fd2da3396040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be19190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff166354b02ba46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c2f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c539190611125565b905260405161055f919060200161113c565b6040517f6ee0787a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f0000000000000000000000005d403c8ad3300b0cb689ea243336f4d39d0e4dae1690636ee0787a90602401602060405180830381865afa158015610cef573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d139190611106565b15610fa75760046020820181815250506040518060a001604052808473ffffffffffffffffffffffffffffffffffffffff1663fd4796c26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d9b9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663438895f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610de9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e0d9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663b8caceb16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e5b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e7f9190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff16634c15a12d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ecd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef19190611125565b81526020018473ffffffffffffffffffffffffffffffffffffffff1663e6fd48bc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f3f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f639190611125565b9052604051610f75919060200161113c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528201525b92915050565b5f60208284031215610fbd575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610fe0575f80fd5b9392505050565b5f602080835273ffffffffffffffffffffffffffffffffffffffff8451166020840152602084015160058110611044577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b80604085015250604084015160608085015280518060808601525f5b8181101561107c5782810184015186820160a001528301611060565b505f60a0828701015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116860101935050505092915050565b8181035f8312801583831316838312821617156110ff577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5092915050565b5f60208284031215611116575f80fd5b81518015158114610fe0575f80fd5b5f60208284031215611135575f80fd5b5051919050565b60a08101610fa782848051825260208101516020830152604081015160408301526060810151606083015260808101516080830152505056fea264697066735822122074d0201d3cb138234d2d3a11e5a593b92f2d28e4d21c088c3df0bab3a1e13f6864736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000052e856790779fd4fca34ba52c67cd191338572c00000000000000000000000001515a13551fdf554203f2a86021e0370a08a8d94000000000000000000000000d10aa71e7baec97c397829bedb5a3504546fe1490000000000000000000000005d403c8ad3300b0cb689ea243336f4d39d0e4dae
-----Decoded View---------------
Arg [0] : _kinkIRMFactory (address): 0x52E856790779fD4fCa34bA52C67Cd191338572C0
Arg [1] : _adaptiveCurveIRMFactory (address): 0x1515a13551fDF554203f2a86021e0370a08a8D94
Arg [2] : _kinkyIRMFactory (address): 0xd10aa71E7bAEC97C397829BEdb5a3504546fe149
Arg [3] : _fixedCyclicalBinaryIRMFactory (address): 0x5d403c8Ad3300B0cB689eA243336F4d39d0e4Dae
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000052e856790779fd4fca34ba52c67cd191338572c0
Arg [1] : 0000000000000000000000001515a13551fdf554203f2a86021e0370a08a8d94
Arg [2] : 000000000000000000000000d10aa71e7baec97c397829bedb5a3504546fe149
Arg [3] : 0000000000000000000000005d403c8ad3300b0cb689ea243336f4d39d0e4dae
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.