ETH Price: $2,926.87 (+3.99%)

Contract

0xfe664F6ccC5508c4E9688B9A5Fd08e165A0FEbF3

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:
VoterV5_GaugeLogic

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {IVoterV5_GaugeLogic, IERC165} from "./IVoterV5_GaugeLogic.sol";
import {IERC20} from "../interfaces/IERC20.sol";
import {IAlgebraFactory} from "@cryptoalgebra/v1-core/contracts/interfaces/IAlgebraFactory.sol";
import {IBribeFactory} from "../interfaces/IBribeFactory.sol";
import {IGaugeFactory} from "../interfaces/IGaugeFactory.sol";
import {IPermissionsRegistry} from "../interfaces/IPermissionsRegistry.sol";

import {IHypervisor} from "../interfaces/IHypervisor.sol";
import {IMultiPositionManager} from "../dex/uniswap-v4/IMultiPositionManager.sol";
import {IPairFactory} from "../interfaces/IPairFactory.sol";
import {IPairInfo} from "../interfaces/IPairInfo.sol";
import {VoterV5_Storage} from "./VoterV5_Storage.sol";
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {UniswapV3Helper} from "../libraries/UniswapV3Helper.sol";

/**
 * @notice Table showing GaugeType configurations
 * ┌──────────────────────┬──────────────────────────┬────────────────────────┐
 * │      GaugeType       │       DEX Factory        │     Gauge Factory      │
 * ├──────────────────────┼──────────────────────────┼────────────────────────┤
 * │    PAIR_CLASSIC      │   PairFactoryUpgradable  │    GaugeFactoryV2      │
 * │    ALM_ALGEBRA_V1    │     AlgebraFactory       │   GaugeFactoryV2_CL    │
 * │ ALM_ICHI_UNISWAP_V3  │     UniswapV3Factory     │   GaugeFactoryV2_CL    │
 * │ ALM_GAMMA_UNISWAP_V4 │   UniswapV4PoolManager   │   GaugeFactoryV2_CL    │
 * └──────────────────────┴──────────────────────────┴────────────────────────┘
 */

/// @notice Enum representing different gauge types
/// @dev Make sure to use the correct gaugeType or gauge creation will fail
enum GaugeType {
    PAIR_CLASSIC, // 0: Classic Stable/Volatile pair
    ALM_ALGEBRA_V1, // 1: Ichi/Gamma concentrated liquidity for Algebra
    ALM_ICHI_UNISWAP_V3, // 2: Ichi concentrated liquidity for UniswapV3
    ALM_GAMMA_UNISWAP_V4 // 3: Gamma concentrated liquidity for UniswapV4
}

/// @title VoterV5_GaugeLogic
/// @notice This contract contains the logic for creating gauges in the VoterV5 system. It is used to save contract
///  size in VoterV5 by separating out expensive logic.
/// @dev This contract MUST be called from VoterV5 through delegatecall().
contract VoterV5_GaugeLogic is IVoterV5_GaugeLogic, VoterV5_Storage, ERC165 {
    /**
     * @notice changelog
     * - 1.1.0: Add Support for UniswapV3 and UniswapV4 Gauges
     */
    string public constant VERSION_GAUGE_LOGIC = "1.1.0";

    /// @notice Maximum valid gauge type enum value
    uint256 public constant MAX_GAUGE_TYPE = uint256(type(GaugeType).max);

    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        return interfaceId == type(IVoterV5_GaugeLogic).interfaceId || super.supportsInterface(interfaceId);
    }

    /// @notice Validate if gauge type is within enum bounds (pure function)
    function isValidGaugeType(uint256 _gaugeType) public pure returns (bool) {
        return _gaugeType <= MAX_GAUGE_TYPE;
    }

    struct _CreateGauge_LocalVars {
        address tokenA;
        address tokenB;
        address rewardToken;
        address dexFactory;
        address gaugeFactory;
        address internal_bribe;
        address external_bribe;
        bool isPair;
    }

    /// @notice create a gauge
    /// @param  _pool       LP address, which varies based on gauge type:
    ///                     - For PAIR_CLASSIC: The actual pair contract address (similar to UniswapV2 pairs)
    ///                     - For ALM strategies (GAMMA): The strategy contract address that manages the position
    /// @param  _gaugeType  enum GaugeType, the type of gauge to create. The associated factory (_factories[_gaugeType])
    ///                     represents different things based on type:
    ///                     - For PAIR_CLASSIC: Deploy a Gauge for Solidly Classic Pairs
    ///                     - For ALM_GAMMA_ALGEBRA: Deploy a Gauge for Gamma + Algebra ALM strategies
    ///                     - For ALM_GAMMA_UNISWAP_V3: Deploy a Gauge for Gamma + UniswapV3 ALM strategies
    ///                     - For ALM_GAMMA_UNISWAP_V4: Deploy a Gauge for Gamma + UniswapV4 ALM strategies
    function createGauge(
        address _pool,
        uint256 _gaugeType
    ) external override returns (address _gauge, address _internal_bribe, address _external_bribe) {
        // Enhanced validation
        require(_gaugeType <= MAX_GAUGE_TYPE, "Invalid gauge type enum");
        require(_gaugeType < _factories.length, "Gauge type not configured");
        require(gauges[_pool] == address(0), "!exists");
        require(_pool.code.length > 0, "!contract");

        _CreateGauge_LocalVars memory vars;
        vars.dexFactory = _factories[_gaugeType];
        vars.gaugeFactory = _gaugeFactories[_gaugeType];
        require(vars.dexFactory != address(0), "dex factory not set");
        require(vars.gaugeFactory != address(0), "gauge factory not set");

        (vars.tokenA) = IPairInfo(_pool).token0();
        (vars.tokenB) = IPairInfo(_pool).token1();
        if (_gaugeType == uint256(GaugeType.PAIR_CLASSIC)) {
            /**
             * @dev Classic Stable/Volatile pair
             */
            vars.isPair = IPairFactory(vars.dexFactory).isPair(_pool);
        } else if (_gaugeType == uint256(GaugeType.ALM_ALGEBRA_V1)) {
            /**
             * @dev ICHI/GAMMA + Algebra ALM strategy
             */
            address _pool_factory = IAlgebraFactory(vars.dexFactory).poolByPair(vars.tokenA, vars.tokenB);
            address _pool_hyper = IHypervisor(_pool).pool();
            require(_pool_hyper == _pool_factory, "wrong tokens");
            vars.isPair = true;
        } else if (_gaugeType == uint256(GaugeType.ALM_ICHI_UNISWAP_V3)) {
            /**
             * @dev ICHI + Uniswap V3 ALM strategy
             */
            address _pool_hyper = IHypervisor(_pool).pool();
            bool isValidPool = UniswapV3Helper.validatePoolExists(vars.dexFactory, vars.tokenA, vars.tokenB, _pool_hyper);
            require(isValidPool, "wrong tokens");
            vars.isPair = true;
        } else if (_gaugeType == uint256(GaugeType.ALM_GAMMA_UNISWAP_V4)) {
            /**
             * @dev GAMMA + Uniswap V4 ALM strategy
             */
            address _poolManager = IMultiPositionManager(_pool).poolManager();
            require(_poolManager == vars.dexFactory, "!poolManager");
            /// @dev IMultiPositionManager supports token0() and token1()
            // vars.tokenA = address(IMultiPositionManager(_pool).token0());
            // vars.tokenB = address(IMultiPositionManager(_pool).token1());
            vars.isPair = true;
        }

        /// @dev Gov can create for any pool, even non-lynex pairs
        if (!IPermissionsRegistry(permissionRegistry).hasRole("GOVERNANCE", msg.sender)) {
            require(vars.isPair, "!_pool");
            if(_gaugeType != uint256(GaugeType.PAIR_CLASSIC)) {
                /// @dev Assume this is an ALM strategy
                require(isWhitelistedPool[_pool], "Only whitelisted strategies");
            }
            if(_gaugeType == uint256(GaugeType.ALM_GAMMA_UNISWAP_V4)) {
                /// @dev UniswapV4 supports native tokens at address(0)
                if(vars.tokenA != address(0)) {
                    require(isWhitelisted[vars.tokenA], "!whitelistedA");
                }
            } else {
                require(vars.tokenA != address(0), "!pair.tokenA");
                require(isWhitelisted[vars.tokenA], "!whitelistedA");
            }
            require(isWhitelisted[vars.tokenB], "!whitelistedB");
            require(vars.tokenB != address(0), "!pair.tokenB");
        }

        /// -----------------------------------------------------------------------
        /// Setup Bribes
        /// -----------------------------------------------------------------------

        // create internal and external bribe
        address _owner = IPermissionsRegistry(permissionRegistry).teamMultisig();
        string memory _type = string.concat(protocolName, " LP Fees: ", IERC20(_pool).symbol());
        vars.internal_bribe = IBribeFactory(bribefactory).createBribe(_owner, vars.tokenA, vars.tokenB, _type);

        _type = string.concat(protocolName, " Bribes: ", IERC20(_pool).symbol());
        vars.external_bribe = IBribeFactory(bribefactory).createBribe(_owner, vars.tokenA, vars.tokenB, _type);

        /// -----------------------------------------------------------------------
        /// Setup Gauge
        /// -----------------------------------------------------------------------

        vars.rewardToken = oToken != address(0) ? oToken : base;

        _gauge = IGaugeFactory(vars.gaugeFactory).createGaugeV2(
            vars.rewardToken,
            _ve,
            _pool,
            address(this), // distribution address
            vars.internal_bribe,
            vars.external_bribe,
            vars.isPair
        );
        // approve spending for protocol token, this is set back to zero if gauge is killed
        IERC20(vars.rewardToken).approve(_gauge, type(uint256).max);

        /// -----------------------------------------------------------------------
        /// Save Gauge Data
        /// -----------------------------------------------------------------------

        internal_bribes[_gauge] = vars.internal_bribe;
        external_bribes[_gauge] = vars.external_bribe;
        gauges[_pool] = _gauge;
        poolForGauge[_gauge] = _pool;
        isGauge[_gauge] = true;
        isAlive[_gauge] = true;
        pools.push(_pool);

        // update supplyIndex (gaugeRewardsPerVoteWeight) gauge => index (globalRewardsPerVoteWeight)
        supplyIndex[_gauge] = index; // new gauges are set to the default global state

        return (_gauge, vars.internal_bribe, vars.external_bribe);
    }
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

/**
 * @title The interface for the Algebra Factory
 * @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
 * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
 */
interface IAlgebraFactory {
  /**
   *  @notice Emitted when the owner of the factory is changed
   *  @param newOwner The owner after the owner was changed
   */
  event Owner(address indexed newOwner);

  /**
   *  @notice Emitted when the vault address is changed
   *  @param newVaultAddress The vault address after the address was changed
   */
  event VaultAddress(address indexed newVaultAddress);

  /**
   *  @notice Emitted when a pool is created
   *  @param token0 The first token of the pool by address sort order
   *  @param token1 The second token of the pool by address sort order
   *  @param pool The address of the created pool
   */
  event Pool(address indexed token0, address indexed token1, address pool);

  /**
   *  @notice Emitted when the farming address is changed
   *  @param newFarmingAddress The farming address after the address was changed
   */
  event FarmingAddress(address indexed newFarmingAddress);

  event FeeConfiguration(
    uint16 alpha1,
    uint16 alpha2,
    uint32 beta1,
    uint32 beta2,
    uint16 gamma1,
    uint16 gamma2,
    uint32 volumeBeta,
    uint16 volumeGamma,
    uint16 baseFee
  );

  /**
   *  @notice Returns the current owner of the factory
   *  @dev Can be changed by the current owner via setOwner
   *  @return The address of the factory owner
   */
  function owner() external view returns (address);

  /**
   *  @notice Returns the current poolDeployerAddress
   *  @return The address of the poolDeployer
   */
  function poolDeployer() external view returns (address);

  /**
   * @dev Is retrieved from the pools to restrict calling
   * certain functions not by a tokenomics contract
   * @return The tokenomics contract address
   */
  function farmingAddress() external view returns (address);

  function vaultAddress() external view returns (address);

  /**
   *  @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
   *  @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
   *  @param tokenA The contract address of either token0 or token1
   *  @param tokenB The contract address of the other token
   *  @return pool The pool address
   */
  function poolByPair(address tokenA, address tokenB) external view returns (address pool);

  /**
   *  @notice Creates a pool for the given two tokens and fee
   *  @param tokenA One of the two tokens in the desired pool
   *  @param tokenB The other of the two tokens in the desired pool
   *  @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved
   *  from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments
   *  are invalid.
   *  @return pool The address of the newly created pool
   */
  function createPool(address tokenA, address tokenB) external returns (address pool);

  /**
   *  @notice Updates the owner of the factory
   *  @dev Must be called by the current owner
   *  @param _owner The new owner of the factory
   */
  function setOwner(address _owner) external;

  /**
   * @dev updates tokenomics address on the factory
   * @param _farmingAddress The new tokenomics contract address
   */
  function setFarmingAddress(address _farmingAddress) external;

  /**
   * @dev updates vault address on the factory
   * @param _vaultAddress The new vault contract address
   */
  function setVaultAddress(address _vaultAddress) external;

  /**
   * @notice Changes initial fee configuration for new pools
   * @dev changes coefficients for sigmoids: α / (1 + e^( (β-x) / γ))
   * alpha1 + alpha2 + baseFee (max possible fee) must be <= type(uint16).max
   * gammas must be > 0
   * @param alpha1 max value of the first sigmoid
   * @param alpha2 max value of the second sigmoid
   * @param beta1 shift along the x-axis for the first sigmoid
   * @param beta2 shift along the x-axis for the second sigmoid
   * @param gamma1 horizontal stretch factor for the first sigmoid
   * @param gamma2 horizontal stretch factor for the second sigmoid
   * @param volumeBeta shift along the x-axis for the outer volume-sigmoid
   * @param volumeGamma horizontal stretch factor the outer volume-sigmoid
   * @param baseFee minimum possible fee
   */
  function setBaseFeeConfiguration(
    uint16 alpha1,
    uint16 alpha2,
    uint32 beta1,
    uint32 beta2,
    uint16 gamma1,
    uint16 gamma2,
    uint32 volumeBeta,
    uint16 volumeGamma,
    uint16 baseFee
  ) external;
}

File 3 of 22 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @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);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

/// @title The interface for the Uniswap V3 Factory
/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees
interface IUniswapV3Factory {
    /// @notice Emitted when the owner of the factory is changed
    /// @param oldOwner The owner before the owner was changed
    /// @param newOwner The owner after the owner was changed
    event OwnerChanged(address indexed oldOwner, address indexed newOwner);

    /// @notice Emitted when a pool is created
    /// @param token0 The first token of the pool by address sort order
    /// @param token1 The second token of the pool by address sort order
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
    /// @param tickSpacing The minimum number of ticks between initialized ticks
    /// @param pool The address of the created pool
    event PoolCreated(
        address indexed token0,
        address indexed token1,
        uint24 indexed fee,
        int24 tickSpacing,
        address pool
    );

    /// @notice Emitted when a new fee amount is enabled for pool creation via the factory
    /// @param fee The enabled fee, denominated in hundredths of a bip
    /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee
    event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);

    /// @notice Returns the current owner of the factory
    /// @dev Can be changed by the current owner via setOwner
    /// @return The address of the factory owner
    function owner() external view returns (address);

    /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled
    /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context
    /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee
    /// @return The tick spacing
    function feeAmountTickSpacing(uint24 fee) external view returns (int24);

    /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
    /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
    /// @param tokenA The contract address of either token0 or token1
    /// @param tokenB The contract address of the other token
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
    /// @return pool The pool address
    function getPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external view returns (address pool);

    /// @notice Creates a pool for the given two tokens and fee
    /// @param tokenA One of the two tokens in the desired pool
    /// @param tokenB The other of the two tokens in the desired pool
    /// @param fee The desired fee for the pool
    /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved
    /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments
    /// are invalid.
    /// @return pool The address of the newly created pool
    function createPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external returns (address pool);

    /// @notice Updates the owner of the factory
    /// @dev Must be called by the current owner
    /// @param _owner The new owner of the factory
    function setOwner(address _owner) external;

    /// @notice Enables a fee amount with the given tickSpacing
    /// @dev Fee amounts may never be removed once enabled
    /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)
    /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount
    function enableFeeAmount(uint24 fee, int24 tickSpacing) external;
}

/// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

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

// import {IImmutableState} from "@uniswap/v4-periphery/src/interfaces/IImmutableState.sol";
interface IImmutableState {
    /// @notice The Uniswap v4 PoolManager contract
    function poolManager() external view returns (address /*IPoolManager*/);
}

/**
 * @title IMultiPositionManager
 * @author Gamma
 * @notice This interface is used to interact with Gamma ALM strategies which use UniswapV4 pools as concentrated liquidity positions.
 */
interface IMultiPositionManager is IERC20, IImmutableState {
  struct Position {
    PoolKey poolKey;
    int24 lowerTick;
    int24 upperTick;
  }

  struct PositionData {
    uint128 liquidity;
    uint256 amount0;
    uint256 amount1;
  }
  function getPositions() external view returns (
      Position[] memory,
      PositionData[] memory
  );
  function basePositionsLength() external view returns (uint256);
  function token0() external view returns (IERC20);
  function token1() external view returns (IERC20);
  function getTotalAmounts() external view returns (
    uint256 total0,
    uint256 total1,
    uint256 totalFee0,
    uint256 totalFee1
  );
  function currentTicks() external view returns (int24[] memory);
  function rebalance(
    Position[] memory baseRanges,
    uint128[] memory liquidities,
    int24 limitWidth,
    uint256[2][] memory inMin,
    uint256[2][] memory outMin,
    int24 aimTick,
    uint24 tickOffset
  ) external;
  function compound(
    uint128[] memory liquidities,
    uint256[2][] memory inMin,
    int24 aimTick,
    uint24 tickOffset
  ) external;
  function claimFee() external;
  function setWhitelist(address _whitelist) external;
  function setFeeRecipient(address _feeRecipient) external;
  function setFee(uint16 fee) external;
  // function setTickOffset(uint24 offset) external;
  function deposit(
    uint256 deposit0Desired,
    uint256 deposit1Desired,
    address to,
    address from
  ) external payable returns (uint256, uint256, uint256);
  function zeroBurnAll() external;
  
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {PoolKey} from "./PoolKey.sol";

type PoolId is bytes32;

/// @notice Library for computing the ID of a pool
library PoolIdLibrary {
    /// @notice Returns value equal to keccak256(abi.encode(poolKey))
    function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) {
        assembly ("memory-safe") {
            // 0xa0 represents the total size of the poolKey struct (5 slots of 32 bytes)
            poolId := keccak256(poolKey, 0xa0)
        }
    }
}

File 10 of 22 : PoolKey.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {PoolIdLibrary} from "./PoolIdLibrary.sol";
// import {Currency} from "./Currency.sol";
// import {IHooks} from "../interfaces/IHooks.sol";

using PoolIdLibrary for PoolKey global;

/// @notice Returns the key for identifying a pool
struct PoolKey {
    /// @notice The lower currency of the pool, sorted numerically
    address currency0; // NOTE: Should be Currency
    /// @notice The higher currency of the pool, sorted numerically
    address currency1; // NOTE: Should be Currency
    /// @notice The pool LP fee, capped at 1_000_000. If the highest bit is 1, the pool has a dynamic fee and must be exactly equal to 0x800000
    uint24 fee;
    /// @notice Ticks that involve positions must be a multiple of tick spacing
    int24 tickSpacing;
    /// @notice The hooks of the pool
    address hooks; // NOTE: Should be IHooks
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IBribeFactory {
    function createInternalBribe(address[] memory) external returns (address);
    function createExternalBribe(address[] memory) external returns (address);
    function createBribe(address _owner,address _token0,address _token1, string memory _type) external returns (address);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function transfer(address recipient, uint amount) external returns (bool);
    function decimals() external view returns (uint8);
    function symbol() external view returns (string memory);
    function balanceOf(address) external view returns (uint);
    function transferFrom(address sender, address recipient, uint amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint);
    function approve(address spender, uint value) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IGaugeFactory {
    function createGauge(address, address, address, address, bool, address[] memory) external returns (address);
    function createGaugeV2(address _rewardToken,address _ve,address _token,address _distribution, address _internal_bribe, address _external_bribe, bool _isPair) external returns (address) ;
}

File 14 of 22 : IHypervisor.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IHypervisor {
    function pool() external view returns(address);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IPairFactory {
    function allPairsLength() external view returns (uint);
    function isPair(address pair) external view returns (bool);
    function getFee(bool) external view returns (uint);
    function allPairs(uint index) external view returns (address);
    function feeManager() external view returns (address);
    function pairCodeHash() external pure returns (bytes32);
    function getPair(address tokenA, address token, bool stable) external view returns (address);
    function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);
    function getInitializable() external view returns (address, address, bool);

    function MAX_REFERRAL_FEE() external view returns(uint);
    function dibs() external view returns(address);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IPairInfo {

    function token0() external view returns(address);
    function reserve0() external view returns(uint);
    function decimals0() external view returns(uint);
    function token1() external view returns(address);
    function reserve1() external view returns(uint);
    function decimals1() external view returns(uint);
    function isPair(address _pair) external view returns(bool);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

interface IPermissionsRegistry {
    function adminMultisig() external view returns (address);

    function teamMultisig() external view returns (address);

    function emergencyCouncil() external view returns (address);

    /// @notice Check if an address has a bytes role
    function hasRole(bytes memory role, address caller) external view returns (bool);

    /// @notice Check if an address has a role
    function hasRoleString(string memory role, address _user) external view returns(bool);

    /// @notice Read roles and return array of role strings
    function rolesToString() external view returns(string[] memory __roles);

    /// @notice Read roles return an array of roles in bytes
    function roles() external view returns(bytes[] memory);

    /// @notice Read the number of roles
    function rolesLength() external view returns(uint);

    /// @notice Return addresses for a given role
    function roleToAddresses(string memory role) external view returns(address[] memory _addresses);

    /// @notice Return roles for a given address
    function addressToRole(address _user) external view returns(string[] memory);
}

File 18 of 22 : IVersionable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IVersionable {
    function VERSION() external view returns (string memory);
}

File 19 of 22 : UniswapV3Helper.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {IUniswapV3Factory} from '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';

/// @title UniswapV3Helper
/// @notice Helper library for UniswapV3 pool validation and fee tier management
/// @dev Used to abstract UniswapV3-specific logic from gauge creation
library UniswapV3Helper {
    /// @notice Standard UniswapV3 fee tiers (in basis points)
    uint24 public constant FEE_LOW = 500; // 0.05%
    uint24 public constant FEE_MEDIUM = 3000; // 0.30%
    uint24 public constant FEE_HIGH = 10000; // 1.00%

    /// @notice Validates that a pool exists in UniswapV3 factory for given tokens
    /// @param _factory The UniswapV3Factory address
    /// @param _tokenA Token A address
    /// @param _tokenB Token B address
    /// @param _expectedPool The expected pool address to validate
    /// @return isValid True if the pool exists in the factory for any standard fee tier
    function validatePoolExists(
        address _factory,
        address _tokenA,
        address _tokenB,
        address _expectedPool
    ) internal view returns (bool isValid) {
        // Check if the pool matches any of the standard fee tiers
        uint24[3] memory fees = [FEE_LOW, FEE_MEDIUM, FEE_HIGH];

        for (uint256 i = 0; i < fees.length; i++) {
            address factoryPool = IUniswapV3Factory(_factory).getPool(_tokenA, _tokenB, fees[i]);
            if (_expectedPool == factoryPool && factoryPool != address(0)) {
                return true;
            }
        }

        return false;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";

/// @title IVoterV5_GaugeLogic
interface IVoterV5_GaugeLogic is IERC165 {
    function createGauge(
        address _pool,
        uint256 _gaugeType
    ) external returns (address _gauge, address _internal_bribe, address _external_bribe);

    function isValidGaugeType(uint256 _gaugeType) external pure returns (bool);
    
    function MAX_GAUGE_TYPE() external pure returns (uint256);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {IVoterV5_GaugeLogic} from "./IVoterV5_GaugeLogic.sol";

/// @title IVoterV5_Storage
/// @notice Interface for accessing public and external variables of the VoterV5_Storage contract
interface IVoterV5_Storage {
    /// @notice Returns the address of the ve token
    function _ve() external view returns (address);

    /// @notice Returns the address of the base token
    function base() external view returns (address);

    /// @notice Returns the address of the option token
    function oToken() external view returns (address);

    /// @notice Returns the address of the bribe factory
    function bribefactory() external view returns (address);

    /// @notice Returns the address of the minter
    function minter() external view returns (address);

    /// @notice Returns the address of the permission registry
    function permissionRegistry() external view returns (address);

    /// @notice Returns the address of a pool at a given index
    /// @param index The index of the pool in the pools array
    function pools(uint256 index) external view returns (address);

    /// @notice Returns the global gauge index
    function index() external view returns (uint256);

    /// @notice Returns the delay between votes in seconds
    function VOTE_DELAY() external view returns (uint256);

    /// @notice Returns the maximum vote delay allowed
    function MAX_VOTE_DELAY() external view returns (uint256);

    /// @notice Returns the claimable amount for a given account
    /// @param account The address of the account
    function claimable(address account) external view returns (uint256);

    /// @notice Returns the gauge address for a given pool
    /// @param pool The address of the pool
    function gauges(address pool) external view returns (address);

    /// @notice Returns the last distribution timestamp for a given gauge
    /// @param gauge The address of the gauge
    function gaugesDistributionTimestamp(address gauge) external view returns (uint256);

    /// @notice Returns the pool address for a given gauge
    /// @param gauge The address of the gauge
    function poolForGauge(address gauge) external view returns (address);

    /// @notice Returns the internal bribe address for a given gauge
    /// @param gauge The address of the gauge
    function internal_bribes(address gauge) external view returns (address);

    /// @notice Returns the external bribe address for a given gauge
    /// @param gauge The address of the gauge
    function external_bribes(address gauge) external view returns (address);

    /// @notice Returns the votes for a given NFT and pool
    /// @param nft The address of the NFT
    /// @param pool The address of the pool
    function votes(address nft, address pool) external view returns (uint256);

    /// @notice Returns the pool address at a given index for a given NFT
    /// @param nft The address of the NFT
    /// @param index The index of the pool in the poolVote array
    function poolVote(address nft, uint256 index) external view returns (address);

    /// @notice Returns the timestamp of the last vote for a given NFT
    /// @param nft The address of the NFT
    function lastVoted(address nft) external view returns (uint256);

    /// @notice Returns whether a given address is a gauge
    /// @param gauge The address of the gauge
    function isGauge(address gauge) external view returns (bool);

    /// @notice Returns whether a given token is whitelisted
    /// @param token The address of the token
    function isWhitelisted(address token) external view returns (bool);

    /// @notice Returns whether a given pool is whitelisted
    /// @param token The address of the pool token
    function isWhitelistedPool(address token) external view returns (bool);

    /// @notice Returns whether a given gauge is alive
    /// @param gauge The address of the gauge
    function isAlive(address gauge) external view returns (bool);

    /// @notice Returns the factory status of a given address
    /// @param factory The address of the factory
    function isFactory(address factory) external view returns (uint8);

    /// @notice Returns whether a given address is a gauge factory
    /// @param gaugeFactory The address of the gauge factory
    /// @dev in 5.4.1, this returns a uint8 instead of a bool
    ///      This allows the same gauge factory to be used across multiple gauge types.
    ///      Storage-safe: bool and uint8 both occupy 1 byte, existing true/false values
    ///      become 1/0 counters seamlessly during upgrades.
    function isGaugeFactory(address gaugeFactory) external view returns (uint8);

    /// @notice Returns whether a given address is a gauge depositor
    /// @param gaugeFactory The address of the gauge factory
    function isGaugeDepositor(address gaugeFactory) external view returns (bool);

    /// @notice Returns the address of the gauge logic contract
    function gaugeLogic() external view returns (IVoterV5_GaugeLogic);

    /// @notice Returns the epoch timestamp when a given gauge was killed
    /// @param gauge The address of the gauge
    function gaugeKilledEpoch(address gauge) external view returns (uint256);
}

File 22 of 22 : VoterV5_Storage.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {IVoterV5_Storage} from "./IVoterV5_Storage.sol";
import {IVoterV5_GaugeLogic} from "./IVoterV5_GaugeLogic.sol";
import {IVersionable} from "../interfaces/IVersionable.sol";

/// @title VoterV5_Storage
/// @notice This contract contains the storage variables for VoterV5.
/// @dev This contract is used to ensure both VoterV5 and VoterV5_GaugeLogic have access to the same storage variables
///  in the correct slots. They MUST both extend this.
/// - The storage layout for all version 5.x contracts MUST remain compatible for upgradeability.
contract VoterV5_Storage is IVoterV5_Storage, IVersionable {
    /// @notice The current version of the contract
    /// - 5.2.0: Add "protocolName", refactor to "oToken"
    /// - 5.2.1: Change from require to revert CustomErrors
    /// - 5.3.1: Add claim helper functions in VoterV5
    /// - 5.4.0: GaugeType improvement, use setFactory to configure factories with GaugeType
    /// - 5.4.1: Change isGaugeFactory mapping from bool to uint8 for reference counting.
    ///          This allows the same gauge factory to be used across multiple gauge types.
    ///          Storage-safe: bool and uint8 both occupy 1 byte, existing true/false values
    ///          become 1/0 counters seamlessly during upgrades.
    string public constant override VERSION = "5.4.1";

    bool internal initflag;

    address public _ve; // ve token that governs these contracts
    address[] internal _factories; // Array with all the pair factories
    address public base; // underlying protocol token
    address public oToken; // option protocol token
    address[] internal _gaugeFactories; // array with all the gauge factories
    address public bribefactory; // bribe factory (internal and external)
    address public minter; // minter mints protocol tokens each epoch
    address public permissionRegistry; // registry to check accesses
    address[] public pools; // all pools viable for incentives

    uint256 public index; // (globalRewardsPerVoteWeight) gauge index
    uint256 internal DURATION; // rewards are released over 1 epoch
    uint256 public VOTE_DELAY; // delay between votes in seconds
    uint256 public MAX_VOTE_DELAY; // Max vote delay allowed

    mapping(address => uint256) internal supplyIndex; /// (gaugeRewardsPerVoteWeight) gauge    => index
    mapping(address => uint256) public claimable; /// @dev deprecated, but leaving for upgradeability
    mapping(address => address) public gauges; // pool     => gauge
    mapping(address => uint256) public gaugesDistributionTimestamp; // gauge    => last Distribution Time
    mapping(address => address) public poolForGauge; // gauge    => pool
    mapping(address => address) public internal_bribes; // gauge    => internal bribe (only fees)
    mapping(address => address) public external_bribes; // gauge    => external bribe (real bribes)
    mapping(address => mapping(address => uint256)) public votes; // nft      => pool     => votes
    mapping(address => address[]) public poolVote; // nft      => pools
    mapping(uint256 => mapping(address => uint256)) internal weightsPerEpoch; // timestamp => pool => weights
    mapping(uint256 => uint256) internal totalWeightsPerEpoch; // timestamp => total weights
    mapping(address => uint256) public lastVoted; // nft      => timestamp of last vote
    mapping(address => bool) public isGauge; // gauge    => boolean [is a gauge?]
    mapping(address => bool) public isWhitelisted; // token    => boolean [is an allowed token?]
    mapping(address => bool) public isWhitelistedPool; // token    => boolean [is an allowed token?]
    mapping(address => bool) public isAlive; // gauge    => boolean [is the gauge alive?]
    mapping(address => uint8) public isFactory; // factory  => boolean [the pair factory exists?]
    mapping(address => uint8) public isGaugeFactory; // g.factory=> usage count [how many gauge types use this factory]
    mapping(address => bool) public isGaugeDepositor; // g.factory=> boolean [the gauge factory exists?]

    IVoterV5_GaugeLogic public gaugeLogic; // gauge logic contract

    /**
     * @dev May 2024: The state variables below this have been added in VoterV5 and the gap variable reduced accordingly.
     */
    mapping(address => uint256) public gaugeKilledEpoch; // gauge => timestamp [epoch when gauge was killed]
    string public protocolName; // name of the protocol for gauge creation

    // Reserved space for future state variables
    uint256[48] private __gap;
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[],"name":"MAX_GAUGE_TYPE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VOTE_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION_GAUGE_LOGIC","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOTE_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"base","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bribefactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_gaugeType","type":"uint256"}],"name":"createGauge","outputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_internal_bribe","type":"address"},{"internalType":"address","name":"_external_bribe","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"external_bribes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaugeKilledEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gaugeLogic","outputs":[{"internalType":"contract IVoterV5_GaugeLogic","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gauges","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaugesDistributionTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"index","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"internal_bribes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAlive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isFactory","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGauge","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGaugeDepositor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGaugeFactory","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gaugeType","type":"uint256"}],"name":"isValidGaugeType","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isWhitelistedPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastVoted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permissionRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolForGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolVote","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pools","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"votes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50611ba1806100206000396000f3fe608060405234801561001057600080fd5b50600436106102115760003560e01c80638dd598fb11610125578063cad1b906116100ad578063e6da04571161007c578063e6da0457146105a3578063eae40f26146105c3578063f2312ab0146105ec578063ffa1ad741461060f578063ffe5195b1461063357600080fd5b8063cad1b9061461051e578063cead7a0814610549578063dcd9e47a1461055e578063e567e8691461059b57600080fd5b8063ae21c4cb116100f4578063ae21c4cb14610493578063ae9c9e3f146104bc578063b55a5c1c146104cf578063b9a09fd5146104e2578063c48f5af41461050b57600080fd5b80638dd598fb146104255780639a61df891461043d578063aa79979b1461045d578063ac4afa381461048057600080fd5b806338752a9d116101a8578063533d3e7111610177578063533d3e71146103ae57806355f168d5146103ce5780635604e235146103f1578063657021fb146103f95780636c4f2e381461041c57600080fd5b806338752a9d146103455780633af32abf14610358578063402914f51461037b5780635001f3b51461039b57600080fd5b80631703e5f9116101e45780631703e5f9146102c75780631a32aad6146102ea5780631c4a55a6146102fd5780632986c0e51461032e57600080fd5b806301ffc9a71461021657806306d6a1b21461023e578063075461721461027f5780630f04ba6714610292575b600080fd5b610229610224366004611753565b61063c565b60405190151581526020015b60405180910390f35b61026761024c36600461179c565b6011602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610235565b600654610267906001600160a01b031681565b6102b56102a036600461179c565b601d6020526000908152604090205460ff1681565b60405160ff9091168152602001610235565b6102296102d536600461179c565b601c6020526000908152604090205460ff1681565b600354610267906001600160a01b031681565b610321604051806040016040528060058152602001640312e312e360dc1b81525081565b6040516102359190611815565b61033760095481565b604051908152602001610235565b600554610267906001600160a01b031681565b61022961036636600461179c565b601a6020526000908152604090205460ff1681565b61033761038936600461179c565b600e6020526000908152604090205481565b600254610267906001600160a01b031681565b6103376103bc36600461179c565b60216020526000908152604090205481565b6102296103dc36600461179c565b601b6020526000908152604090205460ff1681565b610337600381565b6102b561040736600461179c565b601e6020526000908152604090205460ff1681565b610337600c5481565b6000546102679061010090046001600160a01b031681565b61033761044b36600461179c565b60186020526000908152604090205481565b61022961046b36600461179c565b60196020526000908152604090205460ff1681565b61026761048e366004611828565b610673565b6102676104a136600461179c565b6013602052600090815260409020546001600160a01b031681565b602054610267906001600160a01b031681565b600754610267906001600160a01b031681565b6102676104f036600461179c565b600f602052600090815260409020546001600160a01b031681565b610267610519366004611841565b61069d565b61033761052c36600461186d565b601460209081526000928352604080842090915290825290205481565b610229610557366004611828565b6003101590565b61057161056c366004611841565b6106d5565b604080516001600160a01b0394851681529284166020840152921691810191909152606001610235565b610321611593565b6103376105b136600461179c565b60106020526000908152604090205481565b6102676105d136600461179c565b6012602052600090815260409020546001600160a01b031681565b6102296105fa36600461179c565b601f6020526000908152604090205460ff1681565b61032160405180604001604052806005815260200164352e342e3160d81b81525081565b610337600b5481565b60006001600160e01b031982166344707c4760e01b148061066d57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6008818154811061068357600080fd5b6000918252602090912001546001600160a01b0316905081565b601560205281600052604060002081815481106106b957600080fd5b6000918252602090912001546001600160a01b03169150829050565b60008080600384111561072f5760405162461bcd60e51b815260206004820152601760248201527f496e76616c6964206761756765207479706520656e756d00000000000000000060448201526064015b60405180910390fd5b60015484106107805760405162461bcd60e51b815260206004820152601960248201527f47617567652074797065206e6f7420636f6e66696775726564000000000000006044820152606401610726565b6001600160a01b038581166000908152600f602052604090205416156107d25760405162461bcd60e51b81526020600482015260076024820152662165786973747360c81b6044820152606401610726565b6000856001600160a01b03163b116108185760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610726565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091526001858154811061086c5761086c6118a6565b6000918252602090912001546001600160a01b03166060820152600480548690811061089a5761089a6118a6565b6000918252602090912001546001600160a01b0390811660808301526060820151166108fe5760405162461bcd60e51b815260206004820152601360248201527219195e08199858dd1bdc9e481b9bdd081cd95d606a1b6044820152606401610726565b60808101516001600160a01b03166109505760405162461bcd60e51b815260206004820152601560248201527419d85d59d948199858dd1bdc9e481b9bdd081cd95d605a1b6044820152606401610726565b856001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b291906118bc565b6001600160a01b0390811682526040805163d21220a760e01b815290519188169163d21220a7916004808201926020929091908290030181865afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2291906118bc565b6001600160a01b0316602082015284610ab157606081015160405163e5e31b1360e01b81526001600160a01b0388811660048301529091169063e5e31b1390602401602060405180830381865afa158015610a81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa591906118d9565b151560e0820152610d9e565b60018503610c0d5760608101518151602083015160405163d9a641e160e01b81526000936001600160a01b03169263d9a641e192610b06926004016001600160a01b0392831681529116602082015260400190565b602060405180830381865afa158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4791906118bc565b90506000876001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad91906118bc565b9050816001600160a01b0316816001600160a01b031614610bff5760405162461bcd60e51b815260206004820152600c60248201526b77726f6e6720746f6b656e7360a01b6044820152606401610726565b5050600160e0820152610d9e565b60028503610cd3576000866001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7991906118bc565b90506000610c9583606001518460000151856020015185611621565b905080610bff5760405162461bcd60e51b815260206004820152600c60248201526b77726f6e6720746f6b656e7360a01b6044820152606401610726565b60038503610d9e576000866001600160a01b031663dc4c90d36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3f91906118bc565b905081606001516001600160a01b0316816001600160a01b031614610d955760405162461bcd60e51b815260206004820152600c60248201526b10b837b7b626b0b730b3b2b960a11b6044820152606401610726565b50600160e08201525b60075460408051634448e1eb60e01b81526004810191909152600a604482015269474f5645524e414e434560b01b60648201523360248201526001600160a01b0390911690634448e1eb90608401602060405180830381865afa158015610e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2d91906118d9565b611094578060e00151610e6b5760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610726565b8415610ed9576001600160a01b0386166000908152601b602052604090205460ff16610ed95760405162461bcd60e51b815260206004820152601b60248201527f4f6e6c792077686974656c6973746564207374726174656769657300000000006044820152606401610726565b60038503610f4f5780516001600160a01b031615610f4a5780516001600160a01b03166000908152601a602052604090205460ff16610f4a5760405162461bcd60e51b815260206004820152600d60248201526c2177686974656c69737465644160981b6044820152606401610726565b610fee565b80516001600160a01b0316610f955760405162461bcd60e51b815260206004820152600c60248201526b21706169722e746f6b656e4160a01b6044820152606401610726565b80516001600160a01b03166000908152601a602052604090205460ff16610fee5760405162461bcd60e51b815260206004820152600d60248201526c2177686974656c69737465644160981b6044820152606401610726565b6020808201516001600160a01b03166000908152601a909152604090205460ff1661104b5760405162461bcd60e51b815260206004820152600d60248201526c10bbb434ba32b634b9ba32b22160991b6044820152606401610726565b60208101516001600160a01b03166110945760405162461bcd60e51b815260206004820152600c60248201526b10b830b4b9173a37b5b2b72160a11b6044820152606401610726565b6007546040805163dbc0c08560e01b815290516000926001600160a01b03169163dbc0c0859160048083019260209291908290030181865afa1580156110de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110291906118bc565b905060006022886001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611146573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261116e9190810190611911565b60405160200161117f929190611a91565b60408051601f19818403018152908290526005548551602087015161e66b60e01b85529294506001600160a01b039091169261e66b926111c89287929091908790600401611acc565b6020604051808303816000875af11580156111e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120b91906118bc565b8360a001906001600160a01b031690816001600160a01b0316815250506022886001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611268573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112909190810190611911565b6040516020016112a1929190611b0a565b60408051601f19818403018152908290526005548551602087015161e66b60e01b85529294506001600160a01b039091169261e66b926112ea9287929091908790600401611acc565b6020604051808303816000875af1158015611309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132d91906118bc565b6001600160a01b0390811660c085015260035416611356576002546001600160a01b0316611363565b6003546001600160a01b03165b6001600160a01b039081166040808601829052608086015160005460a088015160c089015160e08a015194516307379e7760e41b81526004810196909652610100909204861660248601528d8616604486015230606486015285166084850152841660a484015290151560c483015290911690637379e7709060e4016020604051808303816000875af11580156113fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142291906118bc565b604080850151905163095ea7b360e01b81526001600160a01b038084166004830152600019602483015292985091169063095ea7b3906044016020604051808303816000875af115801561147a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149e91906118d9565b50505060a0810180516001600160a01b03868116600081815260126020908152604080832080549686166001600160a01b031997881617905560c090970180516013835288842080549187169188169190911790559b909316808252600f8452868220805486168417905591815260118352858120805485168317905560198352858120805460ff199081166001908117909255601c85528783208054909116821790556008805491820190557ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3018054909416909117909255600954600d9091529290209190915551945192959293505050565b602280546115a0906119be565b80601f01602080910402602001604051908101604052809291908181526020018280546115cc906119be565b80156116195780601f106115ee57610100808354040283529160200191611619565b820191906000526020600020905b8154815290600101906020018083116115fc57829003601f168201915b505050505081565b604080516060810182526101f48152610bb8602082015261271091810191909152600090815b6003811015611744576000876001600160a01b0316631698ee828888868660038110611675576116756118a6565b60200201516040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015262ffffff166044820152606401602060405180830381865afa1580156116d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f591906118bc565b9050806001600160a01b0316856001600160a01b031614801561172057506001600160a01b03811615155b15611731576001935050505061174b565b508061173c81611b44565b915050611647565b5060009150505b949350505050565b60006020828403121561176557600080fd5b81356001600160e01b03198116811461177d57600080fd5b9392505050565b6001600160a01b038116811461179957600080fd5b50565b6000602082840312156117ae57600080fd5b813561177d81611784565b60005b838110156117d45781810151838201526020016117bc565b838111156117e3576000848401525b50505050565b600081518084526118018160208601602086016117b9565b601f01601f19169290920160200192915050565b60208152600061177d60208301846117e9565b60006020828403121561183a57600080fd5b5035919050565b6000806040838503121561185457600080fd5b823561185f81611784565b946020939093013593505050565b6000806040838503121561188057600080fd5b823561188b81611784565b9150602083013561189b81611784565b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156118ce57600080fd5b815161177d81611784565b6000602082840312156118eb57600080fd5b8151801515811461177d57600080fd5b634e487b7160e01b600052604160045260246000fd5b60006020828403121561192357600080fd5b815167ffffffffffffffff8082111561193b57600080fd5b818401915084601f83011261194f57600080fd5b815181811115611961576119616118fb565b604051601f8201601f19908116603f01168101908382118183101715611989576119896118fb565b816040528281528760208487010111156119a257600080fd5b6119b38360208301602088016117b9565b979650505050505050565b600181811c908216806119d257607f821691505b6020821081036119f257634e487b7160e01b600052602260045260246000fd5b50919050565b8054600090600181811c9080831680611a1257607f831692505b60208084108203611a3357634e487b7160e01b600052602260045260246000fd5b818015611a475760018114611a5857611a85565b60ff19861689528489019650611a85565b60008881526020902060005b86811015611a7d5781548b820152908501908301611a64565b505084890196505b50505050505092915050565b6000611a9d82856119f8565b690102628102332b2b99d160b51b81528351611ac081600a8401602088016117b9565b01600a01949350505050565b6001600160a01b038581168252848116602083015283166040820152608060608201819052600090611b00908301846117e9565b9695505050505050565b6000611b1682856119f8565b68010213934b132b99d160bd1b81528351611b388160098401602088016117b9565b01600901949350505050565b600060018201611b6457634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220ab8f17920b2ee6132d4a63cad9af919a8e3d1734d1a82a76475b9f096792063e64736f6c634300080d0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102115760003560e01c80638dd598fb11610125578063cad1b906116100ad578063e6da04571161007c578063e6da0457146105a3578063eae40f26146105c3578063f2312ab0146105ec578063ffa1ad741461060f578063ffe5195b1461063357600080fd5b8063cad1b9061461051e578063cead7a0814610549578063dcd9e47a1461055e578063e567e8691461059b57600080fd5b8063ae21c4cb116100f4578063ae21c4cb14610493578063ae9c9e3f146104bc578063b55a5c1c146104cf578063b9a09fd5146104e2578063c48f5af41461050b57600080fd5b80638dd598fb146104255780639a61df891461043d578063aa79979b1461045d578063ac4afa381461048057600080fd5b806338752a9d116101a8578063533d3e7111610177578063533d3e71146103ae57806355f168d5146103ce5780635604e235146103f1578063657021fb146103f95780636c4f2e381461041c57600080fd5b806338752a9d146103455780633af32abf14610358578063402914f51461037b5780635001f3b51461039b57600080fd5b80631703e5f9116101e45780631703e5f9146102c75780631a32aad6146102ea5780631c4a55a6146102fd5780632986c0e51461032e57600080fd5b806301ffc9a71461021657806306d6a1b21461023e578063075461721461027f5780630f04ba6714610292575b600080fd5b610229610224366004611753565b61063c565b60405190151581526020015b60405180910390f35b61026761024c36600461179c565b6011602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610235565b600654610267906001600160a01b031681565b6102b56102a036600461179c565b601d6020526000908152604090205460ff1681565b60405160ff9091168152602001610235565b6102296102d536600461179c565b601c6020526000908152604090205460ff1681565b600354610267906001600160a01b031681565b610321604051806040016040528060058152602001640312e312e360dc1b81525081565b6040516102359190611815565b61033760095481565b604051908152602001610235565b600554610267906001600160a01b031681565b61022961036636600461179c565b601a6020526000908152604090205460ff1681565b61033761038936600461179c565b600e6020526000908152604090205481565b600254610267906001600160a01b031681565b6103376103bc36600461179c565b60216020526000908152604090205481565b6102296103dc36600461179c565b601b6020526000908152604090205460ff1681565b610337600381565b6102b561040736600461179c565b601e6020526000908152604090205460ff1681565b610337600c5481565b6000546102679061010090046001600160a01b031681565b61033761044b36600461179c565b60186020526000908152604090205481565b61022961046b36600461179c565b60196020526000908152604090205460ff1681565b61026761048e366004611828565b610673565b6102676104a136600461179c565b6013602052600090815260409020546001600160a01b031681565b602054610267906001600160a01b031681565b600754610267906001600160a01b031681565b6102676104f036600461179c565b600f602052600090815260409020546001600160a01b031681565b610267610519366004611841565b61069d565b61033761052c36600461186d565b601460209081526000928352604080842090915290825290205481565b610229610557366004611828565b6003101590565b61057161056c366004611841565b6106d5565b604080516001600160a01b0394851681529284166020840152921691810191909152606001610235565b610321611593565b6103376105b136600461179c565b60106020526000908152604090205481565b6102676105d136600461179c565b6012602052600090815260409020546001600160a01b031681565b6102296105fa36600461179c565b601f6020526000908152604090205460ff1681565b61032160405180604001604052806005815260200164352e342e3160d81b81525081565b610337600b5481565b60006001600160e01b031982166344707c4760e01b148061066d57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6008818154811061068357600080fd5b6000918252602090912001546001600160a01b0316905081565b601560205281600052604060002081815481106106b957600080fd5b6000918252602090912001546001600160a01b03169150829050565b60008080600384111561072f5760405162461bcd60e51b815260206004820152601760248201527f496e76616c6964206761756765207479706520656e756d00000000000000000060448201526064015b60405180910390fd5b60015484106107805760405162461bcd60e51b815260206004820152601960248201527f47617567652074797065206e6f7420636f6e66696775726564000000000000006044820152606401610726565b6001600160a01b038581166000908152600f602052604090205416156107d25760405162461bcd60e51b81526020600482015260076024820152662165786973747360c81b6044820152606401610726565b6000856001600160a01b03163b116108185760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610726565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091526001858154811061086c5761086c6118a6565b6000918252602090912001546001600160a01b03166060820152600480548690811061089a5761089a6118a6565b6000918252602090912001546001600160a01b0390811660808301526060820151166108fe5760405162461bcd60e51b815260206004820152601360248201527219195e08199858dd1bdc9e481b9bdd081cd95d606a1b6044820152606401610726565b60808101516001600160a01b03166109505760405162461bcd60e51b815260206004820152601560248201527419d85d59d948199858dd1bdc9e481b9bdd081cd95d605a1b6044820152606401610726565b856001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b291906118bc565b6001600160a01b0390811682526040805163d21220a760e01b815290519188169163d21220a7916004808201926020929091908290030181865afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2291906118bc565b6001600160a01b0316602082015284610ab157606081015160405163e5e31b1360e01b81526001600160a01b0388811660048301529091169063e5e31b1390602401602060405180830381865afa158015610a81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa591906118d9565b151560e0820152610d9e565b60018503610c0d5760608101518151602083015160405163d9a641e160e01b81526000936001600160a01b03169263d9a641e192610b06926004016001600160a01b0392831681529116602082015260400190565b602060405180830381865afa158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4791906118bc565b90506000876001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad91906118bc565b9050816001600160a01b0316816001600160a01b031614610bff5760405162461bcd60e51b815260206004820152600c60248201526b77726f6e6720746f6b656e7360a01b6044820152606401610726565b5050600160e0820152610d9e565b60028503610cd3576000866001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7991906118bc565b90506000610c9583606001518460000151856020015185611621565b905080610bff5760405162461bcd60e51b815260206004820152600c60248201526b77726f6e6720746f6b656e7360a01b6044820152606401610726565b60038503610d9e576000866001600160a01b031663dc4c90d36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3f91906118bc565b905081606001516001600160a01b0316816001600160a01b031614610d955760405162461bcd60e51b815260206004820152600c60248201526b10b837b7b626b0b730b3b2b960a11b6044820152606401610726565b50600160e08201525b60075460408051634448e1eb60e01b81526004810191909152600a604482015269474f5645524e414e434560b01b60648201523360248201526001600160a01b0390911690634448e1eb90608401602060405180830381865afa158015610e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2d91906118d9565b611094578060e00151610e6b5760405162461bcd60e51b81526020600482015260066024820152650857dc1bdbdb60d21b6044820152606401610726565b8415610ed9576001600160a01b0386166000908152601b602052604090205460ff16610ed95760405162461bcd60e51b815260206004820152601b60248201527f4f6e6c792077686974656c6973746564207374726174656769657300000000006044820152606401610726565b60038503610f4f5780516001600160a01b031615610f4a5780516001600160a01b03166000908152601a602052604090205460ff16610f4a5760405162461bcd60e51b815260206004820152600d60248201526c2177686974656c69737465644160981b6044820152606401610726565b610fee565b80516001600160a01b0316610f955760405162461bcd60e51b815260206004820152600c60248201526b21706169722e746f6b656e4160a01b6044820152606401610726565b80516001600160a01b03166000908152601a602052604090205460ff16610fee5760405162461bcd60e51b815260206004820152600d60248201526c2177686974656c69737465644160981b6044820152606401610726565b6020808201516001600160a01b03166000908152601a909152604090205460ff1661104b5760405162461bcd60e51b815260206004820152600d60248201526c10bbb434ba32b634b9ba32b22160991b6044820152606401610726565b60208101516001600160a01b03166110945760405162461bcd60e51b815260206004820152600c60248201526b10b830b4b9173a37b5b2b72160a11b6044820152606401610726565b6007546040805163dbc0c08560e01b815290516000926001600160a01b03169163dbc0c0859160048083019260209291908290030181865afa1580156110de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110291906118bc565b905060006022886001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611146573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261116e9190810190611911565b60405160200161117f929190611a91565b60408051601f19818403018152908290526005548551602087015161e66b60e01b85529294506001600160a01b039091169261e66b926111c89287929091908790600401611acc565b6020604051808303816000875af11580156111e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120b91906118bc565b8360a001906001600160a01b031690816001600160a01b0316815250506022886001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611268573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112909190810190611911565b6040516020016112a1929190611b0a565b60408051601f19818403018152908290526005548551602087015161e66b60e01b85529294506001600160a01b039091169261e66b926112ea9287929091908790600401611acc565b6020604051808303816000875af1158015611309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132d91906118bc565b6001600160a01b0390811660c085015260035416611356576002546001600160a01b0316611363565b6003546001600160a01b03165b6001600160a01b039081166040808601829052608086015160005460a088015160c089015160e08a015194516307379e7760e41b81526004810196909652610100909204861660248601528d8616604486015230606486015285166084850152841660a484015290151560c483015290911690637379e7709060e4016020604051808303816000875af11580156113fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142291906118bc565b604080850151905163095ea7b360e01b81526001600160a01b038084166004830152600019602483015292985091169063095ea7b3906044016020604051808303816000875af115801561147a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149e91906118d9565b50505060a0810180516001600160a01b03868116600081815260126020908152604080832080549686166001600160a01b031997881617905560c090970180516013835288842080549187169188169190911790559b909316808252600f8452868220805486168417905591815260118352858120805485168317905560198352858120805460ff199081166001908117909255601c85528783208054909116821790556008805491820190557ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3018054909416909117909255600954600d9091529290209190915551945192959293505050565b602280546115a0906119be565b80601f01602080910402602001604051908101604052809291908181526020018280546115cc906119be565b80156116195780601f106115ee57610100808354040283529160200191611619565b820191906000526020600020905b8154815290600101906020018083116115fc57829003601f168201915b505050505081565b604080516060810182526101f48152610bb8602082015261271091810191909152600090815b6003811015611744576000876001600160a01b0316631698ee828888868660038110611675576116756118a6565b60200201516040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015262ffffff166044820152606401602060405180830381865afa1580156116d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f591906118bc565b9050806001600160a01b0316856001600160a01b031614801561172057506001600160a01b03811615155b15611731576001935050505061174b565b508061173c81611b44565b915050611647565b5060009150505b949350505050565b60006020828403121561176557600080fd5b81356001600160e01b03198116811461177d57600080fd5b9392505050565b6001600160a01b038116811461179957600080fd5b50565b6000602082840312156117ae57600080fd5b813561177d81611784565b60005b838110156117d45781810151838201526020016117bc565b838111156117e3576000848401525b50505050565b600081518084526118018160208601602086016117b9565b601f01601f19169290920160200192915050565b60208152600061177d60208301846117e9565b60006020828403121561183a57600080fd5b5035919050565b6000806040838503121561185457600080fd5b823561185f81611784565b946020939093013593505050565b6000806040838503121561188057600080fd5b823561188b81611784565b9150602083013561189b81611784565b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156118ce57600080fd5b815161177d81611784565b6000602082840312156118eb57600080fd5b8151801515811461177d57600080fd5b634e487b7160e01b600052604160045260246000fd5b60006020828403121561192357600080fd5b815167ffffffffffffffff8082111561193b57600080fd5b818401915084601f83011261194f57600080fd5b815181811115611961576119616118fb565b604051601f8201601f19908116603f01168101908382118183101715611989576119896118fb565b816040528281528760208487010111156119a257600080fd5b6119b38360208301602088016117b9565b979650505050505050565b600181811c908216806119d257607f821691505b6020821081036119f257634e487b7160e01b600052602260045260246000fd5b50919050565b8054600090600181811c9080831680611a1257607f831692505b60208084108203611a3357634e487b7160e01b600052602260045260246000fd5b818015611a475760018114611a5857611a85565b60ff19861689528489019650611a85565b60008881526020902060005b86811015611a7d5781548b820152908501908301611a64565b505084890196505b50505050505092915050565b6000611a9d82856119f8565b690102628102332b2b99d160b51b81528351611ac081600a8401602088016117b9565b01600a01949350505050565b6001600160a01b038581168252848116602083015283166040820152608060608201819052600090611b00908301846117e9565b9695505050505050565b6000611b1682856119f8565b68010213934b132b99d160bd1b81528351611b388160098401602088016117b9565b01600901949350505050565b600060018201611b6457634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220ab8f17920b2ee6132d4a63cad9af919a8e3d1734d1a82a76475b9f096792063e64736f6c634300080d0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
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.