false
true
0

Contract Address Details

0xB9BB2856e0Af9d3e855b0173A40059Fc29b632dA

Contract Name
ArrakisFactoryV1
Creator
0xaa2e0c–4ee07c at 0xb2c2df–f1db89
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
26204015
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
ArrakisFactoryV1




Optimization enabled
true
Compiler version
v0.8.4+commit.c7e474f2




Optimization runs
1
EVM Version
istanbul




Verified at
2026-04-05T01:06:43.151386Z

Constructor Arguments

0000000000000000000000001f98431c8ad98523631ae4a59f267346ea31f984

Arg [0] (address) : 0x1f98431c8ad98523631ae4a59f267346ea31f984

              

contracts/ArrakisFactoryV1.sol

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

import {
    IUniswapV3Factory
} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";
import {IUniswapV3TickSpacing} from "./interfaces/IUniswapV3TickSpacing.sol";
import {IArrakisFactoryV1} from "./interfaces/IArrakisFactoryV1.sol";
import {IArrakisVaultV1Storage} from "./interfaces/IArrakisVaultV1Storage.sol";
import {ArrakisFactoryV1Storage} from "./abstract/ArrakisFactoryV1Storage.sol";
import {EIP173Proxy} from "./vendor/proxy/EIP173Proxy.sol";
import {IEIP173Proxy} from "./interfaces/IEIP173Proxy.sol";
import {
    IERC20Metadata
} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {
    EnumerableSet
} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

contract ArrakisFactoryV1 is ArrakisFactoryV1Storage, IArrakisFactoryV1 {
    using EnumerableSet for EnumerableSet.AddressSet;

    constructor(address _uniswapV3Factory)
        ArrakisFactoryV1Storage(_uniswapV3Factory)
    {} // solhint-disable-line no-empty-blocks

    /// @notice deployVault creates a new instance of a Vault on a specified
    /// UniswapV3Pool. The msg.sender is the initial manager of the pool and will
    /// forever be associated with the Vault as it's `deployer`
    /// @param tokenA one of the tokens in the uniswap pair
    /// @param tokenB the other token in the uniswap pair
    /// @param uniFee fee tier of the uniswap pair
    /// @param manager address of the managing account
    /// @param managerFee proportion of earned fees that go to pool manager in Basis Points
    /// @param lowerTick initial lower bound of the Uniswap V3 position
    /// @param upperTick initial upper bound of the Uniswap V3 position
    /// @return pool the address of the newly created Vault (proxy)
    function deployVault(
        address tokenA,
        address tokenB,
        uint24 uniFee,
        address manager,
        uint16 managerFee,
        int24 lowerTick,
        int24 upperTick
    ) external override returns (address pool) {
        return
            _deployVault(
                tokenA,
                tokenB,
                uniFee,
                manager,
                managerFee,
                lowerTick,
                upperTick
            );
    }

    function _deployVault(
        address tokenA,
        address tokenB,
        uint24 uniFee,
        address manager,
        uint16 managerFee,
        int24 lowerTick,
        int24 upperTick
    ) internal returns (address pool) {
        address uniPool;
        string memory name;
        (pool, uniPool, name) = _preDeploy(
            tokenA,
            tokenB,
            uniFee,
            lowerTick,
            upperTick
        );

        IArrakisVaultV1Storage(pool).initialize(
            name,
            string(abi.encodePacked("RAKIS-", _uint2str(index + 1))),
            uniPool,
            managerFee,
            lowerTick,
            upperTick,
            manager
        );
        _deployers.add(manager);
        _pools[manager].add(pool);
        index += 1;
        emit PoolCreated(uniPool, manager, pool);
    }

    function _preDeploy(
        address tokenA,
        address tokenB,
        uint24 uniFee,
        int24 lowerTick,
        int24 upperTick
    )
        internal
        returns (
            address pool,
            address uniPool,
            string memory name
        )
    {
        (address token0, address token1) = _getTokenOrder(tokenA, tokenB);

        pool = address(new EIP173Proxy(poolImplementation, address(this), ""));

        name = "Arrakis Vault V1";
        try this.getTokenName(token0, token1) returns (string memory result) {
            name = result;
        } catch {} // solhint-disable-line no-empty-blocks

        uniPool = IUniswapV3Factory(factory).getPool(token0, token1, uniFee);
        require(uniPool != address(0), "uniswap pool does not exist");
        require(
            _validateTickSpacing(uniPool, lowerTick, upperTick),
            "tickSpacing mismatch"
        );
    }

    function _validateTickSpacing(
        address uniPool,
        int24 lowerTick,
        int24 upperTick
    ) internal view returns (bool) {
        int24 spacing = IUniswapV3TickSpacing(uniPool).tickSpacing();
        return
            lowerTick < upperTick &&
            lowerTick % spacing == 0 &&
            upperTick % spacing == 0;
    }

    function getTokenName(address token0, address token1)
        external
        view
        returns (string memory)
    {
        string memory symbol0 = IERC20Metadata(token0).symbol();
        string memory symbol1 = IERC20Metadata(token1).symbol();

        return _append("Arrakis Vault V1 ", symbol0, "/", symbol1);
    }

    function upgradePools(address[] memory pools) external onlyManager {
        for (uint256 i = 0; i < pools.length; i++) {
            IEIP173Proxy(pools[i]).upgradeTo(poolImplementation);
        }
    }

    function upgradePoolsAndCall(address[] memory pools, bytes[] calldata datas)
        external
        onlyManager
    {
        require(pools.length == datas.length, "mismatching array length");
        for (uint256 i = 0; i < pools.length; i++) {
            IEIP173Proxy(pools[i]).upgradeToAndCall(
                poolImplementation,
                datas[i]
            );
        }
    }

    function makePoolsImmutable(address[] memory pools) external onlyManager {
        for (uint256 i = 0; i < pools.length; i++) {
            IEIP173Proxy(pools[i]).transferProxyAdmin(address(0));
        }
    }

    /// @notice isPoolImmutable checks if a certain Vault is "immutable" i.e. that the
    /// proxyAdmin is the zero address and thus the underlying implementation cannot be upgraded
    /// @param pool address of the Vault
    /// @return bool signaling if pool is immutable (true) or not (false)
    function isPoolImmutable(address pool) external view returns (bool) {
        return address(0) == getProxyAdmin(pool);
    }

    /// @notice getGelatoPools gets all the Harvesters deployed by Gelato's
    /// default deployer address (since anyone can deploy and manage Harvesters)
    /// @return list of Gelato managed Vault addresses
    function getGelatoPools() external view returns (address[] memory) {
        return getPools(gelatoDeployer);
    }

    /// @notice getDeployers fetches all addresses that have deployed a Vault
    /// @return deployers the list of deployer addresses
    function getDeployers() public view returns (address[] memory) {
        uint256 length = numDeployers();
        address[] memory deployers = new address[](length);
        for (uint256 i = 0; i < length; i++) {
            deployers[i] = _getDeployer(i);
        }

        return deployers;
    }

    /// @notice getPools fetches all the Vault addresses deployed by `deployer`
    /// @param deployer address that has potentially deployed Harvesters (can return empty array)
    /// @return pools the list of Vault addresses deployed by `deployer`
    function getPools(address deployer) public view returns (address[] memory) {
        uint256 length = numPools(deployer);
        address[] memory pools = new address[](length);
        for (uint256 i = 0; i < length; i++) {
            pools[i] = _getPool(deployer, i);
        }

        return pools;
    }

    /// @notice numPools counts the total number of Harvesters in existence
    /// @return result total number of Harvesters deployed
    function numPools() public view returns (uint256 result) {
        address[] memory deployers = getDeployers();
        for (uint256 i = 0; i < deployers.length; i++) {
            result += numPools(deployers[i]);
        }
    }

    /// @notice numDeployers counts the total number of Vault deployer addresses
    /// @return total number of Vault deployer addresses
    function numDeployers() public view returns (uint256) {
        return _deployers.length();
    }

    /// @notice numPools counts the total number of Harvesters deployed by `deployer`
    /// @param deployer deployer address
    /// @return total number of Harvesters deployed by `deployer`
    function numPools(address deployer) public view returns (uint256) {
        return _pools[deployer].length();
    }

    /// @notice getProxyAdmin gets the current address who controls the underlying implementation
    /// of a Vault. For most all pools either this contract address or the zero address will
    /// be the proxyAdmin. If the admin is the zero address the pool's implementation is naturally
    /// no longer upgradable (no one owns the zero address).
    /// @param pool address of the Vault
    /// @return address that controls the Vault implementation (has power to upgrade it)
    function getProxyAdmin(address pool) public view returns (address) {
        return IEIP173Proxy(pool).proxyAdmin();
    }

    function _getDeployer(uint256 index) internal view returns (address) {
        return _deployers.at(index);
    }

    function _getPool(address deployer, uint256 index)
        internal
        view
        returns (address)
    {
        return _pools[deployer].at(index);
    }

    function _getTokenOrder(address tokenA, address tokenB)
        internal
        pure
        returns (address token0, address token1)
    {
        require(tokenA != tokenB, "same token");
        (token0, token1) = tokenA < tokenB
            ? (tokenA, tokenB)
            : (tokenB, tokenA);
        require(token0 != address(0), "no address zero");
    }

    function _append(
        string memory a,
        string memory b,
        string memory c,
        string memory d
    ) internal pure returns (string memory) {
        return string(abi.encodePacked(a, b, c, d));
    }

    function _uint2str(uint256 _i)
        internal
        pure
        returns (string memory _uintAsString)
    {
        if (_i == 0) {
            return "0";
        }
        uint256 j = _i;
        uint256 len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint256 k = len;
        while (_i != 0) {
            k = k - 1;
            uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
            bytes1 b1 = bytes1(temp);
            bstr[k] = b1;
            _i /= 10;
        }
        return string(bstr);
    }
}
        

/extensions/IERC20Metadata.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}
          

/Initializable.sol

// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity ^0.8.0;

/**
 * @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 a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

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

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

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

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}
          

/IUniswapV3Factory.sol

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

/EnumerableSet.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}
          

/IArrakisVaultV1Storage.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.4;

interface IArrakisVaultV1Storage {
    function initialize(
        string memory _name,
        string memory _symbol,
        address _pool,
        uint16 _managerFeeBPS,
        int24 _lowerTick,
        int24 _upperTick,
        address _manager_
    ) external;
}
          

/IUniswapV3TickSpacing.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.4;

interface IUniswapV3TickSpacing {
    function tickSpacing() external view returns (int24);
}
          

/ArrakisFactoryV1Storage.sol

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

import {OwnableUninitialized} from "./OwnableUninitialized.sol";
import {
    Initializable
} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {
    EnumerableSet
} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

// solhint-disable-next-line max-states-count
contract ArrakisFactoryV1Storage is
    OwnableUninitialized, /* XXXX DONT MODIFY ORDERING XXXX */
    Initializable
    // APPEND ADDITIONAL BASE WITH STATE VARS BELOW:
    // XXXX DONT MODIFY ORDERING XXXX
{
    // XXXXXXXX DO NOT MODIFY ORDERING XXXXXXXX
    // solhint-disable-next-line const-name-snakecase
    string public constant version = "1.0.0";
    address public immutable factory;
    address public poolImplementation;
    address public gelatoDeployer;
    EnumerableSet.AddressSet internal _deployers;
    mapping(address => EnumerableSet.AddressSet) internal _pools;
    // APPPEND ADDITIONAL STATE VARS BELOW:
    uint256 public index;
    // XXXXXXXX DO NOT MODIFY ORDERING XXXXXXXX

    event UpdatePoolImplementation(
        address previousImplementation,
        address newImplementation
    );

    constructor(address _uniswapV3Factory) {
        factory = _uniswapV3Factory;
    }

    function initialize(address _implementation, address _manager_)
        external
        initializer
    {
        poolImplementation = _implementation;
        _manager = _manager_;
    }

    function setPoolImplementation(address nextImplementation)
        external
        onlyManager
    {
        emit UpdatePoolImplementation(poolImplementation, nextImplementation);
        poolImplementation = nextImplementation;
    }
}
          

/IERC20.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

/OwnableUninitialized.sol

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.4;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an manager) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the manager 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
 * `onlyManager`, which can be applied to your functions to restrict their use to
 * the manager.
 */
/// @dev DO NOT ADD STATE VARIABLES - APPEND THEM TO GelatoUniV3PoolStorage
/// @dev DO NOT ADD BASE CONTRACTS WITH STATE VARS - APPEND THEM TO GelatoUniV3PoolStorage
abstract contract OwnableUninitialized {
    address internal _manager;

    event OwnershipTransferred(
        address indexed previousManager,
        address indexed newManager
    );

    /// @dev Initializes the contract setting the deployer as the initial manager.
    /// CONSTRUCTOR EMPTY - USE INITIALIZIABLE INSTEAD
    // solhint-disable-next-line no-empty-blocks
    constructor() {}

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

    /**
     * @dev Throws if called by any account other than the manager.
     */
    modifier onlyManager() {
        require(manager() == msg.sender, "Ownable: caller is not the manager");
        _;
    }

    /**
     * @dev Leaves the contract without manager. It will not be possible to call
     * `onlyManager` functions anymore. Can only be called by the current manager.
     *
     * NOTE: Renouncing ownership will leave the contract without an manager,
     * thereby removing any functionality that is only available to the manager.
     */
    function renounceOwnership() public virtual onlyManager {
        emit OwnershipTransferred(_manager, address(0));
        _manager = address(0);
    }

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

/IArrakisFactoryV1.sol

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

interface IArrakisFactoryV1 {
    event PoolCreated(
        address indexed uniPool,
        address indexed manager,
        address indexed pool
    );

    function deployVault(
        address tokenA,
        address tokenB,
        uint24 uniFee,
        address manager,
        uint16 managerFee,
        int24 lowerTick,
        int24 upperTick
    ) external returns (address pool);
}
          

/EIP173Proxy.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.4;

import "./Proxy.sol";

interface ERC165 {
    function supportsInterface(bytes4 id) external view returns (bool);
}

///@notice Proxy implementing EIP173 for ownership management
contract EIP173Proxy is Proxy {
    // ////////////////////////// EVENTS ///////////////////////////////////////////////////////////////////////

    event ProxyAdminTransferred(
        address indexed previousAdmin,
        address indexed newAdmin
    );

    // /////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////////////

    constructor(
        address implementationAddress,
        address adminAddress,
        bytes memory data
    ) payable {
        _setImplementation(implementationAddress, data);
        _setProxyAdmin(adminAddress);
    }

    // ///////////////////// EXTERNAL ///////////////////////////////////////////////////////////////////////////

    function proxyAdmin() external view returns (address) {
        return _proxyAdmin();
    }

    function supportsInterface(bytes4 id) external view returns (bool) {
        if (id == 0x01ffc9a7 || id == 0x7f5828d0) {
            return true;
        }
        if (id == 0xFFFFFFFF) {
            return false;
        }

        ERC165 implementation;
        // solhint-disable-next-line security/no-inline-assembly
        assembly {
            implementation := sload(
                0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
            )
        }

        // Technically this is not standard compliant as ERC-165 require 30,000 gas which that call cannot ensure
        // because it is itself inside `supportsInterface` that might only get 30,000 gas.
        // In practise this is unlikely to be an issue.
        try implementation.supportsInterface(id) returns (bool support) {
            return support;
        } catch {
            return false;
        }
    }

    function transferProxyAdmin(address newAdmin) external onlyProxyAdmin {
        _setProxyAdmin(newAdmin);
    }

    function upgradeTo(address newImplementation) external onlyProxyAdmin {
        _setImplementation(newImplementation, "");
    }

    function upgradeToAndCall(address newImplementation, bytes calldata data)
        external
        payable
        onlyProxyAdmin
    {
        _setImplementation(newImplementation, data);
    }

    // /////////////////////// MODIFIERS ////////////////////////////////////////////////////////////////////////

    modifier onlyProxyAdmin() {
        require(msg.sender == _proxyAdmin(), "NOT_AUTHORIZED");
        _;
    }

    // ///////////////////////// INTERNAL //////////////////////////////////////////////////////////////////////

    function _proxyAdmin() internal view returns (address adminAddress) {
        // solhint-disable-next-line security/no-inline-assembly
        assembly {
            adminAddress := sload(
                0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
            )
        }
    }

    function _setProxyAdmin(address newAdmin) internal {
        address previousAdmin = _proxyAdmin();
        // solhint-disable-next-line security/no-inline-assembly
        assembly {
            sstore(
                0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103,
                newAdmin
            )
        }
        emit ProxyAdminTransferred(previousAdmin, newAdmin);
    }
}
          

/IEIP173Proxy.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.4;

interface IEIP173Proxy {
    function proxyAdmin() external view returns (address);

    function transferProxyAdmin(address newAdmin) external;

    function upgradeTo(address newImplementation) external;

    function upgradeToAndCall(address newImplementation, bytes calldata data)
        external
        payable;
}
          

/Proxy.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.4;

// EIP-1967
abstract contract Proxy {
    // /////////////////////// EVENTS ///////////////////////////////////////////////////////////////////////////

    event ProxyImplementationUpdated(
        address indexed previousImplementation,
        address indexed newImplementation
    );

    // ///////////////////// EXTERNAL ///////////////////////////////////////////////////////////////////////////

    // prettier-ignore
    receive() external payable virtual {
        revert("ETHER_REJECTED"); // explicit reject by default
    }

    fallback() external payable {
        _fallback();
    }

    // ///////////////////////// INTERNAL //////////////////////////////////////////////////////////////////////

    function _fallback() internal {
        // solhint-disable-next-line security/no-inline-assembly
        assembly {
            let implementationAddress := sload(
                0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
            )
            calldatacopy(0x0, 0x0, calldatasize())
            let success := delegatecall(
                gas(),
                implementationAddress,
                0x0,
                calldatasize(),
                0,
                0
            )
            let retSz := returndatasize()
            returndatacopy(0, 0, retSz)
            switch success
                case 0 {
                    revert(0, retSz)
                }
                default {
                    return(0, retSz)
                }
        }
    }

    function _setImplementation(address newImplementation, bytes memory data)
        internal
    {
        address previousImplementation;
        // solhint-disable-next-line security/no-inline-assembly
        assembly {
            previousImplementation := sload(
                0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
            )
        }

        // solhint-disable-next-line security/no-inline-assembly
        assembly {
            sstore(
                0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,
                newImplementation
            )
        }

        emit ProxyImplementationUpdated(
            previousImplementation,
            newImplementation
        );

        if (data.length > 0) {
            (bool success, ) = newImplementation.delegatecall(data);
            if (!success) {
                assembly {
                    // This assembly ensure the revert contains the exact string data
                    let returnDataSize := returndatasize()
                    returndatacopy(0, 0, returnDataSize)
                    revert(0, returnDataSize)
                }
            }
        }
    }
}
          

Compiler Settings

{"remappings":[],"optimizer":{"runs":1,"enabled":true},"metadata":{"useLiteralContent":true,"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"istanbul","compilationTarget":{"contracts/ArrakisFactoryV1.sol":"ArrakisFactoryV1"}}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_uniswapV3Factory","internalType":"address"}]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousManager","internalType":"address","indexed":true},{"type":"address","name":"newManager","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PoolCreated","inputs":[{"type":"address","name":"uniPool","internalType":"address","indexed":true},{"type":"address","name":"manager","internalType":"address","indexed":true},{"type":"address","name":"pool","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"UpdatePoolImplementation","inputs":[{"type":"address","name":"previousImplementation","internalType":"address","indexed":false},{"type":"address","name":"newImplementation","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"pool","internalType":"address"}],"name":"deployVault","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint24","name":"uniFee","internalType":"uint24"},{"type":"address","name":"manager","internalType":"address"},{"type":"uint16","name":"managerFee","internalType":"uint16"},{"type":"int24","name":"lowerTick","internalType":"int24"},{"type":"int24","name":"upperTick","internalType":"int24"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"gelatoDeployer","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getDeployers","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getGelatoPools","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getPools","inputs":[{"type":"address","name":"deployer","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getProxyAdmin","inputs":[{"type":"address","name":"pool","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getTokenName","inputs":[{"type":"address","name":"token0","internalType":"address"},{"type":"address","name":"token1","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"index","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_implementation","internalType":"address"},{"type":"address","name":"_manager_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isPoolImmutable","inputs":[{"type":"address","name":"pool","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"makePoolsImmutable","inputs":[{"type":"address[]","name":"pools","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"manager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"numDeployers","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"result","internalType":"uint256"}],"name":"numPools","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"numPools","inputs":[{"type":"address","name":"deployer","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"poolImplementation","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPoolImplementation","inputs":[{"type":"address","name":"nextImplementation","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradePools","inputs":[{"type":"address[]","name":"pools","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradePoolsAndCall","inputs":[{"type":"address[]","name":"pools","internalType":"address[]"},{"type":"bytes[]","name":"datas","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"version","inputs":[]}]
              

Contract Creation Code

0x60a060405234801561001057600080fd5b506040516128a63803806128a683398101604081905261002f91610044565b60601b6001600160601b031916608052610072565b600060208284031215610055578081fd5b81516001600160a01b038116811461006b578182fd5b9392505050565b60805160601c61280f610097600039600081816102cb0152611177015261280f6000f3fe60806040523480156200001157600080fd5b5060043610620001365760003560e01c8063098eddb1146200013b5780630dfc574b1462000158578063260fc2b814620001715780632986c0e5146200018857806335c62bc2146200019257806340aee041146200019c57806342f5de9914620001b3578063481c6a7514620001ca578063485cc95514620001e357806354fd4d5014620001fa578063562b8103146200022e5780635c39f4671462000247578063607c12b5146200025e578063715018a6146200026857806386238765146200027257806395d807f11462000286578063bd30dfb914620002ae578063c45a015514620002c5578063cefa779914620002ed578063d6f748981462000301578063f2fde38b1462000318578063f3b7dead146200032f578063fef46b281462000346575b600080fd5b620001456200035d565b6040519081526020015b60405180910390f35b6200016f62000169366004620018a0565b62000370565b005b6200016f6200018236600462001862565b620004f9565b6200014560065481565b62000145620005df565b6200016f620001ad36600462001862565b62000656565b62000145620001c436600462001738565b62000740565b620001d462000769565b6040516200014f919062001aa8565b6200016f620001f436600462001776565b62000778565b6200021f604051806040016040528060058152602001640312e302e360dc1b81525081565b6040516200014f919062001b65565b6200023862000875565b6040516200014f919062001b16565b620002386200025836600462001738565b6200088a565b620002386200095f565b6200016f62000a31565b600254620001d4906001600160a01b031681565b6200029d6200029736600462001738565b62000a9e565b60405190151581526020016200014f565b6200021f620002bf36600462001776565b62000abb565b620001d47f000000000000000000000000000000000000000000000000000000000000000081565b600154620001d4906001600160a01b031681565b6200016f6200031236600462001738565b62000c10565b6200016f6200032936600462001738565b62000caf565b620001d46200034036600462001738565b62000d96565b620001d462000357366004620017b3565b62000e0d565b60006200036b600362000e2c565b905090565b336200037b62000769565b6001600160a01b031614620003ad5760405162461bcd60e51b8152600401620003a49062001be5565b60405180910390fd5b82518114620003fa5760405162461bcd60e51b81526020600482015260186024820152770dad2e6dac2e8c6d0d2dcce40c2e4e4c2f240d8cadccee8d60431b6044820152606401620003a4565b60005b8351811015620004f3578381815181106200042857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316634f1ef286600160009054906101000a90046001600160a01b03168585858181106200047557634e487b7160e01b600052603260045260246000fd5b905060200281019062000489919062001c27565b6040518463ffffffff1660e01b8152600401620004a99392919062001ad6565b600060405180830381600087803b158015620004c457600080fd5b505af1158015620004d9573d6000803e3d6000fd5b505050508080620004ea9062001d66565b915050620003fd565b50505050565b336200050462000769565b6001600160a01b0316146200052d5760405162461bcd60e51b8152600401620003a49062001be5565b60005b8151811015620005db578181815181106200055b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316638356ca4f60006040518263ffffffff1660e01b815260040162000591919062001aa8565b600060405180830381600087803b158015620005ac57600080fd5b505af1158015620005c1573d6000803e3d6000fd5b505050508080620005d29062001d66565b91505062000530565b5050565b600080620005ec6200095f565b905060005b815181101562000651576200062e8282815181106200062057634e487b7160e01b600052603260045260246000fd5b602002602001015162000740565b6200063a908462001ca1565b925080620006488162001d66565b915050620005f1565b505090565b336200066162000769565b6001600160a01b0316146200068a5760405162461bcd60e51b8152600401620003a49062001be5565b60005b8151811015620005db57818181518110620006b857634e487b7160e01b600052603260045260246000fd5b6020908102919091010151600154604051631b2ce7f360e11b81526001600160a01b0392831692633659cfe692620006f69291169060040162001aa8565b600060405180830381600087803b1580156200071157600080fd5b505af115801562000726573d6000803e3d6000fd5b505050508080620007379062001d66565b9150506200068d565b6001600160a01b0381166000908152600560205260408120620007639062000e2c565b92915050565b6000546001600160a01b031690565b600054600160a81b900460ff16806200079b5750600054600160a01b900460ff16155b620008005760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620003a4565b600054600160a81b900460ff161580156200082b576000805461ffff60a01b191661010160a01b1790555b600180546001600160a01b038086166001600160a01b0319928316179092556000805492851692909116919091179055801562000870576000805460ff60a81b191690555b505050565b6002546060906200036b906001600160a01b03165b60606000620008998362000740565b90506000816001600160401b03811115620008c457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620008ee578160200160208202803683370190505b50905060005b82811015620009575762000909858262000e37565b8282815181106200092a57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806200094e8162001d66565b915050620008f4565b509392505050565b606060006200096d6200035d565b90506000816001600160401b038111156200099857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620009c2578160200160208202803683370190505b50905060005b8281101562000a2a57620009dc8162000e62565b828281518110620009fd57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528062000a218162001d66565b915050620009c8565b5092915050565b3362000a3c62000769565b6001600160a01b03161462000a655760405162461bcd60e51b8152600401620003a49062001be5565b600080546040516001600160a01b0390911690600080516020620027ba833981519152908390a3600080546001600160a01b0319169055565b600062000aab8262000d96565b6001600160a01b03161592915050565b60606000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562000af957600080fd5b505afa15801562000b0e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000b3891908101906200195a565b90506000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562000b7657600080fd5b505afa15801562000b8b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000bb591908101906200195a565b905062000c0760405180604001604052806011815260200170020b93930b5b4b9902b30bab63a102b189607d1b81525083604051806040016040528060018152602001602f60f81b8152508462000e71565b95945050505050565b3362000c1b62000769565b6001600160a01b03161462000c445760405162461bcd60e51b8152600401620003a49062001be5565b6001546040517f0617fd31aa5ab95ec80eefc1eb61a2c477aa419d1d761b4e46f5f077e47852aa9162000c85916001600160a01b0390911690849062001abc565b60405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b3362000cba62000769565b6001600160a01b03161462000ce35760405162461bcd60e51b8152600401620003a49062001be5565b6001600160a01b03811662000d4c5760405162461bcd60e51b815260206004820152602860248201527f4f776e61626c653a206e6577206d616e6167657220697320746865207a65726f604482015267206164647265737360c01b6064820152608401620003a4565b600080546040516001600160a01b0380851693921691600080516020620027ba83398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b0316633e47158c6040518163ffffffff1660e01b815260040160206040518083038186803b15801562000dd257600080fd5b505afa15801562000de7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000763919062001757565b600062000e208888888888888862000ea5565b98975050505050505050565b600062000763825490565b6001600160a01b038216600090815260056020526040812062000e5b90836200100c565b9392505050565b6000620007636003836200100c565b60608484848460405160200162000e8c949392919062001a19565b6040516020818303038152906040529050949350505050565b600080606062000eb98a8a8a88886200101a565b60065492955090935091506001600160a01b0384169063e25e15e390839062000eef9062000ee990600162001ca1565b620012ac565b60405160200162000f01919062001a78565b604051602081830303815290604052858a8a8a8e6040518863ffffffff1660e01b815260040162000f39979695949392919062001b7a565b600060405180830381600087803b15801562000f5457600080fd5b505af115801562000f69573d6000803e3d6000fd5b5050505062000f838760036200140890919063ffffffff16565b506001600160a01b038716600090815260056020526040902062000fa8908462001408565b5060016006600082825462000fbe919062001ca1565b90915550506040516001600160a01b0380851691898216918516907f9c5d829b9b23efc461f9aeef91979ec04bb903feb3bee4f26d22114abfc7335b90600090a45050979650505050505050565b600062000e5b83836200141f565b60008060606000806200102e8a8a620014b6565b6001546040519294509092506001600160a01b0316903090620010519062001694565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f08015801562001094573d6000803e3d6000fd5b50604080518082018252601081526f417272616b6973205661756c7420563160801b6020820152905163bd30dfb960e01b81529196509350309063bd30dfb990620010e6908590859060040162001abc565b60006040518083038186803b158015620010ff57600080fd5b505afa9250505080156200113757506040513d6000823e601f3d908101601f191682016040526200113491908101906200195a565b60015b620011425762001145565b92505b604051630b4c774160e11b81526001600160a01b038381166004830152828116602483015262ffffff8a1660448301527f00000000000000000000000000000000000000000000000000000000000000001690631698ee829060640160206040518083038186803b158015620011ba57600080fd5b505afa158015620011cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011f5919062001757565b93506001600160a01b0384166200124d5760405162461bcd60e51b815260206004820152601b60248201527a1d5b9a5cddd85c081c1bdbdb08191bd95cc81b9bdd08195e1a5cdd602a1b6044820152606401620003a4565b6200125a84888862001585565b6200129f5760405162461bcd60e51b81526020600482015260146024820152730e8d2c6d6a6e0c2c6d2dcce40dad2e6dac2e8c6d60631b6044820152606401620003a4565b5050955095509592505050565b606081620012d15750506040805180820190915260018152600360fc1b602082015290565b8160005b8115620013015780620012e88162001d66565b9150620012f99050600a8362001ce4565b9150620012d5565b6000816001600160401b038111156200132a57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801562001355576020820181803683370190505b509050815b8515620013ff576200136e60018262001d1d565b905060006200137f600a8862001ce4565b6200138c90600a62001cfb565b62001398908862001d1d565b620013a590603062001cbc565b905060008160f81b905080848481518110620013d157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350620013f5600a8962001ce4565b975050506200135a565b50949350505050565b600062000e5b836001600160a01b03841662001642565b815460009082106200147f5760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401620003a4565b826000018281548110620014a357634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b600080826001600160a01b0316846001600160a01b031614156200150a5760405162461bcd60e51b815260206004820152600a60248201526939b0b6b2903a37b5b2b760b11b6044820152606401620003a4565b826001600160a01b0316846001600160a01b0316106200152c5782846200152f565b83835b90925090506001600160a01b0382166200157e5760405162461bcd60e51b815260206004820152600f60248201526e6e6f2061646472657373207a65726f60881b6044820152606401620003a4565b9250929050565b600080846001600160a01b031663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015620015c257600080fd5b505afa158015620015d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015fd91906200193b565b90508260020b8460020b1280156200162157506200161c818562001d84565b60020b155b801562000c07575062001635818462001d84565b60020b1595945050505050565b60008181526001830160205260408120546200168b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000763565b50600062000763565b6109a58062001e1583390190565b600082601f830112620016b3578081fd5b813560206001600160401b03821115620016d157620016d162001dd5565b8160051b620016e282820162001c6e565b838152828101908684018388018501891015620016fd578687fd5b8693505b858410156200172c578035620017178162001deb565b83526001939093019291840191840162001701565b50979650505050505050565b6000602082840312156200174a578081fd5b813562000e5b8162001deb565b60006020828403121562001769578081fd5b815162000e5b8162001deb565b6000806040838503121562001789578081fd5b8235620017968162001deb565b91506020830135620017a88162001deb565b809150509250929050565b600080600080600080600060e0888a031215620017ce578283fd5b8735620017db8162001deb565b96506020880135620017ed8162001deb565b9550604088013562ffffff8116811462001805578384fd5b94506060880135620018178162001deb565b9350608088013561ffff811681146200182e578384fd5b925060a0880135620018408162001e04565b915060c0880135620018528162001e04565b8091505092959891949750929550565b60006020828403121562001874578081fd5b81356001600160401b038111156200188a578182fd5b6200189884828501620016a2565b949350505050565b600080600060408486031215620018b5578283fd5b83356001600160401b0380821115620018cc578485fd5b620018da87838801620016a2565b94506020860135915080821115620018f0578384fd5b818601915086601f83011262001904578384fd5b81358181111562001913578485fd5b8760208260051b850101111562001928578485fd5b6020830194508093505050509250925092565b6000602082840312156200194d578081fd5b815162000e5b8162001e04565b6000602082840312156200196c578081fd5b81516001600160401b038082111562001983578283fd5b818401915084601f83011262001997578283fd5b815181811115620019ac57620019ac62001dd5565b620019c1601f8201601f191660200162001c6e565b9150808252856020828501011115620019d8578384fd5b620013ff81602084016020860162001d37565b6000815180845262001a0581602086016020860162001d37565b601f01601f19169290920160200192915050565b6000855162001a2d818460208a0162001d37565b85519083019062001a43818360208a0162001d37565b855191019062001a5881836020890162001d37565b845191019062001a6d81836020880162001d37565b019695505050505050565b6552414b49532d60d01b81526000825162001a9b81600685016020870162001d37565b9190910160060192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b6020808252825182820181905260009190848201906040850190845b8181101562001b595783516001600160a01b03168352928401929184019160010162001b32565b50909695505050505050565b60208152600062000e5b6020830184620019eb565b60e08152600062001b8f60e083018a620019eb565b828103602084015262001ba3818a620019eb565b6001600160a01b03988916604085015261ffff9790971660608401525050600293840b60808201529190920b60a0820152921660c09092019190915292915050565b60208082526022908201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206d616e616760408201526132b960f11b606082015260800190565b6000808335601e1984360301811262001c3e578283fd5b8301803591506001600160401b0382111562001c58578283fd5b6020019150368190038213156200157e57600080fd5b604051601f8201601f191681016001600160401b038111828210171562001c995762001c9962001dd5565b604052919050565b6000821982111562001cb75762001cb762001da9565b500190565b600060ff821660ff84168060ff0382111562001cdc5762001cdc62001da9565b019392505050565b60008262001cf65762001cf662001dbf565b500490565b600081600019048311821515161562001d185762001d1862001da9565b500290565b60008282101562001d325762001d3262001da9565b500390565b60005b8381101562001d5457818101518382015260200162001d3a565b83811115620004f35750506000910152565b600060001982141562001d7d5762001d7d62001da9565b5060010190565b60008260020b8062001d9a5762001d9a62001dbf565b808360020b0791505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811462001e0157600080fd5b50565b8060020b811462001e0157600080fdfe60806040526040516109a53803806109a5833981016040819052610022916101a4565b61002c838261003d565b61003582610119565b5050506102ce565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8054908390556040516001600160a01b0380851691908316907f5570d70a002632a7b0b3c9304cc89efb62d8da9eca0dbd7752c83b737906829690600090a3815115610114576000836001600160a01b0316836040516100be9190610270565b600060405180830381855af49150503d80600081146100f9576040519150601f19603f3d011682016040523d82523d6000602084013e6100fe565b606091505b5050905080610112573d806000803e806000fd5b505b505050565b60006101316000805160206109858339815191525490565b90508160008051602061098583398151915255816001600160a01b0316816001600160a01b03167fdf435d422321da6b195902d70fc417c06a32f88379c20dd8f2a8da07088cec2960405160405180910390a35050565b80516001600160a01b038116811461019f57600080fd5b919050565b6000806000606084860312156101b8578283fd5b6101c184610188565b92506101cf60208501610188565b60408501519092506001600160401b03808211156101eb578283fd5b818601915086601f8301126101fe578283fd5b815181811115610210576102106102b8565b604051601f8201601f19908116603f01168101908382118183101715610238576102386102b8565b81604052828152896020848701011115610250578586fd5b61026183602083016020880161028c565b80955050505050509250925092565b6000825161028281846020870161028c565b9190910192915050565b60005b838110156102a757818101518382015260200161028f565b838111156101125750506000910152565b634e487b7160e01b600052604160045260246000fd5b6106a8806102dd6000396000f3fe60806040526004361061004e5760003560e01c806301ffc9a71461009b5780633659cfe6146100d05780633e47158c146100f05780634f1ef2861461011d5780638356ca4f1461013057610091565b366100915760405162461bcd60e51b815260206004820152600e60248201526d115512115497d491529150d5115160921b60448201526064015b60405180910390fd5b610099610150565b005b3480156100a757600080fd5b506100bb6100b63660046105a9565b610189565b60405190151581526020015b60405180910390f35b3480156100dc57600080fd5b506100996100eb3660046104f2565b61027e565b3480156100fc57600080fd5b506101056102d2565b6040516001600160a01b0390911681526020016100c7565b61009961012b36600461050c565b6102e1565b34801561013c57600080fd5b5061009961014b3660046104f2565b61035e565b6000805160206106538339815191525460003681823780813683855af491503d8082833e82801561017f578183f35b8183fd5b50505050565b60006301ffc9a760e01b6001600160e01b0319831614806101ba57506307f5828d60e41b6001600160e01b03198316145b156101c757506001919050565b6001600160e01b031980831614156101e157506000919050565b600080516020610653833981519152546040516301ffc9a760e01b81526001600160e01b0319841660048201526001600160a01b038216906301ffc9a79060240160206040518083038186803b15801561023a57600080fd5b505afa92505050801561026a575060408051601f3d908101601f1916820190925261026791810190610589565b60015b6102775750600092915050565b9392505050565b61028661039f565b6001600160a01b0316336001600160a01b0316146102b65760405162461bcd60e51b81526004016100889061060a565b6102cf81604051806020016040528060008152506103b2565b50565b60006102dc61039f565b905090565b6102e961039f565b6001600160a01b0316336001600160a01b0316146103195760405162461bcd60e51b81526004016100889061060a565b6103598383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103b292505050565b505050565b61036661039f565b6001600160a01b0316336001600160a01b0316146103965760405162461bcd60e51b81526004016100889061060a565b6102cf81610475565b6000805160206106338339815191525490565b6000805160206106538339815191528054908390556040516001600160a01b0380851691908316907f5570d70a002632a7b0b3c9304cc89efb62d8da9eca0dbd7752c83b737906829690600090a3815115610359576000836001600160a01b03168360405161042191906105d1565b600060405180830381855af49150503d806000811461045c576040519150601f19603f3d011682016040523d82523d6000602084013e610461565b606091505b5050905080610183573d806000803e806000fd5b600061047f61039f565b90508160008051602061063383398151915255816001600160a01b0316816001600160a01b03167fdf435d422321da6b195902d70fc417c06a32f88379c20dd8f2a8da07088cec2960405160405180910390a35050565b80356001600160a01b03811681146104ed57600080fd5b919050565b600060208284031215610503578081fd5b610277826104d6565b600080600060408486031215610520578182fd5b610529846104d6565b925060208401356001600160401b0380821115610544578384fd5b818601915086601f830112610557578384fd5b813581811115610565578485fd5b876020828501011115610576578485fd5b6020830194508093505050509250925092565b60006020828403121561059a578081fd5b81518015158114610277578182fd5b6000602082840312156105ba578081fd5b81356001600160e01b031981168114610277578182fd5b60008251815b818110156105f157602081860181015185830152016105d7565b818111156105ff5782828501525b509190910192915050565b6020808252600e908201526d1393d517d055551213d49256915160921b60408201526060019056feb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220730effc08e7ae1c19f69ae08dd52de483b649ded49db9428e4ced9875431474364736f6c63430008040033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0a264697066735822122032c0226340af0379cd7d43429d1502fc96d02b3e0f888c97b7ed277717483dc364736f6c634300080400330000000000000000000000001f98431c8ad98523631ae4a59f267346ea31f984

Deployed ByteCode

0x60806040523480156200001157600080fd5b5060043610620001365760003560e01c8063098eddb1146200013b5780630dfc574b1462000158578063260fc2b814620001715780632986c0e5146200018857806335c62bc2146200019257806340aee041146200019c57806342f5de9914620001b3578063481c6a7514620001ca578063485cc95514620001e357806354fd4d5014620001fa578063562b8103146200022e5780635c39f4671462000247578063607c12b5146200025e578063715018a6146200026857806386238765146200027257806395d807f11462000286578063bd30dfb914620002ae578063c45a015514620002c5578063cefa779914620002ed578063d6f748981462000301578063f2fde38b1462000318578063f3b7dead146200032f578063fef46b281462000346575b600080fd5b620001456200035d565b6040519081526020015b60405180910390f35b6200016f62000169366004620018a0565b62000370565b005b6200016f6200018236600462001862565b620004f9565b6200014560065481565b62000145620005df565b6200016f620001ad36600462001862565b62000656565b62000145620001c436600462001738565b62000740565b620001d462000769565b6040516200014f919062001aa8565b6200016f620001f436600462001776565b62000778565b6200021f604051806040016040528060058152602001640312e302e360dc1b81525081565b6040516200014f919062001b65565b6200023862000875565b6040516200014f919062001b16565b620002386200025836600462001738565b6200088a565b620002386200095f565b6200016f62000a31565b600254620001d4906001600160a01b031681565b6200029d6200029736600462001738565b62000a9e565b60405190151581526020016200014f565b6200021f620002bf36600462001776565b62000abb565b620001d47f0000000000000000000000001f98431c8ad98523631ae4a59f267346ea31f98481565b600154620001d4906001600160a01b031681565b6200016f6200031236600462001738565b62000c10565b6200016f6200032936600462001738565b62000caf565b620001d46200034036600462001738565b62000d96565b620001d462000357366004620017b3565b62000e0d565b60006200036b600362000e2c565b905090565b336200037b62000769565b6001600160a01b031614620003ad5760405162461bcd60e51b8152600401620003a49062001be5565b60405180910390fd5b82518114620003fa5760405162461bcd60e51b81526020600482015260186024820152770dad2e6dac2e8c6d0d2dcce40c2e4e4c2f240d8cadccee8d60431b6044820152606401620003a4565b60005b8351811015620004f3578381815181106200042857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316634f1ef286600160009054906101000a90046001600160a01b03168585858181106200047557634e487b7160e01b600052603260045260246000fd5b905060200281019062000489919062001c27565b6040518463ffffffff1660e01b8152600401620004a99392919062001ad6565b600060405180830381600087803b158015620004c457600080fd5b505af1158015620004d9573d6000803e3d6000fd5b505050508080620004ea9062001d66565b915050620003fd565b50505050565b336200050462000769565b6001600160a01b0316146200052d5760405162461bcd60e51b8152600401620003a49062001be5565b60005b8151811015620005db578181815181106200055b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316638356ca4f60006040518263ffffffff1660e01b815260040162000591919062001aa8565b600060405180830381600087803b158015620005ac57600080fd5b505af1158015620005c1573d6000803e3d6000fd5b505050508080620005d29062001d66565b91505062000530565b5050565b600080620005ec6200095f565b905060005b815181101562000651576200062e8282815181106200062057634e487b7160e01b600052603260045260246000fd5b602002602001015162000740565b6200063a908462001ca1565b925080620006488162001d66565b915050620005f1565b505090565b336200066162000769565b6001600160a01b0316146200068a5760405162461bcd60e51b8152600401620003a49062001be5565b60005b8151811015620005db57818181518110620006b857634e487b7160e01b600052603260045260246000fd5b6020908102919091010151600154604051631b2ce7f360e11b81526001600160a01b0392831692633659cfe692620006f69291169060040162001aa8565b600060405180830381600087803b1580156200071157600080fd5b505af115801562000726573d6000803e3d6000fd5b505050508080620007379062001d66565b9150506200068d565b6001600160a01b0381166000908152600560205260408120620007639062000e2c565b92915050565b6000546001600160a01b031690565b600054600160a81b900460ff16806200079b5750600054600160a01b900460ff16155b620008005760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620003a4565b600054600160a81b900460ff161580156200082b576000805461ffff60a01b191661010160a01b1790555b600180546001600160a01b038086166001600160a01b0319928316179092556000805492851692909116919091179055801562000870576000805460ff60a81b191690555b505050565b6002546060906200036b906001600160a01b03165b60606000620008998362000740565b90506000816001600160401b03811115620008c457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620008ee578160200160208202803683370190505b50905060005b82811015620009575762000909858262000e37565b8282815181106200092a57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806200094e8162001d66565b915050620008f4565b509392505050565b606060006200096d6200035d565b90506000816001600160401b038111156200099857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620009c2578160200160208202803683370190505b50905060005b8281101562000a2a57620009dc8162000e62565b828281518110620009fd57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528062000a218162001d66565b915050620009c8565b5092915050565b3362000a3c62000769565b6001600160a01b03161462000a655760405162461bcd60e51b8152600401620003a49062001be5565b600080546040516001600160a01b0390911690600080516020620027ba833981519152908390a3600080546001600160a01b0319169055565b600062000aab8262000d96565b6001600160a01b03161592915050565b60606000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562000af957600080fd5b505afa15801562000b0e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000b3891908101906200195a565b90506000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562000b7657600080fd5b505afa15801562000b8b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000bb591908101906200195a565b905062000c0760405180604001604052806011815260200170020b93930b5b4b9902b30bab63a102b189607d1b81525083604051806040016040528060018152602001602f60f81b8152508462000e71565b95945050505050565b3362000c1b62000769565b6001600160a01b03161462000c445760405162461bcd60e51b8152600401620003a49062001be5565b6001546040517f0617fd31aa5ab95ec80eefc1eb61a2c477aa419d1d761b4e46f5f077e47852aa9162000c85916001600160a01b0390911690849062001abc565b60405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b3362000cba62000769565b6001600160a01b03161462000ce35760405162461bcd60e51b8152600401620003a49062001be5565b6001600160a01b03811662000d4c5760405162461bcd60e51b815260206004820152602860248201527f4f776e61626c653a206e6577206d616e6167657220697320746865207a65726f604482015267206164647265737360c01b6064820152608401620003a4565b600080546040516001600160a01b0380851693921691600080516020620027ba83398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b0316633e47158c6040518163ffffffff1660e01b815260040160206040518083038186803b15801562000dd257600080fd5b505afa15801562000de7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000763919062001757565b600062000e208888888888888862000ea5565b98975050505050505050565b600062000763825490565b6001600160a01b038216600090815260056020526040812062000e5b90836200100c565b9392505050565b6000620007636003836200100c565b60608484848460405160200162000e8c949392919062001a19565b6040516020818303038152906040529050949350505050565b600080606062000eb98a8a8a88886200101a565b60065492955090935091506001600160a01b0384169063e25e15e390839062000eef9062000ee990600162001ca1565b620012ac565b60405160200162000f01919062001a78565b604051602081830303815290604052858a8a8a8e6040518863ffffffff1660e01b815260040162000f39979695949392919062001b7a565b600060405180830381600087803b15801562000f5457600080fd5b505af115801562000f69573d6000803e3d6000fd5b5050505062000f838760036200140890919063ffffffff16565b506001600160a01b038716600090815260056020526040902062000fa8908462001408565b5060016006600082825462000fbe919062001ca1565b90915550506040516001600160a01b0380851691898216918516907f9c5d829b9b23efc461f9aeef91979ec04bb903feb3bee4f26d22114abfc7335b90600090a45050979650505050505050565b600062000e5b83836200141f565b60008060606000806200102e8a8a620014b6565b6001546040519294509092506001600160a01b0316903090620010519062001694565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f08015801562001094573d6000803e3d6000fd5b50604080518082018252601081526f417272616b6973205661756c7420563160801b6020820152905163bd30dfb960e01b81529196509350309063bd30dfb990620010e6908590859060040162001abc565b60006040518083038186803b158015620010ff57600080fd5b505afa9250505080156200113757506040513d6000823e601f3d908101601f191682016040526200113491908101906200195a565b60015b620011425762001145565b92505b604051630b4c774160e11b81526001600160a01b038381166004830152828116602483015262ffffff8a1660448301527f0000000000000000000000001f98431c8ad98523631ae4a59f267346ea31f9841690631698ee829060640160206040518083038186803b158015620011ba57600080fd5b505afa158015620011cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011f5919062001757565b93506001600160a01b0384166200124d5760405162461bcd60e51b815260206004820152601b60248201527a1d5b9a5cddd85c081c1bdbdb08191bd95cc81b9bdd08195e1a5cdd602a1b6044820152606401620003a4565b6200125a84888862001585565b6200129f5760405162461bcd60e51b81526020600482015260146024820152730e8d2c6d6a6e0c2c6d2dcce40dad2e6dac2e8c6d60631b6044820152606401620003a4565b5050955095509592505050565b606081620012d15750506040805180820190915260018152600360fc1b602082015290565b8160005b8115620013015780620012e88162001d66565b9150620012f99050600a8362001ce4565b9150620012d5565b6000816001600160401b038111156200132a57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801562001355576020820181803683370190505b509050815b8515620013ff576200136e60018262001d1d565b905060006200137f600a8862001ce4565b6200138c90600a62001cfb565b62001398908862001d1d565b620013a590603062001cbc565b905060008160f81b905080848481518110620013d157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350620013f5600a8962001ce4565b975050506200135a565b50949350505050565b600062000e5b836001600160a01b03841662001642565b815460009082106200147f5760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401620003a4565b826000018281548110620014a357634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b600080826001600160a01b0316846001600160a01b031614156200150a5760405162461bcd60e51b815260206004820152600a60248201526939b0b6b2903a37b5b2b760b11b6044820152606401620003a4565b826001600160a01b0316846001600160a01b0316106200152c5782846200152f565b83835b90925090506001600160a01b0382166200157e5760405162461bcd60e51b815260206004820152600f60248201526e6e6f2061646472657373207a65726f60881b6044820152606401620003a4565b9250929050565b600080846001600160a01b031663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015620015c257600080fd5b505afa158015620015d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015fd91906200193b565b90508260020b8460020b1280156200162157506200161c818562001d84565b60020b155b801562000c07575062001635818462001d84565b60020b1595945050505050565b60008181526001830160205260408120546200168b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000763565b50600062000763565b6109a58062001e1583390190565b600082601f830112620016b3578081fd5b813560206001600160401b03821115620016d157620016d162001dd5565b8160051b620016e282820162001c6e565b838152828101908684018388018501891015620016fd578687fd5b8693505b858410156200172c578035620017178162001deb565b83526001939093019291840191840162001701565b50979650505050505050565b6000602082840312156200174a578081fd5b813562000e5b8162001deb565b60006020828403121562001769578081fd5b815162000e5b8162001deb565b6000806040838503121562001789578081fd5b8235620017968162001deb565b91506020830135620017a88162001deb565b809150509250929050565b600080600080600080600060e0888a031215620017ce578283fd5b8735620017db8162001deb565b96506020880135620017ed8162001deb565b9550604088013562ffffff8116811462001805578384fd5b94506060880135620018178162001deb565b9350608088013561ffff811681146200182e578384fd5b925060a0880135620018408162001e04565b915060c0880135620018528162001e04565b8091505092959891949750929550565b60006020828403121562001874578081fd5b81356001600160401b038111156200188a578182fd5b6200189884828501620016a2565b949350505050565b600080600060408486031215620018b5578283fd5b83356001600160401b0380821115620018cc578485fd5b620018da87838801620016a2565b94506020860135915080821115620018f0578384fd5b818601915086601f83011262001904578384fd5b81358181111562001913578485fd5b8760208260051b850101111562001928578485fd5b6020830194508093505050509250925092565b6000602082840312156200194d578081fd5b815162000e5b8162001e04565b6000602082840312156200196c578081fd5b81516001600160401b038082111562001983578283fd5b818401915084601f83011262001997578283fd5b815181811115620019ac57620019ac62001dd5565b620019c1601f8201601f191660200162001c6e565b9150808252856020828501011115620019d8578384fd5b620013ff81602084016020860162001d37565b6000815180845262001a0581602086016020860162001d37565b601f01601f19169290920160200192915050565b6000855162001a2d818460208a0162001d37565b85519083019062001a43818360208a0162001d37565b855191019062001a5881836020890162001d37565b845191019062001a6d81836020880162001d37565b019695505050505050565b6552414b49532d60d01b81526000825162001a9b81600685016020870162001d37565b9190910160060192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b6020808252825182820181905260009190848201906040850190845b8181101562001b595783516001600160a01b03168352928401929184019160010162001b32565b50909695505050505050565b60208152600062000e5b6020830184620019eb565b60e08152600062001b8f60e083018a620019eb565b828103602084015262001ba3818a620019eb565b6001600160a01b03988916604085015261ffff9790971660608401525050600293840b60808201529190920b60a0820152921660c09092019190915292915050565b60208082526022908201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206d616e616760408201526132b960f11b606082015260800190565b6000808335601e1984360301811262001c3e578283fd5b8301803591506001600160401b0382111562001c58578283fd5b6020019150368190038213156200157e57600080fd5b604051601f8201601f191681016001600160401b038111828210171562001c995762001c9962001dd5565b604052919050565b6000821982111562001cb75762001cb762001da9565b500190565b600060ff821660ff84168060ff0382111562001cdc5762001cdc62001da9565b019392505050565b60008262001cf65762001cf662001dbf565b500490565b600081600019048311821515161562001d185762001d1862001da9565b500290565b60008282101562001d325762001d3262001da9565b500390565b60005b8381101562001d5457818101518382015260200162001d3a565b83811115620004f35750506000910152565b600060001982141562001d7d5762001d7d62001da9565b5060010190565b60008260020b8062001d9a5762001d9a62001dbf565b808360020b0791505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811462001e0157600080fd5b50565b8060020b811462001e0157600080fdfe60806040526040516109a53803806109a5833981016040819052610022916101a4565b61002c838261003d565b61003582610119565b5050506102ce565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8054908390556040516001600160a01b0380851691908316907f5570d70a002632a7b0b3c9304cc89efb62d8da9eca0dbd7752c83b737906829690600090a3815115610114576000836001600160a01b0316836040516100be9190610270565b600060405180830381855af49150503d80600081146100f9576040519150601f19603f3d011682016040523d82523d6000602084013e6100fe565b606091505b5050905080610112573d806000803e806000fd5b505b505050565b60006101316000805160206109858339815191525490565b90508160008051602061098583398151915255816001600160a01b0316816001600160a01b03167fdf435d422321da6b195902d70fc417c06a32f88379c20dd8f2a8da07088cec2960405160405180910390a35050565b80516001600160a01b038116811461019f57600080fd5b919050565b6000806000606084860312156101b8578283fd5b6101c184610188565b92506101cf60208501610188565b60408501519092506001600160401b03808211156101eb578283fd5b818601915086601f8301126101fe578283fd5b815181811115610210576102106102b8565b604051601f8201601f19908116603f01168101908382118183101715610238576102386102b8565b81604052828152896020848701011115610250578586fd5b61026183602083016020880161028c565b80955050505050509250925092565b6000825161028281846020870161028c565b9190910192915050565b60005b838110156102a757818101518382015260200161028f565b838111156101125750506000910152565b634e487b7160e01b600052604160045260246000fd5b6106a8806102dd6000396000f3fe60806040526004361061004e5760003560e01c806301ffc9a71461009b5780633659cfe6146100d05780633e47158c146100f05780634f1ef2861461011d5780638356ca4f1461013057610091565b366100915760405162461bcd60e51b815260206004820152600e60248201526d115512115497d491529150d5115160921b60448201526064015b60405180910390fd5b610099610150565b005b3480156100a757600080fd5b506100bb6100b63660046105a9565b610189565b60405190151581526020015b60405180910390f35b3480156100dc57600080fd5b506100996100eb3660046104f2565b61027e565b3480156100fc57600080fd5b506101056102d2565b6040516001600160a01b0390911681526020016100c7565b61009961012b36600461050c565b6102e1565b34801561013c57600080fd5b5061009961014b3660046104f2565b61035e565b6000805160206106538339815191525460003681823780813683855af491503d8082833e82801561017f578183f35b8183fd5b50505050565b60006301ffc9a760e01b6001600160e01b0319831614806101ba57506307f5828d60e41b6001600160e01b03198316145b156101c757506001919050565b6001600160e01b031980831614156101e157506000919050565b600080516020610653833981519152546040516301ffc9a760e01b81526001600160e01b0319841660048201526001600160a01b038216906301ffc9a79060240160206040518083038186803b15801561023a57600080fd5b505afa92505050801561026a575060408051601f3d908101601f1916820190925261026791810190610589565b60015b6102775750600092915050565b9392505050565b61028661039f565b6001600160a01b0316336001600160a01b0316146102b65760405162461bcd60e51b81526004016100889061060a565b6102cf81604051806020016040528060008152506103b2565b50565b60006102dc61039f565b905090565b6102e961039f565b6001600160a01b0316336001600160a01b0316146103195760405162461bcd60e51b81526004016100889061060a565b6103598383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103b292505050565b505050565b61036661039f565b6001600160a01b0316336001600160a01b0316146103965760405162461bcd60e51b81526004016100889061060a565b6102cf81610475565b6000805160206106338339815191525490565b6000805160206106538339815191528054908390556040516001600160a01b0380851691908316907f5570d70a002632a7b0b3c9304cc89efb62d8da9eca0dbd7752c83b737906829690600090a3815115610359576000836001600160a01b03168360405161042191906105d1565b600060405180830381855af49150503d806000811461045c576040519150601f19603f3d011682016040523d82523d6000602084013e610461565b606091505b5050905080610183573d806000803e806000fd5b600061047f61039f565b90508160008051602061063383398151915255816001600160a01b0316816001600160a01b03167fdf435d422321da6b195902d70fc417c06a32f88379c20dd8f2a8da07088cec2960405160405180910390a35050565b80356001600160a01b03811681146104ed57600080fd5b919050565b600060208284031215610503578081fd5b610277826104d6565b600080600060408486031215610520578182fd5b610529846104d6565b925060208401356001600160401b0380821115610544578384fd5b818601915086601f830112610557578384fd5b813581811115610565578485fd5b876020828501011115610576578485fd5b6020830194508093505050509250925092565b60006020828403121561059a578081fd5b81518015158114610277578182fd5b6000602082840312156105ba578081fd5b81356001600160e01b031981168114610277578182fd5b60008251815b818110156105f157602081860181015185830152016105d7565b818111156105ff5782828501525b509190910192915050565b6020808252600e908201526d1393d517d055551213d49256915160921b60408201526060019056feb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220730effc08e7ae1c19f69ae08dd52de483b649ded49db9428e4ced9875431474364736f6c63430008040033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0a264697066735822122032c0226340af0379cd7d43429d1502fc96d02b3e0f888c97b7ed277717483dc364736f6c63430008040033