Contract 0xca84835655a8e863d34875326419a46f823320f6

 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xe77c721b4326f4a6dcd5464f251bfbbe0c369d7c8a4d17704d235d6d6c6c67250x60806040178426922021-08-10 20:23:16409 days 19 hrs ago0xacaabb76e70c7a99693e9057e627088f5fec443d IN  Contract Creation0 MATIC0.00580374521.1
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xe50dddd477241953df249db2cbb50c9554dd1c2b

Contract Name:
MinterAmm

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 1 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity Multiple files format)

File 1 of 26: MinterAmm.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

import "./IERC1155.sol";
import "./SafeERC20.sol";
import "./OwnableUpgradeable.sol";
import "./ERC1155HolderUpgradeable.sol";
import "./ISeriesController.sol";
import "./Proxiable.sol";
import "./Proxy.sol";
import "./Math.sol";
import "./InitializeableAmm.sol";
import "./IAddSeriesToAmm.sol";
import "./IPriceOracle.sol";
import "./ISimpleToken.sol";
import "./IERC20Lib.sol";
import "./EnumerableSet.sol";
import "./SeriesLibrary.sol";

/// This is an implementation of a minting/redeeming AMM (Automated Market Maker) that trades a list of series with the same
/// collateral token. For example, a single WBTC Call AMM contract can trade all strikes of WBTC calls using
/// WBTC as the collateral, and a single WBTC Put AMM contract can trade all strikes of WBTC puts, using
/// USDC as the collateral.
///
/// Each AMM uses a triplet of ERC20 tokens to define the option asset whose price determines the option's value
/// (the underlyingToken), the token used to denominate the strike price (the priceToken) and the token used
/// as collateral writing the option (the collateralToken). The collateralToken also determines the units used
/// in pricing the option's premiums.
///
/// It uses an on-chain Black-Scholes approximation to calculate the price of a single option (which we represent by an
/// ERC1155 token we call "bToken"). The Black-Scholes approximation uses an on-chain oracle price feed to get the
/// current series price of the underlying asset. By using an on-chain oracle the AMM's bonding curve is aware of the
/// time-dependent nature of options pricing (a.k.a. theta-decay), and can price options better than a naive constant
/// product bonding curve such as Uniswap.
///
/// In addition, it uses a novel "mint aware bonding curve" to allow for infinite depth when buying options. A user
/// pays for options in units of the AMM's collateral token, and the AMM uses this collateral to mint additional bTokens
/// to satisfy the user's trade size
///
/// External users can buy bTokens with collateral (wToken trading is disabled in this version).
/// When they do this, the AMM will mint new bTokens and wTokens, sell the wToken to the AMM for more bToken,
/// and transfer the bToken to the user.
///
/// External users can sell bTokens for collateral. When they do this, the AMM will sell a partial amount of assets
/// to get a 50/50 split between bTokens and wTokens, then redeem them for collateral and transfer the collateral back to
/// the user.
///
/// LPs can provide collateral for liquidity. All collateral will be used to mint bTokens/wTokens for each trade.
/// They will be given a corresponding amount of lpTokens to track ownership. The amount of lpTokens is calculated based on
/// total pool value which includes collateral token, active b/wTokens and expired/unclaimed b/wTokens
///
/// LPs can withdraw collateral from liquidity. When withdrawing user can specify if they want their pro-rata b/wTokens
/// to be automatically sold to the pool for collateral. If the chose not to sell then they get pro-rata of all tokens
/// in the pool (collateral, bToken, wToken). If they chose to sell then their bTokens and wTokens will be sold
/// to the pool for collateral incurring slippage.
///
/// All expired unclaimed wTokens are automatically claimed on each deposit or withdrawal
///
/// All conversions between bToken and wToken in the AMM will generate fees that will be send to the protocol fees pool
/// (disabled in this version)
contract MinterAmm is
    InitializeableAmm,
    ERC1155HolderUpgradeable,
    IAddSeriesToAmm,
    OwnableUpgradeable,
    Proxiable
{
    /// Use safe ERC20 functions for any token transfers since people don't follow the ERC20 standard */
    using SafeERC20 for IERC20;
    using SafeERC20 for ISimpleToken;

    using EnumerableSet for EnumerableSet.UintSet;

    /// @dev The token contract that will track lp ownership of the AMM
    ISimpleToken public lpToken;

    /// @dev The ERC20 tokens used by all the Series associated with this AMM
    IERC20 public underlyingToken;
    IERC20 public priceToken;
    IERC20 public collateralToken;

    /// @dev The registry which the AMM will use to lookup individual Series
    ISeriesController public seriesController;

    /// @notice The contract used to mint the option tokens
    IERC1155 public erc1155Controller;

    /// @dev Fees on trading
    uint16 public tradeFeeBasisPoints;

    /// Volatility factor used in the black scholes approximation - can be updated by the owner */
    uint256 public volatilityFactor;

    /// @dev Flag to ensure initialization can only happen once
    bool initialized = false;

    uint256 public constant MINIMUM_TRADE_SIZE = 1000;

    /// @dev A price oracle contract used to get onchain price data
    address private sirenPriceOracle;

    /// @dev Collection of ids of open series
    /// @dev If we ever re-deploy MinterAmm we need to check that the EnumerableSet implementation hasn’t changed,
    /// because we rely on undocumented implementation details (see Note in MinterAmm.claimAllExpiredTokens on
    /// removing series)
    EnumerableSet.UintSet private openSeries;

    /// Emitted when the amm is created
    event AMMInitialized(
        ISimpleToken lpToken,
        address sirenPriceOracle,
        address controller
    );

    /// Emitted when an LP deposits collateral
    event LpTokensMinted(
        address minter,
        uint256 collateralAdded,
        uint256 lpTokensMinted
    );

    /// Emitted when an LP withdraws collateral
    event LpTokensBurned(
        address redeemer,
        uint256 collateralRemoved,
        uint256 lpTokensBurned
    );

    /// Emitted when a user buys bTokens from the AMM
    event BTokensBought(
        address buyer,
        uint64 seriesId,
        uint256 bTokensBought,
        uint256 collateralPaid
    );

    /// Emitted when a user sells bTokens to the AMM
    event BTokensSold(
        address seller,
        uint64 seriesId,
        uint256 bTokensSold,
        uint256 collateralPaid
    );

    /// Emitted when a user sells wTokens to the AMM
    event WTokensSold(
        address seller,
        uint64 seriesId,
        uint256 wTokensSold,
        uint256 collateralPaid
    );

    /// Emitted when the owner updates volatilityFactor
    event VolatilityFactorUpdated(uint256 newVolatilityFactor);

    /// Emitted when a new sirenPriceOracle gets set on an upgraded AMM
    event NewSirenPriceOracle(address newSirenPriceOracle);

    /// @notice Emitted when an expired series has been removed
    event SeriesEvicted(uint64 seriesId);

    // Error codes. We only use error code because we need to reduce the size of this contract's deployed
    // bytecode in order for it to be deployable

    // E02: Invalid _sirenPriceOracle
    // E03: Invalid _underlyingToken
    // E04: Invalid _priceToken
    // E05: Invalid _collateralToken
    // E06: _underlyingToken cannot equal _priceToken
    // E07: Invalid _tokenImplementation
    // E08: Contract can only be initialized once
    // E09: VolatilityFactor is too low
    // E10: Invalid _newImplementation
    // E11: Can only be called by SeriesController
    // E12: withdrawCapital: collateralMinimum must be set

    /// @dev Require minimum trade size to prevent precision errors at low values
    modifier minTradeSize(uint256 tradeSize) {
        require(
            tradeSize >= MINIMUM_TRADE_SIZE,
            "Buy/Sell amount below min size"
        );
        _;
    }

    /// Initialize the contract, and create an lpToken to track ownership
    function initialize(
        ISeriesController _seriesController,
        address _sirenPriceOracle,
        IERC20 _underlyingToken,
        IERC20 _priceToken,
        IERC20 _collateralToken,
        address _tokenImplementation,
        uint16 _tradeFeeBasisPoints
    ) public override {
        require(address(_sirenPriceOracle) != address(0x0), "E02");
        require(address(_underlyingToken) != address(0x0), "E03");
        require(address(_priceToken) != address(0x0), "E04");
        require(address(_collateralToken) != address(0x0), "E05");
        require(address(_underlyingToken) != address(_priceToken), "E06");
        require(_tokenImplementation != address(0x0), "E07");

        // Enforce initialization can only happen once
        require(!initialized, "E08");
        initialized = true;

        // Save off state variables
        seriesController = _seriesController;
        erc1155Controller = IERC1155(_seriesController.erc1155Controller());

        // Approve seriesController to move tokens
        erc1155Controller.setApprovalForAll(address(seriesController), true);

        sirenPriceOracle = _sirenPriceOracle;
        tradeFeeBasisPoints = _tradeFeeBasisPoints;

        // Save off series tokens
        underlyingToken = _underlyingToken;
        priceToken = _priceToken;
        collateralToken = _collateralToken;

        // Create the lpToken and initialize it
        Proxy lpTokenProxy = new Proxy(_tokenImplementation);
        lpToken = ISimpleToken(address(lpTokenProxy));

        // AMM name will be <underlying>-<price>-<collateral>, e.g. WBTC-USDC-WBTC for a WBTC Call AMM
        string memory ammName =
            string(
                abi.encodePacked(
                    IERC20Lib(address(underlyingToken)).symbol(),
                    "-",
                    IERC20Lib(address(priceToken)).symbol(),
                    "-",
                    IERC20Lib(address(collateralToken)).symbol()
                )
            );
        string memory lpTokenName = string(abi.encodePacked("LP-", ammName));
        lpToken.initialize(
            lpTokenName,
            lpTokenName,
            IERC20Lib(address(collateralToken)).decimals()
        );

        // Set default volatility
        // 0.4 * volInSeconds * 1e18
        volatilityFactor = 4000e10;

        __Ownable_init();

        emit AMMInitialized(
            lpToken,
            _sirenPriceOracle,
            address(_seriesController)
        );
    }

    /// The owner can set the volatility factor used to price the options
    function setVolatilityFactor(uint256 _volatilityFactor) public onlyOwner {
        // Check lower bounds: 500e10 corresponds to ~7% annualized volatility
        require(_volatilityFactor > 500e10, "E09");

        volatilityFactor = _volatilityFactor;
        emit VolatilityFactorUpdated(_volatilityFactor);
    }

    /// @notice update the logic contract for this proxy contract
    /// @param _newImplementation the address of the new MinterAmm implementation
    /// @dev only the admin address may call this function
    function updateImplementation(address _newImplementation)
        external
        onlyOwner
    {
        require(_newImplementation != address(0x0), "E10");

        _updateCodeAddress(_newImplementation);
    }

    /// LP allows collateral to be used to mint new options
    /// bTokens and wTokens will be held in this contract and can be traded back and forth.
    /// The amount of lpTokens is calculated based on total pool value
    function provideCapital(uint256 collateralAmount, uint256 lpTokenMinimum)
        external
    {
        // Move collateral into this contract
        collateralToken.safeTransferFrom(
            msg.sender,
            address(this),
            collateralAmount
        );

        // If first LP, mint options, mint LP tokens, and send back any redemption amount
        if (IERC20Lib(address(lpToken)).totalSupply() == 0) {
            // Mint lp tokens to the user
            lpToken.mint(msg.sender, collateralAmount);

            // Emit event
            LpTokensMinted(msg.sender, collateralAmount, collateralAmount);

            // Bail out after initial tokens are minted - nothing else to do
            return;
        }

        // At any given moment the AMM can have the following reserves:
        // * collateral token
        // * active bTokens and wTokens for any series
        // * expired bTokens and wTokens for any series
        // In order to calculate correct LP amount we do the following:
        // 1. Claim expired wTokens and bTokens
        // 2. Add value of all active bTokens and wTokens at current prices
        // 3. Add value of collateral

        claimAllExpiredTokens();

        uint256 poolValue = getTotalPoolValue(false);

        // Mint LP tokens - the percentage added to bTokens should be same as lp tokens added
        uint256 lpTokenExistingSupply =
            IERC20Lib(address(lpToken)).totalSupply();

        uint256 lpTokensNewSupply =
            (poolValue * lpTokenExistingSupply) /
                (poolValue - collateralAmount);
        uint256 lpTokensToMint = lpTokensNewSupply - lpTokenExistingSupply;
        require(lpTokensToMint >= lpTokenMinimum, "Slippage exceeded");
        lpToken.mint(msg.sender, lpTokensToMint);

        // Emit event
        emit LpTokensMinted(msg.sender, collateralAmount, lpTokensToMint);
    }

    /// LP can redeem their LP tokens in exchange for collateral
    /// If `sellTokens` is true pro-rata active b/wTokens will be sold to the pool in exchange for collateral
    /// All expired wTokens will be claimed
    /// LP will get pro-rata collateral asset
    function withdrawCapital(
        uint256 lpTokenAmount,
        bool sellTokens,
        uint256 collateralMinimum
    ) public {
        require(!sellTokens || collateralMinimum > 0, "E12");
        // First get starting numbers
        uint256 redeemerCollateralBalance =
            collateralToken.balanceOf(msg.sender);

        // Get the lpToken supply
        uint256 lpTokenSupply = IERC20Lib(address(lpToken)).totalSupply();

        // Burn the lp tokens
        lpToken.burn(msg.sender, lpTokenAmount);

        // Claim all expired wTokens
        claimAllExpiredTokens();

        uint256 collateralTokenBalance =
            collateralToken.balanceOf(address(this));

        // Withdraw pro-rata collateral token
        // We withdraw this collateral here instead of at the end,
        // because when we sell the residual tokens to the pool we want
        // to exclude the withdrawn collateral
        uint256 ammCollateralBalance =
            collateralTokenBalance -
                ((collateralTokenBalance * lpTokenAmount) / lpTokenSupply);

        // Sell pro-rata active tokens or withdraw if no collateral left
        ammCollateralBalance = _sellOrWithdrawActiveTokens(
            lpTokenAmount,
            lpTokenSupply,
            msg.sender,
            sellTokens,
            ammCollateralBalance
        );

        // Send all accumulated collateralTokens
        collateralToken.safeTransfer(
            msg.sender,
            collateralTokenBalance - ammCollateralBalance
        );

        uint256 collateralTokenSent =
            collateralToken.balanceOf(msg.sender) - redeemerCollateralBalance;

        require(
            !sellTokens || collateralTokenSent >= collateralMinimum,
            "Slippage exceeded"
        );

        // Emit the event
        emit LpTokensBurned(msg.sender, collateralTokenSent, lpTokenAmount);
    }

    /// @notice Claims any remaining collateral from all expired series whose wToken is held by the AMM, and removes
    /// the expired series from the AMM's collection of series
    function claimAllExpiredTokens() public {
        for (uint256 i = 0; i < openSeries.length(); i++) {
            uint64 seriesId = uint64(openSeries.at(i));
            while (
                seriesController.state(seriesId) ==
                ISeriesController.SeriesState.EXPIRED
            ) {
                claimExpiredTokens(seriesId);

                // Handle edge case: If, prior to removing the Series, i was the index of the last Series
                // in openSeries, then after the removal `i` will point to one beyond the end of the array.
                // This means we've iterated through all of the Series in `openSeries`, and we should break
                // out of the while loop. At this point i == openSeries.length(), so the outer for loop
                // will end as well
                if (i == openSeries.length()) {
                    break;
                } else {
                    seriesId = uint64(openSeries.at(i));
                }
            }
        }
    }

    /// @notice Claims any remaining collateral from expired series whose wToken is held by the AMM, and removes
    /// the expired series from the AMM's collection of series
    function claimExpiredTokens(uint64 seriesId) public {
        // claim the expired series' wTokens, which means it can now be safely removed
        uint256 bTokenIndex = SeriesLibrary.bTokenIndex(seriesId);
        uint256 wTokenIndex = SeriesLibrary.wTokenIndex(seriesId);

        uint256 bTokenBalance =
            erc1155Controller.balanceOf(address(this), bTokenIndex);
        if (bTokenBalance > 0) {
            seriesController.exerciseOption(seriesId, bTokenBalance, false);
        }

        uint256 wTokenBalance =
            erc1155Controller.balanceOf(address(this), wTokenIndex);
        if (wTokenBalance > 0) {
            seriesController.claimCollateral(seriesId, wTokenBalance);
        }
        // Remove the expired series to free storage and reduce gas fee
        // NOTE: openSeries.remove will remove the series from the i’th position in the EnumerableSet by
        // swapping it with the last element in EnumerableSet and then calling .pop on the internal array.
        // We are relying on this undocumented behavior of EnumerableSet, which is acceptable because once
        // deployed we will never change the EnumerableSet logic.
        openSeries.remove(seriesId);

        emit SeriesEvicted(seriesId);
    }

    /// During liquidity withdrawal we either sell pro-rata active tokens back to the pool
    /// or withdraw them to the LP
    function _sellOrWithdrawActiveTokens(
        uint256 lpTokenAmount,
        uint256 lpTokenSupply,
        address redeemer,
        bool sellTokens,
        uint256 collateralLeft
    ) internal returns (uint256) {
        for (uint256 i = 0; i < openSeries.length(); i++) {
            uint64 seriesId = uint64(openSeries.at(i));
            if (
                seriesController.state(seriesId) ==
                ISeriesController.SeriesState.OPEN
            ) {
                uint256 bTokenIndex = SeriesLibrary.bTokenIndex(seriesId);
                uint256 wTokenIndex = SeriesLibrary.wTokenIndex(seriesId);

                uint256 bTokenToSell =
                    (erc1155Controller.balanceOf(address(this), bTokenIndex) *
                        lpTokenAmount) / lpTokenSupply;
                uint256 wTokenToSell =
                    (erc1155Controller.balanceOf(address(this), wTokenIndex) *
                        lpTokenAmount) / lpTokenSupply;
                if (!sellTokens || lpTokenAmount == lpTokenSupply) {
                    // Full LP token withdrawal for the last LP in the pool
                    // or if auto-sale is disabled
                    if (bTokenToSell > 0) {
                        bytes memory data;
                        erc1155Controller.safeTransferFrom(
                            address(this),
                            redeemer,
                            bTokenIndex,
                            bTokenToSell,
                            data
                        );
                    }
                    if (wTokenToSell > 0) {
                        bytes memory data;
                        erc1155Controller.safeTransferFrom(
                            address(this),
                            redeemer,
                            wTokenIndex,
                            wTokenToSell,
                            data
                        );
                    }
                } else {
                    // The LP sells their bToken and wToken to the AMM. The AMM
                    // pays the LP by reducing collateralLeft, which is what the
                    // AMM's collateral balance will be after executing this
                    // transaction (see MinterAmm.withdrawCapital to see where
                    // _sellOrWithdrawActiveTokens gets called)
                    uint256 collateralAmountB =
                        optionTokenGetCollateralOutInternal(
                            seriesId,
                            bTokenToSell,
                            collateralLeft,
                            true
                        );

                    // Note! It's possible that either of the two subraction operations
                    // below will underflow and return an error. This will only
                    // happen if the AMM does not have sufficient collateral
                    // balance to buy the bToken and wToken from the LP. If this
                    // happens, this transaction will revert with a
                    // "revert" error message
                    collateralLeft -= collateralAmountB;
                    uint256 collateralAmountW =
                        optionTokenGetCollateralOutInternal(
                            seriesId,
                            wTokenToSell,
                            collateralLeft,
                            false
                        );
                    collateralLeft -= collateralAmountW;
                }
            }
        }

        return collateralLeft;
    }

    /// Get value of all assets in the pool in units of this AMM's collateralToken.
    /// Can specify whether to include the value of expired unclaimed tokens
    function getTotalPoolValue(bool includeUnclaimed)
        public
        view
        returns (uint256)
    {
        // Note! This function assumes the price obtained from the onchain oracle
        // in getCurrentUnderlyingPrice is a valid series price in units of
        // collateralToken/paymentToken. If the onchain price oracle's value
        // were to drift from the true series price, then the bToken price
        // we calculate here would also drift, and will result in undefined
        // behavior for any functions which call getTotalPoolValue
        uint256 underlyingPrice = getCurrentUnderlyingPrice();
        // First, determine the value of all residual b/wTokens
        uint256 activeTokensValue = 0;
        uint256 expiredTokensValue = 0;
        for (uint256 i = 0; i < openSeries.length(); i++) {
            uint64 seriesId = uint64(openSeries.at(i));
            ISeriesController.Series memory series =
                seriesController.series(seriesId);

            uint256 bTokenIndex = SeriesLibrary.bTokenIndex(seriesId);
            uint256 wTokenIndex = SeriesLibrary.wTokenIndex(seriesId);

            uint256 bTokenBalance =
                erc1155Controller.balanceOf(address(this), bTokenIndex);
            uint256 wTokenBalance =
                erc1155Controller.balanceOf(address(this), wTokenIndex);

            if (
                seriesController.state(seriesId) ==
                ISeriesController.SeriesState.OPEN
            ) {
                // value all active bTokens and wTokens at current prices
                uint256 bPrice =
                    getPriceForSeriesInternal(series, underlyingPrice);
                // wPrice = 1 - bPrice
                uint256 wPrice = uint256(1e18) - bPrice;

                uint256 tokensValueCollateral =
                    seriesController.getCollateralPerOptionToken(
                        seriesId,
                        (bTokenBalance * bPrice + wTokenBalance * wPrice) / 1e18
                    );

                activeTokensValue += tokensValueCollateral;
            } else if (
                includeUnclaimed &&
                seriesController.state(seriesId) ==
                ISeriesController.SeriesState.EXPIRED
            ) {
                // Get collateral token locked in the series
                expiredTokensValue += getRedeemableCollateral(
                    seriesId,
                    wTokenBalance,
                    bTokenBalance
                );
            }
        }

        // Add collateral value
        uint256 collateralBalance = collateralToken.balanceOf(address(this));

        return activeTokensValue + expiredTokensValue + collateralBalance;
    }

    /// @notice List the Series ids this AMM trades
    /// @notice Warning: there is no guarantee that the indexes
    /// of any individual Series will remain constant between blocks. At any
    /// point the indexes of a particular Series may change, so do not rely on
    /// the indexes obtained from this function
    /// @return an array of all the series IDs
    function getAllSeries() external view returns (uint64[] memory) {
        uint64[] memory series = new uint64[](openSeries.length());
        for (uint256 i = 0; i < openSeries.length(); i++) {
            series[i] = uint64(openSeries.at(i));
        }
        return series;
    }

    /// @notice Get a specific Series that this AMM trades
    /// @notice Warning: there is no guarantee that the indexes
    /// of any individual Series will remain constant between blocks. At any
    /// point the indexes of a particular Series may change, so do not rely on
    /// the indexes obtained from this function
    /// @param seriesId the ID of the Series
    /// @return an ISeries, if it exists
    function getSeries(uint64 seriesId)
        external
        view
        returns (ISeriesController.Series memory)
    {
        require(openSeries.contains(seriesId), "E13");
        return seriesController.series(seriesId);
    }

    /// This function determines reserves of a bonding curve for a specific series.
    /// Given price of bToken we determine what is the largest pool we can create such that
    /// the ratio of its reserves satisfy the given bToken price: Rb / Rw = (1 - Pb) / Pb
    function getVirtualReserves(uint64 seriesId)
        public
        view
        returns (uint256, uint256)
    {
        require(openSeries.contains(seriesId), "E13");

        return
            getVirtualReservesInternal(
                seriesId,
                collateralToken.balanceOf(address(this))
            );
    }

    function getVirtualReservesInternal(
        uint64 seriesId,
        uint256 collateralTokenBalance
    ) internal view returns (uint256, uint256) {
        uint256 bTokenIndex = SeriesLibrary.bTokenIndex(seriesId);
        uint256 wTokenIndex = SeriesLibrary.wTokenIndex(seriesId);

        // Get residual balances
        uint256 bTokenBalance =
            erc1155Controller.balanceOf(address(this), bTokenIndex);
        uint256 wTokenBalance =
            erc1155Controller.balanceOf(address(this), wTokenIndex);

        ISeriesController.Series memory series =
            seriesController.series(seriesId);

        // For put convert token balances into collateral locked in them
        if (series.isPutOption) {
            bTokenBalance = seriesController.getCollateralPerOptionToken(
                seriesId,
                bTokenBalance
            );
            wTokenBalance = seriesController.getCollateralPerOptionToken(
                seriesId,
                wTokenBalance
            );
        }

        // Max amount of tokens we can get by adding current balance plus what can be minted from collateral
        uint256 bTokenBalanceMax = bTokenBalance + collateralTokenBalance;
        uint256 wTokenBalanceMax = wTokenBalance + collateralTokenBalance;

        uint256 bTokenPrice =
            getPriceForSeriesInternal(series, getCurrentUnderlyingPrice());
        uint256 wTokenPrice = uint256(1e18) - bTokenPrice;

        // Balance on higher reserve side is the sum of what can be minted (collateralTokenBalance)
        // plus existing balance of the token
        uint256 bTokenVirtualBalance;
        uint256 wTokenVirtualBalance;

        if (bTokenPrice <= wTokenPrice) {
            // Rb >= Rw, Pb <= Pw
            bTokenVirtualBalance = bTokenBalanceMax;
            wTokenVirtualBalance =
                (bTokenVirtualBalance * bTokenPrice) /
                wTokenPrice;

            // Sanity check that we don't exceed actual physical balances
            // In case this happens, adjust virtual balances to not exceed maximum
            // available reserves while still preserving correct price
            if (wTokenVirtualBalance > wTokenBalanceMax) {
                wTokenVirtualBalance = wTokenBalanceMax;
                bTokenVirtualBalance =
                    (wTokenVirtualBalance * wTokenPrice) /
                    bTokenPrice;
            }
        } else {
            // if Rb < Rw, Pb > Pw
            wTokenVirtualBalance = wTokenBalanceMax;
            bTokenVirtualBalance =
                (wTokenVirtualBalance * wTokenPrice) /
                bTokenPrice;

            // Sanity check
            if (bTokenVirtualBalance > bTokenBalanceMax) {
                bTokenVirtualBalance = bTokenBalanceMax;
                wTokenVirtualBalance =
                    (bTokenVirtualBalance * bTokenPrice) /
                    wTokenPrice;
            }
        }

        return (bTokenVirtualBalance, wTokenVirtualBalance);
    }

    /// @dev Get the current series price of the underlying token with units of priceToken,
    /// always with 8 decimals
    /// @dev For example, if underlying == WBTC and price == USDC, then this function will return
    /// 4500000000000 ($45_000 in human readable units)
    function getCurrentUnderlyingPrice() private view returns (uint256) {
        return
            IPriceOracle(sirenPriceOracle).getCurrentPrice(
                address(underlyingToken),
                address(priceToken)
            );
    }

    /// @notice Get the bToken price for given Series, in units of the collateral token
    /// and normalized to 1e18. We use a normalization factor of 1e18 because we need
    /// to represent fractional values, yet Solidity does not support floating point numerics.
    /// @notice For example, if this is a WBTC Call option pool and so
    /// the collateral token is WBTC, then a return value of 0.5e18 means X units of bToken
    /// have a price of 0.5 * X units of WBTC. Another example; if this were a WBTC Put
    /// option pool, and so the collateral token is USDC, then a return value of 0.1e18 means
    /// X units of bToken have a price of 0.1 * X * strikePrice units of USDC.
    /// @notice This value will always be between 0 and 1e18, so you can think of it as
    /// representing the price as a fraction of 1 collateral token unit
    function getPriceForSeries(uint64 seriesId)
        external
        view
        returns (uint256)
    {
        require(openSeries.contains(seriesId), "E13");

        return
            getPriceForSeriesInternal(
                seriesController.series(seriesId),
                getCurrentUnderlyingPrice()
            );
    }

    function getPriceForSeriesInternal(
        ISeriesController.Series memory series,
        uint256 underlyingPrice
    ) private view returns (uint256) {
        return
            // Note! This function assumes the price obtained from the onchain oracle
            // in getCurrentUnderlyingPrice is a valid series price in units of
            // underlyingToken/priceToken. If the onchain price oracle's value
            // were to drift from the true series price, then the bToken price
            // we calculate here would also drift, and will result in undefined
            // behavior for any functions which call getPriceForSeries
            calcPrice(
                series.expirationDate - block.timestamp,
                series.strikePrice,
                underlyingPrice,
                volatilityFactor,
                series.isPutOption
            );
    }

    /// @dev Calculate price of bToken based on Black-Scholes approximation by Brennan-Subrahmanyam from their paper
    /// "A Simple Formula to Compute the Implied Standard Deviation" (1988).
    /// Formula: 0.4 * ImplVol * sqrt(timeUntilExpiry) * priceRatio
    ///
    /// Returns premium in units of percentage of collateral locked in a contract for both calls and puts
    function calcPrice(
        uint256 timeUntilExpiry,
        uint256 strike,
        uint256 currentPrice,
        uint256 volatility,
        bool isPutOption
    ) public pure returns (uint256) {
        uint256 intrinsic = 0;
        uint256 timeValue = 0;

        if (isPutOption) {
            if (currentPrice < strike) {
                // ITM
                intrinsic = ((strike - currentPrice) * 1e18) / strike;
            }

            timeValue =
                (Math.sqrt(timeUntilExpiry) * volatility * strike) /
                currentPrice;
        } else {
            if (currentPrice > strike) {
                // ITM
                intrinsic = ((currentPrice - strike) * 1e18) / currentPrice;
            }

            // use a Black-Scholes approximation to calculate the option price given the
            // volatility, strike price, and the current series price
            timeValue =
                (Math.sqrt(timeUntilExpiry) * volatility * currentPrice) /
                strike;
        }

        return intrinsic + timeValue;
    }

    /// @dev Buy bToken of a given series.
    /// We supply series index instead of series address to ensure that only supported series can be traded using this AMM
    /// collateralMaximum is used for slippage protection
    function bTokenBuy(
        uint64 seriesId,
        uint256 bTokenAmount,
        uint256 collateralMaximum
    ) external minTradeSize(bTokenAmount) returns (uint256) {
        require(openSeries.contains(seriesId), "E13");

        require(
            seriesController.state(seriesId) ==
                ISeriesController.SeriesState.OPEN,
            "Series has expired"
        );

        uint256 collateralAmount =
            bTokenGetCollateralIn(seriesId, bTokenAmount);
        require(collateralAmount <= collateralMaximum, "Slippage exceeded");

        // Move collateral into this contract
        collateralToken.safeTransferFrom(
            msg.sender,
            address(this),
            collateralAmount
        );

        // Mint new options only as needed
        uint256 bTokenIndex = SeriesLibrary.bTokenIndex(seriesId);
        uint256 bTokenBalance =
            erc1155Controller.balanceOf(address(this), bTokenIndex);
        if (bTokenBalance < bTokenAmount) {
            // Approve the collateral to mint bTokenAmount of new options
            uint256 bTokenCollateralAmount =
                seriesController.getCollateralPerOptionToken(
                    seriesId,
                    bTokenAmount
                );

            collateralToken.approve(
                address(seriesController),
                bTokenCollateralAmount
            );
            seriesController.mintOptions(
                seriesId,
                bTokenAmount - bTokenBalance
            );
        }

        // Send all bTokens back
        bytes memory data;
        erc1155Controller.safeTransferFrom(
            address(this),
            msg.sender,
            bTokenIndex,
            bTokenAmount,
            data
        );

        // Emit the event
        emit BTokensBought(
            msg.sender,
            seriesId,
            bTokenAmount,
            collateralAmount
        );

        // Return the amount of collateral required to buy
        return collateralAmount;
    }

    /// @notice Sell the bToken of a given series to the AMM in exchange for collateral token
    /// @notice This call will fail if the caller tries to sell a bToken amount larger than the amount of
    /// wToken held by the AMM
    /// @param seriesId The ID of the Series to buy bToken on
    /// @param bTokenAmount The amount of bToken to sell (bToken has the same decimals as the underlying)
    /// @param collateralMinimum The lowest amount of collateral the caller is willing to receive as payment
    /// for their bToken. The actual amount of bToken received may be lower than this due to slippage
    function bTokenSell(
        uint64 seriesId,
        uint256 bTokenAmount,
        uint256 collateralMinimum
    ) external minTradeSize(bTokenAmount) returns (uint256) {
        require(openSeries.contains(seriesId), "E13");

        require(
            seriesController.state(seriesId) ==
                ISeriesController.SeriesState.OPEN,
            "Series has expired"
        );

        uint256 collateralAmount =
            bTokenGetCollateralOut(seriesId, bTokenAmount);
        require(collateralAmount >= collateralMinimum, "Slippage exceeded");

        uint256 bTokenIndex = SeriesLibrary.bTokenIndex(seriesId);
        uint256 wTokenIndex = SeriesLibrary.wTokenIndex(seriesId);

        // Move bToken into this contract
        bytes memory data;
        erc1155Controller.safeTransferFrom(
            msg.sender,
            address(this),
            bTokenIndex,
            bTokenAmount,
            data
        );

        // Always be closing!
        uint256 bTokenBalance =
            erc1155Controller.balanceOf(address(this), bTokenIndex);
        uint256 wTokenBalance =
            erc1155Controller.balanceOf(address(this), wTokenIndex);
        uint256 closeAmount = Math.min(bTokenBalance, wTokenBalance);

        // at this point we know it's worth calling closePosition because
        // the close amount is greater than 0, so let's call it and burn
        // excess option tokens in order to receive collateral tokens
        seriesController.closePosition(seriesId, closeAmount);

        // Send the tokens to the seller
        collateralToken.safeTransfer(msg.sender, collateralAmount);

        // Emit the event
        emit BTokensSold(msg.sender, seriesId, bTokenAmount, collateralAmount);

        // Return the amount of collateral received during sale
        return collateralAmount;
    }

    /// @notice Calculate premium (i.e. the option price) to buy bTokenAmount bTokens for the
    /// given Series
    /// @notice The premium depends on the amount of collateral token in the pool, the reserves
    /// of bToken and wToken in the pool, and the current series price of the underlying
    /// @param seriesId The ID of the Series to buy bToken on
    /// @param bTokenAmount The amount of bToken to buy, which uses the same decimals as
    /// the underlying ERC20 token
    /// @return The amount of collateral token necessary to buy bTokenAmount worth of bTokens
    function bTokenGetCollateralIn(uint64 seriesId, uint256 bTokenAmount)
        public
        view
        returns (uint256)
    {
        // Shortcut for 0 amount
        if (bTokenAmount == 0) return 0;

        bTokenAmount = seriesController.getCollateralPerOptionToken(
            seriesId,
            bTokenAmount
        );

        // For both puts and calls balances are expressed in collateral token
        (uint256 bTokenBalance, uint256 wTokenBalance) =
            getVirtualReserves(seriesId);

        uint256 sumBalance = bTokenBalance + wTokenBalance;
        uint256 toSquare;
        if (sumBalance > bTokenAmount) {
            toSquare = sumBalance - bTokenAmount;
        } else {
            toSquare = bTokenAmount - sumBalance;
        }

        // return the collateral amount
        return
            (((Math.sqrt((toSquare**2) + (4 * bTokenAmount * wTokenBalance)) +
                bTokenAmount) - bTokenBalance) - wTokenBalance) / 2;
    }

    /// @notice Calculate the amount of collateral token the user will receive for selling
    /// bTokenAmount worth of bToken to the pool. This is the option's sell price
    /// @notice The sell price depends on the amount of collateral token in the pool, the reserves
    /// of bToken and wToken in the pool, and the current series price of the underlying
    /// @param seriesId The ID of the Series to sell bToken on
    /// @param bTokenAmount The amount of bToken to sell, which uses the same decimals as
    /// the underlying ERC20 token
    /// @return The amount of collateral token the user will receive upon selling bTokenAmount of
    /// bTokens to the pool
    function bTokenGetCollateralOut(uint64 seriesId, uint256 bTokenAmount)
        public
        view
        returns (uint256)
    {
        return
            optionTokenGetCollateralOutInternal(
                seriesId,
                bTokenAmount,
                collateralToken.balanceOf(address(this)),
                true
            );
    }

    /// @notice Sell the wToken of a given series to the AMM in exchange for collateral token
    /// @param seriesId The ID of the Series to buy wToken on
    /// @param wTokenAmount The amount of wToken to sell (wToken has the same decimals as the underlying)
    /// @param collateralMinimum The lowest amount of collateral the caller is willing to receive as payment
    /// for their wToken. The actual amount of wToken received may be lower than this due to slippage
    function wTokenSell(
        uint64 seriesId,
        uint256 wTokenAmount,
        uint256 collateralMinimum
    ) external minTradeSize(wTokenAmount) returns (uint256) {
        require(openSeries.contains(seriesId), "E13");

        require(
            seriesController.state(seriesId) ==
                ISeriesController.SeriesState.OPEN,
            "Series has expired"
        );

        // Get initial stats
        uint256 collateralAmount =
            wTokenGetCollateralOut(seriesId, wTokenAmount);
        require(collateralAmount >= collateralMinimum, "Slippage exceeded");

        uint256 bTokenIndex = SeriesLibrary.bTokenIndex(seriesId);
        uint256 wTokenIndex = SeriesLibrary.wTokenIndex(seriesId);

        // Move wToken into this contract
        bytes memory data;
        erc1155Controller.safeTransferFrom(
            msg.sender,
            address(this),
            wTokenIndex,
            wTokenAmount,
            data
        );

        // Always be closing!
        uint256 bTokenBalance =
            erc1155Controller.balanceOf(address(this), bTokenIndex);
        uint256 wTokenBalance =
            erc1155Controller.balanceOf(address(this), wTokenIndex);
        uint256 closeAmount = Math.min(bTokenBalance, wTokenBalance);
        if (closeAmount > 0) {
            seriesController.closePosition(seriesId, closeAmount);
        }

        // Send the tokens to the seller
        collateralToken.safeTransfer(msg.sender, collateralAmount);

        // Emit the event
        emit WTokensSold(msg.sender, seriesId, wTokenAmount, collateralAmount);

        // Return the amount of collateral received during sale
        return collateralAmount;
    }

    /// @notice Calculate amount of collateral in exchange for selling wTokens
    function wTokenGetCollateralOut(uint64 seriesId, uint256 wTokenAmount)
        public
        view
        returns (uint256)
    {
        return
            optionTokenGetCollateralOutInternal(
                seriesId,
                wTokenAmount,
                collateralToken.balanceOf(address(this)),
                false
            );
    }

    /// @dev Calculates the amount of collateral token a seller will receive for selling their option tokens,
    /// taking into account the AMM's level of reserves
    /// @param seriesId The ID of the Series
    /// @param optionTokenAmount The amount of option tokens (either bToken or wToken) to be sold
    /// @param _collateralTokenBalance The amount of collateral token held by this AMM
    /// @param isBToken true if the option token is bToken, and false if it's wToken. Depending on which
    /// of the two it is, the equation for calculating the final collateral token is a little different
    /// @return The amount of collateral token the seller will receive in exchange for their option token
    function optionTokenGetCollateralOutInternal(
        uint64 seriesId,
        uint256 optionTokenAmount,
        uint256 _collateralTokenBalance,
        bool isBToken
    ) private view returns (uint256) {
        // Shortcut for 0 amount
        if (optionTokenAmount == 0) return 0;

        optionTokenAmount = seriesController.getCollateralPerOptionToken(
            seriesId,
            optionTokenAmount
        );

        (uint256 bTokenBalance, uint256 wTokenBalance) =
            getVirtualReservesInternal(seriesId, _collateralTokenBalance);

        uint256 balanceFactor;
        if (isBToken) {
            balanceFactor = wTokenBalance;
        } else {
            balanceFactor = bTokenBalance;
        }
        uint256 toSquare = optionTokenAmount + wTokenBalance + bTokenBalance;
        uint256 collateralAmount =
            (toSquare -
                Math.sqrt(
                    (toSquare**2) - (4 * optionTokenAmount * balanceFactor)
                )) / 2;

        return collateralAmount;
    }

    /// @notice Calculate the amount of collateral the AMM would received if all of the
    /// expired Series' wTokens and bTokens were to be redeemed for their underlying collateral
    /// value
    /// @return The amount of collateral token the AMM would receive if it were to exercise/claim
    /// all expired bTokens/wTokens
    function getCollateralValueOfAllExpiredOptionTokens()
        public
        view
        returns (uint256)
    {
        uint256 unredeemedCollateral = 0;

        for (uint256 i = 0; i < openSeries.length(); i++) {
            uint64 seriesId = uint64(openSeries.at(i));

            if (
                seriesController.state(seriesId) ==
                ISeriesController.SeriesState.EXPIRED
            ) {
                uint256 bTokenIndex = SeriesLibrary.bTokenIndex(seriesId);
                uint256 wTokenIndex = SeriesLibrary.wTokenIndex(seriesId);

                // Get the pool's option token balances
                uint256 bTokenBalance =
                    erc1155Controller.balanceOf(address(this), bTokenIndex);
                uint256 wTokenBalance =
                    erc1155Controller.balanceOf(address(this), wTokenIndex);

                // calculate the amount of collateral The AMM would receive by
                // redeeming this Series' bTokens and wTokens
                unredeemedCollateral += getRedeemableCollateral(
                    seriesId,
                    wTokenBalance,
                    bTokenBalance
                );
            }
        }

        return unredeemedCollateral;
    }

    /// @notice Calculate sale value of pro-rata LP b/wTokens in units of collateral token
    function getOptionTokensSaleValue(uint256 lpTokenAmount)
        external
        view
        returns (uint256)
    {
        if (lpTokenAmount == 0) return 0;

        uint256 lpTokenSupply = IERC20Lib(address(lpToken)).totalSupply();
        if (lpTokenSupply == 0) return 0;

        // Calculate the amount of collateral receivable by redeeming all the expired option tokens
        uint256 expiredOptionTokenCollateral =
            getCollateralValueOfAllExpiredOptionTokens();

        // Calculate amount of collateral left in the pool to sell tokens to
        uint256 totalCollateral =
            expiredOptionTokenCollateral +
                collateralToken.balanceOf(address(this));

        // Subtract pro-rata collateral amount to be withdrawn
        totalCollateral =
            (totalCollateral * (lpTokenSupply - lpTokenAmount)) /
            lpTokenSupply;

        // Given remaining collateral calculate how much all tokens can be sold for
        uint256 collateralLeft = totalCollateral;
        for (uint256 i = 0; i < openSeries.length(); i++) {
            uint64 seriesId = uint64(openSeries.at(i));

            if (
                seriesController.state(seriesId) ==
                ISeriesController.SeriesState.OPEN
            ) {
                uint256 bTokenToSell =
                    (erc1155Controller.balanceOf(
                        address(this),
                        SeriesLibrary.bTokenIndex(seriesId)
                    ) * lpTokenAmount) / lpTokenSupply;
                uint256 wTokenToSell =
                    (erc1155Controller.balanceOf(
                        address(this),
                        SeriesLibrary.wTokenIndex(seriesId)
                    ) * lpTokenAmount) / lpTokenSupply;

                uint256 collateralAmountB =
                    optionTokenGetCollateralOutInternal(
                        seriesId,
                        bTokenToSell,
                        collateralLeft,
                        true
                    );
                collateralLeft -= collateralAmountB;

                uint256 collateralAmountW =
                    optionTokenGetCollateralOutInternal(
                        seriesId,
                        wTokenToSell,
                        collateralLeft,
                        false
                    );
                collateralLeft -= collateralAmountW;
            }
        }

        return totalCollateral - collateralLeft;
    }

    /// @dev Calculate the collateral amount receivable by redeeming the given
    /// Series' bTokens and wToken
    /// @param seriesId The index of the Series
    /// @param wTokenBalance The wToken balance for this Series owned by this AMM
    /// @param bTokenBalance The bToken balance for this Series owned by this AMM
    /// @return The total amount of collateral receivable by redeeming the Series' option tokens
    function getRedeemableCollateral(
        uint64 seriesId,
        uint256 wTokenBalance,
        uint256 bTokenBalance
    ) private view returns (uint256) {
        uint256 unredeemedCollateral = 0;
        if (wTokenBalance > 0) {
            (uint256 unclaimedCollateral, ) =
                seriesController.getClaimAmount(seriesId, wTokenBalance);
            unredeemedCollateral += unclaimedCollateral;
        }
        if (bTokenBalance > 0) {
            (uint256 unexercisedCollateral, ) =
                seriesController.getExerciseAmount(seriesId, bTokenBalance);
            unredeemedCollateral += unexercisedCollateral;
        }

        return unredeemedCollateral;
    }

    /// @notice Adds the address of series to the amm
    /// @dev Only the associated SeriesController may call this function
    /// @dev The SeriesController calls this function when it is creating a Series
    /// and adds the Series to this AMM
    function addSeries(uint64 _seriesId) external override {
        require(msg.sender == address(seriesController), "E11");
        // Prevents out of gas error, occuring at 250 series, from locking
        // in LPs when we cycle over openSeries in _sellOrWithdrawActiveTokens.
        // We further lower the limit to 100 series for extra safety.
        require(openSeries.length() <= 100, "Too many open series");
        openSeries.add(_seriesId);
    }

    /// @notice Returns true when interfaceId is the ID of the addSeries function or the ERC165
    /// standard, and false otherwise
    /// @dev This function exists only so the SeriesController can tell when to try to add
    /// Series it has created to the MinterAmm
    function supportsInterface(bytes4 interfaceId)
        public
        view
        override
        returns (bool)
    {
        return
            interfaceId == this.addSeries.selector ||
            super.supportsInterface(interfaceId);
    }
}

File 2 of 26: Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @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
     * ====
     */
    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;
        // solhint-disable-next-line no-inline-assembly
        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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(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) {
        require(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 _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 3 of 26: AddressUpgradeable.sol
// SPDX-License-Identifier: MIT

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;
        // solhint-disable-next-line no-inline-assembly
        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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 4 of 26: ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
import "./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 initializer {
        __Context_init_unchained();
    }

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

    function _msgData() internal view virtual returns (bytes calldata) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
    uint256[50] private __gap;
}

File 5 of 26: EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

            bytes32 lastvalue = set._values[lastIndex];

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

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

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

            return true;
        } else {
            return false;
        }
    }

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

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

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

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

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

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

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

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

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

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

    // UintSet

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

File 6 of 26: ERC1155HolderUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ERC1155ReceiverUpgradeable.sol";
import "./Initializable.sol";

/**
 * @dev _Available since v3.1._
 */
contract ERC1155HolderUpgradeable is Initializable, ERC1155ReceiverUpgradeable {
    function __ERC1155Holder_init() internal initializer {
        __ERC165_init_unchained();
        __ERC1155Receiver_init_unchained();
        __ERC1155Holder_init_unchained();
    }

    function __ERC1155Holder_init_unchained() internal initializer {
    }
    function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
    uint256[50] private __gap;
}

File 7 of 26: ERC1155ReceiverUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC1155ReceiverUpgradeable.sol";
import "./ERC165Upgradeable.sol";
import "./Initializable.sol";

/**
 * @dev _Available since v3.1._
 */
abstract contract ERC1155ReceiverUpgradeable is Initializable, ERC165Upgradeable, IERC1155ReceiverUpgradeable {
    function __ERC1155Receiver_init() internal initializer {
        __ERC165_init_unchained();
        __ERC1155Receiver_init_unchained();
    }

    function __ERC1155Receiver_init_unchained() internal initializer {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
        return interfaceId == type(IERC1155ReceiverUpgradeable).interfaceId
            || super.supportsInterface(interfaceId);
    }
    uint256[50] private __gap;
}

File 8 of 26: ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165Upgradeable.sol";
import "./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 initializer {
        __ERC165_init_unchained();
    }

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

File 9 of 26: IAddSeriesToAmm.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

interface IAddSeriesToAmm {
    function addSeries(uint64 _seriesId) external;
}

File 10 of 26: IERC1155.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}

File 11 of 26: IERC1155ReceiverUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165Upgradeable.sol";

/**
 * _Available since v3.1._
 */
interface IERC1155ReceiverUpgradeable is IERC165Upgradeable {

    /**
        @dev Handles the receipt of a single ERC1155 token type. This function is
        called at the end of a `safeTransferFrom` after the balance has been updated.
        To accept the transfer, this must return
        `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
        (i.e. 0xf23a6e61, or its own function selector).
        @param operator The address which initiated the transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param id The ID of the token being transferred
        @param value The amount of tokens being transferred
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
    */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    )
        external
        returns(bytes4);

    /**
        @dev Handles the receipt of a multiple ERC1155 token types. This function
        is called at the end of a `safeBatchTransferFrom` after the balances have
        been updated. To accept the transfer(s), this must return
        `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
        (i.e. 0xbc197c81, or its own function selector).
        @param operator The address which initiated the batch transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param ids An array containing ids of each token being transferred (order and length must match values array)
        @param values An array containing amounts of each token being transferred (order and length must match ids array)
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
    */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    )
        external
        returns(bytes4);
}

File 12 of 26: IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

File 13 of 26: IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT

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

File 14 of 26: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 15 of 26: IERC20Lib.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

/** Dead simple interface for the ERC20 methods that aren't in the standard interface
 */
interface IERC20Lib {
    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);
}

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

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

import "./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 {UpgradeableProxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

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

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

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

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

        _;

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

File 17 of 26: InitializeableAmm.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

import "./IERC20.sol";
import "./ISeriesController.sol";

interface InitializeableAmm {
    function initialize(
        ISeriesController _seriesController,
        address _priceOracle,
        IERC20 _underlyingToken,
        IERC20 _priceToken,
        IERC20 _collateralToken,
        address _tokenImplementation,
        uint16 _tradeFeeBasisPoints
    ) external;
}

File 18 of 26: IPriceOracle.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

interface IPriceOracle {
    function getSettlementPrice(
        address underlyingToken,
        address priceToken,
        uint256 settlementDate
    ) external view returns (bool, uint256);

    function getCurrentPrice(address underlyingToken, address priceToken)
        external
        view
        returns (uint256);

    function setSettlementPrice(address underlyingToken, address priceToken)
        external;

    function setSettlementPriceForDate(
        address underlyingToken,
        address priceToken,
        uint256 date
    ) external;

    function get8amWeeklyOrDailyAligned(uint256 _timestamp)
        external
        view
        returns (uint256);
}

File 19 of 26: ISeriesController.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

/**
 @title ISeriesController
 @author The Siren Devs
 @notice Onchain options protocol for minting, exercising, and claiming calls and puts
 @notice Manages the lifecycle of individual Series
 @dev The id's for bTokens and wTokens on the same Series are consecutive uints
 */
interface ISeriesController {
    /// @notice The basis points to use for fees on the various SeriesController functions,
    /// in units of basis points (1 basis point = 0.01%)
    struct Fees {
        address feeReceiver;
        uint16 exerciseFeeBasisPoints;
        uint16 closeFeeBasisPoints;
        uint16 claimFeeBasisPoints;
    }

    struct Tokens {
        address underlyingToken;
        address priceToken;
        address collateralToken;
    }

    /// @notice All data pertaining to an individual series
    struct Series {
        uint40 expirationDate;
        bool isPutOption;
        ISeriesController.Tokens tokens;
        uint256 strikePrice;
    }

    /// @notice All possible states a Series can be in with regard to its expiration date
    enum SeriesState {
        /**
         * New option token cans be created.
         * Existing positions can be closed.
         * bTokens cannot be exercised
         * wTokens cannot be claimed
         */
        OPEN,
        /**
         * No new options can be created
         * Positions cannot be closed
         * bTokens can be exercised
         * wTokens can be claimed
         */
        EXPIRED
    }

    /** Enum to track Fee Events */
    enum FeeType {EXERCISE_FEE, CLOSE_FEE, CLAIM_FEE}

    ///////////////////// EVENTS /////////////////////

    /// @notice Emitted when the owner creates a new series
    event SeriesCreated(
        uint64 seriesId,
        Tokens tokens,
        address[] restrictedMinters,
        uint256 strikePrice,
        uint40 expirationDate,
        bool isPutOption
    );

    /// @notice Emitted when the SeriesController gets initialized
    event SeriesControllerInitialized(
        address priceOracle,
        address vault,
        address erc1155Controller,
        Fees fees
    );

    /// @notice Emitted when SeriesController.mintOptions is called, and wToken + bToken are minted
    event OptionMinted(
        address minter,
        uint64 seriesId,
        uint256 optionTokenAmount,
        uint256 wTokenTotalSupply,
        uint256 bTokenTotalSupply
    );

    /// @notice Emitted when either the SeriesController transfers ERC20 funds to the SeriesVault,
    /// or the SeriesController transfers funds from the SeriesVault to a recipient
    event ERC20VaultTransferIn(address sender, uint64 seriesId, uint256 amount);
    event ERC20VaultTransferOut(
        address recipient,
        uint64 seriesId,
        uint256 amount
    );

    event FeePaid(
        FeeType indexed feeType,
        address indexed token,
        uint256 value
    );

    /** Emitted when a bToken is exercised for collateral */
    event OptionExercised(
        address indexed redeemer,
        uint64 seriesId,
        uint256 optionTokenAmount,
        uint256 wTokenTotalSupply,
        uint256 bTokenTotalSupply,
        uint256 collateralAmount
    );

    /** Emitted when a wToken is redeemed after expiration */
    event CollateralClaimed(
        address indexed redeemer,
        uint64 seriesId,
        uint256 optionTokenAmount,
        uint256 wTokenTotalSupply,
        uint256 bTokenTotalSupply,
        uint256 collateralAmount
    );

    /** Emitted when an equal amount of wToken and bToken is redeemed for original collateral */
    event OptionClosed(
        address indexed redeemer,
        uint64 seriesId,
        uint256 optionTokenAmount,
        uint256 wTokenTotalSupply,
        uint256 bTokenTotalSupply,
        uint256 collateralAmount
    );

    ///////////////////// VIEW/PURE FUNCTIONS /////////////////////

    function priceDecimals() external view returns (uint8);

    function erc1155Controller() external view returns (address);

    function series(uint256 seriesId)
        external
        view
        returns (ISeriesController.Series memory);

    function state(uint64 _seriesId) external view returns (SeriesState);

    function calculateFee(uint256 _amount, uint16 _basisPoints)
        external
        pure
        returns (uint256);

    function getExerciseAmount(uint64 _seriesId, uint256 _bTokenAmount)
        external
        view
        returns (uint256, uint256);

    function getClaimAmount(uint64 _seriesId, uint256 _wTokenAmount)
        external
        view
        returns (uint256, uint256);

    function seriesName(uint64 _seriesId) external view returns (string memory);

    function strikePrice(uint64 _seriesId) external view returns (uint256);

    function expirationDate(uint64 _seriesId) external view returns (uint40);

    function underlyingToken(uint64 _seriesId) external view returns (address);

    function priceToken(uint64 _seriesId) external view returns (address);

    function collateralToken(uint64 _seriesId) external view returns (address);

    function exerciseFeeBasisPoints(uint64 _seriesId)
        external
        view
        returns (uint16);

    function closeFeeBasisPoints(uint64 _seriesId)
        external
        view
        returns (uint16);

    function claimFeeBasisPoints(uint64 _seriesId)
        external
        view
        returns (uint16);

    function wTokenIndex(uint64 _seriesId) external pure returns (uint256);

    function bTokenIndex(uint64 _seriesId) external pure returns (uint256);

    function isPutOption(uint64 _seriesId) external view returns (bool);

    function getCollateralPerOptionToken(
        uint64 _seriesId,
        uint256 _optionTokenAmount
    ) external view returns (uint256);

    /// @notice Returns the amount of collateralToken held in the vault on behalf of the Series at _seriesId
    /// @param _seriesId The index of the Series in the SeriesController
    function getSeriesERC20Balance(uint64 _seriesId)
        external
        view
        returns (uint256);

    ///////////////////// MUTATING FUNCTIONS /////////////////////

    function mintOptions(uint64 _seriesId, uint256 _optionTokenAmount) external;

    function exerciseOption(
        uint64 _seriesId,
        uint256 _bTokenAmount,
        bool _revertOtm
    ) external;

    function claimCollateral(uint64 _seriesId, uint256 _wTokenAmount) external;

    function closePosition(uint64 _seriesId, uint256 _optionTokenAmount)
        external;
}

File 20 of 26: ISimpleToken.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

/** Interface for any Siren SimpleToken
 */
interface ISimpleToken {
    function initialize(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) external;

    function mint(address to, uint256 amount) external;

    function burn(address account, uint256 amount) external;
}

File 21 of 26: Math.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

// a library for performing various math operations

library Math {
    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrt(uint256 y) internal pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a < b) return a;
        return b;
    }
}

File 22 of 26: OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ContextUpgradeable.sol";
import "./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 initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), 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 {
        emit OwnershipTransferred(_owner, address(0));
        _owner = 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");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
    uint256[49] private __gap;
}

File 23 of 26: Proxiable.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

contract Proxiable {
    // Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7"
    uint256 constant PROXY_MEM_SLOT =
        0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7;

    event CodeAddressUpdated(address newAddress);

    function _updateCodeAddress(address newAddress) internal {
        require(
            bytes32(PROXY_MEM_SLOT) == Proxiable(newAddress).proxiableUUID(),
            "Not compatible"
        );
        assembly {
            // solium-disable-line
            sstore(PROXY_MEM_SLOT, newAddress)
        }

        emit CodeAddressUpdated(newAddress);
    }

    function getLogicAddress() public view returns (address logicAddress) {
        assembly {
            // solium-disable-line
            logicAddress := sload(PROXY_MEM_SLOT)
        }
    }

    function proxiableUUID() public pure returns (bytes32) {
        return bytes32(PROXY_MEM_SLOT);
    }
}

File 24 of 26: Proxy.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

contract Proxy {
    // Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7"
    uint256 constant PROXY_MEM_SLOT =
        0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7;

    constructor(address contractLogic) public {
        // Verify a valid address was passed in
        require(contractLogic != address(0), "Contract Logic cannot be 0x0");

        // save the code address
        assembly {
            // solium-disable-line
            sstore(PROXY_MEM_SLOT, contractLogic)
        }
    }

    fallback() external payable {
        assembly {
            // solium-disable-line
            let contractLogic := sload(PROXY_MEM_SLOT)
            let ptr := mload(0x40)
            calldatacopy(ptr, 0x0, calldatasize())
            let success := delegatecall(
                gas(),
                contractLogic,
                ptr,
                calldatasize(),
                0,
                0
            )
            let retSz := returndatasize()
            returndatacopy(ptr, 0, retSz)
            switch success
                case 0 {
                    revert(ptr, retSz)
                }
                default {
                    return(ptr, retSz)
                }
        }
    }
}

File 25 of 26: SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 26 of 26: SeriesLibrary.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.0;

library SeriesLibrary {
    function wTokenIndex(uint64 _seriesId) internal pure returns (uint256) {
        return _seriesId * 2;
    }

    function bTokenIndex(uint64 _seriesId) internal pure returns (uint256) {
        return (_seriesId * 2) + 1;
    }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ISimpleToken","name":"lpToken","type":"address"},{"indexed":false,"internalType":"address","name":"sirenPriceOracle","type":"address"},{"indexed":false,"internalType":"address","name":"controller","type":"address"}],"name":"AMMInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint64","name":"seriesId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"bTokensBought","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralPaid","type":"uint256"}],"name":"BTokensBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"uint64","name":"seriesId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"bTokensSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralPaid","type":"uint256"}],"name":"BTokensSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"CodeAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralRemoved","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpTokensBurned","type":"uint256"}],"name":"LpTokensBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralAdded","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpTokensMinted","type":"uint256"}],"name":"LpTokensMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSirenPriceOracle","type":"address"}],"name":"NewSirenPriceOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"seriesId","type":"uint64"}],"name":"SeriesEvicted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newVolatilityFactor","type":"uint256"}],"name":"VolatilityFactorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"uint64","name":"seriesId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"wTokensSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralPaid","type":"uint256"}],"name":"WTokensSold","type":"event"},{"inputs":[],"name":"MINIMUM_TRADE_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_seriesId","type":"uint64"}],"name":"addSeries","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"},{"internalType":"uint256","name":"bTokenAmount","type":"uint256"},{"internalType":"uint256","name":"collateralMaximum","type":"uint256"}],"name":"bTokenBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"},{"internalType":"uint256","name":"bTokenAmount","type":"uint256"}],"name":"bTokenGetCollateralIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"},{"internalType":"uint256","name":"bTokenAmount","type":"uint256"}],"name":"bTokenGetCollateralOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"},{"internalType":"uint256","name":"bTokenAmount","type":"uint256"},{"internalType":"uint256","name":"collateralMinimum","type":"uint256"}],"name":"bTokenSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeUntilExpiry","type":"uint256"},{"internalType":"uint256","name":"strike","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"volatility","type":"uint256"},{"internalType":"bool","name":"isPutOption","type":"bool"}],"name":"calcPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"claimAllExpiredTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"}],"name":"claimExpiredTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc1155Controller","outputs":[{"internalType":"contract IERC1155","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllSeries","outputs":[{"internalType":"uint64[]","name":"","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralValueOfAllExpiredOptionTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogicAddress","outputs":[{"internalType":"address","name":"logicAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lpTokenAmount","type":"uint256"}],"name":"getOptionTokensSaleValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"}],"name":"getPriceForSeries","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"}],"name":"getSeries","outputs":[{"components":[{"internalType":"uint40","name":"expirationDate","type":"uint40"},{"internalType":"bool","name":"isPutOption","type":"bool"},{"components":[{"internalType":"address","name":"underlyingToken","type":"address"},{"internalType":"address","name":"priceToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"}],"internalType":"struct ISeriesController.Tokens","name":"tokens","type":"tuple"},{"internalType":"uint256","name":"strikePrice","type":"uint256"}],"internalType":"struct ISeriesController.Series","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"includeUnclaimed","type":"bool"}],"name":"getTotalPoolValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"}],"name":"getVirtualReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISeriesController","name":"_seriesController","type":"address"},{"internalType":"address","name":"_sirenPriceOracle","type":"address"},{"internalType":"contract IERC20","name":"_underlyingToken","type":"address"},{"internalType":"contract IERC20","name":"_priceToken","type":"address"},{"internalType":"contract IERC20","name":"_collateralToken","type":"address"},{"internalType":"address","name":"_tokenImplementation","type":"address"},{"internalType":"uint16","name":"_tradeFeeBasisPoints","type":"uint16"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lpToken","outputs":[{"internalType":"contract ISimpleToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"lpTokenMinimum","type":"uint256"}],"name":"provideCapital","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"seriesController","outputs":[{"internalType":"contract ISeriesController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_volatilityFactor","type":"uint256"}],"name":"setVolatilityFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeFeeBasisPoints","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlyingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newImplementation","type":"address"}],"name":"updateImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"volatilityFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"},{"internalType":"uint256","name":"wTokenAmount","type":"uint256"}],"name":"wTokenGetCollateralOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"seriesId","type":"uint64"},{"internalType":"uint256","name":"wTokenAmount","type":"uint256"},{"internalType":"uint256","name":"collateralMinimum","type":"uint256"}],"name":"wTokenSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lpTokenAmount","type":"uint256"},{"internalType":"bool","name":"sellTokens","type":"bool"},{"internalType":"uint256","name":"collateralMinimum","type":"uint256"}],"name":"withdrawCapital","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052610102805460ff1916905534801561001b57600080fd5b50615ec3806200002c6000396000f3fe60806040523480156200001157600080fd5b5060043610620001f65760003560e01c806301ffc9a714620001fb57806302504213146200022a578063025b22bc146200024357806303cdf7fe146200025a5780631db14a0f14620002735780632495a59914620002995780632824c14614620002a35780632ff6fe7614620002ba578063318b836314620002c45780633acd219f14620002db5780633b26cf5c14620002f25780634825701814620003095780635205b24a146200032057806352d1902d14620003375780635ef05b0c14620003415780635f8b98ec14620003685780635fcbd285146200037257806365514909146200037c578063715018a6146200039557806371c654ee146200039f578063736525cf14620003b65780637e50774214620003c057806387906e9d14620003ca5780638da5cb5b14620003e15780638fdc057f14620003eb578063a9c862fe1462000411578063abd108ba1462000428578063b2016bd41462000432578063bb736f4b146200043c578063bc197c811462000446578063bd36068c146200046c578063bd4c0cb11462000476578063c3bf70f1146200048d578063d694fd7c14620004a6578063e189969114620004bd578063f23a6e6114620004d4578063f2fde38b14620004eb578063f557bbfe1462000502578063f67325ba1462000519575b600080fd5b620002126200020c36600462004e62565b62000530565b6040516200022191906200548a565b60405180910390f35b620002416200023b366004620051af565b62000560565b005b620002416200025436600462004ca8565b620007d0565b6200026462000856565b60405162000221919062005329565b6200028a62000284366004620051cc565b62000866565b60405162000221919062005495565b62000264620009d1565b62000241620002b4366004620051af565b620009e0565b6200026462000a58565b6200028a620002d5366004620051cc565b62000a67565b6200028a620002ec366004620051cc565b62000b08565b6200024162000303366004620050e0565b62000ba2565b620002416200031a3660046200511a565b62000f4c565b6200028a62000331366004620051f8565b6200122e565b6200028a62001618565b6200035862000352366004620051af565b6200162b565b604051620002219291906200595a565b6200028a62001700565b620002646200194f565b620003866200195e565b6040516200022191906200543b565b6200024162001a36565b62000241620003b036600462004e8c565b62001ab5565b6200024162002108565b6200028a62002233565b6200028a620003db36600462005160565b6200223a565b620002646200233e565b62000402620003fc366004620051af565b6200234d565b604051620002219190620058f4565b6200028a62000422366004620051af565b62002413565b62000264620024e4565b62000264620024f8565b6200028a62002507565b6200045d6200045736600462004ce6565b6200250d565b6040516200022191906200549e565b620002646200251e565b6200028a62000487366004620051f8565b6200252d565b62000497620028f7565b6040516200022191906200594b565b6200028a620004b7366004620051f8565b62002909565b6200028a620004ce366004620050c7565b62002d69565b6200045d620004e536600462004d9d565b6200318c565b62000241620004fc36600462004ca8565b6200319d565b6200024162000513366004620050c7565b62003257565b6200028a6200052a36600462004e0b565b62003308565b60006001600160e01b0319821663141260a360e11b148062000558575062000558826200384d565b90505b919050565b60006200056d8262003875565b905060006200057c83620038a0565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e90620005b59030908790600401620053d2565b60206040518083038186803b158015620005ce57600080fd5b505afa158015620005e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000609919062004e49565b905080156200067e5760ff5460405163125a84cd60e11b81526001600160a01b03909116906324b5099a9062000649908790859060009060040162005995565b600060405180830381600087803b1580156200066457600080fd5b505af115801562000679573d6000803e3d6000fd5b505050505b61010054604051627eeac760e11b81526000916001600160a01b03169062fdd58e90620006b29030908790600401620053d2565b60206040518083038186803b158015620006cb57600080fd5b505afa158015620006e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000706919062004e49565b90508015620007785760ff54604051632df5582b60e01b81526001600160a01b0390911690632df5582b906200074390889085906004016200597c565b600060405180830381600087803b1580156200075e57600080fd5b505af115801562000773573d6000803e3d6000fd5b505050505b6200078f6101036001600160401b038716620038af565b507fb351e3fb12f8e3eaa3fe3e70f3e08111a7e195857585cc413fe5e75bcb3cc0b085604051620007c1919062005968565b60405180910390a15050505050565b620007da620038bd565b6001600160a01b0316620007ed6200233e565b6001600160a01b0316146200081f5760405162461bcd60e51b81526004016200081690620057ca565b60405180910390fd5b6001600160a01b038116620008485760405162461bcd60e51b8152600401620008169062005683565b6200085381620038c1565b50565b610100546001600160a01b031681565b6000816200087757506000620009cb565b60ff54604051635a0c6ccf60e01b81526001600160a01b0390911690635a0c6ccf90620008ab90869086906004016200597c565b60206040518083038186803b158015620008c457600080fd5b505afa158015620008d9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008ff919062004e49565b91506000806200090f856200162b565b9092509050600062000922828462005a0e565b905060008582111562000943576200093b868362005bfb565b905062000952565b6200094f828762005bfb565b90505b600283858862000994836200096983600462005bb0565b62000975919062005bb0565b6200098260028862005ac5565b6200098e919062005a0e565b620039a9565b620009a0919062005a0e565b620009ac919062005bfb565b620009b8919062005bfb565b620009c4919062005a57565b9450505050505b92915050565b60fc546001600160a01b031681565b60ff546001600160a01b0316331462000a0d5760405162461bcd60e51b8152600401620008169062005745565b606462000a1c61010362003a27565b111562000a3d5760405162461bcd60e51b815260040162000816906200579c565b62000a546101036001600160401b03831662003a34565b5050565b60fd546001600160a01b031681565b60fe546040516370a0823160e01b815260009162000b0191859185916001600160a01b03909116906370a082319062000aa590309060040162005329565b60206040518083038186803b15801562000abe57600080fd5b505afa15801562000ad3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000af9919062004e49565b600162003a42565b9392505050565b60fe546040516370a0823160e01b815260009162000b0191859185916001600160a01b03909116906370a082319062000b4690309060040162005329565b60206040518083038186803b15801562000b5f57600080fd5b505afa15801562000b74573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b9a919062004e49565b600062003a42565b81158062000bb05750600081115b62000bcf5760405162461bcd60e51b815260040162000816906200588d565b60fe546040516370a0823160e01b81526000916001600160a01b0316906370a082319062000c0290339060040162005329565b60206040518083038186803b15801562000c1b57600080fd5b505afa15801562000c30573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c56919062004e49565b9050600060fb60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801562000ca957600080fd5b505afa15801562000cbe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ce4919062004e49565b60fb54604051632770a7eb60e21b81529192506001600160a01b031690639dc29fac9062000d199033908990600401620053d2565b600060405180830381600087803b15801562000d3457600080fd5b505af115801562000d49573d6000803e3d6000fd5b5050505062000d5762002108565b60fe546040516370a0823160e01b81526000916001600160a01b0316906370a082319062000d8a90309060040162005329565b60206040518083038186803b15801562000da357600080fd5b505afa15801562000db8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000dde919062004e49565b905060008262000def888462005bb0565b62000dfb919062005a57565b62000e07908362005bfb565b905062000e18878433898562003b84565b905062000e3f3362000e2b838562005bfb565b60fe546001600160a01b0316919062003f44565b60fe546040516370a0823160e01b815260009186916001600160a01b03909116906370a082319062000e7690339060040162005329565b60206040518083038186803b15801562000e8f57600080fd5b505afa15801562000ea4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000eca919062004e49565b62000ed6919062005bfb565b905086158062000ee65750858110155b62000f055760405162461bcd60e51b8152600401620008169062005862565b7ff7f5b08c1cb6009189fe977fb5c4665b4be8a7eff9cb01f0dca3419a1876668b33828a60405162000f3a93929190620053eb565b60405180910390a15050505050505050565b60fe5462000f66906001600160a01b031633308562003fa3565b60fb60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801562000fb557600080fd5b505afa15801562000fca573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ff0919062004e49565b6200108f5760fb546040516340c10f1960e01b81526001600160a01b03909116906340c10f1990620010299033908690600401620053d2565b600060405180830381600087803b1580156200104457600080fd5b505af115801562001059573d6000803e3d6000fd5b5050505060008051602062005e6e8339815191523383846040516200108193929190620053eb565b60405180910390a162000a54565b6200109962002108565b6000620010a7600062003308565b9050600060fb60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015620010fa57600080fd5b505afa1580156200110f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001135919062004e49565b9050600062001145858462005bfb565b62001151838562005bb0565b6200115d919062005a57565b905060006200116d838362005bfb565b905084811015620011925760405162461bcd60e51b8152600401620008169062005862565b60fb546040516340c10f1960e01b81526001600160a01b03909116906340c10f1990620011c69033908590600401620053d2565b600060405180830381600087803b158015620011e157600080fd5b505af1158015620011f6573d6000803e3d6000fd5b5050505060008051602062005e6e8339815191523387836040516200121e93929190620053eb565b60405180910390a1505050505050565b6000826103e8811015620012565760405162461bcd60e51b815260040162000816906200564c565b6200126d6101036001600160401b03871662003fcd565b6200128c5760405162461bcd60e51b8152600401620008169062005762565b60ff54604051632df23d1560e01b81526000916001600160a01b031690632df23d1590620012bf90899060040162005968565b60206040518083038186803b158015620012d857600080fd5b505afa158015620012ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001313919062004f35565b60018111156200133357634e487b7160e01b600052602160045260246000fd5b14620013535760405162461bcd60e51b81526004016200081690620057ff565b600062001361868662000b08565b905083811015620013865760405162461bcd60e51b8152600401620008169062005862565b6000620013938762003875565b90506000620013a288620038a0565b61010054604051637921219560e11b81529192506060916001600160a01b039091169063f242432a90620013e3903390309087908e9088906004016200537b565b600060405180830381600087803b158015620013fe57600080fd5b505af115801562001413573d6000803e3d6000fd5b505061010054604051627eeac760e11b8152600093506001600160a01b03909116915062fdd58e906200144d9030908890600401620053d2565b60206040518083038186803b1580156200146657600080fd5b505afa1580156200147b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620014a1919062004e49565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e90620014da9030908890600401620053d2565b60206040518083038186803b158015620014f357600080fd5b505afa15801562001508573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200152e919062004e49565b905060006200153e838362003fdb565b90508015620015b05760ff5460405163407cf5af60e11b81526001600160a01b03909116906380f9eb5e906200157b908f9085906004016200597c565b600060405180830381600087803b1580156200159657600080fd5b505af1158015620015ab573d6000803e3d6000fd5b505050505b60fe54620015c9906001600160a01b0316338962003f44565b7f907f5456589dfff4087c7c42d8a7b324895905307c7e369f6ce02ef97e4914c3338d8d8a6040516200160094939291906200540c565b60405180910390a150949a9950505050505050505050565b60008051602062005e2e83398151915290565b600080620016456101036001600160401b03851662003fcd565b620016645760405162461bcd60e51b8152600401620008169062005762565b60fe546040516370a0823160e01b8152620016f79185916001600160a01b03909116906370a08231906200169d90309060040162005329565b60206040518083038186803b158015620016b657600080fd5b505afa158015620016cb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016f1919062004e49565b62003ff4565b91509150915091565b600080805b6200171261010362003a27565b811015620019495760006200172a61010383620043d4565b9050600160ff54604051632df23d1560e01b81526001600160a01b0390911690632df23d15906200176090859060040162005968565b60206040518083038186803b1580156200177957600080fd5b505afa1580156200178e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620017b4919062004f35565b6001811115620017d457634e487b7160e01b600052602160045260246000fd5b141562001933576000620017e88262003875565b90506000620017f783620038a0565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e90620018309030908790600401620053d2565b60206040518083038186803b1580156200184957600080fd5b505afa1580156200185e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001884919062004e49565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e90620018bd9030908790600401620053d2565b60206040518083038186803b158015620018d657600080fd5b505afa158015620018eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001911919062004e49565b905062001920858284620043e2565b6200192c908862005a0e565b9650505050505b5080620019408162005c44565b91505062001705565b50905090565b60fb546001600160a01b031681565b606060006200196f61010362003a27565b6001600160401b038111156200199557634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620019bf578160200160208202803683370190505b50905060005b620019d261010362003a27565b8110156200194957620019e861010382620043d4565b82828151811062001a0957634e487b7160e01b600052603260045260246000fd5b6001600160401b03909216602092830291909101909101528062001a2d8162005c44565b915050620019c5565b62001a40620038bd565b6001600160a01b031662001a536200233e565b6001600160a01b03161462001a7c5760405162461bcd60e51b81526004016200081690620057ca565b60c9546040516000916001600160a01b03169060008051602062005e4e833981519152908390a360c980546001600160a01b0319169055565b6001600160a01b03861662001ade5760405162461bcd60e51b81526004016200081690620056a0565b6001600160a01b03851662001b075760405162461bcd60e51b815260040162000816906200570b565b6001600160a01b03841662001b305760405162461bcd60e51b8152600401620008169062005728565b6001600160a01b03831662001b595760405162461bcd60e51b8152600401620008169062005612565b836001600160a01b0316856001600160a01b0316141562001b8e5760405162461bcd60e51b8152600401620008169062005587565b6001600160a01b03821662001bb75760405162461bcd60e51b815260040162000816906200562f565b6101025460ff161562001bde5760405162461bcd60e51b815260040162000816906200577f565b610102805460ff1916600117905560ff80546001600160a01b0389166001600160a01b03199091168117909155604080516301e6fbff60e11b815290516303cdf7fe91600480820192602092909190829003018186803b15801562001c4257600080fd5b505afa15801562001c57573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001c7d919062004cc7565b61010080546001600160a01b0319166001600160a01b03928316179081905560ff5460405163a22cb46560e01b81529183169263a22cb4659262001ccb9290911690600190600401620053b7565b600060405180830381600087803b15801562001ce657600080fd5b505af115801562001cfb573d6000803e3d6000fd5b50506101028054610100600160a81b0319166101006001600160a01b038b8116820292909217909255815461ffff60a01b1916600160a01b61ffff8716021790915560fc80546001600160a01b03199081168a84161790915560fd8054821689841617905560fe80549091169187169190911790555050604051600090839062001d859062004b53565b62001d91919062005329565b604051809103906000f08015801562001dae573d6000803e3d6000fd5b5060fb80546001600160a01b0319166001600160a01b038381169190911790915560fc54604080516395d89b4160e01b8152905193945060009391909216916395d89b419160048083019286929190829003018186803b15801562001e1257600080fd5b505afa15801562001e27573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001e51919081019062004f56565b60fd60009054906101000a90046001600160a01b03166001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562001ea057600080fd5b505afa15801562001eb5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001edf919081019062004f56565b60fe60009054906101000a90046001600160a01b03166001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562001f2e57600080fd5b505afa15801562001f43573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001f6d919081019062004f56565b60405160200162001f81939291906200529c565b604051602081830303815290604052905060008160405160200162001fa79190620052fc565b60408051808303601f1901815282825260fb5460fe5463313ce56760e01b855292519194506001600160a01b0390811693631624f6c693869384939091169163313ce567916004808301926020929190829003018186803b1580156200200c57600080fd5b505afa15801562002021573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200204791906200522d565b6040518463ffffffff1660e01b81526004016200206793929190620054eb565b600060405180830381600087803b1580156200208257600080fd5b505af115801562002097573d6000803e3d6000fd5b505065246139ca80006101015550620020b1905062004525565b60fb546040517fd3d162bfa5462901258cd3d1691a5eea9ef4506e2b789cabe999a6f308f2593b91620020f4916001600160a01b03909116908c908e90620054b3565b60405180910390a150505050505050505050565b60005b6200211861010362003a27565b811015620008535760006200213061010383620043d4565b90505b60ff54604051632df23d1560e01b81526001916001600160a01b031690632df23d15906200216690859060040162005968565b60206040518083038186803b1580156200217f57600080fd5b505afa15801562002194573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620021ba919062004f35565b6001811115620021da57634e487b7160e01b600052602160045260246000fd5b14156200221d57620021ec8162000560565b620021f961010362003a27565b82141562002207576200221d565b6200221561010383620043d4565b905062002133565b50806200222a8162005c44565b9150506200210b565b6101015481565b600080808315620022b857868610156200227e57866200225b878262005bfb565b6200226f90670de0b6b3a764000062005bb0565b6200227b919062005a57565b91505b8587866200228c8b620039a9565b62002298919062005bb0565b620022a4919062005bb0565b620022b0919062005a57565b905062002326565b86861115620022f15785620022ce888262005bfb565b620022e290670de0b6b3a764000062005bb0565b620022ee919062005a57565b91505b868686620022ff8b620039a9565b6200230b919062005bb0565b62002317919062005bb0565b62002323919062005a57565b90505b62002332818362005a0e565b98975050505050505050565b60c9546001600160a01b031690565b6200235762004b61565b6200236e6101036001600160401b03841662003fcd565b6200238d5760405162461bcd60e51b8152600401620008169062005762565b60ff54604051636e1165b560e11b81526001600160a01b039091169063dc22cb6a90620023bf90859060040162005968565b60c06040518083038186803b158015620023d857600080fd5b505afa158015620023ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000558919062004fd1565b60006200242c6101036001600160401b03841662003fcd565b6200244b5760405162461bcd60e51b8152600401620008169062005762565b60ff54604051636e1165b560e11b815262000558916001600160a01b03169063dc22cb6a906200248090869060040162005968565b60c06040518083038186803b1580156200249957600080fd5b505afa158015620024ae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024d4919062004fd1565b620024de620045b3565b62004651565b60008051602062005e2e8339815191525490565b60fe546001600160a01b031681565b6103e881565b63bc197c8160e01b95945050505050565b60ff546001600160a01b031681565b6000826103e8811015620025555760405162461bcd60e51b815260040162000816906200564c565b6200256c6101036001600160401b03871662003fcd565b6200258b5760405162461bcd60e51b8152600401620008169062005762565b60ff54604051632df23d1560e01b81526000916001600160a01b031690632df23d1590620025be90899060040162005968565b60206040518083038186803b158015620025d757600080fd5b505afa158015620025ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002612919062004f35565b60018111156200263257634e487b7160e01b600052602160045260246000fd5b14620026525760405162461bcd60e51b81526004016200081690620057ff565b600062002660868662000a67565b905083811015620026855760405162461bcd60e51b8152600401620008169062005862565b6000620026928762003875565b90506000620026a188620038a0565b61010054604051637921219560e11b81529192506060916001600160a01b039091169063f242432a90620026e2903390309088908e9088906004016200537b565b600060405180830381600087803b158015620026fd57600080fd5b505af115801562002712573d6000803e3d6000fd5b505061010054604051627eeac760e11b8152600093506001600160a01b03909116915062fdd58e906200274c9030908890600401620053d2565b60206040518083038186803b1580156200276557600080fd5b505afa1580156200277a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620027a0919062004e49565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e90620027d99030908890600401620053d2565b60206040518083038186803b158015620027f257600080fd5b505afa15801562002807573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200282d919062004e49565b905060006200283d838362003fdb565b60ff5460405163407cf5af60e11b81529192506001600160a01b0316906380f9eb5e9062002872908f9085906004016200597c565b600060405180830381600087803b1580156200288d57600080fd5b505af1158015620028a2573d6000803e3d6000fd5b505060fe54620028c092506001600160a01b03169050338962003f44565b7f8a1b3f58d5a9a30a8aa47eec24adb52f499676f8a44e310d16ffc21058e5e7ee338d8d8a6040516200160094939291906200540c565b61010054600160a01b900461ffff1681565b6000826103e8811015620029315760405162461bcd60e51b815260040162000816906200564c565b620029486101036001600160401b03871662003fcd565b620029675760405162461bcd60e51b8152600401620008169062005762565b60ff54604051632df23d1560e01b81526000916001600160a01b031690632df23d15906200299a90899060040162005968565b60206040518083038186803b158015620029b357600080fd5b505afa158015620029c8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620029ee919062004f35565b600181111562002a0e57634e487b7160e01b600052602160045260246000fd5b1462002a2e5760405162461bcd60e51b81526004016200081690620057ff565b600062002a3c868662000866565b90508381111562002a615760405162461bcd60e51b8152600401620008169062005862565b60fe5462002a7b906001600160a01b031633308462003fa3565b600062002a888762003875565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e9062002ac19030908690600401620053d2565b60206040518083038186803b15801562002ada57600080fd5b505afa15801562002aef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002b15919062004e49565b90508681101562002cad5760ff54604051635a0c6ccf60e01b81526000916001600160a01b031690635a0c6ccf9062002b55908c908c906004016200597c565b60206040518083038186803b15801562002b6e57600080fd5b505afa15801562002b83573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002ba9919062004e49565b60fe5460ff5460405163095ea7b360e01b81529293506001600160a01b039182169263095ea7b39262002be39216908590600401620053d2565b602060405180830381600087803b15801562002bfe57600080fd5b505af115801562002c13573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002c39919062004e2a565b5060ff546001600160a01b031663ec41d4ef8a62002c58858c62005bfb565b6040518363ffffffff1660e01b815260040162002c779291906200597c565b600060405180830381600087803b15801562002c9257600080fd5b505af115801562002ca7573d6000803e3d6000fd5b50505050505b61010054604051637921219560e11b81526060916001600160a01b03169063f242432a9062002ce9903090339088908e9088906004016200537b565b600060405180830381600087803b15801562002d0457600080fd5b505af115801562002d19573d6000803e3d6000fd5b505050507f17962beb3fc6a7161941050be5382ad578714419e2eaa956e0b909ba5e67fd1f338a8a8760405162002d5494939291906200540c565b60405180910390a15091979650505050505050565b60008162002d7a575060006200055b565b60fb54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801562002dc057600080fd5b505afa15801562002dd5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002dfb919062004e49565b90508062002e0e5760009150506200055b565b600062002e1a62001700565b60fe546040516370a0823160e01b81529192506000916001600160a01b03909116906370a082319062002e5290309060040162005329565b60206040518083038186803b15801562002e6b57600080fd5b505afa15801562002e80573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002ea6919062004e49565b62002eb2908362005a0e565b90508262002ec1868262005bfb565b62002ecd908362005bb0565b62002ed9919062005a57565b90508060005b62002eec61010362003a27565b8110156200317557600062002f0461010383620043d4565b9050600060ff54604051632df23d1560e01b81526001600160a01b0390911690632df23d159062002f3a90859060040162005968565b60206040518083038186803b15801562002f5357600080fd5b505afa15801562002f68573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002f8e919062004f35565b600181111562002fae57634e487b7160e01b600052602160045260246000fd5b14156200315f576101005460009087908a906001600160a01b031662fdd58e3062002fd98762003875565b6040518363ffffffff1660e01b815260040162002ff8929190620053d2565b60206040518083038186803b1580156200301157600080fd5b505afa15801562003026573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200304c919062004e49565b62003058919062005bb0565b62003064919062005a57565b6101005490915060009088908b906001600160a01b031662fdd58e306200308b88620038a0565b6040518363ffffffff1660e01b8152600401620030aa929190620053d2565b60206040518083038186803b158015620030c357600080fd5b505afa158015620030d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620030fe919062004e49565b6200310a919062005bb0565b62003116919062005a57565b9050600062003129848488600162003a42565b905062003137818762005bfb565b955060006200314a858489600062003a42565b905062003158818862005bfb565b9650505050505b50806200316c8162005c44565b91505062002edf565b5062003182818362005bfb565b9695505050505050565b63f23a6e6160e01b95945050505050565b620031a7620038bd565b6001600160a01b0316620031ba6200233e565b6001600160a01b031614620031e35760405162461bcd60e51b81526004016200081690620057ca565b6001600160a01b0381166200320c5760405162461bcd60e51b81526004016200081690620055cc565b60c9546040516001600160a01b0380841692169060008051602062005e4e83398151915290600090a360c980546001600160a01b0319166001600160a01b0392909216919091179055565b62003261620038bd565b6001600160a01b0316620032746200233e565b6001600160a01b0316146200329d5760405162461bcd60e51b81526004016200081690620057ca565b65048c273950008111620032c55760405162461bcd60e51b815260040162000816906200556a565b6101018190556040517f64c041d58edba5f0f8c4b1e3069ab60cd040564677fd1d9533253cd81e41bffb90620032fd90839062005495565b60405180910390a150565b60008062003315620045b3565b905060008060005b6200332a61010362003a27565b811015620037aa5760006200334261010383620043d4565b60ff54604051636e1165b560e11b81529192506000916001600160a01b039091169063dc22cb6a906200337a90859060040162005968565b60c06040518083038186803b1580156200339357600080fd5b505afa158015620033a8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620033ce919062004fd1565b90506000620033dd8362003875565b90506000620033ec84620038a0565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e90620034259030908790600401620053d2565b60206040518083038186803b1580156200343e57600080fd5b505afa15801562003453573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003479919062004e49565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e90620034b29030908790600401620053d2565b60206040518083038186803b158015620034cb57600080fd5b505afa158015620034e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003506919062004e49565b9050600060ff54604051632df23d1560e01b81526001600160a01b0390911690632df23d15906200353c908a9060040162005968565b60206040518083038186803b1580156200355557600080fd5b505afa1580156200356a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003590919062004f35565b6001811115620035b057634e487b7160e01b600052602160045260246000fd5b1415620036ba576000620035c5868c62004651565b90506000620035dd82670de0b6b3a764000062005bfb565b60ff549091506000906001600160a01b0316635a0c6ccf8a670de0b6b3a76400006200360a868962005bb0565b62003616888b62005bb0565b62003622919062005a0e565b6200362e919062005a57565b6040518363ffffffff1660e01b81526004016200364d9291906200597c565b60206040518083038186803b1580156200366657600080fd5b505afa1580156200367b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620036a1919062004e49565b9050620036af818d62005a0e565b9b505050506200378e565b8b80156200376c575060ff54604051632df23d1560e01b81526001916001600160a01b031690632df23d1590620036f6908a9060040162005968565b60206040518083038186803b1580156200370f57600080fd5b505afa15801562003724573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200374a919062004f35565b60018111156200376a57634e487b7160e01b600052602160045260246000fd5b145b156200378e576200377f868284620043e2565b6200378b908962005a0e565b97505b5050505050508080620037a19062005c44565b9150506200331d565b5060fe546040516370a0823160e01b81526000916001600160a01b0316906370a0823190620037de90309060040162005329565b60206040518083038186803b158015620037f757600080fd5b505afa1580156200380c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003832919062004e49565b90508062003841838562005a0e565b62003182919062005a0e565b60006001600160e01b03198216630271189760e51b1480620005585750620005588262004685565b60006200388482600262005bd2565b6200389190600162005a29565b6001600160401b031692915050565b60006200389182600262005bd2565b600062000b0183836200469e565b3390565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015620038fb57600080fd5b505afa15801562003910573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003936919062004e49565b60008051602062005e2e83398151915214620039665760405162461bcd60e51b81526004016200081690620055a4565b8060008051602062005e2e833981519152557feeaed647dc622e55877c30943e5c1d4feb92d1b8cfcc88d974163e9787bde9af81604051620032fd919062005329565b6000600382111562003a185750806000620039c660028362005a57565b620039d390600162005a0e565b90505b8181101562003a1157905080600281620039f1818662005a57565b620039fd919062005a0e565b62003a09919062005a57565b9050620039d6565b506200055b565b81156200055b57506001919050565b60006200055882620047bf565b600062000b018383620047c3565b60008362003a535750600062003b7c565b60ff54604051635a0c6ccf60e01b81526001600160a01b0390911690635a0c6ccf9062003a8790889088906004016200597c565b60206040518083038186803b15801562003aa057600080fd5b505afa15801562003ab5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003adb919062004e49565b935060008062003aec878662003ff4565b915091506000841562003b0157508062003b04565b50815b60008362003b13848a62005a0e565b62003b1f919062005a0e565b90506000600262003b5c8462003b378c600462005bb0565b62003b43919062005bb0565b62003b5060028662005ac5565b6200098e919062005bfb565b62003b68908462005bfb565b62003b74919062005a57565b955050505050505b949350505050565b6000805b62003b9561010362003a27565b81101562003f3957600062003bad61010383620043d4565b9050600060ff54604051632df23d1560e01b81526001600160a01b0390911690632df23d159062003be390859060040162005968565b60206040518083038186803b15801562003bfc57600080fd5b505afa15801562003c11573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003c37919062004f35565b600181111562003c5757634e487b7160e01b600052602160045260246000fd5b141562003f2357600062003c6b8262003875565b9050600062003c7a83620038a0565b61010054604051627eeac760e11b81529192506000918b918d916001600160a01b039091169062fdd58e9062003cb79030908990600401620053d2565b60206040518083038186803b15801562003cd057600080fd5b505afa15801562003ce5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003d0b919062004e49565b62003d17919062005bb0565b62003d23919062005a57565b61010054604051627eeac760e11b81529192506000918c918e916001600160a01b039091169062fdd58e9062003d609030908990600401620053d2565b60206040518083038186803b15801562003d7957600080fd5b505afa15801562003d8e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003db4919062004e49565b62003dc0919062005bb0565b62003dcc919062005a57565b905088158062003ddb57508a8c145b1562003ed957811562003e5a5761010054604051637921219560e11b81526060916001600160a01b03169063f242432a9062003e249030908f908a90899088906004016200537b565b600060405180830381600087803b15801562003e3f57600080fd5b505af115801562003e54573d6000803e3d6000fd5b50505050505b801562003ed35761010054604051637921219560e11b81526060916001600160a01b03169063f242432a9062003e9d9030908f908990889088906004016200537b565b600060405180830381600087803b15801562003eb857600080fd5b505af115801562003ecd573d6000803e3d6000fd5b50505050505b62003f1e565b600062003eea86848b600162003a42565b905062003ef8818a62005bfb565b9850600062003f0b87848c600062003a42565b905062003f19818b62005bfb565b995050505b505050505b508062003f308162005c44565b91505062003b88565b509095945050505050565b62003f9e8363a9059cbb60e01b848460405160240162003f66929190620053d2565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915262004812565b505050565b62003fc7846323b872dd60e01b85858560405160240162003f669392919062005357565b50505050565b600062000b018383620048a9565b60008183101562003fee575081620009cb565b50919050565b6000806000620040048562003875565b905060006200401386620038a0565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e906200404c9030908790600401620053d2565b60206040518083038186803b1580156200406557600080fd5b505afa1580156200407a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620040a0919062004e49565b61010054604051627eeac760e11b81529192506000916001600160a01b039091169062fdd58e90620040d99030908790600401620053d2565b60206040518083038186803b158015620040f257600080fd5b505afa15801562004107573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200412d919062004e49565b60ff54604051636e1165b560e11b81529192506000916001600160a01b039091169063dc22cb6a9062004165908c9060040162005968565b60c06040518083038186803b1580156200417e57600080fd5b505afa15801562004193573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620041b9919062004fd1565b9050806020015115620042da5760ff54604051635a0c6ccf60e01b81526001600160a01b0390911690635a0c6ccf90620041fa908c9087906004016200597c565b60206040518083038186803b1580156200421357600080fd5b505afa15801562004228573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200424e919062004e49565b60ff54604051635a0c6ccf60e01b81529194506001600160a01b031690635a0c6ccf9062004283908c9086906004016200597c565b60206040518083038186803b1580156200429c57600080fd5b505afa158015620042b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620042d7919062004e49565b91505b6000620042e8898562005a0e565b90506000620042f88a8562005a0e565b905060006200430b84620024de620045b3565b905060006200432382670de0b6b3a764000062005bfb565b90506000808284116200437b578591508262004340858462005bb0565b6200434c919062005a57565b905084811115620043755750838362004366848362005bb0565b62004372919062005a57565b91505b620043c0565b5083836200438a848362005bb0565b62004396919062005a57565b915085821115620043c05785915082620043b1858462005bb0565b620043bd919062005a57565b90505b909e909d509b505050505050505050505050565b600062000b018383620048c1565b6000808315620044875760ff54604051632dc6358360e21b81526000916001600160a01b03169063b718d60c906200442190899089906004016200597c565b604080518083038186803b1580156200443957600080fd5b505afa1580156200444e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200447491906200513c565b50905062004483818362005a0e565b9150505b821562003b7c5760ff546040516360b4d34960e01b81526000916001600160a01b0316906360b4d34990620044c390899088906004016200597c565b604080518083038186803b158015620044db57600080fd5b505afa158015620044f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200451691906200513c565b50905062003182818362005a0e565b600054610100900460ff16806200453f575060005460ff16155b6200455e5760405162461bcd60e51b81526004016200081690620056bd565b600054610100900460ff161580156200458a576000805460ff1961ff0019909116610100171660011790555b620045946200491e565b6200459e62004997565b801562000853576000805461ff001916905550565b6101025460fc5460fd5460405163db16a55560e01b81526000936001600160a01b0361010090910481169363db16a55593620045f8939183169216906004016200533d565b60206040518083038186803b1580156200461157600080fd5b505afa15801562004626573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200464c919062004e49565b905090565b600062000b0142846000015164ffffffffff1662004670919062005bfb565b8460600151846101015487602001516200223a565b6001600160e01b031981166301ffc9a760e01b14919050565b60008181526001830160205260408120548015620047b4576000620046c560018362005bfb565b8554909150600090620046db9060019062005bfb565b905060008660000182815481106200470357634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050808760000184815481106200473557634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255828152600189019091526040902084905586548790806200477757634e487b7160e01b600052603160045260246000fd5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050620009cb565b6000915050620009cb565b5490565b6000620047d18383620048a9565b6200480957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620009cb565b506000620009cb565b600062004869826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662004a5a9092919063ffffffff16565b80519091501562003f9e57808060200190518101906200488a919062004e2a565b62003f9e5760405162461bcd60e51b81526004016200081690620058aa565b60009081526001919091016020526040902054151590565b81546000908210620048e75760405162461bcd60e51b8152600401620008169062005528565b8260000182815481106200490b57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b600054610100900460ff168062004938575060005460ff16155b620049575760405162461bcd60e51b81526004016200081690620056bd565b600054610100900460ff161580156200459e576000805460ff1961ff001990911661010017166001179055801562000853576000805461ff001916905550565b600054610100900460ff1680620049b1575060005460ff16155b620049d05760405162461bcd60e51b81526004016200081690620056bd565b600054610100900460ff16158015620049fc576000805460ff1961ff0019909116610100171660011790555b600062004a08620038bd565b60c980546001600160a01b0319166001600160a01b0383169081179091556040519192509060009060008051602062005e4e833981519152908290a350801562000853576000805461ff001916905550565b606062003b7c84846000858562004a718562004b0f565b62004a905760405162461bcd60e51b815260040162000816906200582b565b600080866001600160a01b0316858760405162004aae91906200527e565b60006040518083038185875af1925050503d806000811462004aed576040519150601f19603f3d011682016040523d82523d6000602084013e62004af2565b606091505b509150915062004b0482828662004b15565b979650505050505050565b3b151590565b6060831562004b2657508162000b01565b82511562004b375782518084602001fd5b8160405162461bcd60e51b8152600401620008169190620054d6565b61017a8062005cb483390190565b604080516080810182526000808252602082015290810162004b8262004b8f565b8152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b600082601f83011262004bc0578081fd5b813560206001600160401b0382111562004bde5762004bde62005c78565b80820262004bee828201620059b8565b83815282810190868401838801850189101562004c09578687fd5b8693505b8584101562004c2d57803583526001939093019291840191840162004c0d565b50979650505050505050565b600082601f83011262004c4a578081fd5b813562004c6162004c5b82620059e4565b620059b8565b81815284602083860101111562004c76578283fd5b816020850160208301379081016020019190915292915050565b80356001600160401b03811681146200055b57600080fd5b60006020828403121562004cba578081fd5b813562000b018162005c8e565b60006020828403121562004cd9578081fd5b815162000b018162005c8e565b600080600080600060a0868803121562004cfe578081fd5b853562004d0b8162005c8e565b9450602086013562004d1d8162005c8e565b935060408601356001600160401b038082111562004d39578283fd5b62004d4789838a0162004baf565b9450606088013591508082111562004d5d578283fd5b62004d6b89838a0162004baf565b9350608088013591508082111562004d81578283fd5b5062004d908882890162004c39565b9150509295509295909350565b600080600080600060a0868803121562004db5578081fd5b853562004dc28162005c8e565b9450602086013562004dd48162005c8e565b9350604086013592506060860135915060808601356001600160401b0381111562004dfd578182fd5b62004d908882890162004c39565b60006020828403121562004e1d578081fd5b813562000b018162005ca4565b60006020828403121562004e3c578081fd5b815162000b018162005ca4565b60006020828403121562004e5b578081fd5b5051919050565b60006020828403121562004e74578081fd5b81356001600160e01b03198116811462000b01578182fd5b600080600080600080600060e0888a03121562004ea7578485fd5b873562004eb48162005c8e565b9650602088013562004ec68162005c8e565b9550604088013562004ed88162005c8e565b9450606088013562004eea8162005c8e565b9350608088013562004efc8162005c8e565b925060a088013562004f0e8162005c8e565b915060c088013561ffff8116811462004f25578182fd5b8091505092959891949750929550565b60006020828403121562004f47578081fd5b81516002811062000b01578182fd5b60006020828403121562004f68578081fd5b81516001600160401b0381111562004f7e578182fd5b8201601f8101841362004f8f578182fd5b805162004fa062004c5b82620059e4565b81815285602083850101111562004fb5578384fd5b62004fc882602083016020860162005c15565b95945050505050565b600081830360c081121562004fe4578182fd5b60408051608081016001600160401b0380821183831017156200500b576200500b62005c78565b90835285519064ffffffffff8216821462005024578586fd5b908252602086015190620050388262005ca4565b8160208401526060603f198601121562005050578586fd5b83519450606085019150848210818311171562005071576200507162005c78565b50825284820151620050838162005c8e565b83526060850151620050958162005c8e565b60208401526080850151620050aa8162005c8e565b838301529081019190915260a09290920151606083015250919050565b600060208284031215620050d9578081fd5b5035919050565b600080600060608486031215620050f5578081fd5b833592506020840135620051098162005ca4565b929592945050506040919091013590565b600080604083850312156200512d578182fd5b50508035926020909101359150565b600080604083850312156200514f578182fd5b505080516020909101519092909150565b600080600080600060a0868803121562005178578283fd5b853594506020860135935060408601359250606086013591506080860135620051a18162005ca4565b809150509295509295909350565b600060208284031215620051c1578081fd5b62000b018262004c90565b60008060408385031215620051df578182fd5b620051ea8362004c90565b946020939093013593505050565b6000806000606084860312156200520d578081fd5b620052188462004c90565b95602085013595506040909401359392505050565b6000602082840312156200523f578081fd5b815160ff8116811462000b01578182fd5b600081518084526200526a81602086016020860162005c15565b601f01601f19169290920160200192915050565b600082516200529281846020870162005c15565b9190910192915050565b60008451620052b081846020890162005c15565b8083019050602d60f81b8082528551620052d2816001850160208a0162005c15565b60019201918201528351620052ef81600284016020880162005c15565b0160020195945050505050565b6000624c502d60e81b825282516200531c81600385016020870162005c15565b9190910160030192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009062004b049083018462005250565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b039490941684526001600160401b039290921660208401526040830152606082015260800190565b6020808252825182820181905260009190848201906040850190845b818110156200547e5783516001600160401b03168352928401929184019160010162005457565b50909695505050505050565b901515815260200190565b90815260200190565b6001600160e01b031991909116815260200190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020825262000b01602083018462005250565b60006060825262005500606083018662005250565b828103602084015262005514818662005250565b91505060ff83166040830152949350505050565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b60208082526003908201526245303960e81b604082015260600190565b60208082526003908201526222981b60e91b604082015260600190565b6020808252600e908201526d4e6f7420636f6d70617469626c6560901b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526003908201526245303560e81b604082015260600190565b60208082526003908201526245303760e81b604082015260600190565b6020808252601e908201527f4275792f53656c6c20616d6f756e742062656c6f77206d696e2073697a650000604082015260600190565b60208082526003908201526204531360ec1b604082015260600190565b60208082526003908201526222981960e91b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526003908201526245303360e81b604082015260600190565b602080825260039082015262114c0d60ea1b604082015260600190565b60208082526003908201526245313160e81b604082015260600190565b60208082526003908201526245313360e81b604082015260600190565b60208082526003908201526208a60760eb1b604082015260600190565b602080825260149082015273546f6f206d616e79206f70656e2073657269657360601b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526012908201527114d95c9a595cc81a185cc8195e1c1a5c995960721b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526011908201527014db1a5c1c1859d948195e18d959591959607a1b604082015260600190565b60208082526003908201526222989960e91b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b815164ffffffffff16815260208083015115158183015260408084015180516001600160a01b039081168386015292810151831660608086019190915291015190911660808301529091015160a082015260c00190565b61ffff91909116815260200190565b918252602082015260400190565b6001600160401b0391909116815260200190565b6001600160401b03929092168252602082015260400190565b6001600160401b0393909316835260208301919091521515604082015260600190565b6040518181016001600160401b0381118282101715620059dc57620059dc62005c78565b604052919050565b60006001600160401b0382111562005a005762005a0062005c78565b50601f01601f191660200190565b6000821982111562005a245762005a2462005c62565b500190565b60006001600160401b0382811684821680830382111562005a4e5762005a4e62005c62565b01949350505050565b60008262005a7357634e487b7160e01b81526012600452602481fd5b500490565b80825b600180861162005a8c575062005abc565b81870482111562005aa15762005aa162005c62565b8086161562005aaf57918102915b9490941c93800262005a7b565b94509492505050565b600062000b0160001960ff85168460008262005ae45750600162000b01565b8162005af35750600062000b01565b816001811462005b0c576002811462005b175762005b4b565b600191505062000b01565b60ff84111562005b2b5762005b2b62005c62565b6001841b91508482111562005b445762005b4462005c62565b5062000b01565b5060208310610133831016604e8410600b841016171562005b83575081810a8381111562005b7d5762005b7d62005c62565b62000b01565b62005b92848484600162005a78565b80860482111562005ba75762005ba762005c62565b02949350505050565b600081600019048311821515161562005bcd5762005bcd62005c62565b500290565b60006001600160401b038281168482168115158284048211161562005ba75762005ba762005c62565b60008282101562005c105762005c1062005c62565b500390565b60005b8381101562005c3257818101518382015260200162005c18565b8381111562003fc75750506000910152565b600060001982141562005c5b5762005c5b62005c62565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146200085357600080fd5b80151581146200085357600080fdfe608060405234801561001057600080fd5b5060405161017a38038061017a83398101604081905261002f91610085565b6001600160a01b03811661005e5760405162461bcd60e51b8152600401610055906100b3565b60405180910390fd5b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7556100ea565b600060208284031215610096578081fd5b81516001600160a01b03811681146100ac578182fd5b9392505050565b6020808252601c908201527f436f6e7472616374204c6f6769632063616e6e6f742062652030783000000000604082015260600190565b6082806100f86000396000f3fe60806040527fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75460405136600082376000803683855af491503d806000833e8280156048578183f35b8183fdfea2646970667358221220b04eb4efe1afc63fafe40b925666dcdc7adb4071edf6d91800848d844aa9854164736f6c63430008000033c5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf78be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0e337a2229426e90a5cd240c2f297ff2996f8eb47424c5b228dc36313c67a7ec3a264697066735822122082ceb127a56127aff97a02cba10192804ce1e97e82252de58ec43c8eaca8b64764736f6c63430008000033

Deployed ByteCode Sourcemap

3553:48103:20:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51409:245;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;16647:1253;;;;;;:::i;:::-;;:::i;:::-;;10766:213;;;;;;:::i;:::-;;:::i;4391:33::-;;;:::i;:::-;;;;;;;:::i;38775:974::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;4105:29::-;;;:::i;50675:456::-;;;;;;:::i;:::-;;:::i;4140:24::-;;;:::i;40430:350::-;;;;;;:::i;:::-;;:::i;43045:351::-;;;;;;:::i;:::-;;:::i;13380:1886::-;;;;;;:::i;:::-;;:::i;11208:1901::-;;;;;;:::i;:::-;;:::i;41259:1701::-;;;;;;:::i;:::-;;:::i;945:102:22:-;;;:::i;26071:328:20:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;45481:1246::-;;;:::i;3993:27::-;;;:::i;24866:282::-;;;:::i;:::-;;;;;;;:::i;1945:145:21:-;;;:::i;7667:2491:20:-;;;;;;:::i;:::-;;:::i;15452:1013::-;;;:::i;4599:31::-;;;:::i;32396:1070::-;;;;;;:::i;:::-;;:::i;1313:85:21:-;;;:::i;25567:232:20:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;30794:331::-;;;;;;:::i;:::-;;:::i;748:191:22:-;;;:::i;4170:29:20:-;;;:::i;4732:49::-;;;:::i;698:201:3:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;4283:41:20:-;;;:::i;36344:1845::-;;;;;;:::i;:::-;;:::i;4460:33::-;;;:::i;:::-;;;;;;;:::i;33696:2032::-;;;;;;:::i;:::-;;:::i;46824:2475::-;;;;;;:::i;:::-;;:::i;519:173:3:-;;;;;;:::i;:::-;;:::i;2239:240:21:-;;;;;;:::i;:::-;;:::i;10238:315:20:-;;;;;;:::i;:::-;;:::i;21776:2717::-;;;;;;:::i;:::-;;:::i;51409:245::-;51518:4;-1:-1:-1;;;;;;51557:38:20;;-1:-1:-1;;;51557:38:20;;:90;;;51611:36;51635:11;51611:23;:36::i;:::-;51538:109;;51409:245;;;;:::o;16647:1253::-;16796:19;16818:35;16844:8;16818:25;:35::i;:::-;16796:57;;16863:19;16885:35;16911:8;16885:25;:35::i;:::-;16967:17;;:55;;-1:-1:-1;;;16967:55:20;;16863:57;;-1:-1:-1;16931:21:20;;-1:-1:-1;;;;;16967:17:20;;;;:27;;:55;;17003:4;;17010:11;;16967:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;16931:91;-1:-1:-1;17036:17:20;;17032:111;;17069:16;;:63;;-1:-1:-1;;;17069:63:20;;-1:-1:-1;;;;;17069:16:20;;;;:31;;:63;;17101:8;;17111:13;;17069:16;;:63;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17032:111;17189:17;;:55;;-1:-1:-1;;;17189:55:20;;17153:21;;-1:-1:-1;;;;;17189:17:20;;:27;;:55;;17225:4;;17232:11;;17189:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17153:91;-1:-1:-1;17258:17:20;;17254:105;;17291:16;;:57;;-1:-1:-1;;;17291:57:20;;-1:-1:-1;;;;;17291:16:20;;;;:32;;:57;;17324:8;;17334:13;;17291:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17254:105;17827:27;:10;-1:-1:-1;;;;;17827:27:20;;:17;:27::i;:::-;;17870:23;17884:8;17870:23;;;;;;:::i;:::-;;;;;;;;16647:1253;;;;;:::o;10766:213::-;1536:12:21;:10;:12::i;:::-;-1:-1:-1;;;;;1525:23:21;:7;:5;:7::i;:::-;-1:-1:-1;;;;;1525:23:21;;1517:68;;;;-1:-1:-1;;;1517:68:21;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;10881:34:20;::::1;10873:50;;;;-1:-1:-1::0;;;10873:50:20::1;;;;;;;:::i;:::-;10934:38;10953:18;10934;:38::i;:::-;10766:213:::0;:::o;4391:33::-;;;-1:-1:-1;;;;;4391:33:20;;:::o;38775:974::-;38890:7;38950:17;38946:31;;-1:-1:-1;38976:1:20;38969:8;;38946:31;39003:16;;:102;;-1:-1:-1;;;39003:102:20;;-1:-1:-1;;;;;39003:16:20;;;;:44;;:102;;39061:8;;39083:12;;39003:102;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38988:117;;39195:21;39218;39255:28;39274:8;39255:18;:28::i;:::-;39194:89;;-1:-1:-1;39194:89:20;-1:-1:-1;39294:18:20;39315:29;39194:89;;39315:29;:::i;:::-;39294:50;;39354:16;39397:12;39384:10;:25;39380:159;;;39436:25;39449:12;39436:10;:25;:::i;:::-;39425:36;;39380:159;;;39503:25;39518:10;39503:12;:25;:::i;:::-;39492:36;;39380:159;39741:1;39724:13;39707;39691:12;39611:61;39724:13;39638:16;39691:12;39638:1;:16;:::i;:::-;:32;;;;:::i;:::-;39622:11;39632:1;39622:8;:11;:::i;:::-;39621:50;;;;:::i;:::-;39611:9;:61::i;:::-;:92;;;;:::i;:::-;39610:110;;;;:::i;:::-;39609:128;;;;:::i;:::-;39608:134;;;;:::i;:::-;39589:153;;;;;;38775:974;;;;;:::o;4105:29::-;;;-1:-1:-1;;;;;4105:29:20;;:::o;50675:456::-;50770:16;;-1:-1:-1;;;;;50770:16:20;50748:10;:39;50740:55;;;;-1:-1:-1;;;50740:55:20;;;;;;;:::i;:::-;51061:3;51038:19;:10;:17;:19::i;:::-;:26;;51030:59;;;;-1:-1:-1;;;51030:59:20;;;;;;;:::i;:::-;51099:25;:10;-1:-1:-1;;;;;51099:25:20;;:14;:25::i;:::-;;50675:456;:::o;4140:24::-;;;-1:-1:-1;;;;;4140:24:20;;:::o;40430:350::-;40697:15;;:40;;-1:-1:-1;;;40697:40:20;;40546:7;;40588:185;;40641:8;;40667:12;;-1:-1:-1;;;;;40697:15:20;;;;:25;;:40;;40731:4;;40697:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40755:4;40588:35;:185::i;:::-;40569:204;40430:350;-1:-1:-1;;;40430:350:20:o;43045:351::-;43312:15;;:40;;-1:-1:-1;;;43312:40:20;;43161:7;;43203:186;;43256:8;;43282:12;;-1:-1:-1;;;;;43312:15:20;;;;:25;;:40;;43346:4;;43312:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43370:5;43203:35;:186::i;13380:1886::-;13528:10;13527:11;:36;;;;13562:1;13542:17;:21;13527:36;13519:52;;;;-1:-1:-1;;;13519:52:20;;;;;;;:::i;:::-;13667:15;;:37;;-1:-1:-1;;;13667:37:20;;13619:33;;-1:-1:-1;;;;;13667:15:20;;:25;;:37;;13693:10;;13667:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13619:85;;13749:21;13791:7;;;;;;;;;-1:-1:-1;;;;;13791:7:20;-1:-1:-1;;;;;13773:39:20;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13855:7;;:39;;-1:-1:-1;;;13855:39:20;;13749:65;;-1:-1:-1;;;;;;13855:7:20;;:12;;:39;;13868:10;;13880:13;;13855:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13942:23;:21;:23::i;:::-;14021:15;;:40;;-1:-1:-1;;;14021:40:20;;13976:30;;-1:-1:-1;;;;;14021:15:20;;:25;;:40;;14055:4;;14021:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13976:85;-1:-1:-1;14304:28:20;14432:13;14390:38;14415:13;13976:85;14390:38;:::i;:::-;14389:56;;;;:::i;:::-;14347:99;;:22;:99;:::i;:::-;14304:142;;14553:173;14594:13;14621;14648:10;14672;14696:20;14553:27;:173::i;:::-;14530:196;-1:-1:-1;14786:121:20;14828:10;14852:45;14530:196;14852:22;:45;:::i;:::-;14786:15;;-1:-1:-1;;;;;14786:15:20;;:121;:28;:121::i;:::-;14960:15;;:37;;-1:-1:-1;;;14960:37:20;;14918:27;;15000:25;;-1:-1:-1;;;;;14960:15:20;;;;:25;;:37;;14986:10;;14960:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:65;;;;:::i;:::-;14918:107;;15058:10;15057:11;:55;;;;15095:17;15072:19;:40;;15057:55;15036:119;;;;-1:-1:-1;;;15036:119:20;;;;;;;:::i;:::-;15197:62;15212:10;15224:19;15245:13;15197:62;;;;;;;;:::i;:::-;;;;;;;;13380:1886;;;;;;;;:::o;11208:1901::-;11359:15;;:123;;-1:-1:-1;;;;;11359:15:20;11405:10;11437:4;11456:16;11359:32;:123::i;:::-;11605:7;;;;;;;;;-1:-1:-1;;;;;11605:7:20;-1:-1:-1;;;;;11587:39:20;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11583:362;;11691:7;;:42;;-1:-1:-1;;;11691:42:20;;-1:-1:-1;;;;;11691:7:20;;;;:12;;:42;;11704:10;;11716:16;;11691:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;11789:10:20;11801:16;11819;11774:62;;;;;;;;:::i;:::-;;;;;;;;11928:7;;11583:362;12403:23;:21;:23::i;:::-;12437:17;12457:24;12475:5;12457:17;:24::i;:::-;12437:44;;12586:29;12648:7;;;;;;;;;-1:-1:-1;;;;;12648:7:20;-1:-1:-1;;;;;12630:39:20;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12586:85;-1:-1:-1;12682:25:20;12777:28;12789:16;12777:9;:28;:::i;:::-;12723:33;12735:21;12723:9;:33;:::i;:::-;12722:84;;;;:::i;:::-;12682:124;-1:-1:-1;12816:22:20;12841:41;12861:21;12682:124;12841:41;:::i;:::-;12816:66;;12918:14;12900;:32;;12892:62;;;;-1:-1:-1;;;12892:62:20;;;;;;;:::i;:::-;12964:7;;:40;;-1:-1:-1;;;12964:40:20;;-1:-1:-1;;;;;12964:7:20;;;;:12;;:40;;12977:10;;12989:14;;12964:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;13057:10:20;13069:16;13087:14;13042:60;;;;;;;;:::i;:::-;;;;;;;;11208:1901;;;;;;:::o;41259:1701::-;41420:7;41397:12;4777:4;7482:9;:31;;7461:108;;;;-1:-1:-1;;;7461:108:20;;;;;;;:::i;:::-;41447:29:::1;:10;-1:-1:-1::0;;;;;41447:29:20;::::1;:19;:29::i;:::-;41439:45;;;;-1:-1:-1::0;;;41439:45:20::1;;;;;;;:::i;:::-;41516:16;::::0;:32:::1;::::0;-1:-1:-1;;;41516:32:20;;41568:34:::1;::::0;-1:-1:-1;;;;;41516:16:20::1;::::0;:22:::1;::::0;:32:::1;::::0;41539:8;;41516:32:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:86;;;;;;-1:-1:-1::0;;;41516:86:20::1;;;;;;;;;;41495:151;;;;-1:-1:-1::0;;;41495:151:20::1;;;;;;;:::i;:::-;41686:24;41725:46;41748:8;41758:12;41725:22;:46::i;:::-;41686:85;;41809:17;41789:16;:37;;41781:67;;;;-1:-1:-1::0;;;41781:67:20::1;;;;;;;:::i;:::-;41859:19;41881:35;41907:8;41881:25;:35::i;:::-;41859:57;;41926:19;41948:35;41974:8;41948:25;:35::i;:::-;42063:17;::::0;:164:::1;::::0;-1:-1:-1;;;42063:164:20;;41926:57;;-1:-1:-1;42036:17:20::1;::::0;-1:-1:-1;;;;;42063:17:20;;::::1;::::0;:34:::1;::::0;:164:::1;::::0;42111:10:::1;::::0;42143:4:::1;::::0;41926:57;;42187:12;;42036:17;;42063:164:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;42304:17:20::1;::::0;:55:::1;::::0;-1:-1:-1;;;42304:55:20;;42268:21:::1;::::0;-1:-1:-1;;;;;;42304:17:20;;::::1;::::0;-1:-1:-1;42304:27:20::1;::::0;:55:::1;::::0;42340:4:::1;::::0;42347:11;;42304:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42405:17;::::0;:55:::1;::::0;-1:-1:-1;;;42405:55:20;;42268:91;;-1:-1:-1;42369:21:20::1;::::0;-1:-1:-1;;;;;42405:17:20;;::::1;::::0;:27:::1;::::0;:55:::1;::::0;42441:4:::1;::::0;42448:11;;42405:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42369:91;;42470:19;42492:38;42501:13;42516;42492:8;:38::i;:::-;42470:60:::0;-1:-1:-1;42544:15:20;;42540:99:::1;;42575:16;::::0;:53:::1;::::0;-1:-1:-1;;;42575:53:20;;-1:-1:-1;;;;;42575:16:20;;::::1;::::0;:30:::1;::::0;:53:::1;::::0;42606:8;;42616:11;;42575:53:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;42540:99;42690:15;::::0;:58:::1;::::0;-1:-1:-1;;;;;42690:15:20::1;42719:10;42731:16:::0;42690:28:::1;:58::i;:::-;42790:65;42802:10;42814:8;42824:12;42838:16;42790:65;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;42937:16:20;;41259:1701;-1:-1:-1;;;;;;;;;;41259:1701:20:o;945:102:22:-;-1:-1:-1;;;;;;;;;;;945:102:22;:::o;26071:328:20:-;26161:7;;26201:29;:10;-1:-1:-1;;;;;26201:29:20;;:19;:29::i;:::-;26193:45;;;;-1:-1:-1;;;26193:45:20;;;;;;;:::i;:::-;26338:15;;:40;;-1:-1:-1;;;26338:40:20;;26268:124;;26312:8;;-1:-1:-1;;;;;26338:15:20;;;;:25;;:40;;26372:4;;26338:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26268:26;:124::i;:::-;26249:143;;;;26071:328;;;:::o;45481:1246::-;45580:7;;;45646:1037;45670:19;:10;:17;:19::i;:::-;45666:1;:23;45646:1037;;;45710:15;45735:16;:10;45749:1;45735:13;:16::i;:::-;45710:42;-1:-1:-1;45840:37:20;45788:16;;:32;;-1:-1:-1;;;45788:32:20;;-1:-1:-1;;;;;45788:16:20;;;;:22;;:32;;45811:8;;45788:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;;;;-1:-1:-1;;;45788:89:20;;;;;;;;;;45767:906;;;45910:19;45932:35;45958:8;45932:25;:35::i;:::-;45910:57;;45985:19;46007:35;46033:8;46007:25;:35::i;:::-;46161:17;;:55;;-1:-1:-1;;;46161:55:20;;45985:57;;-1:-1:-1;46117:21:20;;-1:-1:-1;;;;;46161:17:20;;;;:27;;:55;;46197:4;;46204:11;;46161:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46278:17;;:55;;-1:-1:-1;;;46278:55:20;;46117:99;;-1:-1:-1;46234:21:20;;-1:-1:-1;;;;;46278:17:20;;;;:27;;:55;;46314:4;;46321:11;;46278:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46234:99;;46517:141;46562:8;46592:13;46627;46517:23;:141::i;:::-;46493:165;;;;:::i;:::-;;;45767:906;;;;;-1:-1:-1;45691:3:20;;;;:::i;:::-;;;;45646:1037;;;-1:-1:-1;46700:20:20;-1:-1:-1;45481:1246:20;:::o;3993:27::-;;;-1:-1:-1;;;;;3993:27:20;;:::o;24866:282::-;24913:15;24940:22;24978:19;:10;:17;:19::i;:::-;-1:-1:-1;;;;;24965:33:20;;;;;-1:-1:-1;;;24965:33:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24965:33:20;;24940:58;;25013:9;25008:111;25032:19;:10;:17;:19::i;:::-;25028:1;:23;25008:111;;;25091:16;:10;25105:1;25091:13;:16::i;:::-;25072:6;25079:1;25072:9;;;;;;-1:-1:-1;;;25072:9:20;;;;;;;;;-1:-1:-1;;;;;25072:36:20;;;:9;;;;;;;;;;;:36;25053:3;;;;:::i;:::-;;;;25008:111;;1945:145:21;1536:12;:10;:12::i;:::-;-1:-1:-1;;;;;1525:23:21;:7;:5;:7::i;:::-;-1:-1:-1;;;;;1525:23:21;;1517:68;;;;-1:-1:-1;;;1517:68:21;;;;;;;:::i;:::-;2035:6:::1;::::0;2014:40:::1;::::0;2051:1:::1;::::0;-1:-1:-1;;;;;2035:6:21::1;::::0;-1:-1:-1;;;;;;;;;;;2014:40:21;2051:1;;2014:40:::1;2064:6;:19:::0;;-1:-1:-1;;;;;;2064:19:21::1;::::0;;1945:145::o;7667:2491:20:-;-1:-1:-1;;;;;7976:42:20;;7968:58;;;;-1:-1:-1;;;7968:58:20;;;;;;;:::i;:::-;-1:-1:-1;;;;;8044:41:20;;8036:57;;;;-1:-1:-1;;;8036:57:20;;;;;;;:::i;:::-;-1:-1:-1;;;;;8111:36:20;;8103:52;;;;-1:-1:-1;;;8103:52:20;;;;;;;:::i;:::-;-1:-1:-1;;;;;8173:41:20;;8165:57;;;;-1:-1:-1;;;8165:57:20;;;;;;;:::i;:::-;8277:11;-1:-1:-1;;;;;8240:49:20;8248:16;-1:-1:-1;;;;;8240:49:20;;;8232:65;;;;-1:-1:-1;;;8232:65:20;;;;;;;:::i;:::-;-1:-1:-1;;;;;8315:36:20;;8307:52;;;;-1:-1:-1;;;8307:52:20;;;;;;;:::i;:::-;8434:11;;;;8433:12;8425:28;;;;-1:-1:-1;;;8425:28:20;;;;;;;:::i;:::-;8463:11;:18;;-1:-1:-1;;8463:18:20;8477:4;8463:18;;;;8528:36;;-1:-1:-1;;;;;8528:36:20;;-1:-1:-1;;;;;;8528:36:20;;;;;;;;8603:37;;;-1:-1:-1;;;8603:37:20;;;;:35;;:37;;;;;;;;;;;;;;;8528:36;8603:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8574:17;:67;;-1:-1:-1;;;;;;8574:67:20;-1:-1:-1;;;;;8574:67:20;;;;;;;;8747:16;;8703:68;;-1:-1:-1;;;8703:68:20;;:17;;;;:35;;:68;;8747:16;;;;-1:-1:-1;;8703:68:20;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8782:16:20;:36;;-1:-1:-1;;;;;;8782:36:20;;-1:-1:-1;;;;;8782:36:20;;;;;;;;;;;;8828:42;;-1:-1:-1;;;;8828:42:20;-1:-1:-1;;;8828:42:20;;;;;;;;8915:15;:34;;-1:-1:-1;;;;;;8915:34:20;;;;;;;;;;8959:10;:24;;;;;;;;;;8993:15;:34;;;;;;;;;;;;;;-1:-1:-1;;9107:31:20;;-1:-1:-1;;9117:20:20;;9107:31;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9148:7:20;:45;;-1:-1:-1;;;;;;9148:45:20;-1:-1:-1;;;;;9148:45:20;;;;;;;;;;9423:15;;9405:44;;;-1:-1:-1;;;9405:44:20;;;;9148:45;;-1:-1:-1;;;9423:15:20;;;;;9405:42;;:44;;;;;-1:-1:-1;;9405:44:20;;;;;;;9423:15;9405:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9405:44:20;;;;;;;;;;;;:::i;:::-;9514:10;;;;;;;;;-1:-1:-1;;;;;9514:10:20;-1:-1:-1;;;;;9496:37:20;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9496:39:20;;;;;;;;;;;;:::i;:::-;9600:15;;;;;;;;;-1:-1:-1;;;;;9600:15:20;-1:-1:-1;;;;;9582:42:20;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9582:44:20;;;;;;;;;;;;:::i;:::-;9367:277;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;9307:351;;9668:25;9727:7;9703:32;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;9703:32:20;;;;;;9746:7;;9846:15;;-1:-1:-1;;;9828:46:20;;;;9703:32;;-1:-1:-1;;;;;;9746:7:20;;;;:18;;9703:32;;;;9846:15;;;;9828:44;;:46;;;;;9703:32;;9828:46;;;;;;;9846:15;9828:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9746:138;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9985:7:20;9966:16;:26;-1:-1:-1;10003:16:20;;-1:-1:-1;10003:14:20;:16::i;:::-;10063:7;;10035:116;;;;;;-1:-1:-1;;;;;10063:7:20;;;;10084:17;;10123;;10035:116;:::i;:::-;;;;;;;;7667:2491;;;;;;;;;;:::o;15452:1013::-;15507:9;15502:957;15526:19;:10;:17;:19::i;:::-;15522:1;:23;15502:957;;;15566:15;15591:16;:10;15605:1;15591:13;:16::i;:::-;15566:42;;15622:827;15646:16;;:32;;-1:-1:-1;;;15646:32:20;;15698:37;;-1:-1:-1;;;;;15646:16:20;;:22;;:32;;15669:8;;15646:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;;;;-1:-1:-1;;;15646:89:20;;;;;;;;;;15622:827;;;15768:28;15787:8;15768:18;:28::i;:::-;16286:19;:10;:17;:19::i;:::-;16281:1;:24;16277:158;;;16329:5;;16277:158;16399:16;:10;16413:1;16399:13;:16::i;:::-;16381:35;;15622:827;;;-1:-1:-1;15547:3:20;;;;:::i;:::-;;;;15502:957;;4599:31;;;;:::o;32396:1070::-;32583:7;;;32665:756;;;;32715:6;32700:12;:21;32696:136;;;32811:6;32778:21;32787:12;32811:6;32778:21;:::i;:::-;32777:30;;32803:4;32777:30;:::i;:::-;32776:41;;;;:::i;:::-;32764:53;;32696:136;32943:12;32917:6;32904:10;32875:26;32885:15;32875:9;:26::i;:::-;:39;;;;:::i;:::-;:48;;;;:::i;:::-;32874:81;;;;:::i;:::-;32846:109;;32665:756;;;33005:6;32990:12;:21;32986:142;;;33101:12;33068:21;33083:6;33101:12;33068:21;:::i;:::-;33067:30;;33093:4;33067:30;:::i;:::-;33066:47;;;;:::i;:::-;33054:59;;32986:142;33404:6;33372:12;33359:10;33330:26;33340:15;33330:9;:26::i;:::-;:39;;;;:::i;:::-;:54;;;;:::i;:::-;33329:81;;;;:::i;:::-;33301:109;;32665:756;33438:21;33450:9;33438;:21;:::i;:::-;33431:28;32396:1070;-1:-1:-1;;;;;;;;32396:1070:20:o;1313:85:21:-;1385:6;;-1:-1:-1;;;;;1385:6:21;1313:85;:::o;25567:232:20:-;25650:31;;:::i;:::-;25705:29;:10;-1:-1:-1;;;;;25705:29:20;;:19;:29::i;:::-;25697:45;;;;-1:-1:-1;;;25697:45:20;;;;;;;:::i;:::-;25759:16;;:33;;-1:-1:-1;;;25759:33:20;;-1:-1:-1;;;;;25759:16:20;;;;:23;;:33;;25783:8;;25759:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;30794:331::-;30885:7;30916:29;:10;-1:-1:-1;;;;;30916:29:20;;:19;:29::i;:::-;30908:45;;;;-1:-1:-1;;;30908:45:20;;;;;;;:::i;:::-;31026:16;;:33;;-1:-1:-1;;;31026:33:20;;30983:135;;-1:-1:-1;;;;;31026:16:20;;:23;;:33;;31050:8;;31026:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31077:27;:25;:27::i;:::-;30983:25;:135::i;748:191:22:-;-1:-1:-1;;;;;;;;;;;902:21:22;;837:96::o;4170:29:20:-;;;-1:-1:-1;;;;;4170:29:20;;:::o;4732:49::-;4777:4;4732:49;:::o;698:201:3:-;-1:-1:-1;;;698:201:3;;;;;;;:::o;4283:41:20:-;;;-1:-1:-1;;;;;4283:41:20;;:::o;36344:1845::-;36505:7;36482:12;4777:4;7482:9;:31;;7461:108;;;;-1:-1:-1;;;7461:108:20;;;;;;;:::i;:::-;36532:29:::1;:10;-1:-1:-1::0;;;;;36532:29:20;::::1;:19;:29::i;:::-;36524:45;;;;-1:-1:-1::0;;;36524:45:20::1;;;;;;;:::i;:::-;36601:16;::::0;:32:::1;::::0;-1:-1:-1;;;36601:32:20;;36653:34:::1;::::0;-1:-1:-1;;;;;36601:16:20::1;::::0;:22:::1;::::0;:32:::1;::::0;36624:8;;36601:32:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:86;;;;;;-1:-1:-1::0;;;36601:86:20::1;;;;;;;;;;36580:151;;;;-1:-1:-1::0;;;36580:151:20::1;;;;;;;:::i;:::-;36742:24;36781:46;36804:8;36814:12;36781:22;:46::i;:::-;36742:85;;36865:17;36845:16;:37;;36837:67;;;;-1:-1:-1::0;;;36837:67:20::1;;;;;;;:::i;:::-;36915:19;36937:35;36963:8;36937:25;:35::i;:::-;36915:57;;36982:19;37004:35;37030:8;37004:25;:35::i;:::-;37119:17;::::0;:164:::1;::::0;-1:-1:-1;;;37119:164:20;;36982:57;;-1:-1:-1;37092:17:20::1;::::0;-1:-1:-1;;;;;37119:17:20;;::::1;::::0;:34:::1;::::0;:164:::1;::::0;37167:10:::1;::::0;37199:4:::1;::::0;37218:11;;37243:12;;37092:17;;37119:164:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;37360:17:20::1;::::0;:55:::1;::::0;-1:-1:-1;;;37360:55:20;;37324:21:::1;::::0;-1:-1:-1;;;;;;37360:17:20;;::::1;::::0;-1:-1:-1;37360:27:20::1;::::0;:55:::1;::::0;37396:4:::1;::::0;37403:11;;37360:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37461:17;::::0;:55:::1;::::0;-1:-1:-1;;;37461:55:20;;37324:91;;-1:-1:-1;37425:21:20::1;::::0;-1:-1:-1;;;;;37461:17:20;;::::1;::::0;:27:::1;::::0;:55:::1;::::0;37497:4:::1;::::0;37504:11;;37461:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37425:91;;37526:19;37548:38;37557:13;37572;37548:8;:38::i;:::-;37814:16;::::0;:53:::1;::::0;-1:-1:-1;;;37814:53:20;;37526:60;;-1:-1:-1;;;;;;37814:16:20::1;::::0;:30:::1;::::0;:53:::1;::::0;37845:8;;37526:60;;37814:53:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;37919:15:20::1;::::0;:58:::1;::::0;-1:-1:-1;;;;;;37919:15:20::1;::::0;-1:-1:-1;37948:10:20::1;37960:16:::0;37919:28:::1;:58::i;:::-;38019:65;38031:10;38043:8;38053:12;38067:16;38019:65;;;;;;;;;:::i;4460:33::-:0;;;-1:-1:-1;;;4460:33:20;;;;;:::o;33696:2032::-;33856:7;33833:12;4777:4;7482:9;:31;;7461:108;;;;-1:-1:-1;;;7461:108:20;;;;;;;:::i;:::-;33883:29:::1;:10;-1:-1:-1::0;;;;;33883:29:20;::::1;:19;:29::i;:::-;33875:45;;;;-1:-1:-1::0;;;33875:45:20::1;;;;;;;:::i;:::-;33952:16;::::0;:32:::1;::::0;-1:-1:-1;;;33952:32:20;;34004:34:::1;::::0;-1:-1:-1;;;;;33952:16:20::1;::::0;:22:::1;::::0;:32:::1;::::0;33975:8;;33952:32:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:86;;;;;;-1:-1:-1::0;;;33952:86:20::1;;;;;;;;;;33931:151;;;;-1:-1:-1::0;;;33931:151:20::1;;;;;;;:::i;:::-;34093:24;34132:45;34154:8;34164:12;34132:21;:45::i;:::-;34093:84;;34215:17;34195:16;:37;;34187:67;;;;-1:-1:-1::0;;;34187:67:20::1;;;;;;;:::i;:::-;34311:15;::::0;:123:::1;::::0;-1:-1:-1;;;;;34311:15:20::1;34357:10;34389:4;34408:16:::0;34311:32:::1;:123::i;:::-;34488:19;34510:35;34536:8;34510:25;:35::i;:::-;34591:17;::::0;:55:::1;::::0;-1:-1:-1;;;34591:55:20;;34488:57;;-1:-1:-1;34555:21:20::1;::::0;-1:-1:-1;;;;;34591:17:20;;::::1;::::0;:27:::1;::::0;:55:::1;::::0;34627:4:::1;::::0;34488:57;;34591:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34555:91;;34676:12;34660:13;:28;34656:571;;;34827:16;::::0;:126:::1;::::0;-1:-1:-1;;;34827:126:20;;34778:30:::1;::::0;-1:-1:-1;;;;;34827:16:20::1;::::0;:44:::1;::::0;:126:::1;::::0;34893:8;;34923:12;;34827:126:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34968:15;::::0;35017:16:::1;::::0;34968:120:::1;::::0;-1:-1:-1;;;34968:120:20;;34778:175;;-1:-1:-1;;;;;;34968:15:20;;::::1;::::0;:23:::1;::::0;:120:::1;::::0;35017:16:::1;::::0;34778:175;;34968:120:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;35102:16:20::1;::::0;-1:-1:-1;;;;;35102:16:20::1;:28;35148:8:::0;35174:28:::1;35189:13:::0;35174:12;:28:::1;:::i;:::-;35102:114;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;34656:571;;35297:17;::::0;:164:::1;::::0;-1:-1:-1;;;35297:164:20;;35270:17:::1;::::0;-1:-1:-1;;;;;35297:17:20::1;::::0;:34:::1;::::0;:164:::1;::::0;35353:4:::1;::::0;35372:10:::1;::::0;35396:11;;35421:12;;35270:17;;35297:164:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;35503:125;35530:10;35554:8;35576:12;35602:16;35503:125;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;35705:16:20;;33696:2032;-1:-1:-1;;;;;;;33696:2032:20:o;46824:2475::-;46928:7;46955:18;46951:32;;-1:-1:-1;46982:1:20;46975:8;;46951:32;47036:7;;47018:41;;;-1:-1:-1;;;47018:41:20;;;;46994:21;;-1:-1:-1;;;;;47036:7:20;;47018:39;;:41;;;;;;;;;;;;;;47036:7;47018:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46994:65;-1:-1:-1;47073:18:20;47069:32;;47100:1;47093:8;;;;;47069:32;47212:36;47263:44;:42;:44::i;:::-;47480:15;;:40;;-1:-1:-1;;;47480:40:20;;47212:95;;-1:-1:-1;47395:23:20;;-1:-1:-1;;;;;47480:15:20;;;;:25;;:40;;47514:4;;47480:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47433:87;;:28;:87;:::i;:::-;47395:125;-1:-1:-1;47690:13:20;47644:29;47660:13;47690;47644:29;:::i;:::-;47625:49;;:15;:49;:::i;:::-;47624:79;;;;:::i;:::-;47594:109;-1:-1:-1;47594:109:20;47798:22;47848:1395;47872:19;:10;:17;:19::i;:::-;47868:1;:23;47848:1395;;;47912:15;47937:16;:10;47951:1;47937:13;:16::i;:::-;47912:42;-1:-1:-1;48042:34:20;47990:16;;:32;;-1:-1:-1;;;47990:32:20;;-1:-1:-1;;;;;47990:16:20;;;;:22;;:32;;48013:8;;47990:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:86;;;;;;-1:-1:-1;;;47990:86:20;;;;;;;;;;47969:1264;;;48153:17;;48109:20;;48322:13;;48305;;-1:-1:-1;;;;;48153:17:20;:27;48214:4;48245:35;48271:8;48245:25;:35::i;:::-;48153:149;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:165;;;;:::i;:::-;48152:183;;;;:::i;:::-;48397:17;;48109:226;;-1:-1:-1;48353:20:20;;48566:13;;48549;;-1:-1:-1;;;;;48397:17:20;:27;48458:4;48489:35;48515:8;48489:25;:35::i;:::-;48397:149;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:165;;;;:::i;:::-;48396:183;;;;:::i;:::-;48353:226;;48598:25;48646:199;48707:8;48741:12;48779:14;48819:4;48646:35;:199::i;:::-;48598:247;-1:-1:-1;48863:35:20;48598:247;48863:35;;:::i;:::-;;;48917:25;48965:200;49026:8;49060:12;49098:14;49138:5;48965:35;:200::i;:::-;48917:248;-1:-1:-1;49183:35:20;48917:248;49183:35;;:::i;:::-;;;47969:1264;;;;;-1:-1:-1;47893:3:20;;;;:::i;:::-;;;;47848:1395;;;-1:-1:-1;49260:32:20;49278:14;49260:15;:32;:::i;:::-;49253:39;46824:2475;-1:-1:-1;;;;;;46824:2475:20:o;519:173:3:-;-1:-1:-1;;;519:173:3;;;;;;;:::o;2239:240:21:-;1536:12;:10;:12::i;:::-;-1:-1:-1;;;;;1525:23:21;:7;:5;:7::i;:::-;-1:-1:-1;;;;;1525:23:21;;1517:68;;;;-1:-1:-1;;;1517:68:21;;;;;;;:::i;:::-;-1:-1:-1;;;;;2327:22:21;::::1;2319:73;;;;-1:-1:-1::0;;;2319:73:21::1;;;;;;;:::i;:::-;2428:6;::::0;2407:38:::1;::::0;-1:-1:-1;;;;;2407:38:21;;::::1;::::0;2428:6:::1;::::0;-1:-1:-1;;;;;;;;;;;2407:38:21;2428:6:::1;::::0;2407:38:::1;2455:6;:17:::0;;-1:-1:-1;;;;;;2455:17:21::1;-1:-1:-1::0;;;;;2455:17:21;;;::::1;::::0;;;::::1;::::0;;2239:240::o;10238:315:20:-;1536:12:21;:10;:12::i;:::-;-1:-1:-1;;;;;1525:23:21;:7;:5;:7::i;:::-;-1:-1:-1;;;;;1525:23:21;;1517:68;;;;-1:-1:-1;;;1517:68:21;;;;;;;:::i;:::-;10428:6:20::1;10408:17;:26;10400:42;;;;-1:-1:-1::0;;;10400:42:20::1;;;;;;;:::i;:::-;10453:16;:36:::0;;;10504:42:::1;::::0;::::1;::::0;::::1;::::0;10472:17;;10504:42:::1;:::i;:::-;;;;;;;;10238:315:::0;:::o;21776:2717::-;21871:7;22347:23;22373:27;:25;:27::i;:::-;22347:53;;22474:25;22513:26;22558:9;22553:1747;22577:19;:10;:17;:19::i;:::-;22573:1;:23;22553:1747;;;22617:15;22642:16;:10;22656:1;22642:13;:16::i;:::-;22730;;:33;;-1:-1:-1;;;22730:33:20;;22617:42;;-1:-1:-1;22673:38:20;;-1:-1:-1;;;;;22730:16:20;;;;:23;;:33;;22617:42;;22730:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22673:90;;22778:19;22800:35;22826:8;22800:25;:35::i;:::-;22778:57;;22849:19;22871:35;22897:8;22871:25;:35::i;:::-;22961:17;;:55;;-1:-1:-1;;;22961:55:20;;22849:57;;-1:-1:-1;22921:21:20;;-1:-1:-1;;;;;22961:17:20;;;;:27;;:55;;22997:4;;23004:11;;22961:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23070:17;;:55;;-1:-1:-1;;;23070:55:20;;22921:95;;-1:-1:-1;23030:21:20;;-1:-1:-1;;;;;23070:17:20;;;;:27;;:55;;23106:4;;23113:11;;23070:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23030:95;-1:-1:-1;23213:34:20;23161:16;;:32;;-1:-1:-1;;;23161:32:20;;-1:-1:-1;;;;;23161:16:20;;;;:22;;:32;;23184:8;;23161:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:86;;;;;;-1:-1:-1;;;23161:86:20;;;;;;;;;;23140:1150;;;23354:14;23391:50;23417:6;23425:15;23391:25;:50::i;:::-;23354:87;-1:-1:-1;23498:14:20;23515:22;23354:87;23523:4;23515:22;:::i;:::-;23608:16;;23498:39;;-1:-1:-1;23556:29:20;;-1:-1:-1;;;;;23608:16:20;:44;23678:8;23764:4;23738:22;23498:39;23738:13;:22;:::i;:::-;23713;23729:6;23713:13;:22;:::i;:::-;:47;;;;:::i;:::-;23712:56;;;;:::i;:::-;23608:182;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23556:234;-1:-1:-1;23809:42:20;23556:234;23809:42;;:::i;:::-;;;23140:1150;;;;;;23893:16;:125;;;;-1:-1:-1;23929:16:20;;:32;;-1:-1:-1;;;23929:32:20;;23981:37;;-1:-1:-1;;;;;23929:16:20;;:22;;:32;;23952:8;;23929:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;;;;-1:-1:-1;;;23929:89:20;;;;;;;;;;23893:125;23872:418;;;24134:141;24179:8;24209:13;24244;24134:23;:141::i;:::-;24112:163;;;;:::i;:::-;;;23872:418;22553:1747;;;;;;22598:3;;;;;:::i;:::-;;;;22553:1747;;;-1:-1:-1;24370:15:20;;:40;;-1:-1:-1;;;24370:40:20;;24342:25;;-1:-1:-1;;;;;24370:15:20;;:25;;:40;;24404:4;;24370:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;24342:68;-1:-1:-1;24342:68:20;24428:38;24448:18;24428:17;:38;:::i;:::-;:58;;;;:::i;608:266:4:-;732:4;-1:-1:-1;;;;;;755:60:4;;-1:-1:-1;;;755:60:4;;:112;;;831:36;855:11;831:23;:36::i;208:114:25:-;270:7;297:13;:9;309:1;297:13;:::i;:::-;296:19;;314:1;296:19;:::i;:::-;-1:-1:-1;;;;;289:26:25;;208:114;-1:-1:-1;;208:114:25:o;94:108::-;156:7;182:13;:9;194:1;182:13;:::i;8687:155:6:-;8773:4;8800:35;8808:3;8828:5;8800:7;:35::i;809:96:2:-;888:10;809:96;:::o;386:356:22:-;511:10;-1:-1:-1;;;;;501:35:22;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;474:64:22;453:125;;;;-1:-1:-1;;;453:125:22;;;;;;;:::i;:::-;669:10;-1:-1:-1;;;;;;;;;;;646:34:22;705:30;724:10;705:30;;;;;;:::i;247:301:19:-;295:9;324:1;320;:5;316:226;;;-1:-1:-1;345:1:19;360:9;372:5;376:1;345;372:5;:::i;:::-;:9;;380:1;372:9;:::i;:::-;360:21;;395:89;406:1;402;:5;395:89;;;431:1;-1:-1:-1;431:1:19;468;431;455:5;431:1;455;:5;:::i;:::-;:9;;;;:::i;:::-;454:15;;;;:::i;:::-;450:19;;395:89;;;316:226;;;;504:6;;500:42;;-1:-1:-1;530:1:19;247:301;;;:::o;9176:112:6:-;9236:7;9262:19;9270:3;9262:7;:19::i;8390:129::-;8457:4;8480:32;8485:3;8505:5;8480:4;:32::i;44113:1030:20:-;44310:7;44366:22;44362:36;;-1:-1:-1;44397:1:20;44390:8;;44362:36;44429:16;;:107;;-1:-1:-1;;;44429:107:20;;-1:-1:-1;;;;;44429:16:20;;;;:44;;:107;;44487:8;;44509:17;;44429:107;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;44409:127;;44548:21;44571;44608:61;44635:8;44645:23;44608:26;:61::i;:::-;44547:122;;;;44680:21;44715:8;44711:128;;;-1:-1:-1;44755:13:20;44711:128;;;-1:-1:-1;44815:13:20;44711:128;44848:16;44903:13;44867:33;44887:13;44867:17;:33;:::i;:::-;:49;;;;:::i;:::-;44848:68;-1:-1:-1;44926:24:20;45101:1;44993:104;45065:13;45041:21;45045:17;45041:1;:21;:::i;:::-;:37;;;;:::i;:::-;45025:11;45035:1;45025:8;:11;:::i;:::-;45024:55;;;;:::i;44993:104::-;44966:131;;:8;:131;:::i;:::-;44965:137;;;;:::i;:::-;44926:176;-1:-1:-1;;;;;;44113:1030:20;;;;;;;:::o;18032:3577::-;18238:7;;18257:3314;18281:19;:10;:17;:19::i;:::-;18277:1;:23;18257:3314;;;18321:15;18346:16;:10;18360:1;18346:13;:16::i;:::-;18321:42;-1:-1:-1;18450:34:20;18398:16;;:32;;-1:-1:-1;;;18398:32:20;;-1:-1:-1;;;;;18398:16:20;;;;:22;;:32;;18421:8;;18398:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:86;;;;;;-1:-1:-1;;;18398:86:20;;;;;;;;;;18377:3184;;;18517:19;18539:35;18565:8;18539:25;:35::i;:::-;18517:57;;18592:19;18614:35;18640:8;18614:25;:35::i;:::-;18712:17;;:55;;-1:-1:-1;;;18712:55:20;;18592:57;;-1:-1:-1;18668:20:20;;18811:13;;18794;;-1:-1:-1;;;;;18712:17:20;;;;:27;;:55;;18748:4;;18755:11;;18712:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:95;;;;:::i;:::-;18711:113;;;;:::i;:::-;18886:17;;:55;;-1:-1:-1;;;18886:55:20;;18668:156;;-1:-1:-1;18842:20:20;;18985:13;;18968;;-1:-1:-1;;;;;18886:17:20;;;;:27;;:55;;18922:4;;18929:11;;18886:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:95;;;;:::i;:::-;18885:113;;;;:::i;:::-;18842:156;;19021:10;19020:11;:45;;;;19052:13;19035;:30;19020:45;19016:2531;;;19220:16;;19216:372;;19307:17;;:258;;-1:-1:-1;;;19307:258:20;;19264:17;;-1:-1:-1;;;;;19307:17:20;;:34;;:258;;19379:4;;19414:8;;19452:11;;19493:12;;19264:17;;19307:258;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19216:372;;19613:16;;19609:372;;19700:17;;:258;;-1:-1:-1;;;19700:258:20;;19657:17;;-1:-1:-1;;;;;19700:17:20;;:34;;:258;;19772:4;;19807:8;;19845:11;;19886:12;;19657:17;;19700:258;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19609:372;;19016:2531;;;20408:25;20460:219;20525:8;20563:12;20605:14;20649:4;20460:35;:219::i;:::-;20408:271;-1:-1:-1;21142:35:20;20408:271;21142:35;;:::i;:::-;;;21199:25;21251:220;21316:8;21354:12;21396:14;21440:5;21251:35;:220::i;:::-;21199:272;-1:-1:-1;21493:35:20;21199:272;21493:35;;:::i;:::-;;;19016:2531;;;18377:3184;;;;;-1:-1:-1;18302:3:20;;;;:::i;:::-;;;;18257:3314;;;-1:-1:-1;21588:14:20;;18032:3577;-1:-1:-1;;;;;18032:3577:20:o;620:175:24:-;702:86;722:5;752:23;;;777:2;781:5;729:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;729:58:24;;;;;;;;;;;;;;-1:-1:-1;;;;;729:58:24;-1:-1:-1;;;;;;729:58:24;;;;;;;;;;702:19;:86::i;:::-;620:175;;;:::o;801:203::-;901:96;921:5;951:27;;;980:4;986:2;990:5;928:68;;;;;;;;;;:::i;901:96::-;801:203;;;;:::o;8923:172:6:-;9024:4;9051:37;9061:3;9081:5;9051:9;:37::i;554:121:19:-;612:7;639:1;635;:5;631:19;;;-1:-1:-1;649:1:19;642:8;;631:19;-1:-1:-1;667:1:19;554:121;-1:-1:-1;554:121:19:o;26405:3004:20:-;26535:7;26544;26563:19;26585:35;26611:8;26585:25;:35::i;:::-;26563:57;;26630:19;26652:35;26678:8;26652:25;:35::i;:::-;26767:17;;:55;;-1:-1:-1;;;26767:55:20;;26630:57;;-1:-1:-1;26731:21:20;;-1:-1:-1;;;;;26767:17:20;;;;:27;;:55;;26803:4;;26810:11;;26767:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26868:17;;:55;;-1:-1:-1;;;26868:55:20;;26731:91;;-1:-1:-1;26832:21:20;;-1:-1:-1;;;;;26868:17:20;;;;:27;;:55;;26904:4;;26911:11;;26868:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26987:16;;:33;;-1:-1:-1;;;26987:33:20;;26832:91;;-1:-1:-1;26934:38:20;;-1:-1:-1;;;;;26987:16:20;;;;:23;;:33;;27011:8;;26987:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26934:86;;27108:6;:18;;;27104:325;;;27158:16;;:115;;-1:-1:-1;;;27158:115:20;;-1:-1:-1;;;;;27158:16:20;;;;:44;;:115;;27220:8;;27246:13;;27158:115;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;27303:16;;:115;;-1:-1:-1;;;27303:115:20;;27142:131;;-1:-1:-1;;;;;;27303:16:20;;:44;;:115;;27365:8;;27391:13;;27303:115;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;27287:131;;27104:325;27548:24;27575:38;27591:22;27575:13;:38;:::i;:::-;27548:65;-1:-1:-1;27623:24:20;27650:38;27666:22;27650:13;:38;:::i;:::-;27623:65;;27699:19;27733:62;27759:6;27767:27;:25;:27::i;27733:62::-;27699:96;-1:-1:-1;27805:19:20;27827:27;27699:96;27835:4;27827:27;:::i;:::-;27805:49;;28011:28;28049;28107:11;28092;:26;28088:1253;;28191:16;;-1:-1:-1;28315:11:20;28261:34;28284:11;28191:16;28261:34;:::i;:::-;28260:66;;;;:::i;:::-;28221:105;;28596:16;28573:20;:39;28569:248;;;-1:-1:-1;28655:16:20;28791:11;28733:34;28756:11;28655:16;28733:34;:::i;:::-;28732:70;;;;:::i;:::-;28689:113;;28569:248;28088:1253;;;-1:-1:-1;28905:16:20;29029:11;28975:34;28998:11;28905:16;28975:34;:::i;:::-;28974:66;;;;:::i;:::-;28935:105;;29110:16;29087:20;:39;29083:248;;;29169:16;;-1:-1:-1;29305:11:20;29247:34;29270:11;29169:16;29247:34;:::i;:::-;29246:70;;;;:::i;:::-;29203:113;;29083:248;29359:20;;;;-1:-1:-1;26405:3004:20;-1:-1:-1;;;;;;;;;;;;26405:3004:20:o;9630:163:6:-;9725:7;9763:22;9767:3;9779:5;9763:3;:22::i;49728:691:20:-;49876:7;;49941:17;;49937:211;;50024:16;;:56;;-1:-1:-1;;;50024:56:20;;49975:27;;-1:-1:-1;;;;;50024:16:20;;:31;;:56;;50056:8;;50066:13;;50024:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;49974:106:20;-1:-1:-1;50094:43:20;49974:106;50094:43;;:::i;:::-;;;49937:211;;50161:17;;50157:218;;50246:16;;:59;;-1:-1:-1;;;50246:59:20;;50195:29;;-1:-1:-1;;;;;50246:16:20;;:34;;:59;;50281:8;;50291:13;;50246:59;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;50194:111:20;-1:-1:-1;50319:45:20;50194:111;50319:45;;:::i;913:126:21:-;1496:13:17;;;;;;;;:30;;-1:-1:-1;1514:12:17;;;;1513:13;1496:30;1488:89;;;;-1:-1:-1;;;1488:89:17;;;;;;;:::i;:::-;1588:19;1611:13;;;;;;1610:14;1634:98;;;;1668:13;:20;;-1:-1:-1;;;;1668:20:17;;;;;1702:19;1684:4;1702:19;;;1634:98;970:26:21::1;:24;:26::i;:::-;1006;:24;:26::i;:::-;1758:14:17::0;1754:66;;;1804:5;1788:21;;-1:-1:-1;;1788:21:17;;;913:126:21;:::o;29692:243:20:-;29802:16;;29861:15;;29903:10;;29789:139;;-1:-1:-1;;;29789:139:20;;29751:7;;-1:-1:-1;;;;;29802:16:20;;;;;;;29789:46;;:139;;29861:15;;;;29903:10;;29789:139;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29770:158;;29692:243;:::o;31131:883::-;31275:7;31788:219;31839:15;31815:6;:21;;;:39;;;;;;:::i;:::-;31872:6;:18;;;31908:15;31941:16;;31975:6;:18;;;31788:9;:219::i;1003:166:5:-;-1:-1:-1;;;;;;1111:51:5;;-1:-1:-1;;;1111:51:5;1003:166;;;:::o;2202:1533:6:-;2268:4;2405:19;;;:12;;;:19;;;;;;2439:15;;2435:1294;;2808:21;2832:14;2845:1;2832:10;:14;:::i;:::-;2880:18;;2808:38;;-1:-1:-1;2860:17:6;;2880:22;;2901:1;;2880:22;:::i;:::-;2860:42;;3142:17;3162:3;:11;;3174:9;3162:22;;;;;;-1:-1:-1;;;3162:22:6;;;;;;;;;;;;;;;;;3142:42;;3305:9;3276:3;:11;;3288:13;3276:26;;;;;;-1:-1:-1;;;3276:26:6;;;;;;;;;;;;;;;;;;;;:38;;;;3380:23;;;:12;;;:23;;;;;;:36;;;3538:17;;3380:3;;3538:17;;;-1:-1:-1;;;3538:17:6;;;;;;;;;;;;;;;;;;;;;;;;;;3630:3;:12;;:19;3643:5;3630:19;;;;;;;;;;;3623:26;;;3671:4;3664:11;;;;;;;;2435:1294;3713:5;3706:12;;;;;4052:107;4134:18;;4052:107::o;1630:404::-;1693:4;1714:21;1724:3;1729:5;1714:9;:21::i;:::-;1709:319;;-1:-1:-1;1751:23:6;;;;;;;;:11;:23;;;;;;;;;;;;;1931:18;;1909:19;;;:12;;;:19;;;;;;:40;;;;1963:11;;1709:319;-1:-1:-1;2012:5:6;2005:12;;3008:751:24;3427:23;3453:69;3481:4;3453:69;;;;;;;;;;;;;;;;;3461:5;-1:-1:-1;;;;;3453:27:24;;;:69;;;;;:::i;:::-;3536:17;;3427:95;;-1:-1:-1;3536:21:24;3532:221;;3676:10;3665:30;;;;;;;;;;;;:::i;:::-;3657:85;;;;-1:-1:-1;;;3657:85:24;;;;;;;:::i;3816:155:6:-;3913:4;3940:19;;;:12;;;;;:19;;;;;;:24;;;3816:155::o;4501:263::-;4636:18;;4592:7;;4636:26;-1:-1:-1;4615:107:6;;;;-1:-1:-1;;;4615:107:6;;;;;;;:::i;:::-;4739:3;:11;;4751:5;4739:18;;;;;;-1:-1:-1;;;4739:18:6;;;;;;;;;;;;;;;;;4732:25;;4501:263;;;;:::o;740:64:2:-;1496:13:17;;;;;;;;:30;;-1:-1:-1;1514:12:17;;;;1513:13;1496:30;1488:89;;;;-1:-1:-1;;;1488:89:17;;;;;;;:::i;:::-;1588:19;1611:13;;;;;;1610:14;1634:98;;;;1668:13;:20;;-1:-1:-1;;;;1668:20:17;;;;;1702:19;1684:4;1702:19;;;1758:14;1754:66;;;1804:5;1788:21;;-1:-1:-1;;1788:21:17;;;740:64:2;:::o;1045:192:21:-;1496:13:17;;;;;;;;:30;;-1:-1:-1;1514:12:17;;;;1513:13;1496:30;1488:89;;;;-1:-1:-1;;;1488:89:17;;;;;;;:::i;:::-;1588:19;1611:13;;;;;;1610:14;1634:98;;;;1668:13;:20;;-1:-1:-1;;;;1668:20:17;;;;;1702:19;1684:4;1702:19;;;1634:98;1112:17:21::1;1132:12;:10;:12::i;:::-;1154:6;:18:::0;;-1:-1:-1;;;;;;1154:18:21::1;-1:-1:-1::0;;;;;1154:18:21;::::1;::::0;;::::1;::::0;;;1187:43:::1;::::0;1154:18;;-1:-1:-1;1154:18:21;-1:-1:-1;;;;;;;;;;;;;1187:43:21;-1:-1:-1;;1187:43:21::1;1742:1:17;1758:14:::0;1754:66;;;1804:5;1788:21;;-1:-1:-1;;1788:21:17;;;1045:192:21;:::o;3573:193:0:-;3676:12;3707:52;3729:6;3737:4;3743:1;3746:12;3676;4850:18;4861:6;4850:10;:18::i;:::-;4842:60;;;;-1:-1:-1;;;4842:60:0;;;;;;;:::i;:::-;4973:12;4987:23;5014:6;-1:-1:-1;;;;;5014:11:0;5034:5;5042:4;5014:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4972:75;;;;5064:52;5082:7;5091:10;5103:12;5064:17;:52::i;:::-;5057:59;4600:523;-1:-1:-1;;;;;;;4600:523:0:o;718:413::-;1078:20;1116:8;;;718:413::o;7083:725::-;7198:12;7226:7;7222:580;;;-1:-1:-1;7256:10:0;7249:17;;7222:580;7367:17;;:21;7363:429;;7625:10;7619:17;7685:15;7672:10;7668:2;7664:19;7657:44;7574:145;7764:12;7757:20;;-1:-1:-1;;;7757:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:749:26:-;;127:3;120:4;112:6;108:17;104:27;94:2;;149:5;142;135:20;94:2;176:20;;215:4;-1:-1:-1;;;;;231:26:26;;228:2;;;260:18;;:::i;:::-;307:2;303;299:11;330:27;353:2;349;345:11;330:27;:::i;:::-;391:15;;;422:12;;;;454:15;;;488;;;484:24;;481:33;-1:-1:-1;478:2:26;;;531:5;524;517:20;478:2;557:5;548:14;;571:163;585:2;582:1;579:9;571:163;;;642:17;;630:30;;603:1;596:9;;;;;680:12;;;;712;;571:163;;;-1:-1:-1;752:5:26;84:679;-1:-1:-1;;;;;;;84:679:26:o;768:485::-;;865:3;858:4;850:6;846:17;842:27;832:2;;887:5;880;873:20;832:2;927:6;914:20;958:49;973:33;1003:2;973:33;:::i;:::-;958:49;:::i;:::-;1032:2;1023:7;1016:19;1078:3;1071:4;1066:2;1058:6;1054:15;1050:26;1047:35;1044:2;;;1099:5;1092;1085:20;1044:2;1168;1161:4;1153:6;1149:17;1142:4;1133:7;1129:18;1116:55;1191:16;;;1209:4;1187:27;1180:42;;;;1195:7;822:431;-1:-1:-1;;822:431:26:o;1258:173::-;1327:20;;-1:-1:-1;;;;;1376:30:26;;1366:41;;1356:2;;1421:1;1418;1411:12;1436:259;;1548:2;1536:9;1527:7;1523:23;1519:32;1516:2;;;1569:6;1561;1554:22;1516:2;1613:9;1600:23;1632:33;1659:5;1632:33;:::i;1700:263::-;;1823:2;1811:9;1802:7;1798:23;1794:32;1791:2;;;1844:6;1836;1829:22;1791:2;1881:9;1875:16;1900:33;1927:5;1900:33;:::i;1968:1129::-;;;;;;2207:3;2195:9;2186:7;2182:23;2178:33;2175:2;;;2229:6;2221;2214:22;2175:2;2273:9;2260:23;2292:33;2319:5;2292:33;:::i;:::-;2344:5;-1:-1:-1;2401:2:26;2386:18;;2373:32;2414:35;2373:32;2414:35;:::i;:::-;2468:7;-1:-1:-1;2526:2:26;2511:18;;2498:32;-1:-1:-1;;;;;2579:14:26;;;2576:2;;;2611:6;2603;2596:22;2576:2;2639:67;2698:7;2689:6;2678:9;2674:22;2639:67;:::i;:::-;2629:77;;2759:2;2748:9;2744:18;2731:32;2715:48;;2788:2;2778:8;2775:16;2772:2;;;2809:6;2801;2794:22;2772:2;2837:69;2898:7;2887:8;2876:9;2872:24;2837:69;:::i;:::-;2827:79;;2959:3;2948:9;2944:19;2931:33;2915:49;;2989:2;2979:8;2976:16;2973:2;;;3010:6;3002;2995:22;2973:2;;3038:53;3083:7;3072:8;3061:9;3057:24;3038:53;:::i;:::-;3028:63;;;2165:932;;;;;;;;:::o;3102:760::-;;;;;;3291:3;3279:9;3270:7;3266:23;3262:33;3259:2;;;3313:6;3305;3298:22;3259:2;3357:9;3344:23;3376:33;3403:5;3376:33;:::i;:::-;3428:5;-1:-1:-1;3485:2:26;3470:18;;3457:32;3498:35;3457:32;3498:35;:::i;:::-;3552:7;-1:-1:-1;3606:2:26;3591:18;;3578:32;;-1:-1:-1;3657:2:26;3642:18;;3629:32;;-1:-1:-1;3712:3:26;3697:19;;3684:33;-1:-1:-1;;;;;3729:30:26;;3726:2;;;3777:6;3769;3762:22;3726:2;3805:51;3848:7;3839:6;3828:9;3824:22;3805:51;:::i;3867:253::-;;3976:2;3964:9;3955:7;3951:23;3947:32;3944:2;;;3997:6;3989;3982:22;3944:2;4041:9;4028:23;4060:30;4084:5;4060:30;:::i;4125:257::-;;4245:2;4233:9;4224:7;4220:23;4216:32;4213:2;;;4266:6;4258;4251:22;4213:2;4303:9;4297:16;4322:30;4346:5;4322:30;:::i;4387:194::-;;4510:2;4498:9;4489:7;4485:23;4481:32;4478:2;;;4531:6;4523;4516:22;4478:2;-1:-1:-1;4559:16:26;;4468:113;-1:-1:-1;4468:113:26:o;4586:306::-;;4697:2;4685:9;4676:7;4672:23;4668:32;4665:2;;;4718:6;4710;4703:22;4665:2;4749:23;;-1:-1:-1;;;;;;4801:32:26;;4791:43;;4781:2;;4853:6;4845;4838:22;4897:1227;;;;;;;;5181:3;5169:9;5160:7;5156:23;5152:33;5149:2;;;5203:6;5195;5188:22;5149:2;5247:9;5234:23;5266:33;5293:5;5266:33;:::i;:::-;5318:5;-1:-1:-1;5375:2:26;5360:18;;5347:32;5388:35;5347:32;5388:35;:::i;:::-;5442:7;-1:-1:-1;5501:2:26;5486:18;;5473:32;5514:35;5473:32;5514:35;:::i;:::-;5568:7;-1:-1:-1;5627:2:26;5612:18;;5599:32;5640:35;5599:32;5640:35;:::i;:::-;5694:7;-1:-1:-1;5753:3:26;5738:19;;5725:33;5767:35;5725:33;5767:35;:::i;:::-;5821:7;-1:-1:-1;5880:3:26;5865:19;;5852:33;5894:35;5852:33;5894:35;:::i;:::-;5948:7;-1:-1:-1;6007:3:26;5992:19;;5979:33;6056:6;6043:20;;6031:33;;6021:2;;6083:6;6075;6068:22;6021:2;6111:7;6101:17;;;5139:985;;;;;;;;;;:::o;6129:296::-;;6268:2;6256:9;6247:7;6243:23;6239:32;6236:2;;;6289:6;6281;6274:22;6236:2;6326:9;6320:16;6365:1;6358:5;6355:12;6345:2;;6386:6;6378;6371:22;6430:676;;6563:2;6551:9;6542:7;6538:23;6534:32;6531:2;;;6584:6;6576;6569:22;6531:2;6616:16;;-1:-1:-1;;;;;6644:30:26;;6641:2;;;6692:6;6684;6677:22;6641:2;6720:22;;6773:4;6765:13;;6761:27;-1:-1:-1;6751:2:26;;6807:6;6799;6792:22;6751:2;6841;6835:9;6866:49;6881:33;6911:2;6881:33;:::i;6866:49::-;6938:2;6931:5;6924:17;6978:7;6973:2;6968;6964;6960:11;6956:20;6953:33;6950:2;;;7004:6;6996;6989:22;6950:2;7022:54;7073:2;7068;7061:5;7057:14;7052:2;7048;7044:11;7022:54;:::i;:::-;7095:5;6521:585;-1:-1:-1;;;;;6521:585:26:o;7111:1532::-;;7249:9;7240:7;7236:23;7279:3;7275:2;7271:12;7268:2;;;7301:6;7293;7286:22;7268:2;7329;7354:9;;7402:4;7390:17;;-1:-1:-1;;;;;7459:18:26;;;7479:22;;;7456:46;7453:2;;;7505:18;;:::i;:::-;7534:22;;;7578:16;;;7634:12;7623:24;;7613:35;;7603:2;;7667:6;7659;7652:22;7603:2;7685:21;;;7751:2;7736:18;;7730:25;;7764:32;7730:25;7764:32;:::i;:::-;7829:7;7824:2;7816:6;7812:15;7805:32;7871:4;7865:2;7861:7;7857:2;7853:16;7849:27;7846:2;;;7894:6;7886;7879:22;7846:2;7934;7928:9;7912:25;;7980:4;7970:8;7966:19;7946:39;;8039:8;8025:12;8022:26;8017:2;8003:12;8000:20;7997:52;7994:2;;;8052:18;;:::i;:::-;-1:-1:-1;8081:24:26;;8135:18;;;8129:25;8163:35;8129:25;8163:35;:::i;:::-;8207:25;;8277:4;8262:20;;8256:27;8292:35;8256:27;8292:35;:::i;:::-;8357:2;8343:17;;8336:34;8415:4;8400:20;;8394:27;8430:35;8394:27;8430:35;:::i;:::-;8481:17;;;8474:34;8524:15;;;8517:33;;;;8606:3;8591:19;;;;8585:26;8578:4;8566:17;;8559:53;-1:-1:-1;8528:6:26;7216:1427;-1:-1:-1;7216:1427:26:o;8648:190::-;;8760:2;8748:9;8739:7;8735:23;8731:32;8728:2;;;8781:6;8773;8766:22;8728:2;-1:-1:-1;8809:23:26;;8718:120;-1:-1:-1;8718:120:26:o;9042:389::-;;;;9185:2;9173:9;9164:7;9160:23;9156:32;9153:2;;;9206:6;9198;9191:22;9153:2;9247:9;9234:23;9224:33;;9307:2;9296:9;9292:18;9279:32;9320:30;9344:5;9320:30;:::i;:::-;9143:288;;9369:5;;-1:-1:-1;;;9421:2:26;9406:18;;;;9393:32;;9143:288::o;9436:258::-;;;9565:2;9553:9;9544:7;9540:23;9536:32;9533:2;;;9586:6;9578;9571:22;9533:2;-1:-1:-1;;9614:23:26;;;9684:2;9669:18;;;9656:32;;-1:-1:-1;9523:171:26:o;9699:255::-;;;9839:2;9827:9;9818:7;9814:23;9810:32;9807:2;;;9860:6;9852;9845:22;9807:2;-1:-1:-1;;9888:16:26;;9944:2;9929:18;;;9923:25;9888:16;;9923:25;;-1:-1:-1;9797:157:26:o;9959:527::-;;;;;;10136:3;10124:9;10115:7;10111:23;10107:33;10104:2;;;10158:6;10150;10143:22;10104:2;10199:9;10186:23;10176:33;;10256:2;10245:9;10241:18;10228:32;10218:42;;10307:2;10296:9;10292:18;10279:32;10269:42;;10358:2;10347:9;10343:18;10330:32;10320:42;;10412:3;10401:9;10397:19;10384:33;10426:30;10450:5;10426:30;:::i;:::-;10475:5;10465:15;;;10094:392;;;;;;;;:::o;10491:196::-;;10602:2;10590:9;10581:7;10577:23;10573:32;10570:2;;;10623:6;10615;10608:22;10570:2;10651:30;10671:9;10651:30;:::i;10692:264::-;;;10820:2;10808:9;10799:7;10795:23;10791:32;10788:2;;;10841:6;10833;10826:22;10788:2;10869:30;10889:9;10869:30;:::i;:::-;10859:40;10946:2;10931:18;;;;10918:32;;-1:-1:-1;;;10778:178:26:o;10961:332::-;;;;11106:2;11094:9;11085:7;11081:23;11077:32;11074:2;;;11127:6;11119;11112:22;11074:2;11155:30;11175:9;11155:30;:::i;:::-;11145:40;11232:2;11217:18;;11204:32;;-1:-1:-1;11283:2:26;11268:18;;;11255:32;;11064:229;-1:-1:-1;;;11064:229:26:o;11298:293::-;;11419:2;11407:9;11398:7;11394:23;11390:32;11387:2;;;11440:6;11432;11425:22;11387:2;11477:9;11471:16;11527:4;11520:5;11516:16;11509:5;11506:27;11496:2;;11552:6;11544;11537:22;11596:259;;11677:5;11671:12;11704:6;11699:3;11692:19;11720:63;11776:6;11769:4;11764:3;11760:14;11753:4;11746:5;11742:16;11720:63;:::i;:::-;11837:2;11816:15;-1:-1:-1;;11812:29:26;11803:39;;;;11844:4;11799:50;;11647:208;-1:-1:-1;;11647:208:26:o;11860:274::-;;12027:6;12021:13;12043:53;12089:6;12084:3;12077:4;12069:6;12065:17;12043:53;:::i;:::-;12112:16;;;;;11997:137;-1:-1:-1;;11997:137:26:o;12139:960::-;;12606:6;12600:13;12622:53;12668:6;12663:3;12656:4;12648:6;12644:17;12622:53;:::i;:::-;12706:6;12701:3;12697:16;12684:29;;-1:-1:-1;;;12758:2:26;12751:5;12744:17;12792:6;12786:13;12808:65;12864:8;12860:1;12853:5;12849:13;12842:4;12834:6;12830:17;12808:65;:::i;:::-;12936:1;12892:20;;12928:10;;;12921:22;12968:13;;12990:62;12968:13;13039:1;13031:10;;13024:4;13012:17;;12990:62;:::i;:::-;13072:17;13091:1;13068:25;;12576:523;-1:-1:-1;;;;;12576:523:26:o;13104:420::-;;-1:-1:-1;;;13361:3:26;13354:18;13401:6;13395:13;13417:61;13471:6;13467:1;13462:3;13458:11;13451:4;13443:6;13439:17;13417:61;:::i;:::-;13498:16;;;;13516:1;13494:24;;13344:180;-1:-1:-1;;13344:180:26:o;13529:203::-;-1:-1:-1;;;;;13693:32:26;;;;13675:51;;13663:2;13648:18;;13630:102::o;13737:304::-;-1:-1:-1;;;;;13967:15:26;;;13949:34;;14019:15;;14014:2;13999:18;;13992:43;13899:2;13884:18;;13866:175::o;14046:375::-;-1:-1:-1;;;;;14304:15:26;;;14286:34;;14356:15;;;;14351:2;14336:18;;14329:43;14403:2;14388:18;;14381:34;;;;14236:2;14221:18;;14203:218::o;14426:562::-;-1:-1:-1;;;;;14723:15:26;;;14705:34;;14775:15;;14770:2;14755:18;;14748:43;14822:2;14807:18;;14800:34;;;14865:2;14850:18;;14843:34;;;14685:3;14908;14893:19;;14886:32;;;14426:562;;14935:47;;14962:19;;14954:6;14935:47;:::i;14993:284::-;-1:-1:-1;;;;;15179:32:26;;;;15161:51;;15255:14;15248:22;15243:2;15228:18;;15221:50;15149:2;15134:18;;15116:161::o;15282:274::-;-1:-1:-1;;;;;15474:32:26;;;;15456:51;;15538:2;15523:18;;15516:34;15444:2;15429:18;;15411:145::o;15561:345::-;-1:-1:-1;;;;;15781:32:26;;;;15763:51;;15845:2;15830:18;;15823:34;;;;15888:2;15873:18;;15866:34;15751:2;15736:18;;15718:188::o;15911:440::-;-1:-1:-1;;;;;16158:32:26;;;;16140:51;;-1:-1:-1;;;;;16227:31:26;;;;16222:2;16207:18;;16200:59;16247:2;16275:18;;16268:34;16333:2;16318:18;;16311:34;16127:3;16112:19;;16094:257::o;16356:658::-;16525:2;16577:21;;;16647:13;;16550:18;;;16669:22;;;16356:658;;16525:2;16748:15;;;;16722:2;16707:18;;;16356:658;16794:194;16808:6;16805:1;16802:13;16794:194;;;16873:13;;-1:-1:-1;;;;;16869:38:26;16857:51;;16963:15;;;;16928:12;;;;16904:1;16823:9;16794:194;;;-1:-1:-1;17005:3:26;;16505:509;-1:-1:-1;;;;;;16505:509:26:o;17019:187::-;17184:14;;17177:22;17159:41;;17147:2;17132:18;;17114:92::o;17211:177::-;17357:25;;;17345:2;17330:18;;17312:76::o;17393:202::-;-1:-1:-1;;;;;;17555:33:26;;;;17537:52;;17525:2;17510:18;;17492:103::o;18511:405::-;-1:-1:-1;;;;;18790:15:26;;;18772:34;;18842:15;;;18837:2;18822:18;;18815:43;18894:15;;;18889:2;18874:18;;18867:43;18722:2;18707:18;;18689:227::o;18921:221::-;;19070:2;19059:9;19052:21;19090:46;19132:2;19121:9;19117:18;19109:6;19090:46;:::i;19147:463::-;;19368:2;19357:9;19350:21;19394:46;19436:2;19425:9;19421:18;19413:6;19394:46;:::i;:::-;19488:9;19480:6;19476:22;19471:2;19460:9;19456:18;19449:50;19516:34;19543:6;19535;19516:34;:::i;:::-;19508:42;;;19598:4;19590:6;19586:17;19581:2;19570:9;19566:18;19559:45;19340:270;;;;;;:::o;19615:398::-;19817:2;19799:21;;;19856:2;19836:18;;;19829:30;19895:34;19890:2;19875:18;;19868:62;-1:-1:-1;;;19961:2:26;19946:18;;19939:32;20003:3;19988:19;;19789:224::o;20018:326::-;20220:2;20202:21;;;20259:1;20239:18;;;20232:29;-1:-1:-1;;;20292:2:26;20277:18;;20270:33;20335:2;20320:18;;20192:152::o;20349:326::-;20551:2;20533:21;;;20590:1;20570:18;;;20563:29;-1:-1:-1;;;20623:2:26;20608:18;;20601:33;20666:2;20651:18;;20523:152::o;20680:338::-;20882:2;20864:21;;;20921:2;20901:18;;;20894:30;-1:-1:-1;;;20955:2:26;20940:18;;20933:44;21009:2;20994:18;;20854:164::o;21023:402::-;21225:2;21207:21;;;21264:2;21244:18;;;21237:30;21303:34;21298:2;21283:18;;21276:62;-1:-1:-1;;;21369:2:26;21354:18;;21347:36;21415:3;21400:19;;21197:228::o;21430:326::-;21632:2;21614:21;;;21671:1;21651:18;;;21644:29;-1:-1:-1;;;21704:2:26;21689:18;;21682:33;21747:2;21732:18;;21604:152::o;21761:326::-;21963:2;21945:21;;;22002:1;21982:18;;;21975:29;-1:-1:-1;;;22035:2:26;22020:18;;22013:33;22078:2;22063:18;;21935:152::o;22499:354::-;22701:2;22683:21;;;22740:2;22720:18;;;22713:30;22779:32;22774:2;22759:18;;22752:60;22844:2;22829:18;;22673:180::o;22858:326::-;23060:2;23042:21;;;23099:1;23079:18;;;23072:29;-1:-1:-1;;;23132:2:26;23117:18;;23110:33;23175:2;23160:18;;23032:152::o;23189:326::-;23391:2;23373:21;;;23430:1;23410:18;;;23403:29;-1:-1:-1;;;23463:2:26;23448:18;;23441:33;23506:2;23491:18;;23363:152::o;23520:410::-;23722:2;23704:21;;;23761:2;23741:18;;;23734:30;23800:34;23795:2;23780:18;;23773:62;-1:-1:-1;;;23866:2:26;23851:18;;23844:44;23920:3;23905:19;;23694:236::o;23935:326::-;24137:2;24119:21;;;24176:1;24156:18;;;24149:29;-1:-1:-1;;;24209:2:26;24194:18;;24187:33;24252:2;24237:18;;24109:152::o;24266:326::-;24468:2;24450:21;;;24507:1;24487:18;;;24480:29;-1:-1:-1;;;24540:2:26;24525:18;;24518:33;24583:2;24568:18;;24440:152::o;24597:326::-;24799:2;24781:21;;;24838:1;24818:18;;;24811:29;-1:-1:-1;;;24871:2:26;24856:18;;24849:33;24914:2;24899:18;;24771:152::o;24928:326::-;25130:2;25112:21;;;25169:1;25149:18;;;25142:29;-1:-1:-1;;;25202:2:26;25187:18;;25180:33;25245:2;25230:18;;25102:152::o;25259:326::-;25461:2;25443:21;;;25500:1;25480:18;;;25473:29;-1:-1:-1;;;25533:2:26;25518:18;;25511:33;25576:2;25561:18;;25433:152::o;25590:344::-;25792:2;25774:21;;;25831:2;25811:18;;;25804:30;-1:-1:-1;;;25865:2:26;25850:18;;25843:50;25925:2;25910:18;;25764:170::o;25939:356::-;26141:2;26123:21;;;26160:18;;;26153:30;26219:34;26214:2;26199:18;;26192:62;26286:2;26271:18;;26113:182::o;26300:342::-;26502:2;26484:21;;;26541:2;26521:18;;;26514:30;-1:-1:-1;;;26575:2:26;26560:18;;26553:48;26633:2;26618:18;;26474:168::o;26647:353::-;26849:2;26831:21;;;26888:2;26868:18;;;26861:30;26927:31;26922:2;26907:18;;26900:59;26991:2;26976:18;;26821:179::o;27005:341::-;27207:2;27189:21;;;27246:2;27226:18;;;27219:30;-1:-1:-1;;;27280:2:26;27265:18;;27258:47;27337:2;27322:18;;27179:167::o;27351:326::-;27553:2;27535:21;;;27592:1;27572:18;;;27565:29;-1:-1:-1;;;27625:2:26;27610:18;;27603:33;27668:2;27653:18;;27525:152::o;27682:406::-;27884:2;27866:21;;;27923:2;27903:18;;;27896:30;27962:34;27957:2;27942:18;;27935:62;-1:-1:-1;;;28028:2:26;28013:18;;28006:40;28078:3;28063:19;;27856:232::o;28093:703::-;28310:13;;28325:12;28306:32;28288:51;;28409:4;28397:17;;;28391:24;28384:32;28377:40;28355:20;;;28348:70;28465:4;28453:17;;;28447:24;28551:19;;-1:-1:-1;;;;;28547:28:26;;;28525:20;;;28518:58;28622:23;;;28616:30;28612:39;;28607:2;28592:18;;;28585:67;;;;28699:23;;28693:30;28689:39;;;28683:3;28668:19;;28661:68;28773:15;;;28767:22;28498:3;28745:20;;28738:52;28275:3;28260:19;;28242:554::o;28801:188::-;28975:6;28963:19;;;;28945:38;;28933:2;28918:18;;28900:89::o;29176:248::-;29350:25;;;29406:2;29391:18;;29384:34;29338:2;29323:18;;29305:119::o;29429:201::-;-1:-1:-1;;;;;29592:31:26;;;;29574:50;;29562:2;29547:18;;29529:101::o;29840:271::-;-1:-1:-1;;;;;30030:31:26;;;;30012:50;;30093:2;30078:18;;30071:34;30000:2;29985:18;;29967:144::o;30116:352::-;-1:-1:-1;;;;;30328:31:26;;;;30310:50;;30391:2;30376:18;;30369:34;;;;30446:14;30439:22;30348:2;30419:18;;30412:50;30298:2;30283:18;;30265:203::o;30473:251::-;30543:2;30537:9;30573:17;;;-1:-1:-1;;;;;30605:34:26;;30641:22;;;30602:62;30599:2;;;30667:18;;:::i;:::-;30703:2;30696:22;30517:207;;-1:-1:-1;30517:207:26:o;30729:190::-;;-1:-1:-1;;;;;30801:30:26;;30798:2;;;30834:18;;:::i;:::-;-1:-1:-1;30902:2:26;30879:17;-1:-1:-1;;30875:31:26;30908:4;30871:42;;30788:131::o;30924:128::-;;30995:1;30991:6;30988:1;30985:13;30982:2;;;31001:18;;:::i;:::-;-1:-1:-1;31037:9:26;;30972:80::o;31057:236::-;;-1:-1:-1;;;;;31162:10:26;;;31192;;;31222:12;;;31214:21;;31211:2;;;31238:18;;:::i;:::-;31274:13;;31104:189;-1:-1:-1;;;;31104:189:26:o;31298:217::-;;31364:1;31354:2;;-1:-1:-1;;;31389:31:26;;31443:4;31440:1;31433:15;31471:4;31396:1;31461:15;31354:2;-1:-1:-1;31500:9:26;;31344:171::o;31520:453::-;31616:6;31639:5;31653:314;31702:1;31739:2;31729:8;31726:16;31716:2;;31746:5;;;31716:2;31787:4;31782:3;31778:14;31772:4;31769:24;31766:2;;;31796:18;;:::i;:::-;31846:2;31836:8;31832:17;31829:2;;;31861:16;;;;31829:2;31940:17;;;;;31900:15;;31653:314;;;31597:376;;;;;;;:::o;31978:148::-;;32065:55;-1:-1:-1;;32106:4:26;32092:19;;32086:4;32131:922;32215:8;32205:2;;-1:-1:-1;32256:1:26;32270:5;;32205:2;32304:4;32294:2;;-1:-1:-1;32341:1:26;32355:5;;32294:2;32386:4;32404:1;32399:59;;;;32472:1;32467:183;;;;32379:271;;32399:59;32429:1;32420:10;;32443:5;;;32467:183;32504:3;32494:8;32491:17;32488:2;;;32511:18;;:::i;:::-;32567:1;32557:8;32553:16;32544:25;;32595:3;32588:5;32585:14;32582:2;;;32602:18;;:::i;:::-;32635:5;;;32379:271;;32734:2;32724:8;32721:16;32715:3;32709:4;32706:13;32702:36;32696:2;32686:8;32683:16;32678:2;32672:4;32669:12;32665:35;32662:77;32659:2;;;-1:-1:-1;32771:19:26;;;32806:14;;;32803:2;;;32823:18;;:::i;:::-;32856:5;;32659:2;32903:42;32941:3;32931:8;32925:4;32922:1;32903:42;:::i;:::-;32978:6;32973:3;32969:16;32960:7;32957:29;32954:2;;;32989:18;;:::i;:::-;33027:20;;32195:858;-1:-1:-1;;;;32195:858:26:o;33058:168::-;;33164:1;33160;33156:6;33152:14;33149:1;33146:21;33141:1;33134:9;33127:17;33123:45;33120:2;;;33171:18;;:::i;:::-;-1:-1:-1;33211:9:26;;33110:116::o;33231:270::-;;-1:-1:-1;;;;;33340:10:26;;;33370;;;33403:11;;33396:19;33425:12;;;33417:21;;33392:47;33389:2;;;33442:18;;:::i;33506:125::-;;33574:1;33571;33568:8;33565:2;;;33579:18;;:::i;:::-;-1:-1:-1;33616:9:26;;33555:76::o;33636:258::-;33708:1;33718:113;33732:6;33729:1;33726:13;33718:113;;;33808:11;;;33802:18;33789:11;;;33782:39;33754:2;33747:10;33718:113;;;33849:6;33846:1;33843:13;33840:2;;;-1:-1:-1;;33884:1:26;33866:16;;33859:27;33689:205::o;33899:135::-;;-1:-1:-1;;33959:17:26;;33956:2;;;33979:18;;:::i;:::-;-1:-1:-1;34026:1:26;34015:13;;33946:88::o;34039:127::-;34100:10;34095:3;34091:20;34088:1;34081:31;34131:4;34128:1;34121:15;34155:4;34152:1;34145:15;34171:127;34232:10;34227:3;34223:20;34220:1;34213:31;34263:4;34260:1;34253:15;34287:4;34284:1;34277:15;34303:133;-1:-1:-1;;;;;34380:31:26;;34370:42;;34360:2;;34426:1;34423;34416:12;34441:120;34529:5;34522:13;34515:21;34508:5;34505:32;34495:2;;34551:1;34548;34541:12

Swarm Source

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