Contract 0xD777efd0DaaC5BcCDBdD306F404290AD037F8B66

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x22aa2613f3f3c7d4d1e7179a96aa2b9dece1f3cc521c6f3ae5620fd5e02f3d860x60c03461149045282022-06-17 14:35:15650 days 10 hrs ago0xab9769cd4028541ee351cec203a24bf3b873b403 IN  Create: ChainlinkOracle0 ETH0.00314666731 ETH0.326794805
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x3c14e07edd0dc67442fa96f1ec6999c57e810a830 ETH
0x8f9fa61da8880c6759d23cc18c7c0504bcc73d62614bcac02d812c55b0c6bb74172641412022-07-08 16:01:45629 days 9 hrs ago 0x1dcbc0f6f582ec637e7b3e78276646ceac18f179 0xd777efd0daac5bccdbdd306f404290ad037f8b660 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x3c14e07edd0dc67442fa96f1ec6999c57e810a830 ETH
0xb48a20ba56b38708d995008291f4e68306c8d92dc7ebd773a33342315576ef91172640992022-07-08 16:01:45629 days 9 hrs ago 0x1dcbc0f6f582ec637e7b3e78276646ceac18f179 0xd777efd0daac5bccdbdd306f404290ad037f8b660 ETH
0x1c30154122f8a271f19b3dfe30b85bae732c5f8b1c88dc2916eeed98e62821e1171902302022-07-07 13:26:13630 days 11 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x1c30154122f8a271f19b3dfe30b85bae732c5f8b1c88dc2916eeed98e62821e1171902302022-07-07 13:26:13630 days 11 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
0x1c30154122f8a271f19b3dfe30b85bae732c5f8b1c88dc2916eeed98e62821e1171902302022-07-07 13:26:13630 days 11 hrs ago 0xd777efd0daac5bccdbdd306f404290ad037f8b66 0x639fe6ab55c921f74e7fac1ee960c0b6293ba6120 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ChainlinkOracle

Compiler Version
v0.8.14+commit.80d49f37

Optimization Enabled:
Yes with 4999 runs

Other Settings:
default evmVersion
File 1 of 16 : ChainlinkOracle.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.4;

import { Initializable } from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import { AggregatorV3Interface } from '@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol';
import { FlagsInterface } from '@chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol';

import { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';
import { FixedPoint128 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint128.sol';
import { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';
import { SafeCast } from '@uniswap/v3-core-0.8-support/contracts/libraries/SafeCast.sol';

import { AddressHelper } from '../libraries/AddressHelper.sol';
import { PriceMath } from '../libraries/PriceMath.sol';

import { IOracle } from '../interfaces/IOracle.sol';

contract ChainlinkOracle is IOracle {
    using AddressHelper for address;
    using FullMath for uint256;
    using SafeCast for uint256;
    using PriceMath for uint256;

    AggregatorV3Interface public aggregator;
    FlagsInterface public chainlinkFlags;

    uint8 immutable vTokenDecimals;
    uint8 immutable vQuoteDecimals;
    address private constant FLAG_ARBITRUM_SEQ_OFFLINE =
        address(bytes20(bytes32(uint256(keccak256('chainlink.flags.arbitrum-seq-offline')) - 1)));

    error NotEnoughHistory();
    error SequencerOffline();
    error IllegalAggregatorAddress(address aggregator);

    constructor(
        address _aggregator,
        address _flags,
        uint8 _vTokenDecimals,
        uint8 _vQuoteDecimals
    ) {
        if (_aggregator.isZero()) revert IllegalAggregatorAddress(address(0));
        aggregator = AggregatorV3Interface(_aggregator);
        chainlinkFlags = FlagsInterface(_flags);
        vTokenDecimals = _vTokenDecimals;
        vQuoteDecimals = _vQuoteDecimals;
    }

    function getTwapPriceX128(uint32 twapDuration) public view returns (uint256 priceX128) {
        priceX128 = getPrice(twapDuration);
        priceX128 = priceX128.mulDiv(
            FixedPoint128.Q128 * 10**(vQuoteDecimals),
            10**(vTokenDecimals + aggregator.decimals())
        );
    }

    function getPrice(uint256 twapDuration) internal view returns (uint256) {
        FlagsInterface _chainlinkFlags = chainlinkFlags;
        if (address(_chainlinkFlags) != address(0)) {
            bool isRaised = _chainlinkFlags.getFlag(FLAG_ARBITRUM_SEQ_OFFLINE);
            if (isRaised) {
                revert SequencerOffline();
            }
        }
        (uint80 round, uint256 latestPrice, uint256 latestTS) = _getLatestRoundData();
        uint256 endTS = block.timestamp;
        uint256 thresholdTS = endTS - twapDuration;

        //If twap duration = 0 or less data available just return latestPrice
        if (twapDuration == 0 || round == 0 || latestTS <= thresholdTS) {
            return latestPrice;
        }

        uint256 totalTime = endTS - latestTS;
        uint256 twap = latestPrice * totalTime;
        uint256 periodLength;
        uint256 startTS;
        uint256 periodPrice;

        endTS = latestTS;

        //Aggregate prices for all the eligible rounds before thresholdTS i.e. adds price*periodLength to twap
        //For the last eligible round goes till thresholdTS only
        while (true) {
            //If 0 round is reached before reaching thresholdTS then just consider the available data
            if (round == 0) {
                return totalTime == 0 ? latestPrice : twap / totalTime;
            }

            round = round - 1;
            (, periodPrice, startTS) = _getRoundData(round);
            if (periodPrice == 0) break;
            //If the starting time of a period is lesser than threshold timestamp (now-twapDuration) then period is thresholdTS -> endTS
            if (startTS <= thresholdTS) {
                periodLength = (endTS - thresholdTS);
                twap += periodPrice * periodLength;
                totalTime += periodLength;
                break;
            }

            // In normal case where thresholdTS < startTS. The whole period is considered i.e. startTS -> endTS
            periodLength = (endTS - startTS);
            twap += (periodPrice * periodLength);
            totalTime += periodLength;

            //endTS of previous period = startTS of current period
            endTS = startTS;
        }

        //Divide the accumulated value by the whole duration
        return twap == 0 ? latestPrice : twap / totalTime;
    }

    function _getLatestRoundData()
        private
        view
        returns (
            uint80,
            uint256 finalPrice,
            uint256
        )
    {
        (uint80 round, int256 latestPrice, , uint256 latestTS, ) = aggregator.latestRoundData();

        if (latestPrice < 0 && round <= 0) revert NotEnoughHistory();

        if (latestPrice < 0) {
            (round, finalPrice, latestTS) = _getRoundData(round - 1);
        } else {
            finalPrice = uint256(latestPrice);
        }
        return (round, finalPrice, latestTS);
    }

    function _getRoundData(uint80 _round)
        private
        view
        returns (
            uint80,
            uint256,
            uint256
        )
    {
        (uint80 round, int256 latestPrice, , uint256 latestTS, ) = _getRoundDataWithCheck(_round);
        while (latestPrice < 0 && round > 0) {
            round = round - 1;
            (, latestPrice, , latestTS, ) = aggregator.getRoundData(round);
        }
        if (latestPrice < 0 && round <= 0) revert NotEnoughHistory();
        return (round, uint256(latestPrice), latestTS);
    }

    function _getRoundDataWithCheck(uint80 _round)
        private
        view
        returns (
            uint80,
            int256,
            uint256,
            uint256,
            uint80
        )
    {
        try aggregator.getRoundData(_round) returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        ) {
            return (roundId, answer, startedAt, updatedAt, answeredInRound);
        } catch {
            return (0, 0, 0, 0, 0);
        }
    }
}

File 2 of 16 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.0;

import "../../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
        // contract may have been reentered.
        require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} modifier, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

File 3 of 16 : AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorV3Interface {
  function decimals() external view returns (uint8);

  function description() external view returns (string memory);

  function version() external view returns (uint256);

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
}

File 4 of 16 : FlagsInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface FlagsInterface {
  function getFlag(address) external view returns (bool);

  function getFlags(address[] calldata) external view returns (bool[] memory);

  function raiseFlag(address) external;

  function raiseFlags(address[] calldata) external;

  function lowerFlags(address[] calldata) external;

  function setRaisingAccessController(address) external;
}

File 5 of 16 : FixedPoint96.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.4.0;

/// @title FixedPoint96
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
/// @dev Used in SqrtPriceMath.sol
library FixedPoint96 {
    uint8 internal constant RESOLUTION = 96;
    uint256 internal constant Q96 = 0x1000000000000000000000000;
}

File 6 of 16 : FixedPoint128.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.4.0;

/// @title FixedPoint128
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
library FixedPoint128 {
    uint256 internal constant Q128 = 0x100000000000000000000000000000000;
}

File 7 of 16 : FullMath.sol
// 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 Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
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;
        }
    }

    /// @notice Calculates ceil(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
    function mulDivRoundingUp(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            result = mulDiv(a, b, denominator);
            if (mulmod(a, b, denominator) > 0) {
                require(result < type(uint256).max);
                result++;
            }
        }
    }
}

File 8 of 16 : SafeCast.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

/// @title Safe casting methods
/// @notice Contains methods for safely casting between types
library SafeCast {
    /// @notice Cast a uint256 to a uint160, revert on overflow
    /// @param y The uint256 to be downcasted
    /// @return z The downcasted integer, now type uint160
    function toUint160(uint256 y) internal pure returns (uint160 z) {
        require((z = uint160(y)) == y);
    }

    /// @notice Cast a int256 to a int128, revert on overflow or underflow
    /// @param y The int256 to be downcasted
    /// @return z The downcasted integer, now type int128
    function toInt128(int256 y) internal pure returns (int128 z) {
        require((z = int128(y)) == y);
    }

    /// @notice Cast a uint256 to a int256, revert on overflow
    /// @param y The uint256 to be casted
    /// @return z The casted integer, now type int256
    function toInt256(uint256 y) internal pure returns (int256 z) {
        require(y < 2**255);
        z = int256(y);
    }
}

File 9 of 16 : AddressHelper.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import { IVToken } from '../interfaces/IVToken.sol';

/// @title Address helper functions
library AddressHelper {
    /// @notice converts address to uint32, using the least significant 32 bits
    /// @param addr Address to convert
    /// @return truncated last 4 bytes of the address
    function truncate(address addr) internal pure returns (uint32 truncated) {
        assembly {
            truncated := and(addr, 0xffffffff)
        }
    }

    /// @notice converts IERC20 contract to uint32
    /// @param addr contract
    /// @return truncated last 4 bytes of the address
    function truncate(IERC20 addr) internal pure returns (uint32 truncated) {
        return truncate(address(addr));
    }

    /// @notice checks if two addresses are equal
    /// @param a first address
    /// @param b second address
    /// @return true if addresses are equal
    function eq(address a, address b) internal pure returns (bool) {
        return a == b;
    }

    /// @notice checks if addresses of two IERC20 contracts are equal
    /// @param a first contract
    /// @param b second contract
    /// @return true if addresses are equal
    function eq(IERC20 a, IERC20 b) internal pure returns (bool) {
        return eq(address(a), address(b));
    }

    /// @notice checks if an address is zero
    /// @param a address to check
    /// @return true if address is zero
    function isZero(address a) internal pure returns (bool) {
        return a == address(0);
    }

    /// @notice checks if address of an IERC20 contract is zero
    /// @param a contract to check
    /// @return true if address is zero
    function isZero(IERC20 a) internal pure returns (bool) {
        return isZero(address(a));
    }
}

File 10 of 16 : PriceMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.4;

import { FullMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/FullMath.sol';
import { FixedPoint96 } from '@uniswap/v3-core-0.8-support/contracts/libraries/FixedPoint96.sol';
import { TickMath } from '@uniswap/v3-core-0.8-support/contracts/libraries/TickMath.sol';

import { Bisection } from './Bisection.sol';

/// @title Price math functions
library PriceMath {
    using FullMath for uint256;

    error IllegalSqrtPrice(uint160 sqrtPriceX96);

    /// @notice Computes the square of a sqrtPriceX96 value
    /// @param sqrtPriceX96: the square root of the input price in Q96 format
    /// @return priceX128 : input price in Q128 format
    function toPriceX128(uint160 sqrtPriceX96) internal pure returns (uint256 priceX128) {
        if (sqrtPriceX96 < TickMath.MIN_SQRT_RATIO || sqrtPriceX96 >= TickMath.MAX_SQRT_RATIO) {
            revert IllegalSqrtPrice(sqrtPriceX96);
        }

        priceX128 = _toPriceX128(sqrtPriceX96);
    }

    /// @notice computes the square of a sqrtPriceX96 value
    /// @param sqrtPriceX96: input price in Q128 format
    function _toPriceX128(uint160 sqrtPriceX96) private pure returns (uint256 priceX128) {
        priceX128 = uint256(sqrtPriceX96).mulDiv(sqrtPriceX96, 1 << 64);
    }

    /// @notice computes the square root of a priceX128 value
    /// @param priceX128: input price in Q128 format
    /// @return sqrtPriceX96 : the square root of the input price in Q96 format
    function toSqrtPriceX96(uint256 priceX128) internal pure returns (uint160 sqrtPriceX96) {
        // Uses bisection method to find solution to the equation toPriceX128(x) = priceX128
        sqrtPriceX96 = Bisection.findSolution(
            _toPriceX128,
            priceX128,
            /// @dev sqrtPriceX96 is always bounded by MIN_SQRT_RATIO and MAX_SQRT_RATIO.
            ///     If solution falls outside of these bounds, findSolution method reverts
            TickMath.MIN_SQRT_RATIO,
            TickMath.MAX_SQRT_RATIO - 1
        );
    }
}

File 11 of 16 : IOracle.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.0;

interface IOracle {
    function getTwapPriceX128(uint32 twapDuration) external view returns (uint256 priceX128);
}

File 12 of 16 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 13 of 16 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 14 of 16 : IVToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface IVToken is IERC20 {
    function mint(address account, uint256 amount) external;

    function burn(uint256 amount) external;

    function setVPoolWrapper(address) external;
}

File 15 of 16 : TickMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
    error T();
    error R();

    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128
    int24 internal constant MIN_TICK = -887272;
    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128
    int24 internal constant MAX_TICK = -MIN_TICK;

    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
    uint160 internal constant MIN_SQRT_RATIO = 4295128739;
    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;

    /// @notice Calculates sqrt(1.0001^tick) * 2^96
    /// @dev Throws if |tick| > max tick
    /// @param tick The input tick for the above formula
    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)
    /// at the given tick
    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
        unchecked {
            uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
            if (absTick > uint256(int256(MAX_TICK))) revert T();

            uint256 ratio = absTick & 0x1 != 0
                ? 0xfffcb933bd6fad37aa2d162d1a594001
                : 0x100000000000000000000000000000000;
            if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
            if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
            if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
            if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
            if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
            if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
            if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
            if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
            if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
            if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
            if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
            if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
            if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
            if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
            if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
            if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
            if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
            if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
            if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;

            if (tick > 0) ratio = type(uint256).max / ratio;

            // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
            // we then downcast because we know the result always fits within 160 bits due to our tick input constraint
            // we round up in the division so getTickAtSqrtRatio of the output price is always consistent
            sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
        }
    }

    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio
    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may
    /// ever return.
    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96
    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio
    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
        unchecked {
            // second inequality must be < because the price can never reach the price at the max tick
            if (!(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO)) revert R();
            uint256 ratio = uint256(sqrtPriceX96) << 32;

            uint256 r = ratio;
            uint256 msb = 0;

            assembly {
                let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(5, gt(r, 0xFFFFFFFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(4, gt(r, 0xFFFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(3, gt(r, 0xFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(2, gt(r, 0xF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(1, gt(r, 0x3))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := gt(r, 0x1)
                msb := or(msb, f)
            }

            if (msb >= 128) r = ratio >> (msb - 127);
            else r = ratio << (127 - msb);

            int256 log_2 = (int256(msb) - 128) << 64;

            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(63, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(62, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(61, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(60, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(59, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(58, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(57, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(56, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(55, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(54, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(53, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(52, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(51, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(50, f))
            }

            int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number

            int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
            int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);

            tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
        }
    }
}

File 16 of 16 : Bisection.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

/// @title Bisection Method
/// @notice https://en.wikipedia.org/wiki/Bisection_method
library Bisection {
    error SolutionOutOfBounds(uint256 y_target, uint160 x_lower, uint160 x_upper);

    /// @notice Finds the solution to the equation f(x) = y_target using the bisection method
    /// @param f: strictly increasing function f: uint160 -> uint256
    /// @param y_target: the target value of f(x)
    /// @param x_lower: the lower bound for x
    /// @param x_upper: the upper bound for x
    /// @return x_target: the rounded down solution to the equation f(x) = y_target
    function findSolution(
        function(uint160) pure returns (uint256) f,
        uint256 y_target,
        uint160 x_lower,
        uint160 x_upper
    ) internal pure returns (uint160) {
        // compute y at the bounds
        uint256 y_lower = f(x_lower);
        uint256 y_upper = f(x_upper);

        // if y is out of the bounds then revert
        if (y_target < y_lower || y_target > y_upper) revert SolutionOutOfBounds(y_target, x_lower, x_upper);

        // bisect repeatedly until the solution is within an error of 1 unit
        uint256 y_mid;
        uint160 x_mid;
        while (x_upper - x_lower > 1) {
            x_mid = x_lower + (x_upper - x_lower) / 2;
            y_mid = f(x_mid);
            if (y_mid > y_target) {
                x_upper = x_mid;
                y_upper = y_mid;
            } else {
                x_lower = x_mid;
                y_lower = y_mid;
            }
        }

        // at this point, x_upper - x_lower is either 0 or 1
        // if it is 1 then check if x_upper is the solution, else return x_lower as the rounded down solution
        return x_lower != x_upper && f(x_upper) == y_target ? x_upper : x_lower;
    }
}

Settings
{
  "viaIR": true,
  "optimizer": {
    "enabled": true,
    "runs": 4999
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_aggregator","type":"address"},{"internalType":"address","name":"_flags","type":"address"},{"internalType":"uint8","name":"_vTokenDecimals","type":"uint8"},{"internalType":"uint8","name":"_vQuoteDecimals","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"IllegalAggregatorAddress","type":"error"},{"inputs":[],"name":"NotEnoughHistory","type":"error"},{"inputs":[],"name":"SequencerOffline","type":"error"},{"inputs":[],"name":"aggregator","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainlinkFlags","outputs":[{"internalType":"contract FlagsInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"twapDuration","type":"uint32"}],"name":"getTwapPriceX128","outputs":[{"internalType":"uint256","name":"priceX128","type":"uint256"}],"stateMutability":"view","type":"function"}]

60c03461009657601f610b6d38819003918201601f19168301916001600160401b0383118484101761009b57808492608094604052833981010312610096578061004b610076926100b1565b90610058602082016100b1565b6100706060610069604085016100c5565b93016100c5565b926100d3565b604051610a4a9081610123823960805181610143015260a0518160880152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b038216820361009657565b519060ff8216820361009657565b6001600160a01b039081169182156101095760018060a01b0319928360005416176000551690600154161760015560805260a052565b60405163091b998160e11b815260006004820152602490fdfe608080604052600436101561001357600080fd5b6000803560e01c918263245a7bfc146101d957508163dd86c1011461004b575063e4440e0214610043575b600080fd5b61003e610207565b346101d65760206003193601126101d65760043563ffffffff81168091036101d2576101869161007d61017692610486565b61016c6101676100ac7f000000000000000000000000000000000000000000000000000000000000000061026c565b936fffffffffffffffffffffffffffffffff85116001166101c5575b600460206101066100ed845473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051928380927f313ce5670000000000000000000000000000000000000000000000000000000082525afa9182156101b8575b9161018a575b507f0000000000000000000000000000000000000000000000000000000000000000610340565b61026c565b9160801b90610369565b6040519081529081906020820190565b0390f35b6101ab915060203d81116101b1575b6101a381836102aa565b81019061031a565b87610140565b503d610199565b6101c0610333565b61013a565b6101cd61023c565b6100c8565b5080fd5b80fd5b346101d257816003193601126101d25773ffffffffffffffffffffffffffffffffffffffff60209254168152f35b503461003e57600060031936011261003e57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff16604d811161027e575b600a0a90565b61028661023c565b610278565b806000190482118115151661029e570290565b6102a661023c565b0290565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176102eb57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b9081602091031261003e575160ff8116810361003e5790565b506040513d6000823e3d90fd5b60ff8091169116908160ff038111610356570190565b61035e61023c565b0190565b1561003e57565b909160001983830992808302928380861095039480860395146103e357908291610394868411610362565b0981806000031680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b505091506103f2821515610362565b0490565b818110610401570390565b61040961023c565b0390565b9081602091031261003e5751801515810361003e5790565b811561042f570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b69ffffffffffffffffffff600019911660018110610356570190565b81198111610356570190565b6001906104aa6100ed835473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff811661060c575b506104cf61072a565b919290938342906104e084836103f6565b93159081156105f7575b5080156105ed575b6105e5576105048483929695966103f6565b9361050f858861028b565b95915b610537575b5050505090801560001461052a57505090565b6105349250610425565b90565b69ffffffffffffffffffff8116156105d2576105529061045e565b9061055c82610841565b9791509182156105ca578588111561059f57610596929161058a6105838a610590946103f6565b809461028b565b9061047a565b9561047a565b93949082610512565b6105c19697506105bb94506105839193509461058a92956103f6565b9261047a565b38808080610517565b509550610517565b5050505090811560001461052a57505090565b505050505090565b50828411156104f2565b69ffffffffffffffffffff91501615386104ea565b602060405180927f357e47fe000000000000000000000000000000000000000000000000000000008252818061065d600482019073a438451d6458044c3c8cd2f6f31c91ac882a6d91602083019252565b03915afa9081156106d4575b6000916106a6575b5061067c57386104c6565b60046040517fdb502a67000000000000000000000000000000000000000000000000000000008152fd5b6106c7915060203d81116106cd575b6106bf81836102aa565b81019061040d565b38610671565b503d6106b5565b6106dc610333565b610669565b519069ffffffffffffffffffff8216820361003e57565b908160a091031261003e5761070c816106e1565b916020820151916040810151916105346080606084015193016106e1565b600460a073ffffffffffffffffffffffffffffffffffffffff60005416604051928380927ffeaf968c0000000000000000000000000000000000000000000000000000000082525afa8015610834575b600091829083926107ff575b508291906000811280806107eb575b6107c157156107b9575050506107ad6107b29161045e565b610841565b9290919290565b919391925090565b60046040517f9ee522a9000000000000000000000000000000000000000000000000000000008152fd5b5069ffffffffffffffffffff851615610795565b915050610823915060a03d811161082d575b61081b81836102aa565b8101906106f8565b5091905038610786565b503d610811565b61083c610333565b61077a565b61084a9061095d565b509290509091906000926108756100ed855473ffffffffffffffffffffffffffffffffffffffff1690565b925b84821280610948575b1561091e5750506108909061045e565b6040517f9a6fc8f500000000000000000000000000000000000000000000000000000000815269ffffffffffffffffffff8216600482015260a0908181602481875afa908115610911575b859286926108eb575b5050610877565b610905935080919250903d1061082d5761081b81836102aa565b509250509038806108e4565b610919610333565b6108db565b9390949250841280610934575b6107c157929190565b5069ffffffffffffffffffff81161561092b565b5069ffffffffffffffffffff83161515610880565b60009060a069ffffffffffffffffffff602473ffffffffffffffffffffffffffffffffffffffff8554169360405194859384927f9a6fc8f50000000000000000000000000000000000000000000000000000000084521660048301525afa82918291829182918291816109e9575b506109de57505050505080918180918190565b959394509192909190565b935094505050610a07915060a03d811161082d5761081b81836102aa565b92949193909291386109cb56fea2646970667358221220038174ac85da7be6c8f8293f2ff71b601f8f49303ed5bd9751239916b3a0976d64736f6c634300080e0033000000000000000000000000639fe6ab55c921f74e7fac1ee960c0b6293ba6120000000000000000000000003c14e07edd0dc67442fa96f1ec6999c57e810a8300000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000006

Deployed Bytecode

0x608080604052600436101561001357600080fd5b6000803560e01c918263245a7bfc146101d957508163dd86c1011461004b575063e4440e0214610043575b600080fd5b61003e610207565b346101d65760206003193601126101d65760043563ffffffff81168091036101d2576101869161007d61017692610486565b61016c6101676100ac7f000000000000000000000000000000000000000000000000000000000000000661026c565b936fffffffffffffffffffffffffffffffff85116001166101c5575b600460206101066100ed845473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051928380927f313ce5670000000000000000000000000000000000000000000000000000000082525afa9182156101b8575b9161018a575b507f0000000000000000000000000000000000000000000000000000000000000012610340565b61026c565b9160801b90610369565b6040519081529081906020820190565b0390f35b6101ab915060203d81116101b1575b6101a381836102aa565b81019061031a565b87610140565b503d610199565b6101c0610333565b61013a565b6101cd61023c565b6100c8565b5080fd5b80fd5b346101d257816003193601126101d25773ffffffffffffffffffffffffffffffffffffffff60209254168152f35b503461003e57600060031936011261003e57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff16604d811161027e575b600a0a90565b61028661023c565b610278565b806000190482118115151661029e570290565b6102a661023c565b0290565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176102eb57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b9081602091031261003e575160ff8116810361003e5790565b506040513d6000823e3d90fd5b60ff8091169116908160ff038111610356570190565b61035e61023c565b0190565b1561003e57565b909160001983830992808302928380861095039480860395146103e357908291610394868411610362565b0981806000031680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b505091506103f2821515610362565b0490565b818110610401570390565b61040961023c565b0390565b9081602091031261003e5751801515810361003e5790565b811561042f570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b69ffffffffffffffffffff600019911660018110610356570190565b81198111610356570190565b6001906104aa6100ed835473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff811661060c575b506104cf61072a565b919290938342906104e084836103f6565b93159081156105f7575b5080156105ed575b6105e5576105048483929695966103f6565b9361050f858861028b565b95915b610537575b5050505090801560001461052a57505090565b6105349250610425565b90565b69ffffffffffffffffffff8116156105d2576105529061045e565b9061055c82610841565b9791509182156105ca578588111561059f57610596929161058a6105838a610590946103f6565b809461028b565b9061047a565b9561047a565b93949082610512565b6105c19697506105bb94506105839193509461058a92956103f6565b9261047a565b38808080610517565b509550610517565b5050505090811560001461052a57505090565b505050505090565b50828411156104f2565b69ffffffffffffffffffff91501615386104ea565b602060405180927f357e47fe000000000000000000000000000000000000000000000000000000008252818061065d600482019073a438451d6458044c3c8cd2f6f31c91ac882a6d91602083019252565b03915afa9081156106d4575b6000916106a6575b5061067c57386104c6565b60046040517fdb502a67000000000000000000000000000000000000000000000000000000008152fd5b6106c7915060203d81116106cd575b6106bf81836102aa565b81019061040d565b38610671565b503d6106b5565b6106dc610333565b610669565b519069ffffffffffffffffffff8216820361003e57565b908160a091031261003e5761070c816106e1565b916020820151916040810151916105346080606084015193016106e1565b600460a073ffffffffffffffffffffffffffffffffffffffff60005416604051928380927ffeaf968c0000000000000000000000000000000000000000000000000000000082525afa8015610834575b600091829083926107ff575b508291906000811280806107eb575b6107c157156107b9575050506107ad6107b29161045e565b610841565b9290919290565b919391925090565b60046040517f9ee522a9000000000000000000000000000000000000000000000000000000008152fd5b5069ffffffffffffffffffff851615610795565b915050610823915060a03d811161082d575b61081b81836102aa565b8101906106f8565b5091905038610786565b503d610811565b61083c610333565b61077a565b61084a9061095d565b509290509091906000926108756100ed855473ffffffffffffffffffffffffffffffffffffffff1690565b925b84821280610948575b1561091e5750506108909061045e565b6040517f9a6fc8f500000000000000000000000000000000000000000000000000000000815269ffffffffffffffffffff8216600482015260a0908181602481875afa908115610911575b859286926108eb575b5050610877565b610905935080919250903d1061082d5761081b81836102aa565b509250509038806108e4565b610919610333565b6108db565b9390949250841280610934575b6107c157929190565b5069ffffffffffffffffffff81161561092b565b5069ffffffffffffffffffff83161515610880565b60009060a069ffffffffffffffffffff602473ffffffffffffffffffffffffffffffffffffffff8554169360405194859384927f9a6fc8f50000000000000000000000000000000000000000000000000000000084521660048301525afa82918291829182918291816109e9575b506109de57505050505080918180918190565b959394509192909190565b935094505050610a07915060a03d811161082d5761081b81836102aa565b92949193909291386109cb56fea2646970667358221220038174ac85da7be6c8f8293f2ff71b601f8f49303ed5bd9751239916b3a0976d64736f6c634300080e0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000639fe6ab55c921f74e7fac1ee960c0b6293ba6120000000000000000000000003c14e07edd0dc67442fa96f1ec6999c57e810a8300000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000006

-----Decoded View---------------
Arg [0] : _aggregator (address): 0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612
Arg [1] : _flags (address): 0x3C14e07Edd0dC67442FA96f1Ec6999c57E810a83
Arg [2] : _vTokenDecimals (uint8): 18
Arg [3] : _vQuoteDecimals (uint8): 6

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000639fe6ab55c921f74e7fac1ee960c0b6293ba612
Arg [1] : 0000000000000000000000003c14e07edd0dc67442fa96f1ec6999c57e810a83
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000006


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.