Contract Overview
Balance:
0 ETH
EtherValue:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x6dc9f8c1ad35a8a0185ff84f573f5f67be6b68bef1c9eb9c91e57ab172807acb | 0x61014060 | 83068915 | 189 days 10 hrs ago | Exactly: Deployer | IN | Create: InterestRateModel | 0 ETH | 0.000755796613 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
InterestRateModel
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @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 up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (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; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 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. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); 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 (rounding == Rounding.Up && 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 down. * * 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 + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * 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 + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * 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 + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * 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 10, 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 + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.17; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { FixedPointMathLib } from "solmate/src/utils/FixedPointMathLib.sol"; contract InterestRateModel { using FixedPointMathLib for uint256; using FixedPointMathLib for int256; /// @notice Threshold to define which method should be used to calculate the interest rates. /// @dev When `eta` (`delta / alpha`) is lower than this value, use simpson's rule for approximation. uint256 internal constant PRECISION_THRESHOLD = 7.5e14; /// @notice Scale factor of the fixed curve. uint256 public immutable fixedCurveA; /// @notice Origin intercept of the fixed curve. int256 public immutable fixedCurveB; /// @notice Asymptote of the fixed curve. uint256 public immutable fixedMaxUtilization; /// @notice Scale factor of the floating curve. uint256 public immutable floatingCurveA; /// @notice Origin intercept of the floating curve. int256 public immutable floatingCurveB; /// @notice Asymptote of the floating curve. uint256 public immutable floatingMaxUtilization; constructor( uint256 fixedCurveA_, int256 fixedCurveB_, uint256 fixedMaxUtilization_, uint256 floatingCurveA_, int256 floatingCurveB_, uint256 floatingMaxUtilization_ ) { fixedCurveA = fixedCurveA_; fixedCurveB = fixedCurveB_; fixedMaxUtilization = fixedMaxUtilization_; floatingCurveA = floatingCurveA_; floatingCurveB = floatingCurveB_; floatingMaxUtilization = floatingMaxUtilization_; // reverts if it's an invalid curve (such as one yielding a negative interest rate). fixedRate(0, 0); floatingRate(0); } /// @notice Gets the rate to borrow a certain amount at a certain maturity with supply/demand values in the fixed rate /// pool and assets from the backup supplier. /// @param maturity maturity date for calculating days left to maturity. /// @param amount the current borrow's amount. /// @param borrowed ex-ante amount borrowed from this fixed rate pool. /// @param supplied deposits in the fixed rate pool. /// @param backupAssets backup supplier assets. /// @return rate of the fee that the borrower will have to pay (represented with 18 decimals). function fixedBorrowRate( uint256 maturity, uint256 amount, uint256 borrowed, uint256 supplied, uint256 backupAssets ) external view returns (uint256) { if (block.timestamp >= maturity) revert AlreadyMatured(); uint256 potentialAssets = supplied + backupAssets; uint256 utilizationAfter = (borrowed + amount).divWadUp(potentialAssets); if (utilizationAfter > 1e18) revert UtilizationExceeded(); uint256 utilizationBefore = borrowed.divWadDown(potentialAssets); return fixedRate(utilizationBefore, utilizationAfter).mulDivDown(maturity - block.timestamp, 365 days); } /// @notice Gets the current annualized fixed rate to borrow with supply/demand values in the fixed rate pool and /// assets from the backup supplier. /// @param borrowed amount borrowed from the fixed rate pool. /// @param supplied deposits in the fixed rate pool. /// @param backupAssets backup supplier assets. /// @return rate of the fee that the borrower will have to pay and current utilization. function minFixedRate( uint256 borrowed, uint256 supplied, uint256 backupAssets ) external view returns (uint256 rate, uint256 utilization) { utilization = borrowed.divWadUp(supplied + backupAssets); rate = fixedRate(utilization, utilization); } /// @notice Returns the interest rate integral from `u0` to `u1`, using the analytical solution (ln). /// @dev Uses the fixed rate curve parameters. /// Handles special case where delta utilization tends to zero, using simpson's rule. /// @param utilizationBefore ex-ante utilization rate, with 18 decimals precision. /// @param utilizationAfter ex-post utilization rate, with 18 decimals precision. /// @return the interest rate, with 18 decimals precision. function fixedRate(uint256 utilizationBefore, uint256 utilizationAfter) internal view returns (uint256) { uint256 alpha = fixedMaxUtilization - utilizationBefore; uint256 delta = utilizationAfter - utilizationBefore; int256 r = int256( delta.divWadDown(alpha) < PRECISION_THRESHOLD ? (fixedCurveA.divWadDown(alpha) + fixedCurveA.mulDivDown(4e18, fixedMaxUtilization - ((utilizationAfter + utilizationBefore) / 2)) + fixedCurveA.divWadDown(fixedMaxUtilization - utilizationAfter)) / 6 : fixedCurveA.mulDivDown( uint256(int256(alpha.divWadDown(fixedMaxUtilization - utilizationAfter)).lnWad()), delta ) ) + fixedCurveB; assert(r >= 0); return uint256(r); } /// @notice Returns the interest rate for an utilization rate. /// @dev Uses the floating rate curve parameters. /// @param utilization utilization rate, with 18 decimals precision. /// @return the interest rate, with 18 decimals precision. function floatingRate(uint256 utilization) public view returns (uint256) { int256 r = int256(floatingCurveA.divWadDown(floatingMaxUtilization - utilization)) + floatingCurveB; assert(r >= 0); return uint256(r); } } error AlreadyMatured(); error UtilizationExceeded();
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } function powWad(int256 x, int256 y) internal pure returns (int256) { // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y) return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0. } function expWad(int256 x) internal pure returns (int256 r) { unchecked { // When the result is < 0.5 we return zero. This happens when // x <= floor(log(0.5e18) * 1e18) ~ -42e18 if (x <= -42139678854452767551) return 0; // When the result is > (2**255 - 1) / 1e18 we can not represent it as an // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135. if (x >= 135305999368893231589) revert("EXP_OVERFLOW"); // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 // for more intermediate precision and a binary basis. This base conversion // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. x = (x << 78) / 5**18; // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers // of two such that exp(x) = exp(x') * 2**k, where k is an integer. // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96; x = x - k * 54916777467707473351141471128; // k is in the range [-61, 195]. // Evaluate using a (6, 7)-term rational approximation. // p is made monic, we'll multiply by a scale factor later. int256 y = x + 1346386616545796478920950773328; y = ((y * x) >> 96) + 57155421227552351082224309758442; int256 p = y + x - 94201549194550492254356042504812; p = ((p * y) >> 96) + 28719021644029726153956944680412240; p = p * x + (4385272521454847904659076985693276 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. int256 q = x - 2855989394907223263936484059900; q = ((q * x) >> 96) + 50020603652535783019961831881945; q = ((q * x) >> 96) - 533845033583426703283633433725380; q = ((q * x) >> 96) + 3604857256930695427073651918091429; q = ((q * x) >> 96) - 14423608567350463180887372962807573; q = ((q * x) >> 96) + 26449188498355588339934803723976023; assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial won't have zeros in the domain as all its roots are complex. // No scaling is necessary because p is already 2**96 too large. r := sdiv(p, q) } // r should be in the range (0.09, 0.25) * 2**96. // We now need to multiply r by: // * the scale factor s = ~6.031367120. // * the 2**k factor from the range reduction. // * the 1e18 / 2**96 factor for base conversion. // We do this all at once, with an intermediate result in 2**213 // basis, so the final right shift is always by a positive amount. r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)); } } function lnWad(int256 x) internal pure returns (int256 r) { unchecked { require(x > 0, "UNDEFINED"); // We want to convert x from 10**18 fixed point to 2**96 fixed point. // We do this by multiplying by 2**96 / 10**18. But since // ln(x * C) = ln(x) + ln(C), we can simply do nothing here // and add ln(2**96 / 10**18) at the end. // Reduce range of x to (1, 2) * 2**96 // ln(2^k * x) = k * ln(2) + ln(x) int256 k = int256(log2(uint256(x))) - 96; x <<= uint256(159 - k); x = int256(uint256(x) >> 159); // Evaluate using a (8, 8)-term rational approximation. // p is made monic, we will multiply by a scale factor later. int256 p = x + 3273285459638523848632254066296; p = ((p * x) >> 96) + 24828157081833163892658089445524; p = ((p * x) >> 96) + 43456485725739037958740375743393; p = ((p * x) >> 96) - 11111509109440967052023855526967; p = ((p * x) >> 96) - 45023709667254063763336534515857; p = ((p * x) >> 96) - 14706773417378608786704636184526; p = p * x - (795164235651350426258249787498 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. // q is monic by convention. int256 q = x + 5573035233440673466300451813936; q = ((q * x) >> 96) + 71694874799317883764090561454958; q = ((q * x) >> 96) + 283447036172924575727196451306956; q = ((q * x) >> 96) + 401686690394027663651624208769553; q = ((q * x) >> 96) + 204048457590392012362485061816622; q = ((q * x) >> 96) + 31853899698501571402653359427138; q = ((q * x) >> 96) + 909429971244387300277376558375; assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial is known not to have zeros in the domain. // No scaling required because p is already 2**96 too large. r := sdiv(p, q) } // r is in the range (0, 0.125) * 2**96 // Finalization, we need to: // * multiply by the scale factor s = 5.549… // * add ln(2**96 / 10**18) // * add k * ln(2) // * multiply by 10**18 / 2**96 = 5**18 >> 78 // mul s * 5e18 * 2**96, base is now 5**18 * 2**192 r *= 1677202110996718588342820967067443963516166; // add ln(2) * k * 5e18 * 2**192 r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k; // add ln(2**96 / 10**18) * 5e18 * 2**192 r += 600920179829731861736702779321621459595472258049074101567377883020018308; // base conversion: mul 2**18 / 2**192 r >>= 174; } } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // First, divide z - 1 by the denominator and add 1. // We allow z - 1 to underflow if z is 0, because we multiply the // end result by 0 if z is zero, ensuring we return 0 if z is zero. z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { 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) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // 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)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { let y := x // We start y at x, which will help us make our initial estimate. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Goal was to get z*z*y within a small factor of x. More iterations could // get y in a tighter range. Currently, we will have y in [256, 256*2^16). // We ensured y >= 256 so that the relative difference between y and y+1 is small. // That's not possible if x < 256 but we can just verify those cases exhaustively. // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } function log2(uint256 x) internal pure returns (uint256 r) { require(x > 0, "UNDEFINED"); assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) r := or(r, shl(2, lt(0xf, shr(r, x)))) r := or(r, shl(1, lt(0x3, shr(r, x)))) r := or(r, lt(0x1, shr(r, x))) } } function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // z will equal 0 if y is 0, unlike in Solidity where it will revert. z := mod(x, y) } } function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // z will equal 0 if y is 0, unlike in Solidity where it will revert. z := div(x, y) } } /// @dev Will return 0 instead of reverting if y is zero. function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // Add 1 to x * y if x % y > 0. z := add(gt(mod(x, y), 0), div(x, y)) } } }
{ "debug": { "revertStrings": "strip" }, "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"fixedCurveA_","type":"uint256"},{"internalType":"int256","name":"fixedCurveB_","type":"int256"},{"internalType":"uint256","name":"fixedMaxUtilization_","type":"uint256"},{"internalType":"uint256","name":"floatingCurveA_","type":"uint256"},{"internalType":"int256","name":"floatingCurveB_","type":"int256"},{"internalType":"uint256","name":"floatingMaxUtilization_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyMatured","type":"error"},{"inputs":[],"name":"UtilizationExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"borrowed","type":"uint256"},{"internalType":"uint256","name":"supplied","type":"uint256"},{"internalType":"uint256","name":"backupAssets","type":"uint256"}],"name":"fixedBorrowRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fixedCurveA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fixedCurveB","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fixedMaxUtilization","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"floatingCurveA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"floatingCurveB","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"floatingMaxUtilization","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"utilization","type":"uint256"}],"name":"floatingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"borrowed","type":"uint256"},{"internalType":"uint256","name":"supplied","type":"uint256"},{"internalType":"uint256","name":"backupAssets","type":"uint256"}],"name":"minFixedRate","outputs":[{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"utilization","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101406040523480156200001257600080fd5b5060405162000fbf38038062000fbf8339810160408190526200003591620004c3565b608086905260a085905260c084905260e0839052610100829052610120819052620000626000806200007c565b506200006f600062000217565b50505050505050620005b4565b6000808360c0516200008f919062000524565b905060006200009f858562000524565b9050600060a0516602aa1efb94e000620000c885856200026c60201b6200035a1790919060201c565b106200012f576200012962000110620000ff8860c051620000ea919062000524565b876200026c60201b6200035a1790919060201c565b6200028a60201b620003761760201c565b846080516200043360201b62000522179092919060201c565b620001ea565b60066200015c8760c05162000145919062000524565b6080516200026c60201b6200035a1790919060201c565b620001aa673782dace9d9000006002620001778c8c6200053a565b62000183919062000550565b60c05162000192919062000524565b6080516200043360201b62000522179092919060201c565b620001c6876080516200026c60201b6200035a1790919060201c565b620001d291906200053a565b620001de91906200053a565b620001ea919062000550565b620001f6919062000573565b905060008112156200020c576200020c6200059e565b925050505b92915050565b600080610100516200024a846101205162000233919062000524565b60e0516200026c60201b6200035a1790919060201c565b62000256919062000573565b905060008112156200021157620002116200059e565b60006200028383670de0b6b3a76400008462000433565b9392505050565b60008082136200029957600080fd5b60006060620002a88462000453565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d6c8c3f38e95a6b1ff2ab1c3b343619018302821d6d02384773bdf1ac5676facced60901901830290911d6cb9a025d814b29c212b8b1a07cd190190910260016c0504a838426634cdd8738f543560611b03190105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b8282028115158415858304851417166200044c57600080fd5b0492915050565b60008082116200046257600080fd5b5060016001600160801b03821160071b82811c6001600160401b031060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60008060008060008060c08789031215620004dd57600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b634e487b7160e01b600052601160045260246000fd5b818103818111156200021157620002116200050e565b808201808211156200021157620002116200050e565b6000826200056e57634e487b7160e01b600052601260045260246000fd5b500490565b80820182811260008312801582168215821617156200059657620005966200050e565b505092915050565b634e487b7160e01b600052600160045260246000fd5b60805160a05160c05160e051610100516101205161096a6200065560003960008181610187015261023d01526000818160d701526102150152600081816101600152610263015260008181609d0152818161055f015281816105dc0152818161064401526106b70152600081816101c1015261059701526000818160fe0152818161060e0152818161066a015281816106dd0152610708015261096a6000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806384a874661161006657806384a8746614610148578063b99699341461015b578063d837268514610182578063df635f3d146101a9578063dfb08e10146101bc57600080fd5b80630481520b1461009857806326980121146100d25780634d6fc522146100f957806362caa04914610120575b600080fd5b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b61013361012e366004610818565b6101e3565b604080519283526020830191909152016100c9565b6100bf610156366004610844565b610210565b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6100bf6101b736600461085d565b6102ab565b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6000806101fa6101f384866108ae565b8690610541565b90506102068182610556565b9150935093915050565b6000807f0000000000000000000000000000000000000000000000000000000000000000610288610261857f00000000000000000000000000000000000000000000000000000000000000006108c1565b7f00000000000000000000000000000000000000000000000000000000000000009061035a565b61029291906108d4565b905060008112156102a5576102a56108fc565b92915050565b60008542106102cd576040516305a29e1160e51b815260040160405180910390fd5b60006102d983856108ae565b905060006102f1826102eb89896108ae565b90610541565b9050670de0b6b3a764000081111561031c576040516386a8c2bd60e01b815260040160405180910390fd5b6000610328878461035a565b905061034d610337428b6108c1565b6301e133806103468486610556565b9190610522565b9998505050505050505050565b600061036f83670de0b6b3a764000084610522565b9392505050565b600080821361038457600080fd5b6000606061039184610771565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d6c8c3f38e95a6b1ff2ab1c3b343619018302821d6d02384773bdf1ac5676facced60901901830290911d6cb9a025d814b29c212b8b1a07cd1901909102780a09507084cc699bb0e71ea869ffffffffffffffffffffffff190105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b82820281151584158583048514171661053a57600080fd5b0492915050565b600061036f83670de0b6b3a7640000846107ea565b600080610583847f00000000000000000000000000000000000000000000000000000000000000006108c1565b9050600061059185856108c1565b905060007f00000000000000000000000000000000000000000000000000000000000000006602aa1efb94e0006105c8848661035a565b106106395761063461060c610607610600897f00000000000000000000000000000000000000000000000000000000000000006108c1565b879061035a565b610376565b7f00000000000000000000000000000000000000000000000000000000000000009085610522565b61074b565b600661068f610668887f00000000000000000000000000000000000000000000000000000000000000006108c1565b7f00000000000000000000000000000000000000000000000000000000000000009061035a565b610703673782dace9d90000060026106a78c8c6108ae565b6106b19190610912565b6106db907f00000000000000000000000000000000000000000000000000000000000000006108c1565b7f00000000000000000000000000000000000000000000000000000000000000009190610522565b61072d7f00000000000000000000000000000000000000000000000000000000000000008861035a565b61073791906108ae565b61074191906108ae565b61074b9190610912565b61075591906108d4565b90506000811215610768576107686108fc565b95945050505050565b600080821161077f57600080fd5b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b82820281151584158583048514171661080257600080fd5b6001826001830304018115150290509392505050565b60008060006060848603121561082d57600080fd5b505081359360208301359350604090920135919050565b60006020828403121561085657600080fd5b5035919050565b600080600080600060a0868803121561087557600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b808201808211156102a5576102a5610898565b818103818111156102a5576102a5610898565b80820182811260008312801582168215821617156108f4576108f4610898565b505092915050565b634e487b7160e01b600052600160045260246000fd5b60008261092f57634e487b7160e01b600052601260045260246000fd5b50049056fea264697066735822122030753b87d5eaed4b89794a01df3d3f399176f5c3294b4f561d462bca90d6cbee64736f6c63430008110033000000000000000000000000000000000000000000000000054a81f33310c000fffffffffffffffffffffffffffffffffffffffffffffffffaf3b34d5ef3a0000000000000000000000000000000000000000000000000000de0c06dc71106000000000000000000000000000000000000000000000000000044c9a2ec242000fffffffffffffffffffffffffffffffffffffffffffffffffff9a6bba3c950000000000000000000000000000000000000000000000000000dee774ebc451e00
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000054a81f33310c000fffffffffffffffffffffffffffffffffffffffffffffffffaf3b34d5ef3a0000000000000000000000000000000000000000000000000000de0c06dc71106000000000000000000000000000000000000000000000000000044c9a2ec242000fffffffffffffffffffffffffffffffffffffffffffffffffff9a6bba3c950000000000000000000000000000000000000000000000000000dee774ebc451e00
-----Decoded View---------------
Arg [0] : fixedCurveA_ (uint256): 381260000000000000
Arg [1] : fixedCurveB_ (int256): -363750000000000000
Arg [2] : fixedMaxUtilization_ (uint256): 1000010695000000000
Arg [3] : floatingCurveA_ (uint256): 19362000000000000
Arg [4] : floatingCurveB_ (int256): -1787000000000000
Arg [5] : floatingMaxUtilization_ (uint256): 1003870947000000000
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000054a81f33310c000
Arg [1] : fffffffffffffffffffffffffffffffffffffffffffffffffaf3b34d5ef3a000
Arg [2] : 0000000000000000000000000000000000000000000000000de0c06dc7110600
Arg [3] : 0000000000000000000000000000000000000000000000000044c9a2ec242000
Arg [4] : fffffffffffffffffffffffffffffffffffffffffffffffffff9a6bba3c95000
Arg [5] : 0000000000000000000000000000000000000000000000000dee774ebc451e00
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.