From b12523f03c812bbd4c318afc301cf4fd6ad11dd5 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Fri, 3 Nov 2023 14:13:22 +0100 Subject: [PATCH] refactor(fullmath): use uniswap's full math --- lib/v3-core | 2 +- src/ChainlinkOracle.sol | 2 +- src/libraries/FullMath.sol | 107 ------------------------------------- 3 files changed, 2 insertions(+), 109 deletions(-) delete mode 100644 src/libraries/FullMath.sol diff --git a/lib/v3-core b/lib/v3-core index e3589b1..6562c52 160000 --- a/lib/v3-core +++ b/lib/v3-core @@ -1 +1 @@ -Subproject commit e3589b192d0be27e100cd0daaf6c97204fdb1899 +Subproject commit 6562c52e8f75f0c10f9deaf44861847585fc8129 diff --git a/src/ChainlinkOracle.sol b/src/ChainlinkOracle.sol index fc8e2b1..dd6f1cd 100644 --- a/src/ChainlinkOracle.sol +++ b/src/ChainlinkOracle.sol @@ -6,7 +6,7 @@ import {IOracle} from "../lib/morpho-blue/src/interfaces/IOracle.sol"; import {AggregatorV3Interface, ChainlinkDataFeedLib} from "./libraries/ChainlinkDataFeedLib.sol"; import {IERC4626, VaultLib} from "./libraries/VaultLib.sol"; import {ErrorsLib} from "./libraries/ErrorsLib.sol"; -import {FullMath} from "./libraries/FullMath.sol"; +import {FullMath} from "../lib/v3-core/contracts/libraries/FullMath.sol"; /// @title ChainlinkOracle /// @author Morpho Labs diff --git a/src/libraries/FullMath.sol b/src/libraries/FullMath.sol deleted file mode 100644 index 4a7366a..0000000 --- a/src/libraries/FullMath.sol +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title Contains 512-bit math functions -/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of -/// precision -/// @dev From https://github.com/Uniswap/v3-core/blob/0.8/contracts/libraries/FullMath.sol. -library FullMath { - /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or - /// denominator == 0 - /// @param a The multiplicand - /// @param b The multiplier - /// @param denominator The divisor - /// @return result The 256-bit result - /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv - function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { - unchecked { - // 512-bit multiply [prod1 prod0] = a * b - // Compute the product mod 2**256 and mod 2**256 - 1 - // then 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(a, b, not(0)) - prod0 := mul(a, b) - prod1 := sub(sub(mm, prod0), lt(mm, prod0)) - } - - // Handle non-overflow cases, 256 by 256 division - if (prod1 == 0) { - require(denominator > 0); - assembly { - result := div(prod0, denominator) - } - return result; - } - - // 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] - // Compute remainder using mulmod - uint256 remainder; - assembly { - remainder := mulmod(a, b, denominator) - } - // Subtract 256 bit number from 512 bit number - assembly { - prod1 := sub(prod1, gt(remainder, prod0)) - prod0 := sub(prod0, remainder) - } - - // Factor powers of two out of denominator - // Compute largest power of two divisor of denominator. - // Always >= 1. - uint256 twos = (0 - denominator) & denominator; - // Divide denominator by power of two - assembly { - denominator := div(denominator, twos) - } - - // Divide [prod1 prod0] by the factors of two - assembly { - prod0 := div(prod0, twos) - } - // Shift in bits from prod1 into prod0. For this we need - // to flip `twos` such that it is 2**256 / twos. - // If twos is zero, then it becomes one - assembly { - twos := add(div(sub(0, twos), twos), 1) - } - 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 - // correct for four bits. That is, denominator * inv = 1 mod 2**4 - uint256 inv = (3 * denominator) ^ 2; - // Now use 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. - inv *= 2 - denominator * inv; // inverse mod 2**8 - inv *= 2 - denominator * inv; // inverse mod 2**16 - inv *= 2 - denominator * inv; // inverse mod 2**32 - inv *= 2 - denominator * inv; // inverse mod 2**64 - inv *= 2 - denominator * inv; // inverse mod 2**128 - inv *= 2 - denominator * inv; // 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 precoditions 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 * inv; - return result; - } - } -}