ETH Price: $3,356.03 (+2.48%)
Gas: 4 Gwei

Contract

0x7c19858F2f317CcF413B3046C2BeD49F346B7D0F
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60806040127211082021-06-28 7:08:371127 days ago1624864117IN
 Create: Controller
0 ETH0.1045244820

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Controller

Compiler Version
v0.6.10+commit.00c0fcaf

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Unlicense license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-06-28
*/

/**
 * SPDX-License-Identifier: UNLICENSED
 */
pragma solidity =0.6.10;

pragma experimental ABIEncoderV2;

// File: contracts/packages/oz/upgradeability/Initializable.sol

/**
 * @title Initializable
 *
 * @dev Helper contract to support initializer functions. To use it, replace
 * the constructor with a function that has the `initializer` modifier.
 * WARNING: Unlike constructors, initializer functions must be manually
 * invoked. This applies both to deploying an Initializable contract, as well
 * as extending an Initializable contract via inheritance.
 * WARNING: When used with inheritance, manual care must be taken to not invoke
 * a parent initializer twice, or ensure that all initializers are idempotent,
 * because this is not dealt with automatically as with constructors.
 */
contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private initialized;

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

    /**
     * @dev Modifier to use in the initializer function of a contract.
     */
    modifier initializer() {
        require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");

        bool isTopLevelCall = !initializing;
        if (isTopLevelCall) {
            initializing = true;
            initialized = true;
        }

        _;

        if (isTopLevelCall) {
            initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function isConstructor() private view returns (bool) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        address self = address(this);
        uint256 cs;
        assembly {
            cs := extcodesize(self)
        }
        return cs == 0;
    }

    // Reserved storage space to allow for layout changes in the future.
    uint256[50] private ______gap;
}

// File: contracts/packages/oz/upgradeability/GSN/ContextUpgradeable.sol

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with 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 ContextUpgradeable is Initializable {
    function __Context_init() internal initializer {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal initializer {}

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

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

    uint256[50] private __gap;
}

// File: contracts/packages/oz/upgradeability/OwnableUpgradeSafe.sol

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */

    function __Ownable_init(address _sender) internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained(_sender);
    }

    function __Ownable_init_unchained(address _sender) internal initializer {
        _owner = _sender;
        emit OwnershipTransferred(address(0), _sender);
    }

    /**
     * @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 Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

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

    uint256[49] private __gap;
}

// File: contracts/packages/oz/upgradeability/ReentrancyGuardUpgradeSafe.sol

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
contract ReentrancyGuardUpgradeSafe is Initializable {
    bool private _notEntered;

    function __ReentrancyGuard_init() internal initializer {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal initializer {
        // Storing an initial non-zero value makes deployment a bit more
        // expensive, but in exchange the refund on every call to nonReentrant
        // will be lower in amount. Since refunds are capped to a percetange of
        // the total transaction's gas, it is best to keep them low in cases
        // like this one, to increase the likelihood of the full refund coming
        // into effect.
        _notEntered = true;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_notEntered, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _notEntered = false;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _notEntered = true;
    }

    uint256[49] private __gap;
}

// File: contracts/packages/oz/SafeMath.sol

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @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) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @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 sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

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

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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 mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// File: contracts/libs/MarginVault.sol

/**
 * MarginVault Error Codes
 * V1: invalid short otoken amount
 * V2: invalid short otoken index
 * V3: short otoken address mismatch
 * V4: invalid long otoken amount
 * V5: invalid long otoken index
 * V6: long otoken address mismatch
 * V7: invalid collateral amount
 * V8: invalid collateral token index
 * V9: collateral token address mismatch
 */

/**
 * @title MarginVault
 * @author Opyn Team
 * @notice A library that provides the Controller with a Vault struct and the functions that manipulate vaults.
 * Vaults describe discrete position combinations of long options, short options, and collateral assets that a user can have.
 */
library MarginVault {
    using SafeMath for uint256;

    // vault is a struct of 6 arrays that describe a position a user has, a user can have multiple vaults.
    struct Vault {
        // addresses of oTokens a user has shorted (i.e. written) against this vault
        address[] shortOtokens;
        // addresses of oTokens a user has bought and deposited in this vault
        // user can be long oTokens without opening a vault (e.g. by buying on a DEX)
        // generally, long oTokens will be 'deposited' in vaults to act as collateral in order to write oTokens against (i.e. in spreads)
        address[] longOtokens;
        // addresses of other ERC-20s a user has deposited as collateral in this vault
        address[] collateralAssets;
        // quantity of oTokens minted/written for each oToken address in shortOtokens
        uint256[] shortAmounts;
        // quantity of oTokens owned and held in the vault for each oToken address in longOtokens
        uint256[] longAmounts;
        // quantity of ERC-20 deposited as collateral in the vault for each ERC-20 address in collateralAssets
        uint256[] collateralAmounts;
    }

    /**
     * @dev increase the short oToken balance in a vault when a new oToken is minted
     * @param _vault vault to add or increase the short position in
     * @param _shortOtoken address of the _shortOtoken being minted from the user's vault
     * @param _amount number of _shortOtoken being minted from the user's vault
     * @param _index index of _shortOtoken in the user's vault.shortOtokens array
     */
    function addShort(
        Vault storage _vault,
        address _shortOtoken,
        uint256 _amount,
        uint256 _index
    ) external {
        require(_amount > 0, "V1");

        // valid indexes in any array are between 0 and array.length - 1.
        // if adding an amount to an preexisting short oToken, check that _index is in the range of 0->length-1
        if ((_index == _vault.shortOtokens.length) && (_index == _vault.shortAmounts.length)) {
            _vault.shortOtokens.push(_shortOtoken);
            _vault.shortAmounts.push(_amount);
        } else {
            require((_index < _vault.shortOtokens.length) && (_index < _vault.shortAmounts.length), "V2");
            address existingShort = _vault.shortOtokens[_index];
            require((existingShort == _shortOtoken) || (existingShort == address(0)), "V3");

            _vault.shortAmounts[_index] = _vault.shortAmounts[_index].add(_amount);
            _vault.shortOtokens[_index] = _shortOtoken;
        }
    }

    /**
     * @dev decrease the short oToken balance in a vault when an oToken is burned
     * @param _vault vault to decrease short position in
     * @param _shortOtoken address of the _shortOtoken being reduced in the user's vault
     * @param _amount number of _shortOtoken being reduced in the user's vault
     * @param _index index of _shortOtoken in the user's vault.shortOtokens array
     */
    function removeShort(
        Vault storage _vault,
        address _shortOtoken,
        uint256 _amount,
        uint256 _index
    ) external {
        // check that the removed short oToken exists in the vault at the specified index
        require(_index < _vault.shortOtokens.length, "V2");
        require(_vault.shortOtokens[_index] == _shortOtoken, "V3");

        uint256 newShortAmount = _vault.shortAmounts[_index].sub(_amount);

        if (newShortAmount == 0) {
            delete _vault.shortOtokens[_index];
        }
        _vault.shortAmounts[_index] = newShortAmount;
    }

    /**
     * @dev increase the long oToken balance in a vault when an oToken is deposited
     * @param _vault vault to add a long position to
     * @param _longOtoken address of the _longOtoken being added to the user's vault
     * @param _amount number of _longOtoken the protocol is adding to the user's vault
     * @param _index index of _longOtoken in the user's vault.longOtokens array
     */
    function addLong(
        Vault storage _vault,
        address _longOtoken,
        uint256 _amount,
        uint256 _index
    ) external {
        require(_amount > 0, "V4");

        // valid indexes in any array are between 0 and array.length - 1.
        // if adding an amount to an preexisting short oToken, check that _index is in the range of 0->length-1
        if ((_index == _vault.longOtokens.length) && (_index == _vault.longAmounts.length)) {
            _vault.longOtokens.push(_longOtoken);
            _vault.longAmounts.push(_amount);
        } else {
            require((_index < _vault.longOtokens.length) && (_index < _vault.longAmounts.length), "V5");
            address existingLong = _vault.longOtokens[_index];
            require((existingLong == _longOtoken) || (existingLong == address(0)), "V6");

            _vault.longAmounts[_index] = _vault.longAmounts[_index].add(_amount);
            _vault.longOtokens[_index] = _longOtoken;
        }
    }

    /**
     * @dev decrease the long oToken balance in a vault when an oToken is withdrawn
     * @param _vault vault to remove a long position from
     * @param _longOtoken address of the _longOtoken being removed from the user's vault
     * @param _amount number of _longOtoken the protocol is removing from the user's vault
     * @param _index index of _longOtoken in the user's vault.longOtokens array
     */
    function removeLong(
        Vault storage _vault,
        address _longOtoken,
        uint256 _amount,
        uint256 _index
    ) external {
        // check that the removed long oToken exists in the vault at the specified index
        require(_index < _vault.longOtokens.length, "V5");
        require(_vault.longOtokens[_index] == _longOtoken, "V6");

        uint256 newLongAmount = _vault.longAmounts[_index].sub(_amount);

        if (newLongAmount == 0) {
            delete _vault.longOtokens[_index];
        }
        _vault.longAmounts[_index] = newLongAmount;
    }

    /**
     * @dev increase the collateral balance in a vault
     * @param _vault vault to add collateral to
     * @param _collateralAsset address of the _collateralAsset being added to the user's vault
     * @param _amount number of _collateralAsset being added to the user's vault
     * @param _index index of _collateralAsset in the user's vault.collateralAssets array
     */
    function addCollateral(
        Vault storage _vault,
        address _collateralAsset,
        uint256 _amount,
        uint256 _index
    ) external {
        require(_amount > 0, "V7");

        // valid indexes in any array are between 0 and array.length - 1.
        // if adding an amount to an preexisting short oToken, check that _index is in the range of 0->length-1
        if ((_index == _vault.collateralAssets.length) && (_index == _vault.collateralAmounts.length)) {
            _vault.collateralAssets.push(_collateralAsset);
            _vault.collateralAmounts.push(_amount);
        } else {
            require((_index < _vault.collateralAssets.length) && (_index < _vault.collateralAmounts.length), "V8");
            address existingCollateral = _vault.collateralAssets[_index];
            require((existingCollateral == _collateralAsset) || (existingCollateral == address(0)), "V9");

            _vault.collateralAmounts[_index] = _vault.collateralAmounts[_index].add(_amount);
            _vault.collateralAssets[_index] = _collateralAsset;
        }
    }

    /**
     * @dev decrease the collateral balance in a vault
     * @param _vault vault to remove collateral from
     * @param _collateralAsset address of the _collateralAsset being removed from the user's vault
     * @param _amount number of _collateralAsset being removed from the user's vault
     * @param _index index of _collateralAsset in the user's vault.collateralAssets array
     */
    function removeCollateral(
        Vault storage _vault,
        address _collateralAsset,
        uint256 _amount,
        uint256 _index
    ) external {
        // check that the removed collateral exists in the vault at the specified index
        require(_index < _vault.collateralAssets.length, "V8");
        require(_vault.collateralAssets[_index] == _collateralAsset, "V9");

        uint256 newCollateralAmount = _vault.collateralAmounts[_index].sub(_amount);

        if (newCollateralAmount == 0) {
            delete _vault.collateralAssets[_index];
        }
        _vault.collateralAmounts[_index] = newCollateralAmount;
    }
}

// File: contracts/libs/Actions.sol

/**
 * @title Actions
 * @author Opyn Team
 * @notice A library that provides a ActionArgs struct, sub types of Action structs, and functions to parse ActionArgs into specific Actions.
 * errorCode
 * A1 can only parse arguments for open vault actions
 * A2 cannot open vault for an invalid account
 * A3 cannot open vault with an invalid type
 * A4 can only parse arguments for mint actions
 * A5 cannot mint from an invalid account
 * A6 can only parse arguments for burn actions
 * A7 cannot burn from an invalid account
 * A8 can only parse arguments for deposit actions
 * A9 cannot deposit to an invalid account
 * A10 can only parse arguments for withdraw actions
 * A11 cannot withdraw from an invalid account
 * A12 cannot withdraw to an invalid account
 * A13 can only parse arguments for redeem actions
 * A14 cannot redeem to an invalid account
 * A15 can only parse arguments for settle vault actions
 * A16 cannot settle vault for an invalid account
 * A17 cannot withdraw payout to an invalid account
 * A18 can only parse arguments for liquidate action
 * A19 cannot liquidate vault for an invalid account owner
 * A20 cannot send collateral to an invalid account
 * A21 cannot parse liquidate action with no round id
 * A22 can only parse arguments for call actions
 * A23 target address cannot be address(0)
 */
library Actions {
    // possible actions that can be performed
    enum ActionType {
        OpenVault,
        MintShortOption,
        BurnShortOption,
        DepositLongOption,
        WithdrawLongOption,
        DepositCollateral,
        WithdrawCollateral,
        SettleVault,
        Redeem,
        Call,
        Liquidate
    }

    struct ActionArgs {
        // type of action that is being performed on the system
        ActionType actionType;
        // address of the account owner
        address owner;
        // address which we move assets from or to (depending on the action type)
        address secondAddress;
        // asset that is to be transfered
        address asset;
        // index of the vault that is to be modified (if any)
        uint256 vaultId;
        // amount of asset that is to be transfered
        uint256 amount;
        // each vault can hold multiple short / long / collateral assets but we are restricting the scope to only 1 of each in this version
        // in future versions this would be the index of the short / long / collateral asset that needs to be modified
        uint256 index;
        // any other data that needs to be passed in for arbitrary function calls
        bytes data;
    }

    struct MintArgs {
        // address of the account owner
        address owner;
        // index of the vault from which the asset will be minted
        uint256 vaultId;
        // address to which we transfer the minted oTokens
        address to;
        // oToken that is to be minted
        address otoken;
        // each vault can hold multiple short / long / collateral assets but we are restricting the scope to only 1 of each in this version
        // in future versions this would be the index of the short / long / collateral asset that needs to be modified
        uint256 index;
        // amount of oTokens that is to be minted
        uint256 amount;
    }

    struct BurnArgs {
        // address of the account owner
        address owner;
        // index of the vault from which the oToken will be burned
        uint256 vaultId;
        // address from which we transfer the oTokens
        address from;
        // oToken that is to be burned
        address otoken;
        // each vault can hold multiple short / long / collateral assets but we are restricting the scope to only 1 of each in this version
        // in future versions this would be the index of the short / long / collateral asset that needs to be modified
        uint256 index;
        // amount of oTokens that is to be burned
        uint256 amount;
    }

    struct OpenVaultArgs {
        // address of the account owner
        address owner;
        // vault id to create
        uint256 vaultId;
        // vault type, 0 for spread/max loss and 1 for naked margin vault
        uint256 vaultType;
    }

    struct DepositArgs {
        // address of the account owner
        address owner;
        // index of the vault to which the asset will be added
        uint256 vaultId;
        // address from which we transfer the asset
        address from;
        // asset that is to be deposited
        address asset;
        // each vault can hold multiple short / long / collateral assets but we are restricting the scope to only 1 of each in this version
        // in future versions this would be the index of the short / long / collateral asset that needs to be modified
        uint256 index;
        // amount of asset that is to be deposited
        uint256 amount;
    }

    struct RedeemArgs {
        // address to which we pay out the oToken proceeds
        address receiver;
        // oToken that is to be redeemed
        address otoken;
        // amount of oTokens that is to be redeemed
        uint256 amount;
    }

    struct WithdrawArgs {
        // address of the account owner
        address owner;
        // index of the vault from which the asset will be withdrawn
        uint256 vaultId;
        // address to which we transfer the asset
        address to;
        // asset that is to be withdrawn
        address asset;
        // each vault can hold multiple short / long / collateral assets but we are restricting the scope to only 1 of each in this version
        // in future versions this would be the index of the short / long / collateral asset that needs to be modified
        uint256 index;
        // amount of asset that is to be withdrawn
        uint256 amount;
    }

    struct SettleVaultArgs {
        // address of the account owner
        address owner;
        // index of the vault to which is to be settled
        uint256 vaultId;
        // address to which we transfer the remaining collateral
        address to;
    }

    struct LiquidateArgs {
        // address of the vault owner to liquidate
        address owner;
        // address of the liquidated collateral receiver
        address receiver;
        // vault id to liquidate
        uint256 vaultId;
        // amount of debt(otoken) to repay
        uint256 amount;
        // chainlink round id
        uint256 roundId;
    }

    struct CallArgs {
        // address of the callee contract
        address callee;
        // data field for external calls
        bytes data;
    }

    /**
     * @notice parses the passed in action arguments to get the arguments for an open vault action
     * @param _args general action arguments structure
     * @return arguments for a open vault action
     */
    function _parseOpenVaultArgs(ActionArgs memory _args) internal pure returns (OpenVaultArgs memory) {
        require(_args.actionType == ActionType.OpenVault, "A1");
        require(_args.owner != address(0), "A2");

        // if not _args.data included, vault type will be 0 by default
        uint256 vaultType;

        if (_args.data.length == 32) {
            // decode vault type from _args.data
            vaultType = abi.decode(_args.data, (uint256));
        }

        // for now we only have 2 vault types
        require(vaultType < 2, "A3");

        return OpenVaultArgs({owner: _args.owner, vaultId: _args.vaultId, vaultType: vaultType});
    }

    /**
     * @notice parses the passed in action arguments to get the arguments for a mint action
     * @param _args general action arguments structure
     * @return arguments for a mint action
     */
    function _parseMintArgs(ActionArgs memory _args) internal pure returns (MintArgs memory) {
        require(_args.actionType == ActionType.MintShortOption, "A4");
        require(_args.owner != address(0), "A5");

        return
            MintArgs({
                owner: _args.owner,
                vaultId: _args.vaultId,
                to: _args.secondAddress,
                otoken: _args.asset,
                index: _args.index,
                amount: _args.amount
            });
    }

    /**
     * @notice parses the passed in action arguments to get the arguments for a burn action
     * @param _args general action arguments structure
     * @return arguments for a burn action
     */
    function _parseBurnArgs(ActionArgs memory _args) internal pure returns (BurnArgs memory) {
        require(_args.actionType == ActionType.BurnShortOption, "A6");
        require(_args.owner != address(0), "A7");

        return
            BurnArgs({
                owner: _args.owner,
                vaultId: _args.vaultId,
                from: _args.secondAddress,
                otoken: _args.asset,
                index: _args.index,
                amount: _args.amount
            });
    }

    /**
     * @notice parses the passed in action arguments to get the arguments for a deposit action
     * @param _args general action arguments structure
     * @return arguments for a deposit action
     */
    function _parseDepositArgs(ActionArgs memory _args) internal pure returns (DepositArgs memory) {
        require(
            (_args.actionType == ActionType.DepositLongOption) || (_args.actionType == ActionType.DepositCollateral),
            "A8"
        );
        require(_args.owner != address(0), "A9");

        return
            DepositArgs({
                owner: _args.owner,
                vaultId: _args.vaultId,
                from: _args.secondAddress,
                asset: _args.asset,
                index: _args.index,
                amount: _args.amount
            });
    }

    /**
     * @notice parses the passed in action arguments to get the arguments for a withdraw action
     * @param _args general action arguments structure
     * @return arguments for a withdraw action
     */
    function _parseWithdrawArgs(ActionArgs memory _args) internal pure returns (WithdrawArgs memory) {
        require(
            (_args.actionType == ActionType.WithdrawLongOption) || (_args.actionType == ActionType.WithdrawCollateral),
            "A10"
        );
        require(_args.owner != address(0), "A11");
        require(_args.secondAddress != address(0), "A12");

        return
            WithdrawArgs({
                owner: _args.owner,
                vaultId: _args.vaultId,
                to: _args.secondAddress,
                asset: _args.asset,
                index: _args.index,
                amount: _args.amount
            });
    }

    /**
     * @notice parses the passed in action arguments to get the arguments for an redeem action
     * @param _args general action arguments structure
     * @return arguments for a redeem action
     */
    function _parseRedeemArgs(ActionArgs memory _args) internal pure returns (RedeemArgs memory) {
        require(_args.actionType == ActionType.Redeem, "A13");
        require(_args.secondAddress != address(0), "A14");

        return RedeemArgs({receiver: _args.secondAddress, otoken: _args.asset, amount: _args.amount});
    }

    /**
     * @notice parses the passed in action arguments to get the arguments for a settle vault action
     * @param _args general action arguments structure
     * @return arguments for a settle vault action
     */
    function _parseSettleVaultArgs(ActionArgs memory _args) internal pure returns (SettleVaultArgs memory) {
        require(_args.actionType == ActionType.SettleVault, "A15");
        require(_args.owner != address(0), "A16");
        require(_args.secondAddress != address(0), "A17");

        return SettleVaultArgs({owner: _args.owner, vaultId: _args.vaultId, to: _args.secondAddress});
    }

    function _parseLiquidateArgs(ActionArgs memory _args) internal pure returns (LiquidateArgs memory) {
        require(_args.actionType == ActionType.Liquidate, "A18");
        require(_args.owner != address(0), "A19");
        require(_args.secondAddress != address(0), "A20");
        require(_args.data.length == 32, "A21");

        // decode chainlink round id from _args.data
        uint256 roundId = abi.decode(_args.data, (uint256));

        return
            LiquidateArgs({
                owner: _args.owner,
                receiver: _args.secondAddress,
                vaultId: _args.vaultId,
                amount: _args.amount,
                roundId: roundId
            });
    }

    /**
     * @notice parses the passed in action arguments to get the arguments for a call action
     * @param _args general action arguments structure
     * @return arguments for a call action
     */
    function _parseCallArgs(ActionArgs memory _args) internal pure returns (CallArgs memory) {
        require(_args.actionType == ActionType.Call, "A22");
        require(_args.secondAddress != address(0), "A23");

        return CallArgs({callee: _args.secondAddress, data: _args.data});
    }
}

// File: contracts/interfaces/AddressBookInterface.sol

interface AddressBookInterface {
    /* Getters */

    function getOtokenImpl() external view returns (address);

    function getOtokenFactory() external view returns (address);

    function getWhitelist() external view returns (address);

    function getController() external view returns (address);

    function getOracle() external view returns (address);

    function getMarginPool() external view returns (address);

    function getMarginCalculator() external view returns (address);

    function getLiquidationManager() external view returns (address);

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

    /* Setters */

    function setOtokenImpl(address _otokenImpl) external;

    function setOtokenFactory(address _factory) external;

    function setOracleImpl(address _otokenImpl) external;

    function setWhitelist(address _whitelist) external;

    function setController(address _controller) external;

    function setMarginPool(address _marginPool) external;

    function setMarginCalculator(address _calculator) external;

    function setLiquidationManager(address _liquidationManager) external;

    function setAddress(bytes32 _id, address _newImpl) external;
}

// File: contracts/interfaces/OtokenInterface.sol

interface OtokenInterface {
    function addressBook() external view returns (address);

    function underlyingAsset() external view returns (address);

    function strikeAsset() external view returns (address);

    function collateralAsset() external view returns (address);

    function strikePrice() external view returns (uint256);

    function expiryTimestamp() external view returns (uint256);

    function isPut() external view returns (bool);

    function init(
        address _addressBook,
        address _underlyingAsset,
        address _strikeAsset,
        address _collateralAsset,
        uint256 _strikePrice,
        uint256 _expiry,
        bool _isPut
    ) external;

    function getOtokenDetails()
        external
        view
        returns (
            address,
            address,
            address,
            uint256,
            uint256,
            bool
        );

    function mintOtoken(address account, uint256 amount) external;

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

// File: contracts/interfaces/MarginCalculatorInterface.sol

interface MarginCalculatorInterface {
    function addressBook() external view returns (address);

    function getExpiredPayoutRate(address _otoken) external view returns (uint256);

    function getExcessCollateral(MarginVault.Vault calldata _vault, uint256 _vaultType)
        external
        view
        returns (uint256 netValue, bool isExcess);

    function isLiquidatable(
        MarginVault.Vault memory _vault,
        uint256 _vaultType,
        uint256 _vaultLatestUpdate,
        uint256 _roundId
    )
        external
        view
        returns (
            bool,
            uint256,
            uint256
        );
}

// File: contracts/interfaces/OracleInterface.sol

interface OracleInterface {
    function isLockingPeriodOver(address _asset, uint256 _expiryTimestamp) external view returns (bool);

    function isDisputePeriodOver(address _asset, uint256 _expiryTimestamp) external view returns (bool);

    function getExpiryPrice(address _asset, uint256 _expiryTimestamp) external view returns (uint256, bool);

    function getDisputer() external view returns (address);

    function getPricer(address _asset) external view returns (address);

    function getPrice(address _asset) external view returns (uint256);

    function getPricerLockingPeriod(address _pricer) external view returns (uint256);

    function getPricerDisputePeriod(address _pricer) external view returns (uint256);

    function getChainlinkRoundData(address _asset, uint80 _roundId) external view returns (uint256, uint256);

    // Non-view function

    function setAssetPricer(address _asset, address _pricer) external;

    function setLockingPeriod(address _pricer, uint256 _lockingPeriod) external;

    function setDisputePeriod(address _pricer, uint256 _disputePeriod) external;

    function setExpiryPrice(
        address _asset,
        uint256 _expiryTimestamp,
        uint256 _price
    ) external;

    function disputeExpiryPrice(
        address _asset,
        uint256 _expiryTimestamp,
        uint256 _price
    ) external;

    function setDisputer(address _disputer) external;
}

// File: contracts/interfaces/WhitelistInterface.sol

interface WhitelistInterface {
    /* View functions */

    function addressBook() external view returns (address);

    function isWhitelistedProduct(
        address _underlying,
        address _strike,
        address _collateral,
        bool _isPut
    ) external view returns (bool);

    function isWhitelistedCollateral(address _collateral) external view returns (bool);

    function isWhitelistedOtoken(address _otoken) external view returns (bool);

    function isWhitelistedCallee(address _callee) external view returns (bool);

    /* Admin / factory only functions */
    function whitelistProduct(
        address _underlying,
        address _strike,
        address _collateral,
        bool _isPut
    ) external;

    function blacklistProduct(
        address _underlying,
        address _strike,
        address _collateral,
        bool _isPut
    ) external;

    function whitelistCollateral(address _collateral) external;

    function blacklistCollateral(address _collateral) external;

    function whitelistOtoken(address _otoken) external;

    function blacklistOtoken(address _otoken) external;

    function whitelistCallee(address _callee) external;

    function blacklistCallee(address _callee) external;
}

// File: contracts/interfaces/MarginPoolInterface.sol

interface MarginPoolInterface {
    /* Getters */
    function addressBook() external view returns (address);

    function farmer() external view returns (address);

    function getStoredBalance(address _asset) external view returns (uint256);

    /* Admin-only functions */
    function setFarmer(address _farmer) external;

    function farm(
        address _asset,
        address _receiver,
        uint256 _amount
    ) external;

    /* Controller-only functions */
    function transferToPool(
        address _asset,
        address _user,
        uint256 _amount
    ) external;

    function transferToUser(
        address _asset,
        address _user,
        uint256 _amount
    ) external;

    function batchTransferToPool(
        address[] calldata _asset,
        address[] calldata _user,
        uint256[] calldata _amount
    ) external;

    function batchTransferToUser(
        address[] calldata _asset,
        address[] calldata _user,
        uint256[] calldata _amount
    ) external;
}

// File: contracts/interfaces/CalleeInterface.sol

/**
 * @dev Contract interface that can be called from Controller as a call action.
 */
interface CalleeInterface {
    /**
     * Allows users to send this contract arbitrary data.
     * @param _sender The msg.sender to Controller
     * @param _data Arbitrary data given by the sender
     */
    function callFunction(address payable _sender, bytes memory _data) external;
}

// File: contracts/core/Controller.sol

/**
 * Controller Error Codes
 * C1: sender is not full pauser
 * C2: sender is not partial pauser
 * C3: callee is not a whitelisted address
 * C4: system is partially paused
 * C5: system is fully paused
 * C6: msg.sender is not authorized to run action
 * C7: invalid addressbook address
 * C8: invalid owner address
 * C9: invalid input
 * C10: fullPauser cannot be set to address zero
 * C11: partialPauser cannot be set to address zero
 * C12: can not run actions for different owners
 * C13: can not run actions on different vaults
 * C14: invalid final vault state
 * C15: can not run actions on inexistent vault
 * C16: cannot deposit long otoken from this address
 * C17: otoken is not whitelisted to be used as collateral
 * C18: otoken used as collateral is already expired
 * C19: can not withdraw an expired otoken
 * C20: cannot deposit collateral from this address
 * C21: asset is not whitelisted to be used as collateral
 * C22: can not withdraw collateral from a vault with an expired short otoken
 * C23: otoken is not whitelisted to be minted
 * C24: can not mint expired otoken
 * C25: cannot burn from this address
 * C26: can not burn expired otoken
 * C27: otoken is not whitelisted to be redeemed
 * C28: can not redeem un-expired otoken
 * C29: asset prices not finalized yet
 * C30: can't settle vault with no otoken
 * C31: can not settle vault with un-expired otoken
 * C32: can not settle undercollateralized vault
 * C33: can not liquidate vault
 * C34: can not leave less than collateral dust
 * C35: invalid vault id
 * C36: cap amount should be greater than zero
 * C37: collateral exceed naked margin cap
 */

/**
 * @title Controller
 * @author Opyn Team
 * @notice Contract that controls the Gamma Protocol and the interaction of all sub contracts
 */
contract Controller is Initializable, OwnableUpgradeSafe, ReentrancyGuardUpgradeSafe {
    using MarginVault for MarginVault.Vault;
    using SafeMath for uint256;

    AddressBookInterface public addressbook;
    WhitelistInterface public whitelist;
    OracleInterface public oracle;
    MarginCalculatorInterface public calculator;
    MarginPoolInterface public pool;

    ///@dev scale used in MarginCalculator
    uint256 internal constant BASE = 8;

    /// @notice address that has permission to partially pause the system, where system functionality is paused
    /// except redeem and settleVault
    address public partialPauser;

    /// @notice address that has permission to fully pause the system, where all system functionality is paused
    address public fullPauser;

    /// @notice True if all system functionality is paused other than redeem and settle vault
    bool public systemPartiallyPaused;

    /// @notice True if all system functionality is paused
    bool public systemFullyPaused;

    /// @notice True if a call action can only be executed to a whitelisted callee
    bool public callRestricted;

    /// @dev mapping between an owner address and the number of owner address vaults
    mapping(address => uint256) internal accountVaultCounter;
    /// @dev mapping between an owner address and a specific vault using a vault id
    mapping(address => mapping(uint256 => MarginVault.Vault)) internal vaults;
    /// @dev mapping between an account owner and their approved or unapproved account operators
    mapping(address => mapping(address => bool)) internal operators;

    /******************************************************************** V2.0.0 storage upgrade ******************************************************/

    /// @dev mapping to map vault by each vault type, naked margin vault should be set to 1, spread/max loss vault should be set to 0
    mapping(address => mapping(uint256 => uint256)) internal vaultType;
    /// @dev mapping to store the timestamp at which the vault was last updated, will be updated in every action that changes the vault state or when calling sync()
    mapping(address => mapping(uint256 => uint256)) internal vaultLatestUpdate;

    /// @dev mapping to store cap amount for naked margin vault per options collateral asset (scaled by collateral asset decimals)
    mapping(address => uint256) internal nakedCap;

    /// @dev mapping to store amount of naked margin vaults in pool
    mapping(address => uint256) internal nakedPoolBalance;

    /// @notice emits an event when an account operator is updated for a specific account owner
    event AccountOperatorUpdated(address indexed accountOwner, address indexed operator, bool isSet);
    /// @notice emits an event when a new vault is opened
    event VaultOpened(address indexed accountOwner, uint256 vaultId, uint256 indexed vaultType);
    /// @notice emits an event when a long oToken is deposited into a vault
    event LongOtokenDeposited(
        address indexed otoken,
        address indexed accountOwner,
        address indexed from,
        uint256 vaultId,
        uint256 amount
    );
    /// @notice emits an event when a long oToken is withdrawn from a vault
    event LongOtokenWithdrawed(
        address indexed otoken,
        address indexed AccountOwner,
        address indexed to,
        uint256 vaultId,
        uint256 amount
    );
    /// @notice emits an event when a collateral asset is deposited into a vault
    event CollateralAssetDeposited(
        address indexed asset,
        address indexed accountOwner,
        address indexed from,
        uint256 vaultId,
        uint256 amount
    );
    /// @notice emits an event when a collateral asset is withdrawn from a vault
    event CollateralAssetWithdrawed(
        address indexed asset,
        address indexed AccountOwner,
        address indexed to,
        uint256 vaultId,
        uint256 amount
    );
    /// @notice emits an event when a short oToken is minted from a vault
    event ShortOtokenMinted(
        address indexed otoken,
        address indexed AccountOwner,
        address indexed to,
        uint256 vaultId,
        uint256 amount
    );
    /// @notice emits an event when a short oToken is burned
    event ShortOtokenBurned(
        address indexed otoken,
        address indexed AccountOwner,
        address indexed from,
        uint256 vaultId,
        uint256 amount
    );
    /// @notice emits an event when an oToken is redeemed
    event Redeem(
        address indexed otoken,
        address indexed redeemer,
        address indexed receiver,
        address collateralAsset,
        uint256 otokenBurned,
        uint256 payout
    );
    /// @notice emits an event when a vault is settled
    event VaultSettled(
        address indexed accountOwner,
        address indexed oTokenAddress,
        address to,
        uint256 payout,
        uint256 vaultId,
        uint256 indexed vaultType
    );
    /// @notice emits an event when a vault is liquidated
    event VaultLiquidated(
        address indexed liquidator,
        address indexed receiver,
        address indexed vaultOwner,
        uint256 auctionPrice,
        uint256 auctionStartingRound,
        uint256 collateralPayout,
        uint256 debtAmount,
        uint256 vaultId
    );
    /// @notice emits an event when a call action is executed
    event CallExecuted(address indexed from, address indexed to, bytes data);
    /// @notice emits an event when the fullPauser address changes
    event FullPauserUpdated(address indexed oldFullPauser, address indexed newFullPauser);
    /// @notice emits an event when the partialPauser address changes
    event PartialPauserUpdated(address indexed oldPartialPauser, address indexed newPartialPauser);
    /// @notice emits an event when the system partial paused status changes
    event SystemPartiallyPaused(bool isPaused);
    /// @notice emits an event when the system fully paused status changes
    event SystemFullyPaused(bool isPaused);
    /// @notice emits an event when the call action restriction changes
    event CallRestricted(bool isRestricted);
    /// @notice emits an event when a donation transfer executed
    event Donated(address indexed donator, address indexed asset, uint256 amount);
    /// @notice emits an event when naked cap is updated
    event NakedCapUpdated(address indexed collateral, uint256 cap);

    /**
     * @notice modifier to check if the system is not partially paused, where only redeem and settleVault is allowed
     */
    modifier notPartiallyPaused {
        _isNotPartiallyPaused();

        _;
    }

    /**
     * @notice modifier to check if the system is not fully paused, where no functionality is allowed
     */
    modifier notFullyPaused {
        _isNotFullyPaused();

        _;
    }

    /**
     * @notice modifier to check if sender is the fullPauser address
     */
    modifier onlyFullPauser {
        require(msg.sender == fullPauser, "C1");

        _;
    }

    /**
     * @notice modifier to check if the sender is the partialPauser address
     */
    modifier onlyPartialPauser {
        require(msg.sender == partialPauser, "C2");

        _;
    }

    /**
     * @notice modifier to check if the sender is the account owner or an approved account operator
     * @param _sender sender address
     * @param _accountOwner account owner address
     */
    modifier onlyAuthorized(address _sender, address _accountOwner) {
        _isAuthorized(_sender, _accountOwner);

        _;
    }

    /**
     * @notice modifier to check if the called address is a whitelisted callee address
     * @param _callee called address
     */
    modifier onlyWhitelistedCallee(address _callee) {
        if (callRestricted) {
            require(_isCalleeWhitelisted(_callee), "C3");
        }

        _;
    }

    /**
     * @dev check if the system is not in a partiallyPaused state
     */
    function _isNotPartiallyPaused() internal view {
        require(!systemPartiallyPaused, "C4");
    }

    /**
     * @dev check if the system is not in an fullyPaused state
     */
    function _isNotFullyPaused() internal view {
        require(!systemFullyPaused, "C5");
    }

    /**
     * @dev check if the sender is an authorized operator
     * @param _sender msg.sender
     * @param _accountOwner owner of a vault
     */
    function _isAuthorized(address _sender, address _accountOwner) internal view {
        require((_sender == _accountOwner) || (operators[_accountOwner][_sender]), "C6");
    }

    /**
     * @notice initalize the deployed contract
     * @param _addressBook addressbook module
     * @param _owner account owner address
     */
    function initialize(address _addressBook, address _owner) external initializer {
        require(_addressBook != address(0), "C7");
        require(_owner != address(0), "C8");

        __Ownable_init(_owner);
        __ReentrancyGuard_init_unchained();

        addressbook = AddressBookInterface(_addressBook);
        _refreshConfigInternal();

        callRestricted = true;
    }

    /**
     * @notice send asset amount to margin pool
     * @dev use donate() instead of direct transfer() to store the balance in assetBalance
     * @param _asset asset address
     * @param _amount amount to donate to pool
     */
    function donate(address _asset, uint256 _amount) external {
        pool.transferToPool(_asset, msg.sender, _amount);

        emit Donated(msg.sender, _asset, _amount);
    }

    /**
     * @notice allows the partialPauser to toggle the systemPartiallyPaused variable and partially pause or partially unpause the system
     * @dev can only be called by the partialPauser
     * @param _partiallyPaused new boolean value to set systemPartiallyPaused to
     */
    function setSystemPartiallyPaused(bool _partiallyPaused) external onlyPartialPauser {
        require(systemPartiallyPaused != _partiallyPaused, "C9");

        systemPartiallyPaused = _partiallyPaused;

        emit SystemPartiallyPaused(systemPartiallyPaused);
    }

    /**
     * @notice allows the fullPauser to toggle the systemFullyPaused variable and fully pause or fully unpause the system
     * @dev can only be called by the fullyPauser
     * @param _fullyPaused new boolean value to set systemFullyPaused to
     */
    function setSystemFullyPaused(bool _fullyPaused) external onlyFullPauser {
        require(systemFullyPaused != _fullyPaused, "C9");

        systemFullyPaused = _fullyPaused;

        emit SystemFullyPaused(systemFullyPaused);
    }

    /**
     * @notice allows the owner to set the fullPauser address
     * @dev can only be called by the owner
     * @param _fullPauser new fullPauser address
     */
    function setFullPauser(address _fullPauser) external onlyOwner {
        require(_fullPauser != address(0), "C10");
        require(fullPauser != _fullPauser, "C9");
        emit FullPauserUpdated(fullPauser, _fullPauser);
        fullPauser = _fullPauser;
    }

    /**
     * @notice allows the owner to set the partialPauser address
     * @dev can only be called by the owner
     * @param _partialPauser new partialPauser address
     */
    function setPartialPauser(address _partialPauser) external onlyOwner {
        require(_partialPauser != address(0), "C11");
        require(partialPauser != _partialPauser, "C9");
        emit PartialPauserUpdated(partialPauser, _partialPauser);
        partialPauser = _partialPauser;
    }

    /**
     * @notice allows the owner to toggle the restriction on whitelisted call actions and only allow whitelisted
     * call addresses or allow any arbitrary call addresses
     * @dev can only be called by the owner
     * @param _isRestricted new call restriction state
     */
    function setCallRestriction(bool _isRestricted) external onlyOwner {
        require(callRestricted != _isRestricted, "C9");

        callRestricted = _isRestricted;

        emit CallRestricted(callRestricted);
    }

    /**
     * @notice allows a user to give or revoke privileges to an operator which can act on their behalf on their vaults
     * @dev can only be updated by the vault owner
     * @param _operator operator that the sender wants to give privileges to or revoke them from
     * @param _isOperator new boolean value that expresses if the sender is giving or revoking privileges for _operator
     */
    function setOperator(address _operator, bool _isOperator) external {
        require(operators[msg.sender][_operator] != _isOperator, "C9");

        operators[msg.sender][_operator] = _isOperator;

        emit AccountOperatorUpdated(msg.sender, _operator, _isOperator);
    }

    /**
     * @dev updates the configuration of the controller. can only be called by the owner
     */
    function refreshConfiguration() external onlyOwner {
        _refreshConfigInternal();
    }

    /**
     * @notice set cap amount for collateral asset used in naked margin
     * @dev can only be called by owner
     * @param _collateral collateral asset address
     * @param _cap cap amount, should be scaled by collateral asset decimals
     */
    function setNakedCap(address _collateral, uint256 _cap) external onlyOwner {
        require(_cap > 0, "C36");

        nakedCap[_collateral] = _cap;

        emit NakedCapUpdated(_collateral, _cap);
    }

    /**
     * @notice execute a number of actions on specific vaults
     * @dev can only be called when the system is not fully paused
     * @param _actions array of actions arguments
     */
    function operate(Actions.ActionArgs[] memory _actions) external nonReentrant notFullyPaused {
        (bool vaultUpdated, address vaultOwner, uint256 vaultId) = _runActions(_actions);
        if (vaultUpdated) {
            _verifyFinalState(vaultOwner, vaultId);
            vaultLatestUpdate[vaultOwner][vaultId] = now;
        }
    }

    /**
     * @notice sync vault latest update timestamp
     * @dev anyone can update the latest time the vault was touched by calling this function
     * vaultLatestUpdate will sync if the vault is well collateralized
     * @param _owner vault owner address
     * @param _vaultId vault id
     */
    function sync(address _owner, uint256 _vaultId) external nonReentrant notFullyPaused {
        _verifyFinalState(_owner, _vaultId);
        vaultLatestUpdate[_owner][_vaultId] = now;
    }

    /**
     * @notice check if a specific address is an operator for an owner account
     * @param _owner account owner address
     * @param _operator account operator address
     * @return True if the _operator is an approved operator for the _owner account
     */
    function isOperator(address _owner, address _operator) external view returns (bool) {
        return operators[_owner][_operator];
    }

    /**
     * @notice returns the current controller configuration
     * @return whitelist, the address of the whitelist module
     * @return oracle, the address of the oracle module
     * @return calculator, the address of the calculator module
     * @return pool, the address of the pool module
     */
    function getConfiguration()
        external
        view
        returns (
            address,
            address,
            address,
            address
        )
    {
        return (address(whitelist), address(oracle), address(calculator), address(pool));
    }

    /**
     * @notice return a vault's proceeds pre or post expiry, the amount of collateral that can be removed from a vault
     * @param _owner account owner of the vault
     * @param _vaultId vaultId to return balances for
     * @return amount of collateral that can be taken out
     */
    function getProceed(address _owner, uint256 _vaultId) external view returns (uint256) {
        (MarginVault.Vault memory vault, uint256 typeVault, ) = getVaultWithDetails(_owner, _vaultId);

        (uint256 netValue, bool isExcess) = calculator.getExcessCollateral(vault, typeVault);

        if (!isExcess) return 0;

        return netValue;
    }

    /**
     * @notice check if a vault is liquidatable in a specific round id
     * @param _owner vault owner address
     * @param _vaultId vault id to check
     * @param _roundId chainlink round id to check vault status at
     * @return isUnderCollat, true if vault is undercollateralized, the price of 1 repaid otoken and the otoken collateral dust amount
     */
    function isLiquidatable(
        address _owner,
        uint256 _vaultId,
        uint256 _roundId
    )
        external
        view
        returns (
            bool,
            uint256,
            uint256
        )
    {
        (, bool isUnderCollat, uint256 price, uint256 dust) = _isLiquidatable(_owner, _vaultId, _roundId);
        return (isUnderCollat, price, dust);
    }

    /**
     * @notice get an oToken's payout/cash value after expiry, in the collateral asset
     * @param _otoken oToken address
     * @param _amount amount of the oToken to calculate the payout for, always represented in 1e8
     * @return amount of collateral to pay out
     */
    function getPayout(address _otoken, uint256 _amount) public view returns (uint256) {
        return calculator.getExpiredPayoutRate(_otoken).mul(_amount).div(10**BASE);
    }

    /**
     * @dev return if an expired oToken is ready to be settled, only true when price for underlying,
     * strike and collateral assets at this specific expiry is available in our Oracle module
     * @param _otoken oToken
     */
    function isSettlementAllowed(address _otoken) external view returns (bool) {
        (address underlying, address strike, address collateral, uint256 expiry) = _getOtokenDetails(_otoken);
        return _canSettleAssets(underlying, strike, collateral, expiry);
    }

    /**
     * @dev return if underlying, strike, collateral are all allowed to be settled
     * @param _underlying oToken underlying asset
     * @param _strike oToken strike asset
     * @param _collateral oToken collateral asset
     * @param _expiry otoken expiry timestamp
     * @return True if the oToken has expired AND all oracle prices at the expiry timestamp have been finalized, False if not
     */
    function canSettleAssets(
        address _underlying,
        address _strike,
        address _collateral,
        uint256 _expiry
    ) external view returns (bool) {
        return _canSettleAssets(_underlying, _strike, _collateral, _expiry);
    }

    /**
     * @notice get the number of vaults for a specified account owner
     * @param _accountOwner account owner address
     * @return number of vaults
     */
    function getAccountVaultCounter(address _accountOwner) external view returns (uint256) {
        return accountVaultCounter[_accountOwner];
    }

    /**
     * @notice check if an oToken has expired
     * @param _otoken oToken address
     * @return True if the otoken has expired, False if not
     */
    function hasExpired(address _otoken) external view returns (bool) {
        return now >= OtokenInterface(_otoken).expiryTimestamp();
    }

    /**
     * @notice return a specific vault
     * @param _owner account owner
     * @param _vaultId vault id of vault to return
     * @return Vault struct that corresponds to the _vaultId of _owner
     */
    function getVault(address _owner, uint256 _vaultId) external view returns (MarginVault.Vault memory) {
        return (vaults[_owner][_vaultId]);
    }

    /**
     * @notice return a specific vault
     * @param _owner account owner
     * @param _vaultId vault id of vault to return
     * @return Vault struct that corresponds to the _vaultId of _owner, vault type and the latest timestamp when the vault was updated
     */
    function getVaultWithDetails(address _owner, uint256 _vaultId)
        public
        view
        returns (
            MarginVault.Vault memory,
            uint256,
            uint256
        )
    {
        return (vaults[_owner][_vaultId], vaultType[_owner][_vaultId], vaultLatestUpdate[_owner][_vaultId]);
    }

    /**
     * @notice get cap amount for collateral asset
     * @param _asset collateral asset address
     * @return cap amount
     */
    function getNakedCap(address _asset) external view returns (uint256) {
        return nakedCap[_asset];
    }

    /**
     * @notice get amount of collateral deposited in all naked margin vaults
     * @param _asset collateral asset address
     * @return naked pool balance
     */
    function getNakedPoolBalance(address _asset) external view returns (uint256) {
        return nakedPoolBalance[_asset];
    }

    /**
     * @notice execute a variety of actions
     * @dev for each action in the action array, execute the corresponding action, only one vault can be modified
     * for all actions except SettleVault, Redeem, and Call
     * @param _actions array of type Actions.ActionArgs[], which expresses which actions the user wants to execute
     * @return vaultUpdated, indicates if a vault has changed
     * @return owner, the vault owner if a vault has changed
     * @return vaultId, the vault Id if a vault has changed
     */
    function _runActions(Actions.ActionArgs[] memory _actions)
        internal
        returns (
            bool,
            address,
            uint256
        )
    {
        address vaultOwner;
        uint256 vaultId;
        bool vaultUpdated;

        for (uint256 i = 0; i < _actions.length; i++) {
            Actions.ActionArgs memory action = _actions[i];
            Actions.ActionType actionType = action.actionType;

            // actions except Settle, Redeem, Liquidate and Call are "Vault-updating actinos"
            // only allow update 1 vault in each operate call
            if (
                (actionType != Actions.ActionType.SettleVault) &&
                (actionType != Actions.ActionType.Redeem) &&
                (actionType != Actions.ActionType.Liquidate) &&
                (actionType != Actions.ActionType.Call)
            ) {
                // check if this action is manipulating the same vault as all other actions, if a vault has already been updated
                if (vaultUpdated) {
                    require(vaultOwner == action.owner, "C12");
                    require(vaultId == action.vaultId, "C13");
                }
                vaultUpdated = true;
                vaultId = action.vaultId;
                vaultOwner = action.owner;
            }

            if (actionType == Actions.ActionType.OpenVault) {
                _openVault(Actions._parseOpenVaultArgs(action));
            } else if (actionType == Actions.ActionType.DepositLongOption) {
                _depositLong(Actions._parseDepositArgs(action));
            } else if (actionType == Actions.ActionType.WithdrawLongOption) {
                _withdrawLong(Actions._parseWithdrawArgs(action));
            } else if (actionType == Actions.ActionType.DepositCollateral) {
                _depositCollateral(Actions._parseDepositArgs(action));
            } else if (actionType == Actions.ActionType.WithdrawCollateral) {
                _withdrawCollateral(Actions._parseWithdrawArgs(action));
            } else if (actionType == Actions.ActionType.MintShortOption) {
                _mintOtoken(Actions._parseMintArgs(action));
            } else if (actionType == Actions.ActionType.BurnShortOption) {
                _burnOtoken(Actions._parseBurnArgs(action));
            } else if (actionType == Actions.ActionType.Redeem) {
                _redeem(Actions._parseRedeemArgs(action));
            } else if (actionType == Actions.ActionType.SettleVault) {
                _settleVault(Actions._parseSettleVaultArgs(action));
            } else if (actionType == Actions.ActionType.Liquidate) {
                _liquidate(Actions._parseLiquidateArgs(action));
            } else if (actionType == Actions.ActionType.Call) {
                _call(Actions._parseCallArgs(action));
            }
        }

        return (vaultUpdated, vaultOwner, vaultId);
    }

    /**
     * @notice verify the vault final state after executing all actions
     * @param _owner account owner address
     * @param _vaultId vault id of the final vault
     */
    function _verifyFinalState(address _owner, uint256 _vaultId) internal view {
        (MarginVault.Vault memory vault, uint256 typeVault, ) = getVaultWithDetails(_owner, _vaultId);
        (, bool isValidVault) = calculator.getExcessCollateral(vault, typeVault);

        require(isValidVault, "C14");
    }

    /**
     * @notice open a new vault inside an account
     * @dev only the account owner or operator can open a vault, cannot be called when system is partiallyPaused or fullyPaused
     * @param _args OpenVaultArgs structure
     */
    function _openVault(Actions.OpenVaultArgs memory _args)
        internal
        notPartiallyPaused
        onlyAuthorized(msg.sender, _args.owner)
    {
        uint256 vaultId = accountVaultCounter[_args.owner].add(1);

        require(_args.vaultId == vaultId, "C15");

        // store new vault
        accountVaultCounter[_args.owner] = vaultId;
        vaultType[_args.owner][vaultId] = _args.vaultType;

        emit VaultOpened(_args.owner, vaultId, _args.vaultType);
    }

    /**
     * @notice deposit a long oToken into a vault
     * @dev only the account owner or operator can deposit a long oToken, cannot be called when system is partiallyPaused or fullyPaused
     * @param _args DepositArgs structure
     */
    function _depositLong(Actions.DepositArgs memory _args)
        internal
        notPartiallyPaused
        onlyAuthorized(msg.sender, _args.owner)
    {
        require(_checkVaultId(_args.owner, _args.vaultId), "C35");
        // only allow vault owner or vault operator to deposit long otoken
        require((_args.from == msg.sender) || (_args.from == _args.owner), "C16");

        require(whitelist.isWhitelistedOtoken(_args.asset), "C17");

        OtokenInterface otoken = OtokenInterface(_args.asset);

        require(now < otoken.expiryTimestamp(), "C18");

        vaults[_args.owner][_args.vaultId].addLong(_args.asset, _args.amount, _args.index);

        pool.transferToPool(_args.asset, _args.from, _args.amount);

        emit LongOtokenDeposited(_args.asset, _args.owner, _args.from, _args.vaultId, _args.amount);
    }

    /**
     * @notice withdraw a long oToken from a vault
     * @dev only the account owner or operator can withdraw a long oToken, cannot be called when system is partiallyPaused or fullyPaused
     * @param _args WithdrawArgs structure
     */
    function _withdrawLong(Actions.WithdrawArgs memory _args)
        internal
        notPartiallyPaused
        onlyAuthorized(msg.sender, _args.owner)
    {
        require(_checkVaultId(_args.owner, _args.vaultId), "C35");

        OtokenInterface otoken = OtokenInterface(_args.asset);

        require(now < otoken.expiryTimestamp(), "C19");

        vaults[_args.owner][_args.vaultId].removeLong(_args.asset, _args.amount, _args.index);

        pool.transferToUser(_args.asset, _args.to, _args.amount);

        emit LongOtokenWithdrawed(_args.asset, _args.owner, _args.to, _args.vaultId, _args.amount);
    }

    /**
     * @notice deposit a collateral asset into a vault
     * @dev only the account owner or operator can deposit collateral, cannot be called when system is partiallyPaused or fullyPaused
     * @param _args DepositArgs structure
     */
    function _depositCollateral(Actions.DepositArgs memory _args)
        internal
        notPartiallyPaused
        onlyAuthorized(msg.sender, _args.owner)
    {
        require(_checkVaultId(_args.owner, _args.vaultId), "C35");
        // only allow vault owner or vault operator to deposit collateral
        require((_args.from == msg.sender) || (_args.from == _args.owner), "C20");

        require(whitelist.isWhitelistedCollateral(_args.asset), "C21");

        (, uint256 typeVault, ) = getVaultWithDetails(_args.owner, _args.vaultId);

        if (typeVault == 1) {
            nakedPoolBalance[_args.asset] = nakedPoolBalance[_args.asset].add(_args.amount);

            require(nakedPoolBalance[_args.asset] <= nakedCap[_args.asset], "C37");
        }

        vaults[_args.owner][_args.vaultId].addCollateral(_args.asset, _args.amount, _args.index);

        pool.transferToPool(_args.asset, _args.from, _args.amount);

        emit CollateralAssetDeposited(_args.asset, _args.owner, _args.from, _args.vaultId, _args.amount);
    }

    /**
     * @notice withdraw a collateral asset from a vault
     * @dev only the account owner or operator can withdraw collateral, cannot be called when system is partiallyPaused or fullyPaused
     * @param _args WithdrawArgs structure
     */
    function _withdrawCollateral(Actions.WithdrawArgs memory _args)
        internal
        notPartiallyPaused
        onlyAuthorized(msg.sender, _args.owner)
    {
        require(_checkVaultId(_args.owner, _args.vaultId), "C35");

        (MarginVault.Vault memory vault, uint256 typeVault, ) = getVaultWithDetails(_args.owner, _args.vaultId);

        if (_isNotEmpty(vault.shortOtokens)) {
            OtokenInterface otoken = OtokenInterface(vault.shortOtokens[0]);

            require(now < otoken.expiryTimestamp(), "C22");
        }

        if (typeVault == 1) {
            nakedPoolBalance[_args.asset] = nakedPoolBalance[_args.asset].sub(_args.amount);
        }

        vaults[_args.owner][_args.vaultId].removeCollateral(_args.asset, _args.amount, _args.index);

        pool.transferToUser(_args.asset, _args.to, _args.amount);

        emit CollateralAssetWithdrawed(_args.asset, _args.owner, _args.to, _args.vaultId, _args.amount);
    }

    /**
     * @notice mint short oTokens from a vault which creates an obligation that is recorded in the vault
     * @dev only the account owner or operator can mint an oToken, cannot be called when system is partiallyPaused or fullyPaused
     * @param _args MintArgs structure
     */
    function _mintOtoken(Actions.MintArgs memory _args)
        internal
        notPartiallyPaused
        onlyAuthorized(msg.sender, _args.owner)
    {
        require(_checkVaultId(_args.owner, _args.vaultId), "C35");
        require(whitelist.isWhitelistedOtoken(_args.otoken), "C23");

        OtokenInterface otoken = OtokenInterface(_args.otoken);

        require(now < otoken.expiryTimestamp(), "C24");

        vaults[_args.owner][_args.vaultId].addShort(_args.otoken, _args.amount, _args.index);

        otoken.mintOtoken(_args.to, _args.amount);

        emit ShortOtokenMinted(_args.otoken, _args.owner, _args.to, _args.vaultId, _args.amount);
    }

    /**
     * @notice burn oTokens to reduce or remove the minted oToken obligation recorded in a vault
     * @dev only the account owner or operator can burn an oToken, cannot be called when system is partiallyPaused or fullyPaused
     * @param _args MintArgs structure
     */
    function _burnOtoken(Actions.BurnArgs memory _args)
        internal
        notPartiallyPaused
        onlyAuthorized(msg.sender, _args.owner)
    {
        // check that vault id is valid for this vault owner
        require(_checkVaultId(_args.owner, _args.vaultId), "C35");
        // only allow vault owner or vault operator to burn otoken
        require((_args.from == msg.sender) || (_args.from == _args.owner), "C25");

        OtokenInterface otoken = OtokenInterface(_args.otoken);

        // do not allow burning expired otoken
        require(now < otoken.expiryTimestamp(), "C26");

        // remove otoken from vault
        vaults[_args.owner][_args.vaultId].removeShort(_args.otoken, _args.amount, _args.index);

        // burn otoken
        otoken.burnOtoken(_args.from, _args.amount);

        emit ShortOtokenBurned(_args.otoken, _args.owner, _args.from, _args.vaultId, _args.amount);
    }

    /**
     * @notice redeem an oToken after expiry, receiving the payout of the oToken in the collateral asset
     * @dev cannot be called when system is fullyPaused
     * @param _args RedeemArgs structure
     */
    function _redeem(Actions.RedeemArgs memory _args) internal {
        OtokenInterface otoken = OtokenInterface(_args.otoken);

        // check that otoken to redeem is whitelisted
        require(whitelist.isWhitelistedOtoken(_args.otoken), "C27");

        (address collateral, address underlying, address strike, uint256 expiry) = _getOtokenDetails(address(otoken));

        // only allow redeeming expired otoken
        require(now >= expiry, "C28");

        require(_canSettleAssets(underlying, strike, collateral, expiry), "C29");

        uint256 payout = getPayout(_args.otoken, _args.amount);

        otoken.burnOtoken(msg.sender, _args.amount);

        pool.transferToUser(collateral, _args.receiver, payout);

        emit Redeem(_args.otoken, msg.sender, _args.receiver, collateral, _args.amount, payout);
    }

    /**
     * @notice settle a vault after expiry, removing the net proceeds/collateral after both long and short oToken payouts have settled
     * @dev deletes a vault of vaultId after net proceeds/collateral is removed, cannot be called when system is fullyPaused
     * @param _args SettleVaultArgs structure
     */
    function _settleVault(Actions.SettleVaultArgs memory _args) internal onlyAuthorized(msg.sender, _args.owner) {
        require(_checkVaultId(_args.owner, _args.vaultId), "C35");

        (MarginVault.Vault memory vault, uint256 typeVault, ) = getVaultWithDetails(_args.owner, _args.vaultId);

        OtokenInterface otoken;

        // new scope to avoid stack too deep error
        // check if there is short or long otoken in vault
        // do not allow settling vault that have no short or long otoken
        // if there is a long otoken, burn it
        // store otoken address outside of this scope
        {
            bool hasShort = _isNotEmpty(vault.shortOtokens);
            bool hasLong = _isNotEmpty(vault.longOtokens);

            require(hasShort || hasLong, "C30");

            otoken = hasShort ? OtokenInterface(vault.shortOtokens[0]) : OtokenInterface(vault.longOtokens[0]);

            if (hasLong) {
                OtokenInterface longOtoken = OtokenInterface(vault.longOtokens[0]);

                longOtoken.burnOtoken(address(pool), vault.longAmounts[0]);
            }
        }

        (address collateral, address underlying, address strike, uint256 expiry) = _getOtokenDetails(address(otoken));

        // do not allow settling vault with un-expired otoken
        require(now >= expiry, "C31");
        require(_canSettleAssets(underlying, strike, collateral, expiry), "C29");

        (uint256 payout, bool isValidVault) = calculator.getExcessCollateral(vault, typeVault);

        // require that vault is valid (has excess collateral) before settling
        // to avoid allowing settling undercollateralized naked margin vault
        require(isValidVault, "C32");

        delete vaults[_args.owner][_args.vaultId];

        if (typeVault == 1) {
            nakedPoolBalance[collateral] = nakedPoolBalance[collateral].sub(payout);
        }

        pool.transferToUser(collateral, _args.to, payout);

        uint256 vaultId = _args.vaultId;
        address payoutRecipient = _args.to;

        emit VaultSettled(_args.owner, address(otoken), payoutRecipient, payout, vaultId, typeVault);
    }

    /**
     * @notice liquidate naked margin vault
     * @dev can liquidate different vaults id in the same operate() call
     * @param _args liquidation action arguments struct
     */
    function _liquidate(Actions.LiquidateArgs memory _args) internal notPartiallyPaused {
        require(_checkVaultId(_args.owner, _args.vaultId), "C35");

        // check if vault is undercollateralized
        // the price is the amount of collateral asset to pay per 1 repaid debt(otoken)
        // collateralDust is the minimum amount of collateral that can be left in the vault when a partial liquidation occurs
        (MarginVault.Vault memory vault, bool isUnderCollat, uint256 price, uint256 collateralDust) = _isLiquidatable(
            _args.owner,
            _args.vaultId,
            _args.roundId
        );

        require(isUnderCollat, "C33");

        // amount of collateral to offer to liquidator
        uint256 collateralToSell = _args.amount.mul(price).div(1e8);

        // if vault is partially liquidated (amount of short otoken is still greater than zero)
        // make sure remaining collateral amount is greater than dust amount
        if (vault.shortAmounts[0].sub(_args.amount) > 0) {
            require(vault.collateralAmounts[0].sub(collateralToSell) >= collateralDust, "C34");
        }

        // burn short otoken from liquidator address, index of short otoken hardcoded at 0
        // this should always work, if vault have no short otoken, it will not reach this step
        OtokenInterface(vault.shortOtokens[0]).burnOtoken(msg.sender, _args.amount);

        // decrease amount of collateral in liquidated vault, index of collateral to decrease is hardcoded at 0
        vaults[_args.owner][_args.vaultId].removeCollateral(vault.collateralAssets[0], collateralToSell, 0);

        // decrease amount of short otoken in liquidated vault, index of short otoken to decrease is hardcoded at 0
        vaults[_args.owner][_args.vaultId].removeShort(vault.shortOtokens[0], _args.amount, 0);

        // decrease internal naked margin collateral amount
        nakedPoolBalance[vault.collateralAssets[0]] = nakedPoolBalance[vault.collateralAssets[0]].sub(collateralToSell);

        pool.transferToUser(vault.collateralAssets[0], _args.receiver, collateralToSell);

        emit VaultLiquidated(
            msg.sender,
            _args.receiver,
            _args.owner,
            price,
            _args.roundId,
            collateralToSell,
            _args.amount,
            _args.vaultId
        );
    }

    /**
     * @notice execute arbitrary calls
     * @dev cannot be called when system is partiallyPaused or fullyPaused
     * @param _args Call action
     */
    function _call(Actions.CallArgs memory _args) internal notPartiallyPaused onlyWhitelistedCallee(_args.callee) {
        CalleeInterface(_args.callee).callFunction(msg.sender, _args.data);

        emit CallExecuted(msg.sender, _args.callee, _args.data);
    }

    /**
     * @notice check if a vault id is valid for a given account owner address
     * @param _accountOwner account owner address
     * @param _vaultId vault id to check
     * @return True if the _vaultId is valid, False if not
     */
    function _checkVaultId(address _accountOwner, uint256 _vaultId) internal view returns (bool) {
        return ((_vaultId > 0) && (_vaultId <= accountVaultCounter[_accountOwner]));
    }

    function _isNotEmpty(address[] memory _array) internal pure returns (bool) {
        return (_array.length > 0) && (_array[0] != address(0));
    }

    /**
     * @notice return if a callee address is whitelisted or not
     * @param _callee callee address
     * @return True if callee address is whitelisted, False if not
     */
    function _isCalleeWhitelisted(address _callee) internal view returns (bool) {
        return whitelist.isWhitelistedCallee(_callee);
    }

    /**
     * @notice check if a vault is liquidatable in a specific round id
     * @param _owner vault owner address
     * @param _vaultId vault id to check
     * @param _roundId chainlink round id to check vault status at
     * @return vault struct, isLiquidatable, true if vault is undercollateralized, the price of 1 repaid otoken and the otoken collateral dust amount
     */
    function _isLiquidatable(
        address _owner,
        uint256 _vaultId,
        uint256 _roundId
    )
        internal
        view
        returns (
            MarginVault.Vault memory,
            bool,
            uint256,
            uint256
        )
    {
        (MarginVault.Vault memory vault, uint256 typeVault, uint256 latestUpdateTimestamp) = getVaultWithDetails(
            _owner,
            _vaultId
        );
        (bool isUnderCollat, uint256 price, uint256 collateralDust) = calculator.isLiquidatable(
            vault,
            typeVault,
            latestUpdateTimestamp,
            _roundId
        );

        return (vault, isUnderCollat, price, collateralDust);
    }

    /**
     * @dev get otoken detail, from both otoken versions
     */
    function _getOtokenDetails(address _otoken)
        internal
        view
        returns (
            address,
            address,
            address,
            uint256
        )
    {
        OtokenInterface otoken = OtokenInterface(_otoken);
        try otoken.getOtokenDetails() returns (
            address collateral,
            address underlying,
            address strike,
            uint256,
            uint256 expiry,
            bool
        ) {
            return (collateral, underlying, strike, expiry);
        } catch {
            return (otoken.collateralAsset(), otoken.underlyingAsset(), otoken.strikeAsset(), otoken.expiryTimestamp());
        }
    }

    /**
     * @dev return if an expired oToken is ready to be settled, only true when price for underlying,
     * strike and collateral assets at this specific expiry is available in our Oracle module
     * @return True if the oToken has expired AND all oracle prices at the expiry timestamp have been finalized, False if not
     */
    function _canSettleAssets(
        address _underlying,
        address _strike,
        address _collateral,
        uint256 _expiry
    ) internal view returns (bool) {
        return
            oracle.isDisputePeriodOver(_underlying, _expiry) &&
            oracle.isDisputePeriodOver(_strike, _expiry) &&
            oracle.isDisputePeriodOver(_collateral, _expiry);
    }

    /**
     * @dev updates the internal configuration of the controller
     */
    function _refreshConfigInternal() internal {
        whitelist = WhitelistInterface(addressbook.getWhitelist());
        oracle = OracleInterface(addressbook.getOracle());
        calculator = MarginCalculatorInterface(addressbook.getMarginCalculator());
        pool = MarginPoolInterface(addressbook.getMarginPool());
    }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"accountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"isSet","type":"bool"}],"name":"AccountOperatorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"CallExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isRestricted","type":"bool"}],"name":"CallRestricted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"accountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CollateralAssetDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"AccountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CollateralAssetWithdrawed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"donator","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Donated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldFullPauser","type":"address"},{"indexed":true,"internalType":"address","name":"newFullPauser","type":"address"}],"name":"FullPauserUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"accountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LongOtokenDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"AccountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LongOtokenWithdrawed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"NakedCapUpdated","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":true,"internalType":"address","name":"oldPartialPauser","type":"address"},{"indexed":true,"internalType":"address","name":"newPartialPauser","type":"address"}],"name":"PartialPauserUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"collateralAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"otokenBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"AccountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ShortOtokenBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"AccountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ShortOtokenMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"SystemFullyPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"SystemPartiallyPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"vaultOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"auctionPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"auctionStartingRound","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralPayout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"VaultLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"accountOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vaultType","type":"uint256"}],"name":"VaultOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"accountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"oTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vaultType","type":"uint256"}],"name":"VaultSettled","type":"event"},{"inputs":[],"name":"addressbook","outputs":[{"internalType":"contract AddressBookInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculator","outputs":[{"internalType":"contract MarginCalculatorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callRestricted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_underlying","type":"address"},{"internalType":"address","name":"_strike","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_expiry","type":"uint256"}],"name":"canSettleAssets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"donate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fullPauser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_accountOwner","type":"address"}],"name":"getAccountVaultCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfiguration","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"getNakedCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"getNakedPoolBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_otoken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"getProceed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"getVault","outputs":[{"components":[{"internalType":"address[]","name":"shortOtokens","type":"address[]"},{"internalType":"address[]","name":"longOtokens","type":"address[]"},{"internalType":"address[]","name":"collateralAssets","type":"address[]"},{"internalType":"uint256[]","name":"shortAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"longAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"collateralAmounts","type":"uint256[]"}],"internalType":"struct MarginVault.Vault","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"getVaultWithDetails","outputs":[{"components":[{"internalType":"address[]","name":"shortOtokens","type":"address[]"},{"internalType":"address[]","name":"longOtokens","type":"address[]"},{"internalType":"address[]","name":"collateralAssets","type":"address[]"},{"internalType":"uint256[]","name":"shortAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"longAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"collateralAmounts","type":"uint256[]"}],"internalType":"struct MarginVault.Vault","name":"","type":"tuple"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_otoken","type":"address"}],"name":"hasExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addressBook","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"uint256","name":"_roundId","type":"uint256"}],"name":"isLiquidatable","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_otoken","type":"address"}],"name":"isSettlementAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum Actions.ActionType","name":"actionType","type":"uint8"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"secondAddress","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Actions.ActionArgs[]","name":"_actions","type":"tuple[]"}],"name":"operate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract OracleInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"partialPauser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract MarginPoolInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refreshConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isRestricted","type":"bool"}],"name":"setCallRestriction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fullPauser","type":"address"}],"name":"setFullPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"setNakedCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_isOperator","type":"bool"}],"name":"setOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_partialPauser","type":"address"}],"name":"setPartialPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_fullyPaused","type":"bool"}],"name":"setSystemFullyPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_partiallyPaused","type":"bool"}],"name":"setSystemPartiallyPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"systemFullyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"systemPartiallyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelist","outputs":[{"internalType":"contract WhitelistInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50615d8f80620000216000396000f3fe608060405234801561001057600080fd5b50600436106102325760003560e01c8063b617f0c611610130578063ce3e39c0116100b8578063eaa33e141161007c578063eaa33e1414610479578063eab7775b1461049b578063ef4fcafa146104a3578063f2fde38b146104b6578063f77bc88b146104c957610232565b8063ce3e39c014610418578063d66dd43e14610420578063d99d13f514610433578063e69d849d14610453578063e723406c1461046657610232565b8063c220101d116100ff578063c220101d146103c4578063c644d3a2146103d7578063caa6d21a146103ea578063cab2e805146103fd578063cdee058a1461041057610232565b8063b617f0c614610378578063b6363cf21461038b578063bc463a3d1461039e578063beca75d7146103b157610232565b80636bd50cef116101be5780638da5cb5b116101825780638da5cb5b1461032b57806393e59dc1146103335780639daafbe81461033b5780639db938911461035d5780639f677ed91461036557610232565b80636bd50cef146102f35780636c0c3b991461030b57806370dc320c14610313578063715018a61461031b5780637dc0d1d01461032357610232565b8063485cc95511610205578063485cc95514610292578063558a7297146102a5578063565eea19146102b8578063573c473e146102d857806364681083146102eb57610232565b806314b93faf1461023757806316f0115b1461026057806329729d88146102755780632eb1c3a71461027d575b600080fd5b61024a610245366004614e73565b6104dc565b60405161025791906153c0565b60405180910390f35b6102686104f3565b60405161025791906152f7565b610268610502565b61029061028b366004614f63565b610511565b005b6102906102a0366004614e3b565b6105c6565b6102906102b3366004614f36565b6106de565b6102cb6102c6366004614f63565b610797565b6040516102579190615cd5565b6102906102e63660046150f8565b610849565b610290610900565b6102fb61093f565b6040516102579493929190615374565b61024a610964565b610268610974565b610290610983565b610268610a02565b610268610a11565b610268610a21565b61034e610349366004614f63565b610a30565b60405161025793929190615c5d565b610268610cc9565b6102906103733660046150f8565b610cd8565b610290610386366004614fc2565b610d84565b61024a610399366004614e3b565b610e16565b6102906103ac366004614e03565b610e44565b6102906103bf366004614e03565b610f29565b6102cb6103d2366004614f63565b61100e565b6102cb6103e5366004614e03565b6110cf565b6102cb6103f8366004614e03565b6110ea565b61029061040b3660046150f8565b611105565b61024a6111bc565b6102686111cc565b6102cb61042e366004614e03565b6111db565b610446610441366004614f63565b6111f6565b6040516102579190615c28565b610290610461366004614f63565b611457565b61024a610474366004614e03565b611500565b61048c610487366004614f8e565b61152f565b604051610257939291906153cb565b61024a611556565b6102906104b1366004614f63565b611566565b6102906104c4366004614e03565b6115d9565b61024a6104d7366004614e03565b611690565b60006104ea8585858561170c565b95945050505050565b60cd546001600160a01b031681565b60cf546001600160a01b031681565b6105196118a1565b6065546001600160a01b0390811691161461054f5760405162461bcd60e51b8152600401610546906158a3565b60405180910390fd5b6000811161056f5760405162461bcd60e51b81526004016105469061575f565b6001600160a01b038216600081815260d5602052604090819020839055517f6ff730ba70e34bd5ca823424bd15ab869cadc6bad079b527c71bde444ad6402b906105ba908490615cd5565b60405180910390a25050565b600054610100900460ff16806105df57506105df6118a5565b806105ed575060005460ff16155b6106095760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff16158015610634576000805460ff1961ff0019909116610100171660011790555b6001600160a01b03831661065a5760405162461bcd60e51b81526004016105469061580c565b6001600160a01b0382166106805760405162461bcd60e51b815260040161054690615bd4565b610689826118ab565b610691611940565b60c980546001600160a01b0319166001600160a01b0385161790556106b46119d0565b60cf805460ff60b01b1916600160b01b17905580156106d9576000805461ff00191690555b505050565b33600090815260d2602090815260408083206001600160a01b038616845290915290205460ff16151581151514156107285760405162461bcd60e51b815260040161054690615af2565b33600081815260d2602090815260408083206001600160a01b038716808552925291829020805460ff191685151517905590519091907f1ae45540b0875932452da603b351ce2f1758258ba1345e79f8fc94f044cb07879061078b9085906153c0565b60405180910390a35050565b60cc54604051630478409360e41b8152600091610840916305f5e100916108349186916001600160a01b0316906347840930906107d8908a906004016152f7565b60206040518083038186803b1580156107f057600080fd5b505afa158015610804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108289190615166565b9063ffffffff611c2b16565b9063ffffffff611c6516565b90505b92915050565b60ce546001600160a01b031633146108735760405162461bcd60e51b81526004016105469061553f565b60cf5460ff600160a01b90910416151581151514156108a45760405162461bcd60e51b815260040161054690615af2565b60cf805460ff60a01b1916600160a01b831515810291909117918290556040517f531c3d7229f510a8da00a0f5792686958cdd9c8a120c3c030a6053cd66b68556926108f59260ff910416906153c0565b60405180910390a150565b6109086118a1565b6065546001600160a01b039081169116146109355760405162461bcd60e51b8152600401610546906158a3565b61093d6119d0565b565b60ca5460cb5460cc5460cd546001600160a01b03938416949284169391821692911690565b60cf54600160b01b900460ff1681565b60c9546001600160a01b031681565b61098b6118a1565b6065546001600160a01b039081169116146109b85760405162461bcd60e51b8152600401610546906158a3565b6065546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606580546001600160a01b0319169055565b60cb546001600160a01b031681565b6065546001600160a01b03165b90565b60ca546001600160a01b031681565b610a38614bb9565b6001600160a01b038316600081815260d160209081526040808320868452825280832084845260d3835281842087855283528184205494845260d483528184208785528352818420548251825460e09581028201860190945260c081018481529596879693959094929391928692849290918491840182828015610ae557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ac7575b5050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015610b4757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b29575b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610ba957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b8b575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610c0157602002820191906000526020600020905b815481526020019060010190808311610bed575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020018280548015610c5957602002820191906000526020600020905b815481526020019060010190808311610c45575b5050505050815260200160058201805480602002602001604051908101604052809291908181526020018280548015610cb157602002820191906000526020600020905b815481526020019060010190808311610c9d575b50505050508152505092509250925092509250925092565b60ce546001600160a01b031681565b60cf546001600160a01b03163314610d025760405162461bcd60e51b81526004016105469061577c565b60cf5460ff600160a81b9091041615158115151415610d335760405162461bcd60e51b815260040161054690615af2565b60cf805460ff60a81b1916600160a81b831515810291909117918290556040517f4f1d0445688d95c99ca9fc036f551b205fd18ff26a4443b1979c16d1ba66b535926108f59260ff910416906153c0565b60975460ff16610da65760405162461bcd60e51b815260040161054690615b9d565b6097805460ff19169055610db8611ca7565b6000806000610dc684611cd1565b9250925092508215610e0357610ddc8282611f87565b6001600160a01b038216600090815260d46020908152604080832084845290915290204290555b50506097805460ff191660011790555050565b6001600160a01b03918216600090815260d26020908152604080832093909416825291909152205460ff1690565b610e4c6118a1565b6065546001600160a01b03908116911614610e795760405162461bcd60e51b8152600401610546906158a3565b6001600160a01b038116610e9f5760405162461bcd60e51b815260040161054690615679565b60ce546001600160a01b0382811691161415610ecd5760405162461bcd60e51b815260040161054690615af2565b60ce546040516001600160a01b038084169216907f1440312dbc326ddc21bfa95078324bf5aaf6899e8a27cba3057c60adfc84e40b90600090a360ce80546001600160a01b0319166001600160a01b0392909216919091179055565b610f316118a1565b6065546001600160a01b03908116911614610f5e5760405162461bcd60e51b8152600401610546906158a3565b6001600160a01b038116610f845760405162461bcd60e51b8152600401610546906155af565b60cf546001600160a01b0382811691161415610fb25760405162461bcd60e51b815260040161054690615af2565b60cf546040516001600160a01b038084169216907f44f3e9e7b454118e9fcb2e3026396f57ca21d7bd7dcabd31d7f986806422f4df90600090a360cf80546001600160a01b0319166001600160a01b0392909216919091179055565b6000611018614bb9565b60006110248585610a30565b5060cc5460405163cd43fbfb60e01b815292945090925060009182916001600160a01b03169063cd43fbfb906110609087908790600401615c3b565b604080518083038186803b15801561107757600080fd5b505afa15801561108b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110af919061517e565b91509150806110c5576000945050505050610843565b5095945050505050565b6001600160a01b0316600090815260d5602052604090205490565b6001600160a01b0316600090815260d0602052604090205490565b61110d6118a1565b6065546001600160a01b0390811691161461113a5760405162461bcd60e51b8152600401610546906158a3565b60cf5460ff600160b01b909104161515811515141561116b5760405162461bcd60e51b815260040161054690615af2565b60cf805460ff60b01b1916600160b01b831515810291909117918290556040517f26d614575a4c104c181c87003d4bb00cc7ade00d5b47bf8775171c12a376b255926108f59260ff910416906153c0565b60cf54600160a01b900460ff1681565b60cc546001600160a01b031681565b6001600160a01b0316600090815260d6602052604090205490565b6111fe614bb9565b6001600160a01b038316600090815260d1602090815260408083208584528252918290208251815460e09381028201840190945260c08101848152909391928492849184018282801561127a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161125c575b50505050508152602001600182018054806020026020016040519081016040528092919081815260200182805480156112dc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112be575b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561133e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611320575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561139657602002820191906000526020600020905b815481526020019060010190808311611382575b50505050508152602001600482018054806020026020016040519081016040528092919081815260200182805480156113ee57602002820191906000526020600020905b8154815260200190600101908083116113da575b505050505081526020016005820180548060200260200160405190810160405280929190818152602001828054801561144657602002820191906000526020600020905b815481526020019060010190808311611432575b505050505081525050905092915050565b60cd5460405163dd2c99f760e01b81526001600160a01b039091169063dd2c99f79061148b90859033908690600401615350565b600060405180830381600087803b1580156114a557600080fd5b505af11580156114b9573d6000803e3d6000fd5b50505050816001600160a01b0316336001600160a01b03167f4dfff917e1fbb261a082e98cc7d43029621f6a6eb05ff3fef1510d5f1eb4857c8360405161078b9190615cd5565b60008060008060006115118661204d565b93509350935093506115258484848461170c565b9695505050505050565b6000806000806000806115438989896122b2565b919c909b50909950975050505050505050565b60cf54600160a81b900460ff1681565b60975460ff166115885760405162461bcd60e51b815260040161054690615b9d565b6097805460ff1916905561159a611ca7565b6115a48282611f87565b6001600160a01b03909116600090815260d460209081526040808320938352929052204290556097805460ff19166001179055565b6115e16118a1565b6065546001600160a01b0390811691161461160e5760405162461bcd60e51b8152600401610546906158a3565b6001600160a01b0381166116345760405162461bcd60e51b8152600401610546906154f9565b6065546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116cb57600080fd5b505afa1580156116df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117039190615166565b42101592915050565b60cb54604051635fdc714960e01b81526000916001600160a01b031690635fdc71499061173f9088908690600401615337565b60206040518083038186803b15801561175757600080fd5b505afa15801561176b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178f9190615114565b8015611818575060cb54604051635fdc714960e01b81526001600160a01b0390911690635fdc7149906117c89087908690600401615337565b60206040518083038186803b1580156117e057600080fd5b505afa1580156117f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118189190615114565b80156104ea575060cb54604051635fdc714960e01b81526001600160a01b0390911690635fdc7149906118519086908690600401615337565b60206040518083038186803b15801561186957600080fd5b505afa15801561187d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ea9190615114565b3390565b303b1590565b600054610100900460ff16806118c457506118c46118a5565b806118d2575060005460ff16155b6118ee5760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff16158015611919576000805460ff1961ff0019909116610100171660011790555b61192161238d565b61192a8261240f565b801561193c576000805461ff00191690555b5050565b600054610100900460ff168061195957506119596118a5565b80611967575060005460ff16155b6119835760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff161580156119ae576000805460ff1961ff0019909116610100171660011790555b6097805460ff1916600117905580156119cd576000805461ff00191690555b50565b60c960009054906101000a90046001600160a01b03166001600160a01b031663d01f63f56040518163ffffffff1660e01b815260040160206040518083038186803b158015611a1e57600080fd5b505afa158015611a32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a569190614e1f565b60ca80546001600160a01b0319166001600160a01b0392831617905560c9546040805163419d8fe760e11b81529051919092169163833b1fce916004808301926020929190829003018186803b158015611aaf57600080fd5b505afa158015611ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae79190614e1f565b60cb80546001600160a01b0319166001600160a01b0392831617905560c9546040805163cf28493f60e01b81529051919092169163cf28493f916004808301926020929190829003018186803b158015611b4057600080fd5b505afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b789190614e1f565b60cc80546001600160a01b0319166001600160a01b0392831617905560c95460408051633aa431a160e11b8152905191909216916375486342916004808301926020929190829003018186803b158015611bd157600080fd5b505afa158015611be5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c099190614e1f565b60cd80546001600160a01b0319166001600160a01b0392909216919091179055565b600082611c3a57506000610843565b82820282848281611c4757fe5b04146108405760405162461bcd60e51b815260040161054690615845565b600061084083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506124db565b60cf54600160a81b900460ff161561093d5760405162461bcd60e51b815260040161054690615c0c565b60008080808080805b8751811015611f7b57611ceb614bef565b888281518110611cf757fe5b60209081029190910101518051909150600781600a811115611d1557fe5b14158015611d2f5750600881600a811115611d2c57fe5b14155b8015611d475750600a81600a811115611d4457fe5b14155b8015611d5f5750600981600a811115611d5c57fe5b14155b15611dd5578315611dc25781602001516001600160a01b0316866001600160a01b031614611d9f5760405162461bcd60e51b8152600401610546906157d2565b81608001518514611dc25760405162461bcd60e51b8152600401610546906155e9565b6001935081608001519450816020015195505b600081600a811115611de357fe5b1415611dff57611dfa611df583612512565b6125ea565b611f71565b600381600a811115611e0d57fe5b1415611e2457611dfa611e1f836126d9565b6127b5565b600481600a811115611e3257fe5b1415611e4957611dfa611e4483612b06565b612ba5565b600581600a811115611e5757fe5b1415611e6e57611dfa611e69836126d9565b612df9565b600681600a811115611e7c57fe5b1415611e9357611dfa611e8e83612b06565b613157565b600181600a811115611ea157fe5b1415611eb857611dfa611eb38361345b565b6134b9565b600281600a811115611ec657fe5b1415611edd57611dfa611ed8836137a1565b6137ff565b600881600a811115611eeb57fe5b1415611f0257611dfa611efd83613a98565b613b2a565b600781600a811115611f1057fe5b1415611f2757611dfa611f2283613d79565b613e41565b600a81600a811115611f3557fe5b1415611f4c57611dfa611f478361429e565b6143b8565b600981600a811115611f5a57fe5b1415611f7157611f71611f6c83614837565b6148bc565b5050600101611cda565b50969195509350915050565b611f8f614bb9565b6000611f9b8484610a30565b5060cc5460405163cd43fbfb60e01b81529294509092506000916001600160a01b039091169063cd43fbfb90611fd79086908690600401615c3b565b604080518083038186803b158015611fee57600080fd5b505afa158015612002573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612026919061517e565b915050806120465760405162461bcd60e51b815260040161054690615412565b5050505050565b6000806000806000859050806001600160a01b031663af0968fc6040518163ffffffff1660e01b815260040160c06040518083038186803b15801561209157600080fd5b505afa9250505080156120c1575060408051601f3d908101601f191682019092526120be91810190614ec3565b60015b61229757806001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156120fe57600080fd5b505afa158015612112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121369190614e1f565b816001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561216f57600080fd5b505afa158015612183573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a79190614e1f565b826001600160a01b03166317d69bc86040518163ffffffff1660e01b815260040160206040518083038186803b1580156121e057600080fd5b505afa1580156121f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122189190614e1f565b836001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561225157600080fd5b505afa158015612265573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122899190615166565b9450945094509450506122ab565b5093985091965094509092506122ab915050565b9193509193565b6122ba614bb9565b60008060006122c7614bb9565b6000806122d48a8a610a30565b925092509250600080600060cc60009054906101000a90046001600160a01b03166001600160a01b031663a6c569078787878f6040518563ffffffff1660e01b81526004016123269493929190615c82565b60606040518083038186803b15801561233e57600080fd5b505afa158015612352573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123769190615130565b979f919e509c50959a509498505050505050505050565b600054610100900460ff16806123a657506123a66118a5565b806123b4575060005460ff16155b6123d05760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff161580156123fb576000805460ff1961ff0019909116610100171660011790555b80156119cd576000805461ff001916905550565b600054610100900460ff168061242857506124286118a5565b80612436575060005460ff16155b6124525760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff1615801561247d576000805460ff1961ff0019909116610100171660011790555b606580546001600160a01b0319166001600160a01b0384169081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3801561193c576000805461ff00191690555050565b600081836124fc5760405162461bcd60e51b815260040161054691906153e3565b50600083858161250857fe5b0495945050505050565b61251a614c50565b60008251600a81111561252957fe5b146125465760405162461bcd60e51b815260040161054690615623565b60208201516001600160a01b03166125705760405162461bcd60e51b8152600401610546906156b2565b60008260e00151516020141561259b578260e001518060200190518101906125989190615166565b90505b600281106125bb5760405162461bcd60e51b8152600401610546906154c0565b604080516060810182526020808601516001600160a01b03168252608090950151948101949094528301525090565b6125f26149af565b8051339061260082826149d9565b82516001600160a01b0316600090815260d0602052604081205461262b90600163ffffffff614a3a16565b9050808460200151146126505760405162461bcd60e51b8152600401610546906157b5565b83516001600160a01b03908116600090815260d060209081526040808320859055808801805189518616855260d384528285208786529093529281902091909155905186519151909291909116907f5d66689e2c864b4f21efd3988c0ce5dc8a197981b68e81ce73660e92394fe25f906126cb908590615cd5565b60405180910390a350505050565b6126e1614c7a565b60038251600a8111156126f057fe5b1480612708575060058251600a81111561270657fe5b145b6127245760405162461bcd60e51b8152600401610546906159f1565b60208201516001600160a01b031661274e5760405162461bcd60e51b815260040161054690615a0d565b6040518060c0016040528083602001516001600160a01b031681526020018360800151815260200183604001516001600160a01b0316815260200183606001516001600160a01b031681526020018360c0015181526020018360a001518152509050919050565b6127bd6149af565b805133906127cb82826149d9565b6127dd83600001518460200151614a5f565b6127f95760405162461bcd60e51b815260040161054690615725565b60408301516001600160a01b031633148061282d575082600001516001600160a01b031683604001516001600160a01b0316145b6128495760405162461bcd60e51b81526004016105469061555b565b60ca5460608401516040516302328d7360e31b81526001600160a01b03909216916311946b989161287c916004016152f7565b60206040518083038186803b15801561289457600080fd5b505afa1580156128a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128cc9190615114565b6128e85760405162461bcd60e51b815260040161054690615b63565b600083606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561292a57600080fd5b505afa15801561293e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129629190615166565b42106129805760405162461bcd60e51b8152600401610546906156ce565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a08701516080880151935163155bf27360e31b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d9463aadf9398946129f39490939092909190600401615cb1565b60006040518083038186803b158015612a0b57600080fd5b505af4158015612a1f573d6000803e3d6000fd5b505060cd54606087015160408089015160a08a0151915163dd2c99f760e01b81526001600160a01b03909416955063dd2c99f79450612a6393909190600401615350565b600060405180830381600087803b158015612a7d57600080fd5b505af1158015612a91573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167f2607e210004cef0ad6b3e6aedb778bffb03c1586f8dcf55d49afffde210d8bb187602001518860a00151604051612af8929190615cde565b60405180910390a450505050565b612b0e614c7a565b60048251600a811115612b1d57fe5b1480612b35575060068251600a811115612b3357fe5b145b612b515760405162461bcd60e51b8152600401610546906158d8565b60208201516001600160a01b0316612b7b5760405162461bcd60e51b815260040161054690615469565b60408201516001600160a01b031661274e5760405162461bcd60e51b815260040161054690615960565b612bad6149af565b80513390612bbb82826149d9565b612bcd83600001518460200151614a5f565b612be95760405162461bcd60e51b815260040161054690615725565b600083606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c2b57600080fd5b505afa158015612c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c639190615166565b4210612c815760405162461bcd60e51b815260040161054690615a7f565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a08701516080880151935163951dd8d360e01b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d9463951dd8d394612cf49490939092909190600401615cb1565b60006040518083038186803b158015612d0c57600080fd5b505af4158015612d20573d6000803e3d6000fd5b505060cd54606087015160408089015160a08a0151915163fa93b2a560e01b81526001600160a01b03909416955063fa93b2a59450612d6493909190600401615350565b600060405180830381600087803b158015612d7e57600080fd5b505af1158015612d92573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167fbd023c53d293da163d185720d4274f4ddabc09d5304491a55abb296cc811d9fa87602001518860a00151604051612af8929190615cde565b612e016149af565b80513390612e0f82826149d9565b612e2183600001518460200151614a5f565b612e3d5760405162461bcd60e51b815260040161054690615725565b60408301516001600160a01b0316331480612e71575082600001516001600160a01b031683604001516001600160a01b0316145b612e8d5760405162461bcd60e51b81526004016105469061542f565b60ca54606084015160405163f9839d8960e01b81526001600160a01b039092169163f9839d8991612ec0916004016152f7565b60206040518083038186803b158015612ed857600080fd5b505afa158015612eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f109190615114565b612f2c5760405162461bcd60e51b815260040161054690615708565b6000612f4084600001518560200151610a30565b509150508060011415612fdf5760a084015160608501516001600160a01b0316600090815260d66020526040902054612f7e9163ffffffff614a3a16565b6060850180516001600160a01b03908116600090815260d6602081815260408084209690965584518416835260d58152858320549451909316825290915291909120541115612fdf5760405162461bcd60e51b815260040161054690615886565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a0870151608088015193516301f974ab60e61b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d94637e5d2ac0946130529490939092909190600401615cb1565b60006040518083038186803b15801561306a57600080fd5b505af415801561307e573d6000803e3d6000fd5b505060cd54606087015160408089015160a08a0151915163dd2c99f760e01b81526001600160a01b03909416955063dd2c99f794506130c293909190600401615350565b600060405180830381600087803b1580156130dc57600080fd5b505af11580156130f0573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167fbfab88b861f171b7db714f00e5966131253918d55ddba816c3eb94657d10239087602001518860a00151604051612af8929190615cde565b61315f6149af565b8051339061316d82826149d9565b61317f83600001518460200151614a5f565b61319b5760405162461bcd60e51b815260040161054690615725565b6131a3614bb9565b60006131b785600001518660200151610a30565b50915091506131c98260000151614a8c565b1561327c57600082600001516000815181106131e157fe5b60200260200101519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561322457600080fd5b505afa158015613238573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061325c9190615166565b421061327a5760405162461bcd60e51b815260040161054690615943565b505b80600114156132d45760a085015160608601516001600160a01b0316600090815260d660205260409020546132b69163ffffffff614aca16565b60608601516001600160a01b0316600090815260d660205260409020555b84516001600160a01b0316600090815260d16020908152604080832082890151845290915290819020606087015160a088015160808901519351630380bfdd60e61b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d9463e02ff740946133479490939092909190600401615cb1565b60006040518083038186803b15801561335f57600080fd5b505af4158015613373573d6000803e3d6000fd5b505060cd5460608801516040808a015160a08b0151915163fa93b2a560e01b81526001600160a01b03909416955063fa93b2a594506133b793909190600401615350565b600060405180830381600087803b1580156133d157600080fd5b505af11580156133e5573d6000803e3d6000fd5b5050505084604001516001600160a01b031685600001516001600160a01b031686606001516001600160a01b03167ffe86f7694b6c54a528acbe27be61dd4a85e9a89aeef7f650a1b439045ccee5a488602001518960a0015160405161344c929190615cde565b60405180910390a45050505050565b613463614c7a565b60018251600a81111561347257fe5b1461348f5760405162461bcd60e51b815260040161054690615b0e565b60208201516001600160a01b031661274e5760405162461bcd60e51b815260040161054690615b47565b6134c16149af565b805133906134cf82826149d9565b6134e183600001518460200151614a5f565b6134fd5760405162461bcd60e51b815260040161054690615725565b60ca5460608401516040516302328d7360e31b81526001600160a01b03909216916311946b9891613530916004016152f7565b60206040518083038186803b15801561354857600080fd5b505afa15801561355c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135809190615114565b61359c5760405162461bcd60e51b81526004016105469061563f565b600083606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135de57600080fd5b505afa1580156135f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136169190615166565b42106136345760405162461bcd60e51b815260040161054690615828565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a08701516080880151935163ef682c1b60e01b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d9463ef682c1b946136a79490939092909190600401615cb1565b60006040518083038186803b1580156136bf57600080fd5b505af41580156136d3573d6000803e3d6000fd5b50505060408086015160a0870151915163051b0a4160e41b81526001600160a01b03851693506351b0a4109261370c9291600401615337565b600060405180830381600087803b15801561372657600080fd5b505af115801561373a573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167f4d7f96086c92b2f9a254ad21548b1c1f2d99502c7949508866349b96bb1a8d8a87602001518860a00151604051612af8929190615cde565b6137a9614c7a565b60028251600a8111156137b857fe5b146137d55760405162461bcd60e51b815260040161054690615a46565b60208201516001600160a01b031661274e5760405162461bcd60e51b815260040161054690615696565b6138076149af565b8051339061381582826149d9565b61382783600001518460200151614a5f565b6138435760405162461bcd60e51b815260040161054690615725565b60408301516001600160a01b0316331480613877575082600001516001600160a01b031683604001516001600160a01b0316145b6138935760405162461bcd60e51b81526004016105469061565c565b600083606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b1580156138d557600080fd5b505afa1580156138e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061390d9190615166565b421061392b5760405162461bcd60e51b8152600401610546906154a3565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a087015160808801519351637b5c283560e01b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d94637b5c28359461399e9490939092909190600401615cb1565b60006040518083038186803b1580156139b657600080fd5b505af41580156139ca573d6000803e3d6000fd5b50505060408086015160a087015191516356d878f760e01b81526001600160a01b03851693506356d878f792613a039291600401615337565b600060405180830381600087803b158015613a1d57600080fd5b505af1158015613a31573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167fdd96b18f26fd9950581b9fd821fa907fc318845fc4d220b825a7b19bfdd174e887602001518860a00151604051612af8929190615cde565b613aa0614ccb565b60088251600a811115613aaf57fe5b14613acc5760405162461bcd60e51b815260040161054690615b2a565b60408201516001600160a01b0316613af65760405162461bcd60e51b815260040161054690615742565b506040805160608082018352838301516001600160a01b0390811683529084015116602082015260a0909201519082015290565b602081015160ca546040516302328d7360e31b81526001600160a01b03909116906311946b9890613b5f9084906004016152f7565b60206040518083038186803b158015613b7757600080fd5b505afa158015613b8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613baf9190615114565b613bcb5760405162461bcd60e51b815260040161054690615b80565b600080600080613bda8561204d565b935093509350935080421015613c025760405162461bcd60e51b815260040161054690615a29565b613c0e8383868461170c565b613c2a5760405162461bcd60e51b81526004016105469061597d565b6000613c3e87602001518860400151610797565b9050856001600160a01b03166356d878f73389604001516040518363ffffffff1660e01b8152600401613c72929190615337565b600060405180830381600087803b158015613c8c57600080fd5b505af1158015613ca0573d6000803e3d6000fd5b505060cd54895160405163fa93b2a560e01b81526001600160a01b03909216935063fa93b2a59250613cd9918991908690600401615350565b600060405180830381600087803b158015613cf357600080fd5b505af1158015613d07573d6000803e3d6000fd5b5050505086600001516001600160a01b0316336001600160a01b031688602001516001600160a01b03167f18fd144d7dbcbaa6f00fd47a84adc7dc3cc64a326ffa2dc7691a25e3837dba03888b6040015186604051613d689392919061539f565b60405180910390a450505050505050565b613d81614ccb565b60078251600a811115613d9057fe5b14613dad5760405162461bcd60e51b8152600401610546906159d4565b60208201516001600160a01b0316613dd75760405162461bcd60e51b8152600401610546906154dc565b60408201516001600160a01b0316613e015760405162461bcd60e51b815260040161054690615a9c565b604051806060016040528083602001516001600160a01b031681526020018360800151815260200183604001516001600160a01b03168152509050919050565b80513390613e4f82826149d9565b613e6183600001518460200151614a5f565b613e7d5760405162461bcd60e51b815260040161054690615725565b613e85614bb9565b6000613e9985600001518660200151610a30565b5091509150600080613eae8460000151614a8c565b90506000613ebf8560200151614a8c565b90508180613eca5750805b613ee65760405162461bcd60e51b81526004016105469061599a565b81613f09578460200151600081518110613efc57fe5b6020026020010151613f1f565b84518051600090613f1657fe5b60200260200101515b92508015613fd35760008560200151600081518110613f3a57fe5b60200260200101519050806001600160a01b03166356d878f760cd60009054906101000a90046001600160a01b03168860800151600081518110613f7a57fe5b60200260200101516040518363ffffffff1660e01b8152600401613f9f929190615337565b600060405180830381600087803b158015613fb957600080fd5b505af1158015613fcd573d6000803e3d6000fd5b50505050505b5050600080600080613fe48561204d565b93509350935093508042101561400c5760405162461bcd60e51b8152600401610546906156eb565b6140188383868461170c565b6140345760405162461bcd60e51b81526004016105469061597d565b60cc5460405163cd43fbfb60e01b815260009182916001600160a01b039091169063cd43fbfb9061406b908c908c90600401615c3b565b604080518083038186803b15801561408257600080fd5b505afa158015614096573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ba919061517e565b91509150806140db5760405162461bcd60e51b815260040161054690615606565b60d160008d600001516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6020015181526020019081526020016000206000808201600061412a9190614ceb565b614138600183016000614ceb565b614146600283016000614ceb565b614154600383016000614ceb565b614162600483016000614ceb565b614170600583016000614ceb565b505087600114156141be576001600160a01b038616600090815260d660205260409020546141a4908363ffffffff614aca16565b6001600160a01b038716600090815260d660205260409020555b60cd546040808e0151905163fa93b2a560e01b81526001600160a01b039092169163fa93b2a5916141f6918a91908790600401615350565b600060405180830381600087803b15801561421057600080fd5b505af1158015614224573d6000803e3d6000fd5b5050505060008c60200151905060008d60400151905089896001600160a01b03168f600001516001600160a01b03167f522cda7dd0677ee4c9512efd8aa92af93de64b4c2fe2f8bfe7a9234a655a9bf58488876040516142869392919061539f565b60405180910390a45050505050505050505050505050565b6142a6614d09565b600a8251600a8111156142b557fe5b146142d25760405162461bcd60e51b81526004016105469061544c565b60208201516001600160a01b03166142fc5760405162461bcd60e51b8152600401610546906155cc565b60408201516001600160a01b03166143265760405162461bcd60e51b815260040161054690615486565b8160e001515160201461434b5760405162461bcd60e51b815260040161054690615a62565b60008260e001518060200190518101906143659190615166565b90506040518060a0016040528084602001516001600160a01b0316815260200184604001516001600160a01b03168152602001846080015181526020018460a00151815260200182815250915050919050565b6143c06149af565b6143d281600001518260400151614a5f565b6143ee5760405162461bcd60e51b815260040161054690615725565b6143f6614bb9565b60008060006144128560000151866040015187608001516122b2565b9350935093509350826144375760405162461bcd60e51b815260040161054690615ab9565b60006144586305f5e100610834858960600151611c2b90919063ffffffff16565b9050600061448b8760600151876060015160008151811061447557fe5b6020026020010151614aca90919063ffffffff16565b11156144c557816144a7828760a0015160008151811061447557fe5b10156144c55760405162461bcd60e51b815260040161054690615798565b845180516000906144d257fe5b60200260200101516001600160a01b03166356d878f73388606001516040518363ffffffff1660e01b815260040161450b929190615337565b600060405180830381600087803b15801561452557600080fd5b505af1158015614539573d6000803e3d6000fd5b505087516001600160a01b0316600090815260d160209081526040808320818c01518452909152808220908901518051734d3a52a0e98144caf46ac226d83e8f144b5c654d955063e02ff74094509192909161459157fe5b60200260200101518460006040518563ffffffff1660e01b81526004016145bb9493929190615cb1565b60006040518083038186803b1580156145d357600080fd5b505af41580156145e7573d6000803e3d6000fd5b505087516001600160a01b0316600090815260d160209081526040808320818c01518452909152812088518051734d3a52a0e98144caf46ac226d83e8f144b5c654d9550637b5c283594509192909161463c57fe5b6020026020010151896060015160006040518563ffffffff1660e01b815260040161466a9493929190615cb1565b60006040518083038186803b15801561468257600080fd5b505af4158015614696573d6000803e3d6000fd5b505050506146ea8160d6600088604001516000815181106146b357fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054614aca90919063ffffffff16565b60d6600087604001516000815181106146ff57fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555060cd60009054906101000a90046001600160a01b03166001600160a01b031663fa93b2a5866040015160008151811061476057fe5b60200260200101518860200151846040518463ffffffff1660e01b815260040161478c93929190615350565b600060405180830381600087803b1580156147a657600080fd5b505af11580156147ba573d6000803e3d6000fd5b5050505085600001516001600160a01b031686602001516001600160a01b0316336001600160a01b03167f93e59ec97820bb1ed9fb6ddc10619d1574e803b1f79b937414feb8f6b7051f9d868a60800151868c606001518d60400151604051614827959493929190615cec565b60405180910390a4505050505050565b61483f614d4a565b60098251600a81111561484e57fe5b1461486b5760405162461bcd60e51b8152600401610546906157ef565b60408201516001600160a01b03166148955760405162461bcd60e51b8152600401610546906159b7565b50604080518082018252908201516001600160a01b0316815260e090910151602082015290565b6148c46149af565b805160cf54600160b01b900460ff16156148fd576148e181614b0c565b6148fd5760405162461bcd60e51b815260040161054690615bf0565b815160208301516040516309c23da560e41b81526001600160a01b0390921691639c23da50916149329133919060040161530b565b600060405180830381600087803b15801561494c57600080fd5b505af1158015614960573d6000803e3d6000fd5b5050505081600001516001600160a01b0316336001600160a01b03167f8750bdaf6e88201790ee2765fea3ac73b514a52658c818723a30de91029ad000846020015160405161078b91906153e3565b60cf54600160a01b900460ff161561093d5760405162461bcd60e51b815260040161054690615ad6565b806001600160a01b0316826001600160a01b03161480614a1e57506001600160a01b03808216600090815260d2602090815260408083209386168352929052205460ff165b61193c5760405162461bcd60e51b8152600401610546906153f6565b6000828201838110156108405760405162461bcd60e51b815260040161054690615578565b600080821180156108405750506001600160a01b0391909116600090815260d06020526040902054101590565b6000808251118015610843575060006001600160a01b031682600081518110614ab157fe5b60200260200101516001600160a01b0316141592915050565b600061084083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b8d565b60ca546040516351572a2d60e11b81526000916001600160a01b03169063a2ae545a90614b3d9085906004016152f7565b60206040518083038186803b158015614b5557600080fd5b505afa158015614b69573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108439190615114565b60008184841115614bb15760405162461bcd60e51b815260040161054691906153e3565b505050900390565b6040518060c001604052806060815260200160608152602001606081526020016060815260200160608152602001606081525090565b604080516101008101909152806000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b6040518060c0016040528060006001600160a01b031681526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b50805460008255906000526020600020908101906119cd9190614d62565b6040518060a0016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b60408051808201909152600081526060602082015290565b610a1e91905b80821115614d7c5760008155600101614d68565b5090565b803561084381615d36565b600082601f830112614d9b578081fd5b813567ffffffffffffffff811115614db1578182fd5b614dc4601f8201601f1916602001615d0f565b9150808252836020828501011115614ddb57600080fd5b8060208401602084013760009082016020015292915050565b8035600b811061084357600080fd5b600060208284031215614e14578081fd5b813561084081615d36565b600060208284031215614e30578081fd5b815161084081615d36565b60008060408385031215614e4d578081fd5b8235614e5881615d36565b91506020830135614e6881615d36565b809150509250929050565b60008060008060808587031215614e88578182fd5b8435614e9381615d36565b93506020850135614ea381615d36565b92506040850135614eb381615d36565b9396929550929360600135925050565b60008060008060008060c08789031215614edb578182fd5b8651614ee681615d36565b6020880151909650614ef781615d36565b6040880151909550614f0881615d36565b80945050606087015192506080870151915060a0870151614f2881615d4b565b809150509295509295509295565b60008060408385031215614f48578182fd5b8235614f5381615d36565b91506020830135614e6881615d4b565b60008060408385031215614f75578182fd5b8235614f8081615d36565b946020939093013593505050565b600080600060608486031215614fa2578283fd5b8335614fad81615d36565b95602085013595506040909401359392505050565b60006020808385031215614fd4578182fd5b823567ffffffffffffffff80821115614feb578384fd5b81850186601f820112614ffc578485fd5b803592508183111561500c578485fd5b6150198485850201615d0f565b83815284810190828601875b868110156150e9578135850161010080601f19838f03011215615046578a8bfd5b61504f81615d0f565b61505b8e8c8501614df4565b815261506a8e60408501614d80565b8b820152606061507c8f828601614d80565b604083015261508e8f60808601614d80565b818301525060a0830135608082015260c083013560a082015260e083013560c082015281830135898111156150c1578c8dfd5b6150cf8f8d83870101614d8b565b60e083015250865250509287019290870190600101615025565b50909998505050505050505050565b600060208284031215615109578081fd5b813561084081615d4b565b600060208284031215615125578081fd5b815161084081615d4b565b600080600060608486031215615144578081fd5b835161514f81615d4b565b602085015160409095015190969495509392505050565b600060208284031215615177578081fd5b5051919050565b60008060408385031215615190578182fd5b825191506020830151614e6881615d4b565b6000815180845260208085019450808401835b838110156151da5781516001600160a01b0316875295820195908201906001016151b5565b509495945050505050565b6000815180845260208085019450808401835b838110156151da578151875295820195908201906001016151f8565b60008151808452815b818110156152395760208185018101518683018201520161521d565b8181111561524a5782602083870101525b50601f01601f19169290920160200192915050565b6000815160c0845261527460c08501826151a2565b60208401519150848103602086015261528d81836151a2565b6040850151925085810360408701526152a681846151a2565b9150506060840151915084810360608601526152c281836151e5565b6080850151925085810360808701526152db81846151e5565b91505060a0840151915084810360a08601526104ea81836151e5565b6001600160a01b0391909116815260200190565b6001600160a01b038316815260406020820181905260009061532f90830184615214565b949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160a01b039390931683526020830191909152604082015260600190565b901515815260200190565b92151583526020830191909152604082015260600190565b6000602082526108406020830184615214565b602080825260029082015261219b60f11b604082015260600190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526208262760eb1b604082015260600190565b60208082526003908201526241313160e81b604082015260600190565b60208082526003908201526204132360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b602080825260029082015261413360f01b604082015260600190565b60208082526003908201526220989b60e91b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526241313960e81b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526003908201526221999960e91b604082015260600190565b602080825260029082015261413160f01b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b602080825260029082015261413760f01b604082015260600190565b602080825260029082015261209960f11b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243333160e81b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b60208082526003908201526243333560e81b604082015260600190565b602080825260039082015262104c4d60ea1b604082015260600190565b60208082526003908201526221999b60e91b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b60208082526003908201526210cccd60ea1b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b60208082526003908201526220991960e91b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526003908201526243333760e81b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526003908201526204131360ec1b604082015260600190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526220989960e91b604082015260600190565b60208082526003908201526243323960e81b604082015260600190565b60208082526003908201526204333360ec1b604082015260600190565b60208082526003908201526241323360e81b604082015260600190565b60208082526003908201526241313560e81b604082015260600190565b602080825260029082015261082760f31b604082015260600190565b602080825260029082015261413960f01b604082015260600190565b60208082526003908201526208664760eb1b604082015260600190565b602080825260029082015261209b60f11b604082015260600190565b60208082526003908201526241323160e81b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526241313760e81b604082015260600190565b60208082526003908201526243333360e81b604082015260600190565b60208082526002908201526110cd60f21b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b602080825260029082015261104d60f21b604082015260600190565b60208082526003908201526241313360e81b604082015260600190565b602080825260029082015261413560f01b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b602080825260029082015261086760f31b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b602080825260029082015261433560f01b604082015260600190565b600060208252610840602083018461525f565b600060408252615c4e604083018561525f565b90508260208301529392505050565b600060608252615c70606083018661525f565b60208301949094525060400152919050565b600060808252615c95608083018761525f565b6020830195909552506040810192909252606090910152919050565b9384526001600160a01b039290921660208401526040830152606082015260800190565b90815260200190565b918252602082015260400190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff81118282101715615d2e57600080fd5b604052919050565b6001600160a01b03811681146119cd57600080fd5b80151581146119cd57600080fdfea2646970667358221220a7e19740a045ca277745868a9ac88b87f050c6954895e10f38c411c53312ad6f64736f6c634300060a0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102325760003560e01c8063b617f0c611610130578063ce3e39c0116100b8578063eaa33e141161007c578063eaa33e1414610479578063eab7775b1461049b578063ef4fcafa146104a3578063f2fde38b146104b6578063f77bc88b146104c957610232565b8063ce3e39c014610418578063d66dd43e14610420578063d99d13f514610433578063e69d849d14610453578063e723406c1461046657610232565b8063c220101d116100ff578063c220101d146103c4578063c644d3a2146103d7578063caa6d21a146103ea578063cab2e805146103fd578063cdee058a1461041057610232565b8063b617f0c614610378578063b6363cf21461038b578063bc463a3d1461039e578063beca75d7146103b157610232565b80636bd50cef116101be5780638da5cb5b116101825780638da5cb5b1461032b57806393e59dc1146103335780639daafbe81461033b5780639db938911461035d5780639f677ed91461036557610232565b80636bd50cef146102f35780636c0c3b991461030b57806370dc320c14610313578063715018a61461031b5780637dc0d1d01461032357610232565b8063485cc95511610205578063485cc95514610292578063558a7297146102a5578063565eea19146102b8578063573c473e146102d857806364681083146102eb57610232565b806314b93faf1461023757806316f0115b1461026057806329729d88146102755780632eb1c3a71461027d575b600080fd5b61024a610245366004614e73565b6104dc565b60405161025791906153c0565b60405180910390f35b6102686104f3565b60405161025791906152f7565b610268610502565b61029061028b366004614f63565b610511565b005b6102906102a0366004614e3b565b6105c6565b6102906102b3366004614f36565b6106de565b6102cb6102c6366004614f63565b610797565b6040516102579190615cd5565b6102906102e63660046150f8565b610849565b610290610900565b6102fb61093f565b6040516102579493929190615374565b61024a610964565b610268610974565b610290610983565b610268610a02565b610268610a11565b610268610a21565b61034e610349366004614f63565b610a30565b60405161025793929190615c5d565b610268610cc9565b6102906103733660046150f8565b610cd8565b610290610386366004614fc2565b610d84565b61024a610399366004614e3b565b610e16565b6102906103ac366004614e03565b610e44565b6102906103bf366004614e03565b610f29565b6102cb6103d2366004614f63565b61100e565b6102cb6103e5366004614e03565b6110cf565b6102cb6103f8366004614e03565b6110ea565b61029061040b3660046150f8565b611105565b61024a6111bc565b6102686111cc565b6102cb61042e366004614e03565b6111db565b610446610441366004614f63565b6111f6565b6040516102579190615c28565b610290610461366004614f63565b611457565b61024a610474366004614e03565b611500565b61048c610487366004614f8e565b61152f565b604051610257939291906153cb565b61024a611556565b6102906104b1366004614f63565b611566565b6102906104c4366004614e03565b6115d9565b61024a6104d7366004614e03565b611690565b60006104ea8585858561170c565b95945050505050565b60cd546001600160a01b031681565b60cf546001600160a01b031681565b6105196118a1565b6065546001600160a01b0390811691161461054f5760405162461bcd60e51b8152600401610546906158a3565b60405180910390fd5b6000811161056f5760405162461bcd60e51b81526004016105469061575f565b6001600160a01b038216600081815260d5602052604090819020839055517f6ff730ba70e34bd5ca823424bd15ab869cadc6bad079b527c71bde444ad6402b906105ba908490615cd5565b60405180910390a25050565b600054610100900460ff16806105df57506105df6118a5565b806105ed575060005460ff16155b6106095760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff16158015610634576000805460ff1961ff0019909116610100171660011790555b6001600160a01b03831661065a5760405162461bcd60e51b81526004016105469061580c565b6001600160a01b0382166106805760405162461bcd60e51b815260040161054690615bd4565b610689826118ab565b610691611940565b60c980546001600160a01b0319166001600160a01b0385161790556106b46119d0565b60cf805460ff60b01b1916600160b01b17905580156106d9576000805461ff00191690555b505050565b33600090815260d2602090815260408083206001600160a01b038616845290915290205460ff16151581151514156107285760405162461bcd60e51b815260040161054690615af2565b33600081815260d2602090815260408083206001600160a01b038716808552925291829020805460ff191685151517905590519091907f1ae45540b0875932452da603b351ce2f1758258ba1345e79f8fc94f044cb07879061078b9085906153c0565b60405180910390a35050565b60cc54604051630478409360e41b8152600091610840916305f5e100916108349186916001600160a01b0316906347840930906107d8908a906004016152f7565b60206040518083038186803b1580156107f057600080fd5b505afa158015610804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108289190615166565b9063ffffffff611c2b16565b9063ffffffff611c6516565b90505b92915050565b60ce546001600160a01b031633146108735760405162461bcd60e51b81526004016105469061553f565b60cf5460ff600160a01b90910416151581151514156108a45760405162461bcd60e51b815260040161054690615af2565b60cf805460ff60a01b1916600160a01b831515810291909117918290556040517f531c3d7229f510a8da00a0f5792686958cdd9c8a120c3c030a6053cd66b68556926108f59260ff910416906153c0565b60405180910390a150565b6109086118a1565b6065546001600160a01b039081169116146109355760405162461bcd60e51b8152600401610546906158a3565b61093d6119d0565b565b60ca5460cb5460cc5460cd546001600160a01b03938416949284169391821692911690565b60cf54600160b01b900460ff1681565b60c9546001600160a01b031681565b61098b6118a1565b6065546001600160a01b039081169116146109b85760405162461bcd60e51b8152600401610546906158a3565b6065546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606580546001600160a01b0319169055565b60cb546001600160a01b031681565b6065546001600160a01b03165b90565b60ca546001600160a01b031681565b610a38614bb9565b6001600160a01b038316600081815260d160209081526040808320868452825280832084845260d3835281842087855283528184205494845260d483528184208785528352818420548251825460e09581028201860190945260c081018481529596879693959094929391928692849290918491840182828015610ae557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ac7575b5050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015610b4757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b29575b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610ba957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b8b575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610c0157602002820191906000526020600020905b815481526020019060010190808311610bed575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020018280548015610c5957602002820191906000526020600020905b815481526020019060010190808311610c45575b5050505050815260200160058201805480602002602001604051908101604052809291908181526020018280548015610cb157602002820191906000526020600020905b815481526020019060010190808311610c9d575b50505050508152505092509250925092509250925092565b60ce546001600160a01b031681565b60cf546001600160a01b03163314610d025760405162461bcd60e51b81526004016105469061577c565b60cf5460ff600160a81b9091041615158115151415610d335760405162461bcd60e51b815260040161054690615af2565b60cf805460ff60a81b1916600160a81b831515810291909117918290556040517f4f1d0445688d95c99ca9fc036f551b205fd18ff26a4443b1979c16d1ba66b535926108f59260ff910416906153c0565b60975460ff16610da65760405162461bcd60e51b815260040161054690615b9d565b6097805460ff19169055610db8611ca7565b6000806000610dc684611cd1565b9250925092508215610e0357610ddc8282611f87565b6001600160a01b038216600090815260d46020908152604080832084845290915290204290555b50506097805460ff191660011790555050565b6001600160a01b03918216600090815260d26020908152604080832093909416825291909152205460ff1690565b610e4c6118a1565b6065546001600160a01b03908116911614610e795760405162461bcd60e51b8152600401610546906158a3565b6001600160a01b038116610e9f5760405162461bcd60e51b815260040161054690615679565b60ce546001600160a01b0382811691161415610ecd5760405162461bcd60e51b815260040161054690615af2565b60ce546040516001600160a01b038084169216907f1440312dbc326ddc21bfa95078324bf5aaf6899e8a27cba3057c60adfc84e40b90600090a360ce80546001600160a01b0319166001600160a01b0392909216919091179055565b610f316118a1565b6065546001600160a01b03908116911614610f5e5760405162461bcd60e51b8152600401610546906158a3565b6001600160a01b038116610f845760405162461bcd60e51b8152600401610546906155af565b60cf546001600160a01b0382811691161415610fb25760405162461bcd60e51b815260040161054690615af2565b60cf546040516001600160a01b038084169216907f44f3e9e7b454118e9fcb2e3026396f57ca21d7bd7dcabd31d7f986806422f4df90600090a360cf80546001600160a01b0319166001600160a01b0392909216919091179055565b6000611018614bb9565b60006110248585610a30565b5060cc5460405163cd43fbfb60e01b815292945090925060009182916001600160a01b03169063cd43fbfb906110609087908790600401615c3b565b604080518083038186803b15801561107757600080fd5b505afa15801561108b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110af919061517e565b91509150806110c5576000945050505050610843565b5095945050505050565b6001600160a01b0316600090815260d5602052604090205490565b6001600160a01b0316600090815260d0602052604090205490565b61110d6118a1565b6065546001600160a01b0390811691161461113a5760405162461bcd60e51b8152600401610546906158a3565b60cf5460ff600160b01b909104161515811515141561116b5760405162461bcd60e51b815260040161054690615af2565b60cf805460ff60b01b1916600160b01b831515810291909117918290556040517f26d614575a4c104c181c87003d4bb00cc7ade00d5b47bf8775171c12a376b255926108f59260ff910416906153c0565b60cf54600160a01b900460ff1681565b60cc546001600160a01b031681565b6001600160a01b0316600090815260d6602052604090205490565b6111fe614bb9565b6001600160a01b038316600090815260d1602090815260408083208584528252918290208251815460e09381028201840190945260c08101848152909391928492849184018282801561127a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161125c575b50505050508152602001600182018054806020026020016040519081016040528092919081815260200182805480156112dc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112be575b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561133e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611320575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561139657602002820191906000526020600020905b815481526020019060010190808311611382575b50505050508152602001600482018054806020026020016040519081016040528092919081815260200182805480156113ee57602002820191906000526020600020905b8154815260200190600101908083116113da575b505050505081526020016005820180548060200260200160405190810160405280929190818152602001828054801561144657602002820191906000526020600020905b815481526020019060010190808311611432575b505050505081525050905092915050565b60cd5460405163dd2c99f760e01b81526001600160a01b039091169063dd2c99f79061148b90859033908690600401615350565b600060405180830381600087803b1580156114a557600080fd5b505af11580156114b9573d6000803e3d6000fd5b50505050816001600160a01b0316336001600160a01b03167f4dfff917e1fbb261a082e98cc7d43029621f6a6eb05ff3fef1510d5f1eb4857c8360405161078b9190615cd5565b60008060008060006115118661204d565b93509350935093506115258484848461170c565b9695505050505050565b6000806000806000806115438989896122b2565b919c909b50909950975050505050505050565b60cf54600160a81b900460ff1681565b60975460ff166115885760405162461bcd60e51b815260040161054690615b9d565b6097805460ff1916905561159a611ca7565b6115a48282611f87565b6001600160a01b03909116600090815260d460209081526040808320938352929052204290556097805460ff19166001179055565b6115e16118a1565b6065546001600160a01b0390811691161461160e5760405162461bcd60e51b8152600401610546906158a3565b6001600160a01b0381166116345760405162461bcd60e51b8152600401610546906154f9565b6065546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116cb57600080fd5b505afa1580156116df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117039190615166565b42101592915050565b60cb54604051635fdc714960e01b81526000916001600160a01b031690635fdc71499061173f9088908690600401615337565b60206040518083038186803b15801561175757600080fd5b505afa15801561176b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178f9190615114565b8015611818575060cb54604051635fdc714960e01b81526001600160a01b0390911690635fdc7149906117c89087908690600401615337565b60206040518083038186803b1580156117e057600080fd5b505afa1580156117f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118189190615114565b80156104ea575060cb54604051635fdc714960e01b81526001600160a01b0390911690635fdc7149906118519086908690600401615337565b60206040518083038186803b15801561186957600080fd5b505afa15801561187d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ea9190615114565b3390565b303b1590565b600054610100900460ff16806118c457506118c46118a5565b806118d2575060005460ff16155b6118ee5760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff16158015611919576000805460ff1961ff0019909116610100171660011790555b61192161238d565b61192a8261240f565b801561193c576000805461ff00191690555b5050565b600054610100900460ff168061195957506119596118a5565b80611967575060005460ff16155b6119835760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff161580156119ae576000805460ff1961ff0019909116610100171660011790555b6097805460ff1916600117905580156119cd576000805461ff00191690555b50565b60c960009054906101000a90046001600160a01b03166001600160a01b031663d01f63f56040518163ffffffff1660e01b815260040160206040518083038186803b158015611a1e57600080fd5b505afa158015611a32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a569190614e1f565b60ca80546001600160a01b0319166001600160a01b0392831617905560c9546040805163419d8fe760e11b81529051919092169163833b1fce916004808301926020929190829003018186803b158015611aaf57600080fd5b505afa158015611ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae79190614e1f565b60cb80546001600160a01b0319166001600160a01b0392831617905560c9546040805163cf28493f60e01b81529051919092169163cf28493f916004808301926020929190829003018186803b158015611b4057600080fd5b505afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b789190614e1f565b60cc80546001600160a01b0319166001600160a01b0392831617905560c95460408051633aa431a160e11b8152905191909216916375486342916004808301926020929190829003018186803b158015611bd157600080fd5b505afa158015611be5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c099190614e1f565b60cd80546001600160a01b0319166001600160a01b0392909216919091179055565b600082611c3a57506000610843565b82820282848281611c4757fe5b04146108405760405162461bcd60e51b815260040161054690615845565b600061084083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506124db565b60cf54600160a81b900460ff161561093d5760405162461bcd60e51b815260040161054690615c0c565b60008080808080805b8751811015611f7b57611ceb614bef565b888281518110611cf757fe5b60209081029190910101518051909150600781600a811115611d1557fe5b14158015611d2f5750600881600a811115611d2c57fe5b14155b8015611d475750600a81600a811115611d4457fe5b14155b8015611d5f5750600981600a811115611d5c57fe5b14155b15611dd5578315611dc25781602001516001600160a01b0316866001600160a01b031614611d9f5760405162461bcd60e51b8152600401610546906157d2565b81608001518514611dc25760405162461bcd60e51b8152600401610546906155e9565b6001935081608001519450816020015195505b600081600a811115611de357fe5b1415611dff57611dfa611df583612512565b6125ea565b611f71565b600381600a811115611e0d57fe5b1415611e2457611dfa611e1f836126d9565b6127b5565b600481600a811115611e3257fe5b1415611e4957611dfa611e4483612b06565b612ba5565b600581600a811115611e5757fe5b1415611e6e57611dfa611e69836126d9565b612df9565b600681600a811115611e7c57fe5b1415611e9357611dfa611e8e83612b06565b613157565b600181600a811115611ea157fe5b1415611eb857611dfa611eb38361345b565b6134b9565b600281600a811115611ec657fe5b1415611edd57611dfa611ed8836137a1565b6137ff565b600881600a811115611eeb57fe5b1415611f0257611dfa611efd83613a98565b613b2a565b600781600a811115611f1057fe5b1415611f2757611dfa611f2283613d79565b613e41565b600a81600a811115611f3557fe5b1415611f4c57611dfa611f478361429e565b6143b8565b600981600a811115611f5a57fe5b1415611f7157611f71611f6c83614837565b6148bc565b5050600101611cda565b50969195509350915050565b611f8f614bb9565b6000611f9b8484610a30565b5060cc5460405163cd43fbfb60e01b81529294509092506000916001600160a01b039091169063cd43fbfb90611fd79086908690600401615c3b565b604080518083038186803b158015611fee57600080fd5b505afa158015612002573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612026919061517e565b915050806120465760405162461bcd60e51b815260040161054690615412565b5050505050565b6000806000806000859050806001600160a01b031663af0968fc6040518163ffffffff1660e01b815260040160c06040518083038186803b15801561209157600080fd5b505afa9250505080156120c1575060408051601f3d908101601f191682019092526120be91810190614ec3565b60015b61229757806001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156120fe57600080fd5b505afa158015612112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121369190614e1f565b816001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561216f57600080fd5b505afa158015612183573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a79190614e1f565b826001600160a01b03166317d69bc86040518163ffffffff1660e01b815260040160206040518083038186803b1580156121e057600080fd5b505afa1580156121f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122189190614e1f565b836001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561225157600080fd5b505afa158015612265573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122899190615166565b9450945094509450506122ab565b5093985091965094509092506122ab915050565b9193509193565b6122ba614bb9565b60008060006122c7614bb9565b6000806122d48a8a610a30565b925092509250600080600060cc60009054906101000a90046001600160a01b03166001600160a01b031663a6c569078787878f6040518563ffffffff1660e01b81526004016123269493929190615c82565b60606040518083038186803b15801561233e57600080fd5b505afa158015612352573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123769190615130565b979f919e509c50959a509498505050505050505050565b600054610100900460ff16806123a657506123a66118a5565b806123b4575060005460ff16155b6123d05760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff161580156123fb576000805460ff1961ff0019909116610100171660011790555b80156119cd576000805461ff001916905550565b600054610100900460ff168061242857506124286118a5565b80612436575060005460ff16155b6124525760405162461bcd60e51b8152600401610546906158f5565b600054610100900460ff1615801561247d576000805460ff1961ff0019909116610100171660011790555b606580546001600160a01b0319166001600160a01b0384169081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3801561193c576000805461ff00191690555050565b600081836124fc5760405162461bcd60e51b815260040161054691906153e3565b50600083858161250857fe5b0495945050505050565b61251a614c50565b60008251600a81111561252957fe5b146125465760405162461bcd60e51b815260040161054690615623565b60208201516001600160a01b03166125705760405162461bcd60e51b8152600401610546906156b2565b60008260e00151516020141561259b578260e001518060200190518101906125989190615166565b90505b600281106125bb5760405162461bcd60e51b8152600401610546906154c0565b604080516060810182526020808601516001600160a01b03168252608090950151948101949094528301525090565b6125f26149af565b8051339061260082826149d9565b82516001600160a01b0316600090815260d0602052604081205461262b90600163ffffffff614a3a16565b9050808460200151146126505760405162461bcd60e51b8152600401610546906157b5565b83516001600160a01b03908116600090815260d060209081526040808320859055808801805189518616855260d384528285208786529093529281902091909155905186519151909291909116907f5d66689e2c864b4f21efd3988c0ce5dc8a197981b68e81ce73660e92394fe25f906126cb908590615cd5565b60405180910390a350505050565b6126e1614c7a565b60038251600a8111156126f057fe5b1480612708575060058251600a81111561270657fe5b145b6127245760405162461bcd60e51b8152600401610546906159f1565b60208201516001600160a01b031661274e5760405162461bcd60e51b815260040161054690615a0d565b6040518060c0016040528083602001516001600160a01b031681526020018360800151815260200183604001516001600160a01b0316815260200183606001516001600160a01b031681526020018360c0015181526020018360a001518152509050919050565b6127bd6149af565b805133906127cb82826149d9565b6127dd83600001518460200151614a5f565b6127f95760405162461bcd60e51b815260040161054690615725565b60408301516001600160a01b031633148061282d575082600001516001600160a01b031683604001516001600160a01b0316145b6128495760405162461bcd60e51b81526004016105469061555b565b60ca5460608401516040516302328d7360e31b81526001600160a01b03909216916311946b989161287c916004016152f7565b60206040518083038186803b15801561289457600080fd5b505afa1580156128a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128cc9190615114565b6128e85760405162461bcd60e51b815260040161054690615b63565b600083606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561292a57600080fd5b505afa15801561293e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129629190615166565b42106129805760405162461bcd60e51b8152600401610546906156ce565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a08701516080880151935163155bf27360e31b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d9463aadf9398946129f39490939092909190600401615cb1565b60006040518083038186803b158015612a0b57600080fd5b505af4158015612a1f573d6000803e3d6000fd5b505060cd54606087015160408089015160a08a0151915163dd2c99f760e01b81526001600160a01b03909416955063dd2c99f79450612a6393909190600401615350565b600060405180830381600087803b158015612a7d57600080fd5b505af1158015612a91573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167f2607e210004cef0ad6b3e6aedb778bffb03c1586f8dcf55d49afffde210d8bb187602001518860a00151604051612af8929190615cde565b60405180910390a450505050565b612b0e614c7a565b60048251600a811115612b1d57fe5b1480612b35575060068251600a811115612b3357fe5b145b612b515760405162461bcd60e51b8152600401610546906158d8565b60208201516001600160a01b0316612b7b5760405162461bcd60e51b815260040161054690615469565b60408201516001600160a01b031661274e5760405162461bcd60e51b815260040161054690615960565b612bad6149af565b80513390612bbb82826149d9565b612bcd83600001518460200151614a5f565b612be95760405162461bcd60e51b815260040161054690615725565b600083606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c2b57600080fd5b505afa158015612c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c639190615166565b4210612c815760405162461bcd60e51b815260040161054690615a7f565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a08701516080880151935163951dd8d360e01b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d9463951dd8d394612cf49490939092909190600401615cb1565b60006040518083038186803b158015612d0c57600080fd5b505af4158015612d20573d6000803e3d6000fd5b505060cd54606087015160408089015160a08a0151915163fa93b2a560e01b81526001600160a01b03909416955063fa93b2a59450612d6493909190600401615350565b600060405180830381600087803b158015612d7e57600080fd5b505af1158015612d92573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167fbd023c53d293da163d185720d4274f4ddabc09d5304491a55abb296cc811d9fa87602001518860a00151604051612af8929190615cde565b612e016149af565b80513390612e0f82826149d9565b612e2183600001518460200151614a5f565b612e3d5760405162461bcd60e51b815260040161054690615725565b60408301516001600160a01b0316331480612e71575082600001516001600160a01b031683604001516001600160a01b0316145b612e8d5760405162461bcd60e51b81526004016105469061542f565b60ca54606084015160405163f9839d8960e01b81526001600160a01b039092169163f9839d8991612ec0916004016152f7565b60206040518083038186803b158015612ed857600080fd5b505afa158015612eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f109190615114565b612f2c5760405162461bcd60e51b815260040161054690615708565b6000612f4084600001518560200151610a30565b509150508060011415612fdf5760a084015160608501516001600160a01b0316600090815260d66020526040902054612f7e9163ffffffff614a3a16565b6060850180516001600160a01b03908116600090815260d6602081815260408084209690965584518416835260d58152858320549451909316825290915291909120541115612fdf5760405162461bcd60e51b815260040161054690615886565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a0870151608088015193516301f974ab60e61b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d94637e5d2ac0946130529490939092909190600401615cb1565b60006040518083038186803b15801561306a57600080fd5b505af415801561307e573d6000803e3d6000fd5b505060cd54606087015160408089015160a08a0151915163dd2c99f760e01b81526001600160a01b03909416955063dd2c99f794506130c293909190600401615350565b600060405180830381600087803b1580156130dc57600080fd5b505af11580156130f0573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167fbfab88b861f171b7db714f00e5966131253918d55ddba816c3eb94657d10239087602001518860a00151604051612af8929190615cde565b61315f6149af565b8051339061316d82826149d9565b61317f83600001518460200151614a5f565b61319b5760405162461bcd60e51b815260040161054690615725565b6131a3614bb9565b60006131b785600001518660200151610a30565b50915091506131c98260000151614a8c565b1561327c57600082600001516000815181106131e157fe5b60200260200101519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561322457600080fd5b505afa158015613238573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061325c9190615166565b421061327a5760405162461bcd60e51b815260040161054690615943565b505b80600114156132d45760a085015160608601516001600160a01b0316600090815260d660205260409020546132b69163ffffffff614aca16565b60608601516001600160a01b0316600090815260d660205260409020555b84516001600160a01b0316600090815260d16020908152604080832082890151845290915290819020606087015160a088015160808901519351630380bfdd60e61b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d9463e02ff740946133479490939092909190600401615cb1565b60006040518083038186803b15801561335f57600080fd5b505af4158015613373573d6000803e3d6000fd5b505060cd5460608801516040808a015160a08b0151915163fa93b2a560e01b81526001600160a01b03909416955063fa93b2a594506133b793909190600401615350565b600060405180830381600087803b1580156133d157600080fd5b505af11580156133e5573d6000803e3d6000fd5b5050505084604001516001600160a01b031685600001516001600160a01b031686606001516001600160a01b03167ffe86f7694b6c54a528acbe27be61dd4a85e9a89aeef7f650a1b439045ccee5a488602001518960a0015160405161344c929190615cde565b60405180910390a45050505050565b613463614c7a565b60018251600a81111561347257fe5b1461348f5760405162461bcd60e51b815260040161054690615b0e565b60208201516001600160a01b031661274e5760405162461bcd60e51b815260040161054690615b47565b6134c16149af565b805133906134cf82826149d9565b6134e183600001518460200151614a5f565b6134fd5760405162461bcd60e51b815260040161054690615725565b60ca5460608401516040516302328d7360e31b81526001600160a01b03909216916311946b9891613530916004016152f7565b60206040518083038186803b15801561354857600080fd5b505afa15801561355c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135809190615114565b61359c5760405162461bcd60e51b81526004016105469061563f565b600083606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135de57600080fd5b505afa1580156135f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136169190615166565b42106136345760405162461bcd60e51b815260040161054690615828565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a08701516080880151935163ef682c1b60e01b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d9463ef682c1b946136a79490939092909190600401615cb1565b60006040518083038186803b1580156136bf57600080fd5b505af41580156136d3573d6000803e3d6000fd5b50505060408086015160a0870151915163051b0a4160e41b81526001600160a01b03851693506351b0a4109261370c9291600401615337565b600060405180830381600087803b15801561372657600080fd5b505af115801561373a573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167f4d7f96086c92b2f9a254ad21548b1c1f2d99502c7949508866349b96bb1a8d8a87602001518860a00151604051612af8929190615cde565b6137a9614c7a565b60028251600a8111156137b857fe5b146137d55760405162461bcd60e51b815260040161054690615a46565b60208201516001600160a01b031661274e5760405162461bcd60e51b815260040161054690615696565b6138076149af565b8051339061381582826149d9565b61382783600001518460200151614a5f565b6138435760405162461bcd60e51b815260040161054690615725565b60408301516001600160a01b0316331480613877575082600001516001600160a01b031683604001516001600160a01b0316145b6138935760405162461bcd60e51b81526004016105469061565c565b600083606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b1580156138d557600080fd5b505afa1580156138e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061390d9190615166565b421061392b5760405162461bcd60e51b8152600401610546906154a3565b83516001600160a01b0316600090815260d16020908152604080832082880151845290915290819020606086015160a087015160808801519351637b5c283560e01b8152734d3a52a0e98144caf46ac226d83e8f144b5c654d94637b5c28359461399e9490939092909190600401615cb1565b60006040518083038186803b1580156139b657600080fd5b505af41580156139ca573d6000803e3d6000fd5b50505060408086015160a087015191516356d878f760e01b81526001600160a01b03851693506356d878f792613a039291600401615337565b600060405180830381600087803b158015613a1d57600080fd5b505af1158015613a31573d6000803e3d6000fd5b5050505083604001516001600160a01b031684600001516001600160a01b031685606001516001600160a01b03167fdd96b18f26fd9950581b9fd821fa907fc318845fc4d220b825a7b19bfdd174e887602001518860a00151604051612af8929190615cde565b613aa0614ccb565b60088251600a811115613aaf57fe5b14613acc5760405162461bcd60e51b815260040161054690615b2a565b60408201516001600160a01b0316613af65760405162461bcd60e51b815260040161054690615742565b506040805160608082018352838301516001600160a01b0390811683529084015116602082015260a0909201519082015290565b602081015160ca546040516302328d7360e31b81526001600160a01b03909116906311946b9890613b5f9084906004016152f7565b60206040518083038186803b158015613b7757600080fd5b505afa158015613b8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613baf9190615114565b613bcb5760405162461bcd60e51b815260040161054690615b80565b600080600080613bda8561204d565b935093509350935080421015613c025760405162461bcd60e51b815260040161054690615a29565b613c0e8383868461170c565b613c2a5760405162461bcd60e51b81526004016105469061597d565b6000613c3e87602001518860400151610797565b9050856001600160a01b03166356d878f73389604001516040518363ffffffff1660e01b8152600401613c72929190615337565b600060405180830381600087803b158015613c8c57600080fd5b505af1158015613ca0573d6000803e3d6000fd5b505060cd54895160405163fa93b2a560e01b81526001600160a01b03909216935063fa93b2a59250613cd9918991908690600401615350565b600060405180830381600087803b158015613cf357600080fd5b505af1158015613d07573d6000803e3d6000fd5b5050505086600001516001600160a01b0316336001600160a01b031688602001516001600160a01b03167f18fd144d7dbcbaa6f00fd47a84adc7dc3cc64a326ffa2dc7691a25e3837dba03888b6040015186604051613d689392919061539f565b60405180910390a450505050505050565b613d81614ccb565b60078251600a811115613d9057fe5b14613dad5760405162461bcd60e51b8152600401610546906159d4565b60208201516001600160a01b0316613dd75760405162461bcd60e51b8152600401610546906154dc565b60408201516001600160a01b0316613e015760405162461bcd60e51b815260040161054690615a9c565b604051806060016040528083602001516001600160a01b031681526020018360800151815260200183604001516001600160a01b03168152509050919050565b80513390613e4f82826149d9565b613e6183600001518460200151614a5f565b613e7d5760405162461bcd60e51b815260040161054690615725565b613e85614bb9565b6000613e9985600001518660200151610a30565b5091509150600080613eae8460000151614a8c565b90506000613ebf8560200151614a8c565b90508180613eca5750805b613ee65760405162461bcd60e51b81526004016105469061599a565b81613f09578460200151600081518110613efc57fe5b6020026020010151613f1f565b84518051600090613f1657fe5b60200260200101515b92508015613fd35760008560200151600081518110613f3a57fe5b60200260200101519050806001600160a01b03166356d878f760cd60009054906101000a90046001600160a01b03168860800151600081518110613f7a57fe5b60200260200101516040518363ffffffff1660e01b8152600401613f9f929190615337565b600060405180830381600087803b158015613fb957600080fd5b505af1158015613fcd573d6000803e3d6000fd5b50505050505b5050600080600080613fe48561204d565b93509350935093508042101561400c5760405162461bcd60e51b8152600401610546906156eb565b6140188383868461170c565b6140345760405162461bcd60e51b81526004016105469061597d565b60cc5460405163cd43fbfb60e01b815260009182916001600160a01b039091169063cd43fbfb9061406b908c908c90600401615c3b565b604080518083038186803b15801561408257600080fd5b505afa158015614096573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ba919061517e565b91509150806140db5760405162461bcd60e51b815260040161054690615606565b60d160008d600001516001600160a01b03166001600160a01b0316815260200190815260200160002060008d6020015181526020019081526020016000206000808201600061412a9190614ceb565b614138600183016000614ceb565b614146600283016000614ceb565b614154600383016000614ceb565b614162600483016000614ceb565b614170600583016000614ceb565b505087600114156141be576001600160a01b038616600090815260d660205260409020546141a4908363ffffffff614aca16565b6001600160a01b038716600090815260d660205260409020555b60cd546040808e0151905163fa93b2a560e01b81526001600160a01b039092169163fa93b2a5916141f6918a91908790600401615350565b600060405180830381600087803b15801561421057600080fd5b505af1158015614224573d6000803e3d6000fd5b5050505060008c60200151905060008d60400151905089896001600160a01b03168f600001516001600160a01b03167f522cda7dd0677ee4c9512efd8aa92af93de64b4c2fe2f8bfe7a9234a655a9bf58488876040516142869392919061539f565b60405180910390a45050505050505050505050505050565b6142a6614d09565b600a8251600a8111156142b557fe5b146142d25760405162461bcd60e51b81526004016105469061544c565b60208201516001600160a01b03166142fc5760405162461bcd60e51b8152600401610546906155cc565b60408201516001600160a01b03166143265760405162461bcd60e51b815260040161054690615486565b8160e001515160201461434b5760405162461bcd60e51b815260040161054690615a62565b60008260e001518060200190518101906143659190615166565b90506040518060a0016040528084602001516001600160a01b0316815260200184604001516001600160a01b03168152602001846080015181526020018460a00151815260200182815250915050919050565b6143c06149af565b6143d281600001518260400151614a5f565b6143ee5760405162461bcd60e51b815260040161054690615725565b6143f6614bb9565b60008060006144128560000151866040015187608001516122b2565b9350935093509350826144375760405162461bcd60e51b815260040161054690615ab9565b60006144586305f5e100610834858960600151611c2b90919063ffffffff16565b9050600061448b8760600151876060015160008151811061447557fe5b6020026020010151614aca90919063ffffffff16565b11156144c557816144a7828760a0015160008151811061447557fe5b10156144c55760405162461bcd60e51b815260040161054690615798565b845180516000906144d257fe5b60200260200101516001600160a01b03166356d878f73388606001516040518363ffffffff1660e01b815260040161450b929190615337565b600060405180830381600087803b15801561452557600080fd5b505af1158015614539573d6000803e3d6000fd5b505087516001600160a01b0316600090815260d160209081526040808320818c01518452909152808220908901518051734d3a52a0e98144caf46ac226d83e8f144b5c654d955063e02ff74094509192909161459157fe5b60200260200101518460006040518563ffffffff1660e01b81526004016145bb9493929190615cb1565b60006040518083038186803b1580156145d357600080fd5b505af41580156145e7573d6000803e3d6000fd5b505087516001600160a01b0316600090815260d160209081526040808320818c01518452909152812088518051734d3a52a0e98144caf46ac226d83e8f144b5c654d9550637b5c283594509192909161463c57fe5b6020026020010151896060015160006040518563ffffffff1660e01b815260040161466a9493929190615cb1565b60006040518083038186803b15801561468257600080fd5b505af4158015614696573d6000803e3d6000fd5b505050506146ea8160d6600088604001516000815181106146b357fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054614aca90919063ffffffff16565b60d6600087604001516000815181106146ff57fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555060cd60009054906101000a90046001600160a01b03166001600160a01b031663fa93b2a5866040015160008151811061476057fe5b60200260200101518860200151846040518463ffffffff1660e01b815260040161478c93929190615350565b600060405180830381600087803b1580156147a657600080fd5b505af11580156147ba573d6000803e3d6000fd5b5050505085600001516001600160a01b031686602001516001600160a01b0316336001600160a01b03167f93e59ec97820bb1ed9fb6ddc10619d1574e803b1f79b937414feb8f6b7051f9d868a60800151868c606001518d60400151604051614827959493929190615cec565b60405180910390a4505050505050565b61483f614d4a565b60098251600a81111561484e57fe5b1461486b5760405162461bcd60e51b8152600401610546906157ef565b60408201516001600160a01b03166148955760405162461bcd60e51b8152600401610546906159b7565b50604080518082018252908201516001600160a01b0316815260e090910151602082015290565b6148c46149af565b805160cf54600160b01b900460ff16156148fd576148e181614b0c565b6148fd5760405162461bcd60e51b815260040161054690615bf0565b815160208301516040516309c23da560e41b81526001600160a01b0390921691639c23da50916149329133919060040161530b565b600060405180830381600087803b15801561494c57600080fd5b505af1158015614960573d6000803e3d6000fd5b5050505081600001516001600160a01b0316336001600160a01b03167f8750bdaf6e88201790ee2765fea3ac73b514a52658c818723a30de91029ad000846020015160405161078b91906153e3565b60cf54600160a01b900460ff161561093d5760405162461bcd60e51b815260040161054690615ad6565b806001600160a01b0316826001600160a01b03161480614a1e57506001600160a01b03808216600090815260d2602090815260408083209386168352929052205460ff165b61193c5760405162461bcd60e51b8152600401610546906153f6565b6000828201838110156108405760405162461bcd60e51b815260040161054690615578565b600080821180156108405750506001600160a01b0391909116600090815260d06020526040902054101590565b6000808251118015610843575060006001600160a01b031682600081518110614ab157fe5b60200260200101516001600160a01b0316141592915050565b600061084083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b8d565b60ca546040516351572a2d60e11b81526000916001600160a01b03169063a2ae545a90614b3d9085906004016152f7565b60206040518083038186803b158015614b5557600080fd5b505afa158015614b69573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108439190615114565b60008184841115614bb15760405162461bcd60e51b815260040161054691906153e3565b505050900390565b6040518060c001604052806060815260200160608152602001606081526020016060815260200160608152602001606081525090565b604080516101008101909152806000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b6040518060c0016040528060006001600160a01b031681526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b50805460008255906000526020600020908101906119cd9190614d62565b6040518060a0016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b60408051808201909152600081526060602082015290565b610a1e91905b80821115614d7c5760008155600101614d68565b5090565b803561084381615d36565b600082601f830112614d9b578081fd5b813567ffffffffffffffff811115614db1578182fd5b614dc4601f8201601f1916602001615d0f565b9150808252836020828501011115614ddb57600080fd5b8060208401602084013760009082016020015292915050565b8035600b811061084357600080fd5b600060208284031215614e14578081fd5b813561084081615d36565b600060208284031215614e30578081fd5b815161084081615d36565b60008060408385031215614e4d578081fd5b8235614e5881615d36565b91506020830135614e6881615d36565b809150509250929050565b60008060008060808587031215614e88578182fd5b8435614e9381615d36565b93506020850135614ea381615d36565b92506040850135614eb381615d36565b9396929550929360600135925050565b60008060008060008060c08789031215614edb578182fd5b8651614ee681615d36565b6020880151909650614ef781615d36565b6040880151909550614f0881615d36565b80945050606087015192506080870151915060a0870151614f2881615d4b565b809150509295509295509295565b60008060408385031215614f48578182fd5b8235614f5381615d36565b91506020830135614e6881615d4b565b60008060408385031215614f75578182fd5b8235614f8081615d36565b946020939093013593505050565b600080600060608486031215614fa2578283fd5b8335614fad81615d36565b95602085013595506040909401359392505050565b60006020808385031215614fd4578182fd5b823567ffffffffffffffff80821115614feb578384fd5b81850186601f820112614ffc578485fd5b803592508183111561500c578485fd5b6150198485850201615d0f565b83815284810190828601875b868110156150e9578135850161010080601f19838f03011215615046578a8bfd5b61504f81615d0f565b61505b8e8c8501614df4565b815261506a8e60408501614d80565b8b820152606061507c8f828601614d80565b604083015261508e8f60808601614d80565b818301525060a0830135608082015260c083013560a082015260e083013560c082015281830135898111156150c1578c8dfd5b6150cf8f8d83870101614d8b565b60e083015250865250509287019290870190600101615025565b50909998505050505050505050565b600060208284031215615109578081fd5b813561084081615d4b565b600060208284031215615125578081fd5b815161084081615d4b565b600080600060608486031215615144578081fd5b835161514f81615d4b565b602085015160409095015190969495509392505050565b600060208284031215615177578081fd5b5051919050565b60008060408385031215615190578182fd5b825191506020830151614e6881615d4b565b6000815180845260208085019450808401835b838110156151da5781516001600160a01b0316875295820195908201906001016151b5565b509495945050505050565b6000815180845260208085019450808401835b838110156151da578151875295820195908201906001016151f8565b60008151808452815b818110156152395760208185018101518683018201520161521d565b8181111561524a5782602083870101525b50601f01601f19169290920160200192915050565b6000815160c0845261527460c08501826151a2565b60208401519150848103602086015261528d81836151a2565b6040850151925085810360408701526152a681846151a2565b9150506060840151915084810360608601526152c281836151e5565b6080850151925085810360808701526152db81846151e5565b91505060a0840151915084810360a08601526104ea81836151e5565b6001600160a01b0391909116815260200190565b6001600160a01b038316815260406020820181905260009061532f90830184615214565b949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160a01b039390931683526020830191909152604082015260600190565b901515815260200190565b92151583526020830191909152604082015260600190565b6000602082526108406020830184615214565b602080825260029082015261219b60f11b604082015260600190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526208262760eb1b604082015260600190565b60208082526003908201526241313160e81b604082015260600190565b60208082526003908201526204132360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b602080825260029082015261413360f01b604082015260600190565b60208082526003908201526220989b60e91b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526241313960e81b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526003908201526221999960e91b604082015260600190565b602080825260029082015261413160f01b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b602080825260029082015261413760f01b604082015260600190565b602080825260029082015261209960f11b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243333160e81b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b60208082526003908201526243333560e81b604082015260600190565b602080825260039082015262104c4d60ea1b604082015260600190565b60208082526003908201526221999b60e91b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b60208082526003908201526210cccd60ea1b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b60208082526003908201526220991960e91b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526003908201526243333760e81b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526003908201526204131360ec1b604082015260600190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526220989960e91b604082015260600190565b60208082526003908201526243323960e81b604082015260600190565b60208082526003908201526204333360ec1b604082015260600190565b60208082526003908201526241323360e81b604082015260600190565b60208082526003908201526241313560e81b604082015260600190565b602080825260029082015261082760f31b604082015260600190565b602080825260029082015261413960f01b604082015260600190565b60208082526003908201526208664760eb1b604082015260600190565b602080825260029082015261209b60f11b604082015260600190565b60208082526003908201526241323160e81b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526241313760e81b604082015260600190565b60208082526003908201526243333360e81b604082015260600190565b60208082526002908201526110cd60f21b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b602080825260029082015261104d60f21b604082015260600190565b60208082526003908201526241313360e81b604082015260600190565b602080825260029082015261413560f01b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b602080825260029082015261086760f31b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b602080825260029082015261433560f01b604082015260600190565b600060208252610840602083018461525f565b600060408252615c4e604083018561525f565b90508260208301529392505050565b600060608252615c70606083018661525f565b60208301949094525060400152919050565b600060808252615c95608083018761525f565b6020830195909552506040810192909252606090910152919050565b9384526001600160a01b039290921660208401526040830152606082015260800190565b90815260200190565b918252602082015260400190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff81118282101715615d2e57600080fd5b604052919050565b6001600160a01b03811681146119cd57600080fd5b80151581146119cd57600080fdfea2646970667358221220a7e19740a045ca277745868a9ac88b87f050c6954895e10f38c411c53312ad6f64736f6c634300060a0033

Libraries Used


Deployed Bytecode Sourcemap

46247:43399:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64951:259;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;46594:31;;;:::i;:::-;;;;;;;;47023:25;;;:::i;59770:211::-;;;;;;;;;:::i;:::-;;55213:395;;;;;;;;;:::i;59007:283::-;;;;;;;;;:::i;63824:176::-;;;;;;;;;:::i;:::-;;;;;;;;56337:274;;;;;;;;;:::i;59406:94::-;;;:::i;61789:281::-;;;:::i;:::-;;;;;;;;;;;47376:26;;;:::i;46420:39::-;;;:::i;5484:148::-;;;:::i;46508:29::-;;;:::i;4842:79::-;;;:::i;46466:35::-;;;:::i;66520:328::-;;;;;;;;;:::i;:::-;;;;;;;;;;46873:28;;;:::i;56885:239::-;;;;;;;;;:::i;60189:343::-;;;;;;;;;:::i;61326:138::-;;;;;;;;;:::i;57768:297::-;;;;;;;;;:::i;57308:267::-;;;;;;;;;:::i;62379:359::-;;;;;;;;;:::i;67000:111::-;;;;;;;;;:::i;65391:147::-;;;;;;;;;:::i;58367:223::-;;;;;;;;;:::i;47152:33::-;;;:::i;46544:43::-;;;:::i;67297:127::-;;;;;;;;;:::i;66077:153::-;;;;;;;;;:::i;:::-;;;;;;;;55859:179;;;;;;;;;:::i;64253:269::-;;;;;;;;;:::i;63124:401::-;;;;;;;;;:::i;:::-;;;;;;;;;;47254:29;;;:::i;60850:191::-;;;;;;;;;:::i;5787:244::-;;;;;;;;;:::i;65710:141::-;;;;;;;;;:::i;64951:259::-;65118:4;65142:60;65159:11;65172:7;65181:11;65194:7;65142:16;:60::i;:::-;65135:67;64951:259;-1:-1:-1;;;;;64951:259:0:o;46594:31::-;;;-1:-1:-1;;;;;46594:31:0;;:::o;47023:25::-;;;-1:-1:-1;;;;;47023:25:0;;:::o;59770:211::-;5064:12;:10;:12::i;:::-;5054:6;;-1:-1:-1;;;;;5054:6:0;;;:22;;;5046:67;;;;-1:-1:-1;;;5046:67:0;;;;;;;;;;;;;;;;;59871:1:::1;59864:4;:8;59856:24;;;;-1:-1:-1::0;;;59856:24:0::1;;;;;;;;;-1:-1:-1::0;;;;;59893:21:0;::::1;;::::0;;;:8:::1;:21;::::0;;;;;;:28;;;59939:34;::::1;::::0;::::1;::::0;59917:4;;59939:34:::1;;;;;;;;;;59770:211:::0;;:::o;55213:395::-;1225:12;;;;;;;;:31;;;1241:15;:13;:15::i;:::-;1225:47;;;-1:-1:-1;1261:11:0;;;;1260:12;1225:47;1217:106;;;;-1:-1:-1;;;1217:106:0;;;;;;;;;1336:19;1359:12;;;;;;1358:13;1382:99;;;;1417:12;:19;;-1:-1:-1;;;;1417:19:0;;;;;1451:18;1432:4;1451:18;;;1382:99;-1:-1:-1;;;;;55311:26:0;::::1;55303:41;;;;-1:-1:-1::0;;;55303:41:0::1;;;;;;;;;-1:-1:-1::0;;;;;55363:20:0;::::1;55355:35;;;;-1:-1:-1::0;;;55355:35:0::1;;;;;;;;;55403:22;55418:6;55403:14;:22::i;:::-;55436:34;:32;:34::i;:::-;55483:11;:48:::0;;-1:-1:-1;;;;;;55483:48:0::1;-1:-1:-1::0;;;;;55483:48:0;::::1;;::::0;;55542:24:::1;:22;:24::i;:::-;55579:14;:21:::0;;-1:-1:-1;;;;55579:21:0::1;-1:-1:-1::0;;;55579:21:0::1;::::0;;1507:67;;;;1557:5;1542:20;;-1:-1:-1;;1542:20:0;;;1507:67;55213:395;;;:::o;59007:283::-;59103:10;59093:21;;;;:9;:21;;;;;;;;-1:-1:-1;;;;;59093:32:0;;;;;;;;;;;;:47;;;;;;;59085:62;;;;-1:-1:-1;;;59085:62:0;;;;;;;;;59170:10;59160:21;;;;:9;:21;;;;;;;;-1:-1:-1;;;;;59160:32:0;;;;;;;;;;;:46;;-1:-1:-1;;59160:46:0;;;;;;;59224:58;;59160:32;;59170:10;59224:58;;;;59160:46;;59224:58;;;;;;;;;;59007:283;;:::o;63824:176::-;63925:10;;:40;;-1:-1:-1;;;63925:40:0;;63898:7;;63925:67;;63983:8;;63925:53;;63970:7;;-1:-1:-1;;;;;63925:10:0;;:31;;:40;;63957:7;;63925:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;:53;:44;:53;:::i;:::-;:57;:67;:57;:67;:::i;:::-;63918:74;;63824:176;;;;;:::o;56337:274::-;53611:13;;-1:-1:-1;;;;;53611:13:0;53597:10;:27;53589:42;;;;-1:-1:-1;;;53589:42:0;;;;;;;;;56440:21:::1;::::0;::::1;-1:-1:-1::0;;;56440:21:0;;::::1;;:41;;::::0;::::1;;;;56432:56;;;;-1:-1:-1::0;;;56432:56:0::1;;;;;;;;;56501:21;:40:::0;;-1:-1:-1;;;;56501:40:0::1;-1:-1:-1::0;;;56501:40:0;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;;56559:44:::1;::::0;::::1;::::0;::::1;::::0;56501:40:::1;56581:21:::0;::::1;;::::0;56559:44:::1;;;;;;;;;;56337:274:::0;:::o;59406:94::-;5064:12;:10;:12::i;:::-;5054:6;;-1:-1:-1;;;;;5054:6:0;;;:22;;;5046:67;;;;-1:-1:-1;;;5046:67:0;;;;;;;;;59468:24:::1;:22;:24::i;:::-;59406:94::o:0;61789:281::-;61998:9;;62018:6;;62035:10;;62056:4;;-1:-1:-1;;;;;61998:9:0;;;;62018:6;;;;62035:10;;;;62056:4;;;61789:281::o;47376:26::-;;;-1:-1:-1;;;47376:26:0;;;;;:::o;46420:39::-;;;-1:-1:-1;;;;;46420:39:0;;:::o;5484:148::-;5064:12;:10;:12::i;:::-;5054:6;;-1:-1:-1;;;;;5054:6:0;;;:22;;;5046:67;;;;-1:-1:-1;;;5046:67:0;;;;;;;;;5575:6:::1;::::0;5554:40:::1;::::0;5591:1:::1;::::0;-1:-1:-1;;;;;5575:6:0::1;::::0;5554:40:::1;::::0;5591:1;;5554:40:::1;5605:6;:19:::0;;-1:-1:-1;;;;;;5605:19:0::1;::::0;;5484:148::o;46508:29::-;;;-1:-1:-1;;;;;46508:29:0;;:::o;4842:79::-;4907:6;;-1:-1:-1;;;;;4907:6:0;4842:79;;:::o;46466:35::-;;;-1:-1:-1;;;;;46466:35:0;;:::o;66520:328::-;66645:24;;:::i;:::-;-1:-1:-1;;;;;66749:14:0;;66684:7;66749:14;;;:6;:14;;;;;;;;:24;;;;;;;;66775:17;;;:9;:17;;;;;:27;;;;;;;;;66804:25;;;:17;:25;;;;;:35;;;;;;;;;66741:99;;;;;;;;;;;;;;;;;;;;;66684:7;;;;66749:24;;66775:27;;66804:35;;66741:99;;66749:24;;66741:99;;;;66749:24;;66741:99;;66749:24;66741:99;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66741:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66741:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66741:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66520:328;;;;;:::o;46873:28::-;;;-1:-1:-1;;;;;46873:28:0;;:::o;56885:239::-;53409:10;;-1:-1:-1;;;;;53409:10:0;53395;:24;53387:39;;;;-1:-1:-1;;;53387:39:0;;;;;;;;;56977:17:::1;::::0;::::1;-1:-1:-1::0;;;56977:17:0;;::::1;;:33;;::::0;::::1;;;;56969:48;;;;-1:-1:-1::0;;;56969:48:0::1;;;;;;;;;57030:17;:32:::0;;-1:-1:-1;;;;57030:32:0::1;-1:-1:-1::0;;;57030:32:0;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;;57080:36:::1;::::0;::::1;::::0;::::1;::::0;57030:32:::1;57098:17:::0;::::1;;::::0;57080:36:::1;;60189:343:::0;8147:11;;;;8139:55;;;;-1:-1:-1;;;8139:55:0;;;;;;;;;8272:11;:19;;-1:-1:-1;;8272:19:0;;;53215::::1;:17;:19::i;:::-;60293:17:::2;60312:18:::0;60332:15:::2;60351:21;60363:8;60351:11;:21::i;:::-;60292:80;;;;;;60387:12;60383:142;;;60416:38;60434:10;60446:7;60416:17;:38::i;:::-;-1:-1:-1::0;;;;;60469:29:0;::::2;;::::0;;;:17:::2;:29;::::0;;;;;;;:38;;;;;;;;60510:3:::2;60469:44:::0;;60383:142:::2;-1:-1:-1::0;;8452:11:0;:18;;-1:-1:-1;;8452:18:0;8466:4;8452:18;;;-1:-1:-1;;60189:343:0:o;61326:138::-;-1:-1:-1;;;;;61428:17:0;;;61404:4;61428:17;;;:9;:17;;;;;;;;:28;;;;;;;;;;;;;;;61326:138::o;57768:297::-;5064:12;:10;:12::i;:::-;5054:6;;-1:-1:-1;;;;;5054:6:0;;;:22;;;5046:67;;;;-1:-1:-1;;;5046:67:0;;;;;;;;;-1:-1:-1;;;;;57856:28:0;::::1;57848:44;;;;-1:-1:-1::0;;;57848:44:0::1;;;;;;;;;57911:13;::::0;-1:-1:-1;;;;;57911:31:0;;::::1;:13:::0;::::1;:31;;57903:46;;;;-1:-1:-1::0;;;57903:46:0::1;;;;;;;;;57986:13;::::0;57965:51:::1;::::0;-1:-1:-1;;;;;57965:51:0;;::::1;::::0;57986:13:::1;::::0;57965:51:::1;::::0;57986:13:::1;::::0;57965:51:::1;58027:13;:30:::0;;-1:-1:-1;;;;;;58027:30:0::1;-1:-1:-1::0;;;;;58027:30:0;;;::::1;::::0;;;::::1;::::0;;57768:297::o;57308:267::-;5064:12;:10;:12::i;:::-;5054:6;;-1:-1:-1;;;;;5054:6:0;;;:22;;;5046:67;;;;-1:-1:-1;;;5046:67:0;;;;;;;;;-1:-1:-1;;;;;57390:25:0;::::1;57382:41;;;;-1:-1:-1::0;;;57382:41:0::1;;;;;;;;;57442:10;::::0;-1:-1:-1;;;;;57442:25:0;;::::1;:10:::0;::::1;:25;;57434:40;;;;-1:-1:-1::0;;;57434:40:0::1;;;;;;;;;57508:10;::::0;57490:42:::1;::::0;-1:-1:-1;;;;;57490:42:0;;::::1;::::0;57508:10:::1;::::0;57490:42:::1;::::0;57508:10:::1;::::0;57490:42:::1;57543:10;:24:::0;;-1:-1:-1;;;;;;57543:24:0::1;-1:-1:-1::0;;;;;57543:24:0;;;::::1;::::0;;;::::1;::::0;;57308:267::o;62379:359::-;62456:7;62477:30;;:::i;:::-;62509:17;62532:37;62552:6;62560:8;62532:19;:37::i;:::-;-1:-1:-1;62618:10:0;;:48;;-1:-1:-1;;;62618:48:0;;62476:93;;-1:-1:-1;62476:93:0;;-1:-1:-1;62583:16:0;;;;-1:-1:-1;;;;;62618:10:0;;:30;;:48;;62476:93;;;;62618:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62582:84;;;;62684:8;62679:23;;62701:1;62694:8;;;;;;;;62679:23;-1:-1:-1;62722:8:0;62379:359;-1:-1:-1;;;;;62379:359:0:o;67000:111::-;-1:-1:-1;;;;;67087:16:0;67060:7;67087:16;;;:8;:16;;;;;;;67000:111::o;65391:147::-;-1:-1:-1;;;;;65496:34:0;65469:7;65496:34;;;:19;:34;;;;;;;65391:147::o;58367:223::-;5064:12;:10;:12::i;:::-;5054:6;;-1:-1:-1;;;;;5054:6:0;;;:22;;;5046:67;;;;-1:-1:-1;;;5046:67:0;;;;;;;;;58453:14:::1;::::0;::::1;-1:-1:-1::0;;;58453:14:0;;::::1;;:31;;::::0;::::1;;;;58445:46;;;;-1:-1:-1::0;;;58445:46:0::1;;;;;;;;;58504:14;:30:::0;;-1:-1:-1;;;;58504:30:0::1;-1:-1:-1::0;;;58504:30:0;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;;58552::::1;::::0;::::1;::::0;::::1;::::0;58504::::1;58567:14:::0;::::1;;::::0;58552:30:::1;;47152:33:::0;;;-1:-1:-1;;;47152:33:0;;;;;:::o;46544:43::-;;;-1:-1:-1;;;;;46544:43:0;;:::o;67297:127::-;-1:-1:-1;;;;;67392:24:0;67365:7;67392:24;;;:16;:24;;;;;;;67297:127::o;66077:153::-;66152:24;;:::i;:::-;-1:-1:-1;;;;;66197:14:0;;;;;;:6;:14;;;;;;;;:24;;;;;;;;;66189:33;;;;;;;;;;;;;;;;;;;;;;;66197:24;;66189:33;;66197:24;;66189:33;;66197:24;66189:33;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66189:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66189:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66189:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66077:153;;;;:::o;55859:179::-;55928:4;;:48;;-1:-1:-1;;;55928:48:0;;-1:-1:-1;;;;;55928:4:0;;;;:19;;:48;;55948:6;;55956:10;;55968:7;;55928:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56014:6;-1:-1:-1;;;;;55994:36:0;56002:10;-1:-1:-1;;;;;55994:36:0;;56022:7;55994:36;;;;;;;64253:269;64322:4;64340:18;64360:14;64376:18;64396:14;64414:26;64432:7;64414:17;:26::i;:::-;64339:101;;;;;;;;64458:56;64475:10;64487:6;64495:10;64507:6;64458:16;:56::i;:::-;64451:63;64253:269;-1:-1:-1;;;;;;64253:269:0:o;63124:401::-;63298:4;63317:7;63339;63377:18;63397:13;63412:12;63428:43;63444:6;63452:8;63462;63428:15;:43::i;:::-;63374:97;;;;-1:-1:-1;63374:97:0;;-1:-1:-1;63124:401:0;-1:-1:-1;;;;;;;;63124:401:0:o;47254:29::-;;;-1:-1:-1;;;47254:29:0;;;;;:::o;60850:191::-;8147:11;;;;8139:55;;;;-1:-1:-1;;;8139:55:0;;;;;;;;;8272:11;:19;;-1:-1:-1;;8272:19:0;;;53215::::1;:17;:19::i;:::-;60946:35:::2;60964:6;60972:8;60946:17;:35::i;:::-;-1:-1:-1::0;;;;;60992:25:0;;::::2;;::::0;;;:17:::2;:25;::::0;;;;;;;:35;;;;;;;61030:3:::2;60992:41:::0;;8452:11;:18;;-1:-1:-1;;8452:18:0;8466:4;8452:18;;;60850:191::o;5787:244::-;5064:12;:10;:12::i;:::-;5054:6;;-1:-1:-1;;;;;5054:6:0;;;:22;;;5046:67;;;;-1:-1:-1;;;5046:67:0;;;;;;;;;-1:-1:-1;;;;;5876:22:0;::::1;5868:73;;;;-1:-1:-1::0;;;5868:73:0::1;;;;;;;;;5978:6;::::0;5957:38:::1;::::0;-1:-1:-1;;;;;5957:38:0;;::::1;::::0;5978:6:::1;::::0;5957:38:::1;::::0;5978:6:::1;::::0;5957:38:::1;6006:6;:17:::0;;-1:-1:-1;;;;;;6006:17:0::1;-1:-1:-1::0;;;;;6006:17:0;;;::::1;::::0;;;::::1;::::0;;5787:244::o;65710:141::-;65770:4;65817:7;-1:-1:-1;;;;;65801:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65794:3;:49;;;65710:141;-1:-1:-1;;65710:141:0:o;88834:387::-;89039:6;;:48;;-1:-1:-1;;;89039:48:0;;89002:4;;-1:-1:-1;;;;;89039:6:0;;:26;;:48;;89066:11;;89079:7;;89039:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:109;;;;-1:-1:-1;89104:6:0;;:44;;-1:-1:-1;;;89104:44:0;;-1:-1:-1;;;;;89104:6:0;;;;:26;;:44;;89131:7;;89140;;89104:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89039:174;;;;-1:-1:-1;89165:6:0;;:48;;-1:-1:-1;;;89165:48:0;;-1:-1:-1;;;;;89165:6:0;;;;:26;;:48;;89192:11;;89205:7;;89165:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3175:106;3263:10;3175:106;:::o;1674:568::-;2115:4;2182:17;2227:7;1674:568;:::o;4438:151::-;1225:12;;;;;;;;:31;;;1241:15;:13;:15::i;:::-;1225:47;;;-1:-1:-1;1261:11:0;;;;1260:12;1225:47;1217:106;;;;-1:-1:-1;;;1217:106:0;;;;;;;;;1336:19;1359:12;;;;;;1358:13;1382:99;;;;1417:12;:19;;-1:-1:-1;;;;1417:19:0;;;;;1451:18;1432:4;1451:18;;;1382:99;4511:26:::1;:24;:26::i;:::-;4548:33;4573:7;4548:24;:33::i;:::-;1511:14:::0;1507:67;;;1557:5;1542:20;;-1:-1:-1;;1542:20:0;;;1507:67;4438:151;;:::o;7128:520::-;1225:12;;;;;;;;:31;;;1241:15;:13;:15::i;:::-;1225:47;;;-1:-1:-1;1261:11:0;;;;1260:12;1225:47;1217:106;;;;-1:-1:-1;;;1217:106:0;;;;;;;;;1336:19;1359:12;;;;;;1358:13;1382:99;;;;1417:12;:19;;-1:-1:-1;;;;1417:19:0;;;;;1451:18;1432:4;1451:18;;;1382:99;7622:11:::1;:18:::0;;-1:-1:-1;;7622:18:0::1;7636:4;7622:18;::::0;;1507:67;;;;1557:5;1542:20;;-1:-1:-1;;1542:20:0;;;1507:67;7128:520;:::o;89313:330::-;89398:11;;;;;;;;;-1:-1:-1;;;;;89398:11:0;-1:-1:-1;;;;;89398:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89367:9;:58;;-1:-1:-1;;;;;;89367:58:0;-1:-1:-1;;;;;89367:58:0;;;;;;89461:11;;:23;;;-1:-1:-1;;;89461:23:0;;;;:11;;;;;:21;;:23;;;;;;;;;;;;;;:11;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89436:6;:49;;-1:-1:-1;;;;;;89436:49:0;-1:-1:-1;;;;;89436:49:0;;;;;;89535:11;;:33;;;-1:-1:-1;;;89535:33:0;;;;:11;;;;;:31;;:33;;;;;;;;;;;;;;:11;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89496:10;:73;;-1:-1:-1;;;;;;89496:73:0;-1:-1:-1;;;;;89496:73:0;;;;;;89607:11;;:27;;;-1:-1:-1;;;89607:27:0;;;;:11;;;;;:25;;:27;;;;;;;;;;;;;;:11;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89580:4;:55;;-1:-1:-1;;;;;;89580:55:0;-1:-1:-1;;;;;89580:55:0;;;;;;;;;;89313:330::o;10762:471::-;10820:7;11065:6;11061:47;;-1:-1:-1;11095:1:0;11088:8;;11061:47;11132:5;;;11136:1;11132;:5;:1;11156:5;;;;;:10;11148:56;;;;-1:-1:-1;;;11148:56:0;;;;;;;;11701:132;11759:7;11786:39;11790:1;11793;11786:39;;;;;;;;;;;;;;;;;:3;:39::i;54612:95::-;54675:17;;-1:-1:-1;;;54675:17:0;;;;54674:18;54666:33;;;;-1:-1:-1;;;54666:33:0;;;;;;;;67973:2958;68082:4;;;;;;;68243:2626;68267:8;:15;68263:1;:19;68243:2626;;;68304:32;;:::i;:::-;68339:8;68348:1;68339:11;;;;;;;;;;;;;;;;;;68397:17;;68339:11;;-1:-1:-1;68626:30:0;68612:10;:44;;;;;;;;;;68611:108;;;;-1:-1:-1;68693:25:0;68679:10;:39;;;;;;;;;;68611:108;:173;;;;-1:-1:-1;68755:28:0;68741:10;:42;;;;;;;;;;68611:173;:233;;;;-1:-1:-1;68820:23:0;68806:10;:37;;;;;;;;;;68611:233;68589:727;;;69013:12;69009:167;;;69072:6;:12;;;-1:-1:-1;;;;;69058:26:0;:10;-1:-1:-1;;;;;69058:26:0;;69050:42;;;;-1:-1:-1;;;69050:42:0;;;;;;;;;69134:6;:14;;;69123:7;:25;69115:41;;;;-1:-1:-1;;;69115:41:0;;;;;;;;;69209:4;69194:19;;69242:6;:14;;;69232:24;;69288:6;:12;;;69275:25;;68589:727;69350:28;69336:10;:42;;;;;;;;;69332:1526;;;69399:47;69410:35;69438:6;69410:27;:35::i;:::-;69399:10;:47::i;:::-;69332:1526;;;69486:36;69472:10;:50;;;;;;;;;69468:1390;;;69543:47;69556:33;69582:6;69556:25;:33::i;:::-;69543:12;:47::i;69468:1390::-;69630:37;69616:10;:51;;;;;;;;;69612:1246;;;69688:49;69702:34;69729:6;69702:26;:34::i;:::-;69688:13;:49::i;69612:1246::-;69777:36;69763:10;:50;;;;;;;;;69759:1099;;;69834:53;69853:33;69879:6;69853:25;:33::i;:::-;69834:18;:53::i;69759:1099::-;69927:37;69913:10;:51;;;;;;;;;69909:949;;;69985:55;70005:34;70032:6;70005:26;:34::i;:::-;69985:19;:55::i;69909:949::-;70080:34;70066:10;:48;;;;;;;;;70062:796;;;70135:43;70147:30;70170:6;70147:22;:30::i;:::-;70135:11;:43::i;70062:796::-;70218:34;70204:10;:48;;;;;;;;;70200:658;;;70273:43;70285:30;70308:6;70285:22;:30::i;:::-;70273:11;:43::i;70200:658::-;70356:25;70342:10;:39;;;;;;;;;70338:520;;;70402:41;70410:32;70435:6;70410:24;:32::i;:::-;70402:7;:41::i;70338:520::-;70483:30;70469:10;:44;;;;;;;;;70465:393;;;70534:51;70547:37;70577:6;70547:29;:37::i;:::-;70534:12;:51::i;70465:393::-;70625:28;70611:10;:42;;;;;;;;;70607:251;;;70674:47;70685:35;70713:6;70685:27;:35::i;:::-;70674:10;:47::i;70607:251::-;70761:23;70747:10;:37;;;;;;;;;70743:115;;;70805:37;70811:30;70834:6;70811:22;:30::i;:::-;70805:5;:37::i;:::-;-1:-1:-1;;68284:3:0;;68243:2626;;;-1:-1:-1;70889:12:0;70903:10;;-1:-1:-1;70903:10:0;-1:-1:-1;67973:2958:0;-1:-1:-1;;67973:2958:0:o;71126:311::-;71213:30;;:::i;:::-;71245:17;71268:37;71288:6;71296:8;71268:19;:37::i;:::-;-1:-1:-1;71340:10:0;;:48;;-1:-1:-1;;;71340:48:0;;71212:93;;-1:-1:-1;71212:93:0;;-1:-1:-1;71319:17:0;;-1:-1:-1;;;;;71340:10:0;;;;:30;;:48;;71212:93;;;;71340:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71316:72;;;71409:12;71401:28;;;;-1:-1:-1;;;71401:28:0;;;;;;;;;71126:311;;;;;:::o;87778:706::-;87886:7;87908;87930;87952;87987:22;88028:7;87987:49;;88051:6;-1:-1:-1;;;;;88051:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88051:25:0;;;;;;;;-1:-1:-1;;88051:25:0;;;;;;;;;;;;;;;;88047:430;;88366:6;-1:-1:-1;;;;;88366:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88392:6;-1:-1:-1;;;;;88392:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88418:6;-1:-1:-1;;;;;88418:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88440:6;-1:-1:-1;;;;;88440:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88358:107;;;;;;;;;;;88047:430;-1:-1:-1;88285:10:0;;-1:-1:-1;88297:10:0;;-1:-1:-1;88309:6:0;-1:-1:-1;88317:6:0;;-1:-1:-1;88277:47:0;;-1:-1:-1;;88277:47:0;87778:706;;;;;;:::o;86960:734::-;87135:24;;:::i;:::-;87174:4;87193:7;87215;87251:30;;:::i;:::-;87283:17;87302:29;87335:74;87369:6;87390:8;87335:19;:74::i;:::-;87250:159;;;;;;87421:18;87441:13;87456:22;87482:10;;;;;;;;;-1:-1:-1;;;;;87482:10:0;-1:-1:-1;;;;;87482:25:0;;87522:5;87542:9;87566:21;87602:8;87482:139;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87642:5;;87420:201;;-1:-1:-1;87420:201:0;-1:-1:-1;87642:5:0;;-1:-1:-1;86960:734:0;;-1:-1:-1;;;;;;;;;86960:734:0:o;3108:59::-;1225:12;;;;;;;;:31;;;1241:15;:13;:15::i;:::-;1225:47;;;-1:-1:-1;1261:11:0;;;;1260:12;1225:47;1217:106;;;;-1:-1:-1;;;1217:106:0;;;;;;;;;1336:19;1359:12;;;;;;1358:13;1382:99;;;;1417:12;:19;;-1:-1:-1;;;;1417:19:0;;;;;1451:18;1432:4;1451:18;;;1382:99;1511:14;1507:67;;;1557:5;1542:20;;-1:-1:-1;;1542:20:0;;;3108:59;:::o;4597:164::-;1225:12;;;;;;;;:31;;;1241:15;:13;:15::i;:::-;1225:47;;;-1:-1:-1;1261:11:0;;;;1260:12;1225:47;1217:106;;;;-1:-1:-1;;;1217:106:0;;;;;;;;;1336:19;1359:12;;;;;;1358:13;1382:99;;;;1417:12;:19;;-1:-1:-1;;;;1417:19:0;;;;;1451:18;1432:4;1451:18;;;1382:99;4680:6:::1;:16:::0;;-1:-1:-1;;;;;;4680:16:0::1;-1:-1:-1::0;;;;;4680:16:0;::::1;::::0;;::::1;::::0;;;4712:41:::1;::::0;-1:-1:-1;;4712:41:0::1;::::0;-1:-1:-1;;4712:41:0::1;1511:14:::0;1507:67;;;1557:5;1542:20;;-1:-1:-1;;1542:20:0;;;4597:164;;:::o;12321:379::-;12441:7;12543:12;12536:5;12528:28;;;;-1:-1:-1;;;12528:28:0;;;;;;;;;;;12567:9;12583:1;12579;:5;;;;;;;12321:379;-1:-1:-1;;;;;12321:379:0:o;30422:678::-;30499:20;;:::i;:::-;30560;30540:16;;:40;;;;;;;;;30532:55;;;;-1:-1:-1;;;30532:55:0;;;;;;;;;30606:11;;;;-1:-1:-1;;;;;30606:25:0;30598:40;;;;-1:-1:-1;;;30598:40:0;;;;;;;;;30723:17;30757:5;:10;;;:17;30778:2;30757:23;30753:151;;;30870:5;:10;;;30859:33;;;;;;;;;;;;;;30847:45;;30753:151;30983:1;30971:9;:13;30963:28;;;;-1:-1:-1;;;30963:28:0;;;;;;;;;31011:81;;;;;;;;31033:11;;;;;-1:-1:-1;;;;;31011:81:0;;;31055:13;;;;;31011:81;;;;;;;;;;-1:-1:-1;31011:81:0;30422:678::o;71688:496::-;53006:23;:21;:23::i;:::-;71826:11;;71814:10:::1;::::0;53944:37:::1;71814:10:::0;71826:11;53944:13:::1;:37::i;:::-;71893:11:::0;;-1:-1:-1;;;;;71873:32:0::2;71855:15;71873:32:::0;;;:19:::2;:32;::::0;;;;;:39:::2;::::0;71910:1:::2;71873:39;:36;:39;:::i;:::-;71855:57;;71950:7;71933:5;:13;;;:24;71925:40;;;;-1:-1:-1::0;;;71925:40:0::2;;;;;;;;;72026:11:::0;;-1:-1:-1;;;;;72006:32:0;;::::2;;::::0;;;:19:::2;:32;::::0;;;;;;;:42;;;72093:15;;::::2;::::0;;72069:11;;72059:22;::::2;::::0;;:9:::2;:22:::0;;;;;:31;;;;;;;;;;:49;;;;72160:15;;72138:11;;72126:50;;72160:15;;72126:50;;;::::2;::::0;::::2;::::0;::::2;::::0;72041:7;;72126:50:::2;;;;;;;;;;53994:1;53042::::1;;71688:496:::0;:::o;32789:617::-;32864:18;;:::i;:::-;32938:28;32918:16;;:48;;;;;;;;;32917:104;;;-1:-1:-1;32992:28:0;32972:16;;:48;;;;;;;;;32917:104;32895:156;;;;-1:-1:-1;;;32895:156:0;;;;;;;;;33070:11;;;;-1:-1:-1;;;;;33070:25:0;33062:40;;;;-1:-1:-1;;;33062:40:0;;;;;;;;;33135:263;;;;;;;;33173:5;:11;;;-1:-1:-1;;;;;33135:263:0;;;;;33212:5;:13;;;33135:263;;;;33250:5;:19;;;-1:-1:-1;;;;;33135:263:0;;;;;33295:5;:11;;;-1:-1:-1;;;;;33135:263:0;;;;;33332:5;:11;;;33135:263;;;;33370:5;:12;;;33135:263;;;33115:283;;32789:617;;;:::o;72442:858::-;53006:23;:21;:23::i;:::-;72580:11;;72568:10:::1;::::0;53944:37:::1;72568:10:::0;72580:11;53944:13:::1;:37::i;:::-;72617:41:::2;72631:5;:11;;;72644:5;:13;;;72617;:41::i;:::-;72609:57;;;;-1:-1:-1::0;;;72609:57:0::2;;;;;;;;;72762:10;::::0;::::2;::::0;-1:-1:-1;;;;;72762:24:0::2;72776:10;72762:24;::::0;72761:57:::2;;;72806:5;:11;;;-1:-1:-1::0;;;;;72792:25:0::2;:5;:10;;;-1:-1:-1::0;;;;;72792:25:0::2;;72761:57;72753:73;;;;-1:-1:-1::0;;;72753:73:0::2;;;;;;;;;72847:9;::::0;72877:11:::2;::::0;::::2;::::0;72847:42:::2;::::0;-1:-1:-1;;;72847:42:0;;-1:-1:-1;;;;;72847:9:0;;::::2;::::0;:29:::2;::::0;:42:::2;::::0;::::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72839:58;;;;-1:-1:-1::0;;;72839:58:0::2;;;;;;;;;72910:22;72951:5;:11;;;72910:53;;72990:6;-1:-1:-1::0;;;;;72990:22:0::2;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72984:3;:30;72976:46;;;;-1:-1:-1::0;;;72976:46:0::2;;;;;;;;;73042:11:::0;;-1:-1:-1;;;;;73035:19:0::2;;::::0;;;:6:::2;:19;::::0;;;;;;;73055:13;;::::2;::::0;73035:34;;;;;;;;;73078:11:::2;::::0;::::2;::::0;73091:12:::2;::::0;::::2;::::0;73105:11:::2;::::0;::::2;::::0;73035:82;;-1:-1:-1;;;73035:82:0;;:42:::2;::::0;::::2;::::0;:82:::2;::::0;:34;;73078:11;;73091:12;;73105:11;73035:82:::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;73130:4:0::2;::::0;73150:11:::2;::::0;::::2;::::0;73163:10:::2;::::0;;::::2;::::0;73175:12:::2;::::0;::::2;::::0;73130:58;;-1:-1:-1;;;73130:58:0;;-1:-1:-1;;;;;73130:4:0;;::::2;::::0;-1:-1:-1;73130:19:0::2;::::0;-1:-1:-1;73130:58:0::2;::::0;73163:10;;73175:12;73130:58:::2;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;73252:5;:10;;;-1:-1:-1::0;;;;;73206:86:0::2;73239:5;:11;;;-1:-1:-1::0;;;;;73206:86:0::2;73226:5;:11;;;-1:-1:-1::0;;;;;73206:86:0::2;;73264:5;:13;;;73279:5;:12;;;73206:86;;;;;;;;;;;;;;;;53994:1;53042::::1;;72442:858:::0;:::o;33633:682::-;33709:19;;:::i;:::-;33784:29;33764:16;;:49;;;;;;;;;33763:106;;;-1:-1:-1;33839:29:0;33819:16;;:49;;;;;;;;;33763:106;33741:159;;;;-1:-1:-1;;;33741:159:0;;;;;;;;;33919:11;;;;-1:-1:-1;;;;;33919:25:0;33911:41;;;;-1:-1:-1;;;33911:41:0;;;;;;;;;33971:19;;;;-1:-1:-1;;;;;33971:33:0;33963:49;;;;-1:-1:-1;;;33963:49:0;;;;;;;;73561:629;53006:23;:21;:23::i;:::-;73701:11;;73689:10:::1;::::0;53944:37:::1;73689:10:::0;73701:11;53944:13:::1;:37::i;:::-;73738:41:::2;73752:5;:11;;;73765:5;:13;;;73738;:41::i;:::-;73730:57;;;;-1:-1:-1::0;;;73730:57:0::2;;;;;;;;;73800:22;73841:5;:11;;;73800:53;;73880:6;-1:-1:-1::0;;;;;73880:22:0::2;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73874:3;:30;73866:46;;;;-1:-1:-1::0;;;73866:46:0::2;;;;;;;;;73932:11:::0;;-1:-1:-1;;;;;73925:19:0::2;;::::0;;;:6:::2;:19;::::0;;;;;;;73945:13;;::::2;::::0;73925:34;;;;;;;;;73971:11:::2;::::0;::::2;::::0;73984:12:::2;::::0;::::2;::::0;73998:11:::2;::::0;::::2;::::0;73925:85;;-1:-1:-1;;;73925:85:0;;:45:::2;::::0;::::2;::::0;:85:::2;::::0;:34;;73971:11;;73984:12;;73998:11;73925:85:::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;74023:4:0::2;::::0;74043:11:::2;::::0;::::2;::::0;74056:8:::2;::::0;;::::2;::::0;74066:12:::2;::::0;::::2;::::0;74023:56;;-1:-1:-1;;;74023:56:0;;-1:-1:-1;;;;;74023:4:0;;::::2;::::0;-1:-1:-1;74023:19:0::2;::::0;-1:-1:-1;74023:56:0::2;::::0;74056:8;;74066:12;74023:56:::2;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;74144:5;:8;;;-1:-1:-1::0;;;;;74097:85:0::2;74131:5;:11;;;-1:-1:-1::0;;;;;74097:85:0::2;74118:5;:11;;;-1:-1:-1::0;;;;;74097:85:0::2;;74154:5;:13;;;74169:5;:12;;;74097:85;;;;;;;;74450:1064:::0;53006:23;:21;:23::i;:::-;74594:11;;74582:10:::1;::::0;53944:37:::1;74582:10:::0;74594:11;53944:13:::1;:37::i;:::-;74631:41:::2;74645:5;:11;;;74658:5;:13;;;74631;:41::i;:::-;74623:57;;;;-1:-1:-1::0;;;74623:57:0::2;;;;;;;;;74775:10;::::0;::::2;::::0;-1:-1:-1;;;;;74775:24:0::2;74789:10;74775:24;::::0;74774:57:::2;;;74819:5;:11;;;-1:-1:-1::0;;;;;74805:25:0::2;:5;:10;;;-1:-1:-1::0;;;;;74805:25:0::2;;74774:57;74766:73;;;;-1:-1:-1::0;;;74766:73:0::2;;;;;;;;;74860:9;::::0;74894:11:::2;::::0;::::2;::::0;74860:46:::2;::::0;-1:-1:-1;;;74860:46:0;;-1:-1:-1;;;;;74860:9:0;;::::2;::::0;:33:::2;::::0;:46:::2;::::0;::::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74852:62;;;;-1:-1:-1::0;;;74852:62:0::2;;;;;;;;;74930:17;74953:47;74973:5;:11;;;74986:5;:13;;;74953:19;:47::i;:::-;74927:73;;;;75017:9;75030:1;75017:14;75013:213;;;75114:12;::::0;::::2;::::0;75097:11:::2;::::0;::::2;::::0;-1:-1:-1;;;;;75080:29:0::2;;::::0;;;:16:::2;:29;::::0;;;;;:47:::2;::::0;::::2;:33;:47;:::i;:::-;75065:11;::::0;::::2;::::0;;-1:-1:-1;;;;;75048:29:0;;::::2;;::::0;;;:16:::2;:29;::::0;;;;;;;:79;;;;75194:11;;75185:21;::::2;::::0;;:8:::2;:21:::0;;;;;;75169:11;;75152:29;;::::2;::::0;;;;;;;;;;:54:::2;;75144:70;;;;-1:-1:-1::0;;;75144:70:0::2;;;;;;;;;75245:11:::0;;-1:-1:-1;;;;;75238:19:0::2;;::::0;;;:6:::2;:19;::::0;;;;;;;75258:13;;::::2;::::0;75238:34;;;;;;;;;75287:11:::2;::::0;::::2;::::0;75300:12:::2;::::0;::::2;::::0;75314:11:::2;::::0;::::2;::::0;75238:88;;-1:-1:-1;;;75238:88:0;;:48:::2;::::0;::::2;::::0;:88:::2;::::0;:34;;75287:11;;75300:12;;75314:11;75238:88:::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;75339:4:0::2;::::0;75359:11:::2;::::0;::::2;::::0;75372:10:::2;::::0;;::::2;::::0;75384:12:::2;::::0;::::2;::::0;75339:58;;-1:-1:-1;;;75339:58:0;;-1:-1:-1;;;;;75339:4:0;;::::2;::::0;-1:-1:-1;75339:19:0::2;::::0;-1:-1:-1;75339:58:0::2;::::0;75372:10;;75384:12;75339:58:::2;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;75466:5;:10;;;-1:-1:-1::0;;;;;75415:91:0::2;75453:5;:11;;;-1:-1:-1::0;;;;;75415:91:0::2;75440:5;:11;;;-1:-1:-1::0;;;;;75415:91:0::2;;75478:5;:13;;;75493:5;:12;;;75415:91;;;;;;;;75777:977:::0;53006:23;:21;:23::i;:::-;75923:11;;75911:10:::1;::::0;53944:37:::1;75911:10:::0;75923:11;53944:13:::1;:37::i;:::-;75960:41:::2;75974:5;:11;;;75987:5;:13;;;75960;:41::i;:::-;75952:57;;;;-1:-1:-1::0;;;75952:57:0::2;;;;;;;;;76023:30;;:::i;:::-;76055:17;76078:47;76098:5;:11;;;76111:5;:13;;;76078:19;:47::i;:::-;76022:103;;;;;76142:31;76154:5;:18;;;76142:11;:31::i;:::-;76138:190;;;76190:22;76231:5;:18;;;76250:1;76231:21;;;;;;;;;;;;;;76190:63;;76284:6;-1:-1:-1::0;;;;;76284:22:0::2;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76278:3;:30;76270:46;;;;-1:-1:-1::0;;;76270:46:0::2;;;;;;;;;76138:190;;76344:9;76357:1;76344:14;76340:126;;;76441:12;::::0;::::2;::::0;76424:11:::2;::::0;::::2;::::0;-1:-1:-1;;;;;76407:29:0::2;;::::0;;;:16:::2;:29;::::0;;;;;:47:::2;::::0;::::2;:33;:47;:::i;:::-;76392:11;::::0;::::2;::::0;-1:-1:-1;;;;;76375:29:0::2;;::::0;;;:16:::2;:29;::::0;;;;:79;76340:126:::2;76485:11:::0;;-1:-1:-1;;;;;76478:19:0::2;;::::0;;;:6:::2;:19;::::0;;;;;;;76498:13;;::::2;::::0;76478:34;;;;;;;;;76530:11:::2;::::0;::::2;::::0;76543:12:::2;::::0;::::2;::::0;76557:11:::2;::::0;::::2;::::0;76478:91;;-1:-1:-1;;;76478:91:0;;:51:::2;::::0;::::2;::::0;:91:::2;::::0;:34;;76530:11;;76543:12;;76557:11;76478:91:::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;76582:4:0::2;::::0;76602:11:::2;::::0;::::2;::::0;76615:8:::2;::::0;;::::2;::::0;76625:12:::2;::::0;::::2;::::0;76582:56;;-1:-1:-1;;;76582:56:0;;-1:-1:-1;;;;;76582:4:0;;::::2;::::0;-1:-1:-1;76582:19:0::2;::::0;-1:-1:-1;76582:56:0::2;::::0;76615:8;;76625:12;76582:56:::2;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;76708:5;:8;;;-1:-1:-1::0;;;;;76656:90:0::2;76695:5;:11;;;-1:-1:-1::0;;;;;76656:90:0::2;76682:5;:11;;;-1:-1:-1::0;;;;;76656:90:0::2;;76718:5;:13;;;76733:5;:12;;;76656:90;;;;;;;;;;;;;;;;53994:1;;53042::::1;;75777:977:::0;:::o;31319:512::-;31391:15;;:::i;:::-;31447:26;31427:16;;:46;;;;;;;;;31419:61;;;;-1:-1:-1;;;31419:61:0;;;;;;;;;31499:11;;;;-1:-1:-1;;;;;31499:25:0;31491:40;;;;-1:-1:-1;;;31491:40:0;;;;;;;;77057:676;53006:23;:21;:23::i;:::-;77191:11;;77179:10:::1;::::0;53944:37:::1;77179:10:::0;77191:11;53944:13:::1;:37::i;:::-;77228:41:::2;77242:5;:11;;;77255:5;:13;;;77228;:41::i;:::-;77220:57;;;;-1:-1:-1::0;;;77220:57:0::2;;;;;;;;;77296:9;::::0;77326:12:::2;::::0;::::2;::::0;77296:43:::2;::::0;-1:-1:-1;;;77296:43:0;;-1:-1:-1;;;;;77296:9:0;;::::2;::::0;:29:::2;::::0;:43:::2;::::0;::::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77288:59;;;;-1:-1:-1::0;;;77288:59:0::2;;;;;;;;;77360:22;77401:5;:12;;;77360:54;;77441:6;-1:-1:-1::0;;;;;77441:22:0::2;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77435:3;:30;77427:46;;;;-1:-1:-1::0;;;77427:46:0::2;;;;;;;;;77493:11:::0;;-1:-1:-1;;;;;77486:19:0::2;;::::0;;;:6:::2;:19;::::0;;;;;;;77506:13;;::::2;::::0;77486:34;;;;;;;;;77530:12:::2;::::0;::::2;::::0;77544::::2;::::0;::::2;::::0;77558:11:::2;::::0;::::2;::::0;77486:84;;-1:-1:-1;;;77486:84:0;;:43:::2;::::0;::::2;::::0;:84:::2;::::0;:34;;77530:12;;77544;;77558:11;77486:84:::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;;77601:8:0::2;::::0;;::::2;::::0;77611:12:::2;::::0;::::2;::::0;77583:41;;-1:-1:-1;;;77583:41:0;;-1:-1:-1;;;;;77583:17:0;::::2;::::0;-1:-1:-1;77583:17:0::2;::::0;:41:::2;::::0;77601:8;77583:41:::2;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;77687:5;:8;;;-1:-1:-1::0;;;;;77642:83:0::2;77674:5;:11;;;-1:-1:-1::0;;;;;77642:83:0::2;77660:5;:12;;;-1:-1:-1::0;;;;;77642:83:0::2;;77697:5;:13;;;77712:5;:12;;;77642:83;;;;;;;;32050:514:::0;32122:15;;:::i;:::-;32178:26;32158:16;;:46;;;;;;;;;32150:61;;;;-1:-1:-1;;;32150:61:0;;;;;;;;;32230:11;;;;-1:-1:-1;;;;;32230:25:0;32222:40;;;;-1:-1:-1;;;32222:40:0;;;;;;;;78028:936;53006:23;:21;:23::i;:::-;78162:11;;78150:10:::1;::::0;53944:37:::1;78150:10:::0;78162:11;53944:13:::1;:37::i;:::-;78261:41:::2;78275:5;:11;;;78288:5;:13;;;78261;:41::i;:::-;78253:57;;;;-1:-1:-1::0;;;78253:57:0::2;;;;;;;;;78398:10;::::0;::::2;::::0;-1:-1:-1;;;;;78398:24:0::2;78412:10;78398:24;::::0;78397:57:::2;;;78442:5;:11;;;-1:-1:-1::0;;;;;78428:25:0::2;:5;:10;;;-1:-1:-1::0;;;;;78428:25:0::2;;78397:57;78389:73;;;;-1:-1:-1::0;;;78389:73:0::2;;;;;;;;;78475:22;78516:5;:12;;;78475:54;;78604:6;-1:-1:-1::0;;;;;78604:22:0::2;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78598:3;:30;78590:46;;;;-1:-1:-1::0;;;78590:46:0::2;;;;;;;;;78693:11:::0;;-1:-1:-1;;;;;78686:19:0::2;;::::0;;;:6:::2;:19;::::0;;;;;;;78706:13;;::::2;::::0;78686:34;;;;;;;;;78733:12:::2;::::0;::::2;::::0;78747::::2;::::0;::::2;::::0;78761:11:::2;::::0;::::2;::::0;78686:87;;-1:-1:-1;;;78686:87:0;;:46:::2;::::0;::::2;::::0;:87:::2;::::0;:34;;78733:12;;78747;;78761:11;78686:87:::2;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;;78828:10:0::2;::::0;;::::2;::::0;78840:12:::2;::::0;::::2;::::0;78810:43;;-1:-1:-1;;;78810:43:0;;-1:-1:-1;;;;;78810:17:0;::::2;::::0;-1:-1:-1;78810:17:0::2;::::0;:43:::2;::::0;78828:10;78810:43:::2;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;78916:5;:10;;;-1:-1:-1::0;;;;;78871:85:0::2;78903:5;:11;;;-1:-1:-1::0;;;;;78871:85:0::2;78889:5;:12;;;-1:-1:-1::0;;;;;78871:85:0::2;;78928:5;:13;;;78943:5;:12;;;78871:85;;;;;;;;34539:331:::0;34613:17;;:::i;:::-;34671;34651:16;;:37;;;;;;;;;34643:53;;;;-1:-1:-1;;;34643:53:0;;;;;;;;;34715:19;;;;-1:-1:-1;;;;;34715:33:0;34707:49;;;;-1:-1:-1;;;34707:49:0;;;;;;;;;-1:-1:-1;34776:86:0;;;;;;;;;34798:19;;;;-1:-1:-1;;;;;34776:86:0;;;;;34827:11;;;;34776:86;;;;;34848:12;;;;;34776:86;;;;;34539:331::o;79195:847::-;79306:12;;;;79395:9;;:43;;-1:-1:-1;;;79395:43:0;;-1:-1:-1;;;;;79395:9:0;;;;:29;;:43;;79306:12;;79395:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79387:59;;;;-1:-1:-1;;;79387:59:0;;;;;;;;;79460:18;79480;79500:14;79516;79534:34;79560:6;79534:17;:34::i;:::-;79459:109;;;;;;;;79644:6;79637:3;:13;;79629:29;;;;-1:-1:-1;;;79629:29:0;;;;;;;;;79679:56;79696:10;79708:6;79716:10;79728:6;79679:16;:56::i;:::-;79671:72;;;;-1:-1:-1;;;79671:72:0;;;;;;;;;79756:14;79773:37;79783:5;:12;;;79797:5;:12;;;79773:9;:37::i;:::-;79756:54;;79823:6;-1:-1:-1;;;;;79823:17:0;;79841:10;79853:5;:12;;;79823:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;79879:4:0;;79911:14;;79879:55;;-1:-1:-1;;;79879:55:0;;-1:-1:-1;;;;;79879:4:0;;;;-1:-1:-1;79879:19:0;;-1:-1:-1;79879:55:0;;79899:10;;79911:14;79927:6;;79879:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79985:5;:14;;;-1:-1:-1;;;;;79952:82:0;79973:10;-1:-1:-1;;;;;79952:82:0;79959:5;:12;;;-1:-1:-1;;;;;79952:82:0;;80001:10;80013:5;:12;;;80027:6;79952:82;;;;;;;;;;;;;;;;;79195:847;;;;;;;:::o;35105:398::-;35184:22;;:::i;:::-;35247;35227:16;;:42;;;;;;;;;35219:58;;;;-1:-1:-1;;;35219:58:0;;;;;;;;;35296:11;;;;-1:-1:-1;;;;;35296:25:0;35288:41;;;;-1:-1:-1;;;35288:41:0;;;;;;;;;35348:19;;;;-1:-1:-1;;;;;35348:33:0;35340:49;;;;-1:-1:-1;;;35340:49:0;;;;;;;;;35409:86;;;;;;;;35433:5;:11;;;-1:-1:-1;;;;;35409:86:0;;;;;35455:5;:13;;;35409:86;;;;35474:5;:19;;;-1:-1:-1;;;;;35409:86:0;;;;35402:93;;35105:398;;;:::o;80377:2194::-;80473:11;;80461:10;;53944:37;80461:10;80473:11;53944:13;:37::i;:::-;80505:41:::1;80519:5;:11;;;80532:5;:13;;;80505;:41::i;:::-;80497:57;;;;-1:-1:-1::0;;;80497:57:0::1;;;;;;;;;80568:30;;:::i;:::-;80600:17;80623:47;80643:5;:11;;;80656:5;:13;;;80623:19;:47::i;:::-;80567:103;;;;;80683:22;81021:13:::0;81037:31:::1;81049:5;:18;;;81037:11;:31::i;:::-;81021:47;;81083:12;81098:30;81110:5;:17;;;81098:11;:30::i;:::-;81083:45;;81153:8;:19;;;;81165:7;81153:19;81145:35;;;;-1:-1:-1::0;;;81145:35:0::1;;;;;;;;;81206:8;:89;;81274:5;:17;;;81292:1;81274:20;;;;;;;;;;;;;;81206:89;;;81233:18:::0;;:21;;:18:::1;::::0;:21:::1;;;;;;;;;;81206:89;81197:98;;81316:7;81312:193;;;81344:26;81389:5;:17;;;81407:1;81389:20;;;;;;;;;;;;;;81344:66;;81431:10;-1:-1:-1::0;;;;;81431:21:0::1;;81461:4;;;;;;;;;-1:-1:-1::0;;;;;81461:4:0::1;81468:5;:17;;;81486:1;81468:20;;;;;;;;;;;;;;81431:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;81312:193;;53994:1;;81529:18;81549::::0;81569:14:::1;81585::::0;81603:34:::1;81629:6;81603:17;:34::i;:::-;81528:109;;;;;;;;81728:6;81721:3;:13;;81713:29;;;;-1:-1:-1::0;;;81713:29:0::1;;;;;;;;;81761:56;81778:10;81790:6;81798:10;81810:6;81761:16;:56::i;:::-;81753:72;;;;-1:-1:-1::0;;;81753:72:0::1;;;;;;;;;81876:10;::::0;:48:::1;::::0;-1:-1:-1;;;81876:48:0;;81839:14:::1;::::0;;;-1:-1:-1;;;;;81876:10:0;;::::1;::::0;:30:::1;::::0;:48:::1;::::0;81907:5;;81914:9;;81876:48:::1;;;;;;::::0;::::1;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81838:86;;;;82103:12;82095:28;;;;-1:-1:-1::0;;;82095:28:0::1;;;;;;;;;82143:6;:19;82150:5;:11;;;-1:-1:-1::0;;;;;82143:19:0::1;-1:-1:-1::0;;;;;82143:19:0::1;;;;;;;;;;;;:34;82163:5;:13;;;82143:34;;;;;;;;;;;;82136:41:::0;::::1;;;;;;;:::i;:::-;;;::::0;::::1;;;:::i;:::-;;;::::0;::::1;;;:::i;:::-;;;::::0;::::1;;;:::i;:::-;;;::::0;::::1;;;:::i;:::-;;;::::0;::::1;;;:::i;:::-;;;82194:9;82207:1;82194:14;82190:118;;;-1:-1:-1::0;;;;;82256:28:0;::::1;;::::0;;;:16:::1;:28;::::0;;;;;:40:::1;::::0;82289:6;82256:40:::1;:32;:40;:::i;:::-;-1:-1:-1::0;;;;;82225:28:0;::::1;;::::0;;;:16:::1;:28;::::0;;;;:71;82190:118:::1;82320:4;::::0;82352:8:::1;::::0;;::::1;::::0;82320:49;;-1:-1:-1;;;82320:49:0;;-1:-1:-1;;;;;82320:4:0;;::::1;::::0;:19:::1;::::0;:49:::1;::::0;82340:10;;82352:8;82362:6;;82320:49:::1;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;82382:15;82400:5;:13;;;82382:31;;82424:23;82450:5;:8;;;82424:34;;82553:9;82510:6;-1:-1:-1::0;;;;;82476:87:0::1;82489:5;:11;;;-1:-1:-1::0;;;;;82476:87:0::1;;82519:15;82536:6;82544:7;82476:87;;;;;;;;;;;;;;;;;53994:1;;;;;;;;;;;80377:2194:::0;;;:::o;35511:717::-;35588:20;;:::i;:::-;35649;35629:16;;:40;;;;;;;;;35621:56;;;;-1:-1:-1;;;35621:56:0;;;;;;;;;35696:11;;;;-1:-1:-1;;;;;35696:25:0;35688:41;;;;-1:-1:-1;;;35688:41:0;;;;;;;;;35748:19;;;;-1:-1:-1;;;;;35748:33:0;35740:49;;;;-1:-1:-1;;;35740:49:0;;;;;;;;;35808:5;:10;;;:17;35829:2;35808:23;35800:39;;;;-1:-1:-1;;;35800:39:0;;;;;;;;;35906:15;35935:5;:10;;;35924:33;;;;;;;;;;;;;;35906:51;;35990:230;;;;;;;;36030:5;:11;;;-1:-1:-1;;;;;35990:230:0;;;;;36070:5;:19;;;-1:-1:-1;;;;;35990:230:0;;;;;36117:5;:13;;;35990:230;;;;36157:5;:12;;;35990:230;;;;36197:7;35990:230;;;35970:250;;;35511:717;;;:::o;82773:2409::-;53006:23;:21;:23::i;:::-;82876:41:::1;82890:5;:11;;;82903:5;:13;;;82876;:41::i;:::-;82868:57;;;;-1:-1:-1::0;;;82868:57:0::1;;;;;;;;;83205:30;;:::i;:::-;83237:18;83257:13:::0;83272:22:::1;83298:108;83328:5;:11;;;83354:5;:13;;;83382:5;:13;;;83298:15;:108::i;:::-;83204:202;;;;;;;;83427:13;83419:29;;;;-1:-1:-1::0;;;83419:29:0::1;;;;;;;;;83517:24;83544:32;83572:3;83544:23;83561:5;83544;:12;;;:16;;:23;;;;:::i;:32::-;83517:59;;83810:1;83768:39;83794:5;:12;;;83768:5;:18;;;83787:1;83768:21;;;;;;;;;;;;;;:25;;:39;;;;:::i;:::-;:43;83764:158;;;83888:14;83836:48;83867:16;83836:5;:23;;;83860:1;83836:26;;;;;;;:48;:66;;83828:82;;;;-1:-1:-1::0;;;83828:82:0::1;;;;;;;;;84138:18:::0;;:21;;:18:::1;::::0;:21:::1;;;;;;;;;;-1:-1:-1::0;;;;;84122:49:0::1;;84172:10;84184:5;:12;;;84122:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;84330:11:0;;-1:-1:-1;;;;;84323:19:0::1;;::::0;;;:6:::1;:19;::::0;;;;;;;84343:13;;::::1;::::0;84323:34;;;;;;;;84375:22;;::::1;::::0;:25;;84323:51:::1;::::0;-1:-1:-1;84323:51:0::1;::::0;-1:-1:-1;84323:34:0;;84375:22;;:25:::1;;;;;;;;;;84402:16;84420:1;84323:99;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;84559:11:0;;-1:-1:-1;;;;;84552:19:0::1;;::::0;;;:6:::1;:19;::::0;;;;;;;84572:13;;::::1;::::0;84552:34;;;;;;;84599:18;;:21;;84552:46:::1;::::0;-1:-1:-1;84552:46:0::1;::::0;-1:-1:-1;84552:34:0;;84599:18;;:21:::1;;;;;;;;;;84622:5;:12;;;84636:1;84552:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;84758:65;84806:16;84758;:43;84775:5;:22;;;84798:1;84775:25;;;;;;;;;;;;;;-1:-1:-1::0;;;;;84758:43:0::1;-1:-1:-1::0;;;;;84758:43:0::1;;;;;;;;;;;;;:47;;:65;;;;:::i;:::-;84712:16;:43;84729:5;:22;;;84752:1;84729:25;;;;;;;;;;;;;;-1:-1:-1::0;;;;;84712:43:0::1;-1:-1:-1::0;;;;;84712:43:0::1;;;;;;;;;;;;:111;;;;84836:4;;;;;;;;;-1:-1:-1::0;;;;;84836:4:0::1;-1:-1:-1::0;;;;;84836:19:0::1;;84856:5;:22;;;84879:1;84856:25;;;;;;;;;;;;;;84883:5;:14;;;84899:16;84836:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;85018:5;:11;;;-1:-1:-1::0;;;;;84934:240:0::1;84989:5;:14;;;-1:-1:-1::0;;;;;84934:240:0::1;84964:10;-1:-1:-1::0;;;;;84934:240:0::1;;85044:5;85064;:13;;;85092:16;85123:5;:12;;;85150:5;:13;;;84934:240;;;;;;;;;;;;;;;;;;;53042:1;;;;;82773:2409:::0;:::o;36447:296::-;36519:15;;:::i;:::-;36575;36555:16;;:35;;;;;;;;;36547:51;;;;-1:-1:-1;;;36547:51:0;;;;;;;;;36617:19;;;;-1:-1:-1;;;;;36617:33:0;36609:49;;;;-1:-1:-1;;;36609:49:0;;;;;;;;;-1:-1:-1;36678:57:0;;;;;;;;36696:19;;;;-1:-1:-1;;;;;36678:57:0;;;36723:10;;;;;36678:57;;;;;36447:296::o;85357:263::-;53006:23;:21;:23::i;:::-;85453:12;;54218:14:::1;::::0;-1:-1:-1;;;54218:14:0;::::1;;;54214:91;;;54257:29;54278:7;54257:20;:29::i;:::-;54249:44;;;;-1:-1:-1::0;;;54249:44:0::1;;;;;;;;;85494:12:::0;;85533:10:::2;::::0;::::2;::::0;85478:66:::2;::::0;-1:-1:-1;;;85478:66:0;;-1:-1:-1;;;;;85478:42:0;;::::2;::::0;::::2;::::0;:66:::2;::::0;85521:10:::2;::::0;85533;85478:66:::2;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;85587:5;:12;;;-1:-1:-1::0;;;;;85562:50:0::2;85575:10;-1:-1:-1::0;;;;;85562:50:0::2;;85601:5;:10;;;85562:50;;;;;;;54419:103:::0;54486:21;;-1:-1:-1;;;54486:21:0;;;;54485:22;54477:37;;;;-1:-1:-1;;;54477:37:0;;;;;;;;54872:176;54980:13;-1:-1:-1;;;;;54969:24:0;:7;-1:-1:-1;;;;;54969:24:0;;54968:65;;;-1:-1:-1;;;;;;54999:24:0;;;;;;;:9;:24;;;;;;;;:33;;;;;;;;;;;;54968:65;54960:80;;;;-1:-1:-1;;;54960:80:0;;;;;;;;9398:181;9456:7;9488:5;;;9512:6;;;;9504:46;;;;-1:-1:-1;;;9504:46:0;;;;;;;;85878:187;85965:4;86002:1;85991:8;:12;85990:66;;;;-1:-1:-1;;;;;;;86021:34:0;;;;;;;;:19;:34;;;;;;-1:-1:-1;86009:46:0;;85878:187::o;86073:149::-;86142:4;86183:1;86167:6;:13;:17;86166:48;;;;;86211:1;-1:-1:-1;;;;;86190:23:0;:6;86197:1;86190:9;;;;;;;;;;;;;;-1:-1:-1;;;;;86190:23:0;;;86159:55;86073:149;-1:-1:-1;;86073:149:0:o;9854:136::-;9912:7;9939:43;9943:1;9946;9939:43;;;;;;;;;;;;;;;;;:3;:43::i;86419:140::-;86513:9;;:38;;-1:-1:-1;;;86513:38:0;;86489:4;;-1:-1:-1;;;;;86513:9:0;;:29;;:38;;86543:7;;86513:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10285:226;10405:7;10441:12;10433:6;;;;10425:29;;;;-1:-1:-1;;;10425:29:0;;;;;;;;;;-1:-1:-1;;;10477:5:0;;;10285:226::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;5:130;72:20;;97:33;72:20;97:33;;1356:440;;1457:3;1450:4;1442:6;1438:17;1434:27;1424:2;;-1:-1;;1465:12;1424:2;1512:6;1499:20;76511:18;76503:6;76500:30;76497:2;;;-1:-1;;76533:12;76497:2;1534:64;76606:9;76587:17;;-1:-1;;76583:33;76674:4;76664:15;1534:64;;;1525:73;;1618:6;1611:5;1604:21;1722:3;76674:4;1713:6;1646;1704:16;;1701:25;1698:2;;;1739:1;;1729:12;1698:2;81212:6;76674:4;1646:6;1642:17;76674:4;1680:5;1676:16;81189:30;81268:1;81250:16;;;76674:4;81250:16;81243:27;1680:5;1417:379;-1:-1;;1417:379;1804:160;1886:20;;81992:2;81982:13;;81972:2;;82009:1;;81999:12;3763:241;;3867:2;3855:9;3846:7;3842:23;3838:32;3835:2;;;-1:-1;;3873:12;3835:2;85:6;72:20;97:33;124:5;97:33;;4011:263;;4126:2;4114:9;4105:7;4101:23;4097:32;4094:2;;;-1:-1;;4132:12;4094:2;226:6;220:13;238:33;265:5;238:33;;4281:366;;;4402:2;4390:9;4381:7;4377:23;4373:32;4370:2;;;-1:-1;;4408:12;4370:2;85:6;72:20;97:33;124:5;97:33;;;4460:63;-1:-1;4560:2;4599:22;;72:20;97:33;72:20;97:33;;;4568:63;;;;4364:283;;;;;;4654:617;;;;;4809:3;4797:9;4788:7;4784:23;4780:33;4777:2;;;-1:-1;;4816:12;4777:2;85:6;72:20;97:33;124:5;97:33;;;4868:63;-1:-1;4968:2;5007:22;;72:20;97:33;72:20;97:33;;;4976:63;-1:-1;5076:2;5115:22;;72:20;97:33;72:20;97:33;;;4771:500;;;;-1:-1;5084:63;;5184:2;5223:22;3552:20;;-1:-1;;4771:500;5278:940;;;;;;;5475:3;5463:9;5454:7;5450:23;5446:33;5443:2;;;-1:-1;;5482:12;5443:2;226:6;220:13;238:33;265:5;238:33;;;5645:2;5695:22;;220:13;5534:74;;-1:-1;238:33;220:13;238:33;;;5764:2;5814:22;;220:13;5653:74;;-1:-1;238:33;220:13;238:33;;;5772:74;;;;5883:2;5937:9;5933:22;3700:13;5891:74;;6002:3;6057:9;6053:22;3700:13;6011:74;;6122:3;6174:9;6170:22;1295:13;1313:30;1337:5;1313:30;;;6131:71;;;;5437:781;;;;;;;;;6225:360;;;6343:2;6331:9;6322:7;6318:23;6314:32;6311:2;;;-1:-1;;6349:12;6311:2;85:6;72:20;97:33;124:5;97:33;;;6401:63;-1:-1;6501:2;6537:22;;1153:20;1178:30;1153:20;1178:30;;6592:366;;;6713:2;6701:9;6692:7;6688:23;6684:32;6681:2;;;-1:-1;;6719:12;6681:2;85:6;72:20;97:33;124:5;97:33;;;6771:63;6871:2;6910:22;;;;3552:20;;-1:-1;;;6675:283;6965:491;;;;7103:2;7091:9;7082:7;7078:23;7074:32;7071:2;;;-1:-1;;7109:12;7071:2;85:6;72:20;97:33;124:5;97:33;;;7161:63;7261:2;7300:22;;3552:20;;-1:-1;7369:2;7408:22;;;3552:20;;7065:391;-1:-1;;;7065:391;7463:433;;7620:2;;7608:9;7599:7;7595:23;7591:32;7588:2;;;-1:-1;;7626:12;7588:2;7684:17;7671:31;7722:18;;7714:6;7711:30;7708:2;;;-1:-1;;7744:12;7708:2;7863:6;7852:9;7848:22;464:3;457:4;449:6;445:17;441:27;431:2;;-1:-1;;472:12;431:2;519:6;506:20;492:34;;7722:18;76208:6;76205:30;76202:2;;;-1:-1;;76238:12;76202:2;541:108;7620:2;;76275:6;76271:17;76336:15;541:108;;;677:21;;;734:14;;;;709:17;;;-1:-1;814:261;839:6;836:1;833:13;814:261;;;922:3;909:17;713:6;897:30;2120:6;;76606:9;;897:30;2103:3;2099:19;;2095:32;2092:2;;;-1:-1;;2130:12;2092:2;2158:22;2120:6;2158:22;;;2268:64;2328:3;7620:2;897:30;;2268:64;;;2250:16;2243:90;2428:49;2473:3;2449:22;897:30;2449:22;2428:49;;;7620:2;2414:5;2410:16;2403:75;2602:22;2581:49;2626:3;2602:22;897:30;2602:22;2581:49;;;2449:22;2567:5;2563:16;2556:75;2726:49;2771:3;2747:22;897:30;2747:22;2726:49;;;2602:22;2712:5;2708:16;2701:75;;2895:22;897:30;2895:22;3552:20;2747:22;2860:5;2856:16;2849:75;3042:22;897:30;3042:22;3552:20;2895:22;3007:5;3003:16;2996:75;3188:22;897:30;3188:22;3552:20;3042:22;3153:5;3149:16;3142:75;2120:6;897:30;3291:19;3278:33;7722:18;3323:6;3320:30;3317:2;;;-1:-1;;3353:12;3317:2;3398:58;3452:3;7620:2;3443:6;897:30;3428:22;;3398:58;;;3188:22;3380:16;;3373:84;-1:-1;934:78;;-1:-1;;1026:14;;;;1054;;;;861:1;854:9;814:261;;;-1:-1;7764:116;;7582:314;-1:-1;;;;;;;;;7582:314;7903:235;;8004:2;7992:9;7983:7;7979:23;7975:32;7972:2;;;-1:-1;;8010:12;7972:2;1166:6;1153:20;1178:30;1202:5;1178:30;;8145:257;;8257:2;8245:9;8236:7;8232:23;8228:32;8225:2;;;-1:-1;;8263:12;8225:2;1301:6;1295:13;1313:30;1337:5;1313:30;;8409:529;;;;8555:2;8543:9;8534:7;8530:23;8526:32;8523:2;;;-1:-1;;8561:12;8523:2;1301:6;1295:13;1313:30;1337:5;1313:30;;;8721:2;8771:22;;3700:13;8840:2;8890:22;;;3700:13;8613:71;;3700:13;;-1:-1;3700:13;8517:421;-1:-1;;;8517:421;8945:263;;9060:2;9048:9;9039:7;9035:23;9031:32;9028:2;;;-1:-1;;9066:12;9028:2;-1:-1;3700:13;;9022:186;-1:-1;9022:186;9215:393;;;9344:2;9332:9;9323:7;9319:23;9315:32;9312:2;;;-1:-1;;9350:12;9312:2;3706:6;3700:13;9402:74;;9513:2;9564:9;9560:22;1295:13;1313:30;1337:5;1313:30;;10661:670;;10844:5;77115:12;77908:6;77903:3;77896:19;77945:4;;77940:3;77936:14;10856:83;;77945:4;11010:5;76811:14;-1:-1;11049:260;11074:6;11071:1;11068:13;11049:260;;;11135:13;;-1:-1;;;;;78842:54;10215:45;;9769:14;;;;77646;;;;76511:18;11089:9;11049:260;;;-1:-1;11315:10;;10775:556;-1:-1;;;;;10775:556;11370:670;;11553:5;77115:12;77908:6;77903:3;77896:19;77945:4;;77940:3;77936:14;11565:83;;77945:4;11719:5;76811:14;-1:-1;11758:260;11783:6;11780:1;11777:13;11758:260;;;11844:13;;36747:18;;9951:14;;;;77646;;;;11805:1;11798:9;11758:260;;12159:343;;12301:5;77115:12;77908:6;77903:3;77896:19;-1:-1;81357:101;81371:6;81368:1;81365:13;81357:101;;;77945:4;81438:11;;;;;81432:18;81419:11;;;;;81412:39;81386:10;81357:101;;;81473:6;81470:1;81467:13;81464:2;;;-1:-1;77945:4;81529:6;77940:3;81520:16;;81513:27;81464:2;-1:-1;76606:9;81629:14;-1:-1;;81625:28;12458:39;;;;77945:4;12458:39;;12249:253;-1:-1;;12249:253;34842:1796;;35067:16;35061:23;34987:4;35104:14;35097:38;35150:103;34987:4;34982:3;34978:14;35234:12;35150:103;;;35345:4;35338:5;35334:16;35328:23;35308:43;;35397:3;35391:4;35387:14;35345:4;35375:3;35371:14;35364:38;35417:103;35515:4;35501:12;35417:103;;;35617:4;35610:5;35606:16;35600:23;35580:43;;35669:3;35663:4;35659:14;35617:4;35647:3;35643:14;35636:38;35689:103;35787:4;35773:12;35689:103;;;35681:111;;;35885:4;35878:5;35874:16;35868:23;35848:43;;35937:3;35931:4;35927:14;35885:4;35915:3;35911:14;35904:38;35957:103;36055:4;36041:12;35957:103;;;36152:4;36145:5;36141:16;36135:23;36115:43;;36204:3;36198:4;36194:14;36152:4;36182:3;36178:14;36171:38;36224:103;36322:4;36308:12;36224:103;;;36216:111;;;36425:4;36418:5;36414:16;36408:23;36388:43;;36477:3;36471:4;36467:14;36425:4;36455:3;36451:14;36444:38;36497:103;36595:4;36581:12;36497:103;;37135:222;-1:-1;;;;;78842:54;;;;10215:45;;37262:2;37247:18;;37233:124;37364:449;-1:-1;;;;;78842:54;;10215:45;;37553:2;37687;37672:18;;37665:48;;;37364:449;;37727:76;;37538:18;;37789:6;37727:76;;;37719:84;37524:289;-1:-1;;;;37524:289;37820:349;-1:-1;;;;;78842:54;;;;10058:58;;38155:2;38140:18;;36747;37983:2;37968:18;;37954:215;38176:460;-1:-1;;;;;78842:54;;;10215:45;;78842:54;;;;38539:2;38524:18;;10058:58;38622:2;38607:18;;36747;;;;38367:2;38352:18;;38338:298;38643:556;-1:-1;;;;;78842:54;;;10215:45;;78842:54;;;39019:2;39004:18;;10215:45;78842:54;;;39102:2;39087:18;;10215:45;78842:54;;;39185:2;39170:18;;10215:45;38854:3;38839:19;;38825:374;39997:444;-1:-1;;;;;78842:54;;;;10215:45;;40344:2;40329:18;;36747;;;;40427:2;40412:18;;36747;40180:2;40165:18;;40151:290;40448:210;78754:13;;78747:21;12113:34;;40569:2;40554:18;;40540:118;40665:432;78754:13;;78747:21;12113:34;;41000:2;40985:18;;36747;;;;41083:2;41068:18;;36747;40842:2;40827:18;;40813:284;41104:306;;41249:2;41270:17;41263:47;41324:76;41249:2;41238:9;41234:18;41386:6;41324:76;;43163:416;43363:2;43377:47;;;14194:1;43348:18;;;77896:19;-1:-1;;;77936:14;;;14209:25;14253:12;;;43334:245;43586:416;43786:2;43800:47;;;14504:1;43771:18;;;77896:19;-1:-1;;;77936:14;;;14519:26;14564:12;;;43757:245;44009:416;44209:2;44223:47;;;14815:1;44194:18;;;77896:19;-1:-1;;;77936:14;;;14830:26;14875:12;;;44180:245;44432:416;44632:2;44646:47;;;15126:1;44617:18;;;77896:19;-1:-1;;;77936:14;;;15141:26;15186:12;;;44603:245;44855:416;45055:2;45069:47;;;15437:1;45040:18;;;77896:19;-1:-1;;;77936:14;;;15452:26;15497:12;;;45026:245;45278:416;45478:2;45492:47;;;15748:1;45463:18;;;77896:19;-1:-1;;;77936:14;;;15763:26;15808:12;;;45449:245;45701:416;45901:2;45915:47;;;16059:1;45886:18;;;77896:19;-1:-1;;;77936:14;;;16074:26;16119:12;;;45872:245;46124:416;46324:2;46338:47;;;16370:1;46309:18;;;77896:19;-1:-1;;;77936:14;;;16385:25;16429:12;;;46295:245;46547:416;46747:2;46761:47;;;16680:1;46732:18;;;77896:19;-1:-1;;;77936:14;;;16695:26;16740:12;;;46718:245;46970:416;47170:2;47184:47;;;16991:2;47155:18;;;77896:19;17027:34;77936:14;;;17007:55;-1:-1;;;17082:12;;;17075:30;17124:12;;;47141:245;47393:416;47593:2;47607:47;;;17375:1;47578:18;;;77896:19;-1:-1;;;77936:14;;;17390:25;17434:12;;;47564:245;47816:416;48016:2;48030:47;;;17685:1;48001:18;;;77896:19;-1:-1;;;77936:14;;;17700:26;17745:12;;;47987:245;48239:416;48439:2;48453:47;;;17996:2;48424:18;;;77896:19;18032:29;77936:14;;;18012:50;18081:12;;;48410:245;48662:416;48862:2;48876:47;;;18332:1;48847:18;;;77896:19;-1:-1;;;77936:14;;;18347:26;18392:12;;;48833:245;49085:416;49285:2;49299:47;;;18643:1;49270:18;;;77896:19;-1:-1;;;77936:14;;;18658:26;18703:12;;;49256:245;49508:416;49708:2;49722:47;;;18954:1;49693:18;;;77896:19;-1:-1;;;77936:14;;;18969:26;19014:12;;;49679:245;49931:416;50131:2;50145:47;;;19265:1;50116:18;;;77896:19;-1:-1;;;77936:14;;;19280:26;19325:12;;;50102:245;50354:416;50554:2;50568:47;;;19576:1;50539:18;;;77896:19;-1:-1;;;77936:14;;;19591:25;19635:12;;;50525:245;50777:416;50977:2;50991:47;;;19886:1;50962:18;;;77896:19;-1:-1;;;77936:14;;;19901:26;19946:12;;;50948:245;51200:416;51400:2;51414:47;;;20197:1;51385:18;;;77896:19;-1:-1;;;77936:14;;;20212:26;20257:12;;;51371:245;51623:416;51823:2;51837:47;;;20508:1;51808:18;;;77896:19;-1:-1;;;77936:14;;;20523:26;20568:12;;;51794:245;52046:416;52246:2;52260:47;;;20819:1;52231:18;;;77896:19;-1:-1;;;77936:14;;;20834:25;20878:12;;;52217:245;52469:416;52669:2;52683:47;;;21129:1;52654:18;;;77896:19;-1:-1;;;77936:14;;;21144:25;21188:12;;;52640:245;52892:416;53092:2;53106:47;;;21439:1;53077:18;;;77896:19;-1:-1;;;77936:14;;;21454:26;21499:12;;;53063:245;53315:416;53515:2;53529:47;;;21750:1;53500:18;;;77896:19;-1:-1;;;77936:14;;;21765:26;21810:12;;;53486:245;53738:416;53938:2;53952:47;;;22061:1;53923:18;;;77896:19;-1:-1;;;77936:14;;;22076:26;22121:12;;;53909:245;54161:416;54361:2;54375:47;;;22372:1;54346:18;;;77896:19;-1:-1;;;77936:14;;;22387:26;22432:12;;;54332:245;54584:416;54784:2;54798:47;;;22683:1;54769:18;;;77896:19;-1:-1;;;77936:14;;;22698:26;22743:12;;;54755:245;55007:416;55207:2;55221:47;;;22994:1;55192:18;;;77896:19;-1:-1;;;77936:14;;;23009:26;23054:12;;;55178:245;55430:416;55630:2;55644:47;;;23305:1;55615:18;;;77896:19;-1:-1;;;77936:14;;;23320:25;23364:12;;;55601:245;55853:416;56053:2;56067:47;;;23615:1;56038:18;;;77896:19;-1:-1;;;77936:14;;;23630:26;23675:12;;;56024:245;56276:416;56476:2;56490:47;;;23926:1;56461:18;;;77896:19;-1:-1;;;77936:14;;;23941:26;23986:12;;;56447:245;56699:416;56899:2;56913:47;;;24237:1;56884:18;;;77896:19;-1:-1;;;77936:14;;;24252:26;24297:12;;;56870:245;57122:416;57322:2;57336:47;;;24548:1;57307:18;;;77896:19;-1:-1;;;77936:14;;;24563:26;24608:12;;;57293:245;57545:416;57745:2;57759:47;;;24859:1;57730:18;;;77896:19;-1:-1;;;77936:14;;;24874:25;24918:12;;;57716:245;57968:416;58168:2;58182:47;;;25169:1;58153:18;;;77896:19;-1:-1;;;77936:14;;;25184:26;25229:12;;;58139:245;58391:416;58591:2;58605:47;;;25480:2;58576:18;;;77896:19;25516:34;77936:14;;;25496:55;-1:-1;;;25571:12;;;25564:25;25608:12;;;58562:245;58814:416;59014:2;59028:47;;;25859:1;58999:18;;;77896:19;-1:-1;;;77936:14;;;25874:26;25919:12;;;58985:245;59237:416;59437:2;59451:47;;;59422:18;;;77896:19;26206:34;77936:14;;;26186:55;26260:12;;;59408:245;59660:416;59860:2;59874:47;;;26511:1;59845:18;;;77896:19;-1:-1;;;77936:14;;;26526:26;26571:12;;;59831:245;60083:416;60283:2;60297:47;;;26822:2;60268:18;;;77896:19;26858:34;77936:14;;;26838:55;-1:-1;;;26913:12;;;26906:38;26963:12;;;60254:245;60506:416;60706:2;60720:47;;;27214:1;60691:18;;;77896:19;-1:-1;;;77936:14;;;27229:26;27274:12;;;60677:245;60929:416;61129:2;61143:47;;;27525:1;61114:18;;;77896:19;-1:-1;;;77936:14;;;27540:26;27585:12;;;61100:245;61352:416;61552:2;61566:47;;;27836:1;61537:18;;;77896:19;-1:-1;;;77936:14;;;27851:26;27896:12;;;61523:245;61775:416;61975:2;61989:47;;;28147:1;61960:18;;;77896:19;-1:-1;;;77936:14;;;28162:26;28207:12;;;61946:245;62198:416;62398:2;62412:47;;;28458:1;62383:18;;;77896:19;-1:-1;;;77936:14;;;28473:26;28518:12;;;62369:245;62621:416;62821:2;62835:47;;;28769:1;62806:18;;;77896:19;-1:-1;;;77936:14;;;28784:26;28829:12;;;62792:245;63044:416;63244:2;63258:47;;;29080:1;63229:18;;;77896:19;-1:-1;;;77936:14;;;29095:25;29139:12;;;63215:245;63467:416;63667:2;63681:47;;;29390:1;63652:18;;;77896:19;-1:-1;;;77936:14;;;29405:25;29449:12;;;63638:245;63890:416;64090:2;64104:47;;;29700:1;64075:18;;;77896:19;-1:-1;;;77936:14;;;29715:26;29760:12;;;64061:245;64313:416;64513:2;64527:47;;;30011:1;64498:18;;;77896:19;-1:-1;;;77936:14;;;30026:25;30070:12;;;64484:245;64736:416;64936:2;64950:47;;;30321:1;64921:18;;;77896:19;-1:-1;;;77936:14;;;30336:26;30381:12;;;64907:245;65159:416;65359:2;65373:47;;;30632:1;65344:18;;;77896:19;-1:-1;;;77936:14;;;30647:26;30692:12;;;65330:245;65582:416;65782:2;65796:47;;;30943:1;65767:18;;;77896:19;-1:-1;;;77936:14;;;30958:26;31003:12;;;65753:245;66005:416;66205:2;66219:47;;;31254:1;66190:18;;;77896:19;-1:-1;;;77936:14;;;31269:26;31314:12;;;66176:245;66428:416;66628:2;66642:47;;;31565:1;66613:18;;;77896:19;-1:-1;;;77936:14;;;31580:25;31624:12;;;66599:245;66851:416;67051:2;67065:47;;;31875:1;67036:18;;;77896:19;-1:-1;;;77936:14;;;31890:25;31934:12;;;67022:245;67274:416;67474:2;67488:47;;;32185:1;67459:18;;;77896:19;-1:-1;;;77936:14;;;32200:25;32244:12;;;67445:245;67697:416;67897:2;67911:47;;;32495:1;67882:18;;;77896:19;-1:-1;;;77936:14;;;32510:26;32555:12;;;67868:245;68120:416;68320:2;68334:47;;;32806:1;68305:18;;;77896:19;-1:-1;;;77936:14;;;32821:25;32865:12;;;68291:245;68543:416;68743:2;68757:47;;;33116:1;68728:18;;;77896:19;-1:-1;;;77936:14;;;33131:26;33176:12;;;68714:245;68966:416;69166:2;69180:47;;;33427:1;69151:18;;;77896:19;-1:-1;;;77936:14;;;33442:26;33487:12;;;69137:245;69389:416;69589:2;69603:47;;;33738:2;69574:18;;;77896:19;33774:33;77936:14;;;33754:54;33827:12;;;69560:245;69812:416;70012:2;70026:47;;;34078:1;69997:18;;;77896:19;-1:-1;;;77936:14;;;34093:25;34137:12;;;69983:245;70235:416;70435:2;70449:47;;;34388:1;70420:18;;;77896:19;-1:-1;;;77936:14;;;34403:25;34447:12;;;70406:245;70658:416;70858:2;70872:47;;;34698:1;70843:18;;;77896:19;-1:-1;;;77936:14;;;34713:25;34757:12;;;70829:245;71081:358;;71252:2;71273:17;71266:47;71327:102;71252:2;71241:9;71237:18;71415:6;71327:102;;71446:469;;71645:2;71666:17;71659:47;71720:102;71645:2;71634:9;71630:18;71808:6;71720:102;;;71712:110;;36759:5;71901:2;71890:9;71886:18;36747;71616:299;;;;;;71922:580;;72149:2;72170:17;72163:47;72224:102;72149:2;72138:9;72134:18;72312:6;72224:102;;;72405:2;72390:18;;36747;;;;-1:-1;72488:2;72473:18;36747;72216:110;72120:382;-1:-1;72120:382;72509:692;;72764:3;72786:17;72779:47;72840:102;72764:3;72753:9;72749:19;72928:6;72840:102;;;73021:2;73006:18;;36747;;;;-1:-1;73104:2;73089:18;;36747;;;;73187:2;73172:18;;;36747;72832:110;72735:466;-1:-1;72735:466;73208:658;36747:18;;;-1:-1;;;;;78842:54;;;;73662:2;73647:18;;10215:45;73753:2;73738:18;;36747;73852:2;73837:18;;13545:58;73458:3;73443:19;;73429:437;74522:222;36747:18;;;74649:2;74634:18;;74620:124;74751:333;36747:18;;;75070:2;75055:18;;36747;74906:2;74891:18;;74877:207;75091:668;36747:18;;;75495:2;75480:18;;36747;;;;75578:2;75563:18;;36747;;;;75661:2;75646:18;;36747;75744:3;75729:19;;36747:18;75330:3;75315:19;;75301:458;75766:256;75828:2;75822:9;75854:17;;;75929:18;75914:34;;75950:22;;;75911:62;75908:2;;;75986:1;;75976:12;75908:2;75828;75995:22;75806:216;;-1:-1;75806:216;81666:117;-1:-1;;;;;78842:54;;81725:35;;81715:2;;81774:1;;81764:12;81790:111;81871:5;78754:13;78747:21;81849:5;81846:32;81836:2;;81892:1;;81882:12

Swarm Source

ipfs://a7e19740a045ca277745868a9ac88b87f050c6954895e10f38c411c53312ad6f

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.