Contract 0x8869e326a563478a9f7aae4b8a78b518fb24c32f

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xd3496a474ee7a35b8326e310722a83e4f694dede695dabdfd102531b4d04b8bf0x608060402484322021-09-01 18:18:29459 days 6 hrs ago0xc25a67941ae0897933fc9abd6862dc7c34d49155 IN  Create: ACOPool20 ETH0.210120289743 ETH
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x2c2cd11601b48e7c13159549f1652a296de99aee9649ea26c478dbf3c200b055433451002022-12-03 19:32:581 day 5 hrs ago 0x2b3d495f68b3696982a39bf17c49d4ec718760e0 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x7f4b7842d466b8ba4a1377f8abddd09a1745a97436973b8411e645f48cd92151357578752022-11-06 15:17:0328 days 9 hrs ago 0xcae44333f46f3275a079b9dbaa311142ed6ca506 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0xa3efaf00948820d7ce4cd5056a78b4c9f771aadff6012e469beee0e07747d38d357575812022-11-06 15:15:4428 days 9 hrs ago 0xcae44333f46f3275a079b9dbaa311142ed6ca506 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x5ed3b02c7253920a8e962de2046b4231489d4ab2fc2dfcd7d8c03775939e7503357523262022-11-06 14:53:0328 days 10 hrs ago 0xcae44333f46f3275a079b9dbaa311142ed6ca506 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x9eada599d3fcbd77182a619adbcc67b4141fedb6ea5e0ee5b5a5affd588365df341157302022-10-31 8:21:2034 days 16 hrs ago 0xcae44333f46f3275a079b9dbaa311142ed6ca506 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x81c7f82c472423dc5f173cf5915fc7403a40a506619fede1c3ea3d058cc7b8a2331124722022-10-27 17:47:5538 days 7 hrs ago 0x02819a43a70e22e43b6e38c6b5868246775ea0f3 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x62504eaa02a967b34940028fad399751ed7624a6edbe122d1a755ab5bc0e6718325963982022-10-26 0:09:4340 days 49 mins ago 0x02819a43a70e22e43b6e38c6b5868246775ea0f3 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0xb3723f0036592aa71960c5183c5c0715097472e3b1b57b39d6284a52bd55bdcd325958882022-10-26 0:06:1140 days 52 mins ago 0x02819a43a70e22e43b6e38c6b5868246775ea0f3 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0xb766ba1883752562ecc0bc32e1a518e2ed7ec38d2aa798c760c0b5b0675ea1bf324102272022-10-25 8:32:1740 days 16 hrs ago 0xcae44333f46f3275a079b9dbaa311142ed6ca506 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x04c922bd79a24b4777c8d50ed968b2757620d17dcab9f6a58a7c414adfe30aa8323738372022-10-25 5:17:2640 days 19 hrs ago 0x02819a43a70e22e43b6e38c6b5868246775ea0f3 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x1dbc804f696fbb7e4cb962564523d9862ae7abbf2ff450fb36f5541404d1385a317290202022-10-22 12:17:1643 days 12 hrs ago 0x02819a43a70e22e43b6e38c6b5868246775ea0f3 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x7e82c800152979564faaf1b3949d5030f1b97ede726608ad8112d02eef71872f317289292022-10-22 12:16:4443 days 12 hrs ago 0x27790eb12a6c83c080c14f32eaa3232704522ad1 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x6aa79e9c8f28f99e159980b20d2c050d23ab6d9794d84a537fa7c8802ad638f0317287952022-10-22 12:16:0043 days 12 hrs ago 0x2b3d495f68b3696982a39bf17c49d4ec718760e0 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x36aa69867a7af06aa747814909785d0e71ebb4a5c4f04392c5d41aa116d7099f317286802022-10-22 12:15:2243 days 12 hrs ago 0xcae44333f46f3275a079b9dbaa311142ed6ca506 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x54a41b83cadaae4b21cda50d59db15e22a7f524650d6e447b0f678b19abc076e317276112022-10-22 12:09:0343 days 12 hrs ago 0x02819a43a70e22e43b6e38c6b5868246775ea0f3 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x3c803d64f322f878dc1d5f3055865adcb381dd66382e11df64beafd3443fcdc7317275092022-10-22 12:08:2843 days 12 hrs ago 0x27790eb12a6c83c080c14f32eaa3232704522ad1 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0xd2f934bce32a8cda477054c024ea2e2745e509b98a27ca6be3d94c12cd924fc3302210772022-10-15 10:01:1550 days 14 hrs ago 0xcae44333f46f3275a079b9dbaa311142ed6ca506 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x87c6b260c0fb8638fe750b1edef7a481dc4a911667b281aa0a3dda58c3a7f917291278542022-10-08 16:18:2857 days 8 hrs ago 0x2b3d495f68b3696982a39bf17c49d4ec718760e0 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x51ac236ef8892fe1cfb64ce37df097f41852ad8b5e0f56696c5246dc8401db8b282014792022-10-03 17:20:2562 days 7 hrs ago 0x2b3d495f68b3696982a39bf17c49d4ec718760e0 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x66d3177117764a224d4479393ea608a76e3cc6e13224cc729a4b03b81dc022cf281801532022-10-03 14:25:2262 days 10 hrs ago 0x02819a43a70e22e43b6e38c6b5868246775ea0f3 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x66d3177117764a224d4479393ea608a76e3cc6e13224cc729a4b03b81dc022cf281801532022-10-03 14:25:2262 days 10 hrs ago 0x02819a43a70e22e43b6e38c6b5868246775ea0f3 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0xcd094c61ab9b78bd994fe2e9986bb7e7320677ca9249f8e100d4a0bb92eb3bd3280939172022-10-03 3:39:1762 days 21 hrs ago 0x2b3d495f68b3696982a39bf17c49d4ec718760e0 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x0e98c93340eaaae8487b114b8b86cb294293c3d15ed88f02a2be1003033f76e9280935872022-10-03 3:36:2162 days 21 hrs ago 0x2b3d495f68b3696982a39bf17c49d4ec718760e0 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0xbb09a60d84e8605d8b10b4a25fb3f89b78edcf3091d1a388d178e585f41a1514278850002022-10-02 2:46:0863 days 22 hrs ago 0x2b3d495f68b3696982a39bf17c49d4ec718760e0 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
0x12be48e044850f508f18fabdc0be2a8397f4f6b8145c117f8a8da057396212d9261246812022-09-23 7:30:2472 days 17 hrs ago 0xcae44333f46f3275a079b9dbaa311142ed6ca506 0x8869e326a563478a9f7aae4b8a78b518fb24c32f0 ETH
[ Download CSV Export 
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.

Contract Source Code Verified (Exact Match)

Contract Name:
ACOPool2

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity Multiple files format)

File 1 of 14: ACOPool2.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

import './Ownable.sol';
import './ACOAssetHelper.sol';
import './ACOPoolLib.sol';
import './ERC20.sol';
import './IACOFactory.sol';
import './IACOPoolFactory2.sol';
import './IACOAssetConverterHelper.sol';
import './IACOToken.sol';
import './IACOPool2.sol';
import './ILendingPool.sol';

/**
 * @title ACOPool2
 * @dev A pool contract to trade ACO tokens.
 * 
 * The SC errors are defined as code to shrunk the SC bytes size and work around the EIP170.
 * The codes are explained in the table below:
 ********************************************************************************************
 * CODE | FUNCTION                            | DESCRIPTION						            *
 *------------------------------------------------------------------------------------------*
 * E00  | init                                | SC is already initialized                   *
 *------------------------------------------------------------------------------------------*
 * E01  | init                                | Underlying and strike asset are the same    *
 *------------------------------------------------------------------------------------------*
 * E10  | _deposit                            | Invalid collateral amount                   *
 *------------------------------------------------------------------------------------------*
 * E11  | _deposit                            | Invalid destination address                 *
 *------------------------------------------------------------------------------------------*
 * E12  | _deposit                            | Invalid deposit for lending pool token      *
 *------------------------------------------------------------------------------------------*
 * E13  | _deposit                            | The minimum shares were not satisfied       *
 *------------------------------------------------------------------------------------------*
 * E20  | _withdrawWithLocked                 | Invalid shares amount                       *
 *------------------------------------------------------------------------------------------*
 * E21  | _withdrawWithLocked                 | Invalid withdraw for lending pool token     *
 *------------------------------------------------------------------------------------------*
 * E30  | _withdrawNoLocked                   | Invalid shares amount                       *
 *------------------------------------------------------------------------------------------*
 * E31  | _withdrawNoLocked                   | Invalid withdraw for lending pool token     *
 *------------------------------------------------------------------------------------------*
 * E40  | _swap                               | Swap deadline reached                       *
 *------------------------------------------------------------------------------------------*
 * E41  | _swap                               | Invalid destination address                 *
 *------------------------------------------------------------------------------------------*
 * E42  | _internalSelling                    | The maximum payment restriction was reached *
 *------------------------------------------------------------------------------------------*
 * E43  | _internalSelling                    | Insufficient ether amount                   *
 *------------------------------------------------------------------------------------------*
 * E44  | _internalSelling                    | Ether is not expected                       *
 *------------------------------------------------------------------------------------------*
 * E45  | _internalSelling                    | The maximum number of open ACOs was reached *
 *------------------------------------------------------------------------------------------*
 * E50  | _quote                              | Invalid token amount                        *
 *------------------------------------------------------------------------------------------*
 * E51  | _quote                              | Invalid ACO token                           *
 *------------------------------------------------------------------------------------------*
 * E60  | restoreCollateral                   | No balance to restore                       *
 *------------------------------------------------------------------------------------------*
 * E70  | lendCollateral                      | Lend is not available for this pool         *
 *------------------------------------------------------------------------------------------*
 * E80  | withdrawStuckToken                  | The token is forbidden to withdraw          *
 *------------------------------------------------------------------------------------------*
 * E81  | _setAcoPermissionConfig             | Invalid below tolerance percentage          *
 *------------------------------------------------------------------------------------------*
 * E82  | _setAcoPermissionConfig             | Invalid minimum below tolerance percentage  *
 *------------------------------------------------------------------------------------------*
 * E83  | _setAcoPermissionConfig             | Invalid minimum above tolerance percentage  *
 *------------------------------------------------------------------------------------------*
 * E84  | _setAcoPermissionConfig             | Invalid minimum strike price value          *
 *------------------------------------------------------------------------------------------*
 * E85  | _setAcoPermissionConfig             | Invalid expiration range                    *
 *------------------------------------------------------------------------------------------*
 * E86  | _setBaseVolatility                  | Invalid base volatility                     *
 *------------------------------------------------------------------------------------------*
 * E87  | _setStrategy                        | Invalid strategy address                    *
 *------------------------------------------------------------------------------------------*
 * E88  | _setPoolAdmin                       | Invalid pool admin address                  *
 *------------------------------------------------------------------------------------------*
 * E89  | _setProtocolConfig                  | No price on the Oracle                      *
 *------------------------------------------------------------------------------------------*
 * E90  | _setProtocolConfig                  | Invalid fee destination address             *
 *------------------------------------------------------------------------------------------*
 * E91  | _setProtocolConfig                  | Invalid fee value                           *
 *------------------------------------------------------------------------------------------*
 * E92  | _setProtocolConfig                  | Invalid penalty percentage                  *
 *------------------------------------------------------------------------------------------*
 * E93  | _setProtocolConfig                  | Invalid underlying price adjust percentage  *
 *------------------------------------------------------------------------------------------*
 * E94  | _setProtocolConfig                  | Invalid maximum number of open ACOs allowed *
 *------------------------------------------------------------------------------------------*
 * E95  | _startLendingPool                   | Lending pool already started                *
 *------------------------------------------------------------------------------------------*
 * E97  | _privateValidation                  | The pool is public or it is a pool admin    *
 *------------------------------------------------------------------------------------------*
 * E98  | _onlyPoolAdmin                      | Only the pool admin can call the method     *
 *------------------------------------------------------------------------------------------*
 * E99  | _onlyProtocolOwner                  | Only the pool factory can call the method   *
 ********************************************************************************************
 */
contract ACOPool2 is Ownable, ERC20 {
    using SafeMath for uint256;
    
    uint256 internal constant PERCENTAGE_PRECISION = 100000;

    event StartLendingPool(address indexed newLendingPool);

    event SetValidAcoCreator(address indexed creator, bool indexed previousPermission, bool indexed newPermission);
    
    event SetForbiddenAcoCreator(address indexed creator, bool indexed previousStatus, bool indexed newStatus);
    
    event SetProtocolConfig(IACOPool2.PoolProtocolConfig oldConfig, IACOPool2.PoolProtocolConfig newConfig);
	
	event SetAcoPermissionConfigV2(IACOPool2.PoolAcoPermissionConfigV2 oldConfig, IACOPool2.PoolAcoPermissionConfigV2 newConfig);

    event SetBaseVolatility(uint256 indexed oldBaseVolatility, uint256 indexed newBaseVolatility);

	event SetStrategy(address indexed oldStrategy, address indexed newStrategy);
	
    event SetPoolAdmin(address indexed oldAdmin, address indexed newAdmin);

    event RestoreCollateral(uint256 amountOut, uint256 collateralRestored);

    event LendCollateral(uint256 collateralAmount);

	event ACORedeem(address indexed acoToken, uint256 valueSold, uint256 collateralLocked, uint256 collateralRedeemed);

    event Deposit(address indexed account, uint256 shares, uint256 collateralAmount);

    event Withdraw(
		address indexed account, 
		uint256 shares, 
		bool noLocked, 
		uint256 underlyingWithdrawn, 
		uint256 strikeAssetWithdrawn, 
		address[] acos, 
		uint256[] acosAmount
	);

	event Swap(
        address indexed account, 
        address indexed acoToken, 
        uint256 tokenAmount, 
        uint256 price, 
        uint256 protocolFee,
        uint256 underlyingPrice,
		uint256 volatility
    );

    IACOFactory public acoFactory;
    address public underlying;
    address public strikeAsset;
    bool public isCall;
    
    bool public isPrivate;
    uint256 public poolId;

	ILendingPool public lendingPool;
    address public poolAdmin;
	address public strategy;
    uint256 public baseVolatility;
    
    IACOPool2.PoolAcoPermissionConfigV2 public acoPermissionConfigV2;
    IACOPool2.PoolProtocolConfig public protocolConfig;
    
    address[] public acoTokens;
    address[] public openAcos;

    mapping(address => bool) public forbiddenAcoCreators;
    mapping(address => bool) public validAcoCreators;
    mapping(address => IACOPool2.AcoData) public acoData;

    address internal lendingToken;
	uint256 internal underlyingPrecision;

    function init(IACOPool2.InitData calldata initData) external {
		require(underlying == address(0) && strikeAsset == address(0), "E00");
        require(initData.underlying != initData.strikeAsset, "E01");
        
        super.init();

        acoFactory = IACOFactory(initData.acoFactory);
        underlying = initData.underlying;
        strikeAsset = initData.strikeAsset;
        isCall = initData.isCall;
        isPrivate = initData.isPrivate;
        poolId = initData.poolId;
		
		_setProtocolConfig(initData.protocolConfig);
		_setPoolAdmin(initData.admin);
		_setAcoPermissionConfig(initData.acoPermissionConfigV2);
        _setBaseVolatility(initData.baseVolatility);
        _setStrategy(initData.strategy);
        _startLendingPool(initData.lendingPool);

		underlyingPrecision = 10 ** uint256(ACOAssetHelper._getAssetDecimals(initData.underlying));
    }
    
    receive() external payable {
    }

    function name() public override view returns(string memory) {
        return ACOPoolLib.name(underlying, strikeAsset, isCall, poolId);
    }

	function symbol() public override view returns(string memory) {
        return name();
    }

    function decimals() public override view returns(uint8) {
        return ACOAssetHelper._getAssetDecimals(collateral());
    }

	function collateral() public view returns(address) {
        return (isCall ? underlying : strikeAsset);
    }

    function numberOfAcoTokensNegotiated() external view returns(uint256) {
        return acoTokens.length;
    }

    function numberOfOpenAcoTokens() external view returns(uint256) {
        return openAcos.length;
    }

    function canSwap(address acoToken) external view returns(bool) {
        (address _underlying, address _strikeAsset, bool _isCall, uint256 _strikePrice, uint256 _expiryTime) = _getAcoData(acoToken);
		if (_acoBasicDataIsValid(acoToken, _underlying, _strikeAsset, _isCall)) {
            uint256 price = _getPrice(_underlying, _strikeAsset, protocolConfig.assetConverter);
            return ACOPoolLib.acoStrikeAndExpirationIsValid(_strikePrice, _expiryTime, price, acoPermissionConfigV2);
        }
        return false;
    }

	function quote(address acoToken, uint256 tokenAmount) external view returns(
        uint256 swapPrice, 
        uint256 protocolFee, 
        uint256 underlyingPrice, 
        uint256 volatility
    ) {
        IACOPool2.PoolProtocolConfig storage _protocolConfig = protocolConfig;
        (swapPrice, protocolFee, underlyingPrice, volatility,) = _quote(acoToken, tokenAmount, _protocolConfig);
    }

	function getDepositShares(uint256 collateralAmount) external view returns(uint256) {
        (,,uint256 collateralBalance,) = _getCollateralNormalized(true);

        if (collateralBalance == 0) {
            return collateralAmount;
        } else {
            return collateralAmount.mul(totalSupply()).div(collateralBalance);
        }
    }

	function getWithdrawNoLockedData(uint256 shares) external view returns(
        uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn,
		bool isPossible
    ) {
        uint256 _totalSupply = totalSupply();
		if (shares > 0 && shares <= _totalSupply) {
			
			(uint256 underlyingBalance, 
             uint256 strikeAssetBalance, 
             uint256 collateralBalance, 
             uint256 collateralLockedRedeemable) = _getCollateralNormalized(false);
             
            (underlyingWithdrawn, strikeAssetWithdrawn, isPossible) = ACOPoolLib.getBaseWithdrawNoLockedData(
                shares,
                _totalSupply,
                isCall,
                underlyingBalance, 
                strikeAssetBalance, 
                collateralBalance, 
                collateralLockedRedeemable
            );
		}
    }

	function getWithdrawWithLocked(uint256 shares) external view returns(
        uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn,
		address[] memory acos,
		uint256[] memory acosAmount
    ) {
        uint256 _totalSupply = totalSupply();	
        if (shares > 0 && shares <= _totalSupply) {
        
            (underlyingWithdrawn, strikeAssetWithdrawn) = ACOPoolLib.getBaseAssetsWithdrawWithLocked(shares, underlying, strikeAsset, isCall, _totalSupply, lendingToken);
		
            acos = new address[](openAcos.length);
            acosAmount = new uint256[](openAcos.length);
			for (uint256 i = 0; i < openAcos.length; ++i) {
				address acoToken = openAcos[i];
				uint256 tokens = IACOToken(acoToken).currentCollateralizedTokens(address(this));
				
				acos[i] = acoToken;
				acosAmount[i] = tokens.mul(shares).div(_totalSupply);
			}
		}
    }

	function getGeneralData() external view returns(
        uint256 underlyingBalance,
		uint256 strikeAssetBalance,
		uint256 collateralLocked,
        uint256 collateralOnOpenPosition,
        uint256 collateralLockedRedeemable,
		uint256 poolSupply
    ) {
        poolSupply = totalSupply();
        (underlyingBalance, strikeAssetBalance,, collateralLocked, collateralOnOpenPosition, collateralLockedRedeemable) = _getCollateralData(true);
    }
    
    function setAcoPermissionConfig(IACOPool2.PoolAcoPermissionConfigV2 calldata newConfig) external {
        _onlyPoolAdmin();
        _setAcoPermissionConfig(newConfig);
    }

	function setBaseVolatility(uint256 newBaseVolatility) external {
        _onlyPoolAdmin();
		_setBaseVolatility(newBaseVolatility);
	}
	
	function setStrategy(address newStrategy) external {
        _onlyPoolAdmin();
		_setStrategy(newStrategy);
	}
	
	function setPoolAdmin(address newAdmin) external {
	    _onlyPoolAdmin();
		_setPoolAdmin(newAdmin);
	}

	function setValidAcoCreator(address acoCreator, bool newPermission) external {
        _onlyProtocolOwner();
        emit SetValidAcoCreator(acoCreator, validAcoCreators[acoCreator], newPermission);
        validAcoCreators[acoCreator] = newPermission;
    }
    
    function setForbiddenAcoCreator(address acoCreator, bool isForbidden) external {
        _onlyProtocolOwner();
        emit SetForbiddenAcoCreator(acoCreator, forbiddenAcoCreators[acoCreator], isForbidden);
        forbiddenAcoCreators[acoCreator] = isForbidden;
    }
    
    function setProtocolConfig(IACOPool2.PoolProtocolConfig calldata newConfig) external {
        _onlyProtocolOwner();
        _setProtocolConfig(newConfig);
    }

    function startLendingPool(address newLendingPool) external {
        _onlyProtocolOwner();
		_startLendingPool(newLendingPool);
	}

    function withdrawStuckToken(address token, address destination) external {
        _onlyProtocolOwner();
        require(token != underlying && token != strikeAsset && !acoData[token].open && (!_hasLendingPool() || token != lendingToken), "E80");
        uint256 _balance = ACOAssetHelper._getAssetBalanceOf(token, address(this));
        if (_balance > 0) {
            ACOAssetHelper._transferAsset(token, destination, _balance);
        }
    }

	function deposit(
	    uint256 collateralAmount, 
	    uint256 minShares, 
	    address to, 
	    bool isLendingToken
    ) external payable returns(uint256) {
        return _deposit(collateralAmount, minShares, to, isLendingToken);
    }
    
    function withdrawWithLocked(uint256 shares, address account, bool withdrawLendingToken) external returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn,
		address[] memory acos,
		uint256[] memory acosAmount
	) {
        (underlyingWithdrawn, strikeAssetWithdrawn, acos, acosAmount) = _withdrawWithLocked(shares, account, withdrawLendingToken);
    }

	function withdrawNoLocked(
	    uint256 shares, 
	    uint256 minCollateral, 
	    address account, 
	    bool withdrawLendingToken
    ) external returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn
	) {
        (underlyingWithdrawn, strikeAssetWithdrawn) = _withdrawNoLocked(shares, minCollateral, account, withdrawLendingToken);
    }

	function swap(
        address acoToken, 
        uint256 tokenAmount, 
        uint256 restriction, 
        address to, 
        uint256 deadline
    ) external payable {
        _swap(acoToken, tokenAmount, restriction, to, deadline);
    }

    function redeemACOTokens() public {
        for (uint256 i = openAcos.length; i > 0; --i) {
            address acoToken = openAcos[i - 1];
            redeemACOToken(acoToken);
        }
    }

	function redeemACOToken(address acoToken) public {
		IACOPool2.AcoData storage data = acoData[acoToken];
		if (data.open && IACOToken(acoToken).expiryTime() <= block.timestamp) {
			
            data.open = false;
			uint256 lastIndex = openAcos.length - 1;
    		uint256 index = data.openIndex;
    		if (lastIndex != index) {
    		    address last = openAcos[lastIndex];
    			openAcos[index] = last;
    			acoData[last].openIndex = index;
    		}
    		data.openIndex = 0;
            openAcos.pop();

            if (IACOToken(acoToken).currentCollateralizedTokens(address(this)) > 0) {	
			    data.collateralRedeemed = IACOToken(acoToken).redeem();
			    if (_hasLendingPool()) {
			        _depositOnLendingPool(data.collateralRedeemed);
			    }
            }
			
			emit ACORedeem(acoToken, data.valueSold, data.collateralLocked, data.collateralRedeemed);
		}
    }

	function restoreCollateral() external {
        _onlyPoolAdmin();
        
        uint256 balanceOut;
        address assetIn;
        address assetOut;
        if (isCall) {
            balanceOut = _getPoolBalanceOf(strikeAsset);
            assetIn = underlying;
            assetOut = strikeAsset;
        } else {
            balanceOut = _getPoolBalanceOf(underlying);
            assetIn = strikeAsset;
            assetOut = underlying;
        }
        require(balanceOut > 0, "E60");
        
		uint256 etherAmount = 0;
        if (ACOAssetHelper._isEther(assetOut)) {
			etherAmount = balanceOut;
        }
        uint256 collateralRestored = IACOAssetConverterHelper(protocolConfig.assetConverter).swapExactAmountOut{value: etherAmount}(assetOut, assetIn, balanceOut);
        if (_hasLendingPool()) {
            _depositOnLendingPool(collateralRestored);
        }

        emit RestoreCollateral(balanceOut, collateralRestored);
    }

	function lendCollateral() public {
		require(_hasLendingPool(), "E70");
	    uint256 strikeAssetBalance = _getPoolBalanceOf(strikeAsset);
	    if (strikeAssetBalance > 0) {
	        _depositOnLendingPool(strikeAssetBalance);
	        emit LendCollateral(strikeAssetBalance);
	    }
    }

    function _getAcoData(address acoToken) internal view returns(
        address _underlying, 
        address _strikeAsset, 
        bool _isCall, 
        uint256 strikePrice, 
        uint256 expiryTime
    ) {
        (_underlying, _strikeAsset, _isCall, strikePrice, expiryTime) = acoFactory.acoTokenData(acoToken);
    }

	function _quote(
	    address acoToken, 
	    uint256 tokenAmount, 
	    IACOPool2.PoolProtocolConfig storage _protocolConfig
    ) internal view returns(
        uint256 swapPrice, 
        uint256 protocolFee, 
        uint256 underlyingPrice, 
        uint256 volatility, 
        uint256 collateralAmount
    ) {
        require(tokenAmount > 0, "E50");
        
        ACOPoolLib.AcoData memory _acoData = _getAcoDataForQuote(acoToken, tokenAmount);
        
		require(_acoBasicDataIsValid(acoToken, _acoData.underlying, _acoData.strikeAsset, _acoData.isCall), "E51");
		
		underlyingPrice = _getPrice(_acoData.underlying, _acoData.strikeAsset, _protocolConfig.assetConverter);
		
		(swapPrice, protocolFee, volatility, collateralAmount) = ACOPoolLib.quote(ACOPoolLib.QuoteData(
    		lendingToken,
    		strategy,
    		baseVolatility,
    		_protocolConfig.fee,
    		underlyingPrice,
    		underlyingPrecision,
    		_acoData,
    		acoPermissionConfigV2));
    }
    
    function _getAcoDataForQuote(address acoToken, uint256 tokenAmount) internal view returns(ACOPoolLib.AcoData memory _acoData) {
        (address _underlying, address _strikeAsset, bool _isCall, uint256 strikePrice, uint256 expiryTime) = _getAcoData(acoToken);
        _acoData = ACOPoolLib.AcoData(_isCall, strikePrice, expiryTime, tokenAmount, _underlying, _strikeAsset); 
    }
    
	function _deposit(
	    uint256 collateralAmount, 
	    uint256 minShares, 
	    address to,
	    bool isLendingToken
    ) internal returns(uint256 shares) {
        _privateValidation();
        require(collateralAmount > 0, "E10");
        require(to != address(0) && to != address(this), "E11");
        require(!isLendingToken || _hasLendingPool(), "E12");
		
		(,,uint256 collateralBalance,) = _getCollateralNormalized(true);

		address _collateral = collateral();
		if (ACOAssetHelper._isEther(_collateral)) {
            collateralBalance = collateralBalance.sub(msg.value);
		}
        
        if (collateralBalance == 0) {
            shares = collateralAmount;
        } else {
            shares = collateralAmount.mul(totalSupply()).div(collateralBalance);
        }
        require(shares >= minShares, "E13");

        if (isLendingToken) {
            ACOAssetHelper._receiveAsset(lendingToken, collateralAmount);
        } else {
            ACOAssetHelper._receiveAsset(_collateral, collateralAmount);
            if (_hasLendingPool()) {
                _depositOnLendingPool(collateralAmount);
            }
        }
        
        super._mintAction(to, shares);
        
        emit Deposit(to, shares, collateralAmount);
    }

	function _withdrawWithLocked(uint256 shares, address account, bool withdrawLendingToken) internal returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn,
		address[] memory acos,
		uint256[] memory acosAmount
	) {
        require(shares > 0, "E20");
        require(!withdrawLendingToken || _hasLendingPool(), "E21");
        
		redeemACOTokens();
		
        uint256 _totalSupply = totalSupply();
        _callBurn(account, shares);
        
		(underlyingWithdrawn, strikeAssetWithdrawn) = ACOPoolLib.getBaseAssetsWithdrawWithLocked(shares, underlying, strikeAsset, isCall, _totalSupply, lendingToken);
		
		(acos, acosAmount) = _transferOpenPositions(shares, _totalSupply);

		_transferWithdrawnAssets(underlyingWithdrawn, strikeAssetWithdrawn, withdrawLendingToken);

        emit Withdraw(account, shares, false, underlyingWithdrawn, strikeAssetWithdrawn, acos, acosAmount);
    }
    
    function _withdrawNoLocked(
        uint256 shares, 
        uint256 minCollateral, 
        address account, 
        bool withdrawLendingToken
    ) internal returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn
	) {
        require(shares > 0, "E30");
        require(!withdrawLendingToken || _hasLendingPool(), "E31");
        
		redeemACOTokens();
		
        uint256 _totalSupply = totalSupply();
        _callBurn(account, shares);
        
        (underlyingWithdrawn, strikeAssetWithdrawn) = _getAmountToNoLockedWithdraw(shares, _totalSupply, minCollateral, isCall);
        
        _transferWithdrawnAssets(underlyingWithdrawn, strikeAssetWithdrawn, withdrawLendingToken);
		
        emit Withdraw(account, shares, true, underlyingWithdrawn, strikeAssetWithdrawn, new address[](0), new uint256[](0));
    }

    function _transferWithdrawnAssets(
        uint256 underlyingWithdrawn, 
        uint256 strikeAssetWithdrawn, 
        bool withdrawLendingToken
    ) internal {
        if (strikeAssetWithdrawn > 0) {
            if (withdrawLendingToken) {
    		    ACOAssetHelper._transferAsset(lendingToken, msg.sender, strikeAssetWithdrawn);
    		} else if (_hasLendingPool()) {
    		    _withdrawOnLendingPool(strikeAssetWithdrawn, msg.sender);
    		} else {
    		    ACOAssetHelper._transferAsset(strikeAsset, msg.sender, strikeAssetWithdrawn);
    		}
        }
        if (underlyingWithdrawn > 0) {
		    ACOAssetHelper._transferAsset(underlying, msg.sender, underlyingWithdrawn);
        }
    }

	function _getCollateralNormalized(bool isDeposit) internal view returns(
        uint256 underlyingBalance, 
        uint256 strikeAssetBalance, 
        uint256 collateralBalance,
        uint256 collateralLockedRedeemable
    ) {
        uint256 collateralLocked;
        uint256 collateralOnOpenPosition;
        (underlyingBalance, strikeAssetBalance, collateralBalance, collateralLocked, collateralOnOpenPosition, collateralLockedRedeemable) = _getCollateralData(isDeposit);
	        
        collateralBalance = collateralBalance.add(collateralLocked).sub(collateralOnOpenPosition);
    }
    
    function _getCollateralData(bool isDeposit) internal view returns(
        uint256 underlyingBalance, 
        uint256 strikeAssetBalance, 
        uint256 collateralBalance,
        uint256 collateralLocked,
        uint256 collateralOnOpenPosition,
        uint256 collateralLockedRedeemable
    ) {
        IACOPool2.PoolProtocolConfig storage _protocolConfig = protocolConfig;
	    uint256 underlyingPrice = _getPrice(underlying, strikeAsset, _protocolConfig.assetConverter);
        (underlyingBalance, strikeAssetBalance, collateralBalance, collateralLocked, collateralOnOpenPosition, collateralLockedRedeemable) = ACOPoolLib.getCollateralData(
            ACOPoolLib.OpenPositionData(
                isDeposit,
    	        isCall,
    	        underlyingPrice,
    	        baseVolatility,
    	        _protocolConfig.underlyingPriceAdjustPercentage,
    	        _protocolConfig.withdrawOpenPositionPenalty,
    	        _protocolConfig.fee,
    	        underlyingPrecision,
    	        underlying,
    	        strikeAsset,
    	        strategy,
    	        address(acoFactory),
    	        lendingToken),
	        openAcos);
    }
    
    function _getAmountToNoLockedWithdraw(
        uint256 shares, 
        uint256 _totalSupply, 
        uint256 minCollateral,
        bool _isCall
    ) internal view returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn
	) {
        (uint256 underlyingBalance, 
         uint256 strikeAssetBalance, 
         uint256 collateralBalance,) = _getCollateralNormalized(false);

        (underlyingWithdrawn, strikeAssetWithdrawn) = ACOPoolLib.getAmountToNoLockedWithdraw(shares, _totalSupply, underlyingBalance, strikeAssetBalance, collateralBalance, minCollateral, _isCall);
    }

	function _callBurn(address account, uint256 tokenAmount) internal {
        if (account == msg.sender) {
            super._burnAction(account, tokenAmount);
        } else {
            super._burnFrom(account, tokenAmount);
        }
    }

	function _swap(
        address acoToken, 
        uint256 tokenAmount, 
        uint256 restriction, 
        address to, 
        uint256 deadline
    ) internal {
        require(block.timestamp <= deadline, "E40");
        require(to != address(0) && to != acoToken && to != address(this), "E41");
        
        IACOPool2.PoolProtocolConfig storage _protocolConfig = protocolConfig;
        (uint256 swapPrice, uint256 protocolFee, uint256 underlyingPrice, uint256 volatility, uint256 collateralAmount) = _quote(acoToken, tokenAmount, _protocolConfig);
        
        _internalSelling(to, acoToken, collateralAmount, tokenAmount, restriction, swapPrice, protocolFee);

        if (protocolFee > 0) {
            ACOAssetHelper._transferAsset(strikeAsset, _protocolConfig.feeDestination, protocolFee);
        }
        
        emit Swap(to, acoToken, tokenAmount, swapPrice, protocolFee, underlyingPrice, volatility);
    }

    function _internalSelling(
        address to,
        address acoToken, 
        uint256 collateralAmount, 
        uint256 tokenAmount,
        uint256 maxPayment,
        uint256 swapPrice,
        uint256 protocolFee
    ) internal {
        require(swapPrice <= maxPayment, "E42");
        
        address _strikeAsset = strikeAsset;
        uint256 extra = 0;
        if (ACOAssetHelper._isEther(_strikeAsset)) {
            require(msg.value >= swapPrice, "E43");
            extra = msg.value.sub(swapPrice);
        } else {
            require(msg.value == 0, "E44");
            ACOAssetHelper._callTransferFromERC20(_strikeAsset, msg.sender, address(this), swapPrice);
        }
        
        uint256 remaining = swapPrice.sub(protocolFee);
        
        if (_hasLendingPool()) {
            _withdrawOnLendingPool(collateralAmount.sub(remaining), address(this));
        }
        
		address _collateral = collateral();
        IACOPool2.AcoData storage data = acoData[acoToken];
		if (ACOAssetHelper._isEther(_collateral)) {
			tokenAmount = IACOToken(acoToken).mintPayable{value: collateralAmount}();
		} else {
			if (!data.open) {
				_setAuthorizedSpender(_collateral, acoToken);    
			}
			tokenAmount = IACOToken(acoToken).mint(collateralAmount);
		}

		if (!data.open) {
            require(openAcos.length < protocolConfig.maximumOpenAco, "E45");
			acoData[acoToken] = IACOPool2.AcoData(true, remaining, collateralAmount, 0, acoTokens.length, openAcos.length);
            acoTokens.push(acoToken);    
            openAcos.push(acoToken);   
        } else {
			data.collateralLocked = collateralAmount.add(data.collateralLocked);
			data.valueSold = remaining.add(data.valueSold);
		}
        
        ACOAssetHelper._callTransferERC20(acoToken, to, tokenAmount);
        
        if (extra > 0) {
            ACOAssetHelper._transferAsset(_strikeAsset, msg.sender, extra);    
        }
    }

	function _transferOpenPositions(uint256 shares, uint256 _totalSupply) internal returns(
        address[] memory acos, 
        uint256[] memory acosAmount
    ) {
        uint256 size = openAcos.length;
        acos = new address[](size);
        acosAmount = new uint256[](size);
		for (uint256 i = 0; i < size; ++i) {
			address acoToken = openAcos[i];
			uint256 tokens = IACOToken(acoToken).currentCollateralizedTokens(address(this));
			
			acos[i] = acoToken;
			acosAmount[i] = tokens.mul(shares).div(_totalSupply);
			
            if (acosAmount[i] > 0) {
			    IACOToken(acoToken).transferCollateralOwnership(msg.sender, acosAmount[i]);
            }
		}
	}

    function _hasLendingPool() internal view returns(bool) {
        return !isCall && address(lendingPool) != address(0);
    }

    function _depositOnLendingPool(uint256 amount) internal {
        lendingPool.deposit(strikeAsset, amount, address(this), protocolConfig.lendingPoolReferral);
    }

    function _withdrawOnLendingPool(uint256 amount, address to) internal {
        lendingPool.withdraw(strikeAsset, amount, to);
    }

	function _acoBasicDataIsValid(address acoToken, address _underlying, address _strikeAsset, bool _isCall) internal view returns(bool) {
		if (_underlying == underlying && _strikeAsset == strikeAsset && _isCall == isCall) {
		    address creator = acoFactory.creators(acoToken);
		    return (!forbiddenAcoCreators[creator] && (validAcoCreators[address(0)] || validAcoCreators[creator])); 
	    } else {
	        return false;
	    }
	}

	function _getPoolBalanceOf(address asset) internal view returns(uint256) {
        return ACOAssetHelper._getAssetBalanceOf(asset, address(this));
    }
	
	function _getPrice(address _underlying, address _strikeAsset, address assetConverter) internal view returns(uint256) {
	    return IACOAssetConverterHelper(assetConverter).getPrice(_underlying, _strikeAsset);
	}

	function _setAuthorizedSpender(address asset, address spender) internal {
        ACOAssetHelper._callApproveERC20(asset, spender, ACOAssetHelper.MAX_UINT);
    }

    function _setAcoPermissionConfig(IACOPool2.PoolAcoPermissionConfigV2 memory newConfig) internal {
        require(newConfig.tolerancePriceBelowMax < int256(PERCENTAGE_PRECISION) && newConfig.tolerancePriceBelowMin < int256(PERCENTAGE_PRECISION), "E81");
        require(newConfig.tolerancePriceBelowMin < newConfig.tolerancePriceBelowMax || newConfig.tolerancePriceBelowMax < int256(0), "E82");
        require(newConfig.tolerancePriceAboveMin < newConfig.tolerancePriceAboveMax || newConfig.tolerancePriceAboveMax < int256(0), "E83");
        require(newConfig.minStrikePrice < newConfig.maxStrikePrice || newConfig.maxStrikePrice == 0, "E84");
        require(newConfig.minExpiration <= newConfig.maxExpiration, "E85");
        
        emit SetAcoPermissionConfigV2(acoPermissionConfigV2, newConfig);
        
        acoPermissionConfigV2 = newConfig;
    }

    function _setBaseVolatility(uint256 newBaseVolatility) internal {
        require(newBaseVolatility > 0, "E86");
        emit SetBaseVolatility(baseVolatility, newBaseVolatility);
        baseVolatility = newBaseVolatility;
    }
    
    function _setStrategy(address newStrategy) internal {
        require(IACOPoolFactory2(owner()).strategyPermitted(newStrategy), "E87");
        emit SetStrategy(address(strategy), newStrategy);
        strategy = newStrategy;
    }

    function _setPoolAdmin(address newAdmin) internal {
        require(newAdmin != address(0), "E88");
        emit SetPoolAdmin(poolAdmin, newAdmin);
        poolAdmin = newAdmin;
    }

    function _setProtocolConfig(IACOPool2.PoolProtocolConfig memory newConfig) internal {
        address _underlying = underlying;
        address _strikeAsset = strikeAsset;
		require(IACOAssetConverterHelper(newConfig.assetConverter).getPrice(_underlying, _strikeAsset) > 0, "E89");
        require(newConfig.feeDestination != address(0), "E90");
        require(newConfig.fee <= 12500, "E91");
        require(newConfig.withdrawOpenPositionPenalty <= PERCENTAGE_PRECISION, "E92");
        require(newConfig.underlyingPriceAdjustPercentage < PERCENTAGE_PRECISION, "E93");
        require(newConfig.maximumOpenAco > 0, "E94");
        		
		if (isCall) {
            if (!ACOAssetHelper._isEther(_strikeAsset)) {
                _setAuthorizedSpender(_strikeAsset, newConfig.assetConverter);
            }
        } else if (!ACOAssetHelper._isEther(_underlying)) {
            _setAuthorizedSpender(_underlying, newConfig.assetConverter);
        }
        
        emit SetProtocolConfig(protocolConfig, newConfig);
        
        protocolConfig = newConfig;
    }

    function _startLendingPool(address newLendingPool) internal {
        require(address(lendingPool) == address(0), "E95");
        
        if (newLendingPool != address(0) && !isCall) {

            lendingToken = ILendingPool(newLendingPool).getReserveData(strikeAsset).aTokenAddress;
            _setAuthorizedSpender(strikeAsset, newLendingPool);
                
            lendingPool = ILendingPool(newLendingPool);

            emit StartLendingPool(newLendingPool);

            lendCollateral();
        }
    }
    
    function _privateValidation() internal view {
        require(!isPrivate || poolAdmin == msg.sender, "E97");
    }
    
    function _onlyPoolAdmin() internal view {
        require(poolAdmin == msg.sender, "E98");
    }
    
    function _onlyProtocolOwner() internal view {
        require(owner() == msg.sender, "E99");
    }
}

File 2 of 14: ACOAssetHelper.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

library ACOAssetHelper {
    uint256 internal constant MAX_UINT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    function _isEther(address _address) internal pure returns(bool) {
        return _address == address(0);
    }

    function _callApproveERC20(address token, address spender, uint256 amount) internal {
        (bool success, bytes memory returndata) = token.call(abi.encodeWithSelector(0x095ea7b3, spender, amount));
        require(success && (returndata.length == 0 || abi.decode(returndata, (bool))), "approve");
    }

    function _callTransferERC20(address token, address recipient, uint256 amount) internal {
        (bool success, bytes memory returndata) = token.call(abi.encodeWithSelector(0xa9059cbb, recipient, amount));
        require(success && (returndata.length == 0 || abi.decode(returndata, (bool))), "transfer");
    }

     function _callTransferFromERC20(address token, address sender, address recipient, uint256 amount) internal {
        (bool success, bytes memory returndata) = token.call(abi.encodeWithSelector(0x23b872dd, sender, recipient, amount));
        require(success && (returndata.length == 0 || abi.decode(returndata, (bool))), "transferFrom");
    }

    function _getAssetSymbol(address asset) internal view returns(string memory) {
        if (_isEther(asset)) {
            return "ETH";
        } else {
            (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSelector(0x95d89b41));
            require(success, "symbol");
            return abi.decode(returndata, (string));
        }
    }

    function _getAssetDecimals(address asset) internal view returns(uint8) {
        if (_isEther(asset)) {
            return uint8(18);
        } else {
            (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSelector(0x313ce567));
            require(success, "decimals");
            return abi.decode(returndata, (uint8));
        }
    }

    function _getAssetName(address asset) internal view returns(string memory) {
        if (_isEther(asset)) {
            return "Ethereum";
        } else {
            (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSelector(0x06fdde03));
            require(success, "name");
            return abi.decode(returndata, (string));
        }
    }

    function _getAssetBalanceOf(address asset, address account) internal view returns(uint256) {
        if (_isEther(asset)) {
            return account.balance;
        } else {
            (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSelector(0x70a08231, account));
            require(success, "balanceOf");
            return abi.decode(returndata, (uint256));
        }
    }

    function _getAssetAllowance(address asset, address owner, address spender) internal view returns(uint256) {
        if (_isEther(asset)) {
            return 0;
        } else {
            (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSelector(0xdd62ed3e, owner, spender));
            require(success, "allowance");
            return abi.decode(returndata, (uint256));
        }
    }

    function _transferAsset(address asset, address to, uint256 amount) internal {
        if (_isEther(asset)) {
            (bool success,) = to.call{value:amount}(new bytes(0));
            require(success, "send");
        } else {
            _callTransferERC20(asset, to, amount);
        }
    }

    function _receiveAsset(address asset, uint256 amount) internal {
        if (_isEther(asset)) {
            require(msg.value == amount, "Invalid ETH amount");
        } else {
            require(msg.value == 0, "No payable");
            _callTransferFromERC20(asset, msg.sender, address(this), amount);
        }
    }

    function _setAssetInfinityApprove(address asset, address owner, address spender, uint256 amount) internal {
        if (_getAssetAllowance(asset, owner, spender) < amount) {
            _callApproveERC20(asset, spender, MAX_UINT);
        }
    }
}

File 3 of 14: ACOPoolLib.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

import "./SafeMath.sol";
import "./IACOPoolStrategy.sol";
import "./IACOFactory.sol";
import "./IACOToken.sol";
import "./ILendingPool.sol";
import "./IACOPool2.sol";

library ACOPoolLib {
	using SafeMath for uint256;
	
	struct OpenPositionData {
	    bool isDeposit;
	    bool isCall;
	    uint256 underlyingPrice;
	    uint256 baseVolatility;
	    uint256 underlyingPriceAdjustPercentage;
	    uint256 withdrawOpenPositionPenalty;
	    uint256 fee;
	    uint256 underlyingPrecision;
	    address underlying;
	    address strikeAsset;
	    address strategy;
	    address acoFactory;
	    address lendingToken;
	}
	
	struct QuoteData {
		address lendingToken;
		address strategy;
		uint256 baseVolatility;
		uint256 fee;
		uint256 underlyingPrice;
		uint256 underlyingPrecision;
		AcoData acoData;
		IACOPool2.PoolAcoPermissionConfigV2 acoPermissionConfig;
	}
	
	struct AcoData {
        bool isCall;
        uint256 strikePrice; 
        uint256 expiryTime;
        uint256 tokenAmount;
	    address underlying;
        address strikeAsset; 
	}
	
	uint256 public constant PERCENTAGE_PRECISION = 100000;
	
	function name(
        address underlying, 
        address strikeAsset, 
        bool isCall, 
        uint256 poolId
    ) public view returns(string memory) {
        return string(abi.encodePacked(
            "ACO POOL WRITE ",
            _getAssetSymbol(underlying),
            "-",
            _getAssetSymbol(strikeAsset),
            "-",
            (isCall ? "CALL #" : "PUT #"),
            _formatNumber(poolId)
        ));
    }
    
    function acoStrikeAndExpirationIsValid(
		uint256 strikePrice, 
        uint256 acoExpiryTime, 
		uint256 underlyingPrice,
        IACOPool2.PoolAcoPermissionConfigV2 memory acoPermissionConfig
    ) public view returns(bool) {
        return _acoExpirationIsValid(acoExpiryTime, acoPermissionConfig) && _acoStrikePriceIsValid(strikePrice, underlyingPrice, acoPermissionConfig);
    }

    function getBaseAssetsWithdrawWithLocked(
        uint256 shares,
        address underlying,
        address strikeAsset,
        bool isCall,
        uint256 totalSupply,
        address lendingToken
    ) public view returns(
        uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn
    ) {
		uint256 underlyingBalance = _getPoolBalanceOf(underlying);
		uint256 strikeAssetBalance;
		if (isCall || lendingToken == address(0)) {
		    strikeAssetBalance = _getPoolBalanceOf(strikeAsset);
		} else {
		    strikeAssetBalance = _getPoolBalanceOf(lendingToken);
		}
		
		underlyingWithdrawn = underlyingBalance.mul(shares).div(totalSupply);
		strikeAssetWithdrawn = strikeAssetBalance.mul(shares).div(totalSupply);
    }
    
    function getBaseWithdrawNoLockedData(
        uint256 shares,
        uint256 totalSupply,
        bool isCall,
        uint256 underlyingBalance, 
        uint256 strikeAssetBalance, 
        uint256 collateralBalance, 
        uint256 collateralLockedRedeemable
    ) public pure returns(
        uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn,
		bool isPossible
    ) {
		uint256 collateralAmount = shares.mul(collateralBalance).div(totalSupply);
		
		if (isCall) {
			underlyingWithdrawn = collateralAmount;
			strikeAssetWithdrawn = strikeAssetBalance.mul(shares).div(totalSupply);
			isPossible = (collateralAmount <= underlyingBalance.add(collateralLockedRedeemable));
		} else {
			strikeAssetWithdrawn = collateralAmount;
			underlyingWithdrawn = underlyingBalance.mul(shares).div(totalSupply);
			isPossible = (collateralAmount <= strikeAssetBalance.add(collateralLockedRedeemable));
		}
    }
    
    function getAmountToNoLockedWithdraw(
        uint256 shares, 
        uint256 totalSupply,
        uint256 underlyingBalance, 
        uint256 strikeAssetBalance,
        uint256 collateralBalance,
        uint256 minCollateral,
        bool isCall
    ) public pure returns(
        uint256 underlyingWithdrawn, 
        uint256 strikeAssetWithdrawn
    ) {
		uint256 collateralAmount = shares.mul(collateralBalance).div(totalSupply);
		require(collateralAmount >= minCollateral, "ACOPoolLib: The minimum collateral was not satisfied");

        if (isCall) {
			require(collateralAmount <= underlyingBalance, "ACOPoolLib: Collateral balance is not sufficient");
			underlyingWithdrawn = collateralAmount;
			strikeAssetWithdrawn = strikeAssetBalance.mul(shares).div(totalSupply);
        } else {
			require(collateralAmount <= strikeAssetBalance, "ACOPoolLib: Collateral balance is not sufficient");
			strikeAssetWithdrawn = collateralAmount;
			underlyingWithdrawn = underlyingBalance.mul(shares).div(totalSupply);
		}
    }
    
    function quote(QuoteData memory data) public view returns(
        uint256 swapPrice, 
        uint256 protocolFee, 
        uint256 volatility, 
        uint256 collateralAmount
    ) {
        AcoData memory acoData = data.acoData;
        require(_acoExpirationIsValid(acoData.expiryTime, data.acoPermissionConfig), "ACOPoolLib: Invalid ACO token expiration");
		require(_acoStrikePriceIsValid(acoData.strikePrice, data.underlyingPrice, data.acoPermissionConfig), "ACOPoolLib: Invalid ACO token strike price");

        uint256 collateralAvailable;
        (collateralAmount, collateralAvailable) = _getOrderSizeData(data.lendingToken, data.underlyingPrecision, acoData);
        uint256 calcPrice;
        (calcPrice, volatility) = _strategyQuote(data.strategy, data.underlyingPrice, data.baseVolatility, collateralAmount, collateralAvailable, acoData);
        (swapPrice, protocolFee) = _setSwapPriceAndFee(calcPrice, acoData.tokenAmount, data.fee, data.underlyingPrecision);
    }

	function getCollateralData(OpenPositionData memory data, address[] memory openAcos) public view returns(
        uint256 underlyingBalance, 
        uint256 strikeAssetBalance, 
        uint256 collateralBalance,
        uint256 collateralLocked,
        uint256 collateralOnOpenPosition,
        uint256 collateralLockedRedeemable
    ) {
		(underlyingBalance, strikeAssetBalance, collateralBalance) = _getBaseCollateralData(
            data.isDeposit, 
            data.underlying,
            data.strikeAsset,
            data.isCall,
            data.underlyingPrice,
            data.lendingToken,
            data.underlyingPriceAdjustPercentage,
            data.underlyingPrecision);
            
		(collateralLocked, collateralOnOpenPosition, collateralLockedRedeemable) = _poolOpenPositionCollateralBalance(data, openAcos);
	}

    function _formatNumber(uint256 value) internal pure returns(string memory) {
        if (value == 0) {
            return "0";
        }
        uint256 digits;
        uint256 temp = value;
        while (temp != 0) {
            temp /= 10;
            digits++;
        }
        bytes memory buffer = new bytes(digits);
        uint256 index = digits - 1;
        temp = value;
        for (uint256 i = 0; i < digits; ++i) {
            buffer[index] = bytes1(uint8(48 + temp % 10));
            if (index > 0) {
                --index;
            }
            temp /= 10;
        }
        return string(buffer);
    }
	
	function _getBaseCollateralData(
	    bool isDeposit,
	    address underlying,
	    address strikeAsset,
	    bool isCall,
	    uint256 underlyingPrice,
	    address lendingToken,
	    uint256 underlyingPriceAdjustPercentage,
	    uint256 underlyingPrecision
	) internal view returns(
        uint256 underlyingBalance, 
        uint256 strikeAssetBalance, 
        uint256 collateralBalance
    ) {
		underlyingBalance = _getPoolBalanceOf(underlying);
		
		if (isCall) {
		    strikeAssetBalance = _getPoolBalanceOf(strikeAsset);
			collateralBalance = underlyingBalance;
			if (isDeposit && strikeAssetBalance > 0) {
				uint256 priceAdjusted = _getUnderlyingPriceAdjusted(underlyingPrice, underlyingPriceAdjustPercentage, false); 
				collateralBalance = collateralBalance.add(strikeAssetBalance.mul(underlyingPrecision).div(priceAdjusted));
			}
		} else {
            if (lendingToken != address(0)) {
		        strikeAssetBalance = _getPoolBalanceOf(lendingToken);
            } else {
                strikeAssetBalance = _getPoolBalanceOf(strikeAsset);
            }
			collateralBalance = strikeAssetBalance;
			if (isDeposit && underlyingBalance > 0) {
				uint256 priceAdjusted = _getUnderlyingPriceAdjusted(underlyingPrice, underlyingPriceAdjustPercentage, true); 
				collateralBalance = collateralBalance.add(underlyingBalance.mul(priceAdjusted).div(underlyingPrecision));
			}
		}
	}

	function _poolOpenPositionCollateralBalance(OpenPositionData memory data, address[] memory openAcos) internal view returns(
        uint256 collateralLocked, 
        uint256 collateralOnOpenPosition,
        uint256 collateralLockedRedeemable
    ) {
		for (uint256 i = 0; i < openAcos.length; ++i) {
			address acoToken = openAcos[i];
            
            (uint256 locked, uint256 openPosition, uint256 lockedRedeemable) = _getOpenPositionCollateralBalance(acoToken, data);
            
            collateralLocked = collateralLocked.add(locked);
            collateralOnOpenPosition = collateralOnOpenPosition.add(openPosition);
            collateralLockedRedeemable = collateralLockedRedeemable.add(lockedRedeemable);
		}
		if (!data.isDeposit) {
			collateralOnOpenPosition = collateralOnOpenPosition.mul(PERCENTAGE_PRECISION.add(data.withdrawOpenPositionPenalty)).div(PERCENTAGE_PRECISION);
		}
	}
	
	function _getOpenPositionCollateralBalance(address acoToken, OpenPositionData memory data) internal view returns(
        uint256 collateralLocked, 
        uint256 collateralOnOpenPosition,
        uint256 collateralLockedRedeemable
    ) {
        AcoData memory acoData = _getOpenPositionCollateralExtraData(acoToken, data.acoFactory);
        collateralLocked = _getCollateralAmount(acoData.tokenAmount, acoData.strikePrice, acoData.isCall, data.underlyingPrecision);
        
        if (acoData.expiryTime > block.timestamp) {
    		(uint256 price,) = _strategyQuote(data.strategy, data.underlyingPrice, data.baseVolatility, 0, 1, acoData);
    		if (data.fee > 0) {
    		    price = price.mul(PERCENTAGE_PRECISION.add(data.fee)).div(PERCENTAGE_PRECISION);
    		}
    		if (acoData.isCall) {
    			uint256 priceAdjusted = _getUnderlyingPriceAdjusted(data.underlyingPrice, data.underlyingPriceAdjustPercentage, false); 
    			collateralOnOpenPosition = price.mul(acoData.tokenAmount).div(priceAdjusted);
    		} else {
    			collateralOnOpenPosition = price.mul(acoData.tokenAmount).div(data.underlyingPrecision);
    		}
        } else {
            collateralLockedRedeemable = collateralLocked;
        }
    }
    
	function _acoStrikePriceIsValid(
		uint256 strikePrice, 
		uint256 underlyingPrice,
		IACOPool2.PoolAcoPermissionConfigV2 memory acoPermissionConfig
	) internal pure returns(bool) {
	    return (
	        _validatePricePercentageTolerance(strikePrice, underlyingPrice, acoPermissionConfig.tolerancePriceBelowMin, false, true) &&
	        _validatePricePercentageTolerance(strikePrice, underlyingPrice, acoPermissionConfig.tolerancePriceBelowMax, false, false) &&
	        _validatePricePercentageTolerance(strikePrice, underlyingPrice, acoPermissionConfig.tolerancePriceAboveMin, true, false) &&
	        _validatePricePercentageTolerance(strikePrice, underlyingPrice, acoPermissionConfig.tolerancePriceAboveMax, true, true) &&
	        (acoPermissionConfig.minStrikePrice <= strikePrice) &&
	        (acoPermissionConfig.maxStrikePrice == 0 || acoPermissionConfig.maxStrikePrice >= strikePrice)
        );
	}
	
	function _validatePricePercentageTolerance(
	    uint256 strikePrice, 
	    uint256 underlyingPrice, 
	    int256 tolerance, 
	    bool isAbove,
	    bool shouldBeLesser
    ) internal pure returns(bool) {
        if (tolerance < int256(0)) {
            return true;
        } else {
            uint256 value;
            if (isAbove) {
                value = underlyingPrice.mul(PERCENTAGE_PRECISION.add(uint256(tolerance))).div(PERCENTAGE_PRECISION);
            } else {
                value = underlyingPrice.mul(PERCENTAGE_PRECISION.sub(uint256(tolerance))).div(PERCENTAGE_PRECISION);
            }
            if (shouldBeLesser) {
                return strikePrice <= value;
            } else {
                return strikePrice >= value;
            }
        }
    }

	function _acoExpirationIsValid(uint256 acoExpiryTime, IACOPool2.PoolAcoPermissionConfigV2 memory acoPermissionConfig) internal view returns(bool) {
		return acoExpiryTime >= block.timestamp.add(acoPermissionConfig.minExpiration) && acoExpiryTime <= block.timestamp.add(acoPermissionConfig.maxExpiration);
	}
    
    function _getCollateralAmount(
		uint256 tokenAmount,
		uint256 strikePrice,
		bool isCall,
		uint256 underlyingPrecision
	) private pure returns(uint256) {
        if (isCall) {
            return tokenAmount;
        } else if (tokenAmount > 0) {
            return tokenAmount.mul(strikePrice).div(underlyingPrecision);
        } else {
            return 0;
        }
    }
    
    function _getOrderSizeData(
        address lendingToken,
        uint256 underlyingPrecision,
        AcoData memory acoData
    ) private view returns(
        uint256 collateralAmount, 
        uint256 collateralAvailable
    ) {
        if (acoData.isCall) {
            collateralAvailable = _getPoolBalanceOf(acoData.underlying);
            collateralAmount = acoData.tokenAmount; 
        } else {
            if (lendingToken != address(0)) {
                collateralAvailable = _getPoolBalanceOf(lendingToken);
            } else {
                collateralAvailable = _getPoolBalanceOf(acoData.strikeAsset);
            }
            collateralAmount = _getCollateralAmount(acoData.tokenAmount, acoData.strikePrice, acoData.isCall, underlyingPrecision);
            require(collateralAmount > 0, "ACOPoolLib: The token amount is too small");
        }
        require(collateralAmount <= collateralAvailable, "ACOPoolLib: Insufficient liquidity");
    }
    
	function _strategyQuote(
        address strategy,
        uint256 underlyingPrice,
		uint256 baseVolatility,
        uint256 collateralAmount,
        uint256 collateralAvailable,
        AcoData memory acoData
    ) private view returns(uint256 swapPrice, uint256 volatility) {
        (swapPrice, volatility) = IACOPoolStrategy(strategy).quote(IACOPoolStrategy.OptionQuote(
			underlyingPrice,
            acoData.underlying, 
            acoData.strikeAsset, 
            acoData.isCall, 
            acoData.strikePrice, 
            acoData.expiryTime, 
            baseVolatility, 
            collateralAmount, 
            collateralAvailable
        ));
    }
    
    function _setSwapPriceAndFee(
        uint256 calcPrice, 
        uint256 tokenAmount, 
        uint256 fee,
        uint256 underlyingPrecision
    ) private pure returns(uint256 swapPrice, uint256 protocolFee) {
        
        swapPrice = calcPrice.mul(tokenAmount).div(underlyingPrecision);
        
        if (fee > 0) {
            protocolFee = swapPrice.mul(fee).div(PERCENTAGE_PRECISION);
			swapPrice = swapPrice.add(protocolFee);
        }
        require(swapPrice > 0, "ACOPoolLib: Invalid quoted price");
    }
    
    function _getOpenPositionCollateralExtraData(address acoToken, address acoFactory) private view returns(AcoData memory acoData) {
        (address underlying, address strikeAsset, bool isCall, uint256 strikePrice, uint256 expiryTime) = IACOFactory(acoFactory).acoTokenData(acoToken);
        uint256 tokenAmount = IACOToken(acoToken).currentCollateralizedTokens(address(this));
        acoData = AcoData(isCall, strikePrice, expiryTime, tokenAmount, underlying, strikeAsset);
    }
    
	function _getUnderlyingPriceAdjusted(uint256 underlyingPrice, uint256 underlyingPriceAdjustPercentage, bool isMaximum) private pure returns(uint256) {
		if (isMaximum) {
			return underlyingPrice.mul(PERCENTAGE_PRECISION.add(underlyingPriceAdjustPercentage)).div(PERCENTAGE_PRECISION);
		} else {
			return underlyingPrice.mul(PERCENTAGE_PRECISION.sub(underlyingPriceAdjustPercentage)).div(PERCENTAGE_PRECISION);
		}
    }
    
    function _getPoolBalanceOf(address asset) private view returns(uint256) {
        if (asset == address(0)) {
            return address(this).balance;
        } else {
            (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSelector(0x70a08231, address(this)));
            require(success, "ACOPoolLib::_getAssetBalanceOf");
            return abi.decode(returndata, (uint256));
        }
    }
    
    function _getAssetSymbol(address asset) private view returns(string memory) {
        if (asset == address(0)) {
            return "ETH";
        } else {
            (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSelector(0x95d89b41));
            require(success, "ACOPoolLib::_getAssetSymbol");
            return abi.decode(returndata, (string));
        }
    }
}

File 4 of 14: ERC20.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

import "./SafeMath.sol";
import "./IERC20.sol";


abstract contract ERC20 is IERC20 {
    using SafeMath for uint256;
    
    uint256 private _totalSupply;
    mapping (address => uint256) private _balances;
    mapping (address => mapping (address => uint256)) private _allowances;

    function name() public view virtual returns(string memory);
    function symbol() public view virtual returns(string memory);
    function decimals() public view virtual returns(uint8);

    function totalSupply() public view override virtual returns(uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) public view override virtual returns(uint256) {
        return _balances[account];
    }

    function allowance(address owner, address spender) public view override returns(uint256) {
        return _allowances[owner][spender];
    }

    function transfer(address recipient, uint256 amount) public override returns(bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) public override returns(bool) {
        _approveAction(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        _transfer(sender, recipient, amount);
        return true;
    }

    function approve(address spender, uint256 amount) public override returns(bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    function increaseAllowance(address spender, uint256 amount) public returns(bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(amount));
        return true;
    }

    function decreaseAllowance(address spender, uint256 amount) public returns(bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(amount));
        return true;
    }
    
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        _transferAction(sender, recipient, amount);
    }

    function _approve(address owner, address spender, uint256 amount) internal virtual {
        _approveAction(owner, spender, amount);
    }
    
    function _burnFrom(address account, uint256 amount) internal {
        _approveAction(account, msg.sender, _allowances[account][msg.sender].sub(amount));
        _burnAction(account, amount);
    }

    function _transferAction(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20::_transferAction: Invalid sender");
        require(recipient != address(0), "ERC20::_transferAction: Invalid recipient");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        
        emit Transfer(sender, recipient, amount);
    }
    
    function _approveAction(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "ERC20::_approveAction: Invalid owner");
        require(spender != address(0), "ERC20::_approveAction: Invalid spender");

        _allowances[owner][spender] = amount;
        
        emit Approval(owner, spender, amount);
    }
    
    function _mintAction(address account, uint256 amount) internal {
        require(account != address(0), "ERC20::_mintAction: Invalid account");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        
        emit Transfer(address(0), account, amount);
    }

    function _burnAction(address account, uint256 amount) internal {
        require(account != address(0), "ERC20::_burnAction: Invalid account");

        _balances[account] = _balances[account].sub(amount);
        _totalSupply = _totalSupply.sub(amount);
        
        emit Transfer(account, address(0), amount);
    }
}

File 5 of 14: IACOAssetConverterHelper.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

interface IACOAssetConverterHelper {
    function setPairTolerancePercentage(address baseAsset, address quoteAsset, uint256 tolerancePercentage) external;
    function setAggregator(address baseAsset, address quoteAsset, address aggregator) external;
    function setUniswapMiddleRoute(address baseAsset, address quoteAsset, address[] calldata uniswapMiddleRoute) external;
    function withdrawStuckAsset(address asset, address destination) external;
    function hasAggregator(address baseAsset, address quoteAsset) external view returns(bool);
    function getPairData(address baseAsset, address quoteAsset) external view returns(address, uint256, uint256, uint256);
    function getUniswapMiddleRouteByIndex(address baseAsset, address quoteAsset, uint256 index) external view returns(address);
    function getPrice(address baseAsset, address quoteAsset) external view returns(uint256);
    function getPriceWithTolerance(address baseAsset, address quoteAsset, bool isMinimumPrice) external view returns(uint256);
    function getExpectedAmountOutToSwapExactAmountIn(address assetToSold, address assetToBuy, uint256 amountToBuy) external view returns(uint256);
    function getExpectedAmountOutToSwapExactAmountInWithSpecificTolerance(address assetToSold, address assetToBuy, uint256 amountToBuy, uint256 tolerancePercentage) external view returns(uint256);
    function swapExactAmountOut(address assetToSold, address assetToBuy, uint256 amountToSold) external payable returns(uint256);
    function swapExactAmountOutWithSpecificTolerance(address assetToSold, address assetToBuy, uint256 amountToSold, uint256 tolerancePercentage) external payable returns(uint256);
    function swapExactAmountOutWithMinAmountToReceive(address assetToSold, address assetToBuy, uint256 amountToSold, uint256 minAmountToReceive) external payable returns(uint256);
    function swapExactAmountIn(address assetToSold, address assetToBuy, uint256 amountToBuy) external payable returns(uint256);
    function swapExactAmountInWithSpecificTolerance(address assetToSold, address assetToBuy, uint256 amountToBuy, uint256 tolerancePercentage) external payable returns(uint256);
    function swapExactAmountInWithMaxAmountToSold(address assetToSold, address assetToBuy, uint256 amountToBuy, uint256 maxAmountToSold) external payable returns(uint256);
}

File 6 of 14: IACOFactory.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

interface IACOFactory {
	function init(address _factoryAdmin, address _acoTokenImplementation, uint256 _acoFee, address _acoFeeDestination) external;
    function acoFee() external view returns(uint256);
    function factoryAdmin() external view returns(address);
    function acoTokenImplementation() external view returns(address);
    function acoFeeDestination() external view returns(address);
    function acoTokenData(address acoToken) external view returns(address, address, bool, uint256, uint256);
    function creators(address acoToken) external view returns(address);
    function createAcoToken(address underlying, address strikeAsset, bool isCall, uint256 strikePrice, uint256 expiryTime, uint256 maxExercisedAccounts) external returns(address);
    function newAcoToken(address underlying, address strikeAsset, bool isCall, uint256 strikePrice, uint256 expiryTime) external returns(address);
    function getAcoToken(address underlying, address strikeAsset, bool isCall, uint256 strikePrice, uint256 expiryTime) external view returns(address);
    function setFactoryAdmin(address newFactoryAdmin) external;
    function setAcoTokenImplementation(address newAcoTokenImplementation) external;
    function setAcoFee(uint256 newAcoFee) external;
    function setAcoFeeDestination(address newAcoFeeDestination) external;
}

File 7 of 14: IACOPool2.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

import './IERC20.sol';

interface IACOPool2 is IERC20 {

    struct InitData {
        address acoFactory;
        address lendingPool;
        address underlying;
        address strikeAsset;
        bool isCall; 
        uint256 baseVolatility;  
        address admin;
        address strategy;  
        bool isPrivate;
        uint256 poolId;
        PoolAcoPermissionConfigV2 acoPermissionConfigV2;
        PoolProtocolConfig protocolConfig;
    }

	struct AcoData {
        bool open;
        uint256 valueSold;
        uint256 collateralLocked;
        uint256 collateralRedeemed;
        uint256 index;
		uint256 openIndex;
    }
    
    struct PoolAcoPermissionConfig {
        uint256 tolerancePriceBelowMin;
        uint256 tolerancePriceBelowMax;
        uint256 tolerancePriceAboveMin;
        uint256 tolerancePriceAboveMax;
        uint256 minExpiration;
        uint256 maxExpiration;
    }
    
    struct PoolAcoPermissionConfigV2 {
        int256 tolerancePriceBelowMin;
        int256 tolerancePriceBelowMax;
        int256 tolerancePriceAboveMin;
        int256 tolerancePriceAboveMax;
        uint256 minStrikePrice;
        uint256 maxStrikePrice;
        uint256 minExpiration;
        uint256 maxExpiration;
    }
    
    struct PoolProtocolConfig {
        uint16 lendingPoolReferral;
        uint256 withdrawOpenPositionPenalty;
        uint256 underlyingPriceAdjustPercentage;
        uint256 fee;
        uint256 maximumOpenAco;
        address feeDestination;
        address assetConverter;
    }
    
	function init(InitData calldata initData) external;
	function numberOfAcoTokensNegotiated() external view returns(uint256);
    function numberOfOpenAcoTokens() external view returns(uint256);
    function collateral() external view returns(address);
	function canSwap(address acoToken) external view returns(bool);
	function quote(address acoToken, uint256 tokenAmount) external view returns(
		uint256 swapPrice, 
		uint256 protocolFee, 
		uint256 underlyingPrice, 
		uint256 volatility
	);
	function getDepositShares(uint256 collateralAmount) external view returns(uint256 shares);
	function getWithdrawNoLockedData(uint256 shares) external view returns(
		uint256 underlyingWithdrawn, 
		uint256 strikeAssetWithdrawn, 
		bool isPossible
	);
	function getWithdrawWithLocked(uint256 shares) external view returns(
		uint256 underlyingWithdrawn, 
		uint256 strikeAssetWithdrawn, 
		address[] memory acos, 
		uint256[] memory acosAmount
	);
	function getGeneralData() external view returns(
        uint256 underlyingBalance,
		uint256 strikeAssetBalance,
		uint256 collateralLocked,
        uint256 collateralOnOpenPosition,
        uint256 collateralLockedRedeemable,
        uint256 poolSupply
    );
	function setLendingPoolReferral(uint16 newLendingPoolReferral) external;
	function setPoolDataForAcoPermission(uint256 newTolerancePriceBelow, uint256 newTolerancePriceAbove, uint256 newMinExpiration, uint256 newMaxExpiration) external;
	function setAcoPermissionConfig(PoolAcoPermissionConfig calldata newConfig) external;
	function setAcoPermissionConfigV2(PoolAcoPermissionConfigV2 calldata newConfig) external;
	function setPoolAdmin(uint256 newAdmin) external;
	function setProtocolConfig(PoolProtocolConfig calldata newConfig) external;
	function startLendingPool(address newLendingPool) external;
	function setFeeData(address newFeeDestination, uint256 newFee) external;
	function setAssetConverter(address newAssetConverter) external;
    function setTolerancePriceBelow(uint256 newTolerancePriceBelow) external;
    function setTolerancePriceAbove(uint256 newTolerancePriceAbove) external;
    function setMinExpiration(uint256 newMinExpiration) external;
    function setMaxExpiration(uint256 newMaxExpiration) external;
    function setFee(uint256 newFee) external;
    function setFeeDestination(address newFeeDestination) external;
	function setWithdrawOpenPositionPenalty(uint256 newWithdrawOpenPositionPenalty) external;
	function setUnderlyingPriceAdjustPercentage(uint256 newUnderlyingPriceAdjustPercentage) external;
	function setMaximumOpenAco(uint256 newMaximumOpenAco) external;
	function setStrategy(address newStrategy) external;
	function setBaseVolatility(uint256 newBaseVolatility) external;
	function setValidAcoCreator(address acoCreator, bool newPermission) external;
	function setForbiddenAcoCreator(address acoCreator, bool newStatus) external;
    function withdrawStuckToken(address token, address destination) external;
    function deposit(uint256 collateralAmount, uint256 minShares, address to, bool isLendingToken) external payable returns(uint256 acoPoolTokenAmount);
	function depositWithGasToken(uint256 collateralAmount, uint256 minShares, address to, bool isLendingToken) external payable returns(uint256 acoPoolTokenAmount);
	function withdrawNoLocked(uint256 shares, uint256 minCollateral, address account, bool withdrawLendingToken) external returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn
	);
	function withdrawNoLockedWithGasToken(uint256 shares, uint256 minCollateral, address account, bool withdrawLendingToken) external returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn
	);
    function withdrawWithLocked(uint256 shares, address account, bool withdrawLendingToken) external returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn,
		address[] memory acos,
		uint256[] memory acosAmount
	);
	function withdrawWithLockedWithGasToken(uint256 shares, address account, bool withdrawLendingToken) external returns (
		uint256 underlyingWithdrawn,
		uint256 strikeAssetWithdrawn,
		address[] memory acos,
		uint256[] memory acosAmount
	);
    function swap(address acoToken, uint256 tokenAmount, uint256 restriction, address to, uint256 deadline) external payable;
    function swapWithGasToken(address acoToken, uint256 tokenAmount, uint256 restriction, address to, uint256 deadline) external payable;
    function redeemACOTokens() external;
	function redeemACOToken(address acoToken) external;
    function restoreCollateral() external;
    function lendCollateral() external;
}

File 8 of 14: IACOPoolFactory2.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

interface IACOPoolFactory2 {
    function factoryAdmin() external view returns(address);
    function acoPoolImplementation() external view returns(address);
    function acoFactory() external view returns(address);
	function assetConverterHelper() external view returns(address);
    function acoPoolFee() external view returns(uint256);
    function acoPoolFeeDestination() external view returns(address);
	function acoPoolUnderlyingPriceAdjustPercentage() external view returns(uint256);
	function acoPoolWithdrawOpenPositionPenalty() external view returns(uint256);
    function acoPoolMaximumOpenAco() external view returns(uint256);
    function poolAdminPermission(address account) external view returns(bool);
    function strategyPermitted(address strategy) external view returns(bool);
    function acoPoolBasicData(address acoPool) external view returns(address underlying, address strikeAsset, bool isCall);
}

File 9 of 14: IACOPoolStrategy.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

interface IACOPoolStrategy {
    
    struct OptionQuote {
        uint256 underlyingPrice;
        address underlying;
        address strikeAsset;
        bool isCallOption;
        uint256 strikePrice; 
        uint256 expiryTime;
        uint256 baseVolatility;
        uint256 collateralOrderAmount;
        uint256 collateralAvailable;
    }

    function quote(OptionQuote calldata quoteData) external view returns(uint256 optionPrice, uint256 volatility);
}

File 10 of 14: IACOToken.sol
// SPDX-License-Identifier: None
pragma solidity 0.8.4;

import "./IERC20.sol";

interface IACOToken is IERC20 {
	function init(address _underlying, address _strikeAsset, bool _isCall, uint256 _strikePrice, uint256 _expiryTime, uint256 _acoFee, address payable _feeDestination, uint256 _maxExercisedAccounts) external;
    function name() external view returns(string memory);
    function symbol() external view returns(string memory);
    function decimals() external view returns(uint8);
    function underlying() external view returns (address);
    function strikeAsset() external view returns (address);
    function feeDestination() external view returns (address);
    function isCall() external view returns (bool);
    function strikePrice() external view returns (uint256);
    function expiryTime() external view returns (uint256);
    function totalCollateral() external view returns (uint256);
    function acoFee() external view returns (uint256);
	function maxExercisedAccounts() external view returns (uint256);
    function underlyingSymbol() external view returns (string memory);
    function strikeAssetSymbol() external view returns (string memory);
    function underlyingDecimals() external view returns (uint8);
    function strikeAssetDecimals() external view returns (uint8);
    function currentCollateral(address account) external view returns(uint256);
    function unassignableCollateral(address account) external view returns(uint256);
    function assignableCollateral(address account) external view returns(uint256);
    function currentCollateralizedTokens(address account) external view returns(uint256);
    function unassignableTokens(address account) external view returns(uint256);
    function assignableTokens(address account) external view returns(uint256);
    function getCollateralAmount(uint256 tokenAmount) external view returns(uint256);
    function getTokenAmount(uint256 collateralAmount) external view returns(uint256);
    function getBaseExerciseData(uint256 tokenAmount) external view returns(address, uint256);
    function numberOfAccountsWithCollateral() external view returns(uint256);
    function getCollateralOnExercise(uint256 tokenAmount) external view returns(uint256, uint256);
    function collateral() external view returns(address);
    function mintPayable() external payable returns(uint256);
    function mintToPayable(address account) external payable returns(uint256);
    function mint(uint256 collateralAmount) external returns(uint256);
    function mintTo(address account, uint256 collateralAmount) external returns(uint256);
    function burn(uint256 tokenAmount) external returns(uint256);
    function burnFrom(address account, uint256 tokenAmount) external returns(uint256);
    function redeem() external returns(uint256);
    function redeemFrom(address account) external returns(uint256);
    function exercise(uint256 tokenAmount, uint256 salt) external payable returns(uint256);
    function exerciseFrom(address account, uint256 tokenAmount, uint256 salt) external payable returns(uint256);
    function exerciseAccounts(uint256 tokenAmount, address[] calldata accounts) external payable returns(uint256);
    function exerciseAccountsFrom(address account, uint256 tokenAmount, address[] calldata accounts) external payable returns(uint256);
    function transferCollateralOwnership(address recipient, uint256 tokenCollateralizedAmount) external;
}

File 11 of 14: IERC20.sol
// Contract on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

/**
 * @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 12 of 14: ILendingPool.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.4;

library DataTypes {
  // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
  struct ReserveData {
    //stores the reserve configuration
    ReserveConfigurationMap configuration;
    //the liquidity index. Expressed in ray
    uint128 liquidityIndex;
    //variable borrow index. Expressed in ray
    uint128 variableBorrowIndex;
    //the current supply rate. Expressed in ray
    uint128 currentLiquidityRate;
    //the current variable borrow rate. Expressed in ray
    uint128 currentVariableBorrowRate;
    //the current stable borrow rate. Expressed in ray
    uint128 currentStableBorrowRate;
    uint40 lastUpdateTimestamp;
    //tokens addresses
    address aTokenAddress;
    address stableDebtTokenAddress;
    address variableDebtTokenAddress;
    //address of the interest rate strategy
    address interestRateStrategyAddress;
    //the id of the reserve. Represents the position in the list of the active reserves
    uint8 id;
  }

  struct ReserveConfigurationMap {
    //bit 0-15: LTV
    //bit 16-31: Liq. threshold
    //bit 32-47: Liq. bonus
    //bit 48-55: Decimals
    //bit 56: Reserve is active
    //bit 57: reserve is frozen
    //bit 58: borrowing is enabled
    //bit 59: stable rate borrowing enabled
    //bit 60-63: reserved
    //bit 64-79: reserve factor
    uint256 data;
  }

  struct UserConfigurationMap {
    uint256 data;
  }

  enum InterestRateMode {NONE, STABLE, VARIABLE}
}


/**
 * @title LendingPoolAddressesProvider contract
 * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles
 * - Acting also as factory of proxies and admin of those, so with right to change its implementations
 * - Owned by the Aave Governance
 * @author Aave
 **/
interface ILendingPoolAddressesProvider {
  event MarketIdSet(string newMarketId);
  event LendingPoolUpdated(address indexed newAddress);
  event ConfigurationAdminUpdated(address indexed newAddress);
  event EmergencyAdminUpdated(address indexed newAddress);
  event LendingPoolConfiguratorUpdated(address indexed newAddress);
  event LendingPoolCollateralManagerUpdated(address indexed newAddress);
  event PriceOracleUpdated(address indexed newAddress);
  event LendingRateOracleUpdated(address indexed newAddress);
  event ProxyCreated(bytes32 id, address indexed newAddress);
  event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);

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

  function setMarketId(string calldata marketId) external;

  function setAddress(bytes32 id, address newAddress) external;

  function setAddressAsProxy(bytes32 id, address impl) external;

  function getAddress(bytes32 id) external view returns (address);

  function getLendingPool() external view returns (address);

  function setLendingPoolImpl(address pool) external;

  function getLendingPoolConfigurator() external view returns (address);

  function setLendingPoolConfiguratorImpl(address configurator) external;

  function getLendingPoolCollateralManager() external view returns (address);

  function setLendingPoolCollateralManager(address manager) external;

  function getPoolAdmin() external view returns (address);

  function setPoolAdmin(address admin) external;

  function getEmergencyAdmin() external view returns (address);

  function setEmergencyAdmin(address admin) external;

  function getPriceOracle() external view returns (address);

  function setPriceOracle(address priceOracle) external;

  function getLendingRateOracle() external view returns (address);

  function setLendingRateOracle(address lendingRateOracle) external;
}


interface ILendingPool {
  /**
   * @dev Emitted on deposit()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address initiating the deposit
   * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
   * @param amount The amount deposited
   * @param referral The referral code used
   **/
  event Deposit(
    address indexed reserve,
    address user,
    address indexed onBehalfOf,
    uint256 amount,
    uint16 indexed referral
  );

  /**
   * @dev Emitted on withdraw()
   * @param reserve The address of the underlyng asset being withdrawn
   * @param user The address initiating the withdrawal, owner of aTokens
   * @param to Address that will receive the underlying
   * @param amount The amount to be withdrawn
   **/
  event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);

  /**
   * @dev Emitted on borrow() and flashLoan() when debt needs to be opened
   * @param reserve The address of the underlying asset being borrowed
   * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
   * initiator of the transaction on flashLoan()
   * @param onBehalfOf The address that will be getting the debt
   * @param amount The amount borrowed out
   * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable
   * @param borrowRate The numeric rate at which the user has borrowed
   * @param referral The referral code used
   **/
  event Borrow(
    address indexed reserve,
    address user,
    address indexed onBehalfOf,
    uint256 amount,
    uint256 borrowRateMode,
    uint256 borrowRate,
    uint16 indexed referral
  );

  /**
   * @dev Emitted on repay()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The beneficiary of the repayment, getting his debt reduced
   * @param repayer The address of the user initiating the repay(), providing the funds
   * @param amount The amount repaid
   **/
  event Repay(
    address indexed reserve,
    address indexed user,
    address indexed repayer,
    uint256 amount
  );

  /**
   * @dev Emitted on swapBorrowRateMode()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address of the user swapping his rate mode
   * @param rateMode The rate mode that the user wants to swap to
   **/
  event Swap(address indexed reserve, address indexed user, uint256 rateMode);

  /**
   * @dev Emitted on setUserUseReserveAsCollateral()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address of the user enabling the usage as collateral
   **/
  event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);

  /**
   * @dev Emitted on setUserUseReserveAsCollateral()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address of the user enabling the usage as collateral
   **/
  event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);

  /**
   * @dev Emitted on rebalanceStableBorrowRate()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address of the user for which the rebalance has been executed
   **/
  event RebalanceStableBorrowRate(address indexed reserve, address indexed user);

  /**
   * @dev Emitted on flashLoan()
   * @param target The address of the flash loan receiver contract
   * @param initiator The address initiating the flash loan
   * @param asset The address of the asset being flash borrowed
   * @param amount The amount flash borrowed
   * @param premium The fee flash borrowed
   * @param referralCode The referral code used
   **/
  event FlashLoan(
    address indexed target,
    address indexed initiator,
    address indexed asset,
    uint256 amount,
    uint256 premium,
    uint16 referralCode
  );

  /**
   * @dev Emitted when the pause is triggered.
   */
  event Paused();

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

  /**
   * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
   * LendingPoolCollateral manager using a DELEGATECALL
   * This allows to have the events in the generated ABI for LendingPool.
   * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
   * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
   * @param user The address of the borrower getting liquidated
   * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
   * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator
   * @param liquidator The address of the liquidator
   * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
   * to receive the underlying collateral asset directly
   **/
  event LiquidationCall(
    address indexed collateralAsset,
    address indexed debtAsset,
    address indexed user,
    uint256 debtToCover,
    uint256 liquidatedCollateralAmount,
    address liquidator,
    bool receiveAToken
  );

  /**
   * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared
   * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
   * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
   * gets added to the LendingPool ABI
   * @param reserve The address of the underlying asset of the reserve
   * @param liquidityRate The new liquidity rate
   * @param stableBorrowRate The new stable borrow rate
   * @param variableBorrowRate The new variable borrow rate
   * @param liquidityIndex The new liquidity index
   * @param variableBorrowIndex The new variable borrow index
   **/
  event ReserveDataUpdated(
    address indexed reserve,
    uint256 liquidityRate,
    uint256 stableBorrowRate,
    uint256 variableBorrowRate,
    uint256 liquidityIndex,
    uint256 variableBorrowIndex
  );

  /**
   * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
   * - E.g. User deposits 100 USDC and gets in return 100 aUSDC
   * @param asset The address of the underlying asset to deposit
   * @param amount The amount to be deposited
   * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
   *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
   *   is a different wallet
   * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
   *   0 if the action is executed directly by the user, without any middle-man
   **/
  function deposit(
    address asset,
    uint256 amount,
    address onBehalfOf,
    uint16 referralCode
  ) external;

  /**
   * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
   * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
   * @param asset The address of the underlying asset to withdraw
   * @param amount The underlying amount to be withdrawn
   *   - Send the value type(uint256).max in order to withdraw the whole aToken balance
   * @param to Address that will receive the underlying, same as msg.sender if the user
   *   wants to receive it on his own wallet, or a different address if the beneficiary is a
   *   different wallet
   * @return The final amount withdrawn
   **/
  function withdraw(
    address asset,
    uint256 amount,
    address to
  ) external returns (uint256);

  /**
   * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
   * already deposited enough collateral, or he was given enough allowance by a credit delegator on the
   * corresponding debt token (StableDebtToken or VariableDebtToken)
   * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
   *   and 100 stable/variable debt tokens, depending on the `interestRateMode`
   * @param asset The address of the underlying asset to borrow
   * @param amount The amount to be borrowed
   * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
   * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
   *   0 if the action is executed directly by the user, without any middle-man
   * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself
   * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
   * if he has been given credit delegation allowance
   **/
  function borrow(
    address asset,
    uint256 amount,
    uint256 interestRateMode,
    uint16 referralCode,
    address onBehalfOf
  ) external;

  /**
   * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
   * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
   * @param asset The address of the borrowed underlying asset previously borrowed
   * @param amount The amount to repay
   * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
   * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
   * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
   * user calling the function if he wants to reduce/remove his own debt, or the address of any other
   * other borrower whose debt should be removed
   * @return The final amount repaid
   **/
  function repay(
    address asset,
    uint256 amount,
    uint256 rateMode,
    address onBehalfOf
  ) external returns (uint256);

  /**
   * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa
   * @param asset The address of the underlying asset borrowed
   * @param rateMode The rate mode that the user wants to swap to
   **/
  function swapBorrowRateMode(address asset, uint256 rateMode) external;

  /**
   * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
   * - Users can be rebalanced if the following conditions are satisfied:
   *     1. Usage ratio is above 95%
   *     2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
   *        borrowed at a stable rate and depositors are not earning enough
   * @param asset The address of the underlying asset borrowed
   * @param user The address of the user to be rebalanced
   **/
  function rebalanceStableBorrowRate(address asset, address user) external;

  /**
   * @dev Allows depositors to enable/disable a specific deposited asset as collateral
   * @param asset The address of the underlying asset deposited
   * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise
   **/
  function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;

  /**
   * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
   * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
   *   a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
   * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
   * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
   * @param user The address of the borrower getting liquidated
   * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
   * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
   * to receive the underlying collateral asset directly
   **/
  function liquidationCall(
    address collateralAsset,
    address debtAsset,
    address user,
    uint256 debtToCover,
    bool receiveAToken
  ) external;

  /**
   * @dev Allows smartcontracts to access the liquidity of the pool within one transaction,
   * as long as the amount taken plus a fee is returned.
   * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.
   * For further details please visit https://developers.aave.com
   * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface
   * @param assets The addresses of the assets being flash-borrowed
   * @param amounts The amounts amounts being flash-borrowed
   * @param modes Types of the debt to open if the flash loan is not returned:
   *   0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
   *   1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
   *   2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
   * @param onBehalfOf The address  that will receive the debt in the case of using on `modes` 1 or 2
   * @param params Variadic packed params to pass to the receiver as extra information
   * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
   *   0 if the action is executed directly by the user, without any middle-man
   **/
  function flashLoan(
    address receiverAddress,
    address[] calldata assets,
    uint256[] calldata amounts,
    uint256[] calldata modes,
    address onBehalfOf,
    bytes calldata params,
    uint16 referralCode
  ) external;

  /**
   * @dev Returns the user account data across all the reserves
   * @param user The address of the user
   * @return totalCollateralETH the total collateral in ETH of the user
   * @return totalDebtETH the total debt in ETH of the user
   * @return availableBorrowsETH the borrowing power left of the user
   * @return currentLiquidationThreshold the liquidation threshold of the user
   * @return ltv the loan to value of the user
   * @return healthFactor the current health factor of the user
   **/
  function getUserAccountData(address user)
    external
    view
    returns (
      uint256 totalCollateralETH,
      uint256 totalDebtETH,
      uint256 availableBorrowsETH,
      uint256 currentLiquidationThreshold,
      uint256 ltv,
      uint256 healthFactor
    );

  function initReserve(
    address reserve,
    address aTokenAddress,
    address stableDebtAddress,
    address variableDebtAddress,
    address interestRateStrategyAddress
  ) external;

  function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
    external;

  function setConfiguration(address reserve, uint256 configuration) external;

  /**
   * @dev Returns the configuration of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The configuration of the reserve
   **/
  function getConfiguration(address asset)
    external
    view
    returns (DataTypes.ReserveConfigurationMap memory);

  /**
   * @dev Returns the configuration of the user across all the reserves
   * @param user The user address
   * @return The configuration of the user
   **/
  function getUserConfiguration(address user)
    external
    view
    returns (DataTypes.UserConfigurationMap memory);

  /**
   * @dev Returns the normalized income normalized income of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The reserve's normalized income
   */
  function getReserveNormalizedIncome(address asset) external view returns (uint256);

  /**
   * @dev Returns the normalized variable debt per unit of asset
   * @param asset The address of the underlying asset of the reserve
   * @return The reserve normalized variable debt
   */
  function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);

  /**
   * @dev Returns the state and configuration of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The state of the reserve
   **/
  function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);

  function finalizeTransfer(
    address asset,
    address from,
    address to,
    uint256 amount,
    uint256 balanceFromAfter,
    uint256 balanceToBefore
  ) external;

  function getReservesList() external view returns (address[] memory);

  function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);

  function setPause(bool val) external;

  function paused() external view returns (bool);
}

File 13 of 14: Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

/*
 * @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 GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return payable(msg.sender);
    }

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

/**
 * @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.
 */
contract Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function init() internal {
        require(_owner == address(0), "Ownable: Contract initialized");
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view 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 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;
    }
}

File 14 of 14: SafeMath.sol
// Contract on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"acoToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"valueSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralLocked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralRedeemed","type":"uint256"}],"name":"ACORedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"LendCollateral","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":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralRestored","type":"uint256"}],"name":"RestoreCollateral","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"int256","name":"tolerancePriceBelowMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceBelowMax","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMax","type":"int256"},{"internalType":"uint256","name":"minStrikePrice","type":"uint256"},{"internalType":"uint256","name":"maxStrikePrice","type":"uint256"},{"internalType":"uint256","name":"minExpiration","type":"uint256"},{"internalType":"uint256","name":"maxExpiration","type":"uint256"}],"indexed":false,"internalType":"struct IACOPool2.PoolAcoPermissionConfigV2","name":"oldConfig","type":"tuple"},{"components":[{"internalType":"int256","name":"tolerancePriceBelowMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceBelowMax","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMax","type":"int256"},{"internalType":"uint256","name":"minStrikePrice","type":"uint256"},{"internalType":"uint256","name":"maxStrikePrice","type":"uint256"},{"internalType":"uint256","name":"minExpiration","type":"uint256"},{"internalType":"uint256","name":"maxExpiration","type":"uint256"}],"indexed":false,"internalType":"struct IACOPool2.PoolAcoPermissionConfigV2","name":"newConfig","type":"tuple"}],"name":"SetAcoPermissionConfigV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldBaseVolatility","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newBaseVolatility","type":"uint256"}],"name":"SetBaseVolatility","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"bool","name":"previousStatus","type":"bool"},{"indexed":true,"internalType":"bool","name":"newStatus","type":"bool"}],"name":"SetForbiddenAcoCreator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"SetPoolAdmin","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"lendingPoolReferral","type":"uint16"},{"internalType":"uint256","name":"withdrawOpenPositionPenalty","type":"uint256"},{"internalType":"uint256","name":"underlyingPriceAdjustPercentage","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"maximumOpenAco","type":"uint256"},{"internalType":"address","name":"feeDestination","type":"address"},{"internalType":"address","name":"assetConverter","type":"address"}],"indexed":false,"internalType":"struct IACOPool2.PoolProtocolConfig","name":"oldConfig","type":"tuple"},{"components":[{"internalType":"uint16","name":"lendingPoolReferral","type":"uint16"},{"internalType":"uint256","name":"withdrawOpenPositionPenalty","type":"uint256"},{"internalType":"uint256","name":"underlyingPriceAdjustPercentage","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"maximumOpenAco","type":"uint256"},{"internalType":"address","name":"feeDestination","type":"address"},{"internalType":"address","name":"assetConverter","type":"address"}],"indexed":false,"internalType":"struct IACOPool2.PoolProtocolConfig","name":"newConfig","type":"tuple"}],"name":"SetProtocolConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldStrategy","type":"address"},{"indexed":true,"internalType":"address","name":"newStrategy","type":"address"}],"name":"SetStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"bool","name":"previousPermission","type":"bool"},{"indexed":true,"internalType":"bool","name":"newPermission","type":"bool"}],"name":"SetValidAcoCreator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newLendingPool","type":"address"}],"name":"StartLendingPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"acoToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"underlyingPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"volatility","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"bool","name":"noLocked","type":"bool"},{"indexed":false,"internalType":"uint256","name":"underlyingWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"strikeAssetWithdrawn","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"acos","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"acosAmount","type":"uint256[]"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"acoData","outputs":[{"internalType":"bool","name":"open","type":"bool"},{"internalType":"uint256","name":"valueSold","type":"uint256"},{"internalType":"uint256","name":"collateralLocked","type":"uint256"},{"internalType":"uint256","name":"collateralRedeemed","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"openIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acoFactory","outputs":[{"internalType":"contract IACOFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acoPermissionConfigV2","outputs":[{"internalType":"int256","name":"tolerancePriceBelowMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceBelowMax","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMax","type":"int256"},{"internalType":"uint256","name":"minStrikePrice","type":"uint256"},{"internalType":"uint256","name":"maxStrikePrice","type":"uint256"},{"internalType":"uint256","name":"minExpiration","type":"uint256"},{"internalType":"uint256","name":"maxExpiration","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"acoTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseVolatility","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"acoToken","type":"address"}],"name":"canSwap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"minShares","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"isLendingToken","type":"bool"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"forbiddenAcoCreators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"getDepositShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGeneralData","outputs":[{"internalType":"uint256","name":"underlyingBalance","type":"uint256"},{"internalType":"uint256","name":"strikeAssetBalance","type":"uint256"},{"internalType":"uint256","name":"collateralLocked","type":"uint256"},{"internalType":"uint256","name":"collateralOnOpenPosition","type":"uint256"},{"internalType":"uint256","name":"collateralLockedRedeemable","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"getWithdrawNoLockedData","outputs":[{"internalType":"uint256","name":"underlyingWithdrawn","type":"uint256"},{"internalType":"uint256","name":"strikeAssetWithdrawn","type":"uint256"},{"internalType":"bool","name":"isPossible","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"getWithdrawWithLocked","outputs":[{"internalType":"uint256","name":"underlyingWithdrawn","type":"uint256"},{"internalType":"uint256","name":"strikeAssetWithdrawn","type":"uint256"},{"internalType":"address[]","name":"acos","type":"address[]"},{"internalType":"uint256[]","name":"acosAmount","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"acoFactory","type":"address"},{"internalType":"address","name":"lendingPool","type":"address"},{"internalType":"address","name":"underlying","type":"address"},{"internalType":"address","name":"strikeAsset","type":"address"},{"internalType":"bool","name":"isCall","type":"bool"},{"internalType":"uint256","name":"baseVolatility","type":"uint256"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"bool","name":"isPrivate","type":"bool"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"components":[{"internalType":"int256","name":"tolerancePriceBelowMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceBelowMax","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMax","type":"int256"},{"internalType":"uint256","name":"minStrikePrice","type":"uint256"},{"internalType":"uint256","name":"maxStrikePrice","type":"uint256"},{"internalType":"uint256","name":"minExpiration","type":"uint256"},{"internalType":"uint256","name":"maxExpiration","type":"uint256"}],"internalType":"struct IACOPool2.PoolAcoPermissionConfigV2","name":"acoPermissionConfigV2","type":"tuple"},{"components":[{"internalType":"uint16","name":"lendingPoolReferral","type":"uint16"},{"internalType":"uint256","name":"withdrawOpenPositionPenalty","type":"uint256"},{"internalType":"uint256","name":"underlyingPriceAdjustPercentage","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"maximumOpenAco","type":"uint256"},{"internalType":"address","name":"feeDestination","type":"address"},{"internalType":"address","name":"assetConverter","type":"address"}],"internalType":"struct IACOPool2.PoolProtocolConfig","name":"protocolConfig","type":"tuple"}],"internalType":"struct IACOPool2.InitData","name":"initData","type":"tuple"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPrivate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lendCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lendingPool","outputs":[{"internalType":"contract ILendingPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberOfAcoTokensNegotiated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberOfOpenAcoTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"openAcos","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolConfig","outputs":[{"internalType":"uint16","name":"lendingPoolReferral","type":"uint16"},{"internalType":"uint256","name":"withdrawOpenPositionPenalty","type":"uint256"},{"internalType":"uint256","name":"underlyingPriceAdjustPercentage","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"maximumOpenAco","type":"uint256"},{"internalType":"address","name":"feeDestination","type":"address"},{"internalType":"address","name":"assetConverter","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"acoToken","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"swapPrice","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"uint256","name":"underlyingPrice","type":"uint256"},{"internalType":"uint256","name":"volatility","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"acoToken","type":"address"}],"name":"redeemACOToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemACOTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restoreCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"int256","name":"tolerancePriceBelowMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceBelowMax","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMin","type":"int256"},{"internalType":"int256","name":"tolerancePriceAboveMax","type":"int256"},{"internalType":"uint256","name":"minStrikePrice","type":"uint256"},{"internalType":"uint256","name":"maxStrikePrice","type":"uint256"},{"internalType":"uint256","name":"minExpiration","type":"uint256"},{"internalType":"uint256","name":"maxExpiration","type":"uint256"}],"internalType":"struct IACOPool2.PoolAcoPermissionConfigV2","name":"newConfig","type":"tuple"}],"name":"setAcoPermissionConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newBaseVolatility","type":"uint256"}],"name":"setBaseVolatility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"acoCreator","type":"address"},{"internalType":"bool","name":"isForbidden","type":"bool"}],"name":"setForbiddenAcoCreator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setPoolAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"lendingPoolReferral","type":"uint16"},{"internalType":"uint256","name":"withdrawOpenPositionPenalty","type":"uint256"},{"internalType":"uint256","name":"underlyingPriceAdjustPercentage","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"maximumOpenAco","type":"uint256"},{"internalType":"address","name":"feeDestination","type":"address"},{"internalType":"address","name":"assetConverter","type":"address"}],"internalType":"struct IACOPool2.PoolProtocolConfig","name":"newConfig","type":"tuple"}],"name":"setProtocolConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newStrategy","type":"address"}],"name":"setStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"acoCreator","type":"address"},{"internalType":"bool","name":"newPermission","type":"bool"}],"name":"setValidAcoCreator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newLendingPool","type":"address"}],"name":"startLendingPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strikeAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"acoToken","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"restriction","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validAcoCreators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"minCollateral","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"withdrawLendingToken","type":"bool"}],"name":"withdrawNoLocked","outputs":[{"internalType":"uint256","name":"underlyingWithdrawn","type":"uint256"},{"internalType":"uint256","name":"strikeAssetWithdrawn","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"destination","type":"address"}],"name":"withdrawStuckToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"withdrawLendingToken","type":"bool"}],"name":"withdrawWithLocked","outputs":[{"internalType":"uint256","name":"underlyingWithdrawn","type":"uint256"},{"internalType":"uint256","name":"strikeAssetWithdrawn","type":"uint256"},{"internalType":"address[]","name":"acos","type":"address[]"},{"internalType":"uint256[]","name":"acosAmount","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b50615a5480620000216000396000f3fe60806040526004361061037a5760003560e01c806395d89b41116101d1578063c65a491511610102578063e95f92ab116100a0578063f2fde38b1161006f578063f2fde38b14610b59578063f5efbb4f14610b79578063f92a336f14610bfe578063faff660e14610c3b57600080fd5b8063e95f92ab14610ad9578063ecb8282414610af9578063f21bb16914610b19578063f2323b6714610b3957600080fd5b8063d80154d7116100dc578063d80154d714610a49578063d8dfeb4514610a5e578063dd62ed3e14610a73578063e11c296f14610ab957600080fd5b8063c65a4915146109d9578063d10e21e5146109f9578063d5b5f39314610a2957600080fd5b8063acf0ae031161016f578063b782cc4911610149578063b782cc4914610963578063bbe024a914610983578063bc205ad314610999578063c0737bef146109b957600080fd5b8063acf0ae0314610926578063b28798a214610939578063b5b8a8101461094e57600080fd5b8063a59a9973116101ab578063a59a997314610843578063a817857e14610863578063a8c62e76146108e6578063a9059cbb1461090657600080fd5b806395d89b41146107cc5780639b4e23ae146107e1578063a457c2d71461082357600080fd5b80635fd249c4116102ab57806370a0823111610249578063842a2b6711610223578063842a2b671461072e5780638da5cb5b1461074e5780638f79306e1461076c57806392bc3117146107ac57600080fd5b806370a08231146106a35780637643fc7a146106d95780637dcb80a4146106f957600080fd5b80636717f563116102855780636717f5631461063a578063695f3f5d1461064f5780636d636478146106625780636f307dc31461068357600080fd5b80635fd249c4146105da5780636047a77b146105fa5780636714f1eb1461061a57600080fd5b80632ab248071161031857806339509351116102f257806339509351146105065780633e0dc34e146105265780634ac341cc1461053c578063524b7bc91461056c57600080fd5b80632ab24807146104aa578063313ce567146104bf57806333a100ca146104e657600080fd5b806317d69bc81161035457806317d69bc81461041157806318160ddd1461044957806323b872dd14610468578063283d62ad1461048857600080fd5b806306fdde0314610386578063095ea7b3146103b157806317977e94146103e157600080fd5b3661038157005b600080fd5b34801561039257600080fd5b5061039b610c5c565b6040516103a89190615488565b60405180910390f35b3480156103bd57600080fd5b506103d16103cc366004614df1565b610d1c565b60405190151581526020016103a8565b3480156103ed57600080fd5b506103d16103fc366004614cb7565b601d6020526000908152604090205460ff1681565b34801561041d57600080fd5b50600654610431906001600160a01b031681565b6040516001600160a01b0390911681526020016103a8565b34801561045557600080fd5b506001545b6040519081526020016103a8565b34801561047457600080fd5b506103d1610483366004614d84565b610d33565b34801561049457600080fd5b506104a86104a3366004614cb7565b610d82565b005b3480156104b657600080fd5b50601b5461045a565b3480156104cb57600080fd5b506104d4610d96565b60405160ff90911681526020016103a8565b3480156104f257600080fd5b506104a8610501366004614cb7565b610da8565b34801561051257600080fd5b506103d1610521366004614df1565b610db9565b34801561053257600080fd5b5061045a60075481565b34801561054857600080fd5b506103d1610557366004614cb7565b601e6020526000908152604090205460ff1681565b34801561057857600080fd5b50600c54600d54600e54600f5460105460115460125460135461059f979695949392919088565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e0820152610100016103a8565b3480156105e657600080fd5b506104a86105f5366004614f66565b610df4565b34801561060657600080fd5b506104a8610615366004614f4e565b610e13565b34801561062657600080fd5b506104a8610635366004615183565b611078565b34801561064657600080fd5b506104a8611089565b61045a61065d366004615217565b61123f565b34801561066e57600080fd5b506006546103d190600160a01b900460ff1681565b34801561068f57600080fd5b50600554610431906001600160a01b031681565b3480156106af57600080fd5b5061045a6106be366004614cb7565b6001600160a01b031660009081526002602052604090205490565b3480156106e557600080fd5b506104a86106f4366004615007565b611258565b34801561070557600080fd5b50610719610714366004615217565b611272565b604080519283526020830191909152016103a8565b34801561073a57600080fd5b50600454610431906001600160a01b031681565b34801561075a57600080fd5b506000546001600160a01b0316610431565b34801561077857600080fd5b5061078c610787366004614df1565b61128e565b6040805194855260208501939093529183015260608201526080016103a8565b3480156107b857600080fd5b506103d16107c7366004614cb7565b6112b2565b3480156107d857600080fd5b5061039b6113a5565b3480156107ed57600080fd5b506107f66113af565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0016103a8565b34801561082f57600080fd5b506103d161083e366004614df1565b6113e0565b34801561084f57600080fd5b50600854610431906001600160a01b031681565b34801561086f57600080fd5b506108b761087e366004614cb7565b601f6020526000908152604090208054600182015460028301546003840154600485015460059095015460ff9094169492939192909186565b6040805196151587526020870195909552938501929092526060840152608083015260a082015260c0016103a8565b3480156108f257600080fd5b50600a54610431906001600160a01b031681565b34801561091257600080fd5b506103d1610921366004614df1565b611416565b6104a8610934366004614e1c565b611423565b34801561094557600080fd5b506104a8611437565b34801561095a57600080fd5b50601c5461045a565b34801561096f57600080fd5b50600954610431906001600160a01b031681565b34801561098f57600080fd5b5061045a600b5481565b3480156109a557600080fd5b506104a86109b4366004614cef565b61149f565b3480156109c557600080fd5b506104a86109d4366004614dc4565b611577565b3480156109e557600080fd5b506104316109f4366004615183565b6115f5565b348015610a0557600080fd5b50610a19610a143660046151b3565b61161f565b6040516103a89493929190615777565b348015610a3557600080fd5b5061045a610a44366004615183565b611641565b348015610a5557600080fd5b506104a861167c565b348015610a6a57600080fd5b50610431611715565b348015610a7f57600080fd5b5061045a610a8e366004614cef565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b348015610ac557600080fd5b50610a19610ad4366004615183565b611749565b348015610ae557600080fd5b506104a8610af4366004614dc4565b611a2e565b348015610b0557600080fd5b506104a8610b14366004614cb7565b611aac565b348015610b2557600080fd5b50610431610b34366004615183565b611dcc565b348015610b4557600080fd5b506104a8610b54366004614cb7565b611ddc565b348015610b6557600080fd5b506104a8610b74366004614cb7565b611ded565b348015610b8557600080fd5b50601454601554601654601754601854601954601a54610bb89661ffff1695949392916001600160a01b03908116911687565b6040805161ffff9098168852602088019690965294860193909352606085019190915260808401526001600160a01b0390811660a08401521660c082015260e0016103a8565b348015610c0a57600080fd5b50610c1e610c19366004615183565b611f07565b6040805193845260208401929092521515908201526060016103a8565b348015610c4757600080fd5b506006546103d190600160a81b900460ff1681565b60055460065460075460405163768c2ed560e01b81526001600160a01b0393841660048201529282166024840152600160a01b90910460ff16151560448301526064820152606090731607c25ab2a07a49414f78c80b2b8641153a91e89063768c2ed59060840160006040518083038186803b158015610cdb57600080fd5b505af4158015610cef573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d179190810190614ea5565b905090565b6000610d29338484612016565b5060015b92915050565b6001600160a01b0383166000908152600360209081526040808320338085529252822054610d6c918691610d679086612021565b61202d565b610d77848484612156565b5060015b9392505050565b610d8a612161565b610d93816121a3565b50565b6000610d17610da3611715565b61223b565b610db0612161565b610d938161232c565b3360008181526003602090815260408083206001600160a01b03871684529091528120549091610d29918590610def9086612441565b612016565b610dfc612161565b610d93610e0e36839003830183614f78565b61244d565b6005546001600160a01b0316158015610e3557506006546001600160a01b0316155b610e6c5760405162461bcd60e51b815260206004820152600360248201526204530360ec1b60448201526064015b60405180910390fd5b610e7c6080820160608301614cb7565b6001600160a01b0316610e956060830160408401614cb7565b6001600160a01b03161415610ed25760405162461bcd60e51b815260206004820152600360248201526245303160e81b6044820152606401610e63565b610eda61262d565b610ee76020820182614cb7565b600480546001600160a01b0319166001600160a01b0392909216919091179055610f176060820160408301614cb7565b600580546001600160a01b0319166001600160a01b0392909216919091179055610f476080820160608301614cb7565b600680546001600160a01b0319166001600160a01b0392909216919091179055610f7760a0820160808301614e6d565b60068054911515600160a01b0260ff60a01b19909216919091179055610fa561012082016101008301614e6d565b60068054911515600160a81b0260ff60a81b19909216919091179055610120810135600755610fe5610fe03683900383016102408401615018565b6126c9565b610ffd610ff860e0830160c08401614cb7565b6121a3565b611013610e0e3683900383016101408401614f78565b6110208160a001356129bb565b611039611034610100830160e08401614cb7565b61232c565b61105161104c6040830160208401614cb7565b612a25565b611064610da36060830160408401614cb7565b6110729060ff16600a615893565b60215550565b611080612161565b610d93816129bb565b611091612161565b6000806000600660149054906101000a900460ff16156110de576006546110c0906001600160a01b0316612b86565b6005546006549194506001600160a01b03908116935016905061110d565b6005546110f3906001600160a01b0316612b86565b6006546005549194506001600160a01b0390811693501690505b600083116111435760405162461bcd60e51b815260206004820152600360248201526204536360ec1b6044820152606401610e63565b60006001600160a01b0382166111565750825b601a5460405163b503bb2b60e01b81526001600160a01b038481166004830152858116602483015260448201879052600092169063b503bb2b9084906064016020604051808303818588803b1580156111ae57600080fd5b505af11580156111c2573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906111e7919061519b565b90506111f1612b92565b156111ff576111ff81612bbc565b60408051868152602081018390527f89c28f2814c3b5c029895975e6da754b1bfc82368bec347d2b2d14c5353dac99910160405180910390a15050505050565b600061124d85858585612c34565b90505b949350505050565b611260612e37565b610d93610fe036839003830183615018565b60008061128186868686612e86565b9097909650945050505050565b600080808060146112a0878783612fd7565b50929a91995097509095509350505050565b6000806000806000806112c4876131cc565b945094509450945094506112da87868686613267565b1561139857601a546000906112fb90879087906001600160a01b03166133c2565b60405163d821bc8160e01b8152909150731607c25ab2a07a49414f78c80b2b8641153a91e89063d821bc819061133c90869086908690600c906004016157a8565b60206040518083038186803b15801561135457600080fd5b505af4158015611368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138c9190614e89565b98975050505050505050565b5060009695505050505050565b6060610d17610c5c565b6000806000806000806113c160015490565b90506113cd6001613447565b949b939a50909850965091945091925050565b3360008181526003602090815260408083206001600160a01b03871684529091528120549091610d29918590610def9086612021565b6000610d29338484612156565b61143085858585856135b6565b5050505050565b601c545b8015610d93576000601c61145060018461595a565b8154811061146e57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316905061148e81611aac565b506114988161599d565b905061143b565b6114a7612e37565b6005546001600160a01b038381169116148015906114d357506006546001600160a01b03838116911614155b80156114f857506001600160a01b0382166000908152601f602052604090205460ff16155b80156115215750611507612b92565b158061152157506020546001600160a01b03838116911614155b6115535760405162461bcd60e51b815260206004820152600360248201526204538360ec1b6044820152606401610e63565b600061155f833061371a565b905080156115725761157283838361382e565b505050565b61157f612e37565b6001600160a01b0382166000818152601e60205260408082205490518415159360ff9092161515927fb81b610c59b267ffeae941933b259c0949308acb2bc82fbf128a25111ef0584291a46001600160a01b03919091166000908152601e60205260409020805460ff1916911515919091179055565b601b818154811061160557600080fd5b6000918252602090912001546001600160a01b0316905081565b6000806060806116308787876138f3565b929a91995097509095509350505050565b60008061164e6001613aca565b50925050508061165f575090919050565b610d7b8161167661166f60015490565b8690613b0c565b90613b18565b611684612b92565b6116b65760405162461bcd60e51b815260206004820152600360248201526204537360ec1b6044820152606401610e63565b6006546000906116ce906001600160a01b0316612b86565b90508015610d93576116df81612bbc565b6040518181527f0c4fba493c1adabe990310a59f39d3bac577bad06f8e396565d5966ab54688e19060200160405180910390a150565b600654600090600160a01b900460ff1661173957506006546001600160a01b031690565b506005546001600160a01b031690565b600080606080600061175a60015490565b905060008611801561176c5750808611155b15611a265760055460065460205460405163ac7806a760e01b8152600481018a90526001600160a01b0393841660248201528383166044820152600160a01b90920460ff1615156064830152608482018490529190911660a4820152731607c25ab2a07a49414f78c80b2b8641153a91e89063ac7806a79060c401604080518083038186803b1580156117fe57600080fd5b505af4158015611812573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183691906151f4565b601c54919650945067ffffffffffffffff81111561186457634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561188d578160200160208202803683370190505b50601c5490935067ffffffffffffffff8111156118ba57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156118e3578160200160208202803683370190505b50915060005b601c54811015611a24576000601c828154811061191657634e487b7160e01b600052603260045260246000fd5b60009182526020822001546040516345f79d1b60e01b81523060048201526001600160a01b03909116925082906345f79d1b9060240160206040518083038186803b15801561196457600080fd5b505afa158015611978573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199c919061519b565b9050818684815181106119bf57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101526119e584611676838c613b0c565b858481518110611a0557634e487b7160e01b600052603260045260246000fd5b602002602001018181525050505080611a1d906159b4565b90506118e9565b505b509193509193565b611a36612e37565b6001600160a01b0382166000818152601d60205260408082205490518415159360ff9092161515927fde05906ae2ccd415e587b0dffec2bb3e9bc65ac1943800529610b06b582b9da691a46001600160a01b03919091166000908152601d60205260409020805460ff1916911515919091179055565b6001600160a01b0381166000908152601f60205260409020805460ff168015611b45575042826001600160a01b03166399bc0aea6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0a57600080fd5b505afa158015611b1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b42919061519b565b11155b15611dc857805460ff19168155601c54600090611b649060019061595a565b6005830154909150808214611c11576000601c8381548110611b9657634e487b7160e01b600052603260045260246000fd5b600091825260209091200154601c80546001600160a01b039092169250829184908110611bd357634e487b7160e01b600052603260045260246000fd5b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152601f909152604090206005018190555b60006005840155601c805480611c3757634e487b7160e01b600052603160045260246000fd5b600082815260208120600019908301810180546001600160a01b03191690559091019091556040516345f79d1b60e01b81523060048201526001600160a01b038616906345f79d1b9060240160206040518083038186803b158015611c9b57600080fd5b505afa158015611caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd3919061519b565b1115611d6b57836001600160a01b031663be040fb06040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611d1457600080fd5b505af1158015611d28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4c919061519b565b6003840155611d59612b92565b15611d6b57611d6b8360030154612bbc565b600183015460028401546003850154604080519384526020840192909252908201526001600160a01b038516907f33e1adfc662275b6dd743c8c4aaf326f171ed89fc35dd4bd21dd608bb23b4d239060600160405180910390a250505b5050565b601c818154811061160557600080fd5b611de4612e37565b610d9381612a25565b6000546001600160a01b03163314611e475760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e63565b6001600160a01b038116611eac5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e63565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b600080600080611f1660015490565b9050600085118015611f285750808511155b1561200e57600080600080611f3d6000613aca565b60065460405163f713e37d60e01b8152600481018f9052602481018b9052600160a01b90910460ff1615156044820152606481018590526084810184905260a4810183905260c4810182905293975091955093509150731607c25ab2a07a49414f78c80b2b8641153a91e89063f713e37d9060e40160606040518083038186803b158015611fca57600080fd5b505af4158015611fde573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120029190615260565b91995097509550505050505b509193909250565b61157283838361202d565b6000610d7b828461595a565b6001600160a01b03831661208f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964206f6044820152633bb732b960e11b6064820152608401610e63565b6001600160a01b0382166120f45760405162461bcd60e51b815260206004820152602660248201527f45524332303a3a5f617070726f7665416374696f6e3a20496e76616c696420736044820152653832b73232b960d11b6064820152608401610e63565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b611572838383613b24565b6009546001600160a01b031633146121a15760405162461bcd60e51b815260206004820152600360248201526208a72760eb1b6044820152606401610e63565b565b6001600160a01b0381166121df5760405162461bcd60e51b815260206004820152600360248201526208a70760eb1b6044820152606401610e63565b6009546040516001600160a01b038084169216907f09988335037cc8164f3e84c3c0e4809c5bc40e9620a4cda8cda95846ada7a21790600090a3600980546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b03821661225357506012919050565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b179052905160009182916001600160a01b038616916122969161546c565b600060405180830381855afa9150503d80600081146122d1576040519150601f19603f3d011682016040523d82523d6000602084013e6122d6565b606091505b5091509150816123135760405162461bcd60e51b8152602060048201526008602482015267646563696d616c7360c01b6044820152606401610e63565b80806020019051810190611250919061530b565b919050565b6000546001600160a01b031660405163421f2c4d60e01b81526001600160a01b038381166004830152919091169063421f2c4d9060240160206040518083038186803b15801561237b57600080fd5b505afa15801561238f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b39190614e89565b6123e55760405162461bcd60e51b815260206004820152600360248201526245383760e81b6044820152606401610e63565b600a546040516001600160a01b038084169216907f439ae0d36946bc1b7917756b5772ae0c0292339ebc08be0f7bd1daa4a105537290600090a3600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610d7b8284615818565b620186a0816020015112801561246657508051620186a0135b6124985760405162461bcd60e51b815260206004820152600360248201526245383160e81b6044820152606401610e63565b6020810151815112806124af575060008160200151125b6124e15760405162461bcd60e51b8152602060048201526003602482015262229c1960e91b6044820152606401610e63565b8060600151816040015112806124fb575060008160600151125b61252d5760405162461bcd60e51b815260206004820152600360248201526245383360e81b6044820152606401610e63565b8060a0015181608001511080612545575060a0810151155b6125775760405162461bcd60e51b8152602060048201526003602482015262114e0d60ea1b6044820152606401610e63565b8060e001518160c0015111156125b55760405162461bcd60e51b815260206004820152600360248201526245383560e81b6044820152606401610e63565b7ff7b90d9f9adf9df8850de8b0943e2c20ad4c1581f3442c38df925b722431f289600c826040516125e7929190615591565b60405180910390a18051600c556020810151600d556040810151600e556060810151600f55608081015160105560a081015160115560c081015160125560e00151601355565b6000546001600160a01b0316156126865760405162461bcd60e51b815260206004820152601d60248201527f4f776e61626c653a20436f6e747261637420696e697469616c697a65640000006044820152606401610e63565b600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350565b60055460065460c0830151604051635620c32d60e11b81526001600160a01b0393841660048201819052928416602482018190529293600092169063ac41865a9060440160206040518083038186803b15801561272557600080fd5b505afa158015612739573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275d919061519b565b116127905760405162461bcd60e51b815260206004820152600360248201526245383960e81b6044820152606401610e63565b60a08301516001600160a01b03166127d05760405162461bcd60e51b815260206004820152600360248201526204539360ec1b6044820152606401610e63565b6130d48360600151111561280c5760405162461bcd60e51b815260206004820152600360248201526245393160e81b6044820152606401610e63565b620186a0836020015111156128495760405162461bcd60e51b8152602060048201526003602482015262229c9960e91b6044820152606401610e63565b620186a08360400151106128855760405162461bcd60e51b815260206004820152600360248201526245393360e81b6044820152606401610e63565b60008360800151116128bf5760405162461bcd60e51b8152602060048201526003602482015262114e4d60ea1b6044820152606401610e63565b600654600160a01b900460ff16156128f3576001600160a01b038116156128ee576128ee818460c00151613c97565b612910565b6001600160a01b0382161561291057612910828460c00151613c97565b7f87e79bc7e07443f97212936d447d963abeef24fa529740e78873de635c9e65c76014846040516129429291906155ae565b60405180910390a1505080516014805461ffff191661ffff909216919091179055602081015160155560408101516016556060810151601755608081015160185560a0810151601980546001600160a01b03199081166001600160a01b039384161790915560c090920151601a80549093169116179055565b600081116129f15760405162461bcd60e51b8152602060048201526003602482015262229c1b60e91b6044820152606401610e63565b600b546040518291907f530df85870a027fbdcb9a0732734b6471c5ecd497a0474aa81cb4300f820274090600090a3600b55565b6008546001600160a01b031615612a645760405162461bcd60e51b815260206004820152600360248201526245393560e81b6044820152606401610e63565b6001600160a01b03811615801590612a865750600654600160a01b900460ff16155b15610d93576006546040516335ea6a7560e01b81526001600160a01b039182166004820152908216906335ea6a75906024016101806040518083038186803b158015612ad157600080fd5b505afa158015612ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b099190615097565b60e00151602080546001600160a01b0319166001600160a01b03928316179055600654612b37911682613c97565b600880546001600160a01b0319166001600160a01b0383169081179091556040517fe15c60051e9a84c30d7efbb4cd3f86536e3e5dfb442e71bed59cf379f836e66690600090a2610d9361167c565b6000610d2d823061371a565b600654600090600160a01b900460ff16158015610d175750506008546001600160a01b0316151590565b60085460065460145460405163e8eda9df60e01b81526001600160a01b0392831660048201526024810185905230604482015261ffff909116606482015291169063e8eda9df90608401600060405180830381600087803b158015612c2057600080fd5b505af1158015611430573d6000803e3d6000fd5b6000612c3e613ca4565b60008511612c745760405162461bcd60e51b815260206004820152600360248201526204531360ec1b6044820152606401610e63565b6001600160a01b03831615801590612c9557506001600160a01b0383163014155b612cc75760405162461bcd60e51b815260206004820152600360248201526245313160e81b6044820152606401610e63565b811580612cd75750612cd7612b92565b612d095760405162461bcd60e51b815260206004820152600360248201526222989960e91b6044820152606401610e63565b6000612d156001613aca565b50925050506000612d24611715565b90506001600160a01b038116612d4157612d3e8234612021565b91505b81612d4e57869250612d68565b612d6582611676612d5e60015490565b8a90613b0c565b92505b85831015612d9e5760405162461bcd60e51b815260206004820152600360248201526245313360e81b6044820152606401610e63565b8315612dbf57602054612dba906001600160a01b031688613cf9565b612ddf565b612dc98188613cf9565b612dd1612b92565b15612ddf57612ddf87612bbc565b612de98584613d92565b60408051848152602081018990526001600160a01b038716917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a25050949350505050565b33612e4a6000546001600160a01b031690565b6001600160a01b0316146121a15760405162461bcd60e51b815260206004820152600360248201526245393960e81b6044820152606401610e63565b60008060008611612ebf5760405162461bcd60e51b815260206004820152600360248201526204533360ec1b6044820152606401610e63565b821580612ecf5750612ecf612b92565b612f015760405162461bcd60e51b815260206004820152600360248201526245333160e81b6044820152606401610e63565b612f09611437565b6000612f1460015490565b9050612f208588613e84565b612f3b878288600660149054906101000a900460ff16613ea9565b9093509150612f4b838386613f81565b6001600160a01b0385167ff1afea1771c6751a98adbb8147f94b51ce1f9c6936aa48c35ae8e15f74e8bdb388600186866000604051908082528060200260200182016040528015612fa6578160200160208202803683370190505b5060408051600081526020810191829052612fc596959493929161572b565b60405180910390a25094509492505050565b60008060008060008087116130145760405162461bcd60e51b815260206004820152600360248201526204535360ec1b6044820152606401610e63565b60006130208989613ff4565b905061303a8982608001518360a001518460000151613267565b61306c5760405162461bcd60e51b815260206004820152600360248201526245353160e81b6044820152606401610e63565b608081015160a0820151600689015461308f9291906001600160a01b03166133c2565b604080516101008082018352602080546001600160a01b039081168452600a541681840152600b548385015260038c0154606080850191909152608080850187905260215460a08087019190915260c08087018a905287519586018852600c548652600d5494860194909452600e5485880152600f549285019290925260105490840152601154908301526012549082015260135460e082810191909152820152905163663590ff60e01b8152919550731607c25ab2a07a49414f78c80b2b8641153a91e89163663590ff916131679160040161567d565b60806040518083038186803b15801561317f57600080fd5b505af4158015613193573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131b7919061528d565b929c919b509599509497509550929350505050565b6004805460405163073086d760e31b81526001600160a01b03848116938201939093526000928392839283928392169063398436b89060240160a06040518083038186803b15801561321d57600080fd5b505afa158015613231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132559190614d27565b939a9299509097509550909350915050565b6005546000906001600160a01b03858116911614801561329457506006546001600160a01b038481169116145b80156132b25750600660149054906101000a900460ff161515821515145b156133ba576004805460405163933166e160e01b81526001600160a01b03888116938201939093526000929091169063933166e19060240160206040518083038186803b15801561330257600080fd5b505afa158015613316573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061333a9190614cd3565b6001600160a01b0381166000908152601d602052604090205490915060ff161580156133b2575060008052601e6020527f65ce8396b736f5da9d881cc6fbcb11ef9721292dc41ec8c40879fd9edea5744d5460ff16806133b257506001600160a01b0381166000908152601e602052604090205460ff165b915050611250565b506000611250565b604051635620c32d60e11b81526001600160a01b03848116600483015283811660248301526000919083169063ac41865a9060440160206040518083038186803b15801561340f57600080fd5b505afa158015613423573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611250919061519b565b600554600654601a5460009283928392839283928392601492849261347c926001600160a01b039283169291821691166133c2565b604080516101a0810182528b1515815260065460ff600160a01b8204161515602080840191909152828401859052600b54606084015260028701546080840152600187015460a0840152600387015460c084015260215460e08401526005546001600160a01b03908116610100850152918216610120840152600a54821661014084015260048054831661016085015290549091166101808301529151636b4f9d3760e01b8152929350731607c25ab2a07a49414f78c80b2b8641153a91e892636b4f9d37926135509291601c91016154bb565b60c06040518083038186803b15801561356857600080fd5b505af415801561357c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135a091906152c2565b949e939d50919b50995097509095509350505050565b804211156135ec5760405162461bcd60e51b815260206004820152600360248201526204534360ec1b6044820152606401610e63565b6001600160a01b038216158015906136165750846001600160a01b0316826001600160a01b031614155b801561362b57506001600160a01b0382163014155b61365d5760405162461bcd60e51b815260206004820152600360248201526245343160e81b6044820152606401610e63565b60146000808080806136708b8b88612fd7565b94509450945094509450613689888c838d8d8a8a614078565b83156136ae5760065460058701546136ae916001600160a01b0390811691168661382e565b604080518b81526020810187905290810185905260608101849052608081018390526001600160a01b03808d1691908a16907fe7525d00e88ec2fe4949364ebcdf61f80247212b853f121457da56e0df2395899060a00160405180910390a35050505050505050505050565b60006001600160a01b03831661373b57506001600160a01b03811631610d2d565b604080516001600160a01b0384811660248084019190915283518084039091018152604490920183526020820180516001600160e01b03166370a0823160e01b1790529151600092839290871691613793919061546c565b600060405180830381855afa9150503d80600081146137ce576040519150601f19603f3d011682016040523d82523d6000602084013e6137d3565b606091505b5091509150816138115760405162461bcd60e51b81526020600482015260096024820152683130b630b731b2a7b360b91b6044820152606401610e63565b80806020019051810190613825919061519b565b92505050610d2d565b6001600160a01b0383166138e857604080516000808252602082019092526001600160a01b038416908390604051613866919061546c565b60006040518083038185875af1925050503d80600081146138a3576040519150601f19603f3d011682016040523d82523d6000602084013e6138a8565b606091505b50509050806138e25760405162461bcd60e51b8152600401610e63906020808252600490820152631cd95b9960e21b604082015260600190565b50505050565b611572838383614490565b6000806060806000871161392f5760405162461bcd60e51b815260206004820152600360248201526204532360ec1b6044820152606401610e63565b84158061393f575061393f612b92565b6139715760405162461bcd60e51b815260206004820152600360248201526245323160e81b6044820152606401610e63565b613979611437565b600061398460015490565b90506139908789613e84565b60055460065460205460405163ac7806a760e01b8152600481018c90526001600160a01b0393841660248201528383166044820152600160a01b90920460ff1615156064830152608482018490529190911660a4820152731607c25ab2a07a49414f78c80b2b8641153a91e89063ac7806a79060c401604080518083038186803b158015613a1d57600080fd5b505af4158015613a31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a5591906151f4565b9095509350613a64888261458f565b9093509150613a74858588613f81565b866001600160a01b03167ff1afea1771c6751a98adbb8147f94b51ce1f9c6936aa48c35ae8e15f74e8bdb389600088888888604051613ab89695949392919061572b565b60405180910390a25093509350935093565b600080600080600080613adc87613447565b949a509298509096509194509092509050613b0181613afb8685612441565b90612021565b935050509193509193565b6000610d7b828461593b565b6000610d7b8284615830565b6001600160a01b038316613b895760405162461bcd60e51b815260206004820152602660248201527f45524332303a3a5f7472616e73666572416374696f6e3a20496e76616c69642060448201526539b2b73232b960d11b6064820152608401610e63565b6001600160a01b038216613bf15760405162461bcd60e51b815260206004820152602960248201527f45524332303a3a5f7472616e73666572416374696f6e3a20496e76616c6964206044820152681c9958da5c1a595b9d60ba1b6064820152608401610e63565b6001600160a01b038316600090815260026020526040902054613c149082612021565b6001600160a01b038085166000908152600260205260408082209390935590841681522054613c439082612441565b6001600160a01b0380841660008181526002602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906121499085815260200190565b611dc8828260001961484e565b600654600160a81b900460ff161580613cc757506009546001600160a01b031633145b6121a15760405162461bcd60e51b815260206004820152600360248201526245393760e81b6044820152606401610e63565b6001600160a01b038216613d4b57803414611dc85760405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a590811551208185b5bdd5b9d60721b6044820152606401610e63565b3415613d865760405162461bcd60e51b815260206004820152600a6024820152694e6f2070617961626c6560b01b6044820152606401610e63565b611dc88233308461494c565b6001600160a01b038216613df45760405162461bcd60e51b815260206004820152602360248201527f45524332303a3a5f6d696e74416374696f6e3a20496e76616c6964206163636f6044820152621d5b9d60ea1b6064820152608401610e63565b600154613e019082612441565b6001556001600160a01b038216600090815260026020526040902054613e279082612441565b6001600160a01b0383166000818152600260205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90613e789085815260200190565b60405180910390a35050565b6001600160a01b038216331415613e9f57611dc88282614a5f565b611dc88282614b4b565b6000806000806000613ebb6000613aca565b50604051633395f1e560e01b8152600481018d9052602481018c905260448101849052606481018390526084810182905260a481018b905289151560c48201529295509093509150731607c25ab2a07a49414f78c80b2b8641153a91e890633395f1e59060e401604080518083038186803b158015613f3957600080fd5b505af4158015613f4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7191906151f4565b909a909950975050505050505050565b8115613fd7578015613fa957602054613fa4906001600160a01b0316338461382e565b613fd7565b613fb1612b92565b15613fc057613fa48233614b8a565b600654613fd7906001600160a01b0316338461382e565b821561157257600554611572906001600160a01b0316338561382e565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529080808080614033886131cc565b6040805160c081018252931515845260208401929092529082015260608101999099526001600160a01b0391821660808a01521660a088015250949695505050505050565b828211156140ae5760405162461bcd60e51b8152602060048201526003602482015262229a1960e91b6044820152606401610e63565b6006546001600160a01b031660008161410857833410156140f75760405162461bcd60e51b815260206004820152600360248201526245343360e81b6044820152606401610e63565b6141013485612021565b9050614148565b341561413c5760405162461bcd60e51b8152602060048201526003602482015262114d0d60ea1b6044820152606401610e63565b6141488233308761494c565b60006141548585612021565b905061415e612b92565b15614176576141766141708983612021565b30614b8a565b6000614180611715565b6001600160a01b038b81166000908152601f60205260409020919250821661421d578a6001600160a01b031663732a950d8b6040518263ffffffff1660e01b81526004016020604051808303818588803b1580156141dd57600080fd5b505af11580156141f1573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190614216919061519b565b98506142ad565b805460ff1661423057614230828c613c97565b60405163140e25ad60e31b8152600481018b90526001600160a01b038c169063a0712d6890602401602060405180830381600087803b15801561427257600080fd5b505af1158015614286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142aa919061519b565b98505b805460ff1661443b57601854601c54106142ef5760405162461bcd60e51b815260206004820152600360248201526245343560e81b6044820152606401610e63565b6040518060c001604052806001151581526020018481526020018b815260200160008152602001601b805490508152602001601c80549050815250601f60008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050155905050601b8b9080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b03160217905550601c8b9080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b03160217905550614466565b600281015461444b908b90612441565b60028201556001810154614460908490612441565b60018201555b6144718b8d8b614490565b83156144825761448285338661382e565b505050505050505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916144ec919061546c565b6000604051808303816000865af19150503d8060008114614529576040519150601f19603f3d011682016040523d82523d6000602084013e61452e565b606091505b50915091508180156145585750805115806145585750808060200190518101906145589190614e89565b6114305760405162461bcd60e51b81526020600482015260086024820152673a3930b739b332b960c11b6044820152606401610e63565b601c5460609081908067ffffffffffffffff8111156145be57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156145e7578160200160208202803683370190505b5092508067ffffffffffffffff81111561461157634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561463a578160200160208202803683370190505b50915060005b81811015614845576000601c828154811061466b57634e487b7160e01b600052603260045260246000fd5b60009182526020822001546040516345f79d1b60e01b81523060048201526001600160a01b03909116925082906345f79d1b9060240160206040518083038186803b1580156146b957600080fd5b505afa1580156146cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146f1919061519b565b90508186848151811061471457634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015261473a87611676838b613b0c565b85848151811061475a57634e487b7160e01b600052603260045260246000fd5b602002602001018181525050600085848151811061478857634e487b7160e01b600052603260045260246000fd5b6020026020010151111561483257816001600160a01b031663464673c6338786815181106147c657634e487b7160e01b600052603260045260246000fd5b60200260200101516040518363ffffffff1660e01b81526004016147ff9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b15801561481957600080fd5b505af115801561482d573d6000803e3d6000fd5b505050505b50508061483e906159b4565b9050614640565b50509250929050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916148aa919061546c565b6000604051808303816000865af19150503d80600081146148e7576040519150601f19603f3d011682016040523d82523d6000602084013e6148ec565b606091505b50915091508180156149165750805115806149165750808060200190518101906149169190614e89565b6114305760405162461bcd60e51b8152602060048201526007602482015266617070726f766560c81b6044820152606401610e63565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916149b0919061546c565b6000604051808303816000865af19150503d80600081146149ed576040519150601f19603f3d011682016040523d82523d6000602084013e6149f2565b606091505b5091509150818015614a1c575080511580614a1c575080806020019051810190614a1c9190614e89565b614a575760405162461bcd60e51b815260206004820152600c60248201526b7472616e7366657246726f6d60a01b6044820152606401610e63565b505050505050565b6001600160a01b038216614ac15760405162461bcd60e51b815260206004820152602360248201527f45524332303a3a5f6275726e416374696f6e3a20496e76616c6964206163636f6044820152621d5b9d60ea1b6064820152608401610e63565b6001600160a01b038216600090815260026020526040902054614ae49082612021565b6001600160a01b038316600090815260026020526040902055600154614b0a9082612021565b6001556040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001613e78565b6001600160a01b038216600090815260036020908152604080832033808552925290912054614b80918491610d679085612021565b611dc88282614a5f565b600854600654604051631a4ca37b60e21b81526001600160a01b0391821660048201526024810185905283821660448201529116906369328dec90606401602060405180830381600087803b158015614be257600080fd5b505af1158015614bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611572919061519b565b8035612327816159fb565b8051612327816159fb565b600060208284031215614c41578081fd5b6040516020810181811067ffffffffffffffff82111715614c6457614c646159e5565b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff8116811461232757600080fd5b805164ffffffffff8116811461232757600080fd5b805160ff8116811461232757600080fd5b600060208284031215614cc8578081fd5b8135610d7b816159fb565b600060208284031215614ce4578081fd5b8151610d7b816159fb565b60008060408385031215614d01578081fd5b8235614d0c816159fb565b91506020830135614d1c816159fb565b809150509250929050565b600080600080600060a08688031215614d3e578081fd5b8551614d49816159fb565b6020870151909550614d5a816159fb565b6040870151909450614d6b81615a10565b6060870151608090970151959894975095949392505050565b600080600060608486031215614d98578081fd5b8335614da3816159fb565b92506020840135614db3816159fb565b929592945050506040919091013590565b60008060408385031215614dd6578182fd5b8235614de1816159fb565b91506020830135614d1c81615a10565b60008060408385031215614e03578182fd5b8235614e0e816159fb565b946020939093013593505050565b600080600080600060a08688031215614e33578283fd5b8535614e3e816159fb565b945060208601359350604086013592506060860135614e5c816159fb565b949793965091946080013592915050565b600060208284031215614e7e578081fd5b8135610d7b81615a10565b600060208284031215614e9a578081fd5b8151610d7b81615a10565b600060208284031215614eb6578081fd5b815167ffffffffffffffff80821115614ecd578283fd5b818401915084601f830112614ee0578283fd5b815181811115614ef257614ef26159e5565b604051601f8201601f19908116603f01168101908382118183101715614f1a57614f1a6159e5565b81604052828152876020848701011115614f32578586fd5b614f43836020830160208801615971565b979650505050505050565b60006103208284031215614f60578081fd5b50919050565b60006101008284031215614f60578081fd5b6000610100808385031215614f8b578182fd5b6040519081019067ffffffffffffffff82118183101715614fae57614fae6159e5565b81604052833581526020840135602082015260408401356040820152606084013560608201526080840135608082015260a084013560a082015260c084013560c082015260e084013560e0820152809250505092915050565b600060e08284031215614f60578081fd5b600060e08284031215615029578081fd5b6150316157cb565b823561ffff81168114615042578283fd5b808252506020830135602082015260408301356040820152606083013560608201526080830135608082015261507a60a08401614c1a565b60a082015261508b60c08401614c1a565b60c08201529392505050565b600061018082840312156150a9578081fd5b6150b16157f4565b6150bb8484614c30565b81526150c960208401614c71565b60208201526150da60408401614c71565b60408201526150eb60608401614c71565b60608201526150fc60808401614c71565b608082015261510d60a08401614c71565b60a082015261511e60c08401614c91565b60c082015261512f60e08401614c25565b60e0820152610100615142818501614c25565b90820152610120615154848201614c25565b90820152610140615166848201614c25565b90820152610160615178848201614ca6565b908201529392505050565b600060208284031215615194578081fd5b5035919050565b6000602082840312156151ac578081fd5b5051919050565b6000806000606084860312156151c7578081fd5b8335925060208401356151d9816159fb565b915060408401356151e981615a10565b809150509250925092565b60008060408385031215615206578182fd5b505080516020909101519092909150565b6000806000806080858703121561522c578182fd5b84359350602085013592506040850135615245816159fb565b9150606085013561525581615a10565b939692955090935050565b600080600060608486031215615274578081fd5b835192506020840151915060408401516151e981615a10565b600080600080608085870312156152a2578182fd5b505082516020840151604085015160609095015191969095509092509050565b60008060008060008060c087890312156152da578384fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b60006020828403121561531c578081fd5b610d7b82614ca6565b6000815180845260208085019450808401835b8381101561535d5781516001600160a01b031687529582019590820190600101615338565b509495945050505050565b6000815480845260208085019450838352808320835b8381101561535d5781546001600160a01b03168752958201956001918201910161537e565b6000815180845260208085019450808401835b8381101561535d578151875295820195908201906001016153b6565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301525050565b8054825260018101546020830152600281015460408301526003810154606083015260048101546080830152600581015460a0830152600681015460c08301526007015460e090910152565b6000825161547e818460208701615971565b9190910192915050565b60208152600082518060208401526154a7816040850160208701615971565b601f01601f19169190910160400192915050565b82511515815260006101c060208501516154d9602085018215159052565b5060408501516040840152606085015160608401526080850151608084015260a085015160a084015260c085015160c084015260e085015160e084015261010080860151615531828601826001600160a01b03169052565b5050610120858101516001600160a01b0390811691850191909152610140808701518216908501526101608087015182169085015261018080870151909116908401526101a0830181905261558881840185615368565b95945050505050565b61020081016155a08285615420565b610d7b6101008301846153d2565b825461ffff1681526101c081016001840154602083015260028401546040830152600384015460608301526004840154608083015260058401546001600160a01b03166001600160a01b03811660a08401525060068401546001600160a01b03166001600160a01b03811660c084015250825161ffff1660e0830152602083015161010083015260408301516101208301526060830151610140830152608083015161016083015260a08301516001600160a01b0390811661018084015260c0840151166101a0830152610d7b565b60006102808201905060018060a01b0380845116835280602085015116602084015260408401516040840152606084015160608401526080840151608084015260a084015160a084015260c08401518051151560c0850152602081015160e085015260408101516101008501526060810151610120850152816080820151166101408501528160a082015116610160850152505060e08301516157246101808401826153d2565b5092915050565b868152851515602082015284604082015283606082015260c06080820152600061575860c0830185615325565b82810360a084015261576a81856153a3565b9998505050505050505050565b8481528360208201526080604082015260006157966080830185615325565b8281036060840152614f4381856153a3565b848152602081018490526040810183905261016081016155886060830184615420565b60405160e0810167ffffffffffffffff811182821017156157ee576157ee6159e5565b60405290565b604051610180810167ffffffffffffffff811182821017156157ee576157ee6159e5565b6000821982111561582b5761582b6159cf565b500190565b60008261584b57634e487b7160e01b81526012600452602481fd5b500490565b600181815b8085111561588b578160001904821115615871576158716159cf565b8085161561587e57918102915b93841c9390800290615855565b509250929050565b6000610d7b83836000826158a957506001610d2d565b816158b657506000610d2d565b81600181146158cc57600281146158d6576158f2565b6001915050610d2d565b60ff8411156158e7576158e76159cf565b50506001821b610d2d565b5060208310610133831016604e8410600b8410161715615915575081810a610d2d565b61591f8383615850565b8060001904821115615933576159336159cf565b029392505050565b6000816000190483118215151615615955576159556159cf565b500290565b60008282101561596c5761596c6159cf565b500390565b60005b8381101561598c578181015183820152602001615974565b838111156138e25750506000910152565b6000816159ac576159ac6159cf565b506000190190565b60006000198214156159c8576159c86159cf565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610d9357600080fd5b8015158114610d9357600080fdfea26469706673582212204c77c431aa4dbdb7b51b3ad2734af68723bfe4dbdc487f1b641efb37813b64b964736f6c63430008040033

Deployed ByteCode Sourcemap

8262:30135:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11732:142;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1404:158:3;;;;;;;;;;-1:-1:-1;1404:158:3;;;;;:::i;:::-;;:::i;:::-;;;19267:14:14;;19260:22;19242:41;;19230:2;19215:18;1404:158:3;19197:92:14;10532:52:1;;;;;;;;;;-1:-1:-1;10532:52:1;;;;;:::i;:::-;;;;;;;;;;;;;;;;10074:26;;;;;;;;;;-1:-1:-1;10074:26:1;;;;-1:-1:-1;;;;;10074:26:1;;;;;;-1:-1:-1;;;;;16777:32:14;;;16759:51;;16747:2;16732:18;10074:26:1;16714:102:14;555:107:3;;;;;;;;;;-1:-1:-1;642:12:3;;555:107;;;45783:25:14;;;45771:2;45756:18;555:107:3;45738:76:14;1126:270:3;;;;;;;;;;-1:-1:-1;1126:270:3;;;;;:::i;:::-;;:::i;16450:106:1:-;;;;;;;;;;-1:-1:-1;16450:106:1;;;;;:::i;:::-;;:::i;:::-;;12234:112;;;;;;;;;;-1:-1:-1;12322:9:1;:16;12234:112;;11981:128;;;;;;;;;;;;;:::i;:::-;;;52103:4:14;52091:17;;;52073:36;;52061:2;52046:18;11981:128:1;52028:87:14;16331:113:1;;;;;;;;;;-1:-1:-1;16331:113:1;;;;;:::i;:::-;;:::i;1570:197:3:-;;;;;;;;;;-1:-1:-1;1570:197:3;;;;;:::i;:::-;;:::i;10166:21:1:-;;;;;;;;;;;;;;;;10591:48;;;;;;;;;;-1:-1:-1;10591:48:1;;;;;:::i;:::-;;;;;;;;;;;;;;;;10331:64;;;;;;;;;;-1:-1:-1;10331:64:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20636:25:14;;;20692:2;20677:18;;20670:34;;;;20720:18;;;20713:34;;;;20778:2;20763:18;;20756:34;;;;20821:3;20806:19;;20799:35;20865:3;20850:19;;20843:35;20909:3;20894:19;;20887:35;20953:3;20938:19;;20931:35;20623:3;20608:19;10331:64:1;20590:382:14;16006:177:1;;;;;;;;;;-1:-1:-1;16006:177:1;;;;;:::i;:::-;;:::i;10785:892::-;;;;;;;;;;-1:-1:-1;10785:892:1;;;;;:::i;:::-;;:::i;16188:137::-;;;;;;;;;;-1:-1:-1;16188:137:1;;;;;:::i;:::-;;:::i;20268:979::-;;;;;;;;;;;;;:::i;17891:246::-;;;;;;:::i;:::-;;:::i;10107:18::-;;;;;;;;;;-1:-1:-1;10107:18:1;;;;-1:-1:-1;;;10107:18:1;;;;;;10042:25;;;;;;;;;;-1:-1:-1;10042:25:1;;;;-1:-1:-1;;;;;10042:25:1;;;670:126:3;;;;;;;;;;-1:-1:-1;670:126:3;;;;;:::i;:::-;-1:-1:-1;;;;;770:18:3;743:7;770:18;;;:9;:18;;;;;;;670:126;17119:164:1;;;;;;;;;;-1:-1:-1;17119:164:1;;;;;:::i;:::-;;:::i;18528:366::-;;;;;;;;;;-1:-1:-1;18528:366:1;;;;;:::i;:::-;;:::i;:::-;;;;47384:25:14;;;47440:2;47425:18;;47418:34;;;;47357:18;18528:366:1;47339:119:14;10006:29:1;;;;;;;;;;-1:-1:-1;10006:29:1;;;;-1:-1:-1;;;;;10006:29:1;;;2047:79:12;;;;;;;;;;-1:-1:-1;2085:7:12;2112:6;-1:-1:-1;;;;;2112:6:12;2047:79;;13006:409:1;;;;;;;;;;-1:-1:-1;13006:409:1;;;;;:::i;:::-;;:::i;:::-;;;;50128:25:14;;;50184:2;50169:18;;50162:34;;;;50212:18;;;50205:34;50270:2;50255:18;;50248:34;50115:3;50100:19;13006:409:1;50082:206:14;12467:534:1;;;;;;;;;;-1:-1:-1;12467:534:1;;;;;:::i;:::-;;:::i;11879:94::-;;;;;;;;;;;;;:::i;15537:457::-;;;;;;;;;;;;;:::i;:::-;;;;51048:25:14;;;51104:2;51089:18;;51082:34;;;;51132:18;;;51125:34;;;;51190:2;51175:18;;51168:34;51233:3;51218:19;;51211:35;51277:3;51262:19;;51255:35;51035:3;51020:19;15537:457:1;51002:294:14;1775:197:3;;;;;;;;;;-1:-1:-1;1775:197:3;;;;;:::i;:::-;;:::i;10193:31:1:-;;;;;;;;;;-1:-1:-1;10193:31:1;;;;-1:-1:-1;;;;;10193:31:1;;;10646:52;;;;;;;;;;-1:-1:-1;10646:52:1;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19600:14:14;;19593:22;19575:41;;19647:2;19632:18;;19625:34;;;;19675:18;;;19668:34;;;;19733:2;19718:18;;19711:34;19776:3;19761:19;;19754:35;19820:3;19805:19;;19798:35;19562:3;19547:19;10646:52:1;19529:310:14;10259:23:1;;;;;;;;;;-1:-1:-1;10259:23:1;;;;-1:-1:-1;;;;;10259:23:1;;;954:164:3;;;;;;;;;;-1:-1:-1;954:164:3;;;;;:::i;:::-;;:::i;18899:251:1:-;;;;;;:::i;:::-;;:::i;19158:198::-;;;;;;;;;;;;;:::i;12354:105::-;;;;;;;;;;-1:-1:-1;12436:8:1;:15;12354:105;;10231:24;;;;;;;;;;-1:-1:-1;10231:24:1;;;;-1:-1:-1;;;;;10231:24:1;;;10289:29;;;;;;;;;;;;;;;;17432:454;;;;;;;;;;-1:-1:-1;17432:454:1;;;;;:::i;:::-;;:::i;16561:262::-;;;;;;;;;;-1:-1:-1;16561:262:1;;;;;:::i;:::-;;:::i;10465:26::-;;;;;;;;;;-1:-1:-1;10465:26:1;;;;;:::i;:::-;;:::i;18149:374::-;;;;;;;;;;-1:-1:-1;18149:374:1;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;13420:353::-;;;;;;;;;;-1:-1:-1;13420:353:1;;;;;:::i;:::-;;:::i;21252:294::-;;;;;;;;;;;;;:::i;12114:112::-;;;;;;;;;;;;;:::i;804:142:3:-;;;;;;;;;;-1:-1:-1;804:142:3;;;;;:::i;:::-;-1:-1:-1;;;;;911:18:3;;;884:7;911:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;804:142;14646:886:1;;;;;;;;;;-1:-1:-1;14646:886:1;;;;;:::i;:::-;;:::i;16835:272::-;;;;;;;;;;-1:-1:-1;16835:272:1;;;;;:::i;:::-;;:::i;19361:902::-;;;;;;;;;;-1:-1:-1;19361:902:1;;;;;:::i;:::-;;:::i;10498:25::-;;;;;;;;;;-1:-1:-1;10498:25:1;;;;;:::i;:::-;;:::i;17291:133::-;;;;;;;;;;-1:-1:-1;17291:133:1;;;;;:::i;:::-;;:::i;2493:244:12:-;;;;;;;;;;-1:-1:-1;2493:244:12;;;;;:::i;:::-;;:::i;10402:50:1:-;;;;;;;;;;-1:-1:-1;10402:50:1;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10402:50:1;;;;;;;;;;;45301:6:14;45289:19;;;45271:38;;45340:2;45325:18;;45318:34;;;;45368:18;;;45361:34;;;;45426:2;45411:18;;45404:34;;;;45469:3;45454:19;;45447:35;-1:-1:-1;;;;;45557:15:14;;;45509:3;45536:19;;45529:44;45610:15;45604:3;45589:19;;45582:44;45258:3;45243:19;10402:50:1;45225:407:14;13778:863:1;;;;;;;;;;-1:-1:-1;13778:863:1;;;;;:::i;:::-;;:::i;:::-;;;;48273:25:14;;;48329:2;48314:18;;48307:34;;;;48384:14;48377:22;48357:18;;;48350:50;48261:2;48246:18;13778:863:1;48228:178:14;10138:21:1;;;;;;;;;;-1:-1:-1;10138:21:1;;;;-1:-1:-1;;;10138:21:1;;;;;;11732:142;11826:10;;11838:11;;11859:6;;11810:56;;-1:-1:-1;;;11810:56:1;;-1:-1:-1;;;;;11826:10:1;;;11810:56;;;17401:34:14;11838:11:1;;;17451:18:14;;;17444:43;-1:-1:-1;;;11851:6:1;;;;;17530:14:14;17523:22;17503:18;;;17496:50;17562:18;;;17555:34;11777:13:1;;11810:10;;:15;;17335:19:14;;11810:56:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11810:56:1;;;;;;;;;;;;:::i;:::-;11803:63;;11732:142;:::o;1404:158:3:-;1478:4;1495:37;1504:10;1516:7;1525:6;1495:8;:37::i;:::-;-1:-1:-1;1550:4:3;1404:158;;;;;:::o;1126:270::-;-1:-1:-1;;;;;1275:19:3;;1223:4;1275:19;;;:11;:19;;;;;;;;1263:10;1275:31;;;;;;;;1240:79;;1255:6;;1275:43;;1311:6;1275:35;:43::i;:::-;1240:14;:79::i;:::-;1330:36;1340:6;1348:9;1359:6;1330:9;:36::i;:::-;-1:-1:-1;1384:4:3;1126:270;;;;;;:::o;16450:106:1:-;16507:16;:14;:16::i;:::-;16528:23;16542:8;16528:13;:23::i;:::-;16450:106;:::o;11981:128::-;12030:5;12055:46;12088:12;:10;:12::i;:::-;12055:32;:46::i;16331:113::-;16393:16;:14;:16::i;:::-;16414:25;16427:11;16414:12;:25::i;1570:197:3:-;1671:10;1645:4;1692:23;;;:11;:23;;;;;;;;-1:-1:-1;;;;;1692:32:3;;;;;;;;;;1645:4;;1662:75;;1683:7;;1692:44;;1729:6;1692:36;:44::i;:::-;1662:8;:75::i;16006:177:1:-;16114:16;:14;:16::i;:::-;16141:34;;;;;;;;16165:9;16141:34;:::i;:::-;:23;:34::i;10785:892::-;10859:10;;-1:-1:-1;;;;;10859:10:1;:24;:53;;;;-1:-1:-1;10887:11:1;;-1:-1:-1;;;;;10887:11:1;:25;10859:53;10851:69;;;;-1:-1:-1;;;10851:69:1;;36937:2:14;10851:69:1;;;36919:21:14;36976:1;36956:18;;;36949:29;-1:-1:-1;;;36994:18:14;;;36987:33;37037:18;;10851:69:1;;;;;;;;;10962:20;;;;;;;;:::i;:::-;-1:-1:-1;;;;;10939:43:1;:19;;;;;;;;:::i;:::-;-1:-1:-1;;;;;10939:43:1;;;10931:59;;;;-1:-1:-1;;;10931:59:1;;21898:2:14;10931:59:1;;;21880:21:14;21937:1;21917:18;;;21910:29;-1:-1:-1;;;21955:18:14;;;21948:33;21998:18;;10931:59:1;21870:152:14;10931:59:1;11011:12;:10;:12::i;:::-;11061:19;;;;:8;:19;:::i;:::-;11036:10;:45;;-1:-1:-1;;;;;;11036:45:1;-1:-1:-1;;;;;11036:45:1;;;;;;;;;;11105:19;;;;;;;;:::i;:::-;11092:10;:32;;-1:-1:-1;;;;;;11092:32:1;-1:-1:-1;;;;;11092:32:1;;;;;;;;;;11149:20;;;;;;;;:::i;:::-;11135:11;:34;;-1:-1:-1;;;;;;11135:34:1;-1:-1:-1;;;;;11135:34:1;;;;;;;;;;11189:15;;;;;;;;:::i;:::-;11180:6;:24;;;;;-1:-1:-1;;;11180:24:1;-1:-1:-1;;;;11180:24:1;;;;;;;;;11227:18;;;;11180:24;11227:18;;;:::i;:::-;11215:9;:30;;;;;-1:-1:-1;;;11215:30:1;-1:-1:-1;;;;11215:30:1;;;;;;;;;11265:15;;;;11256:6;:24;11289:43;;;;;;;;11308:23;;;11289:43;:::i;:::-;:18;:43::i;:::-;11337:29;11351:14;;;;;;;;:::i;:::-;11337:13;:29::i;:::-;11371:55;;;;;;;;11395:30;;;11371:55;:::i;:::-;11437:43;11456:8;:23;;;11437:18;:43::i;:::-;11491:31;11504:17;;;;;;;;:::i;:::-;11491:12;:31::i;:::-;11533:39;11551:20;;;;;;;;:::i;:::-;11533:17;:39::i;:::-;11615:53;11648:19;;;;;;;;:::i;11615:53::-;11601:68;;11607:62;;11601:2;:68;:::i;:::-;11579:19;:90;-1:-1:-1;10785:892:1:o;16188:137::-;16262:16;:14;:16::i;:::-;16283:37;16302:17;16283:18;:37::i;20268:979::-;20317:16;:14;:16::i;:::-;20354:18;20383:15;20409:16;20440:6;;;;;;;;;;;20436:301;;;20494:11;;20476:30;;-1:-1:-1;;;;;20494:11:1;20476:17;:30::i;:::-;20531:10;;20567:11;;20463:43;;-1:-1:-1;;;;;;20531:10:1;;;;-1:-1:-1;20567:11:1;;-1:-1:-1;20436:301:1;;;20642:10;;20624:29;;-1:-1:-1;;;;;20642:10:1;20624:17;:29::i;:::-;20678:11;;20715:10;;20611:42;;-1:-1:-1;;;;;;20678:11:1;;;;-1:-1:-1;20715:10:1;;-1:-1:-1;20436:301:1;20768:1;20755:10;:14;20747:30;;;;-1:-1:-1;;;20747:30:1;;34923:2:14;20747:30:1;;;34905:21:14;34962:1;34942:18;;;34935:29;-1:-1:-1;;;34980:18:14;;;34973:33;35023:18;;20747:30:1;34895:152:14;20747:30:1;20792:19;-1:-1:-1;;;;;284:22:0;;20826:81:1;;-1:-1:-1;20885:10:1;20826:81;20971:29;;20946:125;;-1:-1:-1;;;20946:125:1;;-1:-1:-1;;;;;17858:15:14;;;20946:125:1;;;17840:34:14;17910:15;;;17890:18;;;17883:43;17942:18;;;17935:34;;;20917:26:1;;20971:29;;20946:74;;21028:11;;17775:18:14;;20946:125:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;20917:154;;21086:17;:15;:17::i;:::-;21082:91;;;21120:41;21142:18;21120:21;:41::i;:::-;21190:49;;;47384:25:14;;;47440:2;47425:18;;47418:34;;;21190:49:1;;47357:18:14;21190:49:1;;;;;;;20268:979;;;;;:::o;17891:246::-;18045:7;18072:57;18081:16;18099:9;18110:2;18114:14;18072:8;:57::i;:::-;18065:64;;17891:246;;;;;;;:::o;17119:164::-;17215:20;:18;:20::i;:::-;17246:29;;;;;;;;17265:9;17246:29;:::i;18528:366::-;18693:27;18725:28;18815:71;18833:6;18841:13;18856:7;18865:20;18815:17;:71::i;:::-;18769:117;;;;-1:-1:-1;18528:366:1;-1:-1:-1;;;;;18528:366:1:o;13006:409::-;13092:17;;;;13279:14;13361:46;13368:8;13378:11;13279:14;13361:6;:46::i;:::-;-1:-1:-1;13304:103:1;;;;-1:-1:-1;13304:103:1;-1:-1:-1;13304:103:1;;-1:-1:-1;13006:409:1;-1:-1:-1;;;;13006:409:1:o;12467:534::-;12524:4;12542:19;12563:20;12585:12;12599:20;12621:19;12644:21;12656:8;12644:11;:21::i;:::-;12541:124;;;;;;;;;;12674:66;12695:8;12705:11;12718:12;12732:7;12674:20;:66::i;:::-;12670:301;;;12810:29;;12757:13;;12773:67;;12783:11;;12796:12;;-1:-1:-1;;;;;12810:29:1;12773:9;:67::i;:::-;12862:97;;-1:-1:-1;;;12862:97:1;;12757:83;;-1:-1:-1;12862:10:1;;:40;;:97;;12903:12;;12917:11;;12757:83;;12937:21;;12862:97;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12855:104;12467:534;-1:-1:-1;;;;;;;;12467:534:1:o;12670:301::-;-1:-1:-1;12988:5:1;;12467:534;-1:-1:-1;;;;;;12467:534:1:o;11879:94::-;11926:13;11959:6;:4;:6::i;15537:457::-;15595:25;15625:26;15656:24;15691:32;15734:34;15773:18;15823:13;642:12:3;;;555:107;15823:13:1;15810:26;;15962:24;15981:4;15962:18;:24::i;:::-;15847:139;;;;-1:-1:-1;15847:139:1;;-1:-1:-1;15847:139:1;-1:-1:-1;15847:139:1;;-1:-1:-1;15537:457:1;;-1:-1:-1;;15537:457:1:o;1775:197:3:-;1876:10;1850:4;1897:23;;;:11;:23;;;;;;;;-1:-1:-1;;;;;1897:32:3;;;;;;;;;;1850:4;;1867:75;;1888:7;;1897:44;;1934:6;1897:36;:44::i;954:164::-;1031:4;1048:40;1058:10;1070:9;1081:6;1048:9;:40::i;18899:251:1:-;19087:55;19093:8;19103:11;19116;19129:2;19133:8;19087:5;:55::i;:::-;18899:251;;;;;:::o;19158:198::-;19220:8;:15;19203:146;19237:5;;19203:146;;19264:16;19283:8;19292:5;19296:1;19292;:5;:::i;:::-;19283:15;;;;;;-1:-1:-1;;;19283:15:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19283:15:1;;-1:-1:-1;19313:24:1;19283:15;19313:14;:24::i;:::-;-1:-1:-1;19244:3:1;;;:::i;:::-;;;19203:146;;17432:454;17516:20;:18;:20::i;:::-;17564:10;;-1:-1:-1;;;;;17555:19:1;;;17564:10;;17555:19;;;;:43;;-1:-1:-1;17587:11:1;;-1:-1:-1;;;;;17578:20:1;;;17587:11;;17578:20;;17555:43;:67;;;;-1:-1:-1;;;;;;17603:14:1;;;;;;:7;:14;;;;;:19;;;17602:20;17555:67;:116;;;;;17628:17;:15;:17::i;:::-;17627:18;:43;;;-1:-1:-1;17658:12:1;;-1:-1:-1;;;;;17649:21:1;;;17658:12;;17649:21;;17627:43;17547:132;;;;-1:-1:-1;;;17547:132:1;;27615:2:14;17547:132:1;;;27597:21:14;27654:1;27634:18;;;27627:29;-1:-1:-1;;;27672:18:14;;;27665:33;27715:18;;17547:132:1;27587:152:14;17547:132:1;17690:16;17709:55;17743:5;17758:4;17709:33;:55::i;:::-;17690:74;-1:-1:-1;17779:12:1;;17775:104;;17808:59;17838:5;17845:11;17858:8;17808:29;:59::i;:::-;17432:454;;;:::o;16561:262::-;16649:20;:18;:20::i;:::-;-1:-1:-1;;;;;16716:28:1;;;;;;:16;:28;;;;;;;16685:75;;;;;;16716:28;;;;16685:75;;;;;;-1:-1:-1;;;;;16771:28:1;;;;;;;;:16;:28;;;;;:44;;-1:-1:-1;;16771:44:1;;;;;;;;;;16561:262::o;10465:26::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10465:26:1;;-1:-1:-1;10465:26:1;:::o;18149:374::-;18259:27;18291:28;18324:21;18350:27;18457:58;18477:6;18485:7;18494:20;18457:19;:58::i;:::-;18393:122;;;;-1:-1:-1;18393:122:1;-1:-1:-1;18393:122:1;;-1:-1:-1;18149:374:1;-1:-1:-1;;;;18149:374:1:o;13420:353::-;13494:7;13517:25;13547:30;13572:4;13547:24;:30::i;:::-;-1:-1:-1;13514:63:1;-1:-1:-1;;;13594:22:1;13590:176;;-1:-1:-1;13640:16:1;;13420:353;-1:-1:-1;13420:353:1:o;13590:176::-;13696:58;13736:17;13696:35;13717:13;642:12:3;;;555:107;13717:13:1;13696:16;;:20;:35::i;:::-;:39;;:58::i;21252:294::-;21298:17;:15;:17::i;:::-;21290:33;;;;-1:-1:-1;;;21290:33:1;;22229:2:14;21290:33:1;;;22211:21:14;22268:1;22248:18;;;22241:29;-1:-1:-1;;;22286:18:14;;;22279:33;22329:18;;21290:33:1;22201:152:14;21290:33:1;21378:11;;21331:26;;21360:30;;-1:-1:-1;;;;;21378:11:1;21360:17;:30::i;:::-;21331:59;-1:-1:-1;21402:22:1;;21398:141;;21438:41;21460:18;21438:21;:41::i;:::-;21496:34;;45783:25:14;;;21496:34:1;;45771:2:14;45756:18;21496:34:1;;;;;;;21252:294;:::o;12114:112::-;12184:6;;12156:7;;-1:-1:-1;;;12184:6:1;;;;:33;;-1:-1:-1;12206:11:1;;-1:-1:-1;;;;;12206:11:1;;11732:142::o;12184:33::-;-1:-1:-1;12193:10:1;;-1:-1:-1;;;;;12193:10:1;;12114:112::o;14646:886::-;14725:27;14757:28;14790:21;14816:27;14862:20;14885:13;642:12:3;;;555:107;14885:13:1;14862:36;;14923:1;14914:6;:10;:36;;;;;14938:12;14928:6;:22;;14914:36;14910:615;;;15074:10;;15086:11;;15121:12;;15023:111;;-1:-1:-1;;;15023:111:1;;;;;46108:25:14;;;-1:-1:-1;;;;;15074:10:1;;;46187:18:14;;;46180:43;15086:11:1;;;46239:18:14;;;46232:43;-1:-1:-1;;;15099:6:1;;;;;46318:14:14;46311:22;46291:18;;;46284:50;46350:19;;;46343:35;;;15121:12:1;;;;46394:19:14;;;46387:44;15023:10:1;;:42;;46080:19:14;;15023:111:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15174:8;:15;14977:157;;-1:-1:-1;14977:157:1;-1:-1:-1;15160:30:1;;;;;;-1:-1:-1;;;15160:30:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15160:30:1;-1:-1:-1;15232:8:1;:15;15153:37;;-1:-1:-1;15218:30:1;;;;;;-1:-1:-1;;;15218:30:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15218:30:1;;15205:43;;15259:9;15254:266;15278:8;:15;15274:19;;15254:266;;;15307:16;15326:8;15335:1;15326:11;;;;;;-1:-1:-1;;;15326:11:1;;;;;;;;;;;;;;;;;;15361:62;;-1:-1:-1;;;15361:62:1;;15417:4;15361:62;;;16759:51:14;-1:-1:-1;;;;;15326:11:1;;;;-1:-1:-1;15326:11:1;;15361:47;;16732:18:14;;15361:62:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15344:79;;15446:8;15436:4;15441:1;15436:7;;;;;;-1:-1:-1;;;15436:7:1;;;;;;;;;-1:-1:-1;;;;;15436:18:1;;;:7;;;;;;;;;;;:18;15477:36;15500:12;15477:18;:6;15488;15477:10;:18::i;:36::-;15461:10;15472:1;15461:13;;;;;;-1:-1:-1;;;15461:13:1;;;;;;;;;;;;;;:52;;;;;15254:266;;15295:3;;;;:::i;:::-;;;15254:266;;;;14910:615;14646:886;;;;;;:::o;16835:272::-;16925:20;:18;:20::i;:::-;-1:-1:-1;;;;;16996:32:1;;;;;;:20;:32;;;;;;;16961:81;;;;;;16996:32;;;;16961:81;;;;;;-1:-1:-1;;;;;17053:32:1;;;;;;;;:20;:32;;;;;:46;;-1:-1:-1;;17053:46:1;;;;;;;;;;16835:272::o;19361:902::-;-1:-1:-1;;;;;19448:17:1;;19415:30;19448:17;;;:7;:17;;;;;19474:9;;;;:64;;;;;19523:15;19497:8;-1:-1:-1;;;;;19487:30:1;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:51;;19474:64;19470:786;;;19560:17;;-1:-1:-1;;19560:17:1;;;19603:8;:15;19572:5;;19603:19;;19560:17;;19603:19;:::i;:::-;19647:14;;;;19583:39;;-1:-1:-1;19674:18:1;;;19670:154;;19707:12;19722:8;19731:9;19722:19;;;;;;-1:-1:-1;;;19722:19:1;;;;;;;;;;;;;;;;;;;19751:8;:15;;-1:-1:-1;;;;;19722:19:1;;;;-1:-1:-1;19722:19:1;;19760:5;;19751:15;;;;-1:-1:-1;;;19751:15:1;;;;;;;;;;;;;;;;;;;;;:22;;-1:-1:-1;;;;;;19751:22:1;-1:-1:-1;;;;;19751:22:1;;;;;;19783:13;;;;;;:7;:13;;;;;;:23;;:31;;;19670:154;19849:1;19832:14;;;:18;19865:8;:14;;;;;-1:-1:-1;;;19865:14:1;;;;;;;;;;;;;;;;-1:-1:-1;;19865:14:1;;;;;;;-1:-1:-1;;;;;;19865:14:1;;;;;;;;;19900:62;;-1:-1:-1;;;19900:62:1;;19956:4;19900:62;;;16759:51:14;-1:-1:-1;;;;;19900:47:1;;;;;16732:18:14;;19900:62:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:66;19896:256;;;20015:8;-1:-1:-1;;;;;20005:26:1;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19979:23;;;:54;20047:17;:15;:17::i;:::-;20043:94;;;20080:46;20102:4;:23;;;20080:21;:46::i;:::-;20187:14;;;;20203:21;;;;20226:23;;;;20167:83;;;49243:25:14;;;49299:2;49284:18;;49277:34;;;;49327:18;;;49320:34;-1:-1:-1;;;;;20167:83:1;;;;;49231:2:14;49216:18;20167:83:1;;;;;;;19470:786;;;19361:902;;:::o;10498:25::-;;;;;;;;;;;;17291:133;17361:20;:18;:20::i;:::-;17386:33;17404:14;17386:17;:33::i;2493:244:12:-;2259:6;;-1:-1:-1;;;;;2259:6:12;698:10;2259:22;2251:67;;;;-1:-1:-1;;;2251:67:12;;31760:2:14;2251:67:12;;;31742:21:14;;;31779:18;;;31772:30;31838:34;31818:18;;;31811:62;31890:18;;2251:67:12;31732:182:14;2251:67:12;-1:-1:-1;;;;;2582:22:12;::::1;2574:73;;;::::0;-1:-1:-1;;;2574:73:12;;23894:2:14;2574:73:12::1;::::0;::::1;23876:21:14::0;23933:2;23913:18;;;23906:30;23972:34;23952:18;;;23945:62;-1:-1:-1;;;24023:18:14;;;24016:36;24069:19;;2574:73:12::1;23866:228:14::0;2574:73:12::1;2684:6;::::0;;2663:38:::1;::::0;-1:-1:-1;;;;;2663:38:12;;::::1;::::0;2684:6;::::1;::::0;2663:38:::1;::::0;::::1;2712:6;:17:::0;;-1:-1:-1;;;;;;2712:17:12::1;-1:-1:-1::0;;;;;2712:17:12;;;::::1;::::0;;;::::1;::::0;;2493:244::o;13778:863:1:-;13859:27;13891:28;13924:15;13958:20;13981:13;642:12:3;;;555:107;13981:13:1;13958:36;;14012:1;14003:6;:10;:36;;;;;14027:12;14017:6;:22;;14003:36;13999:635;;;14053:25;14095:26;14138:25;14180:34;14218:31;14243:5;14218:24;:31::i;:::-;14450:6;;14337:291;;-1:-1:-1;;;14337:291:1;;;;;48728:25:14;;;48769:18;;;48762:34;;;-1:-1:-1;;;14450:6:1;;;;;48839:14:14;48832:22;48812:18;;;48805:50;48871:18;;;48864:34;;;48914:19;;;48907:35;;;48958:19;;;48951:35;;;49002:19;;;48995:35;;;48864:34;;-1:-1:-1;48907:35:14;;-1:-1:-1;48951:35:14;-1:-1:-1;48995:35:14;-1:-1:-1;14337:10:1;;:38;;48700:19:14;;14337:291:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14279:349;;-1:-1:-1;14279:349:1;-1:-1:-1;14279:349:1;-1:-1:-1;;;;;13999:635:1;13778:863;;;;;;:::o;2140:140:3:-;2234:38;2249:5;2256:7;2265:6;2234:14;:38::i;3234:98:13:-;3292:7;3319:5;3323:1;3319;:5;:::i;2964:358:3:-;-1:-1:-1;;;;;3064:19:3;;3056:68;;;;-1:-1:-1;;;3056:68:3;;39667:2:14;3056:68:3;;;39649:21:14;39706:2;39686:18;;;39679:30;39745:34;39725:18;;;39718:62;-1:-1:-1;;;39796:18:14;;;39789:34;39840:19;;3056:68:3;39639:226:14;3056:68:3;-1:-1:-1;;;;;3143:21:3;;3135:72;;;;-1:-1:-1;;;3135:72:3;;33518:2:14;3135:72:3;;;33500:21:14;33557:2;33537:18;;;33530:30;33596:34;33576:18;;;33569:62;-1:-1:-1;;;33647:18:14;;;33640:36;33693:19;;3135:72:3;33490:228:14;3135:72:3;-1:-1:-1;;;;;3220:18:3;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;3282:32;;45783:25:14;;;3282:32:3;;45756:18:14;3282:32:3;;;;;;;;2964:358;;;:::o;1984:148::-;2082:42;2098:6;2106:9;2117:6;2082:15;:42::i;38184:98:1:-;38243:9;;-1:-1:-1;;;;;38243:9:1;38256:10;38243:23;38235:39;;;;-1:-1:-1;;;38235:39:1;;24632:2:14;38235:39:1;;;24614:21:14;24671:1;24651:18;;;24644:29;-1:-1:-1;;;24689:18:14;;;24682:33;24732:18;;38235:39:1;24604:152:14;38235:39:1;38184:98::o;36220:187::-;-1:-1:-1;;;;;36289:22:1;;36281:38;;;;-1:-1:-1;;;36281:38:1;;39336:2:14;36281:38:1;;;39318:21:14;39375:1;39355:18;;;39348:29;-1:-1:-1;;;39393:18:14;;;39386:33;39436:18;;36281:38:1;39308:152:14;36281:38:1;36348:9;;36335:33;;-1:-1:-1;;;;;36335:33:1;;;;36348:9;;36335:33;;36348:9;;36335:33;36379:9;:20;;-1:-1:-1;;;;;;36379:20:1;-1:-1:-1;;;;;36379:20:1;;;;;;;;;;36220:187::o;1700:376:0:-;1764:5;-1:-1:-1;;;;;284:22:0;;1782:287;;-1:-1:-1;1831:2:0;;1700:376;-1:-1:-1;1700:376:0:o;1782:287::-;1926:34;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1926:34:0;-1:-1:-1;;;1926:34:0;;;1909:52;;1868:12;;;;-1:-1:-1;;;;;1909:16:0;;;:52;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1867:94;;;;1984:7;1976:28;;;;-1:-1:-1;;;1976:28:0;;29674:2:14;1976:28:0;;;29656:21:14;29713:1;29693:18;;;29686:29;-1:-1:-1;;;29731:18:14;;;29724:38;29779:18;;1976:28:0;29646:157:14;1976:28:0;2037:10;2026:31;;;;;;;;;;;;:::i;1782:287::-;1700:376;;;:::o;35977:235:1:-;2085:7:12;2112:6;-1:-1:-1;;;;;2112:6:12;36048:56:1;;-1:-1:-1;;;36048:56:1;;-1:-1:-1;;;;;16777:32:14;;;36048:56:1;;;16759:51:14;36048:43:1;;;;;;;16732:18:14;;36048:56:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36040:72;;;;-1:-1:-1;;;36040:72:1;;24301:2:14;36040:72:1;;;24283:21:14;24340:1;24320:18;;;24313:29;-1:-1:-1;;;24358:18:14;;;24351:33;24401:18;;36040:72:1;24273:152:14;36040:72:1;36148:8;;36128:43;;-1:-1:-1;;;;;36128:43:1;;;;36148:8;;36128:43;;36148:8;;36128:43;36182:8;:22;;-1:-1:-1;;;;;;36182:22:1;-1:-1:-1;;;;;36182:22:1;;;;;;;;;;35977:235::o;2853:98:13:-;2911:7;2938:5;2942:1;2938;:5;:::i;34853:871:1:-;8393:6;34968:9;:32;;;:63;:130;;;;-1:-1:-1;35035:32:1;;8393:6;-1:-1:-1;34968:130:1;34960:146;;;;-1:-1:-1;;;34960:146:1;;32856:2:14;34960:146:1;;;32838:21:14;32895:1;32875:18;;;32868:29;-1:-1:-1;;;32913:18:14;;;32906:33;32956:18;;34960:146:1;32828:152:14;34960:146:1;35160:32;;;;35125;;:67;;:115;;;35238:1;35196:9;:32;;;:44;35125:115;35117:131;;;;-1:-1:-1;;;35117:131:1;;35254:2:14;35117:131:1;;;35236:21:14;35293:1;35273:18;;;35266:29;-1:-1:-1;;;35311:18:14;;;35304:33;35354:18;;35117:131:1;35226:152:14;35117:131:1;35302:9;:32;;;35267:9;:32;;;:67;:115;;;;35380:1;35338:9;:32;;;:44;35267:115;35259:131;;;;-1:-1:-1;;;35259:131:1;;33925:2:14;35259:131:1;;;33907:21:14;33964:1;33944:18;;;33937:29;-1:-1:-1;;;33982:18:14;;;33975:33;34025:18;;35259:131:1;33897:152:14;35259:131:1;35436:9;:24;;;35409:9;:24;;;:51;:84;;;-1:-1:-1;35464:24:1;;;;:29;35409:84;35401:100;;;;-1:-1:-1;;;35401:100:1;;25625:2:14;35401:100:1;;;25607:21:14;25664:1;25644:18;;;25637:29;-1:-1:-1;;;25682:18:14;;;25675:33;25725:18;;35401:100:1;25597:152:14;35401:100:1;35547:9;:23;;;35520:9;:23;;;:50;;35512:66;;;;-1:-1:-1;;;35512:66:1;;23232:2:14;35512:66:1;;;23214:21:14;23271:1;23251:18;;;23244:29;-1:-1:-1;;;23289:18:14;;;23282:33;23332:18;;35512:66:1;23204:152:14;35512:66:1;35604:58;35629:21;35652:9;35604:58;;;;;;;:::i;:::-;;;;;;;;35683:33;;:21;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34853:871::o;1729:237:12:-;1791:1;1773:6;-1:-1:-1;;;;;1773:6:12;:20;1765:62;;;;-1:-1:-1;;;1765:62:12;;36579:2:14;1765:62:12;;;36561:21:14;36618:2;36598:18;;;36591:30;36657:31;36637:18;;;36630:59;36706:18;;1765:62:12;36551:179:14;1765:62:12;1838:17;1881:18;;-1:-1:-1;;;;;;1881:18:12;698:10;1881:18;;;;;1915:43;;698:10;;;;1915:43;;1838:17;;1915:43;1729:237;:::o;36415:1086:1:-;36532:10;;36576:11;;36625:24;;;;36600:86;;-1:-1:-1;;;36600:86:1;;-1:-1:-1;;;;;36532:10:1;;;36600:86;;;17033:34:14;;;36576:11:1;;;17083:18:14;;;17076:43;;;36532:10:1;;36510:19;;36600:59;;;;16968:18:14;;36600:86:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:90;36592:106;;;;-1:-1:-1;;;36592:106:1;;36248:2:14;36592:106:1;;;36230:21:14;36287:1;36267:18;;;36260:29;-1:-1:-1;;;36305:18:14;;;36298:33;36348:18;;36592:106:1;36220:152:14;36592:106:1;36717:24;;;;-1:-1:-1;;;;;36717:38:1;36709:54;;;;-1:-1:-1;;;36709:54:1;;29012:2:14;36709:54:1;;;28994:21:14;29051:1;29031:18;;;29024:29;-1:-1:-1;;;29069:18:14;;;29062:33;29112:18;;36709:54:1;28984:152:14;36709:54:1;36799:5;36782:9;:13;;;:22;;36774:38;;;;-1:-1:-1;;;36774:38:1;;29343:2:14;36774:38:1;;;29325:21:14;29382:1;29362:18;;;29355:29;-1:-1:-1;;;29400:18:14;;;29393:33;29443:18;;36774:38:1;29315:152:14;36774:38:1;8393:6;36831:9;:37;;;:61;;36823:77;;;;-1:-1:-1;;;36823:77:1;;26953:2:14;36823:77:1;;;26935:21:14;26992:1;26972:18;;;26965:29;-1:-1:-1;;;27010:18:14;;;27003:33;27053:18;;36823:77:1;26925:152:14;36823:77:1;8393:6;36919:9;:41;;;:64;36911:80;;;;-1:-1:-1;;;36911:80:1;;22560:2:14;36911:80:1;;;22542:21:14;22599:1;22579:18;;;22572:29;-1:-1:-1;;;22617:18:14;;;22610:33;22660:18;;36911:80:1;22532:152:14;36911:80:1;37037:1;37010:9;:24;;;:28;37002:44;;;;-1:-1:-1;;;37002:44:1;;27284:2:14;37002:44:1;;;27266:21:14;27323:1;27303:18;;;27296:29;-1:-1:-1;;;27341:18:14;;;27334:33;27384:18;;37002:44:1;27256:152:14;37002:44:1;37067:6;;-1:-1:-1;;;37067:6:1;;;;37063:314;;;-1:-1:-1;;;;;284:22:0;;;37090:140:1;;37153:61;37175:12;37189:9;:24;;;37153:21;:61::i;:::-;37063:314;;;-1:-1:-1;;;;;284:22:0;;;37247:130:1;;37305:60;37327:11;37340:9;:24;;;37305:21;:60::i;:::-;37402:44;37420:14;37436:9;37402:44;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;37467:26:1;;:14;:26;;-1:-1:-1;;37467:26:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;37467:26:1;;;-1:-1:-1;;;;;37467:26:1;;;;;;;;;;;;;;;;;;;;;;;36415:1086::o;35732:233::-;35835:1;35815:17;:21;35807:37;;;;-1:-1:-1;;;35807:37:1;;21567:2:14;35807:37:1;;;21549:21:14;21606:1;21586:18;;;21579:29;-1:-1:-1;;;21624:18:14;;;21617:33;21667:18;;35807:37:1;21539:152:14;35807:37:1;35878:14;;35860:52;;35894:17;;35878:14;35860:52;;;;;35923:14;:34;35732:233::o;37509:535::-;37596:11;;-1:-1:-1;;;;;37596:11:1;37588:34;37580:50;;;;-1:-1:-1;;;37580:50:1;;35585:2:14;37580:50:1;;;35567:21:14;35624:1;35604:18;;;35597:29;-1:-1:-1;;;35642:18:14;;;35635:33;35685:18;;37580:50:1;35557:152:14;37580:50:1;-1:-1:-1;;;;;37655:28:1;;;;;;:39;;-1:-1:-1;37688:6:1;;-1:-1:-1;;;37688:6:1;;;;37687:7;37655:39;37651:386;;;37772:11;;37728:56;;-1:-1:-1;;;37728:56:1;;-1:-1:-1;;;;;37772:11:1;;;37728:56;;;16759:51:14;37728:43:1;;;;;;16732:18:14;;37728:56:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:70;;;37713:12;:85;;-1:-1:-1;;;;;;37713:85:1;-1:-1:-1;;;;;37713:85:1;;;;;;37835:11;;37813:50;;37835:11;37848:14;37813:21;:50::i;:::-;37896:11;:42;;-1:-1:-1;;;;;;37896:42:1;-1:-1:-1;;;;;37896:42:1;;;;;;;;37960:32;;;;-1:-1:-1;;37960:32:1;38009:16;:14;:16::i;34303:154::-;34367:7;34394:55;34428:5;34443:4;34394:33;:55::i;33411:126::-;33485:6;;33460:4;;-1:-1:-1;;;33485:6:1;;;;33484:7;:45;;;;-1:-1:-1;;33503:11:1;;-1:-1:-1;;;;;33503:11:1;33495:34;;;33411:126::o;33545:166::-;33612:11;;33632;;33668:14;:34;33612:91;;-1:-1:-1;;;33612:91:1;;-1:-1:-1;;;;;33632:11:1;;;33612:91;;;18906:34:14;18956:18;;;18949:34;;;33661:4:1;18999:18:14;;;18992:43;33668:34:1;;;;19051:18:14;;;19044:47;33612:11:1;;;:19;;18840::14;;33612:91:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23293:1290;23439:14;23466:20;:18;:20::i;:::-;23524:1;23505:16;:20;23497:36;;;;-1:-1:-1;;;23497:36:1;;27946:2:14;23497:36:1;;;27928:21:14;27985:1;27965:18;;;27958:29;-1:-1:-1;;;28003:18:14;;;27996:33;28046:18;;23497:36:1;27918:152:14;23497:36:1;-1:-1:-1;;;;;23552:16:1;;;;;;:39;;-1:-1:-1;;;;;;23572:19:1;;23586:4;23572:19;;23552:39;23544:55;;;;-1:-1:-1;;;23544:55:1;;30767:2:14;23544:55:1;;;30749:21:14;30806:1;30786:18;;;30779:29;-1:-1:-1;;;30824:18:14;;;30817:33;30867:18;;23544:55:1;30739:152:14;23544:55:1;23619:14;23618:15;:36;;;;23637:17;:15;:17::i;:::-;23610:52;;;;-1:-1:-1;;;23610:52:1;;38337:2:14;23610:52:1;;;38319:21:14;38376:1;38356:18;;;38349:29;-1:-1:-1;;;38394:18:14;;;38387:33;38437:18;;23610:52:1;38309:152:14;23610:52:1;23674:25;23704:30;23729:4;23704:24;:30::i;:::-;23671:63;;;;;23741:19;23763:12;:10;:12::i;:::-;23741:34;-1:-1:-1;;;;;;284:22:0;;23780:115:1;;23857:32;:17;23879:9;23857:21;:32::i;:::-;23837:52;;23780:115;23919:22;23915:180;;23967:16;23958:25;;23915:180;;;24025:58;24065:17;24025:35;24046:13;642:12:3;;;555:107;24046:13:1;24025:16;;:20;:35::i;:58::-;24016:67;;23915:180;24123:9;24113:6;:19;;24105:35;;;;-1:-1:-1;;;24105:35:1;;31098:2:14;24105:35:1;;;31080:21:14;31137:1;31117:18;;;31110:29;-1:-1:-1;;;31155:18:14;;;31148:33;31198:18;;24105:35:1;31070:152:14;24105:35:1;24157:14;24153:310;;;24217:12;;24188:60;;-1:-1:-1;;;;;24217:12:1;24231:16;24188:28;:60::i;:::-;24153:310;;;24281:59;24310:11;24323:16;24281:28;:59::i;:::-;24359:17;:15;:17::i;:::-;24355:97;;;24397:39;24419:16;24397:21;:39::i;:::-;24483:29;24501:2;24505:6;24483:17;:29::i;:::-;24538:37;;;47384:25:14;;;47440:2;47425:18;;47418:34;;;-1:-1:-1;;;;;24538:37:1;;;;;47357:18:14;24538:37:1;;;;;;;23293:1290;;;;;;;;:::o;38294:100::-;38368:10;38357:7;2085::12;2112:6;-1:-1:-1;;;;;2112:6:12;;2047:79;38357:7:1;-1:-1:-1;;;;;38357:21:1;;38349:37;;;;-1:-1:-1;;;38349:37:1;;24963:2:14;38349:37:1;;;24945:21:14;25002:1;24982:18;;;24975:29;-1:-1:-1;;;25020:18:14;;;25013:33;25063:18;;38349:37:1;24935:152:14;25521:857:1;25699:27;25731:28;25792:1;25783:6;:10;25775:26;;;;-1:-1:-1;;;25775:26:1;;23563:2:14;25775:26:1;;;23545:21:14;23602:1;23582:18;;;23575:29;-1:-1:-1;;;23620:18:14;;;23613:33;23663:18;;25775:26:1;23535:152:14;25775:26:1;25821:20;25820:21;:42;;;;25845:17;:15;:17::i;:::-;25812:58;;;;-1:-1:-1;;;25812:58:1;;26622:2:14;25812:58:1;;;26604:21:14;26661:1;26641:18;;;26634:29;-1:-1:-1;;;26679:18:14;;;26672:33;26722:18;;25812:58:1;26594:152:14;25812:58:1;25885:17;:15;:17::i;:::-;25917:20;25940:13;642:12:3;;;555:107;25940:13:1;25917:36;;25964:26;25974:7;25983:6;25964:9;:26::i;:::-;26057:73;26086:6;26094:12;26108:13;26123:6;;;;;;;;;;;26057:28;:73::i;:::-;26011:119;;-1:-1:-1;26011:119:1;-1:-1:-1;26151:89:1;26011:119;;26219:20;26151:24;:89::i;:::-;-1:-1:-1;;;;;26260:110:1;;;26278:6;26286:4;26292:19;26313:20;26349:1;26335:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26335:16:1;-1:-1:-1;26353:16:1;;;26367:1;26353:16;;;;;;;;;26260:110;;;;;;;;:::i;:::-;;;;;;;;25521:857;;;;;;;;:::o;21890:1000::-;22058:17;22087:19;22118:23;22153:18;22183:24;22248:1;22234:11;:15;22226:31;;;;-1:-1:-1;;;22226:31:1;;40072:2:14;22226:31:1;;;40054:21:14;40111:1;40091:18;;;40084:29;-1:-1:-1;;;40129:18:14;;;40122:33;40172:18;;22226:31:1;40044:152:14;22226:31:1;22278:34;22315:42;22335:8;22345:11;22315:19;:42::i;:::-;22278:79;;22380:90;22401:8;22411;:19;;;22432:8;:20;;;22454:8;:15;;;22380:20;:90::i;:::-;22372:106;;;;-1:-1:-1;;;22372:106:1;;25294:2:14;22372:106:1;;;25276:21:14;25333:1;25313:18;;;25306:29;-1:-1:-1;;;25351:18:14;;;25344:33;25394:18;;22372:106:1;25266:152:14;22372:106:1;22515:19;;;;22536:20;;;;22558:30;;;;22505:84;;22515:19;22536:20;-1:-1:-1;;;;;22558:30:1;22505:9;:84::i;:::-;22672:209;;;;;;;;;22701:12;;;-1:-1:-1;;;;;22701:12:1;;;22672:209;;22722:8;;;22672:209;;;;22739:14;;22672:209;;;;22762:19;;;;22672:209;;;;;;;;;;;;;;;22814:19;;22672:209;;;;;;;;;;;;;;;;;;;;;;22859:21;22672:209;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22655:227;;-1:-1:-1;;;22655:227:1;;22487:102;;-1:-1:-1;22655:10:1;;:16;;:227;;22672:209;22655:227;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22598:284;;;;-1:-1:-1;21890:1000:1;;-1:-1:-1;22598:284:1;;-1:-1:-1;22598:284:1;-1:-1:-1;21890:1000:1;;-1:-1:-1;;;;21890:1000:1:o;21554:331::-;21844:10;;;:33;;-1:-1:-1;;;21844:33:1;;-1:-1:-1;;;;;16777:32:14;;;21844:33:1;;;16759:51:14;;;;21625:19:1;;;;;;;;;;21844:10;;:23;;16732:18:14;;21844:33:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21780:97;;;;-1:-1:-1;21780:97:1;;-1:-1:-1;21780:97:1;-1:-1:-1;21780:97:1;;-1:-1:-1;21554:331:1;-1:-1:-1;;21554:331:1:o;33857:441::-;34014:10;;33984:4;;-1:-1:-1;;;;;33999:25:1;;;34014:10;;33999:25;:56;;;;-1:-1:-1;34044:11:1;;-1:-1:-1;;;;;34028:27:1;;;34044:11;;34028:27;33999:56;:77;;;;;34070:6;;;;;;;;;;;34059:17;;:7;:17;;;33999:77;33995:299;;;34105:10;;;:29;;-1:-1:-1;;;34105:29:1;;-1:-1:-1;;;;;16777:32:14;;;34105:29:1;;;16759:51:14;;;;34087:15:1;;34105:10;;;;:19;;16732:18:14;;34105:29:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;34152:29:1;;;;;;:20;:29;;;;;;34087:47;;-1:-1:-1;34152:29:1;;34151:30;:93;;;;-1:-1:-1;34186:28:1;;;:16;:28;;;;;;;:57;;-1:-1:-1;;;;;;34218:25:1;;;;;;:16;:25;;;;;;;;34186:57;34143:102;;;;;33995:299;-1:-1:-1;34280:5:1;34273:12;;34463:213;34595:76;;-1:-1:-1;;;34595:76:1;;-1:-1:-1;;;;;17051:15:14;;;34595:76:1;;;17033:34:14;17103:15;;;17083:18;;;17076:43;34571:7:1;;34595:49;;;;;;16968:18:14;;34595:76:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;27720:1174::-;28151:10;;28163:11;;28176:30;;27796:25;;;;;;;;;;;;28093:14;;27796:25;;28141:66;;-1:-1:-1;;;;;28151:10:1;;;;28163:11;;;;28176:30;28141:9;:66::i;:::-;28394:471;;;;;;;;;;;;;28465:6;;;-1:-1:-1;;;28465:6:1;;;28394:471;;;;;;;;;;;;;;;;28518:14;;28394:471;;;;28548:47;;;;28394:471;;;;28611:43;;;;28394:471;;;;28670:19;;;;28394:471;;;;28705:19;;28394:471;;;;28740:10;;-1:-1:-1;;;;;28740:10:1;;;28465:6;28394:471;;;28766:11;;;28394:471;;;;28793:8;;;;28394:471;;;;28825:10;;;;;28394:471;;;;28852:12;;;;;28394:471;;;;28351:535;;-1:-1:-1;;;28351:535:1;;28115:92;;-1:-1:-1;28351:10:1;;:28;;:535;;28394:471;28877:8;;28351:535;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28218:668;;;;-1:-1:-1;28218:668:1;;-1:-1:-1;28218:668:1;-1:-1:-1;28218:668:1;-1:-1:-1;28218:668:1;;-1:-1:-1;27720:1174:1;-1:-1:-1;;;;27720:1174:1:o;29772:953::-;29980:8;29961:15;:27;;29953:43;;;;-1:-1:-1;;;29953:43:1;;37675:2:14;29953:43:1;;;37657:21:14;37714:1;37694:18;;;37687:29;-1:-1:-1;;;37732:18:14;;;37725:33;37775:18;;29953:43:1;37647:152:14;29953:43:1;-1:-1:-1;;;;;30015:16:1;;;;;;:34;;;30041:8;-1:-1:-1;;;;;30035:14:1;:2;-1:-1:-1;;;;;30035:14:1;;;30015:34;:57;;;;-1:-1:-1;;;;;;30053:19:1;;30067:4;30053:19;;30015:57;30007:73;;;;-1:-1:-1;;;30007:73:1;;33187:2:14;30007:73:1;;;33169:21:14;33226:1;33206:18;;;33199:29;-1:-1:-1;;;33244:18:14;;;33237:33;33287:18;;30007:73:1;33159:152:14;30007:73:1;30156:14;30101:52;;;;;30295:46;30302:8;30312:11;30156:14;30295:6;:46::i;:::-;30181:160;;;;;;;;;;30362:98;30379:2;30383:8;30393:16;30411:11;30424;30437:9;30448:11;30362:16;:98::i;:::-;30477:15;;30473:135;;30539:11;;30552:30;;;;30509:87;;-1:-1:-1;;;;;30539:11:1;;;;30552:30;30584:11;30509:29;:87::i;:::-;30633:84;;;50552:25:14;;;50608:2;50593:18;;50586:34;;;50636:18;;;50629:34;;;50694:2;50679:18;;50672:34;;;50737:3;50722:19;;50715:35;;;-1:-1:-1;;;;;30633:84:1;;;;;;;;;;50539:3:14;50524:19;30633:84:1;;;;;;;29772:953;;;;;;;;;;;:::o;2470:414:0:-;2552:7;-1:-1:-1;;;;;284:22:0;;2572:305;;-1:-1:-1;;;;;;2615:15:0;;;2608:22;;2572:305;2722:43;;;-1:-1:-1;;;;;16777:32:14;;;2722:43:0;;;;16759:51:14;;;;2722:43:0;;;;;;;;;;16732:18:14;;;;2722:43:0;;;;;;;-1:-1:-1;;;;;2722:43:0;-1:-1:-1;;;2722:43:0;;;2705:61;;2664:12;;;;2705:16;;;;:61;;2722:43;2705:61;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2663:103;;;;2789:7;2781:29;;;;-1:-1:-1;;;2781:29:0;;38999:2:14;2781:29:0;;;38981:21:14;39038:1;39018:18;;;39011:29;-1:-1:-1;;;39056:18:14;;;39049:39;39105:18;;2781:29:0;38971:158:14;2781:29:0;2843:10;2832:33;;;;;;;;;;;;:::i;:::-;2825:40;;;;;;3322:304;-1:-1:-1;;;;;284:22:0;;3409:210;;3485:12;;;3446;3485;;;;;;;;;-1:-1:-1;;;;;3463:7:0;;;3477:6;;3463:35;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3445:53;;;3521:7;3513:24;;;;-1:-1:-1;;;3513:24:0;;;;;;35916:2:14;35898:21;;;35955:1;35935:18;;;35928:29;-1:-1:-1;;;35988:2:14;35973:18;;35966:34;36032:2;36017:18;;35888:153;3513:24:0;3409:210;17432:454:1;;;:::o;3409:210:0:-;3570:37;3589:5;3596:2;3600:6;3570:18;:37::i;24588:921:1:-;24699:27;24731:28;24764:21;24790:27;24850:1;24841:6;:10;24833:26;;;;-1:-1:-1;;;24833:26:1;;38006:2:14;24833:26:1;;;37988:21:14;38045:1;38025:18;;;38018:29;-1:-1:-1;;;38063:18:14;;;38056:33;38106:18;;24833:26:1;37978:152:14;24833:26:1;24879:20;24878:21;:42;;;;24903:17;:15;:17::i;:::-;24870:58;;;;-1:-1:-1;;;24870:58:1;;34592:2:14;24870:58:1;;;34574:21:14;34631:1;34611:18;;;34604:29;-1:-1:-1;;;34649:18:14;;;34642:33;34692:18;;24870:58:1;34564:152:14;24870:58:1;24943:17;:15;:17::i;:::-;24975:20;24998:13;642:12:3;;;555:107;24998:13:1;24975:36;;25022:26;25032:7;25041:6;25022:9;:26::i;:::-;25160:10;;25172:11;;25207:12;;25109:111;;-1:-1:-1;;;25109:111:1;;;;;46108:25:14;;;-1:-1:-1;;;;;25160:10:1;;;46187:18:14;;;46180:43;25172:11:1;;;46239:18:14;;;46232:43;-1:-1:-1;;;25185:6:1;;;;;46318:14:14;46311:22;46291:18;;;46284:50;46350:19;;;46343:35;;;25207:12:1;;;;46394:19:14;;;46387:44;25109:10:1;;:42;;46080:19:14;;25109:111:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;25063:157;;-1:-1:-1;25063:157:1;-1:-1:-1;25250:44:1;25273:6;25281:12;25250:22;:44::i;:::-;25229:65;;-1:-1:-1;25229:65:1;-1:-1:-1;25301:89:1;25326:19;25347:20;25369;25301:24;:89::i;:::-;25417:7;-1:-1:-1;;;;;25408:93:1;;25426:6;25434:5;25441:19;25462:20;25484:4;25490:10;25408:93;;;;;;;;;;;:::i;:::-;;;;;;;;24588:921;;;;;;;;:::o;27103:605::-;27185:25;27222:26;27260:25;27296:34;27349:24;27384:32;27560:29;27579:9;27560:18;:29::i;:::-;27427:162;;-1:-1:-1;27427:162:1;;-1:-1:-1;27427:162:1;;-1:-1:-1;27427:162:1;;-1:-1:-1;27427:162:1;;-1:-1:-1;27427:162:1;-1:-1:-1;27631:69:1;27427:162;27631:39;27427:162;;27631:21;:39::i;:::-;:43;;:69::i;:::-;27611:89;;27103:605;;;;;;;:::o;3591:98:13:-;3649:7;3676:5;3680:1;3676;:5;:::i;3990:98::-;4048:7;4075:5;4079:1;4075;:5;:::i;2500:452:3:-;-1:-1:-1;;;;;2604:20:3;;2596:71;;;;-1:-1:-1;;;2596:71:3;;37268:2:14;2596:71:3;;;37250:21:14;37307:2;37287:18;;;37280:30;37346:34;37326:18;;;37319:62;-1:-1:-1;;;37397:18:14;;;37390:36;37443:19;;2596:71:3;37240:228:14;2596:71:3;-1:-1:-1;;;;;2686:23:3;;2678:77;;;;-1:-1:-1;;;2678:77:3;;30010:2:14;2678:77:3;;;29992:21:14;30049:2;30029:18;;;30022:30;30088:34;30068:18;;;30061:62;-1:-1:-1;;;30139:18:14;;;30132:39;30188:19;;2678:77:3;29982:231:14;2678:77:3;-1:-1:-1;;;;;2788:17:3;;;;;;:9;:17;;;;;;:29;;2810:6;2788:21;:29::i;:::-;-1:-1:-1;;;;;2768:17:3;;;;;;;:9;:17;;;;;;:49;;;;2851:20;;;;;;;:32;;2876:6;2851:24;:32::i;:::-;-1:-1:-1;;;;;2828:20:3;;;;;;;:9;:20;;;;;;;:55;;;;2909:35;;;;;;;;;;2937:6;45783:25:14;;45771:2;45756:18;;45738:76;34681:164:1;34764:73;34797:5;34804:7;-1:-1:-1;;34764:32:1;:73::i;38056:116::-;38120:9;;-1:-1:-1;;;38120:9:1;;;;38119:10;;:37;;-1:-1:-1;38133:9:1;;-1:-1:-1;;;;;38133:9:1;38146:10;38133:23;38119:37;38111:53;;;;-1:-1:-1;;;38111:53:1;;26291:2:14;38111:53:1;;;26273:21:14;26330:1;26310:18;;;26303:29;-1:-1:-1;;;26348:18:14;;;26341:33;26391:18;;38111:53:1;26263:152:14;3634:328:0;-1:-1:-1;;;;;284:22:0;;3708:247;;3765:6;3752:9;:19;3744:50;;;;-1:-1:-1;;;3744:50:0;;30420:2:14;3744:50:0;;;30402:21:14;30459:2;30439:18;;;30432:30;-1:-1:-1;;;30478:18:14;;;30471:48;30536:18;;3744:50:0;30392:168:14;3708:247:0;3835:9;:14;3827:37;;;;-1:-1:-1;;;3827:37:0;;40403:2:14;3827:37:0;;;40385:21:14;40442:2;40422:18;;;40415:30;-1:-1:-1;;;40461:18:14;;;40454:40;40511:18;;3827:37:0;40375:160:14;3827:37:0;3879:64;3902:5;3909:10;3929:4;3936:6;3879:22;:64::i;3334:328:3:-;-1:-1:-1;;;;;3416:21:3;;3408:69;;;;-1:-1:-1;;;3408:69:3;;32452:2:14;3408:69:3;;;32434:21:14;32491:2;32471:18;;;32464:30;32530:34;32510:18;;;32503:62;-1:-1:-1;;;32581:18:14;;;32574:33;32624:19;;3408:69:3;32424:225:14;3408:69:3;3505:12;;:24;;3522:6;3505:16;:24::i;:::-;3490:12;:39;-1:-1:-1;;;;;3561:18:3;;;;;;:9;:18;;;;;;:30;;3584:6;3561:22;:30::i;:::-;-1:-1:-1;;;;;3540:18:3;;;;;;:9;:18;;;;;;:51;;;;3617:37;;3540:18;;;3617:37;;;;3647:6;45783:25:14;;45771:2;45756:18;;45738:76;3617:37:3;;;;;;;;3334:328;;:::o;29520:247:1:-;-1:-1:-1;;;;;29601:21:1;;29612:10;29601:21;29597:163;;;29639:39;29657:7;29666:11;29639:17;:39::i;29597:163::-;29711:37;29727:7;29736:11;29711:15;:37::i;28906:609::-;29091:27;29123:28;29168:25;29206:26;29245:25;29275:31;29300:5;29275:24;:31::i;:::-;-1:-1:-1;29365:142:1;;-1:-1:-1;;;29365:142:1;;;;;51618:25:14;;;51659:18;;;51652:34;;;51702:18;;;51695:34;;;51745:18;;;51738:34;;;51788:19;;;51781:35;;;51832:19;;;51825:35;;;51904:14;;51897:22;51876:19;;;51869:51;29167:139:1;;-1:-1:-1;29167:139:1;;-1:-1:-1;29167:139:1;-1:-1:-1;29365:10:1;;:38;;51590:19:14;;29365:142:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29319:188;;;;-1:-1:-1;28906:609:1;-1:-1:-1;;;;;;;;28906:609:1:o;26386:712::-;26566:24;;26562:395;;26611:20;26607:339;;;26676:12;;26646:77;;-1:-1:-1;;;;;26676:12:1;26690:10;26702:20;26646:29;:77::i;:::-;26607:339;;;26743:17;:15;:17::i;:::-;26739:207;;;26775:56;26798:20;26820:10;26775:22;:56::i;26739:207::-;26890:11;;26860:76;;-1:-1:-1;;;;;26890:11:1;26903:10;26915:20;26860:29;:76::i;:::-;26971:23;;26967:124;;27035:10;;27005:74;;-1:-1:-1;;;;;27035:10:1;27047;27059:19;27005:29;:74::i;22902:382::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23140:21:1;23152:8;23140:11;:21::i;:::-;23183:92;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23183:92:1;;;;;;;;;;;;-1:-1:-1;23183:92:1;;22902:382;-1:-1:-1;;;;;;22902:382:1:o;30733:1979::-;31009:10;30996:9;:23;;30988:39;;;;-1:-1:-1;;;30988:39:1;;32121:2:14;30988:39:1;;;32103:21:14;32160:1;32140:18;;;32133:29;-1:-1:-1;;;32178:18:14;;;32171:33;32221:18;;30988:39:1;32093:152:14;30988:39:1;31071:11;;-1:-1:-1;;;;;31071:11:1;31048:20;284:22:0;31121:322:1;;31200:9;31187;:22;;31179:38;;;;-1:-1:-1;;;31179:38:1;;38668:2:14;31179:38:1;;;38650:21:14;38707:1;38687:18;;;38680:29;-1:-1:-1;;;38725:18:14;;;38718:33;38768:18;;31179:38:1;38640:152:14;31179:38:1;31240:24;:9;31254;31240:13;:24::i;:::-;31232:32;;31121:322;;;31305:9;:14;31297:30;;;;-1:-1:-1;;;31297:30:1;;28277:2:14;31297:30:1;;;28259:21:14;28316:1;28296:18;;;28289:29;-1:-1:-1;;;28334:18:14;;;28327:33;28377:18;;31297:30:1;28249:152:14;31297:30:1;31342:89;31380:12;31394:10;31414:4;31421:9;31342:37;:89::i;:::-;31463:17;31483:26;:9;31497:11;31483:13;:26::i;:::-;31463:46;;31534:17;:15;:17::i;:::-;31530:120;;;31568:70;31591:31;:16;31612:9;31591:20;:31::i;:::-;31632:4;31568:22;:70::i;:::-;31664:19;31686:12;:10;:12::i;:::-;-1:-1:-1;;;;;31742:17:1;;;31709:30;31742:17;;;:7;:17;;;;;31664:34;;-1:-1:-1;284:22:0;;31764:283:1;;31836:8;-1:-1:-1;;;;;31826:31:1;;31865:16;31826:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31812:72;;31764:283;;;31907:9;;;;31902:78;;31925:44;31947:11;31960:8;31925:21;:44::i;:::-;31999:42;;-1:-1:-1;;;31999:42:1;;;;;45783:25:14;;;-1:-1:-1;;;;;31999:24:1;;;;;45756:18:14;;31999:42:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31985:56;;31764:283;32058:9;;;;32053:443;;32110:29;;32092:8;:15;:47;32084:63;;;;-1:-1:-1;;;32084:63:1;;31429:2:14;32084:63:1;;;31411:21:14;31468:1;31448:18;;;31441:29;-1:-1:-1;;;31486:18:14;;;31479:33;31529:18;;32084:63:1;31401:152:14;32084:63:1;32173:90;;;;;;;;32191:4;32173:90;;;;;;32197:9;32173:90;;;;32208:16;32173:90;;;;32226:1;32173:90;;;;32229:9;:16;;;;32173:90;;;;32247:8;:15;;;;32173:90;;;32153:7;:17;32161:8;-1:-1:-1;;;;;32153:17:1;-1:-1:-1;;;;;32153:17:1;;;;;;;;;;;;:110;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32278:9;32293:8;32278:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;32278:24:1;;;;;-1:-1:-1;;;;;32278:24:1;;;;;;32321:8;32335;32321:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;32321:23:1;;;;;-1:-1:-1;;;;;32321:23:1;;;;;;32053:443;;;32416:21;;;;32395:43;;:16;;:20;:43::i;:::-;32371:21;;;:67;32475:14;;;;32461:29;;:9;;:13;:29::i;:::-;32444:14;;;:46;32053:443;32516:60;32550:8;32560:2;32564:11;32516:33;:60::i;:::-;32601:9;;32597:108;;32627:62;32657:12;32671:10;32683:5;32627:29;:62::i;:::-;30733:1979;;;;;;;;;;;;:::o;638:314:0:-;789:53;;;-1:-1:-1;;;;;18172:32:14;;;789:53:0;;;18154:51:14;18221:18;;;;18214:34;;;789:53:0;;;;;;;;;;18127:18:14;;;;789:53:0;;;;;;;-1:-1:-1;;;;;789:53:0;-1:-1:-1;;;789:53:0;;;778:65;;-1:-1:-1;;;;778:10:0;;;;:65;;789:53;778:65;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;736:107;;;;862:7;:69;;;;-1:-1:-1;874:17:0;;:22;;:56;;;911:10;900:30;;;;;;;;;;;;:::i;:::-;854:90;;;;-1:-1:-1;;;854:90:0;;34256:2:14;854:90:0;;;34238:21:14;34295:1;34275:18;;;34268:29;-1:-1:-1;;;34313:18:14;;;34306:38;34361:18;;854:90:0;34228:157:14;32717:686:1;32908:8;:15;32814:21;;;;32908:15;32941:19;;;;;;-1:-1:-1;;;32941:19:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32941:19:1;;32934:26;;32998:4;32984:19;;;;;;-1:-1:-1;;;32984:19:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32984:19:1;;32971:32;;33013:9;33008:391;33032:4;33028:1;:8;33008:391;;;33049:16;33068:8;33077:1;33068:11;;;;;;-1:-1:-1;;;33068:11:1;;;;;;;;;;;;;;;;;;33102:62;;-1:-1:-1;;;33102:62:1;;33158:4;33102:62;;;16759:51:14;-1:-1:-1;;;;;33068:11:1;;;;-1:-1:-1;33068:11:1;;33102:47;;16732:18:14;;33102:62:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;33085:79;;33185:8;33175:4;33180:1;33175:7;;;;;;-1:-1:-1;;;33175:7:1;;;;;;;;;-1:-1:-1;;;;;33175:18:1;;;:7;;;;;;;;;;;:18;33215:36;33238:12;33215:18;:6;33226;33215:10;:18::i;:36::-;33199:10;33210:1;33199:13;;;;;;-1:-1:-1;;;33199:13:1;;;;;;;;;;;;;;:52;;;;;33291:1;33275:10;33286:1;33275:13;;;;;;-1:-1:-1;;;33275:13:1;;;;;;;;;;;;;;;:17;33271:123;;;33314:8;-1:-1:-1;;;;;33304:47:1;;33352:10;33364;33375:1;33364:13;;;;;;-1:-1:-1;;;33364:13:1;;;;;;;;;;;;;;;33304:74;;;;;;;;;;;;;;;-1:-1:-1;;;;;18172:32:14;;;;18154:51;;18236:2;18221:18;;18214:34;18142:2;18127:18;;18109:145;33304:74:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33271:123;33008:391;;33038:3;;;;:::i;:::-;;;33008:391;;;;32717:686;;;;;;:::o;322:308:0:-;470:51;;;-1:-1:-1;;;;;18172:32:14;;;470:51:0;;;18154::14;18221:18;;;;18214:34;;;470:51:0;;;;;;;;;;18127:18:14;;;;470:51:0;;;;;;;-1:-1:-1;;;;;470:51:0;-1:-1:-1;;;470:51:0;;;459:63;;-1:-1:-1;;;;459:10:0;;;;:63;;470:51;459:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;417:105;;;;541:7;:69;;;;-1:-1:-1;553:17:0;;:22;;:56;;;590:10;579:30;;;;;;;;;;;;:::i;:::-;533:89;;;;-1:-1:-1;;;533:89:0;;25956:2:14;533:89:0;;;25938:21:14;25995:1;25975:18;;;25968:29;-1:-1:-1;;;26013:18:14;;;26006:37;26060:18;;533:89:0;25928:156:14;961:346:0;1132:61;;;-1:-1:-1;;;;;17858:15:14;;;1132:61:0;;;17840:34:14;17910:15;;;17890:18;;;17883:43;17942:18;;;;17935:34;;;1132:61:0;;;;;;;;;;17775:18:14;;;;1132:61:0;;;;;;;-1:-1:-1;;;;;1132:61:0;-1:-1:-1;;;1132:61:0;;;1121:73;;-1:-1:-1;;;;1121:10:0;;;;:73;;1132:61;1121:73;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1079:115;;;;1213:7;:69;;;;-1:-1:-1;1225:17:0;;:22;;:56;;;1262:10;1251:30;;;;;;;;;;;;:::i;:::-;1205:94;;;;-1:-1:-1;;;1205:94:0;;22891:2:14;1205:94:0;;;22873:21:14;22930:2;22910:18;;;22903:30;-1:-1:-1;;;22949:18:14;;;22942:42;23001:18;;1205:94:0;22863:162:14;1205:94:0;961:346;;;;;;:::o;3670:328:3:-;-1:-1:-1;;;;;3752:21:3;;3744:69;;;;-1:-1:-1;;;3744:69:3;;28608:2:14;3744:69:3;;;28590:21:14;28647:2;28627:18;;;28620:30;28686:34;28666:18;;;28659:62;-1:-1:-1;;;28737:18:14;;;28730:33;28780:19;;3744:69:3;28580:225:14;3744:69:3;-1:-1:-1;;;;;3847:18:3;;;;;;:9;:18;;;;;;:30;;3870:6;3847:22;:30::i;:::-;-1:-1:-1;;;;;3826:18:3;;;;;;:9;:18;;;;;:51;3903:12;;:24;;3920:6;3903:16;:24::i;:::-;3888:12;:39;3953:37;;45783:25:14;;;3979:1:3;;-1:-1:-1;;;;;3953:37:3;;;;;45771:2:14;45756:18;3953:37:3;45738:76:14;2292:200:3;-1:-1:-1;;;;;2400:20:3;;;;;;:11;:20;;;;;;;;2388:10;2400:32;;;;;;;;;2364:81;;2379:7;;2400:44;;2437:6;2400:36;:44::i;2364:81::-;2456:28;2468:7;2477:6;2456:11;:28::i;33719:133:1:-;33799:11;;33820;;33799:45;;-1:-1:-1;;;33799:45:1;;-1:-1:-1;;;;;33820:11:1;;;33799:45;;;18499:34:14;18549:18;;;18542:34;;;18612:15;;;18592:18;;;18585:43;33799:11:1;;;:20;;18434:18:14;;33799:45:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;14:134:14:-;82:20;;111:31;82:20;111:31;:::i;153:138::-;232:13;;254:31;232:13;254:31;:::i;296:434::-;377:5;425:4;413:9;408:3;404:19;400:30;397:2;;;447:5;440;433:20;397:2;484;478:9;526:4;518:6;514:17;597:6;585:10;582:22;561:18;549:10;546:34;543:62;540:2;;;608:18;;:::i;:::-;644:2;637:22;707:16;;692:32;;-1:-1:-1;677:6:14;387:343;-1:-1:-1;387:343:14:o;735:192::-;814:13;;867:34;856:46;;846:57;;836:2;;917:1;914;907:12;932:169;1010:13;;1063:12;1052:24;;1042:35;;1032:2;;1091:1;1088;1081:12;1106:160;1183:13;;1236:4;1225:16;;1215:27;;1205:2;;1256:1;1253;1246:12;1271:257;1330:6;1383:2;1371:9;1362:7;1358:23;1354:32;1351:2;;;1404:6;1396;1389:22;1351:2;1448:9;1435:23;1467:31;1492:5;1467:31;:::i;1533:261::-;1603:6;1656:2;1644:9;1635:7;1631:23;1627:32;1624:2;;;1677:6;1669;1662:22;1624:2;1714:9;1708:16;1733:31;1758:5;1733:31;:::i;1799:398::-;1867:6;1875;1928:2;1916:9;1907:7;1903:23;1899:32;1896:2;;;1949:6;1941;1934:22;1896:2;1993:9;1980:23;2012:31;2037:5;2012:31;:::i;:::-;2062:5;-1:-1:-1;2119:2:14;2104:18;;2091:32;2132:33;2091:32;2132:33;:::i;:::-;2184:7;2174:17;;;1886:311;;;;;:::o;2202:647::-;2305:6;2313;2321;2329;2337;2390:3;2378:9;2369:7;2365:23;2361:33;2358:2;;;2412:6;2404;2397:22;2358:2;2449:9;2443:16;2468:31;2493:5;2468:31;:::i;:::-;2568:2;2553:18;;2547:25;2518:5;;-1:-1:-1;2581:33:14;2547:25;2581:33;:::i;:::-;2685:2;2670:18;;2664:25;2633:7;;-1:-1:-1;2698:30:14;2664:25;2698:30;:::i;:::-;2794:2;2779:18;;2773:25;2838:3;2823:19;;;2817:26;2348:501;;;;-1:-1:-1;2747:7:14;2773:25;2817:26;2348:501;-1:-1:-1;;;2348:501:14:o;2854:466::-;2931:6;2939;2947;3000:2;2988:9;2979:7;2975:23;2971:32;2968:2;;;3021:6;3013;3006:22;2968:2;3065:9;3052:23;3084:31;3109:5;3084:31;:::i;:::-;3134:5;-1:-1:-1;3191:2:14;3176:18;;3163:32;3204:33;3163:32;3204:33;:::i;:::-;2958:362;;3256:7;;-1:-1:-1;;;3310:2:14;3295:18;;;;3282:32;;2958:362::o;3325:392::-;3390:6;3398;3451:2;3439:9;3430:7;3426:23;3422:32;3419:2;;;3472:6;3464;3457:22;3419:2;3516:9;3503:23;3535:31;3560:5;3535:31;:::i;:::-;3585:5;-1:-1:-1;3642:2:14;3627:18;;3614:32;3655:30;3614:32;3655:30;:::i;3722:325::-;3790:6;3798;3851:2;3839:9;3830:7;3826:23;3822:32;3819:2;;;3872:6;3864;3857:22;3819:2;3916:9;3903:23;3935:31;3960:5;3935:31;:::i;:::-;3985:5;4037:2;4022:18;;;;4009:32;;-1:-1:-1;;;3809:238:14:o;4052:604::-;4147:6;4155;4163;4171;4179;4232:3;4220:9;4211:7;4207:23;4203:33;4200:2;;;4254:6;4246;4239:22;4200:2;4298:9;4285:23;4317:31;4342:5;4317:31;:::i;:::-;4367:5;-1:-1:-1;4419:2:14;4404:18;;4391:32;;-1:-1:-1;4470:2:14;4455:18;;4442:32;;-1:-1:-1;4526:2:14;4511:18;;4498:32;4539:33;4498:32;4539:33;:::i;:::-;4190:466;;;;-1:-1:-1;4190:466:14;;4645:3;4630:19;4617:33;;4190:466;-1:-1:-1;;4190:466:14:o;4661:251::-;4717:6;4770:2;4758:9;4749:7;4745:23;4741:32;4738:2;;;4791:6;4783;4776:22;4738:2;4835:9;4822:23;4854:28;4876:5;4854:28;:::i;4917:255::-;4984:6;5037:2;5025:9;5016:7;5012:23;5008:32;5005:2;;;5058:6;5050;5043:22;5005:2;5095:9;5089:16;5114:28;5136:5;5114:28;:::i;5177:924::-;5257:6;5310:2;5298:9;5289:7;5285:23;5281:32;5278:2;;;5331:6;5323;5316:22;5278:2;5369:9;5363:16;5398:18;5439:2;5431:6;5428:14;5425:2;;;5460:6;5452;5445:22;5425:2;5503:6;5492:9;5488:22;5478:32;;5548:7;5541:4;5537:2;5533:13;5529:27;5519:2;;5575:6;5567;5560:22;5519:2;5609;5603:9;5631:2;5627;5624:10;5621:2;;;5637:18;;:::i;:::-;5712:2;5706:9;5680:2;5766:13;;-1:-1:-1;;5762:22:14;;;5786:2;5758:31;5754:40;5742:53;;;5810:18;;;5830:22;;;5807:46;5804:2;;;5856:18;;:::i;:::-;5896:10;5892:2;5885:22;5931:2;5923:6;5916:18;5971:7;5966:2;5961;5957;5953:11;5949:20;5946:33;5943:2;;;5997:6;5989;5982:22;5943:2;6015:55;6067:2;6062;6054:6;6050:15;6045:2;6041;6037:11;6015:55;:::i;:::-;6089:6;5268:833;-1:-1:-1;;;;;;;5268:833:14:o;6106:205::-;6193:6;6246:3;6234:9;6225:7;6221:23;6217:33;6214:2;;;6268:6;6260;6253:22;6214:2;-1:-1:-1;6296:9:14;6204:107;-1:-1:-1;6204:107:14:o;6316:222::-;6420:6;6473:3;6461:9;6452:7;6448:23;6444:33;6441:2;;;6495:6;6487;6480:22;6543:958;6645:6;6676:3;6720:2;6708:9;6699:7;6695:23;6691:32;6688:2;;;6741:6;6733;6726:22;6688:2;6779;6773:9;6809:15;;;;6854:18;6839:34;;6875:22;;;6836:62;6833:2;;;6901:18;;:::i;:::-;6941:10;6937:2;6930:22;6989:9;6976:23;6968:6;6961:39;7061:2;7050:9;7046:18;7033:32;7028:2;7020:6;7016:15;7009:57;7127:2;7116:9;7112:18;7099:32;7094:2;7086:6;7082:15;7075:57;7193:2;7182:9;7178:18;7165:32;7160:2;7152:6;7148:15;7141:57;7260:3;7249:9;7245:19;7232:33;7226:3;7218:6;7214:16;7207:59;7328:3;7317:9;7313:19;7300:33;7294:3;7286:6;7282:16;7275:59;7396:3;7385:9;7381:19;7368:33;7362:3;7354:6;7350:16;7343:59;7464:3;7453:9;7449:19;7436:33;7430:3;7422:6;7418:16;7411:59;7489:6;7479:16;;;;6656:845;;;;:::o;7506:215::-;7603:6;7656:3;7644:9;7635:7;7631:23;7627:33;7624:2;;;7678:6;7670;7663:22;7726:814;7821:6;7874:3;7862:9;7853:7;7849:23;7845:33;7842:2;;;7896:6;7888;7881:22;7842:2;7927:17;;:::i;:::-;7981:9;7968:23;8035:6;8026:7;8022:20;8013:7;8010:33;8000:2;;8062:6;8054;8047:22;8000:2;8094:7;8087:5;8080:22;;8162:2;8151:9;8147:18;8134:32;8129:2;8122:5;8118:14;8111:56;8227:2;8216:9;8212:18;8199:32;8194:2;8187:5;8183:14;8176:56;8292:2;8281:9;8277:18;8264:32;8259:2;8252:5;8248:14;8241:56;8358:3;8347:9;8343:19;8330:33;8324:3;8317:5;8313:15;8306:58;8397:39;8431:3;8420:9;8416:19;8397:39;:::i;:::-;8391:3;8384:5;8380:15;8373:64;8470:39;8504:3;8493:9;8489:19;8470:39;:::i;:::-;8464:3;8453:15;;8446:64;8457:5;7832:708;-1:-1:-1;;;7832:708:14:o;8545:1348::-;8644:6;8697:3;8685:9;8676:7;8672:23;8668:33;8665:2;;;8719:6;8711;8704:22;8665:2;8750:22;;:::i;:::-;8795:72;8859:7;8848:9;8795:72;:::i;:::-;8788:5;8781:87;8900:49;8945:2;8934:9;8930:18;8900:49;:::i;:::-;8895:2;8888:5;8884:14;8877:73;8982:49;9027:2;9016:9;9012:18;8982:49;:::i;:::-;8977:2;8970:5;8966:14;8959:73;9064:49;9109:2;9098:9;9094:18;9064:49;:::i;:::-;9059:2;9052:5;9048:14;9041:73;9147:50;9192:3;9181:9;9177:19;9147:50;:::i;:::-;9141:3;9134:5;9130:15;9123:75;9231:50;9276:3;9265:9;9261:19;9231:50;:::i;:::-;9225:3;9218:5;9214:15;9207:75;9315:49;9359:3;9348:9;9344:19;9315:49;:::i;:::-;9309:3;9302:5;9298:15;9291:74;9398:50;9443:3;9432:9;9428:19;9398:50;:::i;:::-;9392:3;9385:5;9381:15;9374:75;9468:3;9503:49;9548:2;9537:9;9533:18;9503:49;:::i;:::-;9487:14;;;9480:73;9572:3;9607:49;9637:18;;;9607:49;:::i;:::-;9591:14;;;9584:73;9676:3;9711:49;9741:18;;;9711:49;:::i;:::-;9695:14;;;9688:73;9780:3;9815:47;9843:18;;;9815:47;:::i;:::-;9799:14;;;9792:71;9803:5;8655:1238;-1:-1:-1;;;8655:1238:14:o;9898:190::-;9957:6;10010:2;9998:9;9989:7;9985:23;9981:32;9978:2;;;10031:6;10023;10016:22;9978:2;-1:-1:-1;10059:23:14;;9968:120;-1:-1:-1;9968:120:14:o;10093:194::-;10163:6;10216:2;10204:9;10195:7;10191:23;10187:32;10184:2;;;10237:6;10229;10222:22;10184:2;-1:-1:-1;10265:16:14;;10174:113;-1:-1:-1;10174:113:14:o;10292:460::-;10366:6;10374;10382;10435:2;10423:9;10414:7;10410:23;10406:32;10403:2;;;10456:6;10448;10441:22;10403:2;10497:9;10484:23;10474:33;;10557:2;10546:9;10542:18;10529:32;10570:31;10595:5;10570:31;:::i;:::-;10620:5;-1:-1:-1;10677:2:14;10662:18;;10649:32;10690:30;10649:32;10690:30;:::i;:::-;10739:7;10729:17;;;10393:359;;;;;:::o;10757:255::-;10836:6;10844;10897:2;10885:9;10876:7;10872:23;10868:32;10865:2;;;10918:6;10910;10903:22;10865:2;-1:-1:-1;;10946:16:14;;11002:2;10987:18;;;10981:25;10946:16;;10981:25;;-1:-1:-1;10855:157:14:o;11017:529::-;11100:6;11108;11116;11124;11177:3;11165:9;11156:7;11152:23;11148:33;11145:2;;;11199:6;11191;11184:22;11145:2;11240:9;11227:23;11217:33;;11297:2;11286:9;11282:18;11269:32;11259:42;;11351:2;11340:9;11336:18;11323:32;11364:31;11389:5;11364:31;:::i;:::-;11414:5;-1:-1:-1;11471:2:14;11456:18;;11443:32;11484:30;11443:32;11484:30;:::i;:::-;11135:411;;;;-1:-1:-1;11135:411:14;;-1:-1:-1;;11135:411:14:o;11551:377::-;11636:6;11644;11652;11705:2;11693:9;11684:7;11680:23;11676:32;11673:2;;;11726:6;11718;11711:22;11673:2;11760:9;11754:16;11744:26;;11810:2;11799:9;11795:18;11789:25;11779:35;;11857:2;11846:9;11842:18;11836:25;11870:28;11892:5;11870:28;:::i;11933:378::-;12030:6;12038;12046;12054;12107:3;12095:9;12086:7;12082:23;12078:33;12075:2;;;12129:6;12121;12114:22;12075:2;-1:-1:-1;;12157:16:14;;12213:2;12198:18;;12192:25;12257:2;12242:18;;12236:25;12301:2;12286:18;;;12280:25;12157:16;;12192:25;;-1:-1:-1;12280:25:14;;-1:-1:-1;12065:246:14;-1:-1:-1;12065:246:14:o;12316:502::-;12431:6;12439;12447;12455;12463;12471;12524:3;12512:9;12503:7;12499:23;12495:33;12492:2;;;12546:6;12538;12531:22;12492:2;12580:9;12574:16;12564:26;;12630:2;12619:9;12615:18;12609:25;12599:35;;12674:2;12663:9;12659:18;12653:25;12643:35;;12718:2;12707:9;12703:18;12697:25;12687:35;;12762:3;12751:9;12747:19;12741:26;12731:36;;12807:3;12796:9;12792:19;12786:26;12776:36;;12482:336;;;;;;;;:::o;12823:214::-;12891:6;12944:2;12932:9;12923:7;12919:23;12915:32;12912:2;;;12965:6;12957;12950:22;12912:2;12993:38;13021:9;12993:38;:::i;13151:463::-;13204:3;13242:5;13236:12;13269:6;13264:3;13257:19;13295:4;13324:2;13319:3;13315:12;13308:19;;13361:2;13354:5;13350:14;13382:3;13394:195;13408:6;13405:1;13402:13;13394:195;;;13473:13;;-1:-1:-1;;;;;13469:39:14;13457:52;;13529:12;;;;13564:15;;;;13505:1;13423:9;13394:195;;;-1:-1:-1;13605:3:14;;13212:402;-1:-1:-1;;;;;13212:402:14:o;13619:501::-;13680:3;13718:5;13712:12;13745:6;13740:3;13733:19;13771:4;13800:2;13795:3;13791:12;13784:19;;13824:5;13819:3;13812:18;13868:2;13863:3;13853:18;13889:3;13901:194;13915:6;13912:1;13909:13;13901:194;;;13980:13;;-1:-1:-1;;;;;13976:39:14;13964:52;;14036:12;;;;14012:1;14071:14;;;;13930:9;13901:194;;14125:437;14178:3;14216:5;14210:12;14243:6;14238:3;14231:19;14269:4;14298:2;14293:3;14289:12;14282:19;;14335:2;14328:5;14324:14;14356:3;14368:169;14382:6;14379:1;14376:13;14368:169;;;14443:13;;14431:26;;14477:12;;;;14512:15;;;;14404:1;14397:9;14368:169;;14663:502;14760:5;14754:12;14749:3;14742:25;14816:4;14809:5;14805:16;14799:23;14792:4;14787:3;14783:14;14776:47;14872:4;14865:5;14861:16;14855:23;14848:4;14843:3;14839:14;14832:47;14928:4;14921:5;14917:16;14911:23;14904:4;14899:3;14895:14;14888:47;14984:4;14977:5;14973:16;14967:23;14960:4;14955:3;14951:14;14944:47;15040:4;15033:5;15029:16;15023:23;15016:4;15011:3;15007:14;15000:47;15096:4;15089:5;15085:16;15079:23;15072:4;15067:3;15063:14;15056:47;15152:4;15145:5;15141:16;15135:23;15128:4;15123:3;15119:14;15112:47;14732:433;;:::o;15170:510::-;15269:12;;15257:25;;15331:4;15320:16;;15314:23;15307:4;15298:14;;15291:47;15387:4;15376:16;;15370:23;15363:4;15354:14;;15347:47;15443:4;15432:16;;15426:23;15419:4;15410:14;;15403:47;15499:4;15488:16;;15482:23;15475:4;15466:14;;15459:47;15555:4;15544:16;;15538:23;15531:4;15522:14;;15515:47;15611:4;15600:16;;15594:23;15587:4;15578:14;;15571:47;15667:4;15656:16;15650:23;15643:4;15634:14;;;15627:47;15247:433::o;16334:274::-;16463:3;16501:6;16495:13;16517:53;16563:6;16558:3;16551:4;16543:6;16539:17;16517:53;:::i;:::-;16586:16;;;;;16471:137;-1:-1:-1;;16471:137:14:o;20977:383::-;21126:2;21115:9;21108:21;21089:4;21158:6;21152:13;21201:6;21196:2;21185:9;21181:18;21174:34;21217:66;21276:6;21271:2;21260:9;21256:18;21251:2;21243:6;21239:15;21217:66;:::i;:::-;21344:2;21323:15;-1:-1:-1;;21319:29:14;21304:45;;;;21351:2;21300:54;;21098:262;-1:-1:-1;;21098:262:14:o;40540:1648::-;40840:13;;14637;14630:21;14618:34;;40783:4;40812:3;40912:4;40904:6;40900:17;40894:24;40927:51;40972:4;40961:9;40957:20;40943:12;14637:13;14630:21;14618:34;;14608:50;40927:51;;41034:4;41026:6;41022:17;41016:24;41009:4;40998:9;40994:20;40987:54;41097:4;41089:6;41085:17;41079:24;41072:4;41061:9;41057:20;41050:54;41160:4;41152:6;41148:17;41142:24;41135:4;41124:9;41120:20;41113:54;41223:4;41215:6;41211:17;41205:24;41198:4;41187:9;41183:20;41176:54;41286:4;41278:6;41274:17;41268:24;41261:4;41250:9;41246:20;41239:54;41349:4;41341:6;41337:17;41331:24;41324:4;41313:9;41309:20;41302:54;41375:6;41430:2;41422:6;41418:15;41412:22;41443:54;41493:2;41482:9;41478:18;41462:14;-1:-1:-1;;;;;13108:31:14;13096:44;;13086:60;41443:54;-1:-1:-1;;41516:6:14;41559:15;;;41553:22;-1:-1:-1;;;;;13108:31:14;;;41619:18;;;13096:44;;;;41657:6;41700:15;;;41694:22;13108:31;;41760:18;;;13096:44;41798:6;41841:15;;;41835:22;13108:31;;41901:18;;;13096:44;41939:6;41982:15;;;41976:22;13108:31;;;42042:18;;;13096:44;42092:3;42077:19;;42070:31;;;42118:64;42163:18;;;42155:6;42118:64;:::i;:::-;42110:72;40792:1396;-1:-1:-1;;;;;40792:1396:14:o;42193:501::-;42524:3;42509:19;;42537:70;42513:9;42589:6;42537:70;:::i;:::-;42616:72;42683:3;42672:9;42668:19;42660:6;42616:72;:::i;42699:1000::-;43037:13;;43052:6;43033:26;16292:31;;43002:3;42987:19;;43127:4;43115:17;;43109:24;43102:4;43087:20;;43080:54;43190:4;43178:17;;43172:24;43165:4;43150:20;;43143:54;43253:4;43241:17;;43235:24;43228:4;43213:20;;43206:54;43316:4;43304:17;;43298:24;43291:4;43276:20;;43269:54;43399:4;43387:17;;43381:24;-1:-1:-1;;;;;54742:31:14;-1:-1:-1;;;;;13108:31:14;;43463:4;43448:20;;13096:44;-1:-1:-1;43547:4:14;43535:17;;43529:24;-1:-1:-1;;;;;54742:31:14;-1:-1:-1;;;;;13108:31:14;;43613:4;43598:20;;13096:44;-1:-1:-1;15773:12:14;;15787:6;15769:25;43688:3;43673:19;;15757:38;15844:4;15833:16;;15827:23;15811:14;;;15804:47;15900:4;15889:16;;15883:23;15867:14;;;15860:47;15956:4;15945:16;;15939:23;15923:14;;;15916:47;16012:4;16001:16;;15995:23;15979:14;;;15972:47;16065:4;16054:16;;16048:23;-1:-1:-1;;;;;16141:21:14;;;16125:14;;;16118:45;16216:4;16205:16;;16199:23;16195:32;16179:14;;;16172:56;43628:65;15747:487;43704:1249;43858:4;43900:3;43889:9;43885:19;43877:27;;43940:1;43936;43931:3;43927:11;43923:19;43988:2;43979:6;43973:13;43969:22;43958:9;43951:41;44060:2;44052:4;44044:6;44040:17;44034:24;44030:33;44023:4;44012:9;44008:20;44001:63;44120:4;44112:6;44108:17;44102:24;44095:4;44084:9;44080:20;44073:54;44183:4;44175:6;44171:17;44165:24;44158:4;44147:9;44143:20;44136:54;44246:4;44238:6;44234:17;44228:24;44221:4;44210:9;44206:20;44199:54;44309:4;44301:6;44297:17;44291:24;44284:4;44273:9;44269:20;44262:54;44363:4;44355:6;44351:17;44345:24;44427:12;44421:19;44414:27;44407:35;44400:4;44389:9;44385:20;44378:65;44504:4;44490:12;44486:23;44480:30;44474:3;44463:9;44459:19;44452:59;44572:4;44558:12;44554:23;44548:30;44542:3;44531:9;44527:19;44520:59;44640:4;44626:12;44622:23;44616:30;44610:3;44599:9;44595:19;44588:59;44720:2;44712:4;44698:12;44694:23;44688:30;44684:39;44678:3;44667:9;44663:19;44656:68;44797:2;44789:4;44775:12;44771:23;44765:30;44761:39;44755:3;44744:9;44740:19;44733:68;;;44850:3;44842:6;44838:16;44832:23;44864:83;44939:6;44928:9;44924:22;44908:14;44864:83;:::i;:::-;;43867:1086;;;;:::o;46442:763::-;46805:6;46794:9;46787:25;46862:6;46855:14;46848:22;46843:2;46832:9;46828:18;46821:50;46907:6;46902:2;46891:9;46887:18;46880:34;46950:6;46945:2;46934:9;46930:18;46923:34;46994:3;46988;46977:9;46973:19;46966:32;46768:4;47021:57;47073:3;47062:9;47058:19;47050:6;47021:57;:::i;:::-;47127:9;47119:6;47115:22;47109:3;47098:9;47094:19;47087:51;47155:44;47192:6;47184;47155:44;:::i;:::-;47147:52;46777:428;-1:-1:-1;;;;;;;;;46777:428:14:o;47463:609::-;47776:6;47765:9;47758:25;47819:6;47814:2;47803:9;47799:18;47792:34;47862:3;47857:2;47846:9;47842:18;47835:31;47739:4;47889:57;47941:3;47930:9;47926:19;47918:6;47889:57;:::i;:::-;47994:9;47986:6;47982:22;47977:2;47966:9;47962:18;47955:50;48022:44;48059:6;48051;48022:44;:::i;49365:527::-;49687:25;;;49743:2;49728:18;;49721:34;;;49786:2;49771:18;;49764:34;;;49674:3;49659:19;;49807:79;49882:2;49867:18;;49859:6;49807:79;:::i;52120:247::-;52187:2;52181:9;52229:3;52217:16;;52263:18;52248:34;;52284:22;;;52245:62;52242:2;;;52310:18;;:::i;:::-;52346:2;52339:22;52161:206;:::o;52372:252::-;52444:2;52438:9;52486:3;52474:16;;52520:18;52505:34;;52541:22;;;52502:62;52499:2;;;52567:18;;:::i;52629:128::-;52669:3;52700:1;52696:6;52693:1;52690:13;52687:2;;;52706:18;;:::i;:::-;-1:-1:-1;52742:9:14;;52677:80::o;52762:217::-;52802:1;52828;52818:2;;-1:-1:-1;;;52853:31:14;;52907:4;52904:1;52897:15;52935:4;52860:1;52925:15;52818:2;-1:-1:-1;52964:9:14;;52808:171::o;52984:422::-;53073:1;53116:5;53073:1;53130:270;53151:7;53141:8;53138:21;53130:270;;;53210:4;53206:1;53202:6;53198:17;53192:4;53189:27;53186:2;;;53219:18;;:::i;:::-;53269:7;53259:8;53255:22;53252:2;;;53289:16;;;;53252:2;53368:22;;;;53328:15;;;;53130:270;;;53134:3;53048:358;;;;;:::o;53411:131::-;53471:5;53500:36;53527:8;53521:4;53596:5;53626:8;53616:2;;-1:-1:-1;53667:1:14;53681:5;;53616:2;53715:4;53705:2;;-1:-1:-1;53752:1:14;53766:5;;53705:2;53797:4;53815:1;53810:59;;;;53883:1;53878:130;;;;53790:218;;53810:59;53840:1;53831:10;;53854:5;;;53878:130;53915:3;53905:8;53902:17;53899:2;;;53922:18;;:::i;:::-;-1:-1:-1;;53978:1:14;53964:16;;53993:5;;53790:218;;54092:2;54082:8;54079:16;54073:3;54067:4;54064:13;54060:36;54054:2;54044:8;54041:16;54036:2;54030:4;54027:12;54023:35;54020:77;54017:2;;;-1:-1:-1;54129:19:14;;;54161:5;;54017:2;54208:34;54233:8;54227:4;54208:34;:::i;:::-;54278:6;54274:1;54270:6;54266:19;54257:7;54254:32;54251:2;;;54289:18;;:::i;:::-;54327:20;;53606:747;-1:-1:-1;;;53606:747:14:o;54358:168::-;54398:7;54464:1;54460;54456:6;54452:14;54449:1;54446:21;54441:1;54434:9;54427:17;54423:45;54420:2;;;54471:18;;:::i;:::-;-1:-1:-1;54511:9:14;;54410:116::o;54531:125::-;54571:4;54599:1;54596;54593:8;54590:2;;;54604:18;;:::i;:::-;-1:-1:-1;54641:9:14;;54580:76::o;54784:258::-;54856:1;54866:113;54880:6;54877:1;54874:13;54866:113;;;54956:11;;;54950:18;54937:11;;;54930:39;54902:2;54895:10;54866:113;;;54997:6;54994:1;54991:13;54988:2;;;-1:-1:-1;;55032:1:14;55014:16;;55007:27;54837:205::o;55047:136::-;55086:3;55114:5;55104:2;;55123:18;;:::i;:::-;-1:-1:-1;;;55159:18:14;;55094:89::o;55188:135::-;55227:3;-1:-1:-1;;55248:17:14;;55245:2;;;55268:18;;:::i;:::-;-1:-1:-1;55315:1:14;55304:13;;55235:88::o;55328:127::-;55389:10;55384:3;55380:20;55377:1;55370:31;55420:4;55417:1;55410:15;55444:4;55441:1;55434:15;55460:127;55521:10;55516:3;55512:20;55509:1;55502:31;55552:4;55549:1;55542:15;55576:4;55573:1;55566:15;55592:131;-1:-1:-1;;;;;55667:31:14;;55657:42;;55647:2;;55713:1;55710;55703:12;55728:118;55814:5;55807:13;55800:21;55793:5;55790:32;55780:2;;55836:1;55833;55826:12

Metadata Hash

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