false
false
0
The new Blockscout UI is now open source! Learn how to deploy it here

Contract Address Details

0x2822eE30383EAbCBA817Ab4A7a592F4a194e14b5

Contract Name
VaultRegistry
Creator
0x077675–fb67cc at 0x1efb32–188b07
Balance
0 ETH
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
486018
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
VaultRegistry




Optimization enabled
true
Compiler version
v0.8.12+commit.f00d7308




Optimization runs
10
EVM Version
london




Verified at
2024-06-07T13:16:41.428490Z

contracts/VaultRegistry.sol

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

import "./interfaces/IStrategyRegistry.sol";

// Factory
import "@openzeppelin/contracts-upgradeable/proxy/ClonesUpgradeable.sol";

// Proxy Support
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";

// Vault support
import "./interfaces/IVaultRegistry.sol";
import "./interfaces/IImplementation.sol";

// Beacon support
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";

// Governance
import { IOrchestrator } from "./interfaces/IOrchestrator.sol";

// Inheritance
import { InterfaceManager } from "./VaultRegistry/InterfaceManager.sol";
import { IFeeManager } from "./interfaces/IFeeManager.sol";
import { IMultiPositionManager } from "./interfaces/IMultiPositionManager.sol";

/// @title A registry for vaults
/// @author Steer Protocol
/// @dev All vaults are created through this contract
contract VaultRegistry is
    Initializable,
    UUPSUpgradeable,
    PausableUpgradeable,
    InterfaceManager
{
    /// @dev Vault creation event
    /// @param deployer The address of the deployer
    /// @param vault The address of the vault
    /// @param tokenId ERC721 token id for the vault
    /// @param vaultManager is the address which will manage the vault being created
    event VaultCreated(
        address deployer,
        address vault,
        string beaconName,
        uint256 indexed tokenId,
        address vaultManager
    );

    /// @dev Vault state change event
    /// @param vault The address of the vault
    /// @param newState The new state of the vault
    event VaultStateChanged(address indexed vault, VaultState newState);

    /// @dev Fee setting in FeeManager failed
    event FeeSettingFailed(address, string);

    /**
     * @dev all necessary data for vault. Name and symbol are stored in vault's ERC20. Owner is stored with tokenId in StrategyRegistry.
     * tokenId: NFT identifier number
     * vaultAddress: address of vault this describes
     * state: state of the vault.
     */
    struct VaultData {
        VaultState state;
        uint256 tokenId; //NFT ownership of this vault and all others that use vault's exec bundle
        uint256 vaultID; //unique identifier for this vault and strategy token id
        string payloadIpfs;
        address vaultAddress;
        string beaconName;
    }

    /**
     * PendingApproval: strategy is submitted but has not yet been approved by the owner
     * PendingThreshold: strategy is approved but has not yet reached the threshold of TVL required
     * Paused: strategy was active but something went wrong, so now it's paused
     * Active: strategy is active and can be used
     * Retired: strategy is retired and can no longer be used
     */
    enum VaultState {
        PendingApproval,
        PendingThreshold,
        Paused,
        Active,
        Retired
    }

    // Pause role for disabling vault creation in the event of an emergency
    bytes32 internal constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    // Governance role for controlling aspects of the registry
    bytes32 internal constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");

    // Total vault count
    uint256 public totalVaultCount;

    // Mapping for vaults to their details
    // Vault Address => VaultDetails
    mapping(address => VaultData) internal vaults;

    // Mapping from strategy token ID (Execution Bundle) to list of linked vault IDs
    //  Strategy ID => (VaultId => vault address)
    mapping(uint256 => mapping(uint256 => address)) public linkedVaults;

    // Mapping for strategy token ID to number of vaults created using that strategy.
    mapping(uint256 => uint256) internal linkedVaultCounts;

    //Orchestrator address
    address public orchestrator;

    // Strategy registry address--used for strategy IDs
    IStrategyRegistry public strategyRegistry;

    // Misc addresses--used to point vaults towards the correct contracts.
    address public whitelistRegistry;
    address public feeManager;
    address public vaultHelper;

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() initializer {}

    /// @dev intializes the vault registry
    /// @param _orchestrator The address of the orchestrator
    /// @param _strategyRegistry The address of the strategy registry
    /// @param _whitelistRegistry Address of whitelist registry which keeps track of whitelist managers and members of whitelisted vaults
    function initialize(
        address _orchestrator,
        address _strategyRegistry,
        address _whitelistRegistry
    ) public initializer {
        __UUPSUpgradeable_init();
        __Ownable_init();
        __AccessControl_init();
        __Pausable_init();

        require(_strategyRegistry != address(0), "address(0)");
        require(_whitelistRegistry != address(0), "address(0)");
        require(_orchestrator != address(0), "address(0)");
        orchestrator = _orchestrator;
        // Instantiate the strategy registry
        strategyRegistry = IStrategyRegistry(_strategyRegistry);

        // Record misc addresses
        whitelistRegistry = _whitelistRegistry;
        // Access Control Setup
        // Grant pauser, beacon creator, and ERC165 editor roles to deployer for deploying initial beacons
        _setupRole(PAUSER_ROLE, _msgSender());
        _setupRole(BEACON_CREATOR, _msgSender());
        _setupRole(INTERFACE_EDITOR, _msgSender());
        // Grant admin role to deployer but after registering all initial beacons in its script, deployer will revoke all roles granted to self and grant default admin role and above three roles to multisig
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
    }

    /// @dev Creates a new vault with the given strategy
    /// @dev Registers an execution bundle, mints an NFT and mappings it to execution bundle and it's details.
    /// @param _params is extra parameters in vault.
    /// @param _tokenId is the NFT of the execution bundle this vault will be using. Note that if the given tokenID does not yet exist, the vault will remain inactive.
    /// @param _beaconName beacon identifier of vault type to be created
    /// @param _vaultManager is the address which will manage the vault being created
    /// @dev owner is set as msg.sender.
    function createVault(
        bytes memory _params,
        uint256 _tokenId,
        string memory _beaconName,
        address _vaultManager,
        string memory _payloadIpfs
    ) external whenNotPaused returns (address) {
        require(feeManager != address(0), "FeeManager not set");
        require(vaultHelper != address(0), "Vault helper not set");
        //Validate that no strategy exists of the tokenid passed
        strategyRegistry.ownerOf(_tokenId);
        // Retrieve the address for the vault type to be created
        address beaconAddress = beaconAddresses[_beaconName];
        // Make sure that we have a beacon for the provided vault type
        // This ensures that a bad vault type hasn't been provided
        require(beaconAddress != address(0), "Beacon is not present");
        // Create new vault implementation
        BeaconProxy newVault = new BeaconProxy(
            beaconAddress,
            abi.encodeWithSelector(
                IImplementation.initialize.selector,
                _vaultManager,
                orchestrator,
                owner(),
                _params
            )
        );

        // Add beacon type to mapping
        beaconTypes[address(newVault)] = _beaconName;
        // As the vaultypes will be gradually upgarded one by one there may be situations where
        // there may be a need to create older type of vaults(as they are not yet upgraded) which
        // do not depending on feemanager and also
        // there may be a need to craete the newer vaults which are depending on the fee manager so
        // to maintain backward compatibilty below piece of code is put in try catch block
        // Also in future there may be a vault type that does not use fee manager
        try IMultiPositionManager(address(newVault)).feeDetails() returns (
            uint256 totalFees,
            address[] memory feeWithdrawers,
            string[] memory feeIdentifiers,
            uint256[] memory feeValues
        ) {
            if (totalFees > 0) {
                IFeeManager(feeManager).setDefaultFeeAndWithdrawalPermission(
                    address(newVault),
                    totalFees,
                    feeIdentifiers,
                    feeValues,
                    feeWithdrawers
                );
            }
        } catch {
            emit FeeSettingFailed(
                address(newVault),
                "Fee setting failed in FeeManager"
            );
        }

        // Add enumeration for the vault
        _addLinkedVaultsEnumeration(
            _tokenId,
            address(newVault),
            _payloadIpfs,
            _beaconName
        );

        // Emit vault details
        emit VaultCreated(
            msg.sender,
            address(newVault),
            _beaconName,
            _tokenId,
            _vaultManager
        );

        // Return the address of the new vault
        return address(newVault);
    }

    /// @dev Updates the vault state and emits a VaultStateChanged event
    /// @param _vault The address of the vault
    /// @param _newState The new state of the vault
    /// @dev This function is only available to the registry owner.
    function updateVaultState(
        address _vault,
        VaultState _newState
    ) external onlyOwner {
        vaults[_vault].state = _newState;
        emit VaultStateChanged(_vault, _newState);
    }

    /// @dev Retrieves the creator of the strategy of the given vault
    /// @param _vault The address of the vault
    /// @return The address of the creator
    function getStrategyCreatorForVault(
        address _vault
    ) public view returns (address) {
        return strategyRegistry.ownerOf(vaults[_vault].tokenId);
    }

    function _authorizeUpgrade(
        address newImplementation
    ) internal override onlyOwner {}

    /// @dev Pauses the minting of the ERC721 tokens for the vault
    /// @dev This function is only available to the pauser role
    function pause() public onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() public onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    /// @dev Provides support for vault enumeration
    /// @dev Private function to add a token to this extension's ownership-tracking data structures.
    /// @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
    /// @param _deployedAddress address of the new vault
    function _addLinkedVaultsEnumeration(
        uint256 _tokenId,
        address _deployedAddress,
        string memory _payloadIpfs,
        string memory _beaconName
    ) internal {
        // Get the current count of how many vaults have been created from this strategy.
        uint256 currentCount = linkedVaultCounts[_tokenId];

        // Using _tokenId and count as map keys, add the vault to the list of linked vaults
        linkedVaults[_tokenId][currentCount] = _deployedAddress;

        // Increment the count of how many vaults have been created from a given strategy
        linkedVaultCounts[_tokenId] = currentCount + 1;

        // Store any vault specific data via the _deployedAddress
        vaults[_deployedAddress] = VaultData({
            state: VaultState.PendingThreshold,
            tokenId: _tokenId,
            vaultID: ++totalVaultCount,
            payloadIpfs: _payloadIpfs,
            vaultAddress: _deployedAddress,
            beaconName: _beaconName
        });
    }

    /// @dev Retrieves the details of a given vault by address
    /// @param _address The address of the vault
    /// @return The details of the vault
    function getVaultDetails(
        address _address
    ) public view returns (VaultData memory) {
        return vaults[_address];
    }

    /// @dev Retrieves the vault count by vault token id
    /// @param _tokenId The token id of the vault
    /// @return The count of the vault
    function getVaultCountByStrategyId(
        uint256 _tokenId
    ) public view returns (uint256) {
        return linkedVaultCounts[_tokenId];
    }

    /// @dev Retrieves the vault by vault token id and vault index
    /// @param _tokenId The token id of the vault
    /// @param _vaultId The index of the vault
    /// @return Vault details
    function getVaultByStrategyAndIndex(
        uint256 _tokenId,
        uint256 _vaultId
    ) public view returns (VaultData memory) {
        return vaults[linkedVaults[_tokenId][_vaultId]];
    }

    function setFeeManager(address _feeManager) external onlyOwner {
        require(feeManager == address(0), "Already Set");
        feeManager = _feeManager;
    }

    function setVaultHelper(address _vaultHelper) external onlyOwner {
        vaultHelper = _vaultHelper;
    }
}
        

contracts/interfaces/IMultiPositionManager.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.10;
pragma abicoder v2;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IUniswapV3Pool } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
import { IAlgebraPool } from "@cryptoalgebra/core/contracts/interfaces/IAlgebraPool.sol";

interface IMultiPositionManager is IERC20 {
    struct VaultDetails {
        string vaultType;
        address token0;
        address token1;
        string name;
        string symbol;
        uint256 decimals;
        string token0Name;
        string token1Name;
        string token0Symbol;
        string token1Symbol;
        uint256 token0Decimals;
        uint256 token1Decimals;
        uint256 feeTier;
        uint256 totalLPTokensIssued;
        uint256 token0Balance;
        uint256 token1Balance;
        address vaultCreator;
    }

    struct AlgebraVaultDetails {
        string vaultType;
        address token0;
        address token1;
        string name;
        string symbol;
        uint256 decimals;
        string token0Name;
        string token1Name;
        string token0Symbol;
        string token1Symbol;
        uint256 token0Decimals;
        uint256 token1Decimals;
        uint256 totalLPTokensIssued;
        uint256 token0Balance;
        uint256 token1Balance;
        address vaultCreator;
    }

    struct VaultBalance {
        uint256 amountToken0;
        uint256 amountToken1;
    }

    struct LiquidityPositions {
        int24[] lowerTick;
        int24[] upperTick;
        uint16[] relativeWeight;
    }

    /**
     * @dev initializes vault
     * param _vaultManager is the address which will manage the vault being created
     * param _params is all other parameters this vault will use.
     * param _tokenName is the name of the LPT of this vault.
     * param _symbol is the symbol of the LPT of this vault.
     * param token0 is address of token0
     * param token1 is address of token1
     * param _FEE is pool fee, how much is charged for a swap
     */
    function initialize(
        address _vaultManager,
        address, //orchestrator not needed here as, if this vault is to be managed by orchestrator, _vaultManager parameter should be the orchestrator address
        address _steer,
        bytes memory _params
    ) external;

    ///
    /// @dev Deposits tokens in proportion to the vault's current holdings.
    /// @dev These tokens sit in the vault and are not used for liquidity on
    /// Uniswap until the next rebalance.
    /// @param amount0Desired Max amount of token0 to deposit
    /// @param amount1Desired Max amount of token1 to deposit
    /// @param amount0Min Revert if resulting `amount0` is less than this
    /// @param amount1Min Revert if resulting `amount1` is less than this
    /// @param to Recipient of shares
    /// @return shares Number of shares minted
    /// @return amount0 Amount of token0 deposited
    /// @return amount1 Amount of token1 deposited
    ///
    function deposit(
        uint256 amount0Desired,
        uint256 amount1Desired,
        uint256 amount0Min,
        uint256 amount1Min,
        address to
    ) external returns (uint256 shares, uint256 amount0, uint256 amount1);

    /**
     * @dev burns each vault position which contains liquidity, updating fees owed to that position.
     * @dev call this before calling getTotalAmounts if total amounts must include fees. There's a function in the periphery to do so through a static call.
     */
    function poke() external;

    /**
     * @dev Withdraws tokens in proportion to the vault's holdings.
     * @param shares Shares burned by sender
     * @param amount0Min Revert if resulting `amount0` is smaller than this
     * @param amount1Min Revert if resulting `amount1` is smaller than this
     * @param to Recipient of tokens
     * @return amount0 Amount of token0 sent to recipient
     * @return amount1 Amount of token1 sent to recipient
     */
    function withdraw(
        uint256 shares,
        uint256 amount0Min,
        uint256 amount1Min,
        address to
    ) external returns (uint256 amount0, uint256 amount1);

    /**
     * @dev Internal function to pull funds from pool, update positions if necessary, then deposit funds into pool.
     * @dev reverts if it does not have any liquidity.

     * @dev newPositions requirements:
     * Each lowerTick must be lower than its corresponding upperTick
     * Each lowerTick must be greater than or equal to the tick min (-887272)
     * Each upperTick must be less than or equal to the tick max (887272)
     * All lowerTicks and upperTicks must be divisible by the pool tickSpacing--
        A 0.05% fee pool has tick spacing of 10, 0.3% has tick spacing 60. and 1% has tick spacing 200.)
     */
    function tend(
        LiquidityPositions memory newPositions,
        int256 swapAmount,
        uint160 sqrtPriceLimitX96
    ) external;

    /**
     * @dev Calculates the vault's total holdings of token0 and token1 - in
     *      other words, how much of each token the vault would hold if it withdrew
     *      all its liquidity from Uniswap.
     * @dev this function DOES NOT include fees. To include fees, first poke() and then call getTotalAmounts. There's a function inside the periphery to do so.
     */
    function getTotalAmounts()
        external
        view
        returns (uint256 total0, uint256 total1);

    //Tokens
    function vaultRegistry() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function maxTotalSupply() external view returns (uint256);

    function pool() external view returns (IUniswapV3Pool);

    function TOTAL_FEE() external view returns (uint256);

    function STEER_FRACTION_OF_FEE() external view returns (uint256);

    function feeDetails()
        external
        view
        returns (uint256, address[] memory, string[] memory, uint256[] memory);

    // /**
    //  * @dev Used to collect accumulated protocol fees.
    //  */
    // function steerCollectFees(
    //     uint256 amount0,
    //     uint256 amount1,
    //     address to
    // ) external;

    // /**
    //  * @dev Used to collect accumulated protocol fees.
    //  */
    // function strategistCollectFees(
    //     uint256 amount0,
    //     uint256 amount1,
    //     address to
    // ) external;

    /**
     * @dev Used to collect accumulated protocol fees.
     */
    function collectFees(
        string memory feeIdentifier,
        uint256 amount0,
        uint256 amount1
    ) external;

    /**
     * @dev Removes liquidity in case of emergency.
     */
    function emergencyBurn(
        int24 tickLower,
        int24 tickUpper,
        uint128 liquidity
    ) external returns (uint256 amount0, uint256 amount1);

    function accruedFees0(string memory) external view returns (uint256);

    function accruedFees1(string memory) external view returns (uint256);
}
          

@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;

import "../beacon/IBeaconUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 *
 * @custom:oz-upgrades-unsafe-allow delegatecall
 */
abstract contract ERC1967UpgradeUpgradeable is Initializable {
    function __ERC1967Upgrade_init() internal onlyInitializing {
        __ERC1967Upgrade_init_unchained();
    }

    function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
    }
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            _functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallSecure(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        address oldImplementation = _getImplementation();

        // Initial upgrade and setup call
        _setImplementation(newImplementation);
        if (data.length > 0 || forceCall) {
            _functionDelegateCall(newImplementation, data);
        }

        // Perform rollback test if not already in progress
        StorageSlotUpgradeable.BooleanSlot storage rollbackTesting = StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT);
        if (!rollbackTesting.value) {
            // Trigger rollback using upgradeTo from the new implementation
            rollbackTesting.value = true;
            _functionDelegateCall(
                newImplementation,
                abi.encodeWithSignature("upgradeTo(address)", oldImplementation)
            );
            rollbackTesting.value = false;
            // Check rollback was effective
            require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
            // Finally reset to the new implementation and log the upgrade
            _upgradeTo(newImplementation);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Emitted when the beacon is upgraded.
     */
    event BeaconUpgraded(address indexed beacon);

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(
        address newBeacon,
        bytes memory data,
        bool forceCall
    ) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
        }
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
        require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed");
    }
    uint256[50] private __gap;
}
          

@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol

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

pragma solidity ^0.8.0;

import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";

/**
 * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
 * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
 *
 * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
 * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
 * `UUPSUpgradeable` with a custom implementation of upgrades.
 *
 * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
 *
 * _Available since v4.1._
 */
abstract contract UUPSUpgradeable is Initializable, ERC1967UpgradeUpgradeable {
    function __UUPSUpgradeable_init() internal onlyInitializing {
        __ERC1967Upgrade_init_unchained();
        __UUPSUpgradeable_init_unchained();
    }

    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
    }
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
    address private immutable __self = address(this);

    /**
     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
     * fail.
     */
    modifier onlyProxy() {
        require(address(this) != __self, "Function must be called through delegatecall");
        require(_getImplementation() == __self, "Function must be called through active proxy");
        _;
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     */
    function upgradeTo(address newImplementation) external virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallSecure(newImplementation, new bytes(0), false);
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
     * encoded in `data`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     */
    function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallSecure(newImplementation, data, true);
    }

    /**
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
     * {upgradeTo} and {upgradeToAndCall}.
     *
     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
     *
     * ```solidity
     * function _authorizeUpgrade(address) internal override onlyOwner {}
     * ```
     */
    function _authorizeUpgrade(address newImplementation) internal virtual;
    uint256[50] private __gap;
}
          

contracts/interfaces/IFeeManager.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.6;
pragma abicoder v2;

interface IFeeManager {
    struct Fee {
        string feeIdentifier;
        uint256 feeValue;
    }

    function setFeeAndWithdrawalPermission(
        address vault,
        string[] memory feeIdentifier,
        uint256[] memory feeValue,
        address[] memory withdrawer
    ) external;

    function setDefaultFeeAndWithdrawalPermission(
        address vault,
        uint256 totalVaultFees,
        string[] memory feeIdentifier,
        uint256[] memory feeValue,
        address[] memory withdrawer
    ) external;

    function withdrawFee(address vault, string memory feeIdentifier) external;

    function getFees(address vault) external view returns (Fee[] memory);

    function vaultTotalFees(address vault) external view returns (uint256);

    function setMigratedVaultFeeAndWithdrawalPermission() external;

    function withdrawalPermissions(
        address vault,
        string memory feeIdentifier
    ) external view returns (address);
}
          

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

@openzeppelin/contracts/proxy/Proxy.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)

pragma solidity ^0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}
          

@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolEvents.sol

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

/// @title Events emitted by a pool
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraPoolEvents {
  /**
   * @notice Emitted exactly once by a pool when #initialize is first called on the pool
   * @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize
   * @param price The initial sqrt price of the pool, as a Q64.96
   * @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool
   */
  event Initialize(uint160 price, int24 tick);

  /**
   * @notice Emitted when liquidity is minted for a given position
   * @param sender The address that minted the liquidity
   * @param owner The owner of the position and recipient of any minted liquidity
   * @param bottomTick The lower tick of the position
   * @param topTick The upper tick of the position
   * @param liquidityAmount The amount of liquidity minted to the position range
   * @param amount0 How much token0 was required for the minted liquidity
   * @param amount1 How much token1 was required for the minted liquidity
   */
  event Mint(
    address sender,
    address indexed owner,
    int24 indexed bottomTick,
    int24 indexed topTick,
    uint128 liquidityAmount,
    uint256 amount0,
    uint256 amount1
  );

  /**
   * @notice Emitted when fees are collected by the owner of a position
   * @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees
   * @param owner The owner of the position for which fees are collected
   * @param recipient The address that received fees
   * @param bottomTick The lower tick of the position
   * @param topTick The upper tick of the position
   * @param amount0 The amount of token0 fees collected
   * @param amount1 The amount of token1 fees collected
   */
  event Collect(address indexed owner, address recipient, int24 indexed bottomTick, int24 indexed topTick, uint128 amount0, uint128 amount1);

  /**
   * @notice Emitted when a position's liquidity is removed
   * @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect
   * @param owner The owner of the position for which liquidity is removed
   * @param bottomTick The lower tick of the position
   * @param topTick The upper tick of the position
   * @param liquidityAmount The amount of liquidity to remove
   * @param amount0 The amount of token0 withdrawn
   * @param amount1 The amount of token1 withdrawn
   */
  event Burn(address indexed owner, int24 indexed bottomTick, int24 indexed topTick, uint128 liquidityAmount, uint256 amount0, uint256 amount1);

  /**
   * @notice Emitted by the pool for any swaps between token0 and token1
   * @param sender The address that initiated the swap call, and that received the callback
   * @param recipient The address that received the output of the swap
   * @param amount0 The delta of the token0 balance of the pool
   * @param amount1 The delta of the token1 balance of the pool
   * @param price The sqrt(price) of the pool after the swap, as a Q64.96
   * @param liquidity The liquidity of the pool after the swap
   * @param tick The log base 1.0001 of price of the pool after the swap
   */
  event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 price, uint128 liquidity, int24 tick);

  /**
   * @notice Emitted by the pool for any flashes of token0/token1
   * @param sender The address that initiated the swap call, and that received the callback
   * @param recipient The address that received the tokens from flash
   * @param amount0 The amount of token0 that was flashed
   * @param amount1 The amount of token1 that was flashed
   * @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee
   * @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee
   */
  event Flash(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1);

  /**
   * @notice Emitted when the community fee is changed by the pool
   * @param communityFee0New The updated value of the token0 community fee percent
   * @param communityFee1New The updated value of the token1 community fee percent
   */
  event CommunityFee(uint8 communityFee0New, uint8 communityFee1New);

  /**
   * @notice Emitted when the tick spacing changes
   * @param newTickSpacing The updated value of the new tick spacing
   */
  event TickSpacing(int24 newTickSpacing);

  /**
   * @notice Emitted when new activeIncentive is set
   * @param virtualPoolAddress The address of a virtual pool associated with the current active incentive
   */
  event Incentive(address indexed virtualPoolAddress);

  /**
   * @notice Emitted when the fee changes
   * @param fee The value of the token fee
   */
  event Fee(uint16 fee);

  /**
   * @notice Emitted when the LiquidityCooldown changes
   * @param liquidityCooldown The value of locktime for added liquidity
   */
  event LiquidityCooldown(uint32 liquidityCooldown);
}
          

@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)

pragma solidity ^0.8.0;

import "./IBeacon.sol";
import "../Proxy.sol";
import "../ERC1967/ERC1967Upgrade.sol";

/**
 * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.
 *
 * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
 * conflict with the storage layout of the implementation behind the proxy.
 *
 * _Available since v3.4._
 */
contract BeaconProxy is Proxy, ERC1967Upgrade {
    /**
     * @dev Initializes the proxy with `beacon`.
     *
     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
     * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity
     * constructor.
     *
     * Requirements:
     *
     * - `beacon` must be a contract with the interface {IBeacon}.
     */
    constructor(address beacon, bytes memory data) payable {
        _upgradeBeaconToAndCall(beacon, data, false);
    }

    /**
     * @dev Returns the current beacon address.
     */
    function _beacon() internal view virtual returns (address) {
        return _getBeacon();
    }

    /**
     * @dev Returns the current implementation address of the associated beacon.
     */
    function _implementation() internal view virtual override returns (address) {
        return IBeacon(_getBeacon()).implementation();
    }

    /**
     * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.
     *
     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
     *
     * Requirements:
     *
     * - `beacon` must be a contract.
     * - The implementation returned by `beacon` must be a contract.
     */
    function _setBeacon(address beacon, bytes memory data) internal virtual {
        _upgradeBeaconToAndCall(beacon, data, false);
    }
}
          

@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol

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

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

@cryptoalgebra/core/contracts/interfaces/IAlgebraPool.sol

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

import './pool/IAlgebraPoolImmutables.sol';
import './pool/IAlgebraPoolState.sol';
import './pool/IAlgebraPoolDerivedState.sol';
import './pool/IAlgebraPoolActions.sol';
import './pool/IAlgebraPoolPermissionedActions.sol';
import './pool/IAlgebraPoolEvents.sol';

/**
 * @title The interface for a Algebra Pool
 * @dev The pool interface is broken up into many smaller pieces.
 * Credit to Uniswap Labs under GPL-2.0-or-later license:
 * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
 */
interface IAlgebraPool is
  IAlgebraPoolImmutables,
  IAlgebraPoolState,
  IAlgebraPoolDerivedState,
  IAlgebraPoolActions,
  IAlgebraPoolPermissionedActions,
  IAlgebraPoolEvents
{
  // used only for combining interfaces
}
          

@cryptoalgebra/core/contracts/interfaces/IDataStorageOperator.sol

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

import '../libraries/AdaptiveFee.sol';

interface IDataStorageOperator {
  event FeeConfiguration(AdaptiveFee.Configuration feeConfig);

  /**
   * @notice Returns data belonging to a certain timepoint
   * @param index The index of timepoint in the array
   * @dev There is more convenient function to fetch a timepoint: getTimepoints(). Which requires not an index but seconds
   * @return initialized Whether the timepoint has been initialized and the values are safe to use,
   * blockTimestamp The timestamp of the observation,
   * tickCumulative The tick multiplied by seconds elapsed for the life of the pool as of the timepoint timestamp,
   * secondsPerLiquidityCumulative The seconds per in range liquidity for the life of the pool as of the timepoint timestamp,
   * volatilityCumulative Cumulative standard deviation for the life of the pool as of the timepoint timestamp,
   * averageTick Time-weighted average tick,
   * volumePerLiquidityCumulative Cumulative swap volume per liquidity for the life of the pool as of the timepoint timestamp
   */
  function timepoints(
    uint256 index
  )
    external
    view
    returns (
      bool initialized,
      uint32 blockTimestamp,
      int56 tickCumulative,
      uint160 secondsPerLiquidityCumulative,
      uint88 volatilityCumulative,
      int24 averageTick,
      uint144 volumePerLiquidityCumulative
    );

  /// @notice Initialize the dataStorage array by writing the first slot. Called once for the lifecycle of the timepoints array
  /// @param time The time of the dataStorage initialization, via block.timestamp truncated to uint32
  /// @param tick Initial tick
  function initialize(uint32 time, int24 tick) external;

  /// @dev Reverts if an timepoint at or before the desired timepoint timestamp does not exist.
  /// 0 may be passed as `secondsAgo' to return the current cumulative values.
  /// If called with a timestamp falling between two timepoints, returns the counterfactual accumulator values
  /// at exactly the timestamp between the two timepoints.
  /// @param time The current block timestamp
  /// @param secondsAgo The amount of time to look back, in seconds, at which point to return an timepoint
  /// @param tick The current tick
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param liquidity The current in-range pool liquidity
  /// @return tickCumulative The cumulative tick since the pool was first initialized, as of `secondsAgo`
  /// @return secondsPerLiquidityCumulative The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of `secondsAgo`
  /// @return volatilityCumulative The cumulative volatility value since the pool was first initialized, as of `secondsAgo`
  /// @return volumePerAvgLiquidity The cumulative volume per liquidity value since the pool was first initialized, as of `secondsAgo`
  function getSingleTimepoint(
    uint32 time,
    uint32 secondsAgo,
    int24 tick,
    uint16 index,
    uint128 liquidity
  ) external view returns (int56 tickCumulative, uint160 secondsPerLiquidityCumulative, uint112 volatilityCumulative, uint256 volumePerAvgLiquidity);

  /// @notice Returns the accumulator values as of each time seconds ago from the given time in the array of `secondsAgos`
  /// @dev Reverts if `secondsAgos` > oldest timepoint
  /// @param time The current block.timestamp
  /// @param secondsAgos Each amount of time to look back, in seconds, at which point to return an timepoint
  /// @param tick The current tick
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param liquidity The current in-range pool liquidity
  /// @return tickCumulatives The cumulative tick since the pool was first initialized, as of each `secondsAgo`
  /// @return secondsPerLiquidityCumulatives The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of each `secondsAgo`
  /// @return volatilityCumulatives The cumulative volatility values since the pool was first initialized, as of each `secondsAgo`
  /// @return volumePerAvgLiquiditys The cumulative volume per liquidity values since the pool was first initialized, as of each `secondsAgo`
  function getTimepoints(
    uint32 time,
    uint32[] memory secondsAgos,
    int24 tick,
    uint16 index,
    uint128 liquidity
  )
    external
    view
    returns (
      int56[] memory tickCumulatives,
      uint160[] memory secondsPerLiquidityCumulatives,
      uint112[] memory volatilityCumulatives,
      uint256[] memory volumePerAvgLiquiditys
    );

  /// @notice Returns average volatility in the range from time-WINDOW to time
  /// @param time The current block.timestamp
  /// @param tick The current tick
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param liquidity The current in-range pool liquidity
  /// @return TWVolatilityAverage The average volatility in the recent range
  /// @return TWVolumePerLiqAverage The average volume per liquidity in the recent range
  function getAverages(
    uint32 time,
    int24 tick,
    uint16 index,
    uint128 liquidity
  ) external view returns (uint112 TWVolatilityAverage, uint256 TWVolumePerLiqAverage);

  /// @notice Writes an dataStorage timepoint to the array
  /// @dev Writable at most once per block. Index represents the most recently written element. index must be tracked externally.
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param blockTimestamp The timestamp of the new timepoint
  /// @param tick The active tick at the time of the new timepoint
  /// @param liquidity The total in-range liquidity at the time of the new timepoint
  /// @param volumePerLiquidity The gmean(volumes)/liquidity at the time of the new timepoint
  /// @return indexUpdated The new index of the most recently written element in the dataStorage array
  function write(
    uint16 index,
    uint32 blockTimestamp,
    int24 tick,
    uint128 liquidity,
    uint128 volumePerLiquidity
  ) external returns (uint16 indexUpdated);

  /// @notice Changes fee configuration for the pool
  function changeFeeConfiguration(AdaptiveFee.Configuration calldata feeConfig) external;

  /// @notice Calculates gmean(volume/liquidity) for block
  /// @param liquidity The current in-range pool liquidity
  /// @param amount0 Total amount of swapped token0
  /// @param amount1 Total amount of swapped token1
  /// @return volumePerLiquidity gmean(volume/liquidity) capped by 100000 << 64
  function calculateVolumePerLiquidity(uint128 liquidity, int256 amount0, int256 amount1) external pure returns (uint128 volumePerLiquidity);

  /// @return windowLength Length of window used to calculate averages
  function window() external view returns (uint32 windowLength);

  /// @notice Calculates fee based on combination of sigmoids
  /// @param time The current block.timestamp
  /// @param tick The current tick
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param liquidity The current in-range pool liquidity
  /// @return fee The fee in hundredths of a bip, i.e. 1e-6
  function getFee(uint32 time, int24 tick, uint16 index, uint128 liquidity) external view returns (uint16 fee);
}
          

@openzeppelin/contracts/interfaces/IERC1967.sol

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

pragma solidity ^0.8.0;

/**
 * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
 *
 * _Available since v4.8.3._
 */
interface IERC1967 {
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);
}
          

@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol

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

/// @title Events emitted by a pool
/// @notice Contains all events emitted by the pool
interface IUniswapV3PoolEvents {
    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool
    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize
    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96
    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool
    event Initialize(uint160 sqrtPriceX96, int24 tick);

    /// @notice Emitted when liquidity is minted for a given position
    /// @param sender The address that minted the liquidity
    /// @param owner The owner of the position and recipient of any minted liquidity
    /// @param tickLower The lower tick of the position
    /// @param tickUpper The upper tick of the position
    /// @param amount The amount of liquidity minted to the position range
    /// @param amount0 How much token0 was required for the minted liquidity
    /// @param amount1 How much token1 was required for the minted liquidity
    event Mint(
        address sender,
        address indexed owner,
        int24 indexed tickLower,
        int24 indexed tickUpper,
        uint128 amount,
        uint256 amount0,
        uint256 amount1
    );

    /// @notice Emitted when fees are collected by the owner of a position
    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees
    /// @param owner The owner of the position for which fees are collected
    /// @param tickLower The lower tick of the position
    /// @param tickUpper The upper tick of the position
    /// @param amount0 The amount of token0 fees collected
    /// @param amount1 The amount of token1 fees collected
    event Collect(
        address indexed owner,
        address recipient,
        int24 indexed tickLower,
        int24 indexed tickUpper,
        uint128 amount0,
        uint128 amount1
    );

    /// @notice Emitted when a position's liquidity is removed
    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect
    /// @param owner The owner of the position for which liquidity is removed
    /// @param tickLower The lower tick of the position
    /// @param tickUpper The upper tick of the position
    /// @param amount The amount of liquidity to remove
    /// @param amount0 The amount of token0 withdrawn
    /// @param amount1 The amount of token1 withdrawn
    event Burn(
        address indexed owner,
        int24 indexed tickLower,
        int24 indexed tickUpper,
        uint128 amount,
        uint256 amount0,
        uint256 amount1
    );

    /// @notice Emitted by the pool for any swaps between token0 and token1
    /// @param sender The address that initiated the swap call, and that received the callback
    /// @param recipient The address that received the output of the swap
    /// @param amount0 The delta of the token0 balance of the pool
    /// @param amount1 The delta of the token1 balance of the pool
    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96
    /// @param liquidity The liquidity of the pool after the swap
    /// @param tick The log base 1.0001 of price of the pool after the swap
    event Swap(
        address indexed sender,
        address indexed recipient,
        int256 amount0,
        int256 amount1,
        uint160 sqrtPriceX96,
        uint128 liquidity,
        int24 tick
    );

    /// @notice Emitted by the pool for any flashes of token0/token1
    /// @param sender The address that initiated the swap call, and that received the callback
    /// @param recipient The address that received the tokens from flash
    /// @param amount0 The amount of token0 that was flashed
    /// @param amount1 The amount of token1 that was flashed
    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee
    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee
    event Flash(
        address indexed sender,
        address indexed recipient,
        uint256 amount0,
        uint256 amount1,
        uint256 paid0,
        uint256 paid1
    );

    /// @notice Emitted by the pool for increases to the number of observations that can be stored
    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index
    /// just before a mint/swap/burn.
    /// @param observationCardinalityNextOld The previous value of the next observation cardinality
    /// @param observationCardinalityNextNew The updated value of the next observation cardinality
    event IncreaseObservationCardinalityNext(
        uint16 observationCardinalityNextOld,
        uint16 observationCardinalityNextNew
    );

    /// @notice Emitted when the protocol fee is changed by the pool
    /// @param feeProtocol0Old The previous value of the token0 protocol fee
    /// @param feeProtocol1Old The previous value of the token1 protocol fee
    /// @param feeProtocol0New The updated value of the token0 protocol fee
    /// @param feeProtocol1New The updated value of the token1 protocol fee
    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);

    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner
    /// @param sender The address that collects the protocol fees
    /// @param recipient The address that receives the collected protocol fees
    /// @param amount0 The amount of token0 protocol fees that is withdrawn
    /// @param amount0 The amount of token1 protocol fees that is withdrawn
    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);
}
          

@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "../IERC721Upgradeable.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721EnumerableUpgradeable is IERC721Upgradeable {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}
          

@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControlUpgradeable {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}
          

contracts/VaultRegistry/BeaconManager.sol

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

import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";

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

/**
 * @dev contract managing beacon data for all vaults
 */
abstract contract BeaconManager is
    OwnableUpgradeable,
    AccessControlUpgradeable
{
    /// @dev Beacon registeration event
    /// @param _name The name of the beacon getting registered
    /// @param _address The implementation address that this beacon will point to
    /// @param _ipfsHash IPFS hash for the config of this beacon
    event BeaconRegistered(string _name, address _address, string _ipfsHash);

    /// @dev Beacon config updation event
    /// @param _name The name of the beacon getting registered
    /// @param _ipfsHash updated IPFS hash for the config of this beacon
    event BeaconConfigUpdated(string _name, string _ipfsHash);

    /// @dev Beacon deregisteration event
    /// @param _name The name of the beacon getting registered
    event BeaconDeregistered(string _name);

    // Beacon creator, used to create and register new beacons for new vault types
    bytes32 internal constant BEACON_CREATOR = keccak256("BEACON_CREATOR");

    // Mapping beaconName => beacon address. Used to find the beacon for a given vault type.
    mapping(string => address) public beaconAddresses;

    // Mapping address => beaconName. Used to find what vault type a given beacon or vault is.
    // Note that beaconTypes applies to both beacons and vaults.
    mapping(address => string) public beaconTypes;

    /// @dev Registers a beacon associated with a new vault type
    /// @param _name The name of the vault type this beacon will be using
    /// @param _address The address of the beacon contract
    /// @param _ipfsConfigForBeacon IPFS hash for the config of this beacon
    /// @dev This function is only available to the beacon creator
    /// @dev Registers any address as a new beacon. Useful for alternative beacon types (i.e. a contract which will use a proxy structure other than the standard beacon).
    function registerBeacon(
        string calldata _name,
        address _address,
        string memory _ipfsConfigForBeacon
    ) public onlyRole(BEACON_CREATOR) {
        // Ensure no beacon exists with given name, so that this function can't edit an existing beacon address
        require(beaconAddresses[_name] == address(0), "Beacon already exists");

        // Register beacon
        beaconAddresses[_name] = _address;
        beaconTypes[_address] = _name;
        emit BeaconRegistered(_name, _address, _ipfsConfigForBeacon);
    }

    /// @dev Deploy new beacon for a new vault type AND register it
    /// @param _address The address of the implementation for the beacon
    /// @param _name The name of the beacon (identifier)
    /// @param _ipfsConfigForBeacon IPFS hash for the config of this beacon
    /// note that the contract registered as a beacon should not be used as a vault, to avoid confusion.
    function deployAndRegisterBeacon(
        address _address,
        string calldata _name,
        string calldata _ipfsConfigForBeacon
    ) external onlyRole(BEACON_CREATOR) returns (address) {
        // Ensure no beacon exists with given name, so that this function can't edit an existing beacon address
        require(beaconAddresses[_name] == address(0), "Beacon already exists");

        // Deploy new beacon instance
        Beacon newBeacon = new Beacon(_address);

        // Transfer ownership to governance
        newBeacon.transferOwnership(owner());

        // Record beacon address at beacon name, so that new vaults can be created with this beacon by passing in beacon name
        beaconAddresses[_name] = address(newBeacon);
        beaconTypes[address(newBeacon)] = _name;

        emit BeaconRegistered(_name, _address, _ipfsConfigForBeacon);
        return address(newBeacon);
    }

    /// @dev Updates the ipfs link storing the beaconConfig
    /// @param _name The name of the beacon (identifier)
    /// @param _newIPFSConfigForBeacon IPFS hash for the config of this beacon
    function updateBeaconConfig(
        string calldata _name,
        string calldata _newIPFSConfigForBeacon
    ) external onlyRole(BEACON_CREATOR) {
        require(beaconAddresses[_name] != address(0), "Beacon does not exist");
        emit BeaconConfigUpdated(_name, _newIPFSConfigForBeacon);
    }

    /// @dev Removes a beacon associated with a vault type
    /// @param _name The name of the beacon (identifier)
    /// @dev This will stop the creation of more vaults of the type provided
    function deregisterBeacon(string calldata _name)
        external
        onlyRole(BEACON_CREATOR)
    {
        emit BeaconDeregistered(_name);
        delete beaconAddresses[_name];
    }
}
          

@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolDerivedState.sol

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

/**
 * @title Pool state that is not stored
 * @notice Contains view functions to provide information about the pool that is computed rather than stored on the
 * blockchain. The functions here may have variable gas costs.
 * @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
 * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
 */
interface IAlgebraPoolDerivedState {
  /**
   * @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp
   * @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing
   * the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,
   * you must call it with secondsAgos = [3600, 0].
   * @dev The time weighted average tick represents the geometric time weighted average price of the pool, in
   * log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.
   * @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned
   * @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp
   * @return secondsPerLiquidityCumulatives Cumulative seconds per liquidity-in-range value as of each `secondsAgos`
   * from the current block timestamp
   * @return volatilityCumulatives Cumulative standard deviation as of each `secondsAgos`
   * @return volumePerAvgLiquiditys Cumulative swap volume per liquidity as of each `secondsAgos`
   */
  function getTimepoints(uint32[] calldata secondsAgos)
    external
    view
    returns (
      int56[] memory tickCumulatives,
      uint160[] memory secondsPerLiquidityCumulatives,
      uint112[] memory volatilityCumulatives,
      uint256[] memory volumePerAvgLiquiditys
    );

  /**
   * @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range
   * @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.
   * I.e., snapshots cannot be compared if a position is not held for the entire period between when the first
   * snapshot is taken and the second snapshot is taken.
   * @param bottomTick The lower tick of the range
   * @param topTick The upper tick of the range
   * @return innerTickCumulative The snapshot of the tick accumulator for the range
   * @return innerSecondsSpentPerLiquidity The snapshot of seconds per liquidity for the range
   * @return innerSecondsSpent The snapshot of the number of seconds during which the price was in this range
   */
  function getInnerCumulatives(int24 bottomTick, int24 topTick)
    external
    view
    returns (
      int56 innerTickCumulative,
      uint160 innerSecondsSpentPerLiquidity,
      uint32 innerSecondsSpent
    );
}
          

@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeaconUpgradeable {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}
          

contracts/interfaces/IBeaconInterface.sol

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

interface IBeaconInterface {
    /// @dev Event emitted when the address that the beacon is pointing to is upgraded.
    /// @return address of the new implementation.
    event Upgraded(address indexed newImplementation);

    function implementation() external view returns (address);

    function upgradeImplementationTo(address newImplementation) external;
}
          

@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol

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

/// @title Permissionless pool actions
/// @notice Contains pool methods that can be called by anyone
interface IUniswapV3PoolActions {
    /// @notice Sets the initial price for the pool
    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value
    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96
    function initialize(uint160 sqrtPriceX96) external;

    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position
    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback
    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends
    /// on tickLower, tickUpper, the amount of liquidity, and the current price.
    /// @param recipient The address for which the liquidity will be created
    /// @param tickLower The lower tick of the position in which to add liquidity
    /// @param tickUpper The upper tick of the position in which to add liquidity
    /// @param amount The amount of liquidity to mint
    /// @param data Any data that should be passed through to the callback
    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback
    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback
    function mint(
        address recipient,
        int24 tickLower,
        int24 tickUpper,
        uint128 amount,
        bytes calldata data
    ) external returns (uint256 amount0, uint256 amount1);

    /// @notice Collects tokens owed to a position
    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.
    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or
    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the
    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.
    /// @param recipient The address which should receive the fees collected
    /// @param tickLower The lower tick of the position for which to collect fees
    /// @param tickUpper The upper tick of the position for which to collect fees
    /// @param amount0Requested How much token0 should be withdrawn from the fees owed
    /// @param amount1Requested How much token1 should be withdrawn from the fees owed
    /// @return amount0 The amount of fees collected in token0
    /// @return amount1 The amount of fees collected in token1
    function collect(
        address recipient,
        int24 tickLower,
        int24 tickUpper,
        uint128 amount0Requested,
        uint128 amount1Requested
    ) external returns (uint128 amount0, uint128 amount1);

    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position
    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0
    /// @dev Fees must be collected separately via a call to #collect
    /// @param tickLower The lower tick of the position for which to burn liquidity
    /// @param tickUpper The upper tick of the position for which to burn liquidity
    /// @param amount How much liquidity to burn
    /// @return amount0 The amount of token0 sent to the recipient
    /// @return amount1 The amount of token1 sent to the recipient
    function burn(
        int24 tickLower,
        int24 tickUpper,
        uint128 amount
    ) external returns (uint256 amount0, uint256 amount1);

    /// @notice Swap token0 for token1, or token1 for token0
    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback
    /// @param recipient The address to receive the output of the swap
    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0
    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this
    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap
    /// @param data Any data to be passed through to the callback
    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive
    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 sqrtPriceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);

    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback
    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback
    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling
    /// with 0 amount{0,1} and sending the donation amount(s) from the callback
    /// @param recipient The address which will receive the token0 and token1 amounts
    /// @param amount0 The amount of token0 to send
    /// @param amount1 The amount of token1 to send
    /// @param data Any data to be passed through to the callback
    function flash(
        address recipient,
        uint256 amount0,
        uint256 amount1,
        bytes calldata data
    ) external;

    /// @notice Increase the maximum number of price and liquidity observations that this pool will store
    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to
    /// the input observationCardinalityNext.
    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store
    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;
}
          

@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol

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

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
 */
library StorageSlotUpgradeable {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly {
            r.slot := slot
        }
    }
}
          

@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolActions.sol

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

/// @title Permissionless pool actions
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraPoolActions {
  /**
   * @notice Sets the initial price for the pool
   * @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value
   * @param price the initial sqrt price of the pool as a Q64.96
   */
  function initialize(uint160 price) external;

  /**
   * @notice Adds liquidity for the given recipient/bottomTick/topTick position
   * @dev The caller of this method receives a callback in the form of IAlgebraMintCallback# AlgebraMintCallback
   * in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends
   * on bottomTick, topTick, the amount of liquidity, and the current price.
   * @param sender The address which will receive potential surplus of paid tokens
   * @param recipient The address for which the liquidity will be created
   * @param bottomTick The lower tick of the position in which to add liquidity
   * @param topTick The upper tick of the position in which to add liquidity
   * @param amount The desired amount of liquidity to mint
   * @param data Any data that should be passed through to the callback
   * @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback
   * @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback
   * @return liquidityActual The actual minted amount of liquidity
   */
  function mint(
    address sender,
    address recipient,
    int24 bottomTick,
    int24 topTick,
    uint128 amount,
    bytes calldata data
  )
    external
    returns (
      uint256 amount0,
      uint256 amount1,
      uint128 liquidityActual
    );

  /**
   * @notice Collects tokens owed to a position
   * @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.
   * Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or
   * amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the
   * actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.
   * @param recipient The address which should receive the fees collected
   * @param bottomTick The lower tick of the position for which to collect fees
   * @param topTick The upper tick of the position for which to collect fees
   * @param amount0Requested How much token0 should be withdrawn from the fees owed
   * @param amount1Requested How much token1 should be withdrawn from the fees owed
   * @return amount0 The amount of fees collected in token0
   * @return amount1 The amount of fees collected in token1
   */
  function collect(
    address recipient,
    int24 bottomTick,
    int24 topTick,
    uint128 amount0Requested,
    uint128 amount1Requested
  ) external returns (uint128 amount0, uint128 amount1);

  /**
   * @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position
   * @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0
   * @dev Fees must be collected separately via a call to #collect
   * @param bottomTick The lower tick of the position for which to burn liquidity
   * @param topTick The upper tick of the position for which to burn liquidity
   * @param amount How much liquidity to burn
   * @return amount0 The amount of token0 sent to the recipient
   * @return amount1 The amount of token1 sent to the recipient
   */
  function burn(
    int24 bottomTick,
    int24 topTick,
    uint128 amount
  ) external returns (uint256 amount0, uint256 amount1);

  /**
   * @notice Swap token0 for token1, or token1 for token0
   * @dev The caller of this method receives a callback in the form of IAlgebraSwapCallback# AlgebraSwapCallback
   * @param recipient The address to receive the output of the swap
   * @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0
   * @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
   * @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this
   * value after the swap. If one for zero, the price cannot be greater than this value after the swap
   * @param data Any data to be passed through to the callback. If using the Router it should contain
   * SwapRouter#SwapCallbackData
   * @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive
   * @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive
   */
  function swap(
    address recipient,
    bool zeroToOne,
    int256 amountSpecified,
    uint160 limitSqrtPrice,
    bytes calldata data
  ) external returns (int256 amount0, int256 amount1);

  /**
   * @notice Swap token0 for token1, or token1 for token0 (tokens that have fee on transfer)
   * @dev The caller of this method receives a callback in the form of I AlgebraSwapCallback# AlgebraSwapCallback
   * @param sender The address called this function (Comes from the Router)
   * @param recipient The address to receive the output of the swap
   * @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0
   * @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
   * @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this
   * value after the swap. If one for zero, the price cannot be greater than this value after the swap
   * @param data Any data to be passed through to the callback. If using the Router it should contain
   * SwapRouter#SwapCallbackData
   * @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive
   * @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive
   */
  function swapSupportingFeeOnInputTokens(
    address sender,
    address recipient,
    bool zeroToOne,
    int256 amountSpecified,
    uint160 limitSqrtPrice,
    bytes calldata data
  ) external returns (int256 amount0, int256 amount1);

  /**
   * @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback
   * @dev The caller of this method receives a callback in the form of IAlgebraFlashCallback# AlgebraFlashCallback
   * @dev All excess tokens paid in the callback are distributed to liquidity providers as an additional fee. So this method can be used
   * to donate underlying tokens to currently in-range liquidity providers by calling with 0 amount{0,1} and sending
   * the donation amount(s) from the callback
   * @param recipient The address which will receive the token0 and token1 amounts
   * @param amount0 The amount of token0 to send
   * @param amount1 The amount of token1 to send
   * @param data Any data to be passed through to the callback
   */
  function flash(
    address recipient,
    uint256 amount0,
    uint256 amount1,
    bytes calldata data
  ) external;
}
          

contracts/interfaces/IImplementation.sol

// SPDX-License-Identifier: BSL-1.1

pragma solidity 0.8.12;

interface IImplementation {
    /// @dev To initialize a vault.
    function initialize(
        address _vaultManager,
        address _orchestrator,
        address _steer,
        bytes calldata _params
    ) external;
}
          

@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol

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

pragma solidity ^0.8.0;

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

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since 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.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

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

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

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

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

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

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

@openzeppelin/contracts/interfaces/draft-IERC1822.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822Proxiable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}
          

@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol

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

import './pool/IUniswapV3PoolImmutables.sol';
import './pool/IUniswapV3PoolState.sol';
import './pool/IUniswapV3PoolDerivedState.sol';
import './pool/IUniswapV3PoolActions.sol';
import './pool/IUniswapV3PoolOwnerActions.sol';
import './pool/IUniswapV3PoolEvents.sol';

/// @title The interface for a Uniswap V3 Pool
/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform
/// to the ERC20 specification
/// @dev The pool interface is broken up into many smaller pieces
interface IUniswapV3Pool is
    IUniswapV3PoolImmutables,
    IUniswapV3PoolState,
    IUniswapV3PoolDerivedState,
    IUniswapV3PoolActions,
    IUniswapV3PoolOwnerActions,
    IUniswapV3PoolEvents
{

}
          

@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol

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

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library StringsUpgradeable {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}
          

@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol

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

pragma solidity ^0.8.2;

import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 */
abstract contract ERC1967Upgrade is IERC1967 {
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            Address.isContract(IBeacon(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        }
    }
}
          

@openzeppelin/contracts/utils/StorageSlot.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}
          

@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol

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

@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal onlyInitializing {
        __Context_init_unchained();
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal onlyInitializing {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
    uint256[49] private __gap;
}
          

contracts/Beacon.sol

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

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./interfaces/IBeaconInterface.sol";

contract Beacon is IBeaconInterface, Ownable {
    // Storage

    /// @dev Current implementation address for this beacon,
    ///      i.e. the address which all beacon proxies will delegatecall to.
    address public implementation;

    // Constructor

    /// @param implementationAddress The address all beaconProxies will delegatecall to.
    constructor(address implementationAddress) {
        _setImplementationAddress(implementationAddress);
    }

    /// @dev Upgrades the implementation address of the beacon or the address that the beacon points to.
    /// @param newImplementation Address of implementation that the beacon should be upgraded to.
    function upgradeImplementationTo(address newImplementation)
        public
        virtual
        onlyOwner
    {
        _setImplementationAddress(newImplementation);
    }

    function _setImplementationAddress(address newImplementation) internal {
        require(
            Address.isContract(newImplementation),
            "UpgradeableBeacon: implementation is not a contract"
        );
        implementation = newImplementation;
        emit Upgraded(newImplementation);
    }
}
          

@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol

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

/// @title Permissioned pool actions
/// @notice Contains pool methods that may only be called by the factory owner
interface IUniswapV3PoolOwnerActions {
    /// @notice Set the denominator of the protocol's % share of the fees
    /// @param feeProtocol0 new protocol fee for token0 of the pool
    /// @param feeProtocol1 new protocol fee for token1 of the pool
    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;

    /// @notice Collect the protocol fee accrued to the pool
    /// @param recipient The address to which collected protocol fees should be sent
    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1
    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0
    /// @return amount0 The protocol fee collected in token0
    /// @return amount1 The protocol fee collected in token1
    function collectProtocol(
        address recipient,
        uint128 amount0Requested,
        uint128 amount1Requested
    ) external returns (uint128 amount0, uint128 amount1);
}
          

@cryptoalgebra/core/contracts/libraries/AdaptiveFee.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.7.6;

import "./Constants.sol";

/// @title AdaptiveFee
/// @notice Calculates fee based on combination of sigmoids
library AdaptiveFee {
    // alpha1 + alpha2 + baseFee must be <= type(uint16).max
    struct Configuration {
        uint16 alpha1; // max value of the first sigmoid
        uint16 alpha2; // max value of the second sigmoid
        uint32 beta1; // shift along the x-axis for the first sigmoid
        uint32 beta2; // shift along the x-axis for the second sigmoid
        uint16 gamma1; // horizontal stretch factor for the first sigmoid
        uint16 gamma2; // horizontal stretch factor for the second sigmoid
        uint32 volumeBeta; // shift along the x-axis for the outer volume-sigmoid
        uint16 volumeGamma; // horizontal stretch factor the outer volume-sigmoid
        uint16 baseFee; // minimum possible fee
    }

    /// @notice Calculates fee based on formula:
    /// baseFee + sigmoidVolume(sigmoid1(volatility, volumePerLiquidity) + sigmoid2(volatility, volumePerLiquidity))
    /// maximum value capped by baseFee + alpha1 + alpha2
    function getFee(
        uint88 volatility,
        uint256 volumePerLiquidity,
        Configuration memory config
    ) internal pure returns (uint16 fee) {
        uint256 sumOfSigmoids = sigmoid(
            volatility,
            config.gamma1,
            config.alpha1,
            config.beta1
        ) + sigmoid(volatility, config.gamma2, config.alpha2, config.beta2);

        if (sumOfSigmoids > type(uint16).max) {
            // should be impossible, just in case
            sumOfSigmoids = type(uint16).max;
        }

        return
            uint16(
                config.baseFee +
                    sigmoid(
                        volumePerLiquidity,
                        config.volumeGamma,
                        uint16(sumOfSigmoids),
                        config.volumeBeta
                    )
            ); // safe since alpha1 + alpha2 + baseFee _must_ be <= type(uint16).max
    }

    /// @notice calculates α / (1 + e^( (β-x) / γ))
    /// that is a sigmoid with a maximum value of α, x-shifted by β, and stretched by γ
    /// @dev returns uint256 for fuzzy testing. Guaranteed that the result is not greater than alpha
    function sigmoid(
        uint256 x,
        uint16 g,
        uint16 alpha,
        uint256 beta
    ) internal pure returns (uint256 res) {
        if (x > beta) {
            x = x - beta;
            if (x >= 6 * uint256(g)) return alpha; // so x < 19 bits
            uint256 g8 = uint256(g) ** 8; // < 128 bits (8*16)
            uint256 ex = exp(x, g, g8); // < 155 bits
            res = (alpha * ex) / (g8 + ex); // in worst case: (16 + 155 bits) / 155 bits
            // so res <= alpha
        } else {
            x = beta - x;
            if (x >= 6 * uint256(g)) return 0; // so x < 19 bits
            uint256 g8 = uint256(g) ** 8; // < 128 bits (8*16)
            uint256 ex = g8 + exp(x, g, g8); // < 156 bits
            res = (alpha * g8) / ex; // in worst case: (16 + 128 bits) / 156 bits
            // g8 <= ex, so res <= alpha
        }
    }

    /// @notice calculates e^(x/g) * g^8 in a series, since (around zero):
    /// e^x = 1 + x + x^2/2 + ... + x^n/n! + ...
    /// e^(x/g) = 1 + x/g + x^2/(2*g^2) + ... + x^(n)/(g^n * n!) + ...
    function exp(
        uint256 x,
        uint16 g,
        uint256 gHighestDegree
    ) internal pure returns (uint256 res) {
        // calculating:
        // g**8 + x * g**7 + (x**2 * g**6) / 2 + (x**3 * g**5) / 6 + (x**4 * g**4) / 24 + (x**5 * g**3) / 120 + (x**6 * g^2) / 720 + x**7 * g / 5040 + x**8 / 40320

        // x**8 < 152 bits (19*8) and g**8 < 128 bits (8*16)
        // so each summand < 152 bits and res < 155 bits
        uint256 xLowestDegree = x;
        res = gHighestDegree; // g**8

        gHighestDegree /= g; // g**7
        res += xLowestDegree * gHighestDegree;

        gHighestDegree /= g; // g**6
        xLowestDegree *= x; // x**2
        res += (xLowestDegree * gHighestDegree) / 2;

        gHighestDegree /= g; // g**5
        xLowestDegree *= x; // x**3
        res += (xLowestDegree * gHighestDegree) / 6;

        gHighestDegree /= g; // g**4
        xLowestDegree *= x; // x**4
        res += (xLowestDegree * gHighestDegree) / 24;

        gHighestDegree /= g; // g**3
        xLowestDegree *= x; // x**5
        res += (xLowestDegree * gHighestDegree) / 120;

        gHighestDegree /= g; // g**2
        xLowestDegree *= x; // x**6
        res += (xLowestDegree * gHighestDegree) / 720;

        xLowestDegree *= x; // x**7
        res += (xLowestDegree * g) / 5040 + (xLowestDegree * x) / (40320);
    }
}
          

@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721Upgradeable is IERC165Upgradeable {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}
          

@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol

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

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

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

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

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

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

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

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

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

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

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

@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolPermissionedActions.sol

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

/**
 * @title Permissioned pool actions
 * @notice Contains pool methods that may only be called by the factory owner or tokenomics
 * @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
 * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
 */
interface IAlgebraPoolPermissionedActions {
  /**
   * @notice Set the community's % share of the fees. Cannot exceed 25% (250)
   * @param communityFee0 new community fee percent for token0 of the pool in thousandths (1e-3)
   * @param communityFee1 new community fee percent for token1 of the pool in thousandths (1e-3)
   */
  function setCommunityFee(uint8 communityFee0, uint8 communityFee1) external;

  /// @notice Set the new tick spacing values. Only factory owner
  /// @param newTickSpacing The new tick spacing value
  function setTickSpacing(int24 newTickSpacing) external;

  /**
   * @notice Sets an active incentive
   * @param virtualPoolAddress The address of a virtual pool associated with the incentive
   */
  function setIncentive(address virtualPoolAddress) external;

  /**
   * @notice Sets new lock time for added liquidity
   * @param newLiquidityCooldown The time in seconds
   */
  function setLiquidityCooldown(uint32 newLiquidityCooldown) external;
}
          

contracts/interfaces/IOrchestrator.sol

// SPDX-License-Identifier: BUSL-1.1

pragma solidity 0.8.12;

/**
 * @dev Interface of the Orchestrator.
 */
interface IOrchestrator {
    enum ActionState {
        PENDING,
        COMPLETED
    }

    /**
     * @dev MUST trigger when actions are executed.
     * @param actionHash: keccak256(targetAddress, jobEpoch, calldatas) used to identify this action
     * @param from: the address of the keeper that executed this action
     * @param rewardPerAction: SteerToken reward for this action, to be supplied to operator nodes.
     */
    event ActionExecuted(
        bytes32 indexed actionHash,
        address from,
        uint256 rewardPerAction
    );
    event ActionFailed(bytes32 indexed actionHash);
    event Vote(
        bytes32 indexed actionHash,
        address indexed from,
        bool approved
    );

    // If an action is approved by >= approvalThresholdPercent members, it is approved
    function actionThresholdPercent() external view returns (uint256);

    // Address of GasVault, which is the contract used to recompense keepers for gas they spent executing actions
    function gasVault() external view returns (address);

    // Address of Keeper Registry, which handles keeper verification
    function keeperRegistry() external view returns (address);

    // Operator node action participation reward. Currently unused.
    function rewardPerAction() external view returns (uint256);

    /*
        bytes32 is hash of action. Calculated using keccak256(abi.encode(targetAddress, jobEpoch, calldatas))

        Action approval meaning:
        0: Pending
        1: Approved
        Both votes and overall approval status follow this standard.
    */
    function actions(bytes32) external view returns (ActionState);

    /*  
        actionHash => uint256 where each bit represents one keeper vote.
    */
    function voteBitmaps(bytes32) external view returns (uint256);

    /**
     * @dev initialize the Orchestrator
     * @param _keeperRegistry address of the keeper registry
     * @param _rewardPerAction is # of SteerToken to give to operator nodes for each completed action (currently unused)
     */
    function initialize(address _keeperRegistry, uint256 _rewardPerAction)
        external;

    /**
     * @dev allows owner to set/update gas vault address. Mainly used to resolve mutual dependency.
     */
    function setGasVault(address _gasVault) external;

    /**
     * @dev set the reward given to operator nodes for their participation in a strategy calculation
     * @param _rewardPerAction is amount of steer token to be earned as a reward, per participating operator node per action.
     */
    function setRewardPerAction(uint256 _rewardPerAction) external;

    /**
     * @dev vote (if you are a keeper) on a given action proposal
     * @param actionHash is the hash of the action to be voted on
     * @param vote is the vote to be cast. false: reject, true: approve. false only has an effect if the keeper previously voted true. It resets their vote to false.
     */
    function voteOnAction(bytes32 actionHash, bool vote) external;

    /**
     * @dev Returns true if an action with given `actionId` is approved by all existing members of the group.
     * It’s up to the contract creators to decide if this method should look at majority votes (based on ownership)
     * or if it should ask consent of all the users irrespective of their ownerships.
     */
    function actionApprovalStatus(bytes32 actionHash)
        external
        view
        returns (bool);

    /**
     * @dev Executes the action referenced by the given `actionId` as long as it is approved actionThresholdPercent of group.
     * The executeAction executes all methods as part of given action in an atomic way (either all should succeed or none should succeed).
     * Once executed, the action should be set as executed (state=3) so that it cannot be executed again.

     * @param targetAddress is the address which will be receiving the action's calls.
     * @param jobEpoch is the job epoch of this action.
     * @param calldatas is the COMPLETE calldata of each method to be called
     * note that the hash is created using the sliced calldata, but here it must be complete or the method will revert.
     * @param timeIndependentLengths--For each calldata, the number of bytes that is NOT time-sensitive. If no calldatas are time-sensitive, just pass an empty array.
     * @param jobHash is the identifier for the job this action is related to. This is used for DynamicJobs to identify separate jobs to the subgraph.
     * @return actionState corresponding to post-execution action state. Pending if execution failed, Completed if execution succeeded.
     */
    function executeAction(
        address targetAddress,
        uint256 jobEpoch,
        bytes[] calldata calldatas,
        uint256[] calldata timeIndependentLengths,
        bytes32 jobHash
    ) external returns (ActionState);
}
          

@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol

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

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

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

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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
    uint256[50] private __gap;
}
          

contracts/VaultRegistry/InterfaceManager.sol

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

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

abstract contract InterfaceManager is BeaconManager {
    bytes32 internal constant INTERFACE_EDITOR = keccak256("INTERFACE_EDITOR");

    error IncorrectArrayLengths(
        uint256 selectorLength,
        uint256 isImplementedLength
    );

    /**
     * @dev mapping beacon name => function selector => isImplemented
     */
    mapping(string => mapping(bytes4 => bool)) public interfaceImplementations;

    /**
     * @dev add interface info to given beacon
     */
    function updateInterfaceImplementations(
        string calldata beaconName,
        bytes4[] calldata selectors,
        bool[] calldata isImplemented
    ) external onlyRole(INTERFACE_EDITOR) {
        // Require that array lengths match
        if (selectors.length != isImplemented.length) {
            revert IncorrectArrayLengths(
                selectors.length,
                isImplemented.length
            );
        }

        // Set
        for (uint256 i; i != selectors.length; ++i) {
            interfaceImplementations[beaconName][selectors[i]] = isImplemented[
                i
            ];
        }
    }

    /**
     * @dev check whether msg.sender supports a given interface id. Used to support ERC165 from a central location.
     * @param interfaceId the interface id to check
     */
    function doISupportInterface(bytes4 interfaceId)
        external
        view
        returns (bool)
    {
        string memory beaconOfSender = beaconTypes[msg.sender];
        return interfaceImplementations[beaconOfSender][interfaceId];
    }
}
          

@cryptoalgebra/core/contracts/libraries/Constants.sol

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

library Constants {
    uint8 internal constant RESOLUTION = 96;
    uint256 internal constant Q96 = 0x1000000000000000000000000;
    uint256 internal constant Q128 = 0x100000000000000000000000000000000;
    // fee value in hundredths of a bip, i.e. 1e-6
    uint16 internal constant BASE_FEE = 100;
    int24 internal constant MAX_TICK_SPACING = 500;

    // max(uint128) / (MAX_TICK - MIN_TICK)
    uint128 internal constant MAX_LIQUIDITY_PER_TICK =
        191757638537527648490752896198553;

    uint32 internal constant MAX_LIQUIDITY_COOLDOWN = 1 days;
    uint8 internal constant MAX_COMMUNITY_FEE = 250;
    uint256 internal constant COMMUNITY_FEE_DENOMINATOR = 1000;
}
          

@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol

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

/// @title Pool state that never changes
/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values
interface IUniswapV3PoolImmutables {
    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface
    /// @return The contract address
    function factory() external view returns (address);

    /// @notice The first of the two tokens of the pool, sorted by address
    /// @return The token contract address
    function token0() external view returns (address);

    /// @notice The second of the two tokens of the pool, sorted by address
    /// @return The token contract address
    function token1() external view returns (address);

    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
    /// @return The fee
    function fee() external view returns (uint24);

    /// @notice The pool tick spacing
    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive
    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...
    /// This value is an int24 to avoid casting even though it is always positive.
    /// @return The tick spacing
    function tickSpacing() external view returns (int24);

    /// @notice The maximum amount of position liquidity that can use any tick in the range
    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and
    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool
    /// @return The max amount of liquidity per tick
    function maxLiquidityPerTick() external view returns (uint128);
}
          

@openzeppelin/contracts-upgradeable/proxy/ClonesUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
 * deploying minimal proxy contracts, also known as "clones".
 *
 * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
 * > a minimal bytecode implementation that delegates all calls to a known, fixed address.
 *
 * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
 * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
 * deterministic method.
 *
 * _Available since v3.4._
 */
library ClonesUpgradeable {
    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create(0, ptr, 0x37)
        }
        require(instance != address(0), "ERC1167: create failed");
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy
     * the clone. Using the same `implementation` and `salt` multiple time will revert, since
     * the clones cannot be deployed twice at the same address.
     */
    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create2(0, ptr, 0x37, salt)
        }
        require(instance != address(0), "ERC1167: create2 failed");
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
            mstore(add(ptr, 0x38), shl(0x60, deployer))
            mstore(add(ptr, 0x4c), salt)
            mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
            predicted := keccak256(add(ptr, 0x37), 0x55)
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(address implementation, bytes32 salt)
        internal
        view
        returns (address predicted)
    {
        return predictDeterministicAddress(implementation, salt, address(this));
    }
}
          

@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol

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

/// @title Pool state that can change
/// @notice These methods compose the pool's state, and can change with any frequency including multiple times
/// per transaction
interface IUniswapV3PoolState {
    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas
    /// when accessed externally.
    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value
    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.
    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
    /// boundary.
    /// observationIndex The index of the last oracle observation that was written,
    /// observationCardinality The current maximum number of observations stored in the pool,
    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.
    /// feeProtocol The protocol fee for both tokens of the pool.
    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0
    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.
    /// unlocked Whether the pool is currently locked to reentrancy
    function slot0()
        external
        view
        returns (
            uint160 sqrtPriceX96,
            int24 tick,
            uint16 observationIndex,
            uint16 observationCardinality,
            uint16 observationCardinalityNext,
            uint8 feeProtocol,
            bool unlocked
        );

    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool
    /// @dev This value can overflow the uint256
    function feeGrowthGlobal0X128() external view returns (uint256);

    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool
    /// @dev This value can overflow the uint256
    function feeGrowthGlobal1X128() external view returns (uint256);

    /// @notice The amounts of token0 and token1 that are owed to the protocol
    /// @dev Protocol fees will never exceed uint128 max in either token
    function protocolFees() external view returns (uint128 token0, uint128 token1);

    /// @notice The currently in range liquidity available to the pool
    /// @dev This value has no relationship to the total liquidity across all ticks
    function liquidity() external view returns (uint128);

    /// @notice Look up information about a specific tick in the pool
    /// @param tick The tick to look up
    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or
    /// tick upper,
    /// liquidityNet how much liquidity changes when the pool price crosses the tick,
    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,
    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,
    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick
    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,
    /// secondsOutside the seconds spent on the other side of the tick from the current tick,
    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.
    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.
    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for
    /// a specific position.
    function ticks(int24 tick)
        external
        view
        returns (
            uint128 liquidityGross,
            int128 liquidityNet,
            uint256 feeGrowthOutside0X128,
            uint256 feeGrowthOutside1X128,
            int56 tickCumulativeOutside,
            uint160 secondsPerLiquidityOutsideX128,
            uint32 secondsOutside,
            bool initialized
        );

    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information
    function tickBitmap(int16 wordPosition) external view returns (uint256);

    /// @notice Returns the information about a position by the position's key
    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper
    /// @return _liquidity The amount of liquidity in the position,
    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,
    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,
    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,
    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke
    function positions(bytes32 key)
        external
        view
        returns (
            uint128 _liquidity,
            uint256 feeGrowthInside0LastX128,
            uint256 feeGrowthInside1LastX128,
            uint128 tokensOwed0,
            uint128 tokensOwed1
        );

    /// @notice Returns data about a specific observation index
    /// @param index The element of the observations array to fetch
    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time
    /// ago, rather than at a specific index in the array.
    /// @return blockTimestamp The timestamp of the observation,
    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,
    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,
    /// Returns initialized whether the observation has been initialized and the values are safe to use
    function observations(uint256 index)
        external
        view
        returns (
            uint32 blockTimestamp,
            int56 tickCumulative,
            uint160 secondsPerLiquidityCumulativeX128,
            bool initialized
        );
}
          

@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolImmutables.sol

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

import '../IDataStorageOperator.sol';

/// @title Pool state that never changes
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraPoolImmutables {
  /**
   * @notice The contract that stores all the timepoints and can perform actions with them
   * @return The operator address
   */
  function dataStorageOperator() external view returns (address);

  /**
   * @notice The contract that deployed the pool, which must adhere to the IAlgebraFactory interface
   * @return The contract address
   */
  function factory() external view returns (address);

  /**
   * @notice The first of the two tokens of the pool, sorted by address
   * @return The token contract address
   */
  function token0() external view returns (address);

  /**
   * @notice The second of the two tokens of the pool, sorted by address
   * @return The token contract address
   */
  function token1() external view returns (address);

  /**
   * @notice The maximum amount of position liquidity that can use any tick in the range
   * @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and
   * also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool
   * @return The max amount of liquidity per tick
   */
  function maxLiquidityPerTick() external view returns (uint128);
}
          

@openzeppelin/contracts/utils/Address.sol

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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}
          

contracts/interfaces/IStrategyRegistry.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.12;
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol";

interface IStrategyRegistry is
    IERC721Upgradeable,
    IERC721EnumerableUpgradeable
{
    struct RegisteredStrategy {
        uint256 id;
        string name;
        address owner;
        string execBundle; //IPFS reference of execution bundle
        //GasVault stuff
        uint128 maxGasCost;
        uint128 maxGasPerAction;
    }

    function getStrategyAddress(uint256 tokenId)
        external
        view
        returns (address);

    function getStrategyOwner(uint256 tokenId) external view returns (address);

    /**
     * @dev Create NFT for execution bundle.
     * @param name The name of the strategy.
     * @param execBundle The IPFS reference of the execution bundle.
     * @return newStrategyTokenId The token ID of the NFT.
     */
    function createStrategy(
        address strategyCreator,
        string memory name,
        string memory execBundle,
        uint128 maxGasCost,
        uint128 maxGasPerAction
    ) external returns (uint256 newStrategyTokenId);

    //
    // Todo: add to utility library
    //
    function addressToString(address _address)
        external
        pure
        returns (string memory);

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() external;

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() external;

    function tokenURI(uint256 tokenId) external view returns (string memory);

    function getRegisteredStrategy(uint256 tokenId)
        external
        view
        returns (IStrategyRegistry.RegisteredStrategy memory);

    /**
     * @dev parameters users set for what constitutes an acceptable use of their funds. Can only be set by NFT owner.
     * @param _tokenId is the token ID of the execution bundle.
     * @param _maxGasCost is highest acceptable price to pay per gas, in terms of gwei.
     * @param _maxGasPerMethod is max amount of gas to be sent in one method.
     * @param _maxMethods is the maximum number of methods that can be executed in one action.
     */
    function setGasParameters(
        uint256 _tokenId,
        uint128 _maxGasCost,
        uint128 _maxGasPerMethod,
        uint16 _maxMethods
    ) external;

    //function getExecutionBundle(uint256 tokenId) external view returns (string memory);

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

    function burn(uint256 tokenId) external;

    function supportsInterface(bytes4 interfaceId)
        external
        view
        returns (bool);
}
          

@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControlUpgradeable.sol";
import "../utils/ContextUpgradeable.sol";
import "../utils/StringsUpgradeable.sol";
import "../utils/introspection/ERC165Upgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {
    function __AccessControl_init() internal onlyInitializing {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __AccessControl_init_unchained();
    }

    function __AccessControl_init_unchained() internal onlyInitializing {
    }
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        StringsUpgradeable.toHexString(uint160(account), 20),
                        " is missing role ",
                        StringsUpgradeable.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
    uint256[49] private __gap;
}
          

@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolState.sol

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

/// @title Pool state that can change
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraPoolState {
  /**
   * @notice The globalState structure in the pool stores many values but requires only one slot
   * and is exposed as a single method to save gas when accessed externally.
   * @return price The current price of the pool as a sqrt(token1/token0) Q64.96 value;
   * Returns tick The current tick of the pool, i.e. according to the last tick transition that was run;
   * Returns This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(price) if the price is on a tick
   * boundary;
   * Returns fee The last pool fee value in hundredths of a bip, i.e. 1e-6;
   * Returns timepointIndex The index of the last written timepoint;
   * Returns communityFeeToken0 The community fee percentage of the swap fee in thousandths (1e-3) for token0;
   * Returns communityFeeToken1 The community fee percentage of the swap fee in thousandths (1e-3) for token1;
   * Returns unlocked Whether the pool is currently locked to reentrancy;
   */
  function globalState()
    external
    view
    returns (
      uint160 price,
      int24 tick,
      uint16 fee,
      uint16 timepointIndex,
      uint8 communityFeeToken0,
      uint8 communityFeeToken1,
      bool unlocked
    );

  /**
   * @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool
   * @dev This value can overflow the uint256
   */
  function totalFeeGrowth0Token() external view returns (uint256);

  /**
   * @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool
   * @dev This value can overflow the uint256
   */
  function totalFeeGrowth1Token() external view returns (uint256);

  /**
   * @notice The currently in range liquidity available to the pool
   * @dev This value has no relationship to the total liquidity across all ticks.
   * Returned value cannot exceed type(uint128).max
   */
  function liquidity() external view returns (uint128);

  /**
   * @notice Look up information about a specific tick in the pool
   * @dev This is a public structure, so the `return` natspec tags are omitted.
   * @param tick The tick to look up
   * @return liquidityTotal the total amount of position liquidity that uses the pool either as tick lower or
   * tick upper;
   * Returns liquidityDelta how much liquidity changes when the pool price crosses the tick;
   * Returns outerFeeGrowth0Token the fee growth on the other side of the tick from the current tick in token0;
   * Returns outerFeeGrowth1Token the fee growth on the other side of the tick from the current tick in token1;
   * Returns outerTickCumulative the cumulative tick value on the other side of the tick from the current tick;
   * Returns outerSecondsPerLiquidity the seconds spent per liquidity on the other side of the tick from the current tick;
   * Returns outerSecondsSpent the seconds spent on the other side of the tick from the current tick;
   * Returns initialized Set to true if the tick is initialized, i.e. liquidityTotal is greater than 0
   * otherwise equal to false. Outside values can only be used if the tick is initialized.
   * In addition, these values are only relative and must be used only in comparison to previous snapshots for
   * a specific position.
   */
  function ticks(int24 tick)
    external
    view
    returns (
      uint128 liquidityTotal,
      int128 liquidityDelta,
      uint256 outerFeeGrowth0Token,
      uint256 outerFeeGrowth1Token,
      int56 outerTickCumulative,
      uint160 outerSecondsPerLiquidity,
      uint32 outerSecondsSpent,
      bool initialized
    );

  /** @notice Returns 256 packed tick initialized boolean values. See TickTable for more information */
  function tickTable(int16 wordPosition) external view returns (uint256);

  /**
   * @notice Returns the information about a position by the position's key
   * @dev This is a public mapping of structures, so the `return` natspec tags are omitted.
   * @param key The position's key is a hash of a preimage composed by the owner, bottomTick and topTick
   * @return liquidityAmount The amount of liquidity in the position;
   * Returns lastLiquidityAddTimestamp Timestamp of last adding of liquidity;
   * Returns innerFeeGrowth0Token Fee growth of token0 inside the tick range as of the last mint/burn/poke;
   * Returns innerFeeGrowth1Token Fee growth of token1 inside the tick range as of the last mint/burn/poke;
   * Returns fees0 The computed amount of token0 owed to the position as of the last mint/burn/poke;
   * Returns fees1 The computed amount of token1 owed to the position as of the last mint/burn/poke
   */
  function positions(bytes32 key)
    external
    view
    returns (
      uint128 liquidityAmount,
      uint32 lastLiquidityAddTimestamp,
      uint256 innerFeeGrowth0Token,
      uint256 innerFeeGrowth1Token,
      uint128 fees0,
      uint128 fees1
    );

  /**
   * @notice Returns data about a specific timepoint index
   * @param index The element of the timepoints array to fetch
   * @dev You most likely want to use #getTimepoints() instead of this method to get an timepoint as of some amount of time
   * ago, rather than at a specific index in the array.
   * This is a public mapping of structures, so the `return` natspec tags are omitted.
   * @return initialized whether the timepoint has been initialized and the values are safe to use;
   * Returns blockTimestamp The timestamp of the timepoint;
   * Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the timepoint timestamp;
   * Returns secondsPerLiquidityCumulative the seconds per in range liquidity for the life of the pool as of the timepoint timestamp;
   * Returns volatilityCumulative Cumulative standard deviation for the life of the pool as of the timepoint timestamp;
   * Returns averageTick Time-weighted average tick;
   * Returns volumePerLiquidityCumulative Cumulative swap volume per liquidity for the life of the pool as of the timepoint timestamp;
   */
  function timepoints(uint256 index)
    external
    view
    returns (
      bool initialized,
      uint32 blockTimestamp,
      int56 tickCumulative,
      uint160 secondsPerLiquidityCumulative,
      uint88 volatilityCumulative,
      int24 averageTick,
      uint144 volumePerLiquidityCumulative
    );

  /**
   * @notice Returns the information about active incentive
   * @dev if there is no active incentive at the moment, virtualPool,endTimestamp,startTimestamp would be equal to 0
   * @return virtualPool The address of a virtual pool associated with the current active incentive
   */
  function activeIncentive() external view returns (address virtualPool);

  /**
   * @notice Returns the lock time for added liquidity
   */
  function liquidityCooldown() external view returns (uint32 cooldownInSeconds);

  /**
   * @notice The pool tick spacing
   * @dev Ticks can only be used at multiples of this value
   * e.g.: a tickSpacing of 60 means ticks can be initialized every 60th tick, i.e., ..., -120, -60, 0, 60, 120, ...
   * This value is an int24 to avoid casting even though it is always positive.
   * @return The tick spacing
   */
  function tickSpacing() external view returns (int24);
}
          

@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol

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

/// @title Pool state that is not stored
/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the
/// blockchain. The functions here may have variable gas costs.
interface IUniswapV3PoolDerivedState {
    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp
    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing
    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,
    /// you must call it with secondsAgos = [3600, 0].
    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in
    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.
    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned
    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp
    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block
    /// timestamp
    function observe(uint32[] calldata secondsAgos)
        external
        view
        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);

    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range
    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.
    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first
    /// snapshot is taken and the second snapshot is taken.
    /// @param tickLower The lower tick of the range
    /// @param tickUpper The upper tick of the range
    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range
    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range
    /// @return secondsInside The snapshot of seconds per liquidity for the range
    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)
        external
        view
        returns (
            int56 tickCumulativeInside,
            uint160 secondsPerLiquidityInsideX128,
            uint32 secondsInside
        );
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

import "../utils/Context.sol";

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

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

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

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

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

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

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

@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol

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

pragma solidity ^0.8.0;

import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable {
    function __ERC165_init() internal onlyInitializing {
        __ERC165_init_unchained();
    }

    function __ERC165_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165Upgradeable).interfaceId;
    }
    uint256[50] private __gap;
}
          

@openzeppelin/contracts/proxy/beacon/IBeacon.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}
          

@openzeppelin/contracts/token/ERC20/IERC20.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);
}
          

@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol

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

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library CountersUpgradeable {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}
          

contracts/interfaces/IVaultRegistry.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.12;
pragma abicoder v2; //Used this because function getAssetSymbols uses string[2]

import { IStrategyRegistry } from "./IStrategyRegistry.sol";
import { IOrchestrator } from "./IOrchestrator.sol";

interface IVaultRegistry {
    /**
     * PendingApproval: strategy is submitted but has not yet been approved by the owner
     * PendingThreshold: strategy is approved but has not yet reached the threshold of TVL required
     * Paused: strategy was active but something went wrong, so now it's paused
     * Active: strategy is active and can be used
     * Retired: strategy is retired and can no longer be used
     */
    enum VaultState {
        PendingApproval,
        PendingThreshold,
        Paused,
        Active,
        Retired
    }

    /**
     * @dev all necessary data for vault. Name and symbol are stored in vault's ERC20. Owner is stored with tokenId in StrategyRegistry.
     * tokenId: NFT identifier number
     * vaultAddress: address of vault this describes
     * state: state of the vault.
     */
    struct VaultData {
        VaultState state;
        uint256 tokenId; //NFT ownership of this vault and all others that use vault's exec bundle
        uint256 vaultID; //unique identifier for this vault and strategy token id
        string payloadIpfs;
        address vaultAddress;
        string beaconName;
    }

    /// @dev Vault creation event
    /// @param deployer The address of the deployer
    /// @param vault The address of the vault
    /// @param tokenId ERC721 token id for the vault
    /// @param vaultManager is the address which will manage the vault being created
    event VaultCreated(
        address deployer,
        address vault,
        string beaconName,
        uint256 indexed tokenId,
        address vaultManager
    );

    /// @dev Vault state change event
    /// @param vault The address of the vault
    /// @param newState The new state of the vault
    event VaultStateChanged(address indexed vault, VaultState newState);

    // Total vault count.
    function totalVaultCount() external view returns (uint256);

    function whitelistRegistry() external view returns (address);

    function orchestrator() external view returns (IOrchestrator);

    function beaconAddresses(string calldata) external view returns (address);

    function beaconTypes(address) external view returns (string memory);

    // Interface for the strategy registry
    function strategyRegistry() external view returns (IStrategyRegistry);

    /// @dev intializes the vault registry
    /// @param _orchestrator The address of the orchestrator
    /// @param _strategyRegistry The address of the strategy registry
    /// @param _whitelistRegistry The address of the whitelist registry
    function initialize(
        address _orchestrator,
        address _strategyRegistry,
        address _whitelistRegistry
    ) external;

    /// @dev Registers a beacon associated with a new vault type
    /// @param _name The name of the vault type this beacon will be using
    /// @param _address The address of the upgrade beacon
    /// @param _ipfsConfigForBeacon IPFS hash for the config of this beacon
    function registerBeacon(
        string calldata _name,
        address _address,
        string calldata _ipfsConfigForBeacon
    ) external;

    /// @dev Deploy new beacon for a new vault type AND register it
    /// @param _address The address of the implementation for the beacon
    /// @param _name The name of the beacon (identifier)
    /// @param _ipfsConfigForBeacon IPFS hash for the config of this beacon
    function deployAndRegisterBeacon(
        address _address,
        string calldata _name,
        string calldata _ipfsConfigForBeacon
    ) external returns (address);

    /// @dev Removes a beacon associated with a vault type
    /// @param _name The name of the beacon (identifier)
    /// @dev This will stop the creation of more vaults of the type provided
    function deregisterBeacon(string calldata _name) external;

    /// @dev Creates a new vault with the given strategy
    /// @dev Registers an execution bundle, mints an NFT and mappings it to execution bundle and it's details.
    /// @param _params is extra parameters in vault.
    /// @param _tokenId is the NFT of the execution bundle this vault will be using.
    /// @param _beaconName beacon identifier of vault type to be created
    /// @dev owner is set as msg.sender.
    function createVault(
        bytes memory _params,
        uint256 _tokenId,
        string memory _beaconName,
        address _vaultManager,
        string memory strategyData
    ) external returns (address);

    /// @dev Updates the vault state and emits a VaultStateChanged event
    /// @param _vault The address of the vault
    /// @param _newState The new state of the vault
    /// @dev This function is only available to the registry owner
    function updateVaultState(address _vault, VaultState _newState) external;

    /// @dev Retrieves the creator of a given vault
    /// @param _vault The address of the vault
    /// @return The address of the creator
    function getStrategyCreatorForVault(
        address _vault
    ) external view returns (address);

    /// @dev This function is only available to the pauser role
    function pause() external;

    function unpause() external;

    /// @dev Retrieves the details of a given vault by address
    /// @param _address The address of the vault
    /// @return The details of the vault
    function getVaultDetails(
        address _address
    ) external view returns (VaultData memory);

    /// @dev Retrieves the vault count by vault token id
    /// @param _tokenId The token id of the vault
    /// @return The count of the vault
    function getVaultCountByStrategyId(
        uint256 _tokenId
    ) external view returns (uint256);

    /// @dev Retrieves the vault by vault token id and vault index
    /// @param _tokenId The token id of the vault
    /// @param _vaultId The index of the vault
    /// @return Vault details
    function getVaultByStrategyAndIndex(
        uint256 _tokenId,
        uint256 _vaultId
    ) external view returns (VaultData memory);
}
          

Compiler Settings

{"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":10,"enabled":true},"metadata":{"useLiteralContent":true,"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"london"}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"error","name":"IncorrectArrayLengths","inputs":[{"type":"uint256","name":"selectorLength","internalType":"uint256"},{"type":"uint256","name":"isImplementedLength","internalType":"uint256"}]},{"type":"event","name":"AdminChanged","inputs":[{"type":"address","name":"previousAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconConfigUpdated","inputs":[{"type":"string","name":"_name","internalType":"string","indexed":false},{"type":"string","name":"_ipfsHash","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconDeregistered","inputs":[{"type":"string","name":"_name","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconRegistered","inputs":[{"type":"string","name":"_name","internalType":"string","indexed":false},{"type":"address","name":"_address","internalType":"address","indexed":false},{"type":"string","name":"_ipfsHash","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"FeeSettingFailed","inputs":[{"type":"address","name":"","internalType":"address","indexed":false},{"type":"string","name":"","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"previousAdminRole","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"newAdminRole","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"VaultCreated","inputs":[{"type":"address","name":"deployer","internalType":"address","indexed":false},{"type":"address","name":"vault","internalType":"address","indexed":false},{"type":"string","name":"beaconName","internalType":"string","indexed":false},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true},{"type":"address","name":"vaultManager","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"VaultStateChanged","inputs":[{"type":"address","name":"vault","internalType":"address","indexed":true},{"type":"uint8","name":"newState","internalType":"enum VaultRegistry.VaultState","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DEFAULT_ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"beaconAddresses","inputs":[{"type":"string","name":"","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"beaconTypes","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"createVault","inputs":[{"type":"bytes","name":"_params","internalType":"bytes"},{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"string","name":"_beaconName","internalType":"string"},{"type":"address","name":"_vaultManager","internalType":"address"},{"type":"string","name":"_payloadIpfs","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"deployAndRegisterBeacon","inputs":[{"type":"address","name":"_address","internalType":"address"},{"type":"string","name":"_name","internalType":"string"},{"type":"string","name":"_ipfsConfigForBeacon","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deregisterBeacon","inputs":[{"type":"string","name":"_name","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"doISupportInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"feeManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRoleAdmin","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getStrategyCreatorForVault","inputs":[{"type":"address","name":"_vault","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct VaultRegistry.VaultData","components":[{"type":"uint8","name":"state","internalType":"enum VaultRegistry.VaultState"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"vaultID","internalType":"uint256"},{"type":"string","name":"payloadIpfs","internalType":"string"},{"type":"address","name":"vaultAddress","internalType":"address"},{"type":"string","name":"beaconName","internalType":"string"}]}],"name":"getVaultByStrategyAndIndex","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"uint256","name":"_vaultId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getVaultCountByStrategyId","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct VaultRegistry.VaultData","components":[{"type":"uint8","name":"state","internalType":"enum VaultRegistry.VaultState"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"vaultID","internalType":"uint256"},{"type":"string","name":"payloadIpfs","internalType":"string"},{"type":"address","name":"vaultAddress","internalType":"address"},{"type":"string","name":"beaconName","internalType":"string"}]}],"name":"getVaultDetails","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_orchestrator","internalType":"address"},{"type":"address","name":"_strategyRegistry","internalType":"address"},{"type":"address","name":"_whitelistRegistry","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"interfaceImplementations","inputs":[{"type":"string","name":"","internalType":"string"},{"type":"bytes4","name":"","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"linkedVaults","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"orchestrator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"registerBeacon","inputs":[{"type":"string","name":"_name","internalType":"string"},{"type":"address","name":"_address","internalType":"address"},{"type":"string","name":"_ipfsConfigForBeacon","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFeeManager","inputs":[{"type":"address","name":"_feeManager","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setVaultHelper","inputs":[{"type":"address","name":"_vaultHelper","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IStrategyRegistry"}],"name":"strategyRegistry","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalVaultCount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateBeaconConfig","inputs":[{"type":"string","name":"_name","internalType":"string"},{"type":"string","name":"_newIPFSConfigForBeacon","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateInterfaceImplementations","inputs":[{"type":"string","name":"beaconName","internalType":"string"},{"type":"bytes4[]","name":"selectors","internalType":"bytes4[]"},{"type":"bool[]","name":"isImplemented","internalType":"bool[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateVaultState","inputs":[{"type":"address","name":"_vault","internalType":"address"},{"type":"uint8","name":"_newState","internalType":"enum VaultRegistry.VaultState"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeTo","inputs":[{"type":"address","name":"newImplementation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"upgradeToAndCall","inputs":[{"type":"address","name":"newImplementation","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"vaultHelper","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"whitelistRegistry","inputs":[]}]
              

Contract Creation Code

0x60a0604052306080523480156200001557600080fd5b50600054610100900460ff16620000335760005460ff16156200003d565b6200003d620000e2565b620000a55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000c8576000805461ffff19166101011790555b8015620000db576000805461ff00191690555b5062000106565b6000620000fa306200010060201b62001f3c1760201c565b15905090565b3b151590565b608051614b476200013760003960008181610d2701528181610d6a0152818161156101526115a40152614b476000f3fe608060405260043610620001f45760003560e01c806301ffc9a714620001f957806303286fbf146200023357806306b5203b14620002835780630ad0eb3814620002aa5780631ee6033714620002de578063248a9ca3146200030157806325d8d09e1462000335578063280c8dfd14620003695780632f2ff15d146200038e57806336568abe14620003b35780633659cfe614620003d85780633811936914620003fd5780633f4ba83a1462000416578063437783d6146200042e578063456b79c71462000462578063472d35b914620004875780634b894cff14620004ac5780634f1ef28614620004d15780634f4df28714620004e85780635c975abb146200050d57806367a44ca31462000527578063715018a6146200054c5780638456cb5914620005645780638da5cb5b146200057c57806391d1485414620005945780639774272c14620005b9578063a217fddf14620005de578063ab8b2a7314620005f5578063b74795d9146200061a578063be2bf8ae146200063d578063c0c53b8b1462000662578063d080bf271462000687578063d0c6383d14620006aa578063d0fb020314620006cf578063d547741f14620006f2578063e67fec821462000717578063ec192f8a1462000749578063ed950638146200078f578063f2fde38b14620007b2578063f3b881a314620007d7575b600080fd5b3480156200020657600080fd5b506200021e6200021836600462002bdc565b6200081d565b60405190151581526020015b60405180910390f35b3480156200024057600080fd5b506200021e6200025236600462002cc9565b8151602081840181018051610161825292820194820194909420919093529091526000908152604090205460ff1681565b3480156200029057600080fd5b50620002a8620002a236600462002d7d565b62000855565b005b348015620002b757600080fd5b50620002cf620002c936600462002e03565b62000966565b6040516200022a919062002e23565b348015620002eb57600080fd5b5061016a54620002cf906001600160a01b031681565b3480156200030e57600080fd5b50620003266200032036600462002e37565b620009f1565b6040519081526020016200022a565b3480156200034257600080fd5b506200035a6200035436600462002e51565b62000a07565b6040516200022a919062002f0a565b3480156200037657600080fd5b50620002a86200038836600462002f84565b62000be4565b3480156200039b57600080fd5b50620002a8620003ad36600462002fc9565b62000c72565b348015620003c057600080fd5b50620002a8620003d236600462002fc9565b62000c9a565b348015620003e557600080fd5b50620002a8620003f736600462002e03565b62000d1c565b3480156200040a57600080fd5b50620003266101625481565b3480156200042357600080fd5b50620002a862000df1565b3480156200043b57600080fd5b50620004536200044d36600462002e03565b62000e17565b6040516200022a919062002ffc565b3480156200046f57600080fd5b50620002cf6200048136600462003011565b62000eba565b3480156200049457600080fd5b50620002a8620004a636600462002e03565b620012fd565b348015620004b957600080fd5b50620002cf620004cb366004620030c3565b6200139e565b620002a8620004e23660046200314e565b62001556565b348015620004f557600080fd5b50620002a862000507366004620031ea565b62001618565b3480156200051a57600080fd5b5060975460ff166200021e565b3480156200053457600080fd5b506200035a6200054636600462002e03565b6200172e565b3480156200055957600080fd5b50620002a8620018f5565b3480156200057157600080fd5b50620002a862001937565b3480156200058957600080fd5b50620002cf6200195d565b348015620005a157600080fd5b506200021e620005b336600462002fc9565b6200196c565b348015620005c657600080fd5b50620002a8620005d83660046200328d565b62001998565b348015620005eb57600080fd5b5062000326600081565b3480156200060257600080fd5b506200021e6200061436600462002bdc565b62001a6c565b3480156200062757600080fd5b5061016654620002cf906001600160a01b031681565b3480156200064a57600080fd5b50620002a86200065c366004620032ff565b62001b59565b3480156200066f57600080fd5b50620002a86200068136600462003335565b62001c12565b3480156200069457600080fd5b5061016754620002cf906001600160a01b031681565b348015620006b757600080fd5b50620002a8620006c936600462002e03565b62001e1c565b348015620006dc57600080fd5b5061016954620002cf906001600160a01b031681565b348015620006ff57600080fd5b50620002a86200071136600462002fc9565b62001e73565b3480156200072457600080fd5b50620003266200073636600462002e37565b6000908152610165602052604090205490565b3480156200075657600080fd5b50620002cf6200076836600462002e51565b6101646020908152600092835260408084209091529082529020546001600160a01b031681565b3480156200079c57600080fd5b5061016854620002cf906001600160a01b031681565b348015620007bf57600080fd5b50620002a8620007d136600462002e03565b62001e96565b348015620007e457600080fd5b50620002cf620007f636600462003387565b805160208183018101805161015f825292820191909301209152546001600160a01b031681565b60006001600160e01b03198216637965db0b60e01b14806200084f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008051602062004af283398151915262000871813362001f42565b60006001600160a01b031661015f868660405162000891929190620033c7565b908152604051908190036020019020546001600160a01b031614620008d35760405162461bcd60e51b8152600401620008ca90620033d7565b60405180910390fd5b8261015f8686604051620008e9929190620033c7565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559185166000908152610160909152206200093090868662002a3f565b5060008051602062004a2b833981519152858585856040516200095794939291906200342f565b60405180910390a15050505050565b610167546001600160a01b03828116600090815261016360205260408082206001015490516331a9108f60e11b8152600481019190915290929190911690636352211e90602401602060405180830381865afa158015620009cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200084f919062003473565b600090815261012d602052604090206001015490565b62000a1162002ace565b6000838152610164602090815260408083208584528252808320546001600160a01b0316835261016390915290819020815160c081019092528054829060ff16600481111562000a655762000a6562002e74565b600481111562000a795762000a7962002e74565b8152602001600182015481526020016002820154815260200160038201805462000aa39062003493565b80601f016020809104026020016040519081016040528092919081815260200182805462000ad19062003493565b801562000b225780601f1062000af65761010080835404028352916020019162000b22565b820191906000526020600020905b81548152906001019060200180831162000b0457829003601f168201915b505050918352505060048201546001600160a01b0316602082015260058201805460409092019162000b549062003493565b80601f016020809104026020016040519081016040528092919081815260200182805462000b829062003493565b801562000bd35780601f1062000ba75761010080835404028352916020019162000bd3565b820191906000526020600020905b81548152906001019060200180831162000bb557829003601f168201915b505050505081525050905092915050565b60008051602062004af283398151915262000c00813362001f42565b7f1a066afb4a727dab9f80135f964045d9e6b7e75e1fa27bf957f29dcc024e43ed838360405162000c33929190620034d0565b60405180910390a161015f838360405162000c50929190620033c7565b90815260405190819003602001902080546001600160a01b0319169055505050565b62000c7d82620009f1565b62000c89813362001f42565b62000c95838362001fb1565b505050565b6001600160a01b038116331462000d0c5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401620008ca565b62000d1882826200203c565b5050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016141562000d685760405162461bcd60e51b8152600401620008ca90620034e6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662000d9c620020a7565b6001600160a01b03161462000dc55760405162461bcd60e51b8152600401620008ca9062003521565b62000dd081620020c4565b6040805160008082526020820190925262000dee91839190620020f8565b50565b60008051602062004a8b83398151915262000e0d813362001f42565b62000dee62002252565b610160602052600090815260409020805462000e339062003493565b80601f016020809104026020016040519081016040528092919081815260200182805462000e619062003493565b801562000eb25780601f1062000e865761010080835404028352916020019162000eb2565b820191906000526020600020905b81548152906001019060200180831162000e9457829003601f168201915b505050505081565b600062000ec960975460ff1690565b1562000ee95760405162461bcd60e51b8152600401620008ca906200355c565b610169546001600160a01b031662000f395760405162461bcd60e51b815260206004820152601260248201527111995953585b9859d95c881b9bdd081cd95d60721b6044820152606401620008ca565b61016a546001600160a01b031662000f8b5760405162461bcd60e51b815260206004820152601460248201527315985d5b1d081a195b1c195c881b9bdd081cd95d60621b6044820152606401620008ca565b610167546040516331a9108f60e11b8152600481018790526001600160a01b0390911690636352211e90602401602060405180830381865afa15801562000fd6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ffc919062003473565b50600061015f8560405162001012919062003586565b908152604051908190036020019020546001600160a01b0316905080620010745760405162461bcd60e51b815260206004820152601560248201527410995858dbdb881a5cc81b9bdd081c1c995cd95b9d605a1b6044820152606401620008ca565b61016654600090829063246581f760e01b9087906001600160a01b03166200109b6200195d565b8c604051602401620010b19493929190620035a4565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620010f09062002b0e565b620010fd929190620035e4565b604051809103906000f0801580156200111a573d6000803e3d6000fd5b506001600160a01b03811660009081526101606020908152604090912088519293506200114c92909189019062002b1c565b50806001600160a01b0316631f2c54436040518163ffffffff1660e01b8152600401600060405180830381865afa925050508015620011af57506040513d6000823e601f3d908101601f19168201604052620011ac919081019062003767565b60015b6200122857604080516001600160a01b03831681526020808201839052818301527f4665652073657474696e67206661696c656420696e204665654d616e61676572606082015290517fe39bcf9e9fc06de4055c8d6665f0ef72c7bcc50f8f4b6882d2c408c996ef3eb59181900360800190a1620012a4565b83156200129f57610169546040516302d051b560e31b81526001600160a01b03909116906316828da8906200126a9088908890879087908a90600401620038d8565b600060405180830381600087803b1580156200128557600080fd5b505af11580156200129a573d6000803e3d6000fd5b505050505b505050505b620012b287828689620022e3565b867f3910bed511b4ecc0d6ae24498d585722a54c6ce9ab5e65b4be534cec981f7f6f33838989604051620012ea949392919062003981565b60405180910390a2979650505050505050565b33620013086200195d565b6001600160a01b031614620013315760405162461bcd60e51b8152600401620008ca90620039c1565b610169546001600160a01b0316156200137b5760405162461bcd60e51b815260206004820152600b60248201526a105b1c9958591e4814d95d60aa1b6044820152606401620008ca565b61016980546001600160a01b0319166001600160a01b0392909216919091179055565b600060008051602062004af2833981519152620013bc813362001f42565b60006001600160a01b031661015f8787604051620013dc929190620033c7565b908152604051908190036020019020546001600160a01b031614620014155760405162461bcd60e51b8152600401620008ca90620033d7565b600087604051620014269062002b99565b62001432919062002e23565b604051809103906000f0801580156200144f573d6000803e3d6000fd5b509050806001600160a01b031663f2fde38b6200146b6200195d565b6040518263ffffffff1660e01b815260040162001489919062002e23565b600060405180830381600087803b158015620014a457600080fd5b505af1158015620014b9573d6000803e3d6000fd5b505050508061015f8888604051620014d3929190620033c7565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559183166000908152610160909152206200151a90888862002a3f565b5060008051602062004a2b83398151915287878a888860405162001543959493929190620039f6565b60405180910390a1979650505050505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415620015a25760405162461bcd60e51b8152600401620008ca90620034e6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316620015d6620020a7565b6001600160a01b031614620015ff5760405162461bcd60e51b8152600401620008ca9062003521565b6200160a82620020c4565b62000d1882826001620020f8565b60008051602062004ad283398151915262001634813362001f42565b8382146200166057604051630d07103b60e41b81526004810185905260248101839052604401620008ca565b60005b808514620017245783838281811062001680576200168062003a30565b905060200201602081019062001697919062003a46565b6101618989604051620016ac929190620033c7565b90815260200160405180910390206000888885818110620016d157620016d162003a30565b9050602002016020810190620016e8919062002bdc565b6001600160e01b03191681526020810191909152604001600020805460ff19169115159190911790556200171c8162003a80565b905062001663565b5050505050505050565b6200173862002ace565b6001600160a01b0382166000908152610163602052604090819020815160c081019092528054829060ff16600481111562001777576200177762002e74565b60048111156200178b576200178b62002e74565b81526020016001820154815260200160028201548152602001600382018054620017b59062003493565b80601f0160208091040260200160405190810160405280929190818152602001828054620017e39062003493565b8015620018345780601f10620018085761010080835404028352916020019162001834565b820191906000526020600020905b8154815290600101906020018083116200181657829003601f168201915b505050918352505060048201546001600160a01b03166020820152600582018054604090920191620018669062003493565b80601f0160208091040260200160405190810160405280929190818152602001828054620018949062003493565b8015620018e55780601f10620018b957610100808354040283529160200191620018e5565b820191906000526020600020905b815481529060010190602001808311620018c757829003601f168201915b5050505050815250509050919050565b33620019006200195d565b6001600160a01b031614620019295760405162461bcd60e51b8152600401620008ca90620039c1565b62001935600062002438565b565b60008051602062004a8b83398151915262001953813362001f42565b62000dee6200248a565b60c9546001600160a01b031690565b600091825261012d602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60008051602062004af2833981519152620019b4813362001f42565b60006001600160a01b031661015f8686604051620019d4929190620033c7565b908152604051908190036020019020546001600160a01b0316141562001a355760405162461bcd60e51b815260206004820152601560248201527410995858dbdb88191bd95cc81b9bdd08195e1a5cdd605a1b6044820152606401620008ca565b7f36f2c5b342695ee5dddbc5f4df3702d45b57810740060110c70c87e723e01cf88585858560405162000957949392919062003a9e565b33600090815261016060205260408120805482919062001a8c9062003493565b80601f016020809104026020016040519081016040528092919081815260200182805462001aba9062003493565b801562001b0b5780601f1062001adf5761010080835404028352916020019162001b0b565b820191906000526020600020905b81548152906001019060200180831162001aed57829003601f168201915b505050505090506101618160405162001b25919062003586565b90815260408051602092819003830190206001600160e01b0319959095166000908152949091529092205460ff1692915050565b3362001b646200195d565b6001600160a01b03161462001b8d5760405162461bcd60e51b8152600401620008ca90620039c1565b6001600160a01b038216600090815261016360205260409020805482919060ff1916600183600481111562001bc65762001bc662002e74565b0217905550816001600160a01b03167fb977ce68002d3b49b272b3ae970ad8a17b283cd2b5d40a674c888140bca7436b8260405162001c06919062003ac9565b60405180910390a25050565b600054610100900460ff1662001c2f5760005460ff161562001c33565b303b155b62001c985760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620008ca565b600054610100900460ff1615801562001cbb576000805461ffff19166101011790555b62001cc5620024e6565b62001ccf62002524565b62001cd962002562565b62001ce362002596565b6001600160a01b03831662001d0c5760405162461bcd60e51b8152600401620008ca9062003ad9565b6001600160a01b03821662001d355760405162461bcd60e51b8152600401620008ca9062003ad9565b6001600160a01b03841662001d5e5760405162461bcd60e51b8152600401620008ca9062003ad9565b61016680546001600160a01b038087166001600160a01b031992831617909255610167805486841690831617905561016880549285169290911691909117905562001dc060008051602062004a8b83398151915262001dba3390565b620025d4565b62001ddb60008051602062004af283398151915233620025d4565b62001df660008051602062004ad283398151915233620025d4565b62001e03600033620025d4565b801562001e16576000805461ff00191690555b50505050565b3362001e276200195d565b6001600160a01b03161462001e505760405162461bcd60e51b8152600401620008ca90620039c1565b61016a80546001600160a01b0319166001600160a01b0392909216919091179055565b62001e7e82620009f1565b62001e8a813362001f42565b62000c9583836200203c565b3362001ea16200195d565b6001600160a01b03161462001eca5760405162461bcd60e51b8152600401620008ca90620039c1565b6001600160a01b03811662001f315760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620008ca565b62000dee8162002438565b3b151590565b62001f4e82826200196c565b62000d185762001f69816001600160a01b03166014620025e0565b62001f76836020620025e0565b60405160200162001f8992919062003afd565b60408051601f198184030181529082905262461bcd60e51b8252620008ca9160040162002ffc565b62001fbd82826200196c565b62000d1857600082815261012d602090815260408083206001600160a01b03851684529091529020805460ff1916600117905562001ff83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6200204882826200196c565b1562000d1857600082815261012d602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008051602062004a6b833981519152546001600160a01b031690565b33620020cf6200195d565b6001600160a01b03161462000dee5760405162461bcd60e51b8152600401620008ca90620039c1565b600062002104620020a7565b90506200211184620027a0565b6000835111806200211f5750815b15620021335762002131848462002836565b505b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143805460ff166200224b57805460ff19166001178155604051620021b39086906200218390859060240162002e23565b60408051601f198184030181529190526020810180516001600160e01b0316631b2ce7f360e11b17905262002836565b50805460ff19168155620021c6620020a7565b6001600160a01b0316826001600160a01b031614620022405760405162461bcd60e51b815260206004820152602f60248201527f45524331393637557067726164653a207570677261646520627265616b73206660448201526e75727468657220757067726164657360881b6064820152608401620008ca565b6200224b856200292a565b5050505050565b60975460ff166200229d5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401620008ca565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051620022d9919062002e23565b60405180910390a1565b60008481526101656020908152604080832054610164835281842081855290925290912080546001600160a01b0319166001600160a01b0386161790556200232d81600162003b70565b600086815261016560205260409081902091909155805160c081019091528060018152602001868152602001610162600081546200236b9062003a80565b9182905550815260208082018690526001600160a01b0387166040808401829052606090930186905260009081526101639091522081518154829060ff19166001836004811115620023c157620023c162002e74565b021790555060208281015160018301556040830151600283015560608301518051620023f4926003850192019062002b1c565b5060808201516004820180546001600160a01b0319166001600160a01b0390921691909117905560a082015180516200172491600584019160209091019062002b1c565b60c980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60975460ff1615620024b05760405162461bcd60e51b8152600401620008ca906200355c565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258620022ca3390565b600054610100900460ff16620025105760405162461bcd60e51b8152600401620008ca9062003b8b565b6200251a6200296c565b620019356200296c565b600054610100900460ff166200254e5760405162461bcd60e51b8152600401620008ca9062003b8b565b620025586200296c565b6200193562002996565b600054610100900460ff166200258c5760405162461bcd60e51b8152600401620008ca9062003b8b565b620025106200296c565b600054610100900460ff16620025c05760405162461bcd60e51b8152600401620008ca9062003b8b565b620025ca6200296c565b62001935620029cb565b62000d18828262001fb1565b60606000620025f183600262003bd6565b620025fe90600262003b70565b6001600160401b0381111562002618576200261862002bfa565b6040519080825280601f01601f19166020018201604052801562002643576020820181803683370190505b509050600360fc1b8160008151811062002661576200266162003a30565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811062002693576200269362003a30565b60200101906001600160f81b031916908160001a9053506000620026b984600262003bd6565b620026c690600162003b70565b90505b600181111562002748576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620026fe57620026fe62003a30565b1a60f81b82828151811062002717576200271762003a30565b60200101906001600160f81b031916908160001a90535060049490941c93620027408162003bf8565b9050620026c9565b508315620027995760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620008ca565b9392505050565b803b620028065760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620008ca565b60008051602062004a6b83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060823b620028975760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401620008ca565b600080846001600160a01b031684604051620028b4919062003586565b600060405180830381855af49150503d8060008114620028f1576040519150601f19603f3d011682016040523d82523d6000602084013e620028f6565b606091505b509150915062002921828260405180606001604052806027815260200162004aab6027913962002a01565b95945050505050565b6200293581620027a0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b600054610100900460ff16620019355760405162461bcd60e51b8152600401620008ca9062003b8b565b600054610100900460ff16620029c05760405162461bcd60e51b8152600401620008ca9062003b8b565b620019353362002438565b600054610100900460ff16620029f55760405162461bcd60e51b8152600401620008ca9062003b8b565b6097805460ff19169055565b6060831562002a1257508162002799565b82511562002a235782518084602001fd5b8160405162461bcd60e51b8152600401620008ca919062002ffc565b82805462002a4d9062003493565b90600052602060002090601f01602090048101928262002a71576000855562002abc565b82601f1062002a8c5782800160ff1982351617855562002abc565b8280016001018555821562002abc579182015b8281111562002abc57823582559160200191906001019062002a9f565b5062002aca92915062002ba7565b5090565b6040805160c08101909152806000815260200160008152602001600081526020016060815260200160006001600160a01b03168152602001606081525090565b61090c8062003c1383390190565b82805462002b2a9062003493565b90600052602060002090601f01602090048101928262002b4e576000855562002abc565b82601f1062002b6957805160ff191683800117855562002abc565b8280016001018555821562002abc579182015b8281111562002abc57825182559160200191906001019062002b7c565b61050c806200451f83390190565b5b8082111562002aca576000815560010162002ba8565b80356001600160e01b03198116811462002bd757600080fd5b919050565b60006020828403121562002bef57600080fd5b620027998262002bbe565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562002c3b5762002c3b62002bfa565b604052919050565b60006001600160401b0382111562002c5f5762002c5f62002bfa565b50601f01601f191660200190565b600082601f83011262002c7f57600080fd5b813562002c9662002c908262002c43565b62002c10565b81815284602083860101111562002cac57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121562002cdd57600080fd5b82356001600160401b0381111562002cf457600080fd5b62002d028582860162002c6d565b92505062002d136020840162002bbe565b90509250929050565b60008083601f84011262002d2f57600080fd5b5081356001600160401b0381111562002d4757600080fd5b60208301915083602082850101111562002d6057600080fd5b9250929050565b6001600160a01b038116811462000dee57600080fd5b6000806000806060858703121562002d9457600080fd5b84356001600160401b038082111562002dac57600080fd5b62002dba8883890162002d1c565b90965094506020870135915062002dd18262002d67565b9092506040860135908082111562002de857600080fd5b5062002df78782880162002c6d565b91505092959194509250565b60006020828403121562002e1657600080fd5b8135620027998162002d67565b6001600160a01b0391909116815260200190565b60006020828403121562002e4a57600080fd5b5035919050565b6000806040838503121562002e6557600080fd5b50508035926020909101359150565b634e487b7160e01b600052602160045260246000fd5b6005811062002ea957634e487b7160e01b600052602160045260246000fd5b9052565b60005b8381101562002eca57818101518382015260200162002eb0565b8381111562001e165750506000910152565b6000815180845262002ef681602086016020860162002ead565b601f01601f19169290920160200192915050565b6020815262002f1e60208201835162002e8a565b60208201516040820152604082015160608201526000606083015160c0608084015262002f4f60e084018262002edc565b60808501516001600160a01b031660a085810191909152850151848203601f190160c086015290915062002921828262002edc565b6000806020838503121562002f9857600080fd5b82356001600160401b0381111562002faf57600080fd5b62002fbd8582860162002d1c565b90969095509350505050565b6000806040838503121562002fdd57600080fd5b82359150602083013562002ff18162002d67565b809150509250929050565b60208152600062002799602083018462002edc565b600080600080600060a086880312156200302a57600080fd5b85356001600160401b03808211156200304257600080fd5b6200305089838a0162002c6d565b96506020880135955060408801359150808211156200306e57600080fd5b6200307c89838a0162002c6d565b945060608801359150620030908262002d67565b90925060808701359080821115620030a757600080fd5b50620030b68882890162002c6d565b9150509295509295909350565b600080600080600060608688031215620030dc57600080fd5b8535620030e98162002d67565b945060208601356001600160401b03808211156200310657600080fd5b6200311489838a0162002d1c565b909650945060408801359150808211156200312e57600080fd5b506200313d8882890162002d1c565b969995985093965092949392505050565b600080604083850312156200316257600080fd5b82356200316f8162002d67565b915060208301356001600160401b038111156200318b57600080fd5b620031998582860162002c6d565b9150509250929050565b60008083601f840112620031b657600080fd5b5081356001600160401b03811115620031ce57600080fd5b6020830191508360208260051b850101111562002d6057600080fd5b600080600080600080606087890312156200320457600080fd5b86356001600160401b03808211156200321c57600080fd5b6200322a8a838b0162002d1c565b909850965060208901359150808211156200324457600080fd5b620032528a838b01620031a3565b909650945060408901359150808211156200326c57600080fd5b506200327b89828a01620031a3565b979a9699509497509295939492505050565b60008060008060408587031215620032a457600080fd5b84356001600160401b0380821115620032bc57600080fd5b620032ca8883890162002d1c565b90965094506020870135915080821115620032e457600080fd5b50620032f38782880162002d1c565b95989497509550505050565b600080604083850312156200331357600080fd5b8235620033208162002d67565b915060208301356005811062002ff157600080fd5b6000806000606084860312156200334b57600080fd5b8335620033588162002d67565b925060208401356200336a8162002d67565b915060408401356200337c8162002d67565b809150509250925092565b6000602082840312156200339a57600080fd5b81356001600160401b03811115620033b157600080fd5b620033bf8482850162002c6d565b949350505050565b8183823760009101908152919050565b602080825260159082015274426561636f6e20616c72656164792065786973747360581b604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006200344560608301868862003406565b6001600160a01b0385166020840152828103604084015262003468818562002edc565b979650505050505050565b6000602082840312156200348657600080fd5b8151620027998162002d67565b600181811c90821680620034a857607f821691505b60208210811415620034ca57634e487b7160e01b600052602260045260246000fd5b50919050565b602081526000620033bf60208301848662003406565b6020808252602c9082015260008051602062004a4b83398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c9082015260008051602062004a4b83398151915260408201526b6163746976652070726f787960a01b606082015260800190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b600082516200359a81846020870162002ead565b9190910192915050565b6001600160a01b038581168252848116602083015283166040820152608060608201819052600090620035da9083018462002edc565b9695505050505050565b6001600160a01b0383168152604060208201819052600090620033bf9083018462002edc565b60006001600160401b0382111562003626576200362662002bfa565b5060051b60200190565b600082601f8301126200364257600080fd5b815160206200365562002c90836200360a565b82815260059290921b840181019181810190868411156200367557600080fd5b8286015b84811015620036fa5780516001600160401b038111156200369a5760008081fd5b8701603f81018913620036ad5760008081fd5b848101516040620036c262002c908362002c43565b8281528b82848601011115620036d85760008081fd5b620036e98389830184870162002ead565b865250505091830191830162003679565b509695505050505050565b600082601f8301126200371757600080fd5b815160206200372a62002c90836200360a565b82815260059290921b840181019181810190868411156200374a57600080fd5b8286015b84811015620036fa57805183529183019183016200374e565b600080600080608085870312156200377e57600080fd5b8451602080870151919550906001600160401b0380821115620037a057600080fd5b818801915088601f830112620037b557600080fd5b8151620037c662002c90826200360a565b81815260059190911b8301840190848101908b831115620037e657600080fd5b938501935b8285101562003811578451620038018162002d67565b82529385019390850190620037eb565b60408b015190985094505050808311156200382b57600080fd5b6200383989848a0162003630565b945060608801519250808311156200385057600080fd5b505062002df78782880162003705565b600081518084526020808501945080840160005b83811015620038925781518752958201959082019060010162003874565b509495945050505050565b600081518084526020808501945080840160005b83811015620038925781516001600160a01b031687529582019590820190600101620038b1565b600060a0820160018060a01b03881683526020878185015260a0604085015281875180845260c08601915060c08160051b870101935082890160005b82811015620039465760bf198887030184526200393386835162002edc565b9550928401929084019060010162003914565b505050505082810360608401526200395f818662003860565b905082810360808401526200397581856200389d565b98975050505050505050565b600060018060a01b038087168352808616602084015260806040840152620039ad608084018662002edc565b915080841660608401525095945050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60608152600062003a0c60608301878962003406565b6001600160a01b038616602084015282810360408401526200397581858762003406565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562003a5957600080fd5b813580151581146200279957600080fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141562003a975762003a9762003a6a565b5060010190565b60408152600062003ab460408301868862003406565b82810360208401526200346881858762003406565b602081016200084f828462002e8a565b6020808252600a90820152696164647265737328302960b01b604082015260600190565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b81526000835162003b3181601785016020880162002ead565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835162003b6481602884016020880162002ead565b01602801949350505050565b6000821982111562003b865762003b8662003a6a565b500190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600081600019048311821515161562003bf35762003bf362003a6a565b500290565b60008162003c0a5762003c0a62003a6a565b50600019019056fe608060405260405161090c38038061090c83398101604081905261002291610460565b61002e82826000610035565b505061058a565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610520565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610520565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108e5602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053b565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c65782516103bf576001600160a01b0385163b6103bf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d0565b6103d083836103d8565b949350505050565b8151156103e85781518083602001fd5b8060405162461bcd60e51b81526004016101699190610557565b80516001600160a01b038116811461041957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561044f578181015183820152602001610437565b838111156100f95750506000910152565b6000806040838503121561047357600080fd5b61047c83610402565b60208401519092506001600160401b038082111561049957600080fd5b818501915085601f8301126104ad57600080fd5b8151818111156104bf576104bf61041e565b604051601f8201601f19908116603f011681019083821181831017156104e7576104e761041e565b8160405282815288602084870101111561050057600080fd5b610511836020830160208801610434565b80955050505050509250929050565b60006020828403121561053257600080fd5b6102c882610402565b6000825161054d818460208701610434565b9190910192915050565b6020815260008251806020840152610576816040850160208701610434565b601f01601f19169190910160400192915050565b61034c806105996000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f060279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb9190610247565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a0565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b6060831561020b578251610204576101b385610055565b6102045760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610215565b610215838361021d565b949350505050565b81511561022d5781518083602001fd5b8060405162461bcd60e51b81526004016101fb91906102bc565b60006020828403121561025957600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b8381101561028b578181015183820152602001610273565b8381111561029a576000848401525b50505050565b600082516102b2818460208701610270565b9190910192915050565b60208152600082518060208401526102db816040850160208701610270565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c149cc587c459fdcb5b0b327a81fc3a237cb5f545f983075dc92d02083b7eab964736f6c634300080c0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564608060405234801561001057600080fd5b5060405161050c38038061050c83398101604081905261002f91610179565b61003833610047565b61004181610097565b506101a9565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6100aa8161016a60201b6101751760201c565b6101205760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f60448201527f6e206973206e6f74206120636f6e747261637400000000000000000000000000606482015260840160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03163b151590565b60006020828403121561018b57600080fd5b81516001600160a01b03811681146101a257600080fd5b9392505050565b610354806101b86000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80635c60da1b1461005c5780635c879c101461008b578063715018a6146100a05780638da5cb5b146100a8578063f2fde38b146100b0575b600080fd5b60015461006f906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61009e6100993660046102ee565b6100c3565b005b61009e6100d7565b61006f6100eb565b61009e6100be3660046102ee565b6100fa565b6100cb610184565b6100d4816101e3565b50565b6100df610184565b6100e9600061029e565b565b6000546001600160a01b031690565b610102610184565b6001600160a01b03811661016c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6100d48161029e565b6001600160a01b03163b151590565b3361018d6100eb565b6001600160a01b0316146100e95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610163565b6101ec81610175565b6102545760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b6064820152608401610163565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561030057600080fd5b81356001600160a01b038116811461031757600080fd5b939250505056fea264697066735822122033f2e14e99437c22a1cd8960cb6201771a12eb7f1602bea314497be31bab8fb064736f6c634300080c003324465a1f9a55eb0e9691adbdc0160061ace64f7309611b6aa3add1f00b178d0f46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65645f36c4325e7b3e3c355f553dd2d909e309f22530e6b36ae3260b053f89fb8c2143c4ee843c388ace340d7c40a79a882e9cb3437dbb4d5f773148b941fef1a5afa2646970667358221220719512b2ee1c1ea37b8d9af0d2ca84425a080ae9b16b92502569c18012a39ed864736f6c634300080c0033

Deployed ByteCode

0x608060405260043610620001f45760003560e01c806301ffc9a714620001f957806303286fbf146200023357806306b5203b14620002835780630ad0eb3814620002aa5780631ee6033714620002de578063248a9ca3146200030157806325d8d09e1462000335578063280c8dfd14620003695780632f2ff15d146200038e57806336568abe14620003b35780633659cfe614620003d85780633811936914620003fd5780633f4ba83a1462000416578063437783d6146200042e578063456b79c71462000462578063472d35b914620004875780634b894cff14620004ac5780634f1ef28614620004d15780634f4df28714620004e85780635c975abb146200050d57806367a44ca31462000527578063715018a6146200054c5780638456cb5914620005645780638da5cb5b146200057c57806391d1485414620005945780639774272c14620005b9578063a217fddf14620005de578063ab8b2a7314620005f5578063b74795d9146200061a578063be2bf8ae146200063d578063c0c53b8b1462000662578063d080bf271462000687578063d0c6383d14620006aa578063d0fb020314620006cf578063d547741f14620006f2578063e67fec821462000717578063ec192f8a1462000749578063ed950638146200078f578063f2fde38b14620007b2578063f3b881a314620007d7575b600080fd5b3480156200020657600080fd5b506200021e6200021836600462002bdc565b6200081d565b60405190151581526020015b60405180910390f35b3480156200024057600080fd5b506200021e6200025236600462002cc9565b8151602081840181018051610161825292820194820194909420919093529091526000908152604090205460ff1681565b3480156200029057600080fd5b50620002a8620002a236600462002d7d565b62000855565b005b348015620002b757600080fd5b50620002cf620002c936600462002e03565b62000966565b6040516200022a919062002e23565b348015620002eb57600080fd5b5061016a54620002cf906001600160a01b031681565b3480156200030e57600080fd5b50620003266200032036600462002e37565b620009f1565b6040519081526020016200022a565b3480156200034257600080fd5b506200035a6200035436600462002e51565b62000a07565b6040516200022a919062002f0a565b3480156200037657600080fd5b50620002a86200038836600462002f84565b62000be4565b3480156200039b57600080fd5b50620002a8620003ad36600462002fc9565b62000c72565b348015620003c057600080fd5b50620002a8620003d236600462002fc9565b62000c9a565b348015620003e557600080fd5b50620002a8620003f736600462002e03565b62000d1c565b3480156200040a57600080fd5b50620003266101625481565b3480156200042357600080fd5b50620002a862000df1565b3480156200043b57600080fd5b50620004536200044d36600462002e03565b62000e17565b6040516200022a919062002ffc565b3480156200046f57600080fd5b50620002cf6200048136600462003011565b62000eba565b3480156200049457600080fd5b50620002a8620004a636600462002e03565b620012fd565b348015620004b957600080fd5b50620002cf620004cb366004620030c3565b6200139e565b620002a8620004e23660046200314e565b62001556565b348015620004f557600080fd5b50620002a862000507366004620031ea565b62001618565b3480156200051a57600080fd5b5060975460ff166200021e565b3480156200053457600080fd5b506200035a6200054636600462002e03565b6200172e565b3480156200055957600080fd5b50620002a8620018f5565b3480156200057157600080fd5b50620002a862001937565b3480156200058957600080fd5b50620002cf6200195d565b348015620005a157600080fd5b506200021e620005b336600462002fc9565b6200196c565b348015620005c657600080fd5b50620002a8620005d83660046200328d565b62001998565b348015620005eb57600080fd5b5062000326600081565b3480156200060257600080fd5b506200021e6200061436600462002bdc565b62001a6c565b3480156200062757600080fd5b5061016654620002cf906001600160a01b031681565b3480156200064a57600080fd5b50620002a86200065c366004620032ff565b62001b59565b3480156200066f57600080fd5b50620002a86200068136600462003335565b62001c12565b3480156200069457600080fd5b5061016754620002cf906001600160a01b031681565b348015620006b757600080fd5b50620002a8620006c936600462002e03565b62001e1c565b348015620006dc57600080fd5b5061016954620002cf906001600160a01b031681565b348015620006ff57600080fd5b50620002a86200071136600462002fc9565b62001e73565b3480156200072457600080fd5b50620003266200073636600462002e37565b6000908152610165602052604090205490565b3480156200075657600080fd5b50620002cf6200076836600462002e51565b6101646020908152600092835260408084209091529082529020546001600160a01b031681565b3480156200079c57600080fd5b5061016854620002cf906001600160a01b031681565b348015620007bf57600080fd5b50620002a8620007d136600462002e03565b62001e96565b348015620007e457600080fd5b50620002cf620007f636600462003387565b805160208183018101805161015f825292820191909301209152546001600160a01b031681565b60006001600160e01b03198216637965db0b60e01b14806200084f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60008051602062004af283398151915262000871813362001f42565b60006001600160a01b031661015f868660405162000891929190620033c7565b908152604051908190036020019020546001600160a01b031614620008d35760405162461bcd60e51b8152600401620008ca90620033d7565b60405180910390fd5b8261015f8686604051620008e9929190620033c7565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559185166000908152610160909152206200093090868662002a3f565b5060008051602062004a2b833981519152858585856040516200095794939291906200342f565b60405180910390a15050505050565b610167546001600160a01b03828116600090815261016360205260408082206001015490516331a9108f60e11b8152600481019190915290929190911690636352211e90602401602060405180830381865afa158015620009cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200084f919062003473565b600090815261012d602052604090206001015490565b62000a1162002ace565b6000838152610164602090815260408083208584528252808320546001600160a01b0316835261016390915290819020815160c081019092528054829060ff16600481111562000a655762000a6562002e74565b600481111562000a795762000a7962002e74565b8152602001600182015481526020016002820154815260200160038201805462000aa39062003493565b80601f016020809104026020016040519081016040528092919081815260200182805462000ad19062003493565b801562000b225780601f1062000af65761010080835404028352916020019162000b22565b820191906000526020600020905b81548152906001019060200180831162000b0457829003601f168201915b505050918352505060048201546001600160a01b0316602082015260058201805460409092019162000b549062003493565b80601f016020809104026020016040519081016040528092919081815260200182805462000b829062003493565b801562000bd35780601f1062000ba75761010080835404028352916020019162000bd3565b820191906000526020600020905b81548152906001019060200180831162000bb557829003601f168201915b505050505081525050905092915050565b60008051602062004af283398151915262000c00813362001f42565b7f1a066afb4a727dab9f80135f964045d9e6b7e75e1fa27bf957f29dcc024e43ed838360405162000c33929190620034d0565b60405180910390a161015f838360405162000c50929190620033c7565b90815260405190819003602001902080546001600160a01b0319169055505050565b62000c7d82620009f1565b62000c89813362001f42565b62000c95838362001fb1565b505050565b6001600160a01b038116331462000d0c5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401620008ca565b62000d1882826200203c565b5050565b306001600160a01b037f0000000000000000000000002822ee30383eabcba817ab4a7a592f4a194e14b516141562000d685760405162461bcd60e51b8152600401620008ca90620034e6565b7f0000000000000000000000002822ee30383eabcba817ab4a7a592f4a194e14b56001600160a01b031662000d9c620020a7565b6001600160a01b03161462000dc55760405162461bcd60e51b8152600401620008ca9062003521565b62000dd081620020c4565b6040805160008082526020820190925262000dee91839190620020f8565b50565b60008051602062004a8b83398151915262000e0d813362001f42565b62000dee62002252565b610160602052600090815260409020805462000e339062003493565b80601f016020809104026020016040519081016040528092919081815260200182805462000e619062003493565b801562000eb25780601f1062000e865761010080835404028352916020019162000eb2565b820191906000526020600020905b81548152906001019060200180831162000e9457829003601f168201915b505050505081565b600062000ec960975460ff1690565b1562000ee95760405162461bcd60e51b8152600401620008ca906200355c565b610169546001600160a01b031662000f395760405162461bcd60e51b815260206004820152601260248201527111995953585b9859d95c881b9bdd081cd95d60721b6044820152606401620008ca565b61016a546001600160a01b031662000f8b5760405162461bcd60e51b815260206004820152601460248201527315985d5b1d081a195b1c195c881b9bdd081cd95d60621b6044820152606401620008ca565b610167546040516331a9108f60e11b8152600481018790526001600160a01b0390911690636352211e90602401602060405180830381865afa15801562000fd6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ffc919062003473565b50600061015f8560405162001012919062003586565b908152604051908190036020019020546001600160a01b0316905080620010745760405162461bcd60e51b815260206004820152601560248201527410995858dbdb881a5cc81b9bdd081c1c995cd95b9d605a1b6044820152606401620008ca565b61016654600090829063246581f760e01b9087906001600160a01b03166200109b6200195d565b8c604051602401620010b19493929190620035a4565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620010f09062002b0e565b620010fd929190620035e4565b604051809103906000f0801580156200111a573d6000803e3d6000fd5b506001600160a01b03811660009081526101606020908152604090912088519293506200114c92909189019062002b1c565b50806001600160a01b0316631f2c54436040518163ffffffff1660e01b8152600401600060405180830381865afa925050508015620011af57506040513d6000823e601f3d908101601f19168201604052620011ac919081019062003767565b60015b6200122857604080516001600160a01b03831681526020808201839052818301527f4665652073657474696e67206661696c656420696e204665654d616e61676572606082015290517fe39bcf9e9fc06de4055c8d6665f0ef72c7bcc50f8f4b6882d2c408c996ef3eb59181900360800190a1620012a4565b83156200129f57610169546040516302d051b560e31b81526001600160a01b03909116906316828da8906200126a9088908890879087908a90600401620038d8565b600060405180830381600087803b1580156200128557600080fd5b505af11580156200129a573d6000803e3d6000fd5b505050505b505050505b620012b287828689620022e3565b867f3910bed511b4ecc0d6ae24498d585722a54c6ce9ab5e65b4be534cec981f7f6f33838989604051620012ea949392919062003981565b60405180910390a2979650505050505050565b33620013086200195d565b6001600160a01b031614620013315760405162461bcd60e51b8152600401620008ca90620039c1565b610169546001600160a01b0316156200137b5760405162461bcd60e51b815260206004820152600b60248201526a105b1c9958591e4814d95d60aa1b6044820152606401620008ca565b61016980546001600160a01b0319166001600160a01b0392909216919091179055565b600060008051602062004af2833981519152620013bc813362001f42565b60006001600160a01b031661015f8787604051620013dc929190620033c7565b908152604051908190036020019020546001600160a01b031614620014155760405162461bcd60e51b8152600401620008ca90620033d7565b600087604051620014269062002b99565b62001432919062002e23565b604051809103906000f0801580156200144f573d6000803e3d6000fd5b509050806001600160a01b031663f2fde38b6200146b6200195d565b6040518263ffffffff1660e01b815260040162001489919062002e23565b600060405180830381600087803b158015620014a457600080fd5b505af1158015620014b9573d6000803e3d6000fd5b505050508061015f8888604051620014d3929190620033c7565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b039485161790559183166000908152610160909152206200151a90888862002a3f565b5060008051602062004a2b83398151915287878a888860405162001543959493929190620039f6565b60405180910390a1979650505050505050565b306001600160a01b037f0000000000000000000000002822ee30383eabcba817ab4a7a592f4a194e14b5161415620015a25760405162461bcd60e51b8152600401620008ca90620034e6565b7f0000000000000000000000002822ee30383eabcba817ab4a7a592f4a194e14b56001600160a01b0316620015d6620020a7565b6001600160a01b031614620015ff5760405162461bcd60e51b8152600401620008ca9062003521565b6200160a82620020c4565b62000d1882826001620020f8565b60008051602062004ad283398151915262001634813362001f42565b8382146200166057604051630d07103b60e41b81526004810185905260248101839052604401620008ca565b60005b808514620017245783838281811062001680576200168062003a30565b905060200201602081019062001697919062003a46565b6101618989604051620016ac929190620033c7565b90815260200160405180910390206000888885818110620016d157620016d162003a30565b9050602002016020810190620016e8919062002bdc565b6001600160e01b03191681526020810191909152604001600020805460ff19169115159190911790556200171c8162003a80565b905062001663565b5050505050505050565b6200173862002ace565b6001600160a01b0382166000908152610163602052604090819020815160c081019092528054829060ff16600481111562001777576200177762002e74565b60048111156200178b576200178b62002e74565b81526020016001820154815260200160028201548152602001600382018054620017b59062003493565b80601f0160208091040260200160405190810160405280929190818152602001828054620017e39062003493565b8015620018345780601f10620018085761010080835404028352916020019162001834565b820191906000526020600020905b8154815290600101906020018083116200181657829003601f168201915b505050918352505060048201546001600160a01b03166020820152600582018054604090920191620018669062003493565b80601f0160208091040260200160405190810160405280929190818152602001828054620018949062003493565b8015620018e55780601f10620018b957610100808354040283529160200191620018e5565b820191906000526020600020905b815481529060010190602001808311620018c757829003601f168201915b5050505050815250509050919050565b33620019006200195d565b6001600160a01b031614620019295760405162461bcd60e51b8152600401620008ca90620039c1565b62001935600062002438565b565b60008051602062004a8b83398151915262001953813362001f42565b62000dee6200248a565b60c9546001600160a01b031690565b600091825261012d602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60008051602062004af2833981519152620019b4813362001f42565b60006001600160a01b031661015f8686604051620019d4929190620033c7565b908152604051908190036020019020546001600160a01b0316141562001a355760405162461bcd60e51b815260206004820152601560248201527410995858dbdb88191bd95cc81b9bdd08195e1a5cdd605a1b6044820152606401620008ca565b7f36f2c5b342695ee5dddbc5f4df3702d45b57810740060110c70c87e723e01cf88585858560405162000957949392919062003a9e565b33600090815261016060205260408120805482919062001a8c9062003493565b80601f016020809104026020016040519081016040528092919081815260200182805462001aba9062003493565b801562001b0b5780601f1062001adf5761010080835404028352916020019162001b0b565b820191906000526020600020905b81548152906001019060200180831162001aed57829003601f168201915b505050505090506101618160405162001b25919062003586565b90815260408051602092819003830190206001600160e01b0319959095166000908152949091529092205460ff1692915050565b3362001b646200195d565b6001600160a01b03161462001b8d5760405162461bcd60e51b8152600401620008ca90620039c1565b6001600160a01b038216600090815261016360205260409020805482919060ff1916600183600481111562001bc65762001bc662002e74565b0217905550816001600160a01b03167fb977ce68002d3b49b272b3ae970ad8a17b283cd2b5d40a674c888140bca7436b8260405162001c06919062003ac9565b60405180910390a25050565b600054610100900460ff1662001c2f5760005460ff161562001c33565b303b155b62001c985760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620008ca565b600054610100900460ff1615801562001cbb576000805461ffff19166101011790555b62001cc5620024e6565b62001ccf62002524565b62001cd962002562565b62001ce362002596565b6001600160a01b03831662001d0c5760405162461bcd60e51b8152600401620008ca9062003ad9565b6001600160a01b03821662001d355760405162461bcd60e51b8152600401620008ca9062003ad9565b6001600160a01b03841662001d5e5760405162461bcd60e51b8152600401620008ca9062003ad9565b61016680546001600160a01b038087166001600160a01b031992831617909255610167805486841690831617905561016880549285169290911691909117905562001dc060008051602062004a8b83398151915262001dba3390565b620025d4565b62001ddb60008051602062004af283398151915233620025d4565b62001df660008051602062004ad283398151915233620025d4565b62001e03600033620025d4565b801562001e16576000805461ff00191690555b50505050565b3362001e276200195d565b6001600160a01b03161462001e505760405162461bcd60e51b8152600401620008ca90620039c1565b61016a80546001600160a01b0319166001600160a01b0392909216919091179055565b62001e7e82620009f1565b62001e8a813362001f42565b62000c9583836200203c565b3362001ea16200195d565b6001600160a01b03161462001eca5760405162461bcd60e51b8152600401620008ca90620039c1565b6001600160a01b03811662001f315760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620008ca565b62000dee8162002438565b3b151590565b62001f4e82826200196c565b62000d185762001f69816001600160a01b03166014620025e0565b62001f76836020620025e0565b60405160200162001f8992919062003afd565b60408051601f198184030181529082905262461bcd60e51b8252620008ca9160040162002ffc565b62001fbd82826200196c565b62000d1857600082815261012d602090815260408083206001600160a01b03851684529091529020805460ff1916600117905562001ff83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6200204882826200196c565b1562000d1857600082815261012d602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008051602062004a6b833981519152546001600160a01b031690565b33620020cf6200195d565b6001600160a01b03161462000dee5760405162461bcd60e51b8152600401620008ca90620039c1565b600062002104620020a7565b90506200211184620027a0565b6000835111806200211f5750815b15620021335762002131848462002836565b505b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143805460ff166200224b57805460ff19166001178155604051620021b39086906200218390859060240162002e23565b60408051601f198184030181529190526020810180516001600160e01b0316631b2ce7f360e11b17905262002836565b50805460ff19168155620021c6620020a7565b6001600160a01b0316826001600160a01b031614620022405760405162461bcd60e51b815260206004820152602f60248201527f45524331393637557067726164653a207570677261646520627265616b73206660448201526e75727468657220757067726164657360881b6064820152608401620008ca565b6200224b856200292a565b5050505050565b60975460ff166200229d5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401620008ca565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051620022d9919062002e23565b60405180910390a1565b60008481526101656020908152604080832054610164835281842081855290925290912080546001600160a01b0319166001600160a01b0386161790556200232d81600162003b70565b600086815261016560205260409081902091909155805160c081019091528060018152602001868152602001610162600081546200236b9062003a80565b9182905550815260208082018690526001600160a01b0387166040808401829052606090930186905260009081526101639091522081518154829060ff19166001836004811115620023c157620023c162002e74565b021790555060208281015160018301556040830151600283015560608301518051620023f4926003850192019062002b1c565b5060808201516004820180546001600160a01b0319166001600160a01b0390921691909117905560a082015180516200172491600584019160209091019062002b1c565b60c980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60975460ff1615620024b05760405162461bcd60e51b8152600401620008ca906200355c565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258620022ca3390565b600054610100900460ff16620025105760405162461bcd60e51b8152600401620008ca9062003b8b565b6200251a6200296c565b620019356200296c565b600054610100900460ff166200254e5760405162461bcd60e51b8152600401620008ca9062003b8b565b620025586200296c565b6200193562002996565b600054610100900460ff166200258c5760405162461bcd60e51b8152600401620008ca9062003b8b565b620025106200296c565b600054610100900460ff16620025c05760405162461bcd60e51b8152600401620008ca9062003b8b565b620025ca6200296c565b62001935620029cb565b62000d18828262001fb1565b60606000620025f183600262003bd6565b620025fe90600262003b70565b6001600160401b0381111562002618576200261862002bfa565b6040519080825280601f01601f19166020018201604052801562002643576020820181803683370190505b509050600360fc1b8160008151811062002661576200266162003a30565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811062002693576200269362003a30565b60200101906001600160f81b031916908160001a9053506000620026b984600262003bd6565b620026c690600162003b70565b90505b600181111562002748576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620026fe57620026fe62003a30565b1a60f81b82828151811062002717576200271762003a30565b60200101906001600160f81b031916908160001a90535060049490941c93620027408162003bf8565b9050620026c9565b508315620027995760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620008ca565b9392505050565b803b620028065760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620008ca565b60008051602062004a6b83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060823b620028975760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401620008ca565b600080846001600160a01b031684604051620028b4919062003586565b600060405180830381855af49150503d8060008114620028f1576040519150601f19603f3d011682016040523d82523d6000602084013e620028f6565b606091505b509150915062002921828260405180606001604052806027815260200162004aab6027913962002a01565b95945050505050565b6200293581620027a0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b600054610100900460ff16620019355760405162461bcd60e51b8152600401620008ca9062003b8b565b600054610100900460ff16620029c05760405162461bcd60e51b8152600401620008ca9062003b8b565b620019353362002438565b600054610100900460ff16620029f55760405162461bcd60e51b8152600401620008ca9062003b8b565b6097805460ff19169055565b6060831562002a1257508162002799565b82511562002a235782518084602001fd5b8160405162461bcd60e51b8152600401620008ca919062002ffc565b82805462002a4d9062003493565b90600052602060002090601f01602090048101928262002a71576000855562002abc565b82601f1062002a8c5782800160ff1982351617855562002abc565b8280016001018555821562002abc579182015b8281111562002abc57823582559160200191906001019062002a9f565b5062002aca92915062002ba7565b5090565b6040805160c08101909152806000815260200160008152602001600081526020016060815260200160006001600160a01b03168152602001606081525090565b61090c8062003c1383390190565b82805462002b2a9062003493565b90600052602060002090601f01602090048101928262002b4e576000855562002abc565b82601f1062002b6957805160ff191683800117855562002abc565b8280016001018555821562002abc579182015b8281111562002abc57825182559160200191906001019062002b7c565b61050c806200451f83390190565b5b8082111562002aca576000815560010162002ba8565b80356001600160e01b03198116811462002bd757600080fd5b919050565b60006020828403121562002bef57600080fd5b620027998262002bbe565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562002c3b5762002c3b62002bfa565b604052919050565b60006001600160401b0382111562002c5f5762002c5f62002bfa565b50601f01601f191660200190565b600082601f83011262002c7f57600080fd5b813562002c9662002c908262002c43565b62002c10565b81815284602083860101111562002cac57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121562002cdd57600080fd5b82356001600160401b0381111562002cf457600080fd5b62002d028582860162002c6d565b92505062002d136020840162002bbe565b90509250929050565b60008083601f84011262002d2f57600080fd5b5081356001600160401b0381111562002d4757600080fd5b60208301915083602082850101111562002d6057600080fd5b9250929050565b6001600160a01b038116811462000dee57600080fd5b6000806000806060858703121562002d9457600080fd5b84356001600160401b038082111562002dac57600080fd5b62002dba8883890162002d1c565b90965094506020870135915062002dd18262002d67565b9092506040860135908082111562002de857600080fd5b5062002df78782880162002c6d565b91505092959194509250565b60006020828403121562002e1657600080fd5b8135620027998162002d67565b6001600160a01b0391909116815260200190565b60006020828403121562002e4a57600080fd5b5035919050565b6000806040838503121562002e6557600080fd5b50508035926020909101359150565b634e487b7160e01b600052602160045260246000fd5b6005811062002ea957634e487b7160e01b600052602160045260246000fd5b9052565b60005b8381101562002eca57818101518382015260200162002eb0565b8381111562001e165750506000910152565b6000815180845262002ef681602086016020860162002ead565b601f01601f19169290920160200192915050565b6020815262002f1e60208201835162002e8a565b60208201516040820152604082015160608201526000606083015160c0608084015262002f4f60e084018262002edc565b60808501516001600160a01b031660a085810191909152850151848203601f190160c086015290915062002921828262002edc565b6000806020838503121562002f9857600080fd5b82356001600160401b0381111562002faf57600080fd5b62002fbd8582860162002d1c565b90969095509350505050565b6000806040838503121562002fdd57600080fd5b82359150602083013562002ff18162002d67565b809150509250929050565b60208152600062002799602083018462002edc565b600080600080600060a086880312156200302a57600080fd5b85356001600160401b03808211156200304257600080fd5b6200305089838a0162002c6d565b96506020880135955060408801359150808211156200306e57600080fd5b6200307c89838a0162002c6d565b945060608801359150620030908262002d67565b90925060808701359080821115620030a757600080fd5b50620030b68882890162002c6d565b9150509295509295909350565b600080600080600060608688031215620030dc57600080fd5b8535620030e98162002d67565b945060208601356001600160401b03808211156200310657600080fd5b6200311489838a0162002d1c565b909650945060408801359150808211156200312e57600080fd5b506200313d8882890162002d1c565b969995985093965092949392505050565b600080604083850312156200316257600080fd5b82356200316f8162002d67565b915060208301356001600160401b038111156200318b57600080fd5b620031998582860162002c6d565b9150509250929050565b60008083601f840112620031b657600080fd5b5081356001600160401b03811115620031ce57600080fd5b6020830191508360208260051b850101111562002d6057600080fd5b600080600080600080606087890312156200320457600080fd5b86356001600160401b03808211156200321c57600080fd5b6200322a8a838b0162002d1c565b909850965060208901359150808211156200324457600080fd5b620032528a838b01620031a3565b909650945060408901359150808211156200326c57600080fd5b506200327b89828a01620031a3565b979a9699509497509295939492505050565b60008060008060408587031215620032a457600080fd5b84356001600160401b0380821115620032bc57600080fd5b620032ca8883890162002d1c565b90965094506020870135915080821115620032e457600080fd5b50620032f38782880162002d1c565b95989497509550505050565b600080604083850312156200331357600080fd5b8235620033208162002d67565b915060208301356005811062002ff157600080fd5b6000806000606084860312156200334b57600080fd5b8335620033588162002d67565b925060208401356200336a8162002d67565b915060408401356200337c8162002d67565b809150509250925092565b6000602082840312156200339a57600080fd5b81356001600160401b03811115620033b157600080fd5b620033bf8482850162002c6d565b949350505050565b8183823760009101908152919050565b602080825260159082015274426561636f6e20616c72656164792065786973747360581b604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006200344560608301868862003406565b6001600160a01b0385166020840152828103604084015262003468818562002edc565b979650505050505050565b6000602082840312156200348657600080fd5b8151620027998162002d67565b600181811c90821680620034a857607f821691505b60208210811415620034ca57634e487b7160e01b600052602260045260246000fd5b50919050565b602081526000620033bf60208301848662003406565b6020808252602c9082015260008051602062004a4b83398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c9082015260008051602062004a4b83398151915260408201526b6163746976652070726f787960a01b606082015260800190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b600082516200359a81846020870162002ead565b9190910192915050565b6001600160a01b038581168252848116602083015283166040820152608060608201819052600090620035da9083018462002edc565b9695505050505050565b6001600160a01b0383168152604060208201819052600090620033bf9083018462002edc565b60006001600160401b0382111562003626576200362662002bfa565b5060051b60200190565b600082601f8301126200364257600080fd5b815160206200365562002c90836200360a565b82815260059290921b840181019181810190868411156200367557600080fd5b8286015b84811015620036fa5780516001600160401b038111156200369a5760008081fd5b8701603f81018913620036ad5760008081fd5b848101516040620036c262002c908362002c43565b8281528b82848601011115620036d85760008081fd5b620036e98389830184870162002ead565b865250505091830191830162003679565b509695505050505050565b600082601f8301126200371757600080fd5b815160206200372a62002c90836200360a565b82815260059290921b840181019181810190868411156200374a57600080fd5b8286015b84811015620036fa57805183529183019183016200374e565b600080600080608085870312156200377e57600080fd5b8451602080870151919550906001600160401b0380821115620037a057600080fd5b818801915088601f830112620037b557600080fd5b8151620037c662002c90826200360a565b81815260059190911b8301840190848101908b831115620037e657600080fd5b938501935b8285101562003811578451620038018162002d67565b82529385019390850190620037eb565b60408b015190985094505050808311156200382b57600080fd5b6200383989848a0162003630565b945060608801519250808311156200385057600080fd5b505062002df78782880162003705565b600081518084526020808501945080840160005b83811015620038925781518752958201959082019060010162003874565b509495945050505050565b600081518084526020808501945080840160005b83811015620038925781516001600160a01b031687529582019590820190600101620038b1565b600060a0820160018060a01b03881683526020878185015260a0604085015281875180845260c08601915060c08160051b870101935082890160005b82811015620039465760bf198887030184526200393386835162002edc565b9550928401929084019060010162003914565b505050505082810360608401526200395f818662003860565b905082810360808401526200397581856200389d565b98975050505050505050565b600060018060a01b038087168352808616602084015260806040840152620039ad608084018662002edc565b915080841660608401525095945050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60608152600062003a0c60608301878962003406565b6001600160a01b038616602084015282810360408401526200397581858762003406565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562003a5957600080fd5b813580151581146200279957600080fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141562003a975762003a9762003a6a565b5060010190565b60408152600062003ab460408301868862003406565b82810360208401526200346881858762003406565b602081016200084f828462002e8a565b6020808252600a90820152696164647265737328302960b01b604082015260600190565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b81526000835162003b3181601785016020880162002ead565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835162003b6481602884016020880162002ead565b01602801949350505050565b6000821982111562003b865762003b8662003a6a565b500190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600081600019048311821515161562003bf35762003bf362003a6a565b500290565b60008162003c0a5762003c0a62003a6a565b50600019019056fe608060405260405161090c38038061090c83398101604081905261002291610460565b61002e82826000610035565b505061058a565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610520565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610520565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108e5602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053b565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c65782516103bf576001600160a01b0385163b6103bf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d0565b6103d083836103d8565b949350505050565b8151156103e85781518083602001fd5b8060405162461bcd60e51b81526004016101699190610557565b80516001600160a01b038116811461041957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561044f578181015183820152602001610437565b838111156100f95750506000910152565b6000806040838503121561047357600080fd5b61047c83610402565b60208401519092506001600160401b038082111561049957600080fd5b818501915085601f8301126104ad57600080fd5b8151818111156104bf576104bf61041e565b604051601f8201601f19908116603f011681019083821181831017156104e7576104e761041e565b8160405282815288602084870101111561050057600080fd5b610511836020830160208801610434565b80955050505050509250929050565b60006020828403121561053257600080fd5b6102c882610402565b6000825161054d818460208701610434565b9190910192915050565b6020815260008251806020840152610576816040850160208701610434565b601f01601f19169190910160400192915050565b61034c806105996000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f060279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb9190610247565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a0565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b6060831561020b578251610204576101b385610055565b6102045760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610215565b610215838361021d565b949350505050565b81511561022d5781518083602001fd5b8060405162461bcd60e51b81526004016101fb91906102bc565b60006020828403121561025957600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b8381101561028b578181015183820152602001610273565b8381111561029a576000848401525b50505050565b600082516102b2818460208701610270565b9190910192915050565b60208152600082518060208401526102db816040850160208701610270565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220c149cc587c459fdcb5b0b327a81fc3a237cb5f545f983075dc92d02083b7eab964736f6c634300080c0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564608060405234801561001057600080fd5b5060405161050c38038061050c83398101604081905261002f91610179565b61003833610047565b61004181610097565b506101a9565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6100aa8161016a60201b6101751760201c565b6101205760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f60448201527f6e206973206e6f74206120636f6e747261637400000000000000000000000000606482015260840160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03163b151590565b60006020828403121561018b57600080fd5b81516001600160a01b03811681146101a257600080fd5b9392505050565b610354806101b86000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80635c60da1b1461005c5780635c879c101461008b578063715018a6146100a05780638da5cb5b146100a8578063f2fde38b146100b0575b600080fd5b60015461006f906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61009e6100993660046102ee565b6100c3565b005b61009e6100d7565b61006f6100eb565b61009e6100be3660046102ee565b6100fa565b6100cb610184565b6100d4816101e3565b50565b6100df610184565b6100e9600061029e565b565b6000546001600160a01b031690565b610102610184565b6001600160a01b03811661016c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6100d48161029e565b6001600160a01b03163b151590565b3361018d6100eb565b6001600160a01b0316146100e95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610163565b6101ec81610175565b6102545760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b6064820152608401610163565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561030057600080fd5b81356001600160a01b038116811461031757600080fd5b939250505056fea264697066735822122033f2e14e99437c22a1cd8960cb6201771a12eb7f1602bea314497be31bab8fb064736f6c634300080c003324465a1f9a55eb0e9691adbdc0160061ace64f7309611b6aa3add1f00b178d0f46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65645f36c4325e7b3e3c355f553dd2d909e309f22530e6b36ae3260b053f89fb8c2143c4ee843c388ace340d7c40a79a882e9cb3437dbb4d5f773148b941fef1a5afa2646970667358221220719512b2ee1c1ea37b8d9af0d2ca84425a080ae9b16b92502569c18012a39ed864736f6c634300080c0033