Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers. Name tag integration is not available in advanced view.
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | ||||
---|---|---|---|---|---|---|---|
20294995 | 4 days ago | 0 ETH | |||||
20294995 | 4 days ago | 0 ETH | |||||
20294995 | 4 days ago | 0 ETH | |||||
20294995 | 4 days ago | 0 ETH | |||||
20294995 | 4 days ago | 0 ETH | |||||
20294995 | 4 days ago | 0 ETH | |||||
20294995 | 4 days ago | 0 ETH | |||||
20294995 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293187 | 4 days ago | 0 ETH | |||||
20293184 | 4 days ago | 0 ETH | |||||
20293184 | 4 days ago | 0 ETH | |||||
20293184 | 4 days ago | 0 ETH | |||||
20293184 | 4 days ago | 0 ETH | |||||
20293184 | 4 days ago | 0 ETH | |||||
20293184 | 4 days ago | 0 ETH | |||||
20293184 | 4 days ago | 0 ETH |
Loading...
Loading
Contract Name:
InterestRate
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 300 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { IYieldOracle } from "./interfaces/IYieldOracle.sol"; import { WadRayMath } from "./libraries/math/WadRayMath.sol"; // forgefmt: disable-start struct IlkData { // Word 1 uint96 adjustedProfitMargin; // 27 decimals uint96 minimumKinkRate; // 27 decimals // Word 2 uint16 reserveFactor; // 4 decimals uint96 adjustedBaseRate; // 27 decimals uint96 minimumBaseRate; // 27 decimals uint16 optimalUtilizationRate; // 4 decimals uint16 distributionFactor; // 4 decimals // Word 3 uint96 adjustedAboveKinkSlope; // 27 decimals uint96 minimumAboveKinkSlope; // 27 decimals } // Word 1 // // 256 240 216 192 96 0 // | | | | min_kink_rate | adj_profit_margin | // uint256 constant ADJUSTED_PROFIT_MARGIN_MASK = 0x0000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF; uint256 constant MINIMUM_KINK_RATE_MASK = 0x0000000000000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000; // Word 2 // // 256 240 224 208 112 16 0 // | __ | | | min_base_rate | adj_base_rate | | // ^ ^ ^ // ^ opt_util reserve_factor // distribution_factor uint256 constant RESERVE_FACTOR_MASK = 0x000000000000000000000000000000000000000000000000000000000000FFFF; uint256 constant ADJUSTED_BASE_RATE_MASK = 0x000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF0000; uint256 constant MINIMUM_BASE_RATE_MASK = 0x000000000000FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000; uint256 constant OPTIMAL_UTILIZATION_MASK = 0x00000000FFFF0000000000000000000000000000000000000000000000000000; uint256 constant DISTRIBUTION_FACTOR_MASK = 0x0000FFFF00000000000000000000000000000000000000000000000000000000; // Word 3 // 256 240 216 192 96 0 // | | | | min_above_kink_slope | adj_above_kink_slope | // uint256 constant ADJUSTED_ABOVE_KINK_SLOPE_MASK = 0x0000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF; uint256 constant MINIMUM_ABOVE_KINK_SLOPE_MASK = 0x0000000000000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000; // forgefmt: disable-end // Word 1 uint8 constant ADJUSTED_PROFIT_MARGIN_SHIFT = 0; uint8 constant MINIMUM_KINK_RATE_SHIFT = 96; // Word 2 uint8 constant RESERVE_FACTOR_SHIFT = 0; uint8 constant ADJUSTED_BASE_RATE_SHIFT = 16; uint8 constant MINIMUM_BASE_RATE_SHIFT = 16 + 96; uint8 constant OPTIMAL_UTILIZATION_SHIFT = 16 + 96 + 96; uint8 constant DISTRIBUTION_FACTOR_SHIFT = 16 + 96 + 96 + 16; // Word 3 uint8 constant ADJUSTED_ABOVE_KINK_SLOPE_SHIFT = 0; uint8 constant MINIMUM_ABOVE_KINK_SLOPE_SHIFT = 96; uint48 constant SECONDS_IN_A_YEAR = 31_536_000; /** * @notice An external contract that provides the APY for each collateral type. * A modular design here allows for updating of the parameters at a later date * without upgrading the core protocol. * * @dev Each collateral has its own interest rate model, and every operation on * the `IonPool` (lend, withdraw, borrow, repay) will alter the interest rate * for all collaterals. Therefore, before every operation, the previous interest * rate must be accrued. Ion determines the interest rate for each collateral * based on various collateral-specific parameters which must be stored * on-chain. However, to iterate through all these parameters as contract * storage on every operation introduces an immense gas overhead, especially as * more collaterals are listed on Ion. Therefore, this contract is heavily * optimized to reduce storage reads at the unfortunate cost of code-complexity. * * @custom:security-contact [email protected] */ contract InterestRate { using WadRayMath for *; error CollateralIndexOutOfBounds(); error DistributionFactorsDoNotSumToOne(uint256 sum); error TotalDebtsLength(uint256 COLLATERAL_COUNT, uint256 totalIlkDebtsLength); error InvalidMinimumKinkRate(uint256 minimumKinkRate, uint256 minimumBaseRate); error InvalidIlkDataListLength(uint256 length); error InvalidOptimalUtilizationRate(uint256 optimalUtilizationRate); error InvalidReserveFactor(uint256 reserveFactor); error InvalidYieldOracleAddress(); uint256 private constant MAX_ILKS = 8; /** * @dev Packed collateral configs */ uint256 private immutable ILKCONFIG_0A; uint256 private immutable ILKCONFIG_0B; uint256 private immutable ILKCONFIG_0C; uint256 private immutable ILKCONFIG_1A; uint256 private immutable ILKCONFIG_1B; uint256 private immutable ILKCONFIG_1C; uint256 private immutable ILKCONFIG_2A; uint256 private immutable ILKCONFIG_2B; uint256 private immutable ILKCONFIG_2C; uint256 private immutable ILKCONFIG_3A; uint256 private immutable ILKCONFIG_3B; uint256 private immutable ILKCONFIG_3C; uint256 private immutable ILKCONFIG_4A; uint256 private immutable ILKCONFIG_4B; uint256 private immutable ILKCONFIG_4C; uint256 private immutable ILKCONFIG_5A; uint256 private immutable ILKCONFIG_5B; uint256 private immutable ILKCONFIG_5C; uint256 private immutable ILKCONFIG_6A; uint256 private immutable ILKCONFIG_6B; uint256 private immutable ILKCONFIG_6C; uint256 private immutable ILKCONFIG_7A; uint256 private immutable ILKCONFIG_7B; uint256 private immutable ILKCONFIG_7C; uint256 public immutable COLLATERAL_COUNT; IYieldOracle public immutable YIELD_ORACLE; /** * @notice Creates a new `InterestRate` instance. * @param ilkDataList List of ilk configs. * @param _yieldOracle Address of the Yield oracle. */ constructor(IlkData[] memory ilkDataList, IYieldOracle _yieldOracle) { if (address(_yieldOracle) == address(0)) revert InvalidYieldOracleAddress(); if (ilkDataList.length > MAX_ILKS) revert InvalidIlkDataListLength(ilkDataList.length); COLLATERAL_COUNT = ilkDataList.length; YIELD_ORACLE = _yieldOracle; uint256 distributionFactorSum = 0; for (uint256 i = 0; i < COLLATERAL_COUNT;) { distributionFactorSum += ilkDataList[i].distributionFactor; if (ilkDataList[i].minimumKinkRate < ilkDataList[i].minimumBaseRate) { revert InvalidMinimumKinkRate(ilkDataList[i].minimumKinkRate, ilkDataList[i].minimumBaseRate); } if (ilkDataList[i].optimalUtilizationRate == 0) { revert InvalidOptimalUtilizationRate(ilkDataList[i].optimalUtilizationRate); } if (ilkDataList[i].reserveFactor > 1e4) { revert InvalidReserveFactor(ilkDataList[i].reserveFactor); } // forgefmt: disable-next-line unchecked { ++i; } } if (distributionFactorSum != 1e4) revert DistributionFactorsDoNotSumToOne(distributionFactorSum); (ILKCONFIG_0A, ILKCONFIG_0B, ILKCONFIG_0C) = _packCollateralConfig(ilkDataList, 0); (ILKCONFIG_1A, ILKCONFIG_1B, ILKCONFIG_1C) = _packCollateralConfig(ilkDataList, 1); (ILKCONFIG_2A, ILKCONFIG_2B, ILKCONFIG_2C) = _packCollateralConfig(ilkDataList, 2); (ILKCONFIG_3A, ILKCONFIG_3B, ILKCONFIG_3C) = _packCollateralConfig(ilkDataList, 3); (ILKCONFIG_4A, ILKCONFIG_4B, ILKCONFIG_4C) = _packCollateralConfig(ilkDataList, 4); (ILKCONFIG_5A, ILKCONFIG_5B, ILKCONFIG_5C) = _packCollateralConfig(ilkDataList, 5); (ILKCONFIG_6A, ILKCONFIG_6B, ILKCONFIG_6C) = _packCollateralConfig(ilkDataList, 6); (ILKCONFIG_7A, ILKCONFIG_7B, ILKCONFIG_7C) = _packCollateralConfig(ilkDataList, 7); } /** * @notice Helper function to pack the collateral configs into 3 words. This * function is only called during construction. * @param ilkDataList The list of ilk configs. * @param index The ilkIndex to pack. * @return packedConfig_a * @return packedConfig_b * @return packedConfig_c */ function _packCollateralConfig( IlkData[] memory ilkDataList, uint256 index ) private view returns (uint256 packedConfig_a, uint256 packedConfig_b, uint256 packedConfig_c) { if (index >= COLLATERAL_COUNT) return (0, 0, 0); IlkData memory ilkData = ilkDataList[index]; packedConfig_a = ( uint256(ilkData.adjustedProfitMargin) << ADJUSTED_PROFIT_MARGIN_SHIFT | uint256(ilkData.minimumKinkRate) << MINIMUM_KINK_RATE_SHIFT ); packedConfig_b = ( uint256(ilkData.reserveFactor) << RESERVE_FACTOR_SHIFT | uint256(ilkData.adjustedBaseRate) << ADJUSTED_BASE_RATE_SHIFT | uint256(ilkData.minimumBaseRate) << MINIMUM_BASE_RATE_SHIFT | uint256(ilkData.optimalUtilizationRate) << OPTIMAL_UTILIZATION_SHIFT | uint256(ilkData.distributionFactor) << DISTRIBUTION_FACTOR_SHIFT ); packedConfig_c = ( uint256(ilkData.adjustedAboveKinkSlope) << ADJUSTED_ABOVE_KINK_SLOPE_SHIFT | uint256(ilkData.minimumAboveKinkSlope) << MINIMUM_ABOVE_KINK_SLOPE_SHIFT ); } /** * @notice Helper function to unpack the collateral configs from the 3 * words. * @param index The ilkIndex to unpack. * @return ilkData The unpacked collateral config. */ function unpackCollateralConfig(uint256 index) external view returns (IlkData memory ilkData) { return _unpackCollateralConfig(index); } function _unpackCollateralConfig(uint256 index) internal view returns (IlkData memory ilkData) { if (index > COLLATERAL_COUNT - 1) revert CollateralIndexOutOfBounds(); uint256 packedConfig_a; uint256 packedConfig_b; uint256 packedConfig_c; if (index == 0) { packedConfig_a = ILKCONFIG_0A; packedConfig_b = ILKCONFIG_0B; packedConfig_c = ILKCONFIG_0C; } else if (index == 1) { packedConfig_a = ILKCONFIG_1A; packedConfig_b = ILKCONFIG_1B; packedConfig_c = ILKCONFIG_1C; } else if (index == 2) { packedConfig_a = ILKCONFIG_2A; packedConfig_b = ILKCONFIG_2B; packedConfig_c = ILKCONFIG_2C; } else if (index == 3) { packedConfig_a = ILKCONFIG_3A; packedConfig_b = ILKCONFIG_3B; packedConfig_c = ILKCONFIG_3C; } else if (index == 4) { packedConfig_a = ILKCONFIG_4A; packedConfig_b = ILKCONFIG_4B; packedConfig_c = ILKCONFIG_4C; } else if (index == 5) { packedConfig_a = ILKCONFIG_5A; packedConfig_b = ILKCONFIG_5B; packedConfig_c = ILKCONFIG_5C; } else if (index == 6) { packedConfig_a = ILKCONFIG_6A; packedConfig_b = ILKCONFIG_6B; packedConfig_c = ILKCONFIG_6C; } else if (index == 7) { packedConfig_a = ILKCONFIG_7A; packedConfig_b = ILKCONFIG_7B; packedConfig_c = ILKCONFIG_7C; } uint96 adjustedProfitMargin = uint96((packedConfig_a & ADJUSTED_PROFIT_MARGIN_MASK) >> ADJUSTED_PROFIT_MARGIN_SHIFT); uint96 minimumKinkRate = uint96((packedConfig_a & MINIMUM_KINK_RATE_MASK) >> MINIMUM_KINK_RATE_SHIFT); uint16 reserveFactor = uint16((packedConfig_b & RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_SHIFT); uint96 adjustedBaseRate = uint96((packedConfig_b & ADJUSTED_BASE_RATE_MASK) >> ADJUSTED_BASE_RATE_SHIFT); uint96 minimumBaseRate = uint96((packedConfig_b & MINIMUM_BASE_RATE_MASK) >> MINIMUM_BASE_RATE_SHIFT); uint16 optimalUtilizationRate = uint16((packedConfig_b & OPTIMAL_UTILIZATION_MASK) >> OPTIMAL_UTILIZATION_SHIFT); uint16 distributionFactor = uint16((packedConfig_b & DISTRIBUTION_FACTOR_MASK) >> DISTRIBUTION_FACTOR_SHIFT); uint96 adjustedAboveKinkSlope = uint96((packedConfig_c & ADJUSTED_ABOVE_KINK_SLOPE_MASK) >> ADJUSTED_ABOVE_KINK_SLOPE_SHIFT); uint96 minimumAboveKinkSlope = uint96((packedConfig_c & MINIMUM_ABOVE_KINK_SLOPE_MASK) >> MINIMUM_ABOVE_KINK_SLOPE_SHIFT); ilkData = IlkData({ adjustedProfitMargin: adjustedProfitMargin, minimumKinkRate: minimumKinkRate, reserveFactor: reserveFactor, adjustedBaseRate: adjustedBaseRate, minimumBaseRate: minimumBaseRate, optimalUtilizationRate: optimalUtilizationRate, distributionFactor: distributionFactor, adjustedAboveKinkSlope: adjustedAboveKinkSlope, minimumAboveKinkSlope: minimumAboveKinkSlope }); } /** * @notice Calculates the interest rate for a given collateral. * @param ilkIndex Index of the collateral. * @param totalIlkDebt Total debt of the collateral. [RAD] * @param totalEthSupply Total eth supply of the system. [WAD] * @return The borrow rate for the collateral. [RAY] * @return The reserve factor for the collateral. [RAY] */ function calculateInterestRate( uint256 ilkIndex, uint256 totalIlkDebt, uint256 totalEthSupply ) external view returns (uint256, uint256) { IlkData memory ilkData = _unpackCollateralConfig(ilkIndex); uint256 optimalUtilizationRateRay = ilkData.optimalUtilizationRate.scaleUpToRay(4); uint256 collateralApyRayInSeconds = YIELD_ORACLE.apys(ilkIndex).scaleUpToRay(8) / SECONDS_IN_A_YEAR; uint256 distributionFactor = ilkData.distributionFactor; // The only time the distribution factor will be set to 0 is when a // market has been sunset. In this case, we want to prevent division by // 0, but we also want to prevent the borrow rate from skyrocketing. So // we will return a reasonable borrow rate of kink utilization on the // minimum curve. if (distributionFactor == 0) { return (ilkData.minimumKinkRate, ilkData.reserveFactor.scaleUpToRay(4)); } // [RAD] / [WAD] = [RAY] uint256 utilizationRate = totalEthSupply == 0 ? 0 : totalIlkDebt / (totalEthSupply.wadMulDown(distributionFactor.scaleUpToWad(4))); // Avoid stack too deep uint256 adjustedBelowKinkSlope; { uint256 slopeNumerator; unchecked { slopeNumerator = collateralApyRayInSeconds - ilkData.adjustedProfitMargin - ilkData.adjustedBaseRate; } // Underflow occurred // If underflow occurred, then the Apy was too low or the profitMargin was too high and // we would want to switch to minimum borrow rate. Set slopeNumerator to zero such // that adjusted borrow rate is below the minimum borrow rate. if (slopeNumerator > collateralApyRayInSeconds) { slopeNumerator = 0; } adjustedBelowKinkSlope = slopeNumerator.rayDivDown(optimalUtilizationRateRay); } uint256 minimumBelowKinkSlope = (ilkData.minimumKinkRate - ilkData.minimumBaseRate).rayDivDown(optimalUtilizationRateRay); // Below kink if (utilizationRate < optimalUtilizationRateRay) { uint256 adjustedBorrowRate = adjustedBelowKinkSlope.rayMulDown(utilizationRate) + ilkData.adjustedBaseRate; uint256 minimumBorrowRate = minimumBelowKinkSlope.rayMulDown(utilizationRate) + ilkData.minimumBaseRate; if (adjustedBorrowRate < minimumBorrowRate) { return (minimumBorrowRate, ilkData.reserveFactor.scaleUpToRay(4)); } else { return (adjustedBorrowRate, ilkData.reserveFactor.scaleUpToRay(4)); } } // Above kink else { // For the above kink calculation, we will use the below kink slope // for all utilization up until the kink. From that point on we will // use the above kink slope. uint256 excessUtil = utilizationRate - optimalUtilizationRateRay; uint256 adjustedNormalRate = adjustedBelowKinkSlope.rayMulDown(optimalUtilizationRateRay) + ilkData.adjustedBaseRate; uint256 minimumNormalRate = minimumBelowKinkSlope.rayMulDown(optimalUtilizationRateRay) + ilkData.minimumBaseRate; // [WAD] * [RAY] / [WAD] = [RAY] uint256 adjustedBorrowRate = ilkData.adjustedAboveKinkSlope.rayMulDown(excessUtil) + adjustedNormalRate; uint256 minimumBorrowRate = ilkData.minimumAboveKinkSlope.rayMulDown(excessUtil) + minimumNormalRate; if (adjustedBorrowRate < minimumBorrowRate) { return (minimumBorrowRate, ilkData.reserveFactor.scaleUpToRay(4)); } else { return (adjustedBorrowRate, ilkData.reserveFactor.scaleUpToRay(4)); } } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; interface IYieldOracle { function apys(uint256 ilkIndex) external view returns (uint32); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; uint256 constant WAD = 1e18; uint256 constant RAY = 1e27; uint256 constant RAD = 1e45; /** * @title WadRayMath * * @notice This library provides mul/div[up/down] functionality for WAD, RAY and * RAD with phantom overflow protection as well as scale[up/down] functionality * for WAD, RAY and RAD. * * @custom:security-contact [email protected] */ library WadRayMath { using Math for uint256; error NotScalingUp(uint256 from, uint256 to); error NotScalingDown(uint256 from, uint256 to); /** * @notice Multiplies two WAD numbers and returns the result as a WAD * rounding the result down. * @param a Multiplicand. * @param b Multiplier. */ function wadMulDown(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(b, WAD); } /** * @notice Multiplies two WAD numbers and returns the result as a WAD * rounding the result up. * @param a Multiplicand. * @param b Multiplier. */ function wadMulUp(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(b, WAD, Math.Rounding.Ceil); } /** * @notice Divides two WAD numbers and returns the result as a WAD rounding * the result down. * @param a Dividend. * @param b Divisor. */ function wadDivDown(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(WAD, b); } /** * @notice Divides two WAD numbers and returns the result as a WAD rounding * the result up. * @param a Dividend. * @param b Divisor. */ function wadDivUp(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(WAD, b, Math.Rounding.Ceil); } /** * @notice Multiplies two RAY numbers and returns the result as a RAY * rounding the result down. * @param a Multiplicand * @param b Multiplier */ function rayMulDown(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(b, RAY); } /** * @notice Multiplies two RAY numbers and returns the result as a RAY * rounding the result up. * @param a Multiplicand * @param b Multiplier */ function rayMulUp(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(b, RAY, Math.Rounding.Ceil); } /** * @notice Divides two RAY numbers and returns the result as a RAY * rounding the result down. * @param a Dividend * @param b Divisor */ function rayDivDown(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(RAY, b); } /** * @notice Divides two RAY numbers and returns the result as a RAY * rounding the result up. * @param a Dividend * @param b Divisor */ function rayDivUp(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(RAY, b, Math.Rounding.Ceil); } /** * @notice Multiplies two RAD numbers and returns the result as a RAD * rounding the result down. * @param a Multiplicand * @param b Multiplier */ function radMulDown(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(b, RAD); } /** * @notice Multiplies two RAD numbers and returns the result as a RAD * rounding the result up. * @param a Multiplicand * @param b Multiplier */ function radMulUp(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(b, RAD, Math.Rounding.Ceil); } /** * @notice Divides two RAD numbers and returns the result as a RAD rounding * the result down. * @param a Dividend * @param b Divisor */ function radDivDown(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(RAD, b); } /** * @notice Divides two RAD numbers and returns the result as a RAD rounding * the result up. * @param a Dividend * @param b Divisor */ function radDivUp(uint256 a, uint256 b) internal pure returns (uint256) { return a.mulDiv(RAD, b, Math.Rounding.Ceil); } // --- Scalers --- /** * @notice Scales a value up from WAD. NOTE: The `scale` value must be * less than 18. * @param value to scale up. * @param scale of the returned value. */ function scaleUpToWad(uint256 value, uint256 scale) internal pure returns (uint256) { return scaleUp(value, scale, 18); } /** * @notice Scales a value up from RAY. NOTE: The `scale` value must be * less than 27. * @param value to scale up. * @param scale of the returned value. */ function scaleUpToRay(uint256 value, uint256 scale) internal pure returns (uint256) { return scaleUp(value, scale, 27); } /** * @notice Scales a value up from RAD. NOTE: The `scale` value must be * less than 45. * @param value to scale up. * @param scale of the returned value. */ function scaleUpToRad(uint256 value, uint256 scale) internal pure returns (uint256) { return scaleUp(value, scale, 45); } /** * @notice Scales a value down to WAD. NOTE: The `scale` value must be * greater than 18. * @param value to scale down. * @param scale of the returned value. */ function scaleDownToWad(uint256 value, uint256 scale) internal pure returns (uint256) { return scaleDown(value, scale, 18); } /** * @notice Scales a value down to RAY. NOTE: The `scale` value must be * greater than 27. * @param value to scale down. * @param scale of the returned value. */ function scaleDownToRay(uint256 value, uint256 scale) internal pure returns (uint256) { return scaleDown(value, scale, 27); } /** * @notice Scales a value down to RAD. NOTE: The `scale` value must be * greater than 45. * @param value to scale down. * @param scale of the returned value. */ function scaleDownToRad(uint256 value, uint256 scale) internal pure returns (uint256) { return scaleDown(value, scale, 45); } /** * @notice Scales a value up from one fixed-point precision to another. * @param value to scale up. * @param from Precision to scale from. * @param to Precision to scale to. */ function scaleUp(uint256 value, uint256 from, uint256 to) internal pure returns (uint256) { if (from >= to) revert NotScalingUp(from, to); return value * (10 ** (to - from)); } /** * @notice Scales a value down from one fixed-point precision to another. * @param value to scale down. * @param from Precision to scale from. * @param to Precision to scale to. */ function scaleDown(uint256 value, uint256 from, uint256 to) internal pure returns (uint256) { if (from <= to) revert NotScalingDown(from, to); return value / (10 ** (from - to)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@balancer-labs/v2-interfaces/=lib/balancer-v2-monorepo/pkg/interfaces/", "@balancer-labs/v2-pool-stable/=lib/balancer-v2-monorepo/pkg/pool-stable/", "@chainlink/contracts/=lib/chainlink/contracts/", "@uniswap/v3-periphery/=lib/v3-periphery/", "@uniswap/v3-core/=lib/v3-core/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "balancer-v2-monorepo/=lib/balancer-v2-monorepo/", "chainlink/=lib/chainlink/", "ds-test/=lib/forge-safe/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-safe/=lib/forge-safe/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solady/=lib/solady/", "solidity-stringutils/=lib/forge-safe/lib/surl/lib/solidity-stringutils/", "solmate/=lib/forge-safe/lib/solmate/src/", "surl/=lib/forge-safe/lib/surl/", "v3-core/=lib/v3-core/", "v3-periphery/=lib/v3-periphery/contracts/", "solarray/=lib/solarray/src/", "pendle-core-v2-public/=lib/pendle-core-v2-public/contracts/" ], "optimizer": { "enabled": true, "runs": 300 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "shanghai", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"components":[{"internalType":"uint96","name":"adjustedProfitMargin","type":"uint96"},{"internalType":"uint96","name":"minimumKinkRate","type":"uint96"},{"internalType":"uint16","name":"reserveFactor","type":"uint16"},{"internalType":"uint96","name":"adjustedBaseRate","type":"uint96"},{"internalType":"uint96","name":"minimumBaseRate","type":"uint96"},{"internalType":"uint16","name":"optimalUtilizationRate","type":"uint16"},{"internalType":"uint16","name":"distributionFactor","type":"uint16"},{"internalType":"uint96","name":"adjustedAboveKinkSlope","type":"uint96"},{"internalType":"uint96","name":"minimumAboveKinkSlope","type":"uint96"}],"internalType":"struct IlkData[]","name":"ilkDataList","type":"tuple[]"},{"internalType":"contract IYieldOracle","name":"_yieldOracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CollateralIndexOutOfBounds","type":"error"},{"inputs":[{"internalType":"uint256","name":"sum","type":"uint256"}],"name":"DistributionFactorsDoNotSumToOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"InvalidIlkDataListLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"minimumKinkRate","type":"uint256"},{"internalType":"uint256","name":"minimumBaseRate","type":"uint256"}],"name":"InvalidMinimumKinkRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"optimalUtilizationRate","type":"uint256"}],"name":"InvalidOptimalUtilizationRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"reserveFactor","type":"uint256"}],"name":"InvalidReserveFactor","type":"error"},{"inputs":[],"name":"InvalidYieldOracleAddress","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"}],"name":"NotScalingUp","type":"error"},{"inputs":[{"internalType":"uint256","name":"COLLATERAL_COUNT","type":"uint256"},{"internalType":"uint256","name":"totalIlkDebtsLength","type":"uint256"}],"name":"TotalDebtsLength","type":"error"},{"inputs":[],"name":"COLLATERAL_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"YIELD_ORACLE","outputs":[{"internalType":"contract IYieldOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ilkIndex","type":"uint256"},{"internalType":"uint256","name":"totalIlkDebt","type":"uint256"},{"internalType":"uint256","name":"totalEthSupply","type":"uint256"}],"name":"calculateInterestRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"unpackCollateralConfig","outputs":[{"components":[{"internalType":"uint96","name":"adjustedProfitMargin","type":"uint96"},{"internalType":"uint96","name":"minimumKinkRate","type":"uint96"},{"internalType":"uint16","name":"reserveFactor","type":"uint16"},{"internalType":"uint96","name":"adjustedBaseRate","type":"uint96"},{"internalType":"uint96","name":"minimumBaseRate","type":"uint96"},{"internalType":"uint16","name":"optimalUtilizationRate","type":"uint16"},{"internalType":"uint16","name":"distributionFactor","type":"uint16"},{"internalType":"uint96","name":"adjustedAboveKinkSlope","type":"uint96"},{"internalType":"uint96","name":"minimumAboveKinkSlope","type":"uint96"}],"internalType":"struct IlkData","name":"ilkData","type":"tuple"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6103c060405234801562000011575f80fd5b50604051620016123803806200161283398101604081905262000034916200054d565b6001600160a01b0381166200005c57604051633a9f6af760e11b815260040160405180910390fd5b6008825111156200008f578151604051637792a1c560e11b81526004016200008691815260200190565b60405180910390fd5b8151610380526001600160a01b0381166103a0525f805b61038051811015620002a457838181518110620000c757620000c7620006ca565b602002602001015160c0015161ffff1682620000e49190620006de565b9150838181518110620000fb57620000fb620006ca565b6020026020010151608001516001600160601b0316848281518110620001255762000125620006ca565b6020026020010151602001516001600160601b03161015620001b457838181518110620001565762000156620006ca565b602002602001015160200151848281518110620001775762000177620006ca565b602002602001015160800151604051633f6ca22160e11b8152600401620000869291906001600160601b0392831681529116602082015260400190565b838181518110620001c957620001c9620006ca565b602002602001015160a0015161ffff165f036200022657838181518110620001f557620001f5620006ca565b602002602001015160a0015160405163f2ae6b3d60e01b815260040162000086919061ffff91909116815260200190565b6127108482815181106200023e576200023e620006ca565b60200260200101516040015161ffff1611156200029b578381815181106200026a576200026a620006ca565b602002602001015160400151604051630cd3498760e11b815260040162000086919061ffff91909116815260200190565b600101620000a6565b508061271014620002cc5760405163b9778c0960e01b81526004810182905260240162000086565b620002d8835f62000399565b60c05260a052608052620002ee83600162000399565b610120526101005260e0526200030683600262000399565b6101805261016052610140526200031f83600362000399565b6101e0526101c0526101a0526200033883600462000399565b6102405261022052610200526200035183600562000399565b6102a05261028052610260526200036a83600662000399565b610300526102e0526102c0526200038383600762000399565b6103605261034052610320525062000704915050565b5f805f610380518410620003b557505f9150819050806200048e565b5f858581518110620003cb57620003cb620006ca565b60200260200101519050606060ff1681602001516001600160601b0316901b5f60ff16825f01516001600160601b0316901b17935060e060ff168160c0015161ffff16901b60d060ff168260a0015161ffff16901b607060ff1683608001516001600160601b0316901b601060ff1684606001516001600160601b0316901b5f60ff16856040015161ffff16901b171717179250606060ff168161010001516001600160601b0316901b5f60ff168260e001516001600160601b0316901b179150505b9250925092565b634e487b7160e01b5f52604160045260245ffd5b60405161012081016001600160401b0381118282101715620004cf57620004cf62000495565b60405290565b604051601f8201601f191681016001600160401b038111828210171562000500576200050062000495565b604052919050565b80516001600160601b03811681146200051f575f80fd5b919050565b805161ffff811681146200051f575f80fd5b80516001600160a01b03811681146200051f575f80fd5b5f80604080848603121562000560575f80fd5b83516001600160401b038082111562000577575f80fd5b818601915086601f8301126200058b575f80fd5b8151602082821115620005a257620005a262000495565b620005b2818360051b01620004d5565b828152818101935061012092830285018201928a841115620005d2575f80fd5b948201945b83861015620006ac5780868c031215620005f0575f8081fd5b620005fa620004a9565b620006058762000508565b81526200061484880162000508565b848201526200062588880162000524565b8882015260606200063881890162000508565b9082015260806200064b88820162000508565b9082015260a06200065e88820162000524565b9082015260c06200067188820162000524565b9082015260e06200068488820162000508565b908201526101006200069888820162000508565b9082015285529485019493820193620005d7565b509650620006bc88820162000536565b955050505050509250929050565b634e487b7160e01b5f52603260045260245ffd5b80820180821115620006fe57634e487b7160e01b5f52601160045260245ffd5b92915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161036051610380516103a051610df2620008205f395f8181605301526101a801525f818160b7015261051501525f6108df01525f6108bc01525f61089901525f61086a01525f61084701525f61082401525f6107f501525f6107d201525f6107af01525f61078001525f61075d01525f61073a01525f61070b01525f6106e801525f6106c501525f61069601525f61067301525f61065001525f61062101525f6105fe01525f6105db01525f6105ac01525f61058901525f6105660152610df25ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c806309ea519f1461004e578063161fa6561461009257806348d4b487146100b2578063fe4bab43146100e7575b5f80fd5b6100757f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a56100a0366004610af5565b61010f565b6040516100899190610b0c565b6100d97f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610089565b6100fa6100f5366004610bda565b610166565b60408051928352602083019190915201610089565b60408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810191909152610160826104c6565b92915050565b5f805f610172866104c6565b90505f61019160048360a0015161ffff1661097b90919063ffffffff16565b90505f6301e1338065ffffffffffff1661024760087f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166381ce1c238c6040518263ffffffff1660e01b81526004016101f491815260200190565b602060405180830381865afa15801561020f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102339190610c03565b63ffffffff1661097b90919063ffffffff16565b6102519190610c4e565b60c084015190915061ffff165f819003610297576020840151604085015161027e9061ffff16600461097b565b816001600160601b0316915095509550505050506104be565b5f87156102c2576102b36102ac83600461098f565b899061099c565b6102bd908a610c4e565b6102c4565b5f5b606086015186519192505f916001600160601b039182169116850303848111156102eb57505f5b6102f581876109b0565b9150505f61032086886080015189602001516103119190610c6d565b6001600160601b0316906109b0565b9050858310156103bd5760608701515f906001600160601b031661034484866109c8565b61034e9190610c94565b60808901519091505f906001600160601b031661036b84876109c8565b6103759190610c94565b9050808210156103a757604089015181906103959061ffff16600461097b565b9a509a505050505050505050506104be565b604089015182906103959061ffff16600461097b565b5f6103c88785610ca7565b60608901519091505f906001600160601b03166103e5858a6109c8565b6103ef9190610c94565b60808a01519091505f906001600160601b031661040c858b6109c8565b6104169190610c94565b90505f8261043a858d60e001516001600160601b03166109c890919063ffffffff16565b6104449190610c94565b90505f82610469868e61010001516001600160601b03166109c890919063ffffffff16565b6104739190610c94565b9050808210156104a85760408c015181906104939061ffff16600461097b565b9d509d505050505050505050505050506104be565b60408c015182906104939061ffff16600461097b565b935093915050565b60408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915261053960017f0000000000000000000000000000000000000000000000000000000000000000610ca7565b8211156105595760405163ca89fc4960e01b815260040160405180910390fd5b5f805f845f036105d057507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b8460010361064557507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b846002036106ba57507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b8460030361072f57507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b846004036107a457507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b8460050361081957507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b8460060361088e57507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b846007036108ff57507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000005b60408051610120810182526001600160601b038581168252606095861c8116602083015261ffff85811693830193909352601085901c811682870152607085901c8116608083015260d085901c831660a083015260e094851c90921660c082015282821693810193909352921c90911661010082015292915050565b5f6109888383601b6109e0565b9392505050565b5f610988838360126109e0565b5f6109888383670de0b6b3a7640000610a36565b5f610988836b033b2e3c9fd0803ce800000084610a36565b5f61098883836b033b2e3c9fd0803ce8000000610a36565b5f818310610a0f57604051631a065cf160e01b8152600481018490526024810183905260440160405180910390fd5b610a198383610ca7565b610a2490600a610d9a565b610a2e9085610da5565b949350505050565b5f838302815f1985870982811083820303915050805f03610a6a57838281610a6057610a60610c26565b0492505050610988565b808411610a8a5760405163227bc15360e01b815260040160405180910390fd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b5f60208284031215610b05575f80fd5b5035919050565b5f610120820190506001600160601b03808451168352806020850151166020840152506040830151610b44604084018261ffff169052565b506060830151610b5f60608401826001600160601b03169052565b506080830151610b7a60808401826001600160601b03169052565b5060a0830151610b9060a084018261ffff169052565b5060c0830151610ba660c084018261ffff169052565b5060e0830151610bc160e08401826001600160601b03169052565b50610100928301516001600160601b0316919092015290565b5f805f60608486031215610bec575f80fd5b505081359360208301359350604090920135919050565b5f60208284031215610c13575f80fd5b815163ffffffff81168114610988575f80fd5b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f82610c6857634e487b7160e01b5f52601260045260245ffd5b500490565b6001600160601b03828116828216039080821115610c8d57610c8d610c3a565b5092915050565b8082018082111561016057610160610c3a565b8181038181111561016057610160610c3a565b600181815b80851115610cf457815f1904821115610cda57610cda610c3a565b80851615610ce757918102915b93841c9390800290610cbf565b509250929050565b5f82610d0a57506001610160565b81610d1657505f610160565b8160018114610d2c5760028114610d3657610d52565b6001915050610160565b60ff841115610d4757610d47610c3a565b50506001821b610160565b5060208310610133831016604e8410600b8410161715610d75575081810a610160565b610d7f8383610cba565b805f1904821115610d9257610d92610c3a565b029392505050565b5f6109888383610cfc565b808202811582820484141761016057610160610c3a56fea2646970667358221220b2f7cb8e5fce56ccf7c3e226d1c8b8bfa819b4b0fee4fd484311316a2df06e7664736f6c634300081500330000000000000000000000000000000000000000000000000000000000000040000000000000000000000000437cc840e234c2127f54cd59b0b18af59c586760000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0ff73f71548d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf033b95a04e000000000000000000000000000000000000000000000000000000000000000232800000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fa5fa5ef28e4c800
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c806309ea519f1461004e578063161fa6561461009257806348d4b487146100b2578063fe4bab43146100e7575b5f80fd5b6100757f000000000000000000000000437cc840e234c2127f54cd59b0b18af59c58676081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a56100a0366004610af5565b61010f565b6040516100899190610b0c565b6100d97f000000000000000000000000000000000000000000000000000000000000000181565b604051908152602001610089565b6100fa6100f5366004610bda565b610166565b60408051928352602083019190915201610089565b60408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810191909152610160826104c6565b92915050565b5f805f610172866104c6565b90505f61019160048360a0015161ffff1661097b90919063ffffffff16565b90505f6301e1338065ffffffffffff1661024760087f000000000000000000000000437cc840e234c2127f54cd59b0b18af59c5867606001600160a01b03166381ce1c238c6040518263ffffffff1660e01b81526004016101f491815260200190565b602060405180830381865afa15801561020f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102339190610c03565b63ffffffff1661097b90919063ffffffff16565b6102519190610c4e565b60c084015190915061ffff165f819003610297576020840151604085015161027e9061ffff16600461097b565b816001600160601b0316915095509550505050506104be565b5f87156102c2576102b36102ac83600461098f565b899061099c565b6102bd908a610c4e565b6102c4565b5f5b606086015186519192505f916001600160601b039182169116850303848111156102eb57505f5b6102f581876109b0565b9150505f61032086886080015189602001516103119190610c6d565b6001600160601b0316906109b0565b9050858310156103bd5760608701515f906001600160601b031661034484866109c8565b61034e9190610c94565b60808901519091505f906001600160601b031661036b84876109c8565b6103759190610c94565b9050808210156103a757604089015181906103959061ffff16600461097b565b9a509a505050505050505050506104be565b604089015182906103959061ffff16600461097b565b5f6103c88785610ca7565b60608901519091505f906001600160601b03166103e5858a6109c8565b6103ef9190610c94565b60808a01519091505f906001600160601b031661040c858b6109c8565b6104169190610c94565b90505f8261043a858d60e001516001600160601b03166109c890919063ffffffff16565b6104449190610c94565b90505f82610469868e61010001516001600160601b03166109c890919063ffffffff16565b6104739190610c94565b9050808210156104a85760408c015181906104939061ffff16600461097b565b9d509d505050505050505050505050506104be565b60408c015182906104939061ffff16600461097b565b935093915050565b60408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915261053960017f0000000000000000000000000000000000000000000000000000000000000001610ca7565b8211156105595760405163ca89fc4960e01b815260040160405180910390fd5b5f805f845f036105d057507f0000000000000000000000002a0ff73f71548d0000000000000000000000000091507f000027102328000000000bf033b95a04e000000000000000000000000000000090507f000000000000000000000003fa5fa5ef28e4c8000000000000000000000000006108ff565b8460010361064557507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b846002036106ba57507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b8460030361072f57507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b846004036107a457507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b8460050361081957507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b8460060361088e57507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000006108ff565b846007036108ff57507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000090507f00000000000000000000000000000000000000000000000000000000000000005b60408051610120810182526001600160601b038581168252606095861c8116602083015261ffff85811693830193909352601085901c811682870152607085901c8116608083015260d085901c831660a083015260e094851c90921660c082015282821693810193909352921c90911661010082015292915050565b5f6109888383601b6109e0565b9392505050565b5f610988838360126109e0565b5f6109888383670de0b6b3a7640000610a36565b5f610988836b033b2e3c9fd0803ce800000084610a36565b5f61098883836b033b2e3c9fd0803ce8000000610a36565b5f818310610a0f57604051631a065cf160e01b8152600481018490526024810183905260440160405180910390fd5b610a198383610ca7565b610a2490600a610d9a565b610a2e9085610da5565b949350505050565b5f838302815f1985870982811083820303915050805f03610a6a57838281610a6057610a60610c26565b0492505050610988565b808411610a8a5760405163227bc15360e01b815260040160405180910390fd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b5f60208284031215610b05575f80fd5b5035919050565b5f610120820190506001600160601b03808451168352806020850151166020840152506040830151610b44604084018261ffff169052565b506060830151610b5f60608401826001600160601b03169052565b506080830151610b7a60808401826001600160601b03169052565b5060a0830151610b9060a084018261ffff169052565b5060c0830151610ba660c084018261ffff169052565b5060e0830151610bc160e08401826001600160601b03169052565b50610100928301516001600160601b0316919092015290565b5f805f60608486031215610bec575f80fd5b505081359360208301359350604090920135919050565b5f60208284031215610c13575f80fd5b815163ffffffff81168114610988575f80fd5b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f82610c6857634e487b7160e01b5f52601260045260245ffd5b500490565b6001600160601b03828116828216039080821115610c8d57610c8d610c3a565b5092915050565b8082018082111561016057610160610c3a565b8181038181111561016057610160610c3a565b600181815b80851115610cf457815f1904821115610cda57610cda610c3a565b80851615610ce757918102915b93841c9390800290610cbf565b509250929050565b5f82610d0a57506001610160565b81610d1657505f610160565b8160018114610d2c5760028114610d3657610d52565b6001915050610160565b60ff841115610d4757610d47610c3a565b50506001821b610160565b5060208310610133831016604e8410600b8410161715610d75575081810a610160565b610d7f8383610cba565b805f1904821115610d9257610d92610c3a565b029392505050565b5f6109888383610cfc565b808202811582820484141761016057610160610c3a56fea2646970667358221220b2f7cb8e5fce56ccf7c3e226d1c8b8bfa819b4b0fee4fd484311316a2df06e7664736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000437cc840e234c2127f54cd59b0b18af59c586760000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0ff73f71548d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf033b95a04e000000000000000000000000000000000000000000000000000000000000000232800000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fa5fa5ef28e4c800
-----Decoded View---------------
Arg [0] : ilkDataList (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [1] : _yieldOracle (address): 0x437CC840e234C2127f54CD59B0B18aF59c586760
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 000000000000000000000000437cc840e234c2127f54cd59b0b18af59c586760
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000002a0ff73f71548d00
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000bf033b95a04e000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000002328
Arg [9] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [11] : 000000000000000000000000000000000000000000000003fa5fa5ef28e4c800
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.