Contract
0x8C2F35c8076bCb5D4b696bAE11AcA0ac0Dd873e4
1
Contract Overview
Balance:
0 ETH
EtherValue:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x9d59c6e9bc95906f22d674005b65f2560eaa1bc5de6f6c96e4f6f13a12e4b555 | 0x61014060 | 83069049 | 189 days 10 hrs ago | Exactly: Deployer | IN | Contract Creation | 0 ETH | 0.000751891899 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Similar Match Source Code This contract matches the deployed ByteCode of the Source Code for Contract 0x6c51C1718dc482B8001FbEc5649174c9fB7d41bB The constructor portion of the code might be different and could alter the actual behaviour of the contract
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
6101406040523480156200001257600080fd5b5060405162000fbf38038062000fbf8339810160408190526200003591620004c3565b608086905260a085905260c084905260e0839052610100829052610120819052620000626000806200007c565b506200006f600062000217565b50505050505050620005b4565b6000808360c0516200008f919062000524565b905060006200009f858562000524565b9050600060a0516602aa1efb94e000620000c885856200026c60201b6200035a1790919060201c565b106200012f576200012962000110620000ff8860c051620000ea919062000524565b876200026c60201b6200035a1790919060201c565b6200028a60201b620003761760201c565b846080516200043360201b62000522179092919060201c565b620001ea565b60066200015c8760c05162000145919062000524565b6080516200026c60201b6200035a1790919060201c565b620001aa673782dace9d9000006002620001778c8c6200053a565b62000183919062000550565b60c05162000192919062000524565b6080516200043360201b62000522179092919060201c565b620001c6876080516200026c60201b6200035a1790919060201c565b620001d291906200053a565b620001de91906200053a565b620001ea919062000550565b620001f6919062000573565b905060008112156200020c576200020c6200059e565b925050505b92915050565b600080610100516200024a846101205162000233919062000524565b60e0516200026c60201b6200035a1790919060201c565b62000256919062000573565b905060008112156200021157620002116200059e565b60006200028383670de0b6b3a76400008462000433565b9392505050565b60008082136200029957600080fd5b60006060620002a88462000453565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d6c8c3f38e95a6b1ff2ab1c3b343619018302821d6d02384773bdf1ac5676facced60901901830290911d6cb9a025d814b29c212b8b1a07cd190190910260016c0504a838426634cdd8738f543560611b03190105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b8282028115158415858304851417166200044c57600080fd5b0492915050565b60008082116200046257600080fd5b5060016001600160801b03821160071b82811c6001600160401b031060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60008060008060008060c08789031215620004dd57600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b634e487b7160e01b600052601160045260246000fd5b818103818111156200021157620002116200050e565b808201808211156200021157620002116200050e565b6000826200056e57634e487b7160e01b600052601260045260246000fd5b500490565b80820182811260008312801582168215821617156200059657620005966200050e565b505092915050565b634e487b7160e01b600052600160045260246000fd5b60805160a05160c05160e051610100516101205161096a6200065560003960008181610187015261023d01526000818160d701526102150152600081816101600152610263015260008181609d0152818161055f015281816105dc0152818161064401526106b70152600081816101c1015261059701526000818160fe0152818161060e0152818161066a015281816106dd0152610708015261096a6000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806384a874661161006657806384a8746614610148578063b99699341461015b578063d837268514610182578063df635f3d146101a9578063dfb08e10146101bc57600080fd5b80630481520b1461009857806326980121146100d25780634d6fc522146100f957806362caa04914610120575b600080fd5b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b61013361012e366004610818565b6101e3565b604080519283526020830191909152016100c9565b6100bf610156366004610844565b610210565b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6100bf6101b736600461085d565b6102ab565b6100bf7f000000000000000000000000000000000000000000000000000000000000000081565b6000806101fa6101f384866108ae565b8690610541565b90506102068182610556565b9150935093915050565b6000807f0000000000000000000000000000000000000000000000000000000000000000610288610261857f00000000000000000000000000000000000000000000000000000000000000006108c1565b7f00000000000000000000000000000000000000000000000000000000000000009061035a565b61029291906108d4565b905060008112156102a5576102a56108fc565b92915050565b60008542106102cd576040516305a29e1160e51b815260040160405180910390fd5b60006102d983856108ae565b905060006102f1826102eb89896108ae565b90610541565b9050670de0b6b3a764000081111561031c576040516386a8c2bd60e01b815260040160405180910390fd5b6000610328878461035a565b905061034d610337428b6108c1565b6301e133806103468486610556565b9190610522565b9998505050505050505050565b600061036f83670de0b6b3a764000084610522565b9392505050565b600080821361038457600080fd5b6000606061039184610771565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d6c8c3f38e95a6b1ff2ab1c3b343619018302821d6d02384773bdf1ac5676facced60901901830290911d6cb9a025d814b29c212b8b1a07cd1901909102780a09507084cc699bb0e71ea869ffffffffffffffffffffffff190105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b82820281151584158583048514171661053a57600080fd5b0492915050565b600061036f83670de0b6b3a7640000846107ea565b600080610583847f00000000000000000000000000000000000000000000000000000000000000006108c1565b9050600061059185856108c1565b905060007f00000000000000000000000000000000000000000000000000000000000000006602aa1efb94e0006105c8848661035a565b106106395761063461060c610607610600897f00000000000000000000000000000000000000000000000000000000000000006108c1565b879061035a565b610376565b7f00000000000000000000000000000000000000000000000000000000000000009085610522565b61074b565b600661068f610668887f00000000000000000000000000000000000000000000000000000000000000006108c1565b7f00000000000000000000000000000000000000000000000000000000000000009061035a565b610703673782dace9d90000060026106a78c8c6108ae565b6106b19190610912565b6106db907f00000000000000000000000000000000000000000000000000000000000000006108c1565b7f00000000000000000000000000000000000000000000000000000000000000009190610522565b61072d7f00000000000000000000000000000000000000000000000000000000000000008861035a565b61073791906108ae565b61074191906108ae565b61074b9190610912565b61075591906108d4565b90506000811215610768576107686108fc565b95945050505050565b600080821161077f57600080fd5b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b82820281151584158583048514171661080257600080fd5b6001826001830304018115150290509392505050565b60008060006060848603121561082d57600080fd5b505081359360208301359350604090920135919050565b60006020828403121561085657600080fd5b5035919050565b600080600080600060a0868803121561087557600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b808201808211156102a5576102a5610898565b818103818111156102a5576102a5610898565b80820182811260008312801582168215821617156108f4576108f4610898565b505092915050565b634e487b7160e01b600052600160045260246000fd5b60008261092f57634e487b7160e01b600052601260045260246000fd5b50049056fea264697066735822122030753b87d5eaed4b89794a01df3d3f399176f5c3294b4f561d462bca90d6cbee64736f6c63430008110033000000000000000000000000000000000000000000000000045c9e2f4ce7c000fffffffffffffffffffffffffffffffffffffffffffffffffbd357fe639000000000000000000000000000000000000000000000000000000dec7008c726400000000000000000000000000000000000000000000000000000470de4df820000fffffffffffffffffffffffffffffffffffffffffffffffffff7d429850440000000000000000000000000000000000000000000000000000e0ff6fb36e74000
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.