ETH Price: $3,090.71 (+0.06%)

Contract

0x5f509a3C3F16dF2Fba7bF84dEE1eFbce6BB85587

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PriceGetter

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.28;

import "./IPriceGetter.sol";
import "./chainlink/ChainlinkOracle.sol";
import "./extensions/IPriceGetterProtocol.sol";
import "./lib/UtilityLibrary.sol";

import {Hypervisor} from "./interfaces/IGammaHypervisor.sol";
import {IICHIVault} from "./interfaces/IICHIVault.sol";

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

/** 
VERSION: 3.0
 
DISCLAIMER: 
This smart contract is provided for user interface purposes only and is not intended to be used for smart contract logic. 
Any attempt to rely on this code for the execution of a smart contract may result in unexpected behavior, 
errors, or other issues that could lead to financial loss or other damages. 
The user assumes all responsibility and risk for proper usage. 
The developer and associated parties make no warranties and are not liable for any damages incurred.
*/

contract PriceGetter is IPriceGetter, ChainlinkOracle, Initializable, OwnableUpgradeable {
    enum OracleType {
        NONE,
        CHAIN_LINK
    }

    struct OracleInfo {
        OracleType oracleType;
        address oracleAddress;
        uint8 oracleDecimals;
    }

    mapping(Protocol => IPriceGetterProtocol) public protocolPriceGetter;
    mapping(address => OracleInfo) public tokenOracles;
    TokenAndDecimals private wrappedNative;
    TokenAndDecimals[] public stableUsdTokens;
    uint256 public nativeLiquidityThreshold;
    uint256 public stableUsdThreshold;

    // Reserved storage space to allow for layout changes in the future.
    uint256[50] private __gap;

    /**
     * @dev This contract constructor takes in several parameters which includes the wrapped native token address,
     * an array of addresses for stable USD tokens, an array of addresses for oracle tokens, and an array of addresses
     * for oracles.
     *
     * @param _wNative Address of the wrapped native token
     * @param _nativeLiquidityThreshold The native liquidity threshold
     * @param _stableUsdTokens Array of stable USD token addresses
     * @param _oracleTokens Array of oracle token addresses
     * @param _oracles Array of oracle addresses
     */
    function initialize(
        address _wNative,
        uint256 _nativeLiquidityThreshold,
        uint256 _stableUsdThreshold,
        address[] calldata _stableUsdTokens,
        address[] calldata _oracleTokens,
        address[] calldata _oracles
    ) public initializer {
        __Ownable_init();
        nativeLiquidityThreshold = _nativeLiquidityThreshold;
        stableUsdThreshold = _stableUsdThreshold;
        // Check if the lengths of the oracleTokens and oracles arrays match
        require(_oracleTokens.length == _oracles.length, "Oracle length mismatch");

        // Loop through the oracleTokens array and set the oracle address for each oracle token using the _setTokenOracle() internal helper function
        for (uint256 i = 0; i < _oracleTokens.length; i++) {
            /// @dev Assumes OracleType.CHAIN_LINK
            _setTokenOracle(_oracleTokens[i], _oracles[i], OracleType.CHAIN_LINK);
        }

        // Add the stable USD tokens to the stableCoins array using the addStableUsdTokens() internal helper function
        addStableUsdTokens(_stableUsdTokens);

        // Set the wrapped native token (wrappedNative) address
        wrappedNative = TokenAndDecimals(_wNative, UtilityLibrary._getTokenDecimals(_wNative));
    }

    /** SETTERS */

    /**
     * @dev Adds new stable USD tokens to the list of supported stable USD tokens.
     * @param newStableUsdTokens An array of addresses representing the new stable USD tokens to add.
     */
    function addStableUsdTokens(address[] calldata newStableUsdTokens) public onlyOwner {
        for (uint256 i = 0; i < newStableUsdTokens.length; i++) {
            address stableUsdToken = newStableUsdTokens[i];
            bool exists = false;

            for (uint256 j = 0; j < stableUsdTokens.length; j++) {
                if (stableUsdTokens[j].tokenAddress == stableUsdToken) {
                    exists = true;
                    break;
                }
            }

            if (!exists) {
                TokenAndDecimals memory newStableToken = TokenAndDecimals(
                    stableUsdToken,
                    UtilityLibrary._getTokenDecimals(stableUsdToken)
                );
                stableUsdTokens.push(newStableToken);
            }
        }
    }

    /**
     * @dev Removes the stable address.
     * @param tokens An array of token addresses to remove the stable address for.
     */
    function removeStableUsdTokens(address[] calldata tokens) external onlyOwner {
        for (uint256 i = 0; i < tokens.length; i++) {
            address token = tokens[i];
            uint256 length = stableUsdTokens.length;
            for (uint256 j = 0; j < length; j++) {
                if (stableUsdTokens[j].tokenAddress == token) {
                    stableUsdTokens[j] = stableUsdTokens[length - 1];
                    stableUsdTokens.pop();
                    break;
                }
            }
        }
    }

    /**
     * @dev Sets the oracle address and type for a specified token.
     * @param token The address of the token to set the oracle for.
     * @param oracleAddress The address of the oracle contract.
     * @param oracleType The type of the oracle (e.g. Chainlink, Uniswap).
     */
    function setTokenOracle(address token, address oracleAddress, OracleType oracleType) public onlyOwner {
        _setTokenOracle(token, oracleAddress, oracleType);
    }

    /**
     * @dev Removes the oracle address for a specified token.
     * @param token The address of the token to set the oracle for.
     */
    function removeTokenOracle(address token) public onlyOwner {
        delete tokenOracles[token];
    }

    /**
     * @dev Sets the oracle address and type for a specified token.
     * @param token The address of the token to set the oracle for.
     * @param oracleAddress The address of the oracle contract.
     * @param oracleType The type of the oracle (e.g. Chainlink, Uniswap).
     */
    function _setTokenOracle(address token, address oracleAddress, OracleType oracleType) internal {
        uint8 oracleDecimals = 18;
        try IERC20(oracleAddress).decimals() returns (uint8 dec) {
            oracleDecimals = dec;
        } catch {}

        tokenOracles[token] = OracleInfo({
            oracleType: oracleType,
            oracleAddress: oracleAddress,
            oracleDecimals: oracleDecimals
        });
    }

    function setNativeLiquidityThreshold(uint256 _nativeLiquidityThreshold) public onlyOwner {
        nativeLiquidityThreshold = _nativeLiquidityThreshold;
    }

    function setStableUsdThreshold(uint256 _stableUsdThreshold) public onlyOwner {
        stableUsdThreshold = _stableUsdThreshold;
    }

    function setPriceGetterProtocol(Protocol protocol, address extension) public onlyOwner {
        protocolPriceGetter[protocol] = IPriceGetterProtocol(extension);
    }

    /**
     * @dev Sets the price getter protocols for multiple protocols at once.
     * @param protocols The protocols for which to set the price getter.
     * @param extensions The addresses of the price getter extensions for each protocol.
     */
    function setPriceGetterProtocols(Protocol[] memory protocols, address[] memory extensions) public onlyOwner {
        require(protocols.length == extensions.length, "Number of protocols must match number of extensions");
        for (uint256 i; i < protocols.length; i++) {
            setPriceGetterProtocol(protocols[i], extensions[i]);
        }
    }

    /** GETTERS */
    // ========== Get Token Prices ==========

    function getTokenPriceTry(
        address token,
        Protocol protocol,
        address factory
    ) public view returns (uint256 tokenPrice, uint256 usdBalance) {
        try this.getTokenPrice(token, protocol, factory) returns (uint256 _tokenPrice, uint256 _usdBalance) {
            tokenPrice = _tokenPrice;
            usdBalance = _usdBalance;
        } catch {
            return (0, 0);
        }
    }

    /**
     * @dev Returns the current price of the given token based on the specified protocol and time interval.
     * If protocol is set to 'Both', the price is calculated as a weighted average of the V2 and V3 prices,
     * where the weights are the respective liquidity pools. If protocol is set to 'V2' or 'V3', the price
     * is calculated based on the respective liquidity pool.
     * @param token Address of the token for which the price is requested.
     * @param protocol The liquidity protocol used to calculate the price.
     * @param factory The address of the factory used to calculate the price.
     * @return tokenPrice The price of the token in USD.
     */
    function getTokenPrice(
        address token,
        Protocol protocol,
        address factory
    ) public view returns (uint256 tokenPrice, uint256 usdBalance) {
        IPriceGetterProtocol extension = getPriceGetterProtocol(protocol);
        (tokenPrice, usdBalance) = extension.getTokenPrice(token, factory, getParams());
    }

    function getTokenPrices(
        address[] calldata tokens,
        Protocol protocol,
        address factory
    ) public view returns (uint256[] memory tokenPrices) {
        uint256 tokenLength = tokens.length;
        tokenPrices = new uint256[](tokenLength);

        for (uint256 i; i < tokenLength; i++) {
            address token = tokens[i];
            (tokenPrices[i], ) = getTokenPrice(token, protocol, factory);
        }
    }

    // ========== Get LP Prices ==========

    /**
     * @dev Returns the LP token price with try-catch error handling
     * @param lp The address of the LP token
     * @param protocol The protocol version to use
     * @param factory The address of the factory
     * @return price The current price of LP, returns 0 if price fetch fails
     */
    function getLPPriceTry(address lp, Protocol protocol, address factory) public view returns (uint256 price) {
        try this.getLPPrice(lp, protocol, factory) returns (uint256 _price) {
            price = _price;
        } catch {
            return 0;
        }
    }

    function getLPPrice(address lp, Protocol protocol, address factory) external view returns (uint256 price) {
        IPriceGetterProtocol extension = getPriceGetterProtocol(protocol);
        price = extension.getLPPrice(lp, factory, getParams());
    }

    /**
     * @dev Returns the wrapped LP token price with try-catch error handling
     * @param lp The address of the wrapped LP token
     * @param protocol The protocol version to use
     * @param factory The address of the factory
     * @param wrapper The type of wrapper (Gamma, Ichi, etc)
     * @return price The current price of wrapped LP, returns 0 if price fetch fails
     */
    function getWrappedLPPriceTry(
        address lp,
        Protocol protocol,
        address factory,
        Wrappers wrapper
    ) public view returns (uint256 price) {
        try this.getWrappedLPPrice(lp, protocol, factory, wrapper) returns (uint256 _price) {
            price = _price;
        } catch {
            return 0;
        }
    }

    function getWrappedLPPrice(
        address lp,
        Protocol protocol,
        address factory,
        Wrappers wrapper
    ) public view override returns (uint256 price) {
        if (protocol != Protocol.UniV3 && protocol != Protocol.Algebra && protocol != Protocol.UniV4 && protocol != Protocol.AlgebraV4) {
            revert("Protocol does not have wrappers");
        }

        address token0;
        address token1;
        uint256 total0;
        uint256 total1;

        if (wrapper == IPriceGetter.Wrappers.Gamma) {
            token0 = address(Hypervisor(lp).token0());
            token1 = address(Hypervisor(lp).token1());
        } else if (wrapper == IPriceGetter.Wrappers.Ichi) {
            token0 = IICHIVault(lp).token0();
            token1 = IICHIVault(lp).token1();
        } else {
            //As backup just try token0() and token1() which is default interface usually
            token0 = address(Hypervisor(lp).token0());
            token1 = address(Hypervisor(lp).token1());
        }

        (uint256 priceToken0, ) = getTokenPrice(token0, protocol, factory);
        (uint256 priceToken1, ) = getTokenPrice(token1, protocol, factory);

        if (wrapper == IPriceGetter.Wrappers.Gamma) {
            (total0, total1) = Hypervisor(lp).getTotalAmounts();
        } else if (wrapper == IPriceGetter.Wrappers.Ichi) {
            (total0, total1) = IICHIVault(lp).getTotalAmounts();
        } else {
            //as backup just try gamma which is has pretty generic interface
            (total0, total1) = Hypervisor(lp).getTotalAmounts();
        }

        price =
            (priceToken0 *
                UtilityLibrary._normalizeToken(total0, token0) +
                priceToken1 *
                UtilityLibrary._normalizeToken(total1, token1)) /
            IERC20(lp).totalSupply();
    }

    // ========== Get Native Prices ==========

    /**
     * @dev Returns the current price of wrappedNative in USD based on the given protocol.
     * @param protocol The protocol version to use
     * @param factory The address of the factory used to calculate the price.
     * @return nativePrice The current price of wrappedNative in USD.
     */
    function getNativePrice(Protocol protocol, address factory) public view returns (uint256 nativePrice) {
        /// @dev Short circuit if oracle price is found
        uint256 oraclePrice = getOraclePriceNormalized(wrappedNative.tokenAddress);
        if (oraclePrice > 0) {
            return oraclePrice;
        }

        IPriceGetterProtocol extension = getPriceGetterProtocol(protocol);
        nativePrice = extension.getNativePrice(factory, getParams());
    }

    /**
     * @dev Retrieves the normalized USD price of a token from its oracle.
     * @param token Address of the token to retrieve the price for.
     * @return price The normalized USD price of the token from its oracle.
     */
    function getOraclePriceNormalized(address token) public view returns (uint256 price) {
        OracleInfo memory oracleInfo = tokenOracles[token];
        if (oracleInfo.oracleType == OracleType.CHAIN_LINK) {
            uint256 tokenUSDPrice = _getChainlinkPriceRaw(oracleInfo.oracleAddress);
            return UtilityLibrary._normalize(tokenUSDPrice, oracleInfo.oracleDecimals);
        }
        /// @dev Additional oracle types can be implemented here.
        // else if (oracleInfo.oracleType == OracleType.<NEW_ORACLE>) { }
        return 0;
    }

    function getPriceGetterProtocol(Protocol protocol) public view returns (IPriceGetterProtocol extension) {
        extension = protocolPriceGetter[protocol];
        if (address(extension) == address(0)) {
            revert("Invalid extension");
        }
    }

    /** VIEW FUNCTIONS */

    function getParams() public view returns (IPriceGetterProtocol.PriceGetterParams memory params) {
        params = IPriceGetterProtocol.PriceGetterParams(
            this,
            wrappedNative,
            stableUsdTokens,
            nativeLiquidityThreshold,
            stableUsdThreshold
        );
    }
}

// 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);

  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
    );
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal onlyInitializing {
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal onlyInitializing {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

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.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * 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 prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

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

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

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

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized != type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or 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 {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
    }

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.28;

interface IPriceGetter {
    enum Protocol {
        UniV2,
        UniV3,
        UniV4,
        Algebra,
        AlgebraV4,
        Solidly,
        Curve
    }

    enum Wrappers {
        Gamma,
        Ichi,
        Steer
    }

    struct TokenAndDecimals {
        address tokenAddress;
        uint8 decimals;
    }

    function getTokenPrice(
        address token,
        Protocol protocol,
        address factory
    ) external view returns (uint256 price, uint256 usdBalance);
    function getLPPrice(address lp, Protocol protocol, address factory) external view returns (uint256 price);
    function getWrappedLPPrice(
        address lp,
        Protocol protocol,
        address factory,
        IPriceGetter.Wrappers wrapper
    ) external view returns (uint256 price);
    function getNativePrice(Protocol protocol, address factory) external view returns (uint256 nativePrice);
    function getOraclePriceNormalized(address token) external view returns (uint256 price);
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

abstract contract ChainlinkOracle {
    /// @notice Returns the price of the token in decimals of oracle
    function _getChainlinkPriceRaw(address oracleAddress) internal view returns (uint256) {
        AggregatorV3Interface priceFeed = AggregatorV3Interface(oracleAddress);
        (, int256 price, , , ) = priceFeed.latestRoundData();
        return uint256(price);
    }

    /// @notice Returns the price of the token in wei with 18 decimals
    function _getChainlinkPriceNormalized(address oracleAddress) internal view returns (uint256) {
        AggregatorV3Interface priceFeed = AggregatorV3Interface(oracleAddress);
        (, int256 price, , , ) = AggregatorV3Interface(oracleAddress).latestRoundData();
        uint8 decimals = priceFeed.decimals();
        return (uint256(price) * 10 ** 18) / 10 ** decimals;
    }
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.28;

import "../IPriceGetter.sol";

interface IPriceGetterProtocol {
    struct PriceGetterParams {
        IPriceGetter mainPriceGetter;
        IPriceGetter.TokenAndDecimals wrappedNative;
        IPriceGetter.TokenAndDecimals[] stableUsdTokens;
        uint256 nativeLiquidityThreshold;
        uint256 stableUsdThreshold;
    }

    /**
     * @dev Returns the price of a token.
     * @param token The address of the token to get the price for.
     * @return price The current price of the token.
     */
    function getTokenPrice(
        address token,
        address factory,
        PriceGetterParams memory params
    ) external view returns (uint256 price, uint256 usdBalance);

    /**
     * @dev Returns the price of an LP token.
     * @param lp The address of the LP token to get the price for.
     * @return price The current price of the LP token.
     */
    function getLPPrice(
        address lp,
        address factory,
        PriceGetterParams memory params
    ) external view returns (uint256 price);

    /**
     * @dev Returns the current price of the native token in USD.
     * @return nativePrice The current price of the native token in USD.
     */
    function getNativePrice(
        address factory,
        PriceGetterParams memory params
    ) external view returns (uint256 nativePrice);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import "../token-lib/IERC20.sol";

interface Hypervisor is IERC20 {
    function token0() external view returns (IERC20);

    function token1() external view returns (IERC20);

    function whitelistedAddress() external view returns (address);

    function withdraw(
        uint256 shares,
        address to,
        address from,
        uint256[4] memory minAmounts
    ) external returns (uint256 amount0, uint256 amount1);

    function getTotalAmounts() external view returns (uint256 total0, uint256 total1);
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.6.6;

interface IICHIVault {
    function ichiVaultFactory() external view returns (address);

    function pool() external view returns (address);
    function token0() external view returns (address);
    function allowToken0() external view returns (bool);
    function token1() external view returns (address);
    function allowToken1() external view returns (bool);
    function fee() external view returns (uint24);
    function tickSpacing() external view returns (int24);
    function affiliate() external view returns (address);

    function baseLower() external view returns (int24);
    function baseUpper() external view returns (int24);
    function limitLower() external view returns (int24);
    function limitUpper() external view returns (int24);

    function deposit0Max() external view returns (uint256);
    function deposit1Max() external view returns (uint256);
    function maxTotalSupply() external view returns (uint256);
    function hysteresis() external view returns (uint256);

    function getTotalAmounts() external view returns (uint256, uint256);

    function deposit(uint256, uint256, address) external returns (uint256);

    function withdraw(uint256, address) external returns (uint256, uint256);

    function rebalance(
        int24 _baseLower,
        int24 _baseUpper,
        int24 _limitLower,
        int24 _limitUpper,
        int256 swapQuantity
    ) external;

    function setDepositMax(uint256 _deposit0Max, uint256 _deposit1Max) external;

    function setAffiliate(address _affiliate) external;

    event DeployICHIVault(
        address indexed sender,
        address indexed pool,
        bool allowToken0,
        bool allowToken1,
        address owner,
        uint256 twapPeriod
    );

    event SetTwapPeriod(address sender, uint32 newTwapPeriod);

    event Deposit(address indexed sender, address indexed to, uint256 shares, uint256 amount0, uint256 amount1);

    event Withdraw(address indexed sender, address indexed to, uint256 shares, uint256 amount0, uint256 amount1);

    event Rebalance(
        int24 tick,
        uint256 totalAmount0,
        uint256 totalAmount1,
        uint256 feeAmount0,
        uint256 feeAmount1,
        uint256 totalSupply
    );

    event MaxTotalSupply(address indexed sender, uint256 maxTotalSupply);

    event Hysteresis(address indexed sender, uint256 hysteresis);

    event DepositMax(address indexed sender, uint256 deposit0Max, uint256 deposit1Max);

    event Affiliate(address indexed sender, address affiliate);
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.28;

import "../token-lib/IERC20.sol";

library UtilityLibrary {
    function _isSorted(address tokenA, address tokenB) internal pure returns (bool isSorted) {
        //  (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        isSorted = tokenA < tokenB ? true : false;
    }

    function _getTokenDecimals(address token) internal view returns (uint8 decimals) {
        try IERC20(token).decimals() returns (uint8 dec) {
            decimals = dec;
        } catch {
            decimals = 18;
        }
    }

    /// @notice Normalize the amount of a token to wei or 1e18
    function _normalizeToken(uint256 amount, address token) internal view returns (uint256) {
        return _normalize(amount, _getTokenDecimals(token));
    }

    /// @notice Normalize the amount of a token to wei or 1e18
    function _normalizeToken112(uint112 amount, address token) internal view returns (uint112) {
        return _normalize112(amount, _getTokenDecimals(token));
    }

    /// @notice Normalize the amount passed to wei or 1e18 decimals
    function _normalize(uint256 amount, uint8 decimals) internal pure returns (uint256) {
        if (decimals == 18) return amount;
        return (amount * (10 ** 18)) / (10 ** decimals);
    }

    /// @notice Normalize the amount passed to wei or 1e18 decimals
    function _normalize112(uint112 amount, uint8 decimals) internal pure returns (uint112) {
        if (decimals == 18) {
            return amount;
        } else if (decimals > 18) {
            return uint112(amount / (10 ** (decimals - 18)));
        } else {
            return uint112(amount * (10 ** (18 - decimals)));
        }
    }
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.5.0;

interface IERC20 {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

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

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

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint);

    function balanceOf(address owner) external view returns (uint);

    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);

    function transfer(address to, uint value) external returns (bool);

    function transferFrom(address from, address to, uint value) external returns (bool);
}

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

Contract Security Audit

Contract ABI

API
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address[]","name":"newStableUsdTokens","type":"address[]"}],"name":"addStableUsdTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"factory","type":"address"}],"name":"getLPPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"factory","type":"address"}],"name":"getLPPriceTry","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"factory","type":"address"}],"name":"getNativePrice","outputs":[{"internalType":"uint256","name":"nativePrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getOraclePriceNormalized","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getParams","outputs":[{"components":[{"internalType":"contract IPriceGetter","name":"mainPriceGetter","type":"address"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"internalType":"struct IPriceGetter.TokenAndDecimals","name":"wrappedNative","type":"tuple"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"internalType":"struct IPriceGetter.TokenAndDecimals[]","name":"stableUsdTokens","type":"tuple[]"},{"internalType":"uint256","name":"nativeLiquidityThreshold","type":"uint256"},{"internalType":"uint256","name":"stableUsdThreshold","type":"uint256"}],"internalType":"struct IPriceGetterProtocol.PriceGetterParams","name":"params","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"}],"name":"getPriceGetterProtocol","outputs":[{"internalType":"contract IPriceGetterProtocol","name":"extension","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"factory","type":"address"}],"name":"getTokenPrice","outputs":[{"internalType":"uint256","name":"tokenPrice","type":"uint256"},{"internalType":"uint256","name":"usdBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"factory","type":"address"}],"name":"getTokenPriceTry","outputs":[{"internalType":"uint256","name":"tokenPrice","type":"uint256"},{"internalType":"uint256","name":"usdBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"factory","type":"address"}],"name":"getTokenPrices","outputs":[{"internalType":"uint256[]","name":"tokenPrices","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"factory","type":"address"},{"internalType":"enum IPriceGetter.Wrappers","name":"wrapper","type":"uint8"}],"name":"getWrappedLPPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"factory","type":"address"},{"internalType":"enum IPriceGetter.Wrappers","name":"wrapper","type":"uint8"}],"name":"getWrappedLPPriceTry","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wNative","type":"address"},{"internalType":"uint256","name":"_nativeLiquidityThreshold","type":"uint256"},{"internalType":"uint256","name":"_stableUsdThreshold","type":"uint256"},{"internalType":"address[]","name":"_stableUsdTokens","type":"address[]"},{"internalType":"address[]","name":"_oracleTokens","type":"address[]"},{"internalType":"address[]","name":"_oracles","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nativeLiquidityThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IPriceGetter.Protocol","name":"","type":"uint8"}],"name":"protocolPriceGetter","outputs":[{"internalType":"contract IPriceGetterProtocol","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"removeStableUsdTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeTokenOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nativeLiquidityThreshold","type":"uint256"}],"name":"setNativeLiquidityThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IPriceGetter.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"extension","type":"address"}],"name":"setPriceGetterProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IPriceGetter.Protocol[]","name":"protocols","type":"uint8[]"},{"internalType":"address[]","name":"extensions","type":"address[]"}],"name":"setPriceGetterProtocols","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stableUsdThreshold","type":"uint256"}],"name":"setStableUsdThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"oracleAddress","type":"address"},{"internalType":"enum PriceGetter.OracleType","name":"oracleType","type":"uint8"}],"name":"setTokenOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stableUsdThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stableUsdTokens","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenOracles","outputs":[{"internalType":"enum PriceGetter.OracleType","name":"oracleType","type":"uint8"},{"internalType":"address","name":"oracleAddress","type":"address"},{"internalType":"uint8","name":"oracleDecimals","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608080604052346015576120d1908161001b8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c80631e2fa68d1461150f5780632c5c014414611008578063354c894a14610fef5780634bb3ae6214610fd157806352b4fdbe14610df15780635e615a6b14610dbd5780636888b44014610d13578063715018a614610cb65780637d60227b14610c9d57806384fac4ce14610c7a57806388e32fc214610c3f5780638da5cb5b14610c165780639b788f0b14610bdc578063a9828f8a14610bbe578063abacdeab14610aa5578063af63775f14610662578063b0af197014610626578063b6fe86c414610601578063b71c7ed6146104eb578063b88869b3146104cf578063bd49243214610450578063bff9eb361461042f578063d135babe1461040e578063ed0f171b1461028d578063f2fde38b146101fe578063fcd9c2f0146101bf578063fefa8342146101765763ff72def21461015057600080fd5b3461017157602061016961016336611827565b90611e0d565b604051908152f35b600080fd5b34610171576020366003190112610171576004356068548110156101715761019f604091611856565b505481516001600160a01b038216815260a09190911c60ff166020820152f35b34610171576101df6101d036611827565b91906101da611eca565b61180e565b80546001600160a01b0319166001600160a01b03909216919091179055005b346101715760203660031901126101715761021761163b565b61021f611eca565b6001600160a01b038116156102395761023790611f22565b005b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b34610171576020366003190112610171576004356001600160401b038111610171576102bd90369060040161160b565b906102c6611eca565b60005b8281106102d257005b6102e56102e0828585611887565b611897565b6068546001600160a01b039091169060005b81811061030a575b5050506001016102c9565b8261031482611856565b50546001600160a01b03161461032c576001016102f7565b915060001981019081116103f85761034661034d91611856565b5091611856565b61038a578181036103b6575b505060685480156103a057600019019061037282611856565b92909261038a576000600193556068559084806102ff565b634e487b7160e01b600052600060045260246000fd5b634e487b7160e01b600052603160045260246000fd5b815481546001600160a01b039091166001600160a01b0319821681178355925460ff60a01b166001600160a81b03199091169092179190911790558380610359565b634e487b7160e01b600052601160045260246000fd5b3461017157602036600319011261017157610427611eca565b600435606955005b3461017157602036600319011261017157610448611eca565b600435606a55005b34610171576020366003190112610171576001600160a01b0361047161163b565b16600052606660205260406000205460ff81166040519060028110156104b9578152600882901c6001600160a01b0316602082015260a89190911c60ff166040820152606090f35b634e487b7160e01b600052602160045260246000fd5b346101715760206101696104e236611651565b92919091611da7565b34610171576020366003190112610171576004356001600160401b0381116101715761051b90369060040161160b565b90610524611eca565b60005b82811061053057005b61053e6102e0828585611887565b6068546001600160a01b03821692916000805b8381106105d5575b501561056c575b50506001915001610527565b61057760ff91612043565b60405194610584866116e4565b8552166020840152600160401b8110156105bf578060016105a89201606855611856565b61038a576001926105b891611d03565b8480610560565b634e487b7160e01b600052604160045260246000fd5b856105df82611856565b50546001600160a01b0316146105f757600101610551565b5050600187610559565b3461017157604061061a610614366116a1565b91611d3b565b82519182526020820152f35b34610171576020366003190112610171576004356007811015610171576020906001600160a01b03906106589061180e565b5416604051908152f35b346101715760c03660031901126101715761067b61163b565b6064356001600160401b0381116101715761069a90369060040161160b565b90916084356001600160401b038111610171576106bb90369060040161160b565b93909260a4356001600160401b038111610171576106dd90369060040161160b565b90946000549560ff8760081c161596878098610a98575b8015610a81575b15610a255760ff19811660011760005587610a13575b5061072c60ff60005460081c1661072781611fe3565b611fe3565b61073533611f22565b602435606955604435606a558288036109d5576001979192600092835b8181106108c557505050505050610767611eca565b8460005b828110610807575050505061077f81612043565b906040519061078d826116e4565b6001600160a01b031680825260ff8316602090920191909152606780546001600160a81b03191690911760a09290921b60ff60a01b169190911790556107cf57005b60207f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989161ff001960005416600055604051908152a1005b6108156102e0828587611887565b6068546001600160a01b03821691600085815b848110610899575b505015610843575b50505001859061076b565b60ff9192945061085290612043565b6040519461085f866116e4565b8552166020840152600160401b8110156105bf5780886108829201606855611856565b61038a57879261089191611d03565b878080610838565b856108a382611856565b50546001600160a01b0316146108bb57018690610828565b509050858c610830565b6108d36102e0828489611887565b906108e26102e0828688611887565b60405163313ce56760e01b81526001600160a01b039091169290601290602081600481885afa600091816109a5575b5061099d575b5060405191886109268461171a565b6104b9578e83526020830194855260ff604084019216825260018060a01b03166000526066602052604060002091519060028210156104b9578e9460ff845491610100600160a81b03905160081b16928160a81b905160a81b1693169069ffffffffffffffffffff60b01b16171717905501610752565b90508e610917565b6109c791925060203d81116109ce575b6109bf8183611735565b810190611fca565b9038610911565b503d6109b5565b60405162461bcd60e51b815260206004820152601660248201527509ee4c2c6d8ca40d8cadccee8d040dad2e6dac2e8c6d60531b6044820152606490fd5b61ffff19166101011760005588610711565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b1580156106fb5750600160ff8216146106fb565b50600160ff8216106106f4565b3461017157606036600319011261017157610abe61163b565b6024356001600160a01b038116908190036101715760443591600283101561017157610ae8611eca565b60405163313ce56760e01b815260129190602081600481875afa60009181610b9d575b50610b95575b50610b2860405194610b228661171a565b85611b99565b6020840192835260ff604085019216825260018060a01b03166000526066602052604060002092519160028310156104b95760ff845491610100600160a81b03905160081b16928160a81b905160a81b1693169069ffffffffffffffffffff60b01b161717179055600080f35b915084610b11565b610bb791925060203d6020116109ce576109bf8183611735565b9086610b0b565b34610171576000366003190112610171576020606954604051908152f35b3461017157602036600319011261017157600435600781101561017157610c04602091611cad565b6040516001600160a01b039091168152f35b34610171576000366003190112610171576033546040516001600160a01b039091168152602090f35b3461017157602036600319011261017157610c5861163b565b610c60611eca565b6001600160a01b0316600090815260666020526040812055005b34610171576020366003190112610171576020610169610c9861163b565b611ba5565b3461017157604061061a610cb0366116a1565b91611b21565b3461017157600036600319011261017157610ccf611eca565b603380546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461017157610d616020610d26366116a1565b906001600160a01b0390610d3990611cad565b1690610d436119db565b6040516344ee250760e11b8152958694859384939160048501611af8565b03915afa8015610db157600090610d7e575b602090604051908152f35b506020813d602011610da9575b81610d9860209383611735565b810103126101715760209051610d73565b3d9150610d8b565b6040513d6000823e3d90fd5b3461017157600036600319011261017157610ded610dd96119db565b60405191829160208352602083019061176d565b0390f35b34610171576040366003190112610171576004356001600160401b0381116101715736602382011215610171578060040135610e2c81611756565b91610e3a6040519384611735565b8183526024602084019260051b8201019036821161017157602401915b818310610fb857602435846001600160401b0382116101715736602383011215610171578160040135610e8981611756565b92610e976040519485611735565b8184526024602085019260051b8201019036821161017157602401915b818310610f9857505050610ec6611eca565b8051825103610f375760005b815181101561023757610ee581836118ab565b519060078210156104b957600191610f136001600160a01b03610f0884886118ab565b5116916101da611eca565b90838060a01b03166bffffffffffffffffffffffff60a01b82541617905501610ed2565b60405162461bcd60e51b815260206004820152603360248201527f4e756d626572206f662070726f746f636f6c73206d757374206d61746368206e604482015272756d626572206f6620657874656e73696f6e7360681b6064820152608490fd5b82356001600160a01b038116810361017157815260209283019201610eb4565b8235600781101561017157815260209283019201610e57565b34610171576000366003190112610171576020606a54604051908152f35b34610171576020610169611002366116a1565b91611969565b346101715761101636611651565b6007839294931015806104b95760018314159081611501575b816114ef575b816114de575b5061149957600091600382101591826114855780159384156113155750604051630dfe168160e01b81526001600160a01b0386169490602081600481895afa908115610db1576004916020916000916112f8575b5060405163d21220a760e01b81526001600160a01b0391909116979092839182905afa8015610db1576110e3916000916112c9575b506001600160a01b0316975b6110db818689611b21565b509489611b21565b50936104b95715611212575060408051636253bb0f60e11b815290816004816001600160a01b0389165afa918215610db15761115194611145936000936000916111cb575b509161114561114b9261113f61113f959691612043565b90611f82565b906118f4565b96612043565b82018092116103f8576040516318160ddd60e01b815290602090829060049082906001600160a01b03165afa908115610db157600091611198575b60206101698385611907565b90506020813d6020116111c3575b816111b360209383611735565b810103126101715751602061118c565b3d91506111a6565b61113f945061113f93915061114b926111fe6111459260403d60401161120b575b6111f68183611735565b8101906118de565b9096509294509250611128565b503d6111ec565b91926000926001036112795760408051636253bb0f60e11b815290816004816001600160a01b038a165afa90811561126e579161114593918593611151979694916111cb57509161114561114b9261113f61113f959691612043565b6040513d86823e3d90fd5b60408051636253bb0f60e11b815290816004816001600160a01b038a165afa90811561126e579161114593918593611151979694916111cb57509161114561114b9261113f61113f959691612043565b6112eb915060203d6020116112f1575b6112e38183611735565b8101906118bf565b896110c4565b503d6112d9565b61130f9150823d84116112f1576112e38183611735565b8a61108f565b925082600182036113c25750604051630dfe168160e01b81526001600160a01b0386169490602081600481895afa908115610db1576004916020916000916113a5575b50966040519283809263d21220a760e01b82525afa8015610db1576110e391600091611386575b50976110d0565b61139f915060203d6020116112f1576112e38183611735565b8961137f565b6113bc9150823d84116112f1576112e38183611735565b8a611358565b604051630dfe168160e01b81526001600160a01b0387169591906020816004818a5afa918215611479576004926020929061145c575b5060405163d21220a760e01b81526001600160a01b0391909116979092839182905afa8015610db1576110e39160009161143d575b506001600160a01b0316976110d0565b611456915060203d6020116112f1576112e38183611735565b8961142d565b6114739150823d84116112f1576112e38183611735565b8a6113f8565b604051903d90823e3d90fd5b634e487b7160e01b84526021600452602484fd5b60405162461bcd60e51b815260206004820152601f60248201527f50726f746f636f6c20646f6573206e6f742068617665207772617070657273006044820152606490fd5b90506104b95760048214158561103b565b8091506104b957600283141590611035565b50506003821415600061102f565b34610171576060366003190112610171576004356001600160401b0381116101715761153f90369060040161160b565b602435916007831015610171576044356001600160a01b03811681036101715761156883611756565b936115766040519586611735565b83855261158284611756565b602086019490601f190136863760005b8181106115de5785876040519182916020830190602084525180915260408301919060005b8181106115c5575050500390f35b82518452859450602093840193909201916001016115b7565b806115f985856115f46102e0600196888c611887565b611b21565b50611604828a6118ab565b5201611592565b9181601f84011215610171578235916001600160401b038311610171576020808501948460051b01011161017157565b600435906001600160a01b038216820361017157565b6080906003190112610171576004356001600160a01b03811681036101715790602435600781101561017157906044356001600160a01b0381168103610171579060643560038110156101715790565b6060906003190112610171576004356001600160a01b03811681036101715790602435600781101561017157906044356001600160a01b03811681036101715790565b604081019081106001600160401b038211176105bf57604052565b60a081019081106001600160401b038211176105bf57604052565b606081019081106001600160401b038211176105bf57604052565b90601f801991011681019081106001600160401b038211176105bf57604052565b6001600160401b0381116105bf5760051b60200190565b80516001600160a01b039081168352602080830151805190921681850152015160ff16604083015260c08201919060408101519260c060608401528351809152602060e0840194019060005b8181106117d957505050608081606060a093015182850152015191015290565b90919460206040826118036001948a5160ff6020809260018060a01b038151168552015116910152565b0196019291016117b9565b60078110156104b9576000526065602052604060002090565b604090600319011261017157600435600781101561017157906024356001600160a01b03811681036101715790565b60685481101561187157606860005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b91908110156118715760051b0190565b356001600160a01b03811681036101715790565b80518210156118715760209160051b010190565b9081602091031261017157516001600160a01b03811681036101715790565b9190826040910312610171576020825192015190565b818102929181159184041417156103f857565b8115611911570490565b634e487b7160e01b600052601260045260246000fd5b9060078210156104b95752565b6001600160a01b03909116815260608101939290916040919061195b906020850190611927565b6001600160a01b0316910152565b9060209161198b60405194859384936301a222d160e61b855260048501611934565b0381305afa600091816119a7575b506119a45750600090565b90565b9091506020813d6020116119d3575b816119c360209383611735565b8101031261017157519038611999565b3d91506119b6565b600060806040516119eb816116ff565b8281526040516119fa816116e4565b8381528360208201526020820152606060408201528260608201520152606954606a5460405191611a2a836116ff565b308352604051611a39816116e4565b6067546001600160a01b038116825260a01c60ff16602080830191909152840152606854611a6681611756565b90611a746040519283611735565b8082526020820160686000527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977536000915b838310611ac2575050505060408401526060830152608082015290565b600160208192604051611ad4816116e4565b60ff8654858060a01b038116835260a01c1683820152815201920192019190611aa5565b6001600160a01b039182168152911660208201526060604082018190526119a49291019061176d565b611b61926040926001600160a01b0390611b3a90611cad565b1690611b446119db565b8451637644752d60e11b8152958694859384939160048501611af8565b03915afa8015610db157600091600091611b7a57509091565b9050611b95915060403d60401161120b576111f68183611735565b9091565b60028210156104b95752565b60018060a01b03166000526066602052604060002060405190611bc78261171a565b5490611bd660ff831682611b99565b602081019060018060a01b038360081c16825260ff604082019360a81c168352519060028210156104b957600160009214611c115750905090565b51604051633fabe5a360e21b81529060a090829060049082906001600160a01b03165afa918215611479578092611c53575b505060ff6119a492511690611f82565b90915060a0823d60a011611ca5575b81611c6f60a09383611735565b81010312611ca257509060ff82611c886119a494611f6b565b50611c9a608060208301519201611f6b565b509192611c43565b80fd5b3d9150611c62565b6001600160a01b0390611cbf9061180e565b5416908115611cca57565b60405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21032bc3a32b739b4b7b760791b6044820152606490fd5b81518154602093909301516001600160a81b03199093166001600160a01b03919091161760a09290921b60ff60a01b16919091179055565b60408051637d60227b60e01b81529493909285928392611d6092909160048501611934565b0381305afa9182600091600094611d84575b50611d805750600091508190565b9190565b909350611da0915060403d60401161120b576111f68183611735565b9238611d72565b604051630b17005160e21b81526001600160a01b039091166004820152929190611dd5906024850190611927565b6001600160a01b0316604483015260038110156104b9576064820152602081608481305afa600091816119a757506119a45750600090565b606754611e22906001600160a01b0316611ba5565b80611ec45750611e7f916020916001600160a01b0390611e4190611cad565b16611e4a6119db565b604080516365cdd57160e11b81526001600160a01b03909416600485015260248401529193849283918291604483019061176d565b03915afa908115610db157600091611e95575090565b90506020813d602011611ebc575b81611eb060209383611735565b81010312610171575190565b3d9150611ea3565b91505090565b6033546001600160a01b03163303611ede57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b519069ffffffffffffffffffff8216820361017157565b9060ff169060128214611fc557670de0b6b3a7640000810290808204670de0b6b3a764000014901517156103f857604d82116103f8576119a491600a0a90611907565b905090565b90816020910312610171575160ff811681036101715790565b15611fea57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b60405163313ce56760e01b815290602090829060049082906001600160a01b03165afa6000918161207a575b506119a45750601290565b61209491925060203d6020116109ce576109bf8183611735565b903861206f56fea264697066735822122039928da7f933ce99ce7e7f6de87b151854d698f87cde809a390eeddeea3e224764736f6c634300081c0033

Deployed Bytecode

0x6080604052600436101561001257600080fd5b60003560e01c80631e2fa68d1461150f5780632c5c014414611008578063354c894a14610fef5780634bb3ae6214610fd157806352b4fdbe14610df15780635e615a6b14610dbd5780636888b44014610d13578063715018a614610cb65780637d60227b14610c9d57806384fac4ce14610c7a57806388e32fc214610c3f5780638da5cb5b14610c165780639b788f0b14610bdc578063a9828f8a14610bbe578063abacdeab14610aa5578063af63775f14610662578063b0af197014610626578063b6fe86c414610601578063b71c7ed6146104eb578063b88869b3146104cf578063bd49243214610450578063bff9eb361461042f578063d135babe1461040e578063ed0f171b1461028d578063f2fde38b146101fe578063fcd9c2f0146101bf578063fefa8342146101765763ff72def21461015057600080fd5b3461017157602061016961016336611827565b90611e0d565b604051908152f35b600080fd5b34610171576020366003190112610171576004356068548110156101715761019f604091611856565b505481516001600160a01b038216815260a09190911c60ff166020820152f35b34610171576101df6101d036611827565b91906101da611eca565b61180e565b80546001600160a01b0319166001600160a01b03909216919091179055005b346101715760203660031901126101715761021761163b565b61021f611eca565b6001600160a01b038116156102395761023790611f22565b005b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b34610171576020366003190112610171576004356001600160401b038111610171576102bd90369060040161160b565b906102c6611eca565b60005b8281106102d257005b6102e56102e0828585611887565b611897565b6068546001600160a01b039091169060005b81811061030a575b5050506001016102c9565b8261031482611856565b50546001600160a01b03161461032c576001016102f7565b915060001981019081116103f85761034661034d91611856565b5091611856565b61038a578181036103b6575b505060685480156103a057600019019061037282611856565b92909261038a576000600193556068559084806102ff565b634e487b7160e01b600052600060045260246000fd5b634e487b7160e01b600052603160045260246000fd5b815481546001600160a01b039091166001600160a01b0319821681178355925460ff60a01b166001600160a81b03199091169092179190911790558380610359565b634e487b7160e01b600052601160045260246000fd5b3461017157602036600319011261017157610427611eca565b600435606955005b3461017157602036600319011261017157610448611eca565b600435606a55005b34610171576020366003190112610171576001600160a01b0361047161163b565b16600052606660205260406000205460ff81166040519060028110156104b9578152600882901c6001600160a01b0316602082015260a89190911c60ff166040820152606090f35b634e487b7160e01b600052602160045260246000fd5b346101715760206101696104e236611651565b92919091611da7565b34610171576020366003190112610171576004356001600160401b0381116101715761051b90369060040161160b565b90610524611eca565b60005b82811061053057005b61053e6102e0828585611887565b6068546001600160a01b03821692916000805b8381106105d5575b501561056c575b50506001915001610527565b61057760ff91612043565b60405194610584866116e4565b8552166020840152600160401b8110156105bf578060016105a89201606855611856565b61038a576001926105b891611d03565b8480610560565b634e487b7160e01b600052604160045260246000fd5b856105df82611856565b50546001600160a01b0316146105f757600101610551565b5050600187610559565b3461017157604061061a610614366116a1565b91611d3b565b82519182526020820152f35b34610171576020366003190112610171576004356007811015610171576020906001600160a01b03906106589061180e565b5416604051908152f35b346101715760c03660031901126101715761067b61163b565b6064356001600160401b0381116101715761069a90369060040161160b565b90916084356001600160401b038111610171576106bb90369060040161160b565b93909260a4356001600160401b038111610171576106dd90369060040161160b565b90946000549560ff8760081c161596878098610a98575b8015610a81575b15610a255760ff19811660011760005587610a13575b5061072c60ff60005460081c1661072781611fe3565b611fe3565b61073533611f22565b602435606955604435606a558288036109d5576001979192600092835b8181106108c557505050505050610767611eca565b8460005b828110610807575050505061077f81612043565b906040519061078d826116e4565b6001600160a01b031680825260ff8316602090920191909152606780546001600160a81b03191690911760a09290921b60ff60a01b169190911790556107cf57005b60207f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989161ff001960005416600055604051908152a1005b6108156102e0828587611887565b6068546001600160a01b03821691600085815b848110610899575b505015610843575b50505001859061076b565b60ff9192945061085290612043565b6040519461085f866116e4565b8552166020840152600160401b8110156105bf5780886108829201606855611856565b61038a57879261089191611d03565b878080610838565b856108a382611856565b50546001600160a01b0316146108bb57018690610828565b509050858c610830565b6108d36102e0828489611887565b906108e26102e0828688611887565b60405163313ce56760e01b81526001600160a01b039091169290601290602081600481885afa600091816109a5575b5061099d575b5060405191886109268461171a565b6104b9578e83526020830194855260ff604084019216825260018060a01b03166000526066602052604060002091519060028210156104b9578e9460ff845491610100600160a81b03905160081b16928160a81b905160a81b1693169069ffffffffffffffffffff60b01b16171717905501610752565b90508e610917565b6109c791925060203d81116109ce575b6109bf8183611735565b810190611fca565b9038610911565b503d6109b5565b60405162461bcd60e51b815260206004820152601660248201527509ee4c2c6d8ca40d8cadccee8d040dad2e6dac2e8c6d60531b6044820152606490fd5b61ffff19166101011760005588610711565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b1580156106fb5750600160ff8216146106fb565b50600160ff8216106106f4565b3461017157606036600319011261017157610abe61163b565b6024356001600160a01b038116908190036101715760443591600283101561017157610ae8611eca565b60405163313ce56760e01b815260129190602081600481875afa60009181610b9d575b50610b95575b50610b2860405194610b228661171a565b85611b99565b6020840192835260ff604085019216825260018060a01b03166000526066602052604060002092519160028310156104b95760ff845491610100600160a81b03905160081b16928160a81b905160a81b1693169069ffffffffffffffffffff60b01b161717179055600080f35b915084610b11565b610bb791925060203d6020116109ce576109bf8183611735565b9086610b0b565b34610171576000366003190112610171576020606954604051908152f35b3461017157602036600319011261017157600435600781101561017157610c04602091611cad565b6040516001600160a01b039091168152f35b34610171576000366003190112610171576033546040516001600160a01b039091168152602090f35b3461017157602036600319011261017157610c5861163b565b610c60611eca565b6001600160a01b0316600090815260666020526040812055005b34610171576020366003190112610171576020610169610c9861163b565b611ba5565b3461017157604061061a610cb0366116a1565b91611b21565b3461017157600036600319011261017157610ccf611eca565b603380546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461017157610d616020610d26366116a1565b906001600160a01b0390610d3990611cad565b1690610d436119db565b6040516344ee250760e11b8152958694859384939160048501611af8565b03915afa8015610db157600090610d7e575b602090604051908152f35b506020813d602011610da9575b81610d9860209383611735565b810103126101715760209051610d73565b3d9150610d8b565b6040513d6000823e3d90fd5b3461017157600036600319011261017157610ded610dd96119db565b60405191829160208352602083019061176d565b0390f35b34610171576040366003190112610171576004356001600160401b0381116101715736602382011215610171578060040135610e2c81611756565b91610e3a6040519384611735565b8183526024602084019260051b8201019036821161017157602401915b818310610fb857602435846001600160401b0382116101715736602383011215610171578160040135610e8981611756565b92610e976040519485611735565b8184526024602085019260051b8201019036821161017157602401915b818310610f9857505050610ec6611eca565b8051825103610f375760005b815181101561023757610ee581836118ab565b519060078210156104b957600191610f136001600160a01b03610f0884886118ab565b5116916101da611eca565b90838060a01b03166bffffffffffffffffffffffff60a01b82541617905501610ed2565b60405162461bcd60e51b815260206004820152603360248201527f4e756d626572206f662070726f746f636f6c73206d757374206d61746368206e604482015272756d626572206f6620657874656e73696f6e7360681b6064820152608490fd5b82356001600160a01b038116810361017157815260209283019201610eb4565b8235600781101561017157815260209283019201610e57565b34610171576000366003190112610171576020606a54604051908152f35b34610171576020610169611002366116a1565b91611969565b346101715761101636611651565b6007839294931015806104b95760018314159081611501575b816114ef575b816114de575b5061149957600091600382101591826114855780159384156113155750604051630dfe168160e01b81526001600160a01b0386169490602081600481895afa908115610db1576004916020916000916112f8575b5060405163d21220a760e01b81526001600160a01b0391909116979092839182905afa8015610db1576110e3916000916112c9575b506001600160a01b0316975b6110db818689611b21565b509489611b21565b50936104b95715611212575060408051636253bb0f60e11b815290816004816001600160a01b0389165afa918215610db15761115194611145936000936000916111cb575b509161114561114b9261113f61113f959691612043565b90611f82565b906118f4565b96612043565b82018092116103f8576040516318160ddd60e01b815290602090829060049082906001600160a01b03165afa908115610db157600091611198575b60206101698385611907565b90506020813d6020116111c3575b816111b360209383611735565b810103126101715751602061118c565b3d91506111a6565b61113f945061113f93915061114b926111fe6111459260403d60401161120b575b6111f68183611735565b8101906118de565b9096509294509250611128565b503d6111ec565b91926000926001036112795760408051636253bb0f60e11b815290816004816001600160a01b038a165afa90811561126e579161114593918593611151979694916111cb57509161114561114b9261113f61113f959691612043565b6040513d86823e3d90fd5b60408051636253bb0f60e11b815290816004816001600160a01b038a165afa90811561126e579161114593918593611151979694916111cb57509161114561114b9261113f61113f959691612043565b6112eb915060203d6020116112f1575b6112e38183611735565b8101906118bf565b896110c4565b503d6112d9565b61130f9150823d84116112f1576112e38183611735565b8a61108f565b925082600182036113c25750604051630dfe168160e01b81526001600160a01b0386169490602081600481895afa908115610db1576004916020916000916113a5575b50966040519283809263d21220a760e01b82525afa8015610db1576110e391600091611386575b50976110d0565b61139f915060203d6020116112f1576112e38183611735565b8961137f565b6113bc9150823d84116112f1576112e38183611735565b8a611358565b604051630dfe168160e01b81526001600160a01b0387169591906020816004818a5afa918215611479576004926020929061145c575b5060405163d21220a760e01b81526001600160a01b0391909116979092839182905afa8015610db1576110e39160009161143d575b506001600160a01b0316976110d0565b611456915060203d6020116112f1576112e38183611735565b8961142d565b6114739150823d84116112f1576112e38183611735565b8a6113f8565b604051903d90823e3d90fd5b634e487b7160e01b84526021600452602484fd5b60405162461bcd60e51b815260206004820152601f60248201527f50726f746f636f6c20646f6573206e6f742068617665207772617070657273006044820152606490fd5b90506104b95760048214158561103b565b8091506104b957600283141590611035565b50506003821415600061102f565b34610171576060366003190112610171576004356001600160401b0381116101715761153f90369060040161160b565b602435916007831015610171576044356001600160a01b03811681036101715761156883611756565b936115766040519586611735565b83855261158284611756565b602086019490601f190136863760005b8181106115de5785876040519182916020830190602084525180915260408301919060005b8181106115c5575050500390f35b82518452859450602093840193909201916001016115b7565b806115f985856115f46102e0600196888c611887565b611b21565b50611604828a6118ab565b5201611592565b9181601f84011215610171578235916001600160401b038311610171576020808501948460051b01011161017157565b600435906001600160a01b038216820361017157565b6080906003190112610171576004356001600160a01b03811681036101715790602435600781101561017157906044356001600160a01b0381168103610171579060643560038110156101715790565b6060906003190112610171576004356001600160a01b03811681036101715790602435600781101561017157906044356001600160a01b03811681036101715790565b604081019081106001600160401b038211176105bf57604052565b60a081019081106001600160401b038211176105bf57604052565b606081019081106001600160401b038211176105bf57604052565b90601f801991011681019081106001600160401b038211176105bf57604052565b6001600160401b0381116105bf5760051b60200190565b80516001600160a01b039081168352602080830151805190921681850152015160ff16604083015260c08201919060408101519260c060608401528351809152602060e0840194019060005b8181106117d957505050608081606060a093015182850152015191015290565b90919460206040826118036001948a5160ff6020809260018060a01b038151168552015116910152565b0196019291016117b9565b60078110156104b9576000526065602052604060002090565b604090600319011261017157600435600781101561017157906024356001600160a01b03811681036101715790565b60685481101561187157606860005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b91908110156118715760051b0190565b356001600160a01b03811681036101715790565b80518210156118715760209160051b010190565b9081602091031261017157516001600160a01b03811681036101715790565b9190826040910312610171576020825192015190565b818102929181159184041417156103f857565b8115611911570490565b634e487b7160e01b600052601260045260246000fd5b9060078210156104b95752565b6001600160a01b03909116815260608101939290916040919061195b906020850190611927565b6001600160a01b0316910152565b9060209161198b60405194859384936301a222d160e61b855260048501611934565b0381305afa600091816119a7575b506119a45750600090565b90565b9091506020813d6020116119d3575b816119c360209383611735565b8101031261017157519038611999565b3d91506119b6565b600060806040516119eb816116ff565b8281526040516119fa816116e4565b8381528360208201526020820152606060408201528260608201520152606954606a5460405191611a2a836116ff565b308352604051611a39816116e4565b6067546001600160a01b038116825260a01c60ff16602080830191909152840152606854611a6681611756565b90611a746040519283611735565b8082526020820160686000527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977536000915b838310611ac2575050505060408401526060830152608082015290565b600160208192604051611ad4816116e4565b60ff8654858060a01b038116835260a01c1683820152815201920192019190611aa5565b6001600160a01b039182168152911660208201526060604082018190526119a49291019061176d565b611b61926040926001600160a01b0390611b3a90611cad565b1690611b446119db565b8451637644752d60e11b8152958694859384939160048501611af8565b03915afa8015610db157600091600091611b7a57509091565b9050611b95915060403d60401161120b576111f68183611735565b9091565b60028210156104b95752565b60018060a01b03166000526066602052604060002060405190611bc78261171a565b5490611bd660ff831682611b99565b602081019060018060a01b038360081c16825260ff604082019360a81c168352519060028210156104b957600160009214611c115750905090565b51604051633fabe5a360e21b81529060a090829060049082906001600160a01b03165afa918215611479578092611c53575b505060ff6119a492511690611f82565b90915060a0823d60a011611ca5575b81611c6f60a09383611735565b81010312611ca257509060ff82611c886119a494611f6b565b50611c9a608060208301519201611f6b565b509192611c43565b80fd5b3d9150611c62565b6001600160a01b0390611cbf9061180e565b5416908115611cca57565b60405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21032bc3a32b739b4b7b760791b6044820152606490fd5b81518154602093909301516001600160a81b03199093166001600160a01b03919091161760a09290921b60ff60a01b16919091179055565b60408051637d60227b60e01b81529493909285928392611d6092909160048501611934565b0381305afa9182600091600094611d84575b50611d805750600091508190565b9190565b909350611da0915060403d60401161120b576111f68183611735565b9238611d72565b604051630b17005160e21b81526001600160a01b039091166004820152929190611dd5906024850190611927565b6001600160a01b0316604483015260038110156104b9576064820152602081608481305afa600091816119a757506119a45750600090565b606754611e22906001600160a01b0316611ba5565b80611ec45750611e7f916020916001600160a01b0390611e4190611cad565b16611e4a6119db565b604080516365cdd57160e11b81526001600160a01b03909416600485015260248401529193849283918291604483019061176d565b03915afa908115610db157600091611e95575090565b90506020813d602011611ebc575b81611eb060209383611735565b81010312610171575190565b3d9150611ea3565b91505090565b6033546001600160a01b03163303611ede57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b519069ffffffffffffffffffff8216820361017157565b9060ff169060128214611fc557670de0b6b3a7640000810290808204670de0b6b3a764000014901517156103f857604d82116103f8576119a491600a0a90611907565b905090565b90816020910312610171575160ff811681036101715790565b15611fea57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b60405163313ce56760e01b815290602090829060049082906001600160a01b03165afa6000918161207a575b506119a45750601290565b61209491925060203d6020116109ce576109bf8183611735565b903861206f56fea264697066735822122039928da7f933ce99ce7e7f6de87b151854d698f87cde809a390eeddeea3e224764736f6c634300081c0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.