Contract 0xB7b4270cFD938F4F1C111ac819e7365E8Ce0300a 1

 
Txn Hash Method
Index
From
To
Value
0xe2609c7ce80a77f587dbbdb04137eafba6aad290105e0d4174c7c1783f77d0d0Initiate Withdra...261002582022-09-28 21:55:5756 secs ago0x0eff12a3469b90bc6bec4a42bc826d8052adc1f5 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0001340622170.00100155
0x266f1940a61470e1239d871d901f30402b0388b25e73343bc2acdaa35980da8cInitiate Deposit260982222022-09-28 21:40:2616 mins ago0x5c8b4e451f85f37c269e57290f91303e2fe3a631 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000414141760.00100155
0xe4b887c7b1c69bd25633df96ba0fd745163d2b0a5b9212845d8e2a52ef3c062fInitiate Deposit260958722022-09-28 21:21:5634 mins ago0xba6d9cfe93232caf24fc2fb64c887b45869b8e0a IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000442355210.00100155
0x2e79f287f198e4d43d1e634e4c94a208bade1b454a1f51bbdc4a193c296cf708Initiate Deposit260957722022-09-28 21:21:0935 mins ago0xdde7e64836a7323634c09fc6234eb8f1062d2eb0 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000492492480.00100155
0x98bec4296cb00de37d63f65a90a378106b3a1e69d30ade8eb3d5483048633d75Initiate Deposit260957192022-09-28 21:20:3936 mins ago0x5920741c7b50475168514e1812e0acac14cd1843 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000492492480.00100155
0x5a9a7437b20ae131ac546e36fc219ddb693a98d752476a31e3efa1584b16f4c7Initiate Deposit260956322022-09-28 21:19:5436 mins ago0x2ce2d1db6ef600ecd3d8b60b6f5b487e85fbc86c IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000491156360.00100155
0x984c60bf586dd6a2c70aa01e2057ec42dfd4f8bc402696e7b5d30b053d92fa7fInitiate Deposit260956152022-09-28 21:19:3937 mins ago0x9fe5b6f30dad62df6807f34539257e3a98537ec3 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.000049293770.00100155
0x1716ca9d8dae61f077138544579bf618464ddea6ad27839c38cd8d099d09c3feInitiate Deposit260954802022-09-28 21:18:3838 mins ago0x94dc4cb418cd4d9f919fe7ed25f4241eef16102d IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000492492480.00100155
0x2d39b4bac160c596e007f7f6b65bdc07c4aaa510d7467c46ac3d3b723e673122Initiate Deposit260952092022-09-28 21:16:2240 mins ago0x05cd21e678f9cb8f69816eb550caa5e4adaeb6ae IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000520134770.00100155
0x316ff3644ebe34c91d55e7c087b9c0560d0c49f1ba4804aaf3fcaa0852dd8383Initiate Deposit260950792022-09-28 21:14:5242 mins ago0xacbc9cf397799a52b9507d3b814d88518a35c82f IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.000059315840.00100155
0x8fc7b25a51a79935e429446e1ad639fe00ac08aaff1c0dab42968e3327ee0aa9Initiate Deposit260949912022-09-28 21:13:5243 mins ago0xac9ea0e0aed6ea8d8bf0376eef82e6e54d89f7a8 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.000059315840.00100155
0xbe732f5034d198d54b93d935002dba0c5669e5d699cbc486dba906cb2f9fe290Initiate Deposit260948652022-09-28 21:12:5144 mins ago0xd77316d490f5653174f8ae9ebd1f5eb1b01b75c1 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000692288820.00100155
0x6a17d1a9150418de4299170b5b60f85eac80e6f07c9490ee824845ae06de8678Initiate Deposit260947962022-09-28 21:12:2144 mins ago0xdff6d40f698876469c74244ad848066c217f72c0 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000692288820.00100155
0x8bf84b7f47b6911e9be0f1162e303069d1c5669c703ecc3218f685bd6cd8eb75Initiate Deposit260946162022-09-28 21:10:4946 mins ago0x8a3e96ee03bed8eecf9791cf946262658e7dcfc8 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000692244150.00100155
0x2bef283142d3848868c243d11a961902fececd5e427d2dd44392ba33b9245ae2Initiate Deposit260944902022-09-28 21:09:3347 mins ago0xd3dd81e990040e64920b1f3f60be65c26c1898cc IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.000077887810.00100155
0x878a3fa5cbe073526853b12c64d6609d84a3d08fb8b0537b5c29bf2b2c2c7408Initiate Deposit260943442022-09-28 21:08:1548 mins ago0x28ba21ef72861de18533bfcd1e23da9ce38b2735 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000790555930.00100155
0x45e84cbc334675be73054cdfceec7b4b8174b9da5ba6f5b3576a973d8b4cbd36Initiate Deposit260941882022-09-28 21:06:5949 mins ago0x5c00b21be9040941e8156bd4f23dbce7ea9fc045 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000788407640.00100155
0xfcfc381a2d56823890d171217613868f6b114b3b0f827af517a0369108229a6eInitiate Deposit260940102022-09-28 21:05:5750 mins ago0xd76236988ebb37ee9df5db30416a6724b04ec066 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000790555930.00100155
0xfa31aa8e93c052789e2ad527826d954ef1543c6247c761ac2a72a086288d5fc2Initiate Deposit260938332022-09-28 21:04:4152 mins ago0xde818155e2925346207e1fb90b9eea09ded40b42 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000786809610.00100155
0x2757c38619ac93a78d951a4be3101d30129e1fd900c1f53162f72fb71d00250aInitiate Deposit260937102022-09-28 21:03:2653 mins ago0xda91066aace5be94d370d22088d733a4107716fe IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000786809610.00100155
0x549bda2d55a53825c812f072c2bf161a598d88056d38d835c06081cefbdd185cInitiate Deposit260935352022-09-28 21:01:5554 mins ago0xcf1f050deaaae94432b33feb885f66cef2156867 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000786809610.00100155
0xaa991fe1d7be0ceaa19ea7f08f5ec25d491c1ec3a4665e0a9defe17f05c7f235Initiate Deposit260934822022-09-28 21:01:4055 mins ago0x9ed58beaf01781712b8c157288a884a1e64cb835 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000879218310.00100155
0x7390892fbc44a931892c5acda5a59ff59458bd288b277f81b037abf0e2625a18Initiate Deposit260933772022-09-28 21:00:3956 mins ago0x7e033b94ea46646484d25028dad6288934ceaeda IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000561384110.00100155
0x2079d8a111563600ca9c55e4df86c8651bf059f4273a1a2fc423443cb05a24b7Process Deposit ...260933062022-09-28 21:00:0956 mins ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000521397630.00100155
0x4a9d139793773c9817e55b8983e5b6ae1b80cf3c267ea2c11f6018a159a17817Initiate Deposit260932052022-09-28 20:59:2357 mins ago0x65b38802f7918f8cf04208de9f41ff95d954fb4a IN  0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a0 Ether0.0000494731130.00100155
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xb2deec830861b7fe8bd7027330aa826d33def9316f61eb29ddbdbfcbbd26354b260149362022-09-28 13:49:568 hrs 6 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0x65243f54fa63a9bab8eca39e7a42e3b1fe3928e17cc6918d852cc3cfd52645cb260138092022-09-28 13:46:418 hrs 10 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0xf00f039ca5b4e8278f6e99dc7734252e4044bc71ed168ad8d7909f76ea337429260125422022-09-28 13:42:268 hrs 14 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0x92b9c514e9799b9d758570818fb607b772ef48995d4abae76a747c7f37e60227260116492022-09-28 13:39:268 hrs 17 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0x818b20b4b5ddeb10806103713a1b7fe5d7c3de0e6c7308a844137e322d02359b260115482022-09-28 13:38:568 hrs 17 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0x33085bb354630662462a07b7e35260b7cbd878b7688951e6a44e1d6a9c0a5259260108042022-09-28 13:36:118 hrs 20 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0xe4c3d31e81bf9af44a1d1b58aa9a01c6dd12767195a525948c23fd4199f5c12e260105722022-09-28 13:35:418 hrs 21 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0x94f4fe21969027dd77e3aa13a2e56f7d99fa8496b696e62decc5f2ea5e425f35260104092022-09-28 13:34:568 hrs 21 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0x00cc1fbc904b8ca55ccc2b9913bbb94b0a844a35504206c707cc0879347eb914260100272022-09-28 13:33:568 hrs 22 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0x681e84fb8864be2dfd2d23750be9bf99231bb5ff9c50f087bf332f1bdf3553a2260095412022-09-28 13:31:568 hrs 24 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0x85638a9995a0933507f01cd5a4ad6e3b36de52aeefabc247d01d0c50150c81da260094222022-09-28 13:31:418 hrs 25 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0xedf8af34c723fbac5ce2acb31675e5250eeb38deb75a5930805dd27f4ad7656a260092842022-09-28 13:31:268 hrs 25 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0xe23fd6f6325db3d102fb9e4520685ff6b5b05c7f31177ac8758fac7e108c62a1260092372022-09-28 13:31:118 hrs 25 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0x74d568c4ba21347a2b404a384e4285b0167981dfd1f2a7edee2883fa0bae0005260091442022-09-28 13:30:568 hrs 25 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0xbda13edbb82ed8f8afbf271917ac0a2d487a7e4a4b09a0ec6cc14363387b04dc260089362022-09-28 13:30:268 hrs 26 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0x6cc73ff277a8b1c152fdf1fe12e6f86c15d0773fe6e5b593df81d988168f382b260086392022-09-28 13:29:268 hrs 27 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0x27d3e87e5825ffc20c1a35d71acae9fae9cb7dfafbc31f121f54d00024a321fc260085302022-09-28 13:28:568 hrs 27 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0xc13ea496a0dfe5c2ffba6c48cdccc028bd350a32fcfd1a069d743bcb9953bcbc260084422022-09-28 13:28:418 hrs 28 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0xc00891a071db254c5784d12e5b49bcaf46a9af0d0993120952cd5b8bddb4884e260083792022-09-28 13:28:268 hrs 28 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0xa929f691cab0778a0f237733f3a2c3af09a851e7c4a5c55655c836deb9933fd9260081642022-09-28 13:27:108 hrs 29 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0x538f007e76909378a02afa7ec3eb4bdd9f106e4b3988b24543458c02d05caa40260079862022-09-28 13:26:258 hrs 30 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0xde991ff754a3f3eb09a162948cd31ca750aeb31aa4d6617b8a53508e2b15c157260079562022-09-28 13:26:108 hrs 30 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0xc4109c391224619e49ba366bcc04546603f6eb3bf5fb0ebbef83ac0b468cbe80260077582022-09-28 13:25:108 hrs 31 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
0x4de9cd837d1bef2839b4653e39c04aa231fe09fb9c5fcd461eef90faeafc7209260077422022-09-28 13:24:558 hrs 31 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300aSynthetix: sUSD Token0 Ether
0x5642120d661cd9c8b7d3ea9f752e85f3fad561087ea0e7a7a26895368694173b260076212022-09-28 13:24:408 hrs 32 mins ago 0xb7b4270cfd938f4f1c111ac819e7365e8ce0300a 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60 Ether
[ Download CSV Export 
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
CallSellingQuoteVault

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Optimistic.Etherscan.io on 2022-09-02
*/

// Sources flattened with hardhat v2.9.6 https://hardhat.org

// File @rari-capital/solmate/src/auth/[email protected]

// -License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
abstract contract Auth {
    event OwnerUpdated(address indexed user, address indexed newOwner);

    event AuthorityUpdated(address indexed user, Authority indexed newAuthority);

    address public owner;

    Authority public authority;

    constructor(address _owner, Authority _authority) {
        owner = _owner;
        authority = _authority;

        emit OwnerUpdated(msg.sender, _owner);
        emit AuthorityUpdated(msg.sender, _authority);
    }

    modifier requiresAuth() virtual {
        require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED");

        _;
    }

    function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) {
        Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas.

        // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be
        // aware that this makes protected functions uncallable even to the owner if the authority is out of order.
        return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner;
    }

    function setAuthority(Authority newAuthority) public virtual {
        // We check if the caller is the owner first because we want to ensure they can
        // always swap out the authority even if it's reverting or using up a lot of gas.
        require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig));

        authority = newAuthority;

        emit AuthorityUpdated(msg.sender, newAuthority);
    }

    function setOwner(address newOwner) public virtual requiresAuth {
        owner = newOwner;

        emit OwnerUpdated(msg.sender, newOwner);
    }
}

/// @notice A generic interface for a contract which provides authorization data to an Auth instance.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
interface Authority {
    function canCall(
        address user,
        address target,
        bytes4 functionSig
    ) external view returns (bool);
}


// File @rari-capital/solmate/src/tokens/[email protected]

// -License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}


// File @rari-capital/solmate/src/utils/[email protected]

// -License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // Divide z by the denominator.
            z := div(z, denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // First, divide z - 1 by the denominator and add 1.
            // We allow z - 1 to underflow if z is 0, because we multiply the
            // end result by 0 if z is zero, ensuring we return 0 if z is zero.
            z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        assembly {
            // Start off with z at 1.
            z := 1

            // Used below to help find a nearby power of 2.
            let y := x

            // Find the lowest power of 2 that is at least sqrt(x).
            if iszero(lt(y, 0x100000000000000000000000000000000)) {
                y := shr(128, y) // Like dividing by 2 ** 128.
                z := shl(64, z) // Like multiplying by 2 ** 64.
            }
            if iszero(lt(y, 0x10000000000000000)) {
                y := shr(64, y) // Like dividing by 2 ** 64.
                z := shl(32, z) // Like multiplying by 2 ** 32.
            }
            if iszero(lt(y, 0x100000000)) {
                y := shr(32, y) // Like dividing by 2 ** 32.
                z := shl(16, z) // Like multiplying by 2 ** 16.
            }
            if iszero(lt(y, 0x10000)) {
                y := shr(16, y) // Like dividing by 2 ** 16.
                z := shl(8, z) // Like multiplying by 2 ** 8.
            }
            if iszero(lt(y, 0x100)) {
                y := shr(8, y) // Like dividing by 2 ** 8.
                z := shl(4, z) // Like multiplying by 2 ** 4.
            }
            if iszero(lt(y, 0x10)) {
                y := shr(4, y) // Like dividing by 2 ** 4.
                z := shl(2, z) // Like multiplying by 2 ** 2.
            }
            if iszero(lt(y, 0x8)) {
                // Equivalent to 2 ** z.
                z := shl(1, z)
            }

            // Shifting right by 1 is like dividing by 2.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // Compute a rounded down version of z.
            let zRoundDown := div(x, z)

            // If zRoundDown is smaller, use it.
            if lt(zRoundDown, z) {
                z := zRoundDown
            }
        }
    }
}


// File @rari-capital/solmate/src/utils/[email protected]

// -License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 private locked = 1;

    modifier nonReentrant() virtual {
        require(locked == 1, "REENTRANCY");

        locked = 2;

        _;

        locked = 1;
    }
}


// File @rari-capital/solmate/src/utils/[email protected]

// -License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
            mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}


// File contracts/utils/Pausable.sol

// -License-Identifier: MIT
pragma solidity 0.8.9;

abstract contract Pausable {

    bool private _paused;
    bool private _depositsPaused;

    constructor() {
        _paused = false;
        _depositsPaused = false;
    }

    function paused() public view virtual returns (bool) {
        return _paused;
    }

    function depositsPaused() public view virtual returns (bool) {
        return _depositsPaused;
    }

    modifier whenNotPaused() {
        if (paused()) {
            revert Paused();
        }
        _;
    }

    modifier whenPaused() {
        if (!paused()) {
            revert NotPaused();
        }
        _;
    }

    modifier whenDepositsNotPaused() {
        if(depositsPaused()) {
            revert DepositsPaused();
        }
        _;
    }

    modifier whenDepositsPaused() {
        if (!depositsPaused()) {
            revert DepositsNotPaused();
        }
        _;
    }

    function _pause() internal virtual whenNotPaused {
        _paused = true;
        _depositsPaused = true;
        emit SetPaused(msg.sender);
    }

    function _pauseDeposits() internal virtual whenDepositsNotPaused {
        _depositsPaused = true;
        emit SetDepositsPaused(msg.sender);
    }

    function _unpause() internal virtual whenPaused {
        _paused = false;
        _depositsPaused = false;
        emit SetUnpaused(msg.sender);
    }

    function _unpauseDeposits() internal virtual whenDepositsPaused {
        _depositsPaused = false;
        emit SetDepositsUnpaused(msg.sender);
    }

    error Paused();
    error DepositsPaused();
    error NotPaused();
    error DepositsNotPaused();

    event SetPaused(address account);
    event SetDepositsPaused(address account);
    event SetUnpaused(address account);
    event SetDepositsUnpaused(address account);
}


// File contracts/interfaces/synthetix/IExchangeRates.sol

// -License-Identifier: MIT
pragma solidity 0.8.9;

interface IExchangeRates {
    function rateAndInvalid(
        bytes32 currencyKey
    ) external view returns (uint rate, bool isInvalid);
}


// File contracts/interfaces/IPolynomialVaultToken.sol

// -License-Identifier: MIT
pragma solidity 0.8.9;

interface IPolynomialVaultToken {
    function mint(address _user, uint256 _amt) external;
    function burn(address _user, uint256 _amt) external;

    function totalSupply() external view returns (uint256 totalSupply);
    function balanceOf(address user) external view returns (uint256 balance);
}


// File contracts/interfaces/IPolynomialVault.sol

// -License-Identifier: MIT
pragma solidity 0.8.9;

interface IPolynomialVault {}


// File contracts/interfaces/lyra/IOptionMarket.sol

// -License-Identifier: MIT
pragma solidity 0.8.9;

interface IOptionMarket {
    enum OptionType {
        LONG_CALL,
        LONG_PUT,
        SHORT_CALL_BASE,
        SHORT_CALL_QUOTE,
        SHORT_PUT_QUOTE
    }

    struct Strike {
        // strike listing identifier
        uint id;
        // strike price
        uint strikePrice;
        // volatility component specific to the strike listing (boardIv * skew = vol of strike)
        uint skew;
        // total user long call exposure
        uint longCall;
        // total user short call (base collateral) exposure
        uint shortCallBase;
        // total user short call (quote collateral) exposure
        uint shortCallQuote;
        // total user long put exposure
        uint longPut;
        // total user short put (quote collateral) exposure
        uint shortPut;
        // id of board to which strike belongs
        uint boardId;
    }
    
    struct OptionBoard {
        // board identifier
        uint id;
        // expiry of all strikes belonging to board
        uint expiry;
        // volatility component specific to board (boardIv * skew = vol of strike)
        uint iv;
        // admin settable flag blocking all trading on this board
        bool frozen;
        // list of all strikes belonging to this board
        uint[] strikeIds;
    }

    function getStrikeAndBoard(uint strikeId) external view returns (Strike memory, OptionBoard memory);

    function getStrikeAndExpiry(uint strikeId) external view returns (uint strikePrice, uint expiry);

    function getSettlementParameters(uint strikeId) external view returns (
        uint strikePrice,
        uint priceAtExpiry,
        uint strikeToBaseReturned
    );

    function addCollateral(uint positionId, uint amountCollateral) external;
}


// File contracts/interfaces/lyra/IOptionMarketWrapperWithSwaps.sol

// -License-Identifier: MIT
pragma solidity 0.8.9;

interface IOptionMarketWrapperWithSwaps {
    struct ReturnDetails {
        address market;
        uint positionId;
        address owner;
        uint amount;
        uint totalCost;
        uint totalFee;
        int swapFee;
        address token;
    }

    struct OptionPositionParams {
        IOptionMarket optionMarket;
        uint strikeId; // The id of the relevant OptionListing
        uint positionId;
        uint iterations;
        uint setCollateralTo;
        uint currentCollateral;
        IOptionMarket.OptionType optionType; // Is the trade a long/short & call/put?
        uint amount; // The amount the user has requested to close
        uint minCost; // Min amount for the cost of the trade
        uint maxCost; // Max amount for the cost of the trade
        uint inputAmount; // Amount of stable coins the user can use
        ERC20 inputAsset; // Address of coin user wants to open with
    }

    function openPosition(OptionPositionParams memory params) external returns (ReturnDetails memory returnDetails);

    function closePosition(OptionPositionParams memory params) external returns (ReturnDetails memory returnDetails);
}


// File contracts/interfaces/lyra/IOptionToken.sol

// -License-Identifier: MIT
pragma solidity 0.8.9;

interface IOptionToken {
    enum PositionState {
        EMPTY,
        ACTIVE,
        CLOSED,
        LIQUIDATED,
        SETTLED,
        MERGED
    }

    function getPositionState(uint positionId) external view returns (PositionState);

    function getApproved(uint256 tokenId) external view returns (address operator);

    function approve(address to, uint256 tokenId) external;
}


// File contracts/interfaces/lyra/IOptionGreekCache.sol

// -License-Identifier: MIT
pragma solidity 0.8.9;

interface IOptionGreekCache {
    struct GreekCacheParameters {
        // Cap the number of strikes per board to avoid hitting gasLimit constraints
        uint maxStrikesPerBoard;
        // How much spot price can move since last update before deposits/withdrawals are blocked
        uint acceptableSpotPricePercentMove;
        // How much time has passed since last update before deposits/withdrawals are blocked
        uint staleUpdateDuration;
        // Length of the GWAV for the baseline volatility used to fire the vol circuit breaker
        uint varianceIvGWAVPeriod;
        // Length of the GWAV for the skew ratios used to fire the vol circuit breaker
        uint varianceSkewGWAVPeriod;
        // Length of the GWAV for the baseline used to determine the NAV of the pool
        uint optionValueIvGWAVPeriod;
        // Length of the GWAV for the skews used to determine the NAV of the pool
        uint optionValueSkewGWAVPeriod;
        // Minimum skew that will be fed into the GWAV calculation
        // Prevents near 0 values being used to heavily manipulate the GWAV
        uint gwavSkewFloor;
        // Maximum skew that will be fed into the GWAV calculation
        uint gwavSkewCap;
        // Interest/risk free rate
        int rateAndCarry;
    }

    function getGreekCacheParams() external view returns (GreekCacheParameters memory);

    function getIvGWAV(uint boardId, uint secondsAgo) external view returns (uint ivGWAV);

    function getSkewGWAV(uint strikeId, uint secondsAgo) external view returns (uint skewGWAV);
}


// File contracts/libraries/DecimalMath.sol

//-License-Identifier: MIT
//
//Copyright (c) 2019 Synthetix
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.

pragma solidity ^0.8.9;

/**
 * @title DecimalMath
 * @author Lyra
 * @dev Modified synthetix SafeDecimalMath to include internal arithmetic underflow/overflow.
 * @dev https://docs.synthetix.io/contracts/source/libraries/SafeDecimalMath/
 */

library DecimalMath {
  /* Number of decimal places in the representations. */
  uint8 public constant decimals = 18;
  uint8 public constant highPrecisionDecimals = 27;

  /* The number representing 1.0. */
  uint public constant UNIT = 10**uint(decimals);

  /* The number representing 1.0 for higher fidelity numbers. */
  uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals);
  uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals);

  /**
   * @return Provides an interface to UNIT.
   */
  function unit() external pure returns (uint) {
    return UNIT;
  }

  /**
   * @return Provides an interface to PRECISE_UNIT.
   */
  function preciseUnit() external pure returns (uint) {
    return PRECISE_UNIT;
  }

  /**
   * @return The result of multiplying x and y, interpreting the operands as fixed-point
   * decimals.
   *
   * @dev A unit factor is divided out after the product of x and y is evaluated,
   * so that product must be less than 2**256. As this is an integer division,
   * the internal division always rounds down. This helps save on gas. Rounding
   * is more expensive on gas.
   */
  function multiplyDecimal(uint x, uint y) internal pure returns (uint) {
    /* Divide by UNIT to remove the extra factor introduced by the product. */
    return (x * y) / UNIT;
  }

  /**
   * @return The result of safely multiplying x and y, interpreting the operands
   * as fixed-point decimals of the specified precision unit.
   *
   * @dev The operands should be in the form of a the specified unit factor which will be
   * divided out after the product of x and y is evaluated, so that product must be
   * less than 2**256.
   *
   * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
   * Rounding is useful when you need to retain fidelity for small decimal numbers
   * (eg. small fractions or percentages).
   */
  function _multiplyDecimalRound(
    uint x,
    uint y,
    uint precisionUnit
  ) private pure returns (uint) {
    /* Divide by UNIT to remove the extra factor introduced by the product. */
    uint quotientTimesTen = (x * y) / (precisionUnit / 10);

    if (quotientTimesTen % 10 >= 5) {
      quotientTimesTen += 10;
    }

    return quotientTimesTen / 10;
  }

  /**
   * @return The result of safely multiplying x and y, interpreting the operands
   * as fixed-point decimals of a precise unit.
   *
   * @dev The operands should be in the precise unit factor which will be
   * divided out after the product of x and y is evaluated, so that product must be
   * less than 2**256.
   *
   * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
   * Rounding is useful when you need to retain fidelity for small decimal numbers
   * (eg. small fractions or percentages).
   */
  function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
    return _multiplyDecimalRound(x, y, PRECISE_UNIT);
  }

  /**
   * @return The result of safely multiplying x and y, interpreting the operands
   * as fixed-point decimals of a standard unit.
   *
   * @dev The operands should be in the standard unit factor which will be
   * divided out after the product of x and y is evaluated, so that product must be
   * less than 2**256.
   *
   * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
   * Rounding is useful when you need to retain fidelity for small decimal numbers
   * (eg. small fractions or percentages).
   */
  function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) {
    return _multiplyDecimalRound(x, y, UNIT);
  }

  /**
   * @return The result of safely dividing x and y. The return value is a high
   * precision decimal.
   *
   * @dev y is divided after the product of x and the standard precision unit
   * is evaluated, so the product of x and UNIT must be less than 2**256. As
   * this is an integer division, the result is always rounded down.
   * This helps save on gas. Rounding is more expensive on gas.
   */
  function divideDecimal(uint x, uint y) internal pure returns (uint) {
    /* Reintroduce the UNIT factor that will be divided out by y. */
    return (x * UNIT) / y;
  }

  /**
   * @return The result of safely dividing x and y. The return value is as a rounded
   * decimal in the precision unit specified in the parameter.
   *
   * @dev y is divided after the product of x and the specified precision unit
   * is evaluated, so the product of x and the specified precision unit must
   * be less than 2**256. The result is rounded to the nearest increment.
   */
  function _divideDecimalRound(
    uint x,
    uint y,
    uint precisionUnit
  ) private pure returns (uint) {
    uint resultTimesTen = (x * (precisionUnit * 10)) / y;

    if (resultTimesTen % 10 >= 5) {
      resultTimesTen += 10;
    }

    return resultTimesTen / 10;
  }

  /**
   * @return The result of safely dividing x and y. The return value is as a rounded
   * standard precision decimal.
   *
   * @dev y is divided after the product of x and the standard precision unit
   * is evaluated, so the product of x and the standard precision unit must
   * be less than 2**256. The result is rounded to the nearest increment.
   */
  function divideDecimalRound(uint x, uint y) internal pure returns (uint) {
    return _divideDecimalRound(x, y, UNIT);
  }

  /**
   * @return The result of safely dividing x and y. The return value is as a rounded
   * high precision decimal.
   *
   * @dev y is divided after the product of x and the high precision unit
   * is evaluated, so the product of x and the high precision unit must
   * be less than 2**256. The result is rounded to the nearest increment.
   */
  function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
    return _divideDecimalRound(x, y, PRECISE_UNIT);
  }

  /**
   * @dev Convert a standard decimal representation to a high precision one.
   */
  function decimalToPreciseDecimal(uint i) internal pure returns (uint) {
    return i * UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR;
  }

  /**
   * @dev Convert a high precision decimal to a standard decimal representation.
   */
  function preciseDecimalToDecimal(uint i) internal pure returns (uint) {
    uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);

    if (quotientTimesTen % 10 >= 5) {
      quotientTimesTen += 10;
    }

    return quotientTimesTen / 10;
  }
}


// File contracts/libraries/SignedDecimalMath.sol

//-License-Identifier: MIT
//
//Copyright (c) 2019 Synthetix
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.

pragma solidity ^0.8.9;

/**
 * @title SignedDecimalMath
 * @author Lyra
 * @dev Modified synthetix SafeSignedDecimalMath to include internal arithmetic underflow/overflow.
 * @dev https://docs.synthetix.io/contracts/source/libraries/safedecimalmath
 */
library SignedDecimalMath {
  /* Number of decimal places in the representations. */
  uint8 public constant decimals = 18;
  uint8 public constant highPrecisionDecimals = 27;

  /* The number representing 1.0. */
  int public constant UNIT = int(10**uint(decimals));

  /* The number representing 1.0 for higher fidelity numbers. */
  int public constant PRECISE_UNIT = int(10**uint(highPrecisionDecimals));
  int private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = int(10**uint(highPrecisionDecimals - decimals));

  /**
   * @return Provides an interface to UNIT.
   */
  function unit() external pure returns (int) {
    return UNIT;
  }

  /**
   * @return Provides an interface to PRECISE_UNIT.
   */
  function preciseUnit() external pure returns (int) {
    return PRECISE_UNIT;
  }

  /**
   * @dev Rounds an input with an extra zero of precision, returning the result without the extra zero.
   * Half increments round away from zero; positive numbers at a half increment are rounded up,
   * while negative such numbers are rounded down. This behaviour is designed to be consistent with the
   * unsigned version of this library (SafeDecimalMath).
   */
  function _roundDividingByTen(int valueTimesTen) private pure returns (int) {
    int increment;
    if (valueTimesTen % 10 >= 5) {
      increment = 10;
    } else if (valueTimesTen % 10 <= -5) {
      increment = -10;
    }
    return (valueTimesTen + increment) / 10;
  }

  /**
   * @return The result of multiplying x and y, interpreting the operands as fixed-point
   * decimals.
   *
   * @dev A unit factor is divided out after the product of x and y is evaluated,
   * so that product must be less than 2**256. As this is an integer division,
   * the internal division always rounds down. This helps save on gas. Rounding
   * is more expensive on gas.
   */
  function multiplyDecimal(int x, int y) internal pure returns (int) {
    /* Divide by UNIT to remove the extra factor introduced by the product. */
    return (x * y) / UNIT;
  }

  /**
   * @return The result of safely multiplying x and y, interpreting the operands
   * as fixed-point decimals of the specified precision unit.
   *
   * @dev The operands should be in the form of a the specified unit factor which will be
   * divided out after the product of x and y is evaluated, so that product must be
   * less than 2**256.
   *
   * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
   * Rounding is useful when you need to retain fidelity for small decimal numbers
   * (eg. small fractions or percentages).
   */
  function _multiplyDecimalRound(
    int x,
    int y,
    int precisionUnit
  ) private pure returns (int) {
    /* Divide by UNIT to remove the extra factor introduced by the product. */
    int quotientTimesTen = (x * y) / (precisionUnit / 10);
    return _roundDividingByTen(quotientTimesTen);
  }

  /**
   * @return The result of safely multiplying x and y, interpreting the operands
   * as fixed-point decimals of a precise unit.
   *
   * @dev The operands should be in the precise unit factor which will be
   * divided out after the product of x and y is evaluated, so that product must be
   * less than 2**256.
   *
   * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
   * Rounding is useful when you need to retain fidelity for small decimal numbers
   * (eg. small fractions or percentages).
   */
  function multiplyDecimalRoundPrecise(int x, int y) internal pure returns (int) {
    return _multiplyDecimalRound(x, y, PRECISE_UNIT);
  }

  /**
   * @return The result of safely multiplying x and y, interpreting the operands
   * as fixed-point decimals of a standard unit.
   *
   * @dev The operands should be in the standard unit factor which will be
   * divided out after the product of x and y is evaluated, so that product must be
   * less than 2**256.
   *
   * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
   * Rounding is useful when you need to retain fidelity for small decimal numbers
   * (eg. small fractions or percentages).
   */
  function multiplyDecimalRound(int x, int y) internal pure returns (int) {
    return _multiplyDecimalRound(x, y, UNIT);
  }

  /**
   * @return The result of safely dividing x and y. The return value is a high
   * precision decimal.
   *
   * @dev y is divided after the product of x and the standard precision unit
   * is evaluated, so the product of x and UNIT must be less than 2**256. As
   * this is an integer division, the result is always rounded down.
   * This helps save on gas. Rounding is more expensive on gas.
   */
  function divideDecimal(int x, int y) internal pure returns (int) {
    /* Reintroduce the UNIT factor that will be divided out by y. */
    return (x * UNIT) / y;
  }

  /**
   * @return The result of safely dividing x and y. The return value is as a rounded
   * decimal in the precision unit specified in the parameter.
   *
   * @dev y is divided after the product of x and the specified precision unit
   * is evaluated, so the product of x and the specified precision unit must
   * be less than 2**256. The result is rounded to the nearest increment.
   */
  function _divideDecimalRound(
    int x,
    int y,
    int precisionUnit
  ) private pure returns (int) {
    int resultTimesTen = (x * (precisionUnit * 10)) / y;
    return _roundDividingByTen(resultTimesTen);
  }

  /**
   * @return The result of safely dividing x and y. The return value is as a rounded
   * standard precision decimal.
   *
   * @dev y is divided after the product of x and the standard precision unit
   * is evaluated, so the product of x and the standard precision unit must
   * be less than 2**256. The result is rounded to the nearest increment.
   */
  function divideDecimalRound(int x, int y) internal pure returns (int) {
    return _divideDecimalRound(x, y, UNIT);
  }

  /**
   * @return The result of safely dividing x and y. The return value is as a rounded
   * high precision decimal.
   *
   * @dev y is divided after the product of x and the high precision unit
   * is evaluated, so the product of x and the high precision unit must
   * be less than 2**256. The result is rounded to the nearest increment.
   */
  function divideDecimalRoundPrecise(int x, int y) internal pure returns (int) {
    return _divideDecimalRound(x, y, PRECISE_UNIT);
  }

  /**
   * @dev Convert a standard decimal representation to a high precision one.
   */
  function decimalToPreciseDecimal(int i) internal pure returns (int) {
    return i * UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR;
  }

  /**
   * @dev Convert a high precision decimal to a standard decimal representation.
   */
  function preciseDecimalToDecimal(int i) internal pure returns (int) {
    int quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);
    return _roundDividingByTen(quotientTimesTen);
  }
}


// File contracts/libraries/HigherMath.sol

// -License-Identifier: UNLICENSED
pragma solidity 0.8.9;

// Slightly modified version of:
// - https://github.com/recmo/experiment-solexp/blob/605738f3ed72d6c67a414e992be58262fbc9bb80/src/FixedPointMathLib.sol
library HigherMath {
  /// @dev Computes ln(x) for a 1e27 fixed point. Loses 9 last significant digits of precision.
  function lnPrecise(int x) internal pure returns (int r) {
    return ln(x / 1e9) * 1e9;
  }

  /// @dev Computes e ^ x for a 1e27 fixed point. Loses 9 last significant digits of precision.
  function expPrecise(int x) internal pure returns (uint r) {
    return exp(x / 1e9) * 1e9;
  }

  // Computes ln(x) in 1e18 fixed point.
  // Reverts if x is negative or zero.
  // Consumes 670 gas.
  function ln(int x) internal pure returns (int r) {
    unchecked {
      if (x < 1) {
        if (x < 0) revert LnNegativeUndefined();
        revert Overflow();
      }

      // We want to convert x from 10**18 fixed point to 2**96 fixed point.
      // We do this by multiplying by 2**96 / 10**18.
      // But since ln(x * C) = ln(x) + ln(C), we can simply do nothing here
      // and add ln(2**96 / 10**18) at the end.

      // Reduce range of x to (1, 2) * 2**96
      // ln(2^k * x) = k * ln(2) + ln(x)
      // Note: inlining ilog2 saves 8 gas.
      int k = int(ilog2(uint(x))) - 96;
      x <<= uint(159 - k);
      x = int(uint(x) >> 159);

      // Evaluate using a (8, 8)-term rational approximation
      // p is made monic, we will multiply by a scale factor later
      int p = x + 3273285459638523848632254066296;
      p = ((p * x) >> 96) + 24828157081833163892658089445524;
      p = ((p * x) >> 96) + 43456485725739037958740375743393;
      p = ((p * x) >> 96) - 11111509109440967052023855526967;
      p = ((p * x) >> 96) - 45023709667254063763336534515857;
      p = ((p * x) >> 96) - 14706773417378608786704636184526;
      p = p * x - (795164235651350426258249787498 << 96);
      //emit log_named_int("p", p);
      // We leave p in 2**192 basis so we don't need to scale it back up for the division.
      // q is monic by convention
      int q = x + 5573035233440673466300451813936;
      q = ((q * x) >> 96) + 71694874799317883764090561454958;
      q = ((q * x) >> 96) + 283447036172924575727196451306956;
      q = ((q * x) >> 96) + 401686690394027663651624208769553;
      q = ((q * x) >> 96) + 204048457590392012362485061816622;
      q = ((q * x) >> 96) + 31853899698501571402653359427138;
      q = ((q * x) >> 96) + 909429971244387300277376558375;
      assembly {
        // Div in assembly because solidity adds a zero check despite the `unchecked`.
        // The q polynomial is known not to have zeros in the domain. (All roots are complex)
        // No scaling required because p is already 2**96 too large.
        r := sdiv(p, q)
      }
      // r is in the range (0, 0.125) * 2**96

      // Finalization, we need to
      // * multiply by the scale factor s = 5.549…
      // * add ln(2**96 / 10**18)
      // * add k * ln(2)
      // * multiply by 10**18 / 2**96 = 5**18 >> 78
      // mul s * 5e18 * 2**96, base is now 5**18 * 2**192
      r *= 1677202110996718588342820967067443963516166;
      // add ln(2) * k * 5e18 * 2**192
      r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;
      // add ln(2**96 / 10**18) * 5e18 * 2**192
      r += 600920179829731861736702779321621459595472258049074101567377883020018308;
      // base conversion: mul 2**18 / 2**192
      r >>= 174;
    }
  }

  // Integer log2
  // @returns floor(log2(x)) if x is nonzero, otherwise 0. This is the same
  //          as the location of the highest set bit.
  // Consumes 232 gas. This could have been an 3 gas EVM opcode though.
  function ilog2(uint x) internal pure returns (uint r) {
    assembly {
      r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
      r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
      r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
      r := or(r, shl(4, lt(0xffff, shr(r, x))))
      r := or(r, shl(3, lt(0xff, shr(r, x))))
      r := or(r, shl(2, lt(0xf, shr(r, x))))
      r := or(r, shl(1, lt(0x3, shr(r, x))))
      r := or(r, lt(0x1, shr(r, x)))
    }
  }

  // Computes e^x in 1e18 fixed point.
  function exp(int x) internal pure returns (uint r) {
    unchecked {
      // Input x is in fixed point format, with scale factor 1/1e18.

      // When the result is < 0.5 we return zero. This happens when
      // x <= floor(log(0.5e18) * 1e18) ~ -42e18
      if (x <= -42139678854452767551) {
        return 0;
      }

      // When the result is > (2**255 - 1) / 1e18 we can not represent it
      // as an int256. This happens when x >= floor(log((2**255 -1) / 1e18) * 1e18) ~ 135.
      if (x >= 135305999368893231589) revert ExpOverflow();

      // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96
      // for more intermediate precision and a binary basis. This base conversion
      // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.
      x = (x << 78) / 5**18;

      // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers of two
      // such that exp(x) = exp(x') * 2**k, where k is an integer.
      // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).
      int k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;
      x = x - k * 54916777467707473351141471128;
      // k is in the range [-61, 195].

      // Evaluate using a (6, 7)-term rational approximation
      // p is made monic, we will multiply by a scale factor later
      int p = x + 2772001395605857295435445496992;
      p = ((p * x) >> 96) + 44335888930127919016834873520032;
      p = ((p * x) >> 96) + 398888492587501845352592340339721;
      p = ((p * x) >> 96) + 1993839819670624470859228494792842;
      p = p * x + (4385272521454847904632057985693276 << 96);
      // We leave p in 2**192 basis so we don't need to scale it back up for the division.
      // Evaluate using using Knuth's scheme from p. 491.
      int z = x + 750530180792738023273180420736;
      z = ((z * x) >> 96) + 32788456221302202726307501949080;
      int w = x - 2218138959503481824038194425854;
      w = ((w * z) >> 96) + 892943633302991980437332862907700;
      int q = z + w - 78174809823045304726920794422040;
      q = ((q * w) >> 96) + 4203224763890128580604056984195872;
      assembly {
        // Div in assembly because solidity adds a zero check despite the `unchecked`.
        // The q polynomial is known not to have zeros in the domain. (All roots are complex)
        // No scaling required because p is already 2**96 too large.
        r := sdiv(p, q)
      }
      // r should be in the range (0.09, 0.25) * 2**96.

      // We now need to multiply r by
      //  * the scale factor s = ~6.031367120...,
      //  * the 2**k factor from the range reduction, and
      //  * the 1e18 / 2**96 factor for base converison.
      // We do all of this at once, with an intermediate result in 2**213 basis
      // so the final right shift is always by a positive amount.
      r = (uint(r) * 3822833074963236453042738258902158003155416615667) >> uint(195 - k);
    }
  }

  error Overflow();
  error ExpOverflow();
  error LnNegativeUndefined();
}


// File contracts/libraries/BlackScholes.sol

// -License-Identifier: ISC

//ISC License
//
//Copyright (c) 2021 Lyra Finance
//
//Permission to use, copy, modify, and/or distribute this software for any
//purpose with or without fee is hereby granted, provided that the above
//copyright notice and this permission notice appear in all copies.
//
//THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
//REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
//AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
//INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
//LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
//PERFORMANCE OF THIS SOFTWARE.

pragma solidity 0.8.9;



/**
* @title BlackScholes
* @author Lyra
* @dev Contract to compute the black scholes price of options. Where the unit is unspecified, it should be treated as a
* PRECISE_DECIMAL, which has 1e27 units of precision. The default decimal matches the ethereum standard of 1e18 units
* of precision.
*/
library BlackScholesLib {
    using DecimalMath for uint;
    using SignedDecimalMath for int;
    
    struct PricesDeltaStdVega {
        uint callPrice;
        uint putPrice;
        int callDelta;
        int putDelta;
        uint vega;
        uint stdVega;
    }
    
    /**
    * @param timeToExpirySec Number of seconds to the expiry of the option
    * @param volatilityDecimal Implied volatility over the period til expiry as a percentage
    * @param spotDecimal The current price of the base asset
    * @param strikePriceDecimal The strikePrice price of the option
    * @param rateDecimal The percentage risk free rate + carry cost
    */
    struct BlackScholesInputs {
        uint timeToExpirySec;
        uint volatilityDecimal;
        uint spotDecimal;
        uint strikePriceDecimal;
        int rateDecimal;
    }
    
    uint private constant SECONDS_PER_YEAR = 31536000;
    /// @dev Internally this library uses 27 decimals of precision
    uint private constant PRECISE_UNIT = 1e27;
    uint private constant SQRT_TWOPI = 2506628274631000502415765285;
    /// @dev Below this value, return 0
    int private constant MIN_CDF_STD_DIST_INPUT = (int(PRECISE_UNIT) * -45) / 10; // -4.5
    /// @dev Above this value, return 1
    int private constant MAX_CDF_STD_DIST_INPUT = int(PRECISE_UNIT) * 10;
    /// @dev Value to use to avoid any division by 0 or values near 0
    uint private constant MIN_T_ANNUALISED = PRECISE_UNIT / SECONDS_PER_YEAR; // 1 second
    uint private constant MIN_VOLATILITY = PRECISE_UNIT / 10000; // 0.001%
    uint private constant VEGA_STANDARDISATION_MIN_DAYS = 7 days;
    /// @dev Magic numbers for normal CDF
    uint private constant SPLIT = 7071067811865470000000000000;
    uint private constant N0 = 220206867912376000000000000000;
    uint private constant N1 = 221213596169931000000000000000;
    uint private constant N2 = 112079291497871000000000000000;
    uint private constant N3 = 33912866078383000000000000000;
    uint private constant N4 = 6373962203531650000000000000;
    uint private constant N5 = 700383064443688000000000000;
    uint private constant N6 = 35262496599891100000000000;
    uint private constant M0 = 440413735824752000000000000000;
    uint private constant M1 = 793826512519948000000000000000;
    uint private constant M2 = 637333633378831000000000000000;
    uint private constant M3 = 296564248779674000000000000000;
    uint private constant M4 = 86780732202946100000000000000;
    uint private constant M5 = 16064177579207000000000000000;
    uint private constant M6 = 1755667163182640000000000000;
    uint private constant M7 = 88388347648318400000000000;
    
    /////////////////////////////////////
    // Option Pricing public functions //
    /////////////////////////////////////
    
    /**
    * @dev Returns call and put prices for options with given parameters.
    */
    function optionPrices(BlackScholesInputs memory bsInput) public pure returns (uint call, uint put) {
        uint tAnnualised = _annualise(bsInput.timeToExpirySec);
        uint spotPrecise = bsInput.spotDecimal.decimalToPreciseDecimal();
        uint strikePricePrecise = bsInput.strikePriceDecimal.decimalToPreciseDecimal();
        int ratePrecise = bsInput.rateDecimal.decimalToPreciseDecimal();
        (int d1, int d2) = _d1d2(
            tAnnualised,
            bsInput.volatilityDecimal.decimalToPreciseDecimal(),
            spotPrecise,
            strikePricePrecise,
            ratePrecise
        );
        (call, put) = _optionPrices(tAnnualised, spotPrecise, strikePricePrecise, ratePrecise, d1, d2);
        return (call.preciseDecimalToDecimal(), put.preciseDecimalToDecimal());
    }
    
    /**
    * @dev Returns call/put prices and delta/stdVega for options with given parameters.
    */
    function pricesDeltaStdVega(BlackScholesInputs memory bsInput) public pure returns (PricesDeltaStdVega memory) {
        uint tAnnualised = _annualise(bsInput.timeToExpirySec);
        uint spotPrecise = bsInput.spotDecimal.decimalToPreciseDecimal();
        
        (int d1, int d2) = _d1d2(
            tAnnualised,
            bsInput.volatilityDecimal.decimalToPreciseDecimal(),
            spotPrecise,
            bsInput.strikePriceDecimal.decimalToPreciseDecimal(),
            bsInput.rateDecimal.decimalToPreciseDecimal()
        );
        (uint callPrice, uint putPrice) = _optionPrices(
            tAnnualised,
            spotPrecise,
            bsInput.strikePriceDecimal.decimalToPreciseDecimal(),
            bsInput.rateDecimal.decimalToPreciseDecimal(),
            d1,
            d2
        );
        (uint vegaPrecise, uint stdVegaPrecise) = _standardVega(d1, spotPrecise, bsInput.timeToExpirySec);
        (int callDelta, int putDelta) = _delta(d1);
        
        return
        PricesDeltaStdVega(
            callPrice.preciseDecimalToDecimal(),
            putPrice.preciseDecimalToDecimal(),
            callDelta.preciseDecimalToDecimal(),
            putDelta.preciseDecimalToDecimal(),
            vegaPrecise.preciseDecimalToDecimal(),
            stdVegaPrecise.preciseDecimalToDecimal()
        );
    }
    
    /**
    * @dev Returns call delta given parameters.
    */
    
    function delta(BlackScholesInputs memory bsInput) public pure returns (int callDeltaDecimal, int putDeltaDecimal) {
        uint tAnnualised = _annualise(bsInput.timeToExpirySec);
        uint spotPrecise = bsInput.spotDecimal.decimalToPreciseDecimal();
        
        (int d1, ) = _d1d2(
            tAnnualised,
            bsInput.volatilityDecimal.decimalToPreciseDecimal(),
            spotPrecise,
            bsInput.strikePriceDecimal.decimalToPreciseDecimal(),
            bsInput.rateDecimal.decimalToPreciseDecimal()
        );
        
        (int callDelta, int putDelta) = _delta(d1);
        return (callDelta.preciseDecimalToDecimal(), putDelta.preciseDecimalToDecimal());
    }
    
    /**
    * @dev Returns non-normalized vega given parameters. Quoted in cents.
    */
    function vega(BlackScholesInputs memory bsInput) public pure returns (uint vegaDecimal) {
        uint tAnnualised = _annualise(bsInput.timeToExpirySec);
        uint spotPrecise = bsInput.spotDecimal.decimalToPreciseDecimal();
        
        (int d1, ) = _d1d2(
            tAnnualised,
            bsInput.volatilityDecimal.decimalToPreciseDecimal(),
            spotPrecise,
            bsInput.strikePriceDecimal.decimalToPreciseDecimal(),
            bsInput.rateDecimal.decimalToPreciseDecimal()
        );
        return _vega(tAnnualised, spotPrecise, d1).preciseDecimalToDecimal();
    }
    
    //////////////////////
    // Computing Greeks //
    //////////////////////
    
    /**
    * @dev Returns internal coefficients of the Black-Scholes call price formula, d1 and d2.
    * @param tAnnualised Number of years to expiry
    * @param volatility Implied volatility over the period til expiry as a percentage
    * @param spot The current price of the base asset
    * @param strikePrice The strikePrice price of the option
    * @param rate The percentage risk free rate + carry cost
    */
    function _d1d2(
        uint tAnnualised,
        uint volatility,
        uint spot,
        uint strikePrice,
        int rate
    ) internal pure returns (int d1, int d2) {
        // Set minimum values for tAnnualised and volatility to not break computation in extreme scenarios
        // These values will result in option prices reflecting only the difference in stock/strikePrice, which is expected.
        // This should be caught before calling this function, however the function shouldn't break if the values are 0.
        tAnnualised = tAnnualised < MIN_T_ANNUALISED ? MIN_T_ANNUALISED : tAnnualised;
        volatility = volatility < MIN_VOLATILITY ? MIN_VOLATILITY : volatility;
        
        int vtSqrt = int(volatility.multiplyDecimalRoundPrecise(_sqrtPrecise(tAnnualised)));
        int log = HigherMath.lnPrecise(int(spot.divideDecimalRoundPrecise(strikePrice)));
        int v2t = (int(volatility.multiplyDecimalRoundPrecise(volatility) / 2) + rate).multiplyDecimalRoundPrecise(
            int(tAnnualised)
        );
        d1 = (log + v2t).divideDecimalRoundPrecise(vtSqrt);
        d2 = d1 - vtSqrt;
    }
    
    /**
    * @dev Internal coefficients of the Black-Scholes call price formula.
    * @param tAnnualised Number of years to expiry
    * @param spot The current price of the base asset
    * @param strikePrice The strikePrice price of the option
    * @param rate The percentage risk free rate + carry cost
    * @param d1 Internal coefficient of Black-Scholes
    * @param d2 Internal coefficient of Black-Scholes
    */
    function _optionPrices(
        uint tAnnualised,
        uint spot,
        uint strikePrice,
        int rate,
        int d1,
        int d2
    ) internal pure returns (uint call, uint put) {
        uint strikePricePV = strikePrice.multiplyDecimalRoundPrecise(
            HigherMath.expPrecise(int(-rate.multiplyDecimalRoundPrecise(int(tAnnualised))))
        );
        uint spotNd1 = spot.multiplyDecimalRoundPrecise(_stdNormalCDF(d1));
        uint strikePriceNd2 = strikePricePV.multiplyDecimalRoundPrecise(_stdNormalCDF(d2));
        
        // We clamp to zero if the minuend is less than the subtrahend
        // In some scenarios it may be better to compute put price instead and derive call from it depending on which way
        // around is more precise.
        call = strikePriceNd2 <= spotNd1 ? spotNd1 - strikePriceNd2 : 0;
        put = call + strikePricePV;
        put = spot <= put ? put - spot : 0;
    }
    
    /*
    * Greeks
    */
    
    /**
    * @dev Returns the option's delta value
    * @param d1 Internal coefficient of Black-Scholes
    */
    function _delta(int d1) internal pure returns (int callDelta, int putDelta) {
        callDelta = int(_stdNormalCDF(d1));
        putDelta = callDelta - int(PRECISE_UNIT);
    }
    
    /**
    * @dev Returns the option's vega value based on d1. Quoted in cents.
    *
    * @param d1 Internal coefficient of Black-Scholes
    * @param tAnnualised Number of years to expiry
    * @param spot The current price of the base asset
    */
    function _vega(
        uint tAnnualised,
        uint spot,
        int d1
    ) internal pure returns (uint) {
        return _sqrtPrecise(tAnnualised).multiplyDecimalRoundPrecise(_stdNormal(d1).multiplyDecimalRoundPrecise(spot));
    }
    
    /**
    * @dev Returns the option's vega value with expiry modified to be at least VEGA_STANDARDISATION_MIN_DAYS
    * @param d1 Internal coefficient of Black-Scholes
    * @param spot The current price of the base asset
    * @param timeToExpirySec Number of seconds to expiry
    */
    function _standardVega(
        int d1,
        uint spot,
        uint timeToExpirySec
    ) internal pure returns (uint, uint) {
        uint tAnnualised = _annualise(timeToExpirySec);
        uint normalisationFactor = _getVegaNormalisationFactorPrecise(timeToExpirySec);
        uint vegaPrecise = _vega(tAnnualised, spot, d1);
        return (vegaPrecise, vegaPrecise.multiplyDecimalRoundPrecise(normalisationFactor));
    }
    
    function _getVegaNormalisationFactorPrecise(uint timeToExpirySec) internal pure returns (uint) {
        timeToExpirySec = timeToExpirySec < VEGA_STANDARDISATION_MIN_DAYS ? VEGA_STANDARDISATION_MIN_DAYS : timeToExpirySec;
        uint daysToExpiry = timeToExpirySec / 1 days;
        uint thirty = 30 * PRECISE_UNIT;
        return _sqrtPrecise(thirty / daysToExpiry) / 100;
    }
    
    /////////////////////
    // Math Operations //
    /////////////////////
    
    /**
    * @dev Compute the absolute value of `val`.
    *
    * @param val The number to absolute value.
    */
    function _abs(int val) internal pure returns (uint) {
        return uint(val < 0 ? -val : val);
    }
    
    /// @notice Calculates the square root of x, rounding down (borrowed from https://github.com/paulrberg/prb-math)
    /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
    /// @param x The uint256 number for which to calculate the square root.
    /// @return result The result as an uint256.
    function _sqrt(uint x) internal pure returns (uint result) {
        if (x == 0) {
            return 0;
        }
        
        // Calculate the square root of the perfect square of a power of two that is the closest to x.
        uint xAux = uint(x);
        result = 1;
        if (xAux >= 0x100000000000000000000000000000000) {
            xAux >>= 128;
            result <<= 64;
        }
        if (xAux >= 0x10000000000000000) {
            xAux >>= 64;
            result <<= 32;
        }
        if (xAux >= 0x100000000) {
            xAux >>= 32;
            result <<= 16;
        }
        if (xAux >= 0x10000) {
            xAux >>= 16;
            result <<= 8;
        }
        if (xAux >= 0x100) {
            xAux >>= 8;
            result <<= 4;
        }
        if (xAux >= 0x10) {
            xAux >>= 4;
            result <<= 2;
        }
        if (xAux >= 0x8) {
            result <<= 1;
        }
        
        // The operations can never overflow because the result is max 2^127 when it enters this block.
        unchecked {
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1; // Seven iterations should be enough
            uint roundedDownResult = x / result;
            return result >= roundedDownResult ? roundedDownResult : result;
        }
    }
    
    /**
    * @dev Returns the square root of the value using Newton's method.
    */
    function _sqrtPrecise(uint x) internal pure returns (uint) {
        // Add in an extra unit factor for the square root to gobble;
        // otherwise, sqrt(x * UNIT) = sqrt(x) * sqrt(UNIT)
        return _sqrt(x * PRECISE_UNIT);
    }
    
    /**
    * @dev The standard normal distribution of the value.
    */
    function _stdNormal(int x) internal pure returns (uint) {
        return
        HigherMath.expPrecise(int(-x.multiplyDecimalRoundPrecise(x / 2))).divideDecimalRoundPrecise(SQRT_TWOPI);
    }
    
    /**
    * @dev The standard normal cumulative distribution of the value.
    * borrowed from a C++ implementation https://stackoverflow.com/a/23119456
    */
    function _stdNormalCDF(int x) public pure returns (uint) {
        uint z = _abs(x);
        int c;
        
        if (z <= 37 * PRECISE_UNIT) {
            uint e = HigherMath.expPrecise(-int(z.multiplyDecimalRoundPrecise(z / 2)));
            if (z < SPLIT) {
                c = int(
                    (_stdNormalCDFNumerator(z).divideDecimalRoundPrecise(_stdNormalCDFDenom(z)).multiplyDecimalRoundPrecise(e))
                );
            } else {
                uint f = (z +
                    PRECISE_UNIT.divideDecimalRoundPrecise(
                        z +
                        (2 * PRECISE_UNIT).divideDecimalRoundPrecise(
                            z +
                            (3 * PRECISE_UNIT).divideDecimalRoundPrecise(
                                z + (4 * PRECISE_UNIT).divideDecimalRoundPrecise(z + ((PRECISE_UNIT * 13) / 20))
                            )
                        )
                    ));
                    c = int(e.divideDecimalRoundPrecise(f.multiplyDecimalRoundPrecise(SQRT_TWOPI)));
                }
            }
        return uint((x <= 0 ? c : (int(PRECISE_UNIT) - c)));
    }
        
    /**
    * @dev Helper for _stdNormalCDF
    */
    function _stdNormalCDFNumerator(uint z) internal pure returns (uint) {
        uint numeratorInner = ((((((N6 * z) / PRECISE_UNIT + N5) * z) / PRECISE_UNIT + N4) * z) / PRECISE_UNIT + N3);
        return (((((numeratorInner * z) / PRECISE_UNIT + N2) * z) / PRECISE_UNIT + N1) * z) / PRECISE_UNIT + N0;
    }
    
    /**
    * @dev Helper for _stdNormalCDF
    */
    function _stdNormalCDFDenom(uint z) internal pure returns (uint) {
        uint denominatorInner = ((((((M7 * z) / PRECISE_UNIT + M6) * z) / PRECISE_UNIT + M5) * z) / PRECISE_UNIT + M4);
        return
        (((((((denominatorInner * z) / PRECISE_UNIT + M3) * z) / PRECISE_UNIT + M2) * z) / PRECISE_UNIT + M1) * z) /
        PRECISE_UNIT +
        M0;
    }
    
    /**
    * @dev Converts an integer number of seconds to a fractional number of years.
    */
    function _annualise(uint secs) internal pure returns (uint yearFraction) {
        return secs.divideDecimalRoundPrecise(SECONDS_PER_YEAR);
    }
}


// File contracts/core/CallSellingQuoteVault.sol

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











contract CallSellingQuoteVault is
    IPolynomialVault,
    Auth,
    ReentrancyGuard,
    Pausable
{
    /// -----------------------------------------------------------------------
    /// Library usage
    /// -----------------------------------------------------------------------
    using FixedPointMathLib for uint256;
    using SafeTransferLib for ERC20;

    /// -----------------------------------------------------------------------
    /// Data Structures
    /// -----------------------------------------------------------------------

    struct PositionData {
        uint256 positionId;
        uint256 amount;
        uint256 collateral;
        int256 premiumCollected;
    }

    struct QueuedDeposit {
        uint256 id;
        address user;
        uint256 depositedAmount;
        uint256 mintedTokens;
        uint256 requestedTime;
    }

    struct QueuedWithdraw {
        uint256 id;
        address user;
        uint256 withdrawnTokens;
        uint256 returnedAmount;
        uint256 requestedTime;
    }

    /// -----------------------------------------------------------------------
    /// Constants
    /// -----------------------------------------------------------------------

    IOptionMarket.OptionType public constant OPTION_TYPE =
        IOptionMarket.OptionType.SHORT_CALL_QUOTE;

    /// -----------------------------------------------------------------------
    /// Immutable parameters
    /// -----------------------------------------------------------------------

    /// @notice Human Readable Name of the Vault
    bytes32 public immutable name;

    /// @notice Synthetix Synth key of the underlying token
    bytes32 public immutable UNDERLYING_SYNTH_KEY;

    /// @notice sUSD
    ERC20 public immutable SUSD;

    /// @notice Corresponding vault token
    IPolynomialVaultToken public immutable VAULT_TOKEN;

    /// @notice Lyra Option Market
    IOptionMarket public immutable MARKET;

    /// @notice Lyra Option Market Wrapper
    IOptionMarketWrapperWithSwaps public immutable MARKET_WRAPPER;

    /// @notice Lyra Option Token
    IOptionToken public immutable OPTION_TOKEN;

    /// @notice Lyra Options Greek Cache
    IOptionGreekCache public immutable GREEKS;

    /// @notice Synthetix Exchange Rates
    IExchangeRates public immutable RATES;

    /// -----------------------------------------------------------------------
    /// Storage variables
    /// -----------------------------------------------------------------------

    /// @notice Collateralization ratio
    uint256 public collateralization;

    /// @notice Minimum deposit amount
    uint256 public minDepositAmount;

    /// @notice Minimum deposit delay
    uint256 public minDepositDelay;

    /// @notice Minimum withdrawal delay
    uint256 public minWithdrawDelay;

    /// @notice GWAV Length
    uint256 public gwavLength;

    /// @notice Trade Iterations
    uint256 public tradeIterations;

    /// @notice Delta cutoff for trades
    int256 public deltaCutoff;

    /// @notice Fee Receipient
    address public feeReceipient;

    /// @notice Performance Fee
    uint256 public performanceFee;

    /// @notice Withdrawal Fee
    uint256 public withdrawalFee;

    /// @notice Total queued deposits
    uint256 public totalQueuedDeposits;

    /// @notice Total queued withdrawals
    uint256 public totalQueuedWithdrawals;

    /// @notice Next deposit queue item that needs to be processed
    uint256 public queuedDepositHead = 1;

    /// @notice Next deposit queue ID that needs to be processed
    uint256 public nextQueuedDepositId = 1;

    /// @notice Next withdrawal queue item that needs to be processed
    uint256 public queuedWithdrawalHead = 1;

    /// @notice Next withdrawal queue ID that needs to be processed
    uint256 public nextQueuedWithdrawalId = 1;

    /// @notice Total funds
    uint256 public totalFunds;

    /// @notice Used funds
    uint256 public usedFunds;

    /// @notice Total premium collected
    int256 public totalPremiumCollected;

    /// @notice An array of active strike IDs
    uint256[] public liveStrikes;

    /// @notice Strike ID => Position Data
    mapping(uint256 => PositionData) public positionDatas;

    /// @notice Deposit Queue
    mapping(uint256 => QueuedDeposit) public depositQueue;

    /// @notice Withdrawal Queue
    mapping(uint256 => QueuedWithdraw) public withdrawalQueue;

    constructor(
        ERC20 _susd,
        IPolynomialVaultToken _vaultToken,
        IOptionMarket _market,
        IOptionMarketWrapperWithSwaps _marketWrapper,
        IOptionToken _optionToken,
        IOptionGreekCache _greeks,
        IExchangeRates _exchangeRates,
        bytes32 _underlyingKey,
        bytes32 _name
    ) Auth(msg.sender, Authority(address(0x0))) {
        VAULT_TOKEN = _vaultToken;
        MARKET = _market;
        MARKET_WRAPPER = _marketWrapper;
        OPTION_TOKEN = _optionToken;
        GREEKS = _greeks;
        RATES = _exchangeRates;
        UNDERLYING_SYNTH_KEY = _underlyingKey;
        SUSD = _susd;
        name = _name;
    }

    /// -----------------------------------------------------------------------
    /// User actions
    /// -----------------------------------------------------------------------

    /// @notice Initiate deposit to the vault
    /// @notice If there are no active positions, deposits are processed immediately
    /// @notice Otherwise it is added to the deposit queue
    /// @param user Address of the user to receive the VAULT_TOKENs upon processing
    /// @param amount Amount of sUSD being depositted
    function initiateDeposit(address user, uint256 amount)
        external
        nonReentrant
        whenDepositsNotPaused
    {
        if (user == address(0x0)) {
            revert ExpectedNonZero();
        }

        if (amount < minDepositAmount) {
            revert MinimumDepositRequired(minDepositAmount, amount);
        }

        // Instant processing
        if (liveStrikes.length == 0) {
            uint256 tokenPrice = getTokenPrice();
            uint256 tokensToMint = amount.divWadDown(tokenPrice);
            VAULT_TOKEN.mint(user, tokensToMint);
            totalFunds += amount;
            emit ProcessDeposit(0, user, amount, tokensToMint, block.timestamp);
        } else {
            // Queueing the deposit request
            QueuedDeposit storage newDeposit = depositQueue[
                nextQueuedDepositId
            ];

            newDeposit.id = nextQueuedDepositId++;
            newDeposit.user = user;
            newDeposit.depositedAmount = amount;
            newDeposit.requestedTime = block.timestamp;

            totalQueuedDeposits += amount;
            emit InitiateDeposit(newDeposit.id, msg.sender, user, amount);
        }

        SUSD.safeTransferFrom(msg.sender, address(this), amount);
    }

    /// @notice Initiate withdrawal from the vault
    /// @notice If there are no active positions, withdrawals are processed instantly
    /// @notice Otherwise the request is added to the withdrawal queue
    /// @param user Address of the user to receive the sUSD upon processing
    /// @param tokens Amounts of VAULT_TOKENs being requested to burn / withdraw
    function initiateWithdrawal(address user, uint256 tokens)
        external
        nonReentrant
    {
        if (user == address(0x0)) {
            revert ExpectedNonZero();
        }

        // Instant processing
        if (liveStrikes.length == 0) {
            uint256 tokenPrice = getTokenPrice();
            uint256 susdToReturn = tokens.mulWadDown(tokenPrice);
            SUSD.safeTransfer(user, susdToReturn);
            totalFunds -= susdToReturn;
            emit ProcessWithdrawal(
                0,
                user,
                tokens,
                susdToReturn,
                block.timestamp
            );
        } else {
            // Queueing the withdrawal request
            QueuedWithdraw storage newWithdraw = withdrawalQueue[
                nextQueuedWithdrawalId
            ];

            newWithdraw.id = nextQueuedWithdrawalId++;
            newWithdraw.user = user;
            newWithdraw.withdrawnTokens = tokens;
            newWithdraw.requestedTime = block.timestamp;

            totalQueuedWithdrawals += tokens;
            emit InitiateWithdrawal(newWithdraw.id, msg.sender, user, tokens);
        }

        VAULT_TOKEN.burn(msg.sender, tokens);
    }

    /// @notice Process queued deposit requests
    /// @param idCount Number of deposit queue items to process
    function processDepositQueue(uint256 idCount) external nonReentrant {
        uint256 tokenPrice = getTokenPrice();

        for (uint256 i = 0; i < idCount; i++) {
            QueuedDeposit storage current = depositQueue[queuedDepositHead];

            if (
                current.requestedTime == 0 ||
                block.timestamp < current.requestedTime + minDepositDelay
            ) {
                return;
            }

            uint256 tokensToMint = current.depositedAmount.divWadDown(
                tokenPrice
            );

            current.mintedTokens = tokensToMint;
            totalQueuedDeposits -= current.depositedAmount;
            totalFunds += current.depositedAmount;
            VAULT_TOKEN.mint(current.user, tokensToMint);

            emit ProcessDeposit(
                current.id,
                current.user,
                current.depositedAmount,
                current.mintedTokens,
                current.requestedTime
            );

            current.depositedAmount = 0;
            queuedDepositHead++;
        }
    }

    /// @notice Process queued withdrawal requests
    /// @param idCount Number of withdrawal queue items to process
    function processWithdrawalQueue(uint256 idCount) external nonReentrant {
        for (uint256 i = 0; i < idCount; i++) {
            uint256 tokenPrice = getTokenPrice();

            QueuedWithdraw storage current = withdrawalQueue[
                queuedWithdrawalHead
            ];

            if (
                current.requestedTime == 0 ||
                block.timestamp < current.requestedTime + minWithdrawDelay
            ) {
                return;
            }

            uint256 availableFunds = totalFunds - usedFunds;

            if (availableFunds == 0) {
                return;
            }

            uint256 susdToReturn = current.withdrawnTokens.mulWadDown(
                tokenPrice
            );

            // Partial withdrawals if not enough available funds in the vault
            // Queue head is not increased
            if (susdToReturn > availableFunds) {
                current.returnedAmount = availableFunds;
                uint256 tokensBurned = availableFunds.divWadUp(tokenPrice);

                totalQueuedWithdrawals -= tokensBurned;
                current.withdrawnTokens -= tokensBurned;

                totalFunds -= availableFunds;

                if (withdrawalFee > 0) {
                    uint256 withdrawFees = availableFunds.mulWadDown(
                        withdrawalFee
                    );
                    SUSD.safeTransfer(feeReceipient, withdrawFees);
                    availableFunds -= withdrawFees;
                }

                SUSD.safeTransfer(current.user, availableFunds);

                emit ProcessWithdrawalPartially(
                    current.id,
                    current.user,
                    tokensBurned,
                    availableFunds,
                    current.requestedTime
                );
                return;
            } else {
                // Complete full withdrawal
                current.returnedAmount = susdToReturn;
                totalQueuedWithdrawals -= current.withdrawnTokens;
                current.withdrawnTokens = 0;

                totalFunds -= susdToReturn;

                if (withdrawalFee > 0) {
                    uint256 withdrawFees = susdToReturn.mulWadDown(
                        withdrawalFee
                    );
                    SUSD.safeTransfer(feeReceipient, withdrawFees);
                    susdToReturn -= withdrawFees;
                }

                SUSD.safeTransfer(current.user, susdToReturn);

                emit ProcessWithdrawal(
                    current.id,
                    current.user,
                    current.withdrawnTokens,
                    susdToReturn,
                    current.requestedTime
                );
            }

            queuedWithdrawalHead++;
        }
    }

    /// -----------------------------------------------------------------------
    /// View methods
    /// -----------------------------------------------------------------------

    /// @notice Get VAULT_TOKEN price
    /// @notice Calculated using the Black-Scholes price of active option positions
    function getTokenPrice() public view returns (uint256) {
        if (totalFunds == 0) {
            return 1e18;
        }

        uint256 totalSupply = getTotalSupply();
        if (liveStrikes.length == 0) {
            return totalFunds.divWadDown(totalSupply);
        }

        uint256 totalValue = totalFunds + uint256(totalPremiumCollected);
        for (uint256 i = 0; i < liveStrikes.length; i++) {
            uint256 strikeId = liveStrikes[i];
            PositionData memory position = positionDatas[strikeId];
            (uint256 callPremium, ) = getPremiumForStrike(strikeId);
            totalValue -= callPremium.mulWadDown(position.amount);
        }
        return totalValue.divWadDown(totalSupply);
    }

    /// @notice Returns the total supply of the VAULT_TOKEN
    function getTotalSupply() public view returns (uint256) {
        return VAULT_TOKEN.totalSupply() + totalQueuedWithdrawals;
    }

    /// @notice Returns liveStrikes array
    function getLiveStrikes() public view returns (uint256[] memory) {
        return liveStrikes;
    }

    /// -----------------------------------------------------------------------
    /// Internal View methods
    /// -----------------------------------------------------------------------

    /// @notice Returns the Black-Scholes premium of call and put options
    /// @param _strikeId Lyra Strike ID
    function getPremiumForStrike(uint256 _strikeId)
        internal
        view
        returns (uint256 callPremium, uint256 putPremium)
    {
        (
            IOptionMarket.Strike memory strike,
            IOptionMarket.OptionBoard memory board
        ) = MARKET.getStrikeAndBoard(_strikeId);

        (uint256 spotPrice, bool isInvalid) = RATES.rateAndInvalid(
            UNDERLYING_SYNTH_KEY
        );

        if (spotPrice == 0 || isInvalid) {
            revert();
        }

        if (block.timestamp > board.expiry) {
            (uint256 strikePrice, uint256 priceAtExpiry, ) = MARKET
                .getSettlementParameters(_strikeId);

            if (priceAtExpiry == 0) {
                revert InvalidExpiryPrice();
            }

            callPremium = priceAtExpiry > strikePrice
                ? priceAtExpiry - strikePrice
                : 0;
        } else {
            uint256 boardIv = GREEKS.getIvGWAV(board.id, gwavLength);
            uint256 strikeSkew = GREEKS.getSkewGWAV(_strikeId, gwavLength);
            BlackScholesLib.BlackScholesInputs memory bsInput = BlackScholesLib
                .BlackScholesInputs({
                    timeToExpirySec: board.expiry - block.timestamp,
                    volatilityDecimal: boardIv.mulWadDown(strikeSkew),
                    spotDecimal: spotPrice,
                    strikePriceDecimal: strike.strikePrice,
                    rateDecimal: GREEKS.getGreekCacheParams().rateAndCarry
                });

            (callPremium, putPremium) = BlackScholesLib.optionPrices(bsInput);
        }
    }

    /// @notice Returns the delta of the call option given its strike ID
    /// @param _strikeId Lyra Strike ID
    function getCallDelta(uint256 _strikeId)
        internal
        view
        returns (int256 callDelta)
    {
        (
            IOptionMarket.Strike memory strike,
            IOptionMarket.OptionBoard memory board
        ) = MARKET.getStrikeAndBoard(_strikeId);

        (uint256 spotPrice, bool isInvalid) = RATES.rateAndInvalid(
            UNDERLYING_SYNTH_KEY
        );

        if (spotPrice == 0 || isInvalid) {
            revert InvalidPrice(spotPrice, isInvalid);
        }

        BlackScholesLib.BlackScholesInputs memory bsInput = BlackScholesLib
            .BlackScholesInputs({
                timeToExpirySec: board.expiry - block.timestamp,
                volatilityDecimal: board.iv.mulWadDown(strike.skew),
                spotDecimal: spotPrice,
                strikePriceDecimal: strike.strikePrice,
                rateDecimal: GREEKS.getGreekCacheParams().rateAndCarry
            });

        (callDelta, ) = BlackScholesLib.delta(bsInput);
    }

    /// -----------------------------------------------------------------------
    /// Keeper actions
    /// -----------------------------------------------------------------------

    /// @notice Open a short call position
    /// @param strikeId Lyra strike ID of the call option
    /// @param amount Amount of options to short
    function openPosition(uint256 strikeId, uint256 amount)
        external
        requiresAuth
        nonReentrant
        whenNotPaused
    {
        _openShortPosition(strikeId, amount);
    }

    /// @notice Close an active short call position
    /// @param strikeId Lyra strike ID of the call option
    /// @param amount Amount of options to close
    /// @param premiumAmount Amount of UNDERLYING to convert to sUSD to pay back the premium
    function closePosition(
        uint256 strikeId,
        uint256 amount,
        uint256 premiumAmount
    ) external requiresAuth nonReentrant whenNotPaused {
        _closeShortPosition(strikeId, amount, premiumAmount);
    }

    /// @notice Add additional collateral to an active short position
    /// @param strikeId Lyra strike ID of the call option
    /// @param amount Amount of additional UNDERLYING to add
    function addCollateral(uint256 strikeId, uint256 amount)
        external
        requiresAuth
        nonReentrant
        whenNotPaused
    {
        _addCollateral(strikeId, amount);
    }

    /// @notice Calculat the accounting of settled options
    /// @param strikeIds Array of strike IDs
    function settleOptions(uint256[] memory strikeIds)
        external
        requiresAuth
        nonReentrant
        whenNotPaused
    {
        _settleOptions(strikeIds);
    }

    /// -----------------------------------------------------------------------
    /// Owner actions
    /// -----------------------------------------------------------------------

    /// @notice Pause contracts
    function pause() external requiresAuth {
        _pause();
    }

    /// @notice Pause deposits
    function pauseDeposits() external requiresAuth {
        _pauseDeposits();
    }

    /// @notice Unpause contracts
    function unpause() external requiresAuth {
        _unpause();
    }

    /// @notice Unpause deposits
    function unpauseDeposits() external requiresAuth {
        _unpauseDeposits();
    }

    /// @notice Set collateralization ratio for selling option
    /// @param _ratio Collateralization ratio in 18 decimals
    function setCollateralization(uint256 _ratio) external requiresAuth {
        if (_ratio > 2e18 || _ratio < 5e17) {
            revert InvalidCollateralization(collateralization, _ratio);
        }

        emit UpdateCollateralization(collateralization, _ratio);

        collateralization = _ratio;
    }

    /// @notice Set fee receipient address
    /// @param _feeReceipient Address of the new fee receipient
    function setFeeReceipient(address _feeReceipient) external requiresAuth {
        if (_feeReceipient == address(0x0)) {
            revert ExpectedNonZero();
        }

        emit UpdateFeeReceipient(feeReceipient, _feeReceipient);

        feeReceipient = _feeReceipient;
    }

    /// @notice Set Fees
    /// @param _performanceFee New Performance Fee
    /// @param _withdrawalFee New Withdrawal Fee
    function setFees(uint256 _performanceFee, uint256 _withdrawalFee)
        external
        requiresAuth
    {
        if (_performanceFee > 1e17 || _withdrawalFee > 1e16) {
            revert FeesTooHigh(
                performanceFee,
                withdrawalFee,
                _performanceFee,
                _withdrawalFee
            );
        }

        emit UpdateFees(
            performanceFee,
            withdrawalFee,
            _performanceFee,
            _withdrawalFee
        );

        performanceFee = _performanceFee;
        withdrawalFee = _withdrawalFee;
    }

    /// @notice Set Minimum deposit amount
    /// @param _minAmt Minimum deposit amount
    function setMinDepositAmount(uint256 _minAmt) external requiresAuth {
        emit UpdateMinDeposit(minDepositAmount, _minAmt);
        minDepositAmount = _minAmt;
    }

    /// @notice Set Deposit and Withdrawal delays
    /// @param _depositDelay New Deposit Delay
    /// @param _withdrawDelay New Withdrawal Delay
    function setDelays(uint256 _depositDelay, uint256 _withdrawDelay)
        external
        requiresAuth
    {
        emit UpdateDelays(
            minDepositDelay,
            _depositDelay,
            minWithdrawDelay,
            _withdrawDelay
        );
        minDepositDelay = _depositDelay;
        minWithdrawDelay = _withdrawDelay;
    }

    /// @notice Set GWAV Length
    /// @param _length Length in seconds
    function setGWAVLength(uint256 _length) external requiresAuth {
        emit UpdateGWAVLength(gwavLength, _length);
        gwavLength = _length;
    }

    /// @notice Set Trade iterations
    /// @param _iterations Trade iterations
    function setIterations(uint256 _iterations) external requiresAuth {
        emit UpdateTradeIterations(tradeIterations, _iterations);
        tradeIterations = _iterations;
    }

    /// @notice Set Delta Cutoff
    /// @param _deltaCutoff Delta cutoff value
    function setDeltaCutoff(int256 _deltaCutoff) external requiresAuth {
        if (_deltaCutoff < 5e17) {
            emit UpdateDeltaCutoff(deltaCutoff, _deltaCutoff);
            deltaCutoff = _deltaCutoff;
        }
    }

    /// @notice Save ERC20 token from the vault (not SUSD or UNDERLYING)
    /// @param token Address of the token
    /// @param receiver Address of the receiver
    /// @param amt Amount to save
    function saveToken(
        address token,
        address receiver,
        uint256 amt
    ) external requiresAuth {
        require(token != address(SUSD));
        ERC20(token).transfer(receiver, amt);
    }

    /// -----------------------------------------------------------------------
    /// Internal Methods
    /// -----------------------------------------------------------------------

    function _openShortPosition(uint256 _strikeId, uint256 _amt) internal {
        int256 callDelta = getCallDelta(_strikeId);

        // call options with delta higher than 0.25 should not be traded by the vault
        if (callDelta > deltaCutoff) {
            revert OptionTooRisky(_strikeId, callDelta);
        }

        PositionData storage positionData = positionDatas[_strikeId];

        if (
            positionData.positionId != 0 &&
            OPTION_TOKEN.getApproved(positionData.positionId) !=
            address(MARKET_WRAPPER)
        ) {
            OPTION_TOKEN.approve(
                address(MARKET_WRAPPER),
                positionData.positionId
            );
        }

        (uint256 strikePrice, ) = MARKET.getStrikeAndExpiry(_strikeId);

        uint256 collateralReq = _amt.mulWadDown(strikePrice).mulWadDown(
            collateralization
        );

        usedFunds += collateralReq;

        if (usedFunds > totalFunds) {
            revert InsufficientFunds(
                totalFunds,
                usedFunds - collateralReq,
                collateralReq
            );
        }
        uint256 totalCollateral = positionData.collateral + collateralReq;

        SUSD.safeApprove(address(MARKET_WRAPPER), collateralReq);

        IOptionMarketWrapperWithSwaps.OptionPositionParams memory params;

        params.optionMarket = MARKET;
        params.strikeId = _strikeId;
        params.positionId = positionData.positionId;
        params.iterations = tradeIterations;
        params.setCollateralTo = totalCollateral;
        params.currentCollateral = positionData.collateral;
        params.optionType = OPTION_TYPE;
        params.amount = _amt;
        params.minCost = 0;
        params.maxCost = collateralReq;
        params.inputAmount = collateralReq;
        params.inputAsset = SUSD;

        IOptionMarketWrapperWithSwaps.ReturnDetails
            memory returnDetails = MARKET_WRAPPER.openPosition(params);
        positionData.collateral = totalCollateral;
        positionData.amount += _amt;
        positionData.premiumCollected += int256(returnDetails.totalCost);
        totalPremiumCollected += int256(returnDetails.totalCost);

        if (positionData.positionId == 0) {
            positionData.positionId = returnDetails.positionId;
            liveStrikes.push(_strikeId);
        }

        emit OpenPosition(
            _strikeId,
            positionData.positionId,
            _amt,
            collateralReq,
            returnDetails.totalCost,
            callDelta
        );
    }

    function _closeShortPosition(
        uint256 _strikeId,
        uint256 _amt,
        uint256 _premiumAmt
    ) internal {
        PositionData storage positionData = positionDatas[_strikeId];

        if (
            positionData.positionId == 0 ||
            positionData.amount < _amt ||
            _premiumAmt > uint256(totalPremiumCollected)
        ) {
            revert InvalidCloseRequest(_strikeId, positionData.positionId);
        }

        if (
            OPTION_TOKEN.getApproved(positionData.positionId) !=
            address(MARKET_WRAPPER)
        ) {
            OPTION_TOKEN.approve(
                address(MARKET_WRAPPER),
                positionData.positionId
            );
        }

        uint256 collateralToRemove;
        uint256 totalCollateral;
        (uint256 strikePrice, ) = MARKET.getStrikeAndExpiry(_strikeId);

        if (_amt == positionData.amount) {
            collateralToRemove = positionData.collateral;
        } else {
            collateralToRemove = _amt.mulWadUp(strikePrice).mulWadUp(
                collateralization
            );
            totalCollateral = positionData.collateral - collateralToRemove;
        }

        ERC20(SUSD).safeApprove(address(MARKET_WRAPPER), _premiumAmt);

        IOptionMarketWrapperWithSwaps.OptionPositionParams memory params;

        params.optionMarket = MARKET;
        params.strikeId = _strikeId;
        params.positionId = positionData.positionId;
        params.iterations = tradeIterations;
        params.setCollateralTo = totalCollateral;
        params.currentCollateral = positionData.collateral;
        params.optionType = OPTION_TYPE;
        params.amount = _amt;
        params.minCost = 0;
        params.maxCost = type(uint256).max;
        params.inputAmount = _premiumAmt;
        params.inputAsset = SUSD;

        IOptionMarketWrapperWithSwaps.ReturnDetails
            memory returnDetails = MARKET_WRAPPER.closePosition(params);
        uint256 premiumUsed = returnDetails.totalCost;

        positionData.collateral = totalCollateral;
        positionData.amount -= _amt;
        positionData.premiumCollected -= int256(premiumUsed);

        if (positionData.amount == 0) {
            if (positionData.premiumCollected > 0) {
                uint256 profit = uint256(positionData.premiumCollected);
                uint256 perfFees = profit.mulWadDown(performanceFee);
                ERC20(SUSD).safeTransfer(feeReceipient, perfFees);
                totalFunds += (profit - perfFees);
            } else {
                totalFunds -= uint256(-positionData.premiumCollected);
            }
            positionData.positionId = 0;
            positionData.premiumCollected = 0;
            _removeStrikeId(_strikeId);
        }

        totalPremiumCollected -= int256(premiumUsed);
        usedFunds -= collateralToRemove;

        emit ClosePosition(
            _strikeId,
            positionData.positionId,
            _amt,
            collateralToRemove,
            premiumUsed
        );
    }

    function _addCollateral(uint256 _strikeId, uint256 _amt) internal {
        usedFunds += _amt;

        if (usedFunds > totalFunds) {
            revert InsufficientFunds(totalFunds, usedFunds - _amt, _amt);
        }

        PositionData storage positionData = positionDatas[_strikeId];

        ERC20(SUSD).safeApprove(address(MARKET), _amt);
        MARKET.addCollateral(positionData.positionId, _amt);
        positionData.collateral += _amt;

        emit AddCollateral(_strikeId, positionData.positionId, _amt);
    }

    /// @notice This doesn't actually settle the options, instead it only does the accounting for the settlement
    /// @notice Actual settlement can be done by anyone and doesn't return any data
    /// @notice Because of the above reason, relevant strike ids should be settled separately before calling this method
    function _settleOptions(uint256[] memory _strikeIds) internal {
        for (uint256 i = 0; i < _strikeIds.length; i++) {
            PositionData storage positionData = positionDatas[_strikeIds[i]];

            if (positionData.amount == 0) {
                revert ExpectedNonZero();
            }

            IOptionToken.PositionState optionState = OPTION_TOKEN
                .getPositionState(positionData.positionId);
            if (optionState != IOptionToken.PositionState.SETTLED) {
                revert OptionNotSettled(
                    _strikeIds[i],
                    positionData.positionId,
                    optionState
                );
            }

            (uint256 strikePrice, uint256 priceAtExpiry, ) = MARKET
                .getSettlementParameters(_strikeIds[i]);

            if (priceAtExpiry == 0) {
                revert InvalidExpiryPrice();
            }

            uint256 ammProfit = (priceAtExpiry > strikePrice)
                ? (priceAtExpiry - strikePrice).mulWadDown(positionData.amount)
                : 0;

            if (ammProfit > 0) {
                totalFunds -= ammProfit;
            }

            usedFunds -= positionData.collateral;

            if (positionData.premiumCollected > 0) {
                uint256 profit = uint256(positionData.premiumCollected);
                uint256 perfFees;
                if (ammProfit == 0) {
                    perfFees = profit.mulWadDown(performanceFee);
                    ERC20(SUSD).safeTransfer(feeReceipient, perfFees);
                }
                totalFunds += (profit - perfFees);
                totalPremiumCollected -= int256(profit);
                if (totalPremiumCollected < 0) {
                    totalFunds -= uint256(-totalPremiumCollected);
                    totalPremiumCollected = 0;
                }
            } else {
                totalFunds -= uint256(-positionData.premiumCollected);
            }

            emit SettleOption(
                _strikeIds[i],
                positionData.positionId,
                positionData.amount,
                positionData.collateral,
                positionData.premiumCollected,
                ammProfit
            );

            positionData.positionId = 0;
            positionData.premiumCollected = 0;
            positionData.amount = 0;
            positionData.collateral = 0;

            _removeStrikeId(_strikeIds[i]);
        }
    }

    function _removeStrikeId(uint256 _strikeId) internal {
        uint256 i;
        uint256 n = liveStrikes.length;
        for (i = 0; i < n; i++) {
            if (_strikeId == liveStrikes[i]) {
                break;
            }
        }

        if (i < n) {
            liveStrikes[i] = liveStrikes[n - 1];
            liveStrikes.pop();
        }
    }

    /// -----------------------------------------------------------------------
    /// Errors
    /// -----------------------------------------------------------------------

    /// General
    error InsufficientFunds(
        uint256 totalFunds,
        uint256 usedFunds,
        uint256 requiredFunds
    );
    error ExpectedNonZero();

    /// Trading errors
    error InvalidPrice(uint256 spotPrice, bool isInvalid);
    error InvalidExpiryPrice();
    error InvalidCloseRequest(uint256 strikeId, uint256 positionId);
    error OptionNotSettled(
        uint256 strikeId,
        uint256 positionId,
        IOptionToken.PositionState optionState
    );
    error OptionTooRisky(uint256 strikeId, int256 delta);

    /// Deposit and Withdrawals
    error MinimumDepositRequired(uint256 minDeposit, uint256 requestedAmount);

    /// Owner actions
    error InvalidCollateralization(
        uint256 currentCollateralization,
        uint256 requestedCollateralization
    );
    error FeesTooHigh(
        uint256 currentPerf,
        uint256 currentWithdraw,
        uint256 newPerf,
        uint256 newWithdraw
    );

    /// -----------------------------------------------------------------------
    /// Events
    /// -----------------------------------------------------------------------

    /// @notice Initiate Deposit Event
    /// @param depositId Deposit ID
    /// @param depositor Address of the fund depositor (msg.sender)
    /// @param user Address of the user who'll be getting the VAULT_TOKENs
    /// @param amount Amount depositted (in UNDERLYING)
    event InitiateDeposit(
        uint256 depositId,
        address depositor,
        address user,
        uint256 amount
    );

    /// @notice Process Deposit Event
    /// @param depositId Deposit ID
    /// @param user Address of the user who'll be getting the VAULT_TOKENs
    /// @param amount Amount depositted (in UNDERLYING)
    /// @param tokens Amount of VAULT_TOKENs minted
    /// @param requestedTime Timestamp of the initiateDeposit call
    event ProcessDeposit(
        uint256 depositId,
        address user,
        uint256 amount,
        uint256 tokens,
        uint256 requestedTime
    );

    /// @notice Initiate Withdrawal Event
    /// @param withdrawalId Withdrawal ID
    /// @param withdrawer Address of the user who requested withdraw (msg.sender)
    /// @param user Address of the user who'll be getting UNDERLYING tokens upon processing
    /// @param tokens Amount of VAULT_TOKENs to burn / withdraw
    event InitiateWithdrawal(
        uint256 withdrawalId,
        address withdrawer,
        address user,
        uint256 tokens
    );

    /// @notice Process Withdrawal Event
    /// @param withdrawalId Withdrawal ID
    /// @param user Address of the user who's getting the funds
    /// @param tokens Amount of VAULT_TOKENs burned
    /// @param amount Amount of UNDERLYING returned
    /// @param requestedTime Timestamp of the initiateWithdraw call
    event ProcessWithdrawal(
        uint256 withdrawalId,
        address user,
        uint256 tokens,
        uint256 amount,
        uint256 requestedTime
    );

    /// @notice Process Withdrawal Partially Event
    /// @param withdrawalId Withdrawal ID
    /// @param user Address of the user who's getting the funds
    /// @param tokens Amount of VAULT_TOKENs burned
    /// @param amount Amount of UNDERLYING returned
    /// @param requestedTime Timestamp of the initiateWithdraw call
    event ProcessWithdrawalPartially(
        uint256 withdrawalId,
        address user,
        uint256 tokens,
        uint256 amount,
        uint256 requestedTime
    );

    /// @notice Update Collateralization Event
    /// @param oldCollateralization Old Collateralization
    /// @param newCollateralization New Collateralization
    event UpdateCollateralization(
        uint256 oldCollateralization,
        uint256 newCollateralization
    );

    /// @notice Update Fee Receipient Event
    /// @param oldFeeReceipient Address of the old fee receipient
    /// @param newFeeReceipient Address of the new fee receipient
    event UpdateFeeReceipient(
        address oldFeeReceipient,
        address newFeeReceipient
    );

    /// @notice Update Fees Event
    /// @param oldPerf Old Perfomance Fee
    /// @param oldWithdraw Old Withdrawal Fee
    /// @param newPerf New Performance Fee
    /// @param newWithdraw New Withdrawal Fee
    event UpdateFees(
        uint256 oldPerf,
        uint256 oldWithdraw,
        uint256 newPerf,
        uint256 newWithdraw
    );

    /// @notice Update Minimum Deposit Amount Event
    /// @param oldMinimum Previous minimum deposit amount
    /// @param newMinimum New minimum deposit amount
    event UpdateMinDeposit(uint256 oldMinimum, uint256 newMinimum);

    /// @notice Update Deposit and Withdraw delays Event
    /// @param oldDepositDelay Old Deposit Delay
    /// @param newDepositDelay New Deposit Delay
    /// @param oldWithdrawDelay Old Withdraw Delay
    /// @param newWithdrawDelay New Withdraw Delay
    event UpdateDelays(
        uint256 oldDepositDelay,
        uint256 newDepositDelay,
        uint256 oldWithdrawDelay,
        uint256 newWithdrawDelay
    );

    /// @notice Update GWAV Length
    /// @param oldLength Old Length
    /// @param newLength New Length
    event UpdateGWAVLength(uint256 oldLength, uint256 newLength);

    /// @notice Update Trade Iterations
    /// @param oldIterations Old Iterations
    /// @param newIterations New Iterations
    event UpdateTradeIterations(uint256 oldIterations, uint256 newIterations);

    /// @notice Update Delta Cutoff
    /// @param oldCutoff Old delta cutoff
    /// @param newCutoff New delta cutoff
    event UpdateDeltaCutoff(int256 oldCutoff, int256 newCutoff);

    /// @notice Open Position Event
    /// @param strikeId Lyra Strike ID
    /// @param positionId Corresponding Position ID
    /// @param amount Amount of additional short position
    /// @param collateral Collateral used
    /// @param premiumCollected Premium collected from opening the short position
    /// @param callDelta Call Delta of the option
    event OpenPosition(
        uint256 strikeId,
        uint256 positionId,
        uint256 amount,
        uint256 collateral,
        uint256 premiumCollected,
        int256 callDelta
    );

    /// @notice Close Position Event
    /// @param strikeId Lyra Strike ID
    /// @param positionId Corresponding Position ID
    /// @param amount Amount of short position closed
    /// @param collateralWithdrawn Amount of collateral withdrawn
    /// @param premiumPaid Amount of premium paid to close the position
    event ClosePosition(
        uint256 strikeId,
        uint256 positionId,
        uint256 amount,
        uint256 collateralWithdrawn,
        uint256 premiumPaid
    );

    /// @notice Add Collateral Event
    /// @param strikeId Lyra Strike ID
    /// @param positionId Corresponding Position ID
    /// @param amount Amount of additional collateral added
    event AddCollateral(uint256 strikeId, uint256 positionId, uint256 amount);

    /// @notice Settle Option Event
    /// @param strikeId Lyra Strike ID
    /// @param positionId Corresponding Position ID
    /// @param amount Total amount of options
    /// @param totalCollateral Total collateral
    /// @param totalPremium Total premium collected
    /// @param loss Total loss from the position
    event SettleOption(
        uint256 strikeId,
        uint256 positionId,
        uint256 amount,
        uint256 totalCollateral,
        int256 totalPremium,
        uint256 loss
    );
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract ERC20","name":"_susd","type":"address"},{"internalType":"contract IPolynomialVaultToken","name":"_vaultToken","type":"address"},{"internalType":"contract IOptionMarket","name":"_market","type":"address"},{"internalType":"contract IOptionMarketWrapperWithSwaps","name":"_marketWrapper","type":"address"},{"internalType":"contract IOptionToken","name":"_optionToken","type":"address"},{"internalType":"contract IOptionGreekCache","name":"_greeks","type":"address"},{"internalType":"contract IExchangeRates","name":"_exchangeRates","type":"address"},{"internalType":"bytes32","name":"_underlyingKey","type":"bytes32"},{"internalType":"bytes32","name":"_name","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DepositsNotPaused","type":"error"},{"inputs":[],"name":"DepositsPaused","type":"error"},{"inputs":[],"name":"ExpectedNonZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentPerf","type":"uint256"},{"internalType":"uint256","name":"currentWithdraw","type":"uint256"},{"internalType":"uint256","name":"newPerf","type":"uint256"},{"internalType":"uint256","name":"newWithdraw","type":"uint256"}],"name":"FeesTooHigh","type":"error"},{"inputs":[{"internalType":"uint256","name":"totalFunds","type":"uint256"},{"internalType":"uint256","name":"usedFunds","type":"uint256"},{"internalType":"uint256","name":"requiredFunds","type":"uint256"}],"name":"InsufficientFunds","type":"error"},{"inputs":[{"internalType":"uint256","name":"strikeId","type":"uint256"},{"internalType":"uint256","name":"positionId","type":"uint256"}],"name":"InvalidCloseRequest","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentCollateralization","type":"uint256"},{"internalType":"uint256","name":"requestedCollateralization","type":"uint256"}],"name":"InvalidCollateralization","type":"error"},{"inputs":[],"name":"InvalidExpiryPrice","type":"error"},{"inputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"},{"internalType":"bool","name":"isInvalid","type":"bool"}],"name":"InvalidPrice","type":"error"},{"inputs":[{"internalType":"uint256","name":"minDeposit","type":"uint256"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"name":"MinimumDepositRequired","type":"error"},{"inputs":[],"name":"NotPaused","type":"error"},{"inputs":[{"internalType":"uint256","name":"strikeId","type":"uint256"},{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"enum IOptionToken.PositionState","name":"optionState","type":"uint8"}],"name":"OptionNotSettled","type":"error"},{"inputs":[{"internalType":"uint256","name":"strikeId","type":"uint256"},{"internalType":"int256","name":"delta","type":"int256"}],"name":"OptionTooRisky","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strikeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AddCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strikeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"premiumPaid","type":"uint256"}],"name":"ClosePosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"address","name":"depositor","type":"address"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InitiateDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"withdrawalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"InitiateWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strikeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"premiumCollected","type":"uint256"},{"indexed":false,"internalType":"int256","name":"callDelta","type":"int256"}],"name":"OpenPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestedTime","type":"uint256"}],"name":"ProcessDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"withdrawalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestedTime","type":"uint256"}],"name":"ProcessWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"withdrawalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestedTime","type":"uint256"}],"name":"ProcessWithdrawalPartially","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"SetDepositsPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"SetDepositsUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"SetPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"SetUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strikeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalCollateral","type":"uint256"},{"indexed":false,"internalType":"int256","name":"totalPremium","type":"int256"},{"indexed":false,"internalType":"uint256","name":"loss","type":"uint256"}],"name":"SettleOption","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCollateralization","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCollateralization","type":"uint256"}],"name":"UpdateCollateralization","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldDepositDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDepositDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldWithdrawDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newWithdrawDelay","type":"uint256"}],"name":"UpdateDelays","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int256","name":"oldCutoff","type":"int256"},{"indexed":false,"internalType":"int256","name":"newCutoff","type":"int256"}],"name":"UpdateDeltaCutoff","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldFeeReceipient","type":"address"},{"indexed":false,"internalType":"address","name":"newFeeReceipient","type":"address"}],"name":"UpdateFeeReceipient","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldPerf","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldWithdraw","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPerf","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newWithdraw","type":"uint256"}],"name":"UpdateFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLength","type":"uint256"}],"name":"UpdateGWAVLength","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinimum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinimum","type":"uint256"}],"name":"UpdateMinDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldIterations","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newIterations","type":"uint256"}],"name":"UpdateTradeIterations","type":"event"},{"inputs":[],"name":"GREEKS","outputs":[{"internalType":"contract IOptionGreekCache","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MARKET","outputs":[{"internalType":"contract IOptionMarket","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MARKET_WRAPPER","outputs":[{"internalType":"contract IOptionMarketWrapperWithSwaps","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTION_TOKEN","outputs":[{"internalType":"contract IOptionToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTION_TYPE","outputs":[{"internalType":"enum IOptionMarket.OptionType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATES","outputs":[{"internalType":"contract IExchangeRates","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUSD","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNDERLYING_SYNTH_KEY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_TOKEN","outputs":[{"internalType":"contract IPolynomialVaultToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"strikeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"strikeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"premiumAmount","type":"uint256"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralization","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deltaCutoff","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"depositQueue","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"depositedAmount","type":"uint256"},{"internalType":"uint256","name":"mintedTokens","type":"uint256"},{"internalType":"uint256","name":"requestedTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeReceipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLiveStrikes","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gwavLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"initiateDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"initiateWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"liveStrikes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDepositDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minWithdrawDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextQueuedDepositId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextQueuedWithdrawalId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"strikeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"openPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"performanceFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"positionDatas","outputs":[{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"int256","name":"premiumCollected","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"idCount","type":"uint256"}],"name":"processDepositQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"idCount","type":"uint256"}],"name":"processWithdrawalQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"queuedDepositHead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"queuedWithdrawalHead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"saveToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ratio","type":"uint256"}],"name":"setCollateralization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositDelay","type":"uint256"},{"internalType":"uint256","name":"_withdrawDelay","type":"uint256"}],"name":"setDelays","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"_deltaCutoff","type":"int256"}],"name":"setDeltaCutoff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeReceipient","type":"address"}],"name":"setFeeReceipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_performanceFee","type":"uint256"},{"internalType":"uint256","name":"_withdrawalFee","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"setGWAVLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_iterations","type":"uint256"}],"name":"setIterations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minAmt","type":"uint256"}],"name":"setMinDepositAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"strikeIds","type":"uint256[]"}],"name":"settleOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPremiumCollected","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalQueuedDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalQueuedWithdrawals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeIterations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usedFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawalQueue","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"withdrawnTokens","type":"uint256"},{"internalType":"uint256","name":"returnedAmount","type":"uint256"},{"internalType":"uint256","name":"requestedTime","type":"uint256"}],"stateMutability":"view","type":"function"}]

6101a0604052600160025560016010556001601155600160125560016013553480156200002b57600080fd5b5060405162005a2d38038062005a2d8339810160408190526200004e9162000138565b60008054336001600160a01b03199182168117835560018054909216909155604051909190829081907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908490a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350506003805461ffff191690556001600160a01b0397881660e05295871661010052938616610120529185166101405284166101605283166101805260a052911660c052608052620001f7565b6001600160a01b03811681146200013557600080fd5b50565b60008060008060008060008060006101208a8c0312156200015857600080fd5b895162000165816200011f565b60208b015190995062000178816200011f565b60408b01519098506200018b816200011f565b60608b01519097506200019e816200011f565b60808b0151909650620001b1816200011f565b60a08b0151909550620001c4816200011f565b60c08b0151909450620001d7816200011f565b8093505060e08a015191506101008a015190509295985092959850929598565b60805160a05160c05160e051610100516101205161014051610160516101805161566e620003bf6000396000818161062f01528181613289015261477e0152600081816108ca0152818161347c015281816135370152818161360a015261489d0152600081816108a301528181612a5b01528181612b2701528181613b0401528181613bcd015261417c01526000818161086a01528181612a3701528181612b5401528181612d5501528181612e5901528181613ae001528181613bfa01528181613d810152613ea401526000818161090401528181612bf501528181612d840152818161316b015281816133640152818161391c0152818161397a01528181613c7001528181613db0015281816142780152614660015260008181610503015281816115f00152818161202601528181612329015261262201526000818161044b01528181610f9901528181610fe3015281816110ed0152818161113701528181611b2301528181612188015281816127d201528181612d3301528181612e0a015281816138fa01528181613d5f01528181613e5501528181613fb6015261440601526000818161072b015281816132510152614746015260006103d9015261566e6000f3fe608060405234801561001057600080fd5b50600436106103c55760003560e01c80637a9e5e4b116101ff578063bc0d6c571161011a578063deccdf63116100ad578063f46f16c21161007c578063f46f16c2146108ff578063f7164fc714610926578063fc2da41f1461092f578063fd9d40771461093857600080fd5b8063deccdf6314610895578063e3d51ddd1461089e578063e55d1a52146108c5578063ec552346146108ec57600080fd5b8063c8393ba9116100e9578063c8393ba91461083f578063caca00f414610852578063d2450c7614610865578063d91d2f601461088c57600080fd5b8063bc0d6c57146107ca578063bf7e214f146107dd578063c4e41b22146107f0578063c822adda146107f857600080fd5b80638da4e2f9116101925780639cc621df116101615780639cc621df1461077c578063a8f35adf14610791578063b35648d7146107a4578063b41e20d4146107b757600080fd5b80638da4e2f9146107265780638da5cb5b1461074d578063968ed600146107605780639afdb2c21461076957600080fd5b806387788782116101ce57806387788782146106f6578063892df74f146106ff5780638bc7e8c4146107085780638d3ddf771461071157600080fd5b80637a9e5e4b146106515780637f54b4131461066457806383290a3c146106775780638456cb59146106ee57600080fd5b80634499d14b116102ef5780635c975abb1161028257806370f520811161025157806370f52081146105af578063771126af146105c25780637772ba071461061757806379f67c441461062a57600080fd5b80635c975abb1461057757806360da3e831461058e57806363d8882a1461059e578063645006ca146105a657600080fd5b80634b94f50e116102be5780634b94f50e1461054a5780634d8737cb146105525780634ffaa7361461056557806358f67c0b1461056e57600080fd5b80634499d14b146104fe578063481bf0b814610525578063499d75d81461052e5780634b48f20d1461053757600080fd5b8063208e7e9311610367578063342c00b311610336578063342c00b3146104c757806335f748c2146104da5780633740ebb3146104e35780633f4ba83a146104f657600080fd5b8063208e7e93146104855780632a80cda31461048e5780632b6fcf2e146104a15780633012b05c146104b457600080fd5b80630b78f9c0116103a35780630b78f9c01461041757806313af40351461042a57806315a01bc11461043d57806315d8eeba1461044657600080fd5b806302191980146103ca57806306fdde03146103d45780630b2ad0881461040e575b600080fd5b6103d2610941565b005b6103fb7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6103fb60135481565b6103d2610425366004614c52565b6109b9565b6103d2610438366004614c89565b610aeb565b6103fb60155481565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610405565b6103fb60105481565b6103d261049c366004614ca6565b610bb7565b6103d26104af366004614ca6565b610c61565b6103d26104c2366004614c52565b610d0b565b6103d26104d5366004614ca6565b610e1a565b6103fb60065481565b600b5461046d906001600160a01b031681565b6103d26111f9565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103fb600f5481565b6103fb600a5481565b6103d2610545366004614c89565b61126a565b6103fb611394565b6103d2610560366004614ca6565b6114ac565b6103fb60095481565b6103fb600e5481565b60035460ff165b6040519015158152602001610405565b600354610100900460ff1661057e565b6103d26116f3565b6103fb60055481565b6103d26105bd366004614ca6565b611764565b6105f76105d0366004614ca6565b60186020526000908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610405565b6103d2610625366004614c52565b611822565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103d261065f366004614c89565b6118e1565b6103fb610672366004614ca6565b611a26565b6106be610685366004614ca6565b6019602052600090815260409020805460018201546002830154600384015460049094015492936001600160a01b039092169290919085565b604080519586526001600160a01b039094166020860152928401919091526060830152608082015260a001610405565b6103d2611a47565b6103fb600c5481565b6103fb60125481565b6103fb600d5481565b610719600381565b6040516104059190614d02565b6103fb7f000000000000000000000000000000000000000000000000000000000000000081565b60005461046d906001600160a01b031681565b6103fb60145481565b6103d2610777366004614d10565b611ab8565b610784611c01565b6040516104059190614d51565b6103d261079f366004614c52565b611c59565b6103d26107b2366004614d95565b611d5f565b6103d26107c5366004614ca6565b611e70565b6103d26107d8366004614ed4565b611f1a565b60015461046d906001600160a01b031681565b6103fb61201f565b6106be610806366004614ca6565b601a602052600090815260409020805460018201546002830154600384015460049094015492936001600160a01b039092169290919085565b6103d261084d366004614f6a565b6120c4565b6103d2610860366004614ca6565b612396565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103fb60045481565b6103fb60085481565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103d26108fa366004614f6a565b61249f565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103fb60165481565b6103fb60115481565b6103fb60075481565b61096f336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b6109af5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b6109b76128f5565b565b6109e7336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b610a225760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b67016345785d8a0000821180610a3e5750662386f26fc1000081115b15610a9257600c54600d546040517f0995039e0000000000000000000000000000000000000000000000000000000081526004810192909252602482015260448101839052606481018290526084016109a6565b600c54600d546040805192835260208301919091528101839052606081018290527f5c3aee3d65f7eb02cded951435d06b06ef307bc7f57b98975c4a41dc116e711c9060800160405180910390a1600c91909155600d55565b610b19336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b610b545760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b610be5336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b610c205760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b60055460408051918252602082018390527f915e1f57375bebe5483299c788956d167e46a28a143974dc29bba5a420aa4354910160405180910390a1600555565b610c8f336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b610cca5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b60085460408051918252602082018390527f40777929ad14ec610067fc9c075e20805fe1c57e1879cf2b583355109971c546910160405180910390a1600855565b610d39336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b610d745760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600254600114610dc65760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560035460ff1615610e07576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e118282612999565b50506001600255565b600254600114610e6c5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560005b81811015610e11576000610e85611394565b6012546000908152601a602052604090206004810154919250901580610ebb57506007548160040154610eb89190614fc5565b42105b15610ec8575050506111f1565b6000601554601454610eda9190614fdd565b905080610eea57505050506111f1565b6002820154600090610efc9085612fea565b90508181111561107757600383018290556000610f198386613006565b905080600f6000828254610f2d9190614fdd565b9250508190555080846002016000828254610f489190614fdd565b925050819055508260146000828254610f619190614fdd565b9091555050600d5415610fd0576000610f85600d5485612fea90919063ffffffff16565b600b54909150610fc2906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168361301b565b610fcc8185614fdd565b9350505b600184015461100c906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168561301b565b835460018501546004860154604080519384526001600160a01b039092166020840152828201849052606083018690526080830152517f36a40db5d5631acd8e2764bd196c60dd82faed72aea6647297ab6af63309b58e9181900360a00190a15050505050506111f1565b600383018190556002830154600f8054600090611095908490614fdd565b9091555050600060028401819055601480548392906110b5908490614fdd565b9091555050600d54156111245760006110d9600d5483612fea90919063ffffffff16565b600b54909150611116906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168361301b565b6111208183614fdd565b9150505b6001830154611160906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168361301b565b8254600184015460028501546004860154604080519485526001600160a01b039093166020850152918301526060820183905260808201527f86dc3fd2a6c267674f2f2ef1b4b7283dcca31e1e2517a55358795c65eca1fe039060a00160405180910390a1601280549060006111d583614ff4565b91905055505050505080806111e990614ff4565b915050610e73565b506001600255565b611227336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b6112625760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6109b76130ba565b611298336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b6112d35760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6001600160a01b038116611313576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b54604080516001600160a01b03928316815291831660208301527fc8bc890a52e17e373db7ac75d8f97911a18bffc2ef18bd8047ed55770ee6ba8b910160405180910390a1600b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000601454600014156113ae5750670de0b6b3a764000090565b60006113b861201f565b6017549091506113d5576014546113cf908261314e565b91505090565b60006016546014546113e79190614fc5565b905060005b60175481101561149a5760006017828154811061140b5761140b61502d565b600091825260208083209091015480835260188252604080842081516080810183528154815260018201549481019490945260028101549184019190915260030154606083015292509061145e83613163565b509050611478826020015182612fea90919063ffffffff16565b6114829086614fdd565b9450505050808061149290614ff4565b9150506113ec565b506114a5818361314e565b9250505090565b6002546001146114fe5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b60028055600061150c611394565b905060005b828110156116e95760105460009081526019602052604090206004810154158061154b575060065481600401546115489190614fc5565b42105b15611558575050506111f1565b600281015460009061156a908561314e565b90508082600301819055508160020154600e600082825461158b9190614fdd565b90915550506002820154601480546000906115a7908490614fc5565b909155505060018201546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152602481018390527f0000000000000000000000000000000000000000000000000000000000000000909116906340c10f1990604401600060405180830381600087803b15801561163657600080fd5b505af115801561164a573d6000803e3d6000fd5b505083546001850154600286015460038701546004880154604080519586526001600160a01b0390941660208601528484019290925260608401526080830152517f4d356a2d534287c80daa3bb725dcc09c0ad1049e50c1e328646c49e5a0b2c6cb93509081900360a0019150a160006002830181905560108054916116cf83614ff4565b9190505550505080806116e190614ff4565b915050611511565b5050506001600255565b611721336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b61175c5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6109b7613779565b611792336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b6117cd5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6706f05b59d3b2000081121561181f57600a5460408051918252602082018390527fbfc81c1ba7d829304f63f4bffe5910955b03f6951f1177ba93883cff15a40567910160405180910390a1600a8190555b50565b611850336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b61188b5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6006546007546040805192835260208301859052820152606081018290527fc8f5f7dffddfef257dee57a6cd0384a4900f2ab48c3e69766faa5577e6a7cbcb9060800160405180910390a1600691909155600755565b6000546001600160a01b03163314806119b957506001546040517fb70096130000000000000000000000000000000000000000000000000000000081523360048201523060248201526000357fffffffff000000000000000000000000000000000000000000000000000000001660448201526001600160a01b039091169063b70096139060640160206040518083038186803b15801561198157600080fd5b505afa158015611995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b99190615071565b6119c257600080fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b60178181548110611a3657600080fd5b600091825260209091200154905081565b611a75336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b611ab05760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6109b7613812565b611ae6336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b611b215760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161415611b6057600080fd5b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b158015611bc357600080fd5b505af1158015611bd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bfb9190615071565b50505050565b60606017805480602002602001604051908101604052809291908181526020018280548015611c4f57602002820191906000526020600020905b815481526020019060010190808311611c3b575b5050505050905090565b611c87336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b611cc25760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600254600114611d145760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560035460ff1615611d55576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e1182826138ab565b611d8d336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b611dc85760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600254600114611e1a5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560035460ff1615611e5b576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e66838383613a3f565b5050600160025550565b611e9e336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b611ed95760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b60095460408051918252602082018390527ff53b0be70f27baabf334832258c8da935a270674357a3d0e51ad87896efbc654910160405180910390a1600955565b611f48336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b611f835760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600254600114611fd55760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560035460ff1615612016576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111f1816140cc565b6000600f547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561207d57600080fd5b505afa158015612091573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b5919061508c565b6120bf9190614fc5565b905090565b6002546001146121165760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b600280556001600160a01b03821661215a576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175461222457600061216b611394565b905060006121798383612fea565b90506121af6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016858361301b565b80601460008282546121c19190614fdd565b909155505060408051600081526001600160a01b0386166020820152908101849052606081018290524260808201527f86dc3fd2a6c267674f2f2ef1b4b7283dcca31e1e2517a55358795c65eca1fe039060a00160405180910390a150506122f4565b601380546000818152601a60205260408120929061224183614ff4565b9091555081556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03851617905560028101829055426004820155600f805483919060009061229e908490614fc5565b90915550508054604080519182523360208301526001600160a01b0385168282015260608201849052517f6af4b9a67fcdcb6bdd58b7b26c00492d52c66372d350d228ec6a5420bb13fe329181900360800190a1505b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac90604401600060405180830381600087803b15801561237557600080fd5b505af1158015612389573d6000803e3d6000fd5b5050600160025550505050565b6123c4336000357fffffffff00000000000000000000000000000000000000000000000000000000166127fa565b6123ff5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b671bc16d674ec8000081118061241c57506706f05b59d3b2000081105b1561245e57600480546040517f618e3d2d00000000000000000000000000000000000000000000000000000000815291820152602481018290526044016109a6565b60045460408051918252602082018390527f7cbf954c53f0cfe32163baacd57a397c9a307b23673e8dbb6e84fe0ea1f5e59d910160405180910390a1600455565b6002546001146124f15760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b60028055600354610100900460ff1615612537576040517fdeeb694300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038216612577576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005548110156125c1576005546040517f54443ec40000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016109a6565b6017546126f55760006125d2611394565b905060006125e0838361314e565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152602482018390529192507f0000000000000000000000000000000000000000000000000000000000000000909116906340c10f1990604401600060405180830381600087803b15801561266857600080fd5b505af115801561267c573d6000803e3d6000fd5b5050505082601460008282546126929190614fc5565b909155505060408051600081526001600160a01b0386166020820152908101849052606081018290524260808201527f4d356a2d534287c80daa3bb725dcc09c0ad1049e50c1e328646c49e5a0b2c6cb9060a00160405180910390a150506127c5565b601180546000818152601960205260408120929061271283614ff4565b9091555081556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03851617905560028101829055426004820155600e805483919060009061276f908490614fc5565b90915550508054604080519182523360208301526001600160a01b0385168282015260608201849052517f1ccb85c4426dacaaa67edc2ae6421283328736c96dd21b82026889d72414832c9181900360800190a1505b610e116001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330846145ad565b6001546000906001600160a01b031680158015906128d357506040517fb70096130000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301523060248301527fffffffff000000000000000000000000000000000000000000000000000000008516604483015282169063b70096139060640160206040518083038186803b15801561289b57600080fd5b505afa1580156128af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d39190615071565b806128eb57506000546001600160a01b038581169116145b9150505b92915050565b600354610100900460ff1615612937576040517fdeeb694300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556040513381527fcb92ca4a4d7ab7e82e1f35164d09a91663f3393b45f06fcac5a73f63ae6bf23f906020015b60405180910390a1565b60006129a483614659565b9050600a548113156129ec576040517fdc818acd00000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044016109a6565b6000838152601860205260409020805415801590612af0575080546040517f081812fc0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116927f00000000000000000000000000000000000000000000000000000000000000009091169163081812fc91612a949160040190815260200190565b60206040518083038186803b158015612aac57600080fd5b505afa158015612ac0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae491906150b0565b6001600160a01b031614155b15612bc35780546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163095ea7b391612b90917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015612baa57600080fd5b505af1158015612bbe573d6000803e3d6000fd5b505050505b6040517fcf6bcba0000000000000000000000000000000000000000000000000000000008152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063cf6bcba090602401604080518083038186803b158015612c3e57600080fd5b505afa158015612c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7691906150cd565b5090506000612c9a600454612c948488612fea90919063ffffffff16565b90612fea565b90508060156000828254612cae9190614fc5565b90915550506014546015541115612d125760145481601554612cd09190614fdd565b6040517ff5623b7200000000000000000000000000000000000000000000000000000000815260048101929092526024820152604481018290526064016109a6565b6000818460020154612d249190614fc5565b9050612d7a6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000084614a06565b612d82614bce565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020810188905284546040820152600954606082015260808101829052600285015460a0820152600360c082018190525060e0810187905260006101008201819052610120820184905261014082018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166101608401526040517f8bc369690000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000090911690638bc3696990612e909085906004016150f1565b61010060405180830381600087803b158015612eab57600080fd5b505af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ee3919061518e565b905082866002018190555087866001016000828254612f029190614fc5565b90915550506080810151600387018054600090612f20908490615235565b9091555050608081015160168054600090612f3c908490615235565b90915550508554612f845760208101518655601780546001810182556000919091527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c15018990555b8554608082810151604080518d8152602081019490945283018b9052606083018790529082015260a081018890527f1bd03927c37312e9dc9bb94d819a9ee53bdbc8ad5a7b6dc25074b02f3908b3539060c00160405180910390a1505050505050505050565b6000612fff8383670de0b6b3a7640000614aa5565b9392505050565b6000612fff83670de0b6b3a764000084614ac4565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611bfb5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016109a6565b60035460ff166130f6576040517f6cd6020100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556040513381527f3bd4fb9a28883a4c90034f2cd214c1f94fc09854604f38dee6a87e5455e2123b9060200161298f565b6000612fff83670de0b6b3a764000084614aa5565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4c4a0d0866040518263ffffffff1660e01b81526004016131b791815260200190565b60006040518083038186803b1580156131cf57600080fd5b505afa1580156131e3573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526132299190810190615374565b6040517f0c71cd230000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152919350915060009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630c71cd2390602401604080518083038186803b1580156132ca57600080fd5b505afa1580156132de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613302919061542e565b9150915081600014806133125750805b1561331c57600080fd5b826020015142111561343f576040517f1fdb6cbd0000000000000000000000000000000000000000000000000000000081526004810188905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631fdb6cbd9060240160606040518083038186803b1580156133a657600080fd5b505afa1580156133ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133de919061545a565b5091509150806000141561341e576040517f30c7646e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81811161342c576000613436565b6134368282614fdd565b97505050613770565b82516008546040517ff3fd9b3d000000000000000000000000000000000000000000000000000000008152600481019290925260248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f3fd9b3d9060440160206040518083038186803b1580156134c657600080fd5b505afa1580156134da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fe919061508c565b6008546040517f7df712680000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691637df7126891613575918d91600401918252602082015260400190565b60206040518083038186803b15801561358d57600080fd5b505afa1580156135a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c5919061508c565b905060006040518060a001604052804288602001516135e49190614fdd565b81526020016135f38585612fea565b8152602001868152602001886020015181526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f369f2ac6040518163ffffffff1660e01b81526004016101406040518083038186803b15801561366257600080fd5b505afa158015613676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369a9190615488565b61012001519052604080517fbcf1e77900000000000000000000000000000000000000000000000000000000815282516004820152602083015160248201529082015160448201526060820151606482015260808201516084820152909150730052a341bea99c4b452816235fc2216143c5f21c9063bcf1e7799060a401604080518083038186803b15801561372f57600080fd5b505af4158015613743573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376791906150cd565b90995097505050505b50505050915091565b600354610100900460ff166137ba576040517fa4d3098c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690556040513381527fd9b17f88c19eed029496a647acd647444182c708871dadb0b13c8db2bbcdff369060200161298f565b60035460ff161561384f576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790556040513381527ff87d42f34d6dc854596ee7e10d09f6ef97f38e4ab22330c4fcb384c7e7f81d199060200161298f565b80601560008282546138bd9190614fc5565b909155505060145460155411156138df5760145481601554612cd09190614fdd565b60008281526018602052604090206139416001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000084614a06565b80546040517fa8f35adf0000000000000000000000000000000000000000000000000000000081526004810191909152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a8f35adf90604401600060405180830381600087803b1580156139c657600080fd5b505af11580156139da573d6000803e3d6000fd5b50505050818160020160008282546139f29190614fc5565b9091555050805460408051858152602081019290925281018390527f8dedd193eae1d427fb5f6ae4dcd87fa15d38eabb7ecf00bf9c85a8f692d709dc9060600160405180910390a1505050565b600083815260186020526040902080541580613a5e5750828160010154105b80613a6a575060165482115b15613aae5780546040517f1e61e6a70000000000000000000000000000000000000000000000000000000081526109a6918691600401918252602082015260400190565b80546040517f081812fc0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116927f00000000000000000000000000000000000000000000000000000000000000009091169163081812fc91613b3d9160040190815260200190565b60206040518083038186803b158015613b5557600080fd5b505afa158015613b69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8d91906150b0565b6001600160a01b031614613c695780546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163095ea7b391613c36917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015613c5057600080fd5b505af1158015613c64573d6000803e3d6000fd5b505050505b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cf6bcba0886040518263ffffffff1660e01b8152600401613cbc91815260200190565b604080518083038186803b158015613cd357600080fd5b505afa158015613ce7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d0b91906150cd565b5090508360010154861415613d265783600201549250613d52565b600454613d3d90613d378884614af2565b90614af2565b9250828460020154613d4f9190614fdd565b91505b613da66001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000087614a06565b613dae614bce565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020810188905284546040820152600954606082015260808101839052600285015460a0820152600360c082018190525060e08101879052600061010082018190527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61012083015261014082018790526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166101608401526040517fb738a96b0000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000009091169063b738a96b90613edb9085906004016150f1565b61010060405180830381600087803b158015613ef657600080fd5b505af1158015613f0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f2e919061518e565b905060008160800151905084876002018190555088876001016000828254613f569190614fdd565b9250508190555080876003016000828254613f71919061550f565b9091555050600187015461403f57600087600301541315614007576003870154600c54600090613fa2908390612fea565b600b54909150613fdf906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168361301b565b613fe98183614fdd565b60146000828254613ffa9190614fc5565b9091555061402c92505050565b866003015461401590615583565b601460008282546140269190614fdd565b90915550505b6000808855600388015561403f8a614b07565b8060166000828254614051919061550f565b92505081905550856015600082825461406a9190614fdd565b90915550508654604080518c8152602081019290925281018a905260608101879052608081018290527fee19d4dcc15e899950ecf28027eee5796688964dc923320a7eedcfc95abfc7a29060a00160405180910390a150505050505050505050565b60005b81518110156145a9576000601860008484815181106140f0576140f061502d565b602002602001015181526020019081526020016000209050806001015460001415614147576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80546040517feb29dc5e0000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163eb29dc5e916141b39160040190815260200190565b60206040518083038186803b1580156141cb57600080fd5b505afa1580156141df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061420391906155bc565b9050600481600581111561421957614219614cbf565b14614273578383815181106142305761423061502d565b60200260200101518260000154826040517f25c1b4cf0000000000000000000000000000000000000000000000000000000081526004016109a6939291906155dd565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631fdb6cbd8787815181106142b7576142b761502d565b60200260200101516040518263ffffffff1660e01b81526004016142dd91815260200190565b60606040518083038186803b1580156142f557600080fd5b505afa158015614309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061432d919061545a565b5091509150806000141561436d576040517f30c7646e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082821161437d576000614390565b600185015461439090612c948585614fdd565b905080156143b05780601460008282546143aa9190614fdd565b90915550505b8460020154601560008282546143c69190614fdd565b90915550506003850154600012156144a257600385015460008261442f57600c546143f2908390612fea565b600b5490915061442f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168361301b565b6144398183614fdd565b6014600082825461444a9190614fc5565b925050819055508160166000828254614463919061550f565b90915550506016546000131561449b5760165461447f90615583565b601460008282546144909190614fdd565b909155505060006016555b50506144c7565b84600301546144b090615583565b601460008282546144c19190614fdd565b90915550505b7f5c7fe62083bc914e5249c3b877823e54536d036c26578aa386223d00f9db704c8787815181106144fa576144fa61502d565b602002602001015186600001548760010154886002015489600301548660405161454c96959493929190958652602086019490945260408501929092526060840152608083015260a082015260c00190565b60405180910390a16000808655600386018190556001860181905560028601558651614591908890889081106145845761458461502d565b6020026020010151614b07565b505050505080806145a190614ff4565b9150506140cf565b5050565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806146525760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064016109a6565b5050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4c4a0d0856040518263ffffffff1660e01b81526004016146ac91815260200190565b60006040518083038186803b1580156146c457600080fd5b505afa1580156146d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261471e9190810190615374565b6040517f0c71cd230000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152919350915060009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630c71cd2390602401604080518083038186803b1580156147bf57600080fd5b505afa1580156147d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147f7919061542e565b9150915081600014806148075750805b15614849576040517f7ba847270000000000000000000000000000000000000000000000000000000081526004810183905281151560248201526044016109a6565b60006040518060a001604052804286602001516148669190614fdd565b815260200161488687604001518760400151612fea90919063ffffffff16565b8152602001848152602001866020015181526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f369f2ac6040518163ffffffff1660e01b81526004016101406040518083038186803b1580156148f557600080fd5b505afa158015614909573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061492d9190615488565b61012001519052604080517fdc1f2cd800000000000000000000000000000000000000000000000000000000815282516004820152602083015160248201529082015160448201526060820151606482015260808201516084820152909150730052a341bea99c4b452816235fc2216143c5f21c9063dc1f2cd89060a401604080518083038186803b1580156149c257600080fd5b505af41580156149d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149fa91906150cd565b50979650505050505050565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611bfb5760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c454400000000000000000000000000000000000060448201526064016109a6565b828202811515841585830485141716614abd57600080fd5b0492915050565b828202811515841585830485141716614adc57600080fd5b6001826001830304018115150290509392505050565b6000612fff8383670de0b6b3a7640000614ac4565b6017546000905b80821015614b525760178281548110614b2957614b2961502d565b9060005260206000200154831415614b4057614b52565b81614b4a81614ff4565b925050614b0e565b80821015614bc9576017614b67600183614fdd565b81548110614b7757614b7761502d565b906000526020600020015460178381548110614b9557614b9561502d565b6000918252602090912001556017805480614bb257614bb2615609565b600190038181906000526020600020016000905590555b505050565b60405180610180016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160006004811115614c2057614c20614cbf565b81526020016000815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b60008060408385031215614c6557600080fd5b50508035926020909101359150565b6001600160a01b038116811461181f57600080fd5b600060208284031215614c9b57600080fd5b8135612fff81614c74565b600060208284031215614cb857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60058110614cfe57614cfe614cbf565b9052565b602081016128ef8284614cee565b600080600060608486031215614d2557600080fd5b8335614d3081614c74565b92506020840135614d4081614c74565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b81811015614d8957835183529284019291840191600101614d6d565b50909695505050505050565b600080600060608486031215614daa57600080fd5b505081359360208301359350604090920135919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715614e1357614e13614dc1565b60405290565b604051610120810167ffffffffffffffff81118282101715614e1357614e13614dc1565b604051610140810167ffffffffffffffff81118282101715614e1357614e13614dc1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614ea857614ea8614dc1565b604052919050565b600067ffffffffffffffff821115614eca57614eca614dc1565b5060051b60200190565b60006020808385031215614ee757600080fd5b823567ffffffffffffffff811115614efe57600080fd5b8301601f81018513614f0f57600080fd5b8035614f22614f1d82614eb0565b614e61565b81815260059190911b82018301908381019087831115614f4157600080fd5b928401925b82841015614f5f57833582529284019290840190614f46565b979650505050505050565b60008060408385031215614f7d57600080fd5b8235614f8881614c74565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115614fd857614fd8614f96565b500190565b600082821015614fef57614fef614f96565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561502657615026614f96565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051801515811461506c57600080fd5b919050565b60006020828403121561508357600080fd5b612fff8261505c565b60006020828403121561509e57600080fd5b5051919050565b805161506c81614c74565b6000602082840312156150c257600080fd5b8151612fff81614c74565b600080604083850312156150e057600080fd5b505080516020909101519092909150565b81516001600160a01b0316815261018081016020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015161514760c0840182614cee565b5060e08381015190830152610100808401519083015261012080840151908301526101408084015190830152610160928301516001600160a01b0316929091019190915290565b60006101008083850312156151a257600080fd5b6040519081019067ffffffffffffffff821181831017156151c5576151c5614dc1565b81604052835191506151d682614c74565b818152602084015160208201526151ef604085016150a5565b6040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c082015261522860e085016150a5565b60e0820152949350505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561526f5761526f614f96565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156152a3576152a3614f96565b50500190565b600060a082840312156152bb57600080fd5b6152c3614df0565b90508151815260208083015181830152604083015160408301526152e96060840161505c565b6060830152608083015167ffffffffffffffff81111561530857600080fd5b8301601f8101851361531957600080fd5b8051615327614f1d82614eb0565b81815260059190911b8201830190838101908783111561534657600080fd5b928401925b828410156153645783518252928401929084019061534b565b6080860152509295945050505050565b60008082840361014081121561538957600080fd5b6101208082121561539957600080fd5b6153a1614e19565b9150845182526020850151602083015260408501516040830152606085015160608301526080850151608083015260a085015160a083015260c085015160c083015260e085015160e08301526101008086015181840152508193508085015191505067ffffffffffffffff81111561541857600080fd5b615424858286016152a9565b9150509250929050565b6000806040838503121561544157600080fd5b825191506154516020840161505c565b90509250929050565b60008060006060848603121561546f57600080fd5b8351925060208401519150604084015190509250925092565b6000610140828403121561549b57600080fd5b6154a3614e3d565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152508091505092915050565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561554957615549614f96565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561557d5761557d614f96565b50500390565b60007f80000000000000000000000000000000000000000000000000000000000000008214156155b5576155b5614f96565b5060000390565b6000602082840312156155ce57600080fd5b815160068110612fff57600080fd5b8381526020810183905260608101600683106155fb576155fb614cbf565b826040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212208658eba0811b3d065947163ce9e8140feba7a4558037c2af6364122a43041ab064736f6c634300080900330000000000000000000000008c6f28f2f1a3c87f0f938b96d27520d9751ec8d9000000000000000000000000835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60000000000000000000000001d42a98848e022908069c2c545ae44cc78509bc8000000000000000000000000cce7819d65f348c64b7beb205ba367b3fe33763b000000000000000000000000cfdff4e171133d55de2e45c66a0e144a135d93f2000000000000000000000000bb3e8eac35e649ed1071a9ec42223d474e67b19a00000000000000000000000022602469d704bffb0936c7a7cfcd18f7aa2693757345544800000000000000000000000000000000000000000000000000000000734554482043616c6c2053656c6c696e672051756f7465000000000000000000

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000008c6f28f2f1a3c87f0f938b96d27520d9751ec8d9000000000000000000000000835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac60000000000000000000000001d42a98848e022908069c2c545ae44cc78509bc8000000000000000000000000cce7819d65f348c64b7beb205ba367b3fe33763b000000000000000000000000cfdff4e171133d55de2e45c66a0e144a135d93f2000000000000000000000000bb3e8eac35e649ed1071a9ec42223d474e67b19a00000000000000000000000022602469d704bffb0936c7a7cfcd18f7aa2693757345544800000000000000000000000000000000000000000000000000000000734554482043616c6c2053656c6c696e672051756f7465000000000000000000

-----Decoded View---------------
Arg [0] : _susd (address): 0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9
Arg [1] : _vaultToken (address): 0x835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac6
Arg [2] : _market (address): 0x1d42a98848e022908069c2c545ae44cc78509bc8
Arg [3] : _marketWrapper (address): 0xcce7819d65f348c64b7beb205ba367b3fe33763b
Arg [4] : _optionToken (address): 0xcfdff4e171133d55de2e45c66a0e144a135d93f2
Arg [5] : _greeks (address): 0xbb3e8eac35e649ed1071a9ec42223d474e67b19a
Arg [6] : _exchangeRates (address): 0x22602469d704bffb0936c7a7cfcd18f7aa269375
Arg [7] : _underlyingKey (bytes32): 0x7345544800000000000000000000000000000000000000000000000000000000
Arg [8] : _name (bytes32): 0x734554482043616c6c2053656c6c696e672051756f7465000000000000000000

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000008c6f28f2f1a3c87f0f938b96d27520d9751ec8d9
Arg [1] : 000000000000000000000000835afb7b0f1f3a0df0ecdc7a4cf86b7894072ac6
Arg [2] : 0000000000000000000000001d42a98848e022908069c2c545ae44cc78509bc8
Arg [3] : 000000000000000000000000cce7819d65f348c64b7beb205ba367b3fe33763b
Arg [4] : 000000000000000000000000cfdff4e171133d55de2e45c66a0e144a135d93f2
Arg [5] : 000000000000000000000000bb3e8eac35e649ed1071a9ec42223d474e67b19a
Arg [6] : 00000000000000000000000022602469d704bffb0936c7a7cfcd18f7aa269375
Arg [7] : 7345544800000000000000000000000000000000000000000000000000000000
Arg [8] : 734554482043616c6c2053656c6c696e672051756f7465000000000000000000


Library Used

BlackScholesLib : 0x0052a341bea99c4b452816235fc2216143c5f21c

Deployed ByteCode Sourcemap

75580:41090:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95103:82;;;:::i;:::-;;77201:29;;;;;;;;160:25:1;;;148:2;133:18;77201:29:0;;;;;;;;79493:41;;;;;;96415:615;;;;;;:::i;:::-;;:::i;2109:151::-;;;;;;:::i;:::-;;:::i;79634:24::-;;;;;;77376:27;;;;;;;;-1:-1:-1;;;;;1358:55:1;;;1340:74;;1328:2;1313:18;77376:27:0;1181:239:1;79147:36:0;;;;;;97129:172;;;;;;:::i;:::-;;:::i;97905:154::-;;;;;;:::i;:::-;;:::i;93373:201::-;;;;;;:::i;:::-;;:::i;85630:2890::-;;;;;;:::i;:::-;;:::i;78368:30::-;;;;;;78732:28;;;;;-1:-1:-1;;;;;78732:28:0;;;95228:70;;;:::i;77455:50::-;;;;;79033:37;;;;;;78666:25;;;;;;95991:288;;;;;;:::i;:::-;;:::i;88838:745::-;;;:::i;84388:1114::-;;;;;;:::i;:::-;;:::i;78586:30::-;;;;;;78948:34;;;;;;24846:86;24917:7;;;;24846:86;;;2446:14:1;;2439:22;2421:41;;2409:2;2394:18;24846:86:0;2281:187:1;24940:102:0;25019:15;;;;;;;24940:102;;95340:86;;;:::i;78289:31::-;;;;;;98421:227;;;;;;:::i;:::-;;:::i;79880:53::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2886:25:1;;;2942:2;2927:18;;2920:34;;;;2970:18;;;2963:34;3028:2;3013:18;;3006:34;2873:3;2858:19;79880:53:0;2657:389:1;97460:362:0;;;;;;:::i;:::-;;:::i;77930:37::-;;;;;1659:442;;;;;;:::i;:::-;;:::i;79799:28::-;;;;;;:::i;:::-;;:::i;79973:53::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;79973:53:0;;;;;;;;;;;;;3832:25:1;;;-1:-1:-1;;;;;3893:55:1;;;3888:2;3873:18;;3866:83;3965:18;;;3958:34;;;;4023:2;4008:18;;4001:34;4066:3;4051:19;;4044:35;3819:3;3804:19;79973:53:0;3573:512:1;94997:66:0;;;:::i;78802:29::-;;;;;;79376:39;;;;;;78872:28;;;;;;76843:105;;76907:41;76843:105;;;;;;;;;:::i;77300:45::-;;;;;680:20;;;;;-1:-1:-1;;;;;680:20:0;;;79572:25;;;;;;98857:218;;;;;;:::i;:::-;;:::i;89835:102::-;;;:::i;:::-;;;;;;;:::i;94272:198::-;;;;;;:::i;:::-;;:::i;93838:234::-;;;;;;:::i;:::-;;:::i;98150:181::-;;;;;;:::i;:::-;;:::i;94584:185::-;;;;;;:::i;:::-;;:::i;709:26::-;;;;;-1:-1:-1;;;;;709:26:0;;;89652:132;;;:::i;80069:57::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;80069:57:0;;;;;;;;;83016:1250;;;;;;:::i;:::-;;:::i;95560:314::-;;;;;;:::i;:::-;;:::i;77640:61::-;;;;;78208:32;;;;;;78518:25;;;;;;77745:42;;;;;77838:41;;;;;81350:1288;;;;;;:::i;:::-;;:::i;77550:37::-;;;;;79708:35;;;;;;79258:38;;;;;;78449:31;;;;;;95103:82;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;;;;;;;;;95161:16:::1;:14;:16::i;:::-;95103:82::o:0;96415:615::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;96559:4:::1;96541:15;:22;:47;;;;96584:4;96567:14;:21;96541:47;96537:245;;;96642:14;::::0;96675:13:::1;::::0;96612:158:::1;::::0;::::1;::::0;;::::1;::::0;::::1;2886:25:1::0;;;;2927:18;;;2920:34;2970:18;;;2963:34;;;3013:18;;;3006:34;;;2858:19;;96612:158:0::1;2657:389:1::0;96537:245:0::1;96824:14;::::0;96853:13:::1;::::0;96799:137:::1;::::0;;2886:25:1;;;2942:2;2927:18;;2920:34;;;;2970:18;;2963:34;;;3028:2;3013:18;;3006:34;;;96799:137:0::1;::::0;2873:3:1;2858:19;96799:137:0::1;;;;;;;96949:14;:32:::0;;;;96992:13:::1;:30:::0;96415:615::o;2109:151::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;2184:5:::1;:16:::0;;;::::1;-1:-1:-1::0;;;;;2184:16:0;::::1;::::0;;::::1;::::0;;2218:34:::1;::::0;2184:16;;2231:10:::1;::::0;2218:34:::1;::::0;2184:5;2218:34:::1;2109:151:::0;:::o;97129:172::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;97230:16:::1;::::0;97213:43:::1;::::0;;10956:25:1;;;11012:2;10997:18;;10990:34;;;97213:43:0::1;::::0;10929:18:1;97213:43:0::1;;;;;;;97267:16;:26:::0;97129:172::o;97905:154::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;98000:10:::1;::::0;97983:37:::1;::::0;;10956:25:1;;;11012:2;10997:18;;10990:34;;;97983:37:0::1;::::0;10929:18:1;97983:37:0::1;;;;;;;98031:10;:20:::0;97905:154::o;93373:201::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;11237:2:1;18522:34:0::1;::::0;::::1;11219:21:1::0;11276:2;11256:18;;;11249:30;11315:12;11295:18;;;11288:40;11345:18;;18522:34:0::1;11035:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;93530:36:::3;93549:8;93559:6;93530:18;:36::i;:::-;-1:-1:-1::0;;18615:1:0::1;18606:6;:10:::0;93373:201::o;85630:2890::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;11237:2:1;18522:34:0;;;11219:21:1;11276:2;11256:18;;;11249:30;11315:12;11295:18;;;11288:40;11345:18;;18522:34:0;11035:334:1;18522:34:0;18578:1;18569:10;;85717:9:::1;85712:2801;85736:7;85732:1;:11;85712:2801;;;85765:18;85786:15;:13;:15::i;:::-;85885:20;::::0;85818:30:::1;85851:69:::0;;;:15:::1;:69;::::0;;;;85959:21:::1;::::0;::::1;::::0;85765:36;;-1:-1:-1;85851:69:0;85959:26;;:105:::1;;;86048:16;;86024:7;:21;;;:40;;;;:::i;:::-;86006:15;:58;85959:105;85937:184;;;86099:7;;;;;85937:184;86137:22;86175:9;;86162:10;;:22;;;;:::i;:::-;86137:47:::0;-1:-1:-1;86205:19:0;86201:66:::1;;86245:7;;;;;;86201:66;86306:23;::::0;::::1;::::0;86283:20:::1;::::0;86306:78:::1;::::0;86359:10;86306:34:::1;:78::i;:::-;86283:101;;86543:14;86528:12;:29;86524:1939;;;86578:22;::::0;::::1;:39:::0;;;86636:20:::1;86659:35;86603:14:::0;86683:10;86659:23:::1;:35::i;:::-;86636:58;;86741:12;86715:22;;:38;;;;;;;:::i;:::-;;;;;;;;86799:12;86772:7;:23;;;:39;;;;;;;:::i;:::-;;;;;;;;86846:14;86832:10;;:28;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;86885:13:0::1;::::0;:17;86881:299:::1;;86927:20;86950:88;87002:13;;86950:14;:25;;:88;;;;:::i;:::-;87079:13;::::0;86927:111;;-1:-1:-1;87061:46:0::1;::::0;-1:-1:-1;;;;;87061:4:0::1;:17:::0;::::1;::::0;87079:13:::1;86927:111:::0;87061:17:::1;:46::i;:::-;87130:30;87148:12:::0;87130:30;::::1;:::i;:::-;;;86904:276;86881:299;87218:12;::::0;::::1;::::0;87200:47:::1;::::0;-1:-1:-1;;;;;87200:4:0::1;:17:::0;::::1;::::0;87218:12:::1;87232:14:::0;87200:17:::1;:47::i;:::-;87322:10:::0;;87355:12:::1;::::0;::::1;::::0;87462:21:::1;::::0;::::1;::::0;87273:229:::1;::::0;;3832:25:1;;;-1:-1:-1;;;;;87355:12:0;;::::1;3888:2:1::0;3873:18;;3866:83;3965:18;;;3958:34;;;4023:2;4008:18;;4001:34;;;4066:3;4051:19;;4044:35;87273:229:0;::::1;::::0;;;;3819:3:1;87273:229:0;;::::1;87521:7;;;;;;;;86524:1939;87613:22;::::0;::::1;:37:::0;;;87695:23:::1;::::0;::::1;::::0;87669:22:::1;:49:::0;;:22:::1;::::0;:49:::1;::::0;87695:23;;87669:49:::1;:::i;:::-;::::0;;;-1:-1:-1;;87763:1:0::1;87737:23;::::0;::::1;:27:::0;;;87785:10:::1;:26:::0;;87799:12;;87763:1;87785:26:::1;::::0;87799:12;;87785:26:::1;:::i;:::-;::::0;;;-1:-1:-1;;87836:13:0::1;::::0;:17;87832:295:::1;;87878:20;87901:86;87951:13;;87901:12;:23;;:86;;;;:::i;:::-;88028:13;::::0;87878:109;;-1:-1:-1;88010:46:0::1;::::0;-1:-1:-1;;;;;88010:4:0::1;:17:::0;::::1;::::0;88028:13:::1;87878:109:::0;88010:17:::1;:46::i;:::-;88079:28;88095:12:::0;88079:28;::::1;:::i;:::-;;;87855:272;87832:295;88165:12;::::0;::::1;::::0;88147:45:::1;::::0;-1:-1:-1;;;;;88147:4:0::1;:17:::0;::::1;::::0;88165:12:::1;88179::::0;88147:17:::1;:45::i;:::-;88258:10:::0;;88291:12:::1;::::0;::::1;::::0;88326:23:::1;::::0;::::1;::::0;88407:21:::1;::::0;::::1;::::0;88218:229:::1;::::0;;3832:25:1;;;-1:-1:-1;;;;;88291:12:0;;::::1;3888:2:1::0;3873:18;;3866:83;3965:18;;;3958:34;4023:2;4008:18;;4001:34;;;4066:3;4051:19;;4044:35;88218:229:0::1;::::0;3819:3:1;3804:19;88218:229:0::1;;;;;;;88479:20;:22:::0;;;:20:::1;:22;::::0;::::1;:::i;:::-;;;;;;85750:2763;;;;85745:3;;;;;:::i;:::-;;;;85712:2801;;18592:1;-1:-1:-1::0;18615:1:0;18606:6;:10;85630:2890::o;95228:70::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;95280:10:::1;:8;:10::i;95991:288::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;-1:-1:-1;;;;;96078:30:0;::::1;96074:87;;96132:17;;;;;;;;;;;;;;96074:87;96198:13;::::0;96178:50:::1;::::0;;-1:-1:-1;;;;;96198:13:0;;::::1;12261:34:1::0;;12331:15;;;12326:2;12311:18;;12304:43;96178:50:0::1;::::0;12173:18:1;96178:50:0::1;;;;;;;96241:13;:30:::0;;;::::1;-1:-1:-1::0;;;;;96241:30:0;;;::::1;::::0;;;::::1;::::0;;95991:288::o;88838:745::-;88884:7;88908:10;;88922:1;88908:15;88904:59;;;-1:-1:-1;88947:4:0;;88838:745::o;88904:59::-;88975:19;88997:16;:14;:16::i;:::-;89028:11;:18;88975:38;;-1:-1:-1;89024:97:0;;89075:10;;:34;;89097:11;89075:21;:34::i;:::-;89068:41;;;88838:745;:::o;89024:97::-;89133:18;89175:21;;89154:10;;:43;;;;:::i;:::-;89133:64;;89213:9;89208:316;89232:11;:18;89228:22;;89208:316;;;89272:16;89291:11;89303:1;89291:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;89351:23;;;:13;:23;;;;;;89320:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89291:14;-1:-1:-1;89320:54:0;89415:29;89291:14;89415:19;:29::i;:::-;89389:55;;;89473:39;89496:8;:15;;;89473:11;:22;;:39;;;;:::i;:::-;89459:53;;;;:::i;:::-;;;89257:267;;;89252:3;;;;;:::i;:::-;;;;89208:316;;;-1:-1:-1;89541:34:0;:10;89563:11;89541:21;:34::i;:::-;89534:41;;;;88838:745;:::o;84388:1114::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;11237:2:1;18522:34:0;;;11219:21:1;11276:2;11256:18;;;11249:30;11315:12;11295:18;;;11288:40;11345:18;;18522:34:0;11035:334:1;18522:34:0;18578:1;18569:10;;84467:18:::1;84488:15;:13;:15::i;:::-;84467:36;;84521:9;84516:979;84540:7;84536:1;:11;84516:979;;;84614:17;::::0;84569:29:::1;84601:31:::0;;;:12:::1;:31;::::0;;;;84671:21:::1;::::0;::::1;::::0;:26;;:104:::1;;;84760:15;;84736:7;:21;;;:39;;;;:::i;:::-;84718:15;:57;84671:104;84649:183;;;84810:7;;;;;84649:183;84871:23;::::0;::::1;::::0;84848:20:::1;::::0;84871:78:::1;::::0;84924:10;84871:34:::1;:78::i;:::-;84848:101;;84989:12;84966:7;:20;;:35;;;;85039:7;:23;;;85016:19;;:46;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;85091:23:0::1;::::0;::::1;::::0;85077:10:::1;:37:::0;;:10:::1;::::0;:37:::1;::::0;85091:23;;85077:37:::1;:::i;:::-;::::0;;;-1:-1:-1;;85146:12:0::1;::::0;::::1;::::0;85129:44:::1;::::0;;;;-1:-1:-1;;;;;85146:12:0;;::::1;85129:44;::::0;::::1;12721:74:1::0;12811:18;;;12804:34;;;85129:11:0::1;:16:::0;;::::1;::::0;::::1;::::0;12694:18:1;;85129:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;85228:10:0;;85257:12:::1;::::0;::::1;::::0;85288:23:::1;::::0;::::1;::::0;85330:20:::1;::::0;::::1;::::0;85369:21:::1;::::0;::::1;::::0;85195:210:::1;::::0;;3832:25:1;;;-1:-1:-1;;;;;85257:12:0;;::::1;3888:2:1::0;3873:18;;3866:83;3965:18;;;3958:34;;;;4023:2;4008:18;;4001:34;4066:3;4051:19;;4044:35;85195:210:0;::::1;::::0;-1:-1:-1;85195:210:0;;;;3819:3:1;85195:210:0;;-1:-1:-1;85195:210:0::1;85448:1;85422:23;::::0;::::1;:27:::0;;;85464:17:::1;:19:::0;;;::::1;::::0;::::1;:::i;:::-;;;;;;84554:941;;84549:3;;;;;:::i;:::-;;;;84516:979;;;;84456:1046;-1:-1:-1::0;18615:1:0;18606:6;:10;84388:1114::o;95340:86::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;95400:18:::1;:16;:18::i;98421:227::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;98518:4:::1;98503:12;:19;98499:142;;;98562:11;::::0;98544:44:::1;::::0;;10956:25:1;;;11012:2;10997:18;;10990:34;;;98544:44:0::1;::::0;10929:18:1;98544:44:0::1;;;;;;;98603:11;:26:::0;;;98499:142:::1;98421:227:::0;:::o;97460:362::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;97614:15:::1;::::0;97672:16:::1;::::0;97587:141:::1;::::0;;2886:25:1;;;2942:2;2927:18;;2920:34;;;2970:18;;2963:34;3028:2;3013:18;;3006:34;;;97587:141:0::1;::::0;2873:3:1;2858:19;97587:141:0::1;;;;;;;97739:15;:31:::0;;;;97781:16:::1;:33:::0;97460:362::o;1659:442::-;1933:5;;-1:-1:-1;;;;;1933:5:0;1919:10;:19;;:76;;-1:-1:-1;1942:9:0;;:53;;;;;1960:10;1942:53;;;13359:34:1;1980:4:0;13409:18:1;;;13402:43;1942:9:0;1987:7;;;13461:18:1;;;13454:107;-1:-1:-1;;;;;1942:9:0;;;;:17;;13271:18:1;;1942:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1911:85;;;;;;2009:9;:24;;;;-1:-1:-1;;;;;2009:24:0;;;;;;;;2051:42;;2068:10;;2051:42;;-1:-1:-1;;2051:42:0;1659:442;:::o;79799:28::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;79799:28:0;:::o;94997:66::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;95047:8:::1;:6;:8::i;98857:218::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;99014:4:::1;-1:-1:-1::0;;;;;98997:22:0::1;:5;-1:-1:-1::0;;;;;98997:22:0::1;;;98989:31;;;::::0;::::1;;99031:36;::::0;;;;-1:-1:-1;;;;;12739:55:1;;;99031:36:0::1;::::0;::::1;12721:74:1::0;12811:18;;;12804:34;;;99031:21:0;::::1;::::0;::::1;::::0;12694:18:1;;99031:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;98857:218:::0;;;:::o;89835:102::-;89882:16;89918:11;89911:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89835:102;:::o;94272:198::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;11237:2:1;18522:34:0::1;::::0;::::1;11219:21:1::0;11276:2;11256:18;;;11249:30;11315:12;11295:18;;;11288:40;11345:18;;18522:34:0::1;11035:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;94430:32:::3;94445:8;94455:6;94430:14;:32::i;93838:234::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;11237:2:1;18522:34:0::1;::::0;::::1;11219:21:1::0;11276:2;11256:18;;;11249:30;11315:12;11295:18;;;11288:40;11345:18;;18522:34:0::1;11035:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;94012:52:::3;94032:8;94042:6;94050:13;94012:19;:52::i;:::-;-1:-1:-1::0;;18615:1:0::1;18606:6;:10:::0;-1:-1:-1;93838:234:0:o;98150:181::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;98254:15:::1;::::0;98232:51:::1;::::0;;10956:25:1;;;11012:2;10997:18;;10990:34;;;98232:51:0::1;::::0;10929:18:1;98232:51:0::1;;;;;;;98294:15;:29:::0;98150:181::o;94584:185::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;11237:2:1;18522:34:0::1;::::0;::::1;11219:21:1::0;11276:2;11256:18;;;11249:30;11315:12;11295:18;;;11288:40;11345:18;;18522:34:0::1;11035:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;94736:25:::3;94751:9;94736:14;:25::i;89652:132::-:0;89699:7;89754:22;;89726:11;-1:-1:-1;;;;;89726:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;;;;:::i;:::-;89719:57;;89652:132;:::o;83016:1250::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;11237:2:1;18522:34:0;;;11219:21:1;11276:2;11256:18;;;11249:30;11315:12;11295:18;;;11288:40;11345:18;;18522:34:0;11035:334:1;18522:34:0;18578:1;18569:10;;-1:-1:-1;;;;;83134:20:0;::::1;83130:77;;83178:17;;;;;;;;;;;;;;83130:77;83254:11;:18:::0;83250:960:::1;;83294:18;83315:15;:13;:15::i;:::-;83294:36:::0;-1:-1:-1;83345:20:0::1;83368:29;:6:::0;83294:36;83368:17:::1;:29::i;:::-;83345:52:::0;-1:-1:-1;83412:37:0::1;-1:-1:-1::0;;;;;83412:4:0::1;:17;83430:4:::0;83345:52;83412:17:::1;:37::i;:::-;83478:12;83464:10;;:26;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;83510:165:0::1;::::0;;83546:1:::1;3832:25:1::0;;-1:-1:-1;;;;;3893:55:1;;3888:2;3873:18;;3866:83;3965:18;;;3958:34;;;4023:2;4008:18;;4001:34;;;83645:15:0::1;4066:3:1::0;4051:19;;4044:35;83510:165:0::1;::::0;3819:3:1;3804:19;83510:165:0::1;;;;;;;83279:408;;83250:960;;;83827:22;::::0;;83756:34:::1;83793:71:::0;;;:15:::1;:71;::::0;;;;;83827:22;83898:24:::1;83827:22:::0;83898:24:::1;:::i;:::-;::::0;;;-1:-1:-1;83881:41:0;;83937:16:::1;::::0;::::1;:23:::0;;;::::1;-1:-1:-1::0;;;;;83937:23:0;::::1;;::::0;;83975:27:::1;::::0;::::1;:36:::0;;;84054:15:::1;84026:25;::::0;::::1;:43:::0;84086:22:::1;:32:::0;;83975:36;;84086:22;-1:-1:-1;;84086:32:0::1;::::0;83975:36;;84086:32:::1;:::i;:::-;::::0;;;-1:-1:-1;;84157:14:0;;84138:60:::1;::::0;;14893:25:1;;;84173:10:0::1;15010:2:1::0;14995:18;;14988:43;-1:-1:-1;;;;;15067:15:1;;15047:18;;;15040:43;15114:2;15099:18;;15092:34;;;84138:60:0;::::1;::::0;;;;14880:3:1;84138:60:0;;::::1;83693:517;83250:960;84222:36;::::0;;;;84239:10:::1;84222:36;::::0;::::1;12721:74:1::0;12811:18;;;12804:34;;;84222:11:0::1;-1:-1:-1::0;;;;;84222:16:0::1;::::0;::::1;::::0;12694:18:1;;84222:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;18615:1:0;18606:6;:10;-1:-1:-1;;;;83016:1250:0:o;95560:314::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10247:2:1;1017:58:0;;;10229:21:1;10286:2;10266:18;;;10259:30;-1:-1:-1;;;10305:18:1;;;10298:42;10357:18;;1017:58:0;10045:336:1;1017:58:0;95652:4:::1;95643:6;:13;:30;;;;95669:4;95660:6;:13;95643:30;95639:121;;;95722:17;::::0;;95697:51:::1;::::0;::::1;::::0;;;;::::1;10956:25:1::0;10997:18;;;10990:34;;;10929:18;;95697:51:0::1;10782:248:1::0;95639:121:0::1;95801:17;::::0;95777:50:::1;::::0;;10956:25:1;;;11012:2;10997:18;;10990:34;;;95777:50:0::1;::::0;10929:18:1;95777:50:0::1;;;;;;;95840:17;:26:::0;95560:314::o;81350:1288::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;11237:2:1;18522:34:0;;;11219:21:1;11276:2;11256:18;;;11249:30;11315:12;11295:18;;;11288:40;11345:18;;18522:34:0;11035:334:1;18522:34:0;18578:1;18569:10;;25019:15;;;;;;;25333:71:::1;;;25376:16;;;;;;;;;;;;;;25333:71;-1:-1:-1::0;;;;;81496:20:0;::::2;81492:77;;81540:17;;;;;;;;;;;;;;81492:77;81594:16;;81585:6;:25;81581:113;;;81657:16;::::0;81634:48:::2;::::0;::::2;::::0;;::::2;::::0;::::2;10956:25:1::0;;;;10997:18;;;10990:34;;;10929:18;;81634:48:0::2;10782:248:1::0;81581:113:0::2;81741:11;:18:::0;81737:825:::2;;81781:18;81802:15;:13;:15::i;:::-;81781:36:::0;-1:-1:-1;81832:20:0::2;81855:29;:6:::0;81781:36;81855:17:::2;:29::i;:::-;81899:36;::::0;;;;-1:-1:-1;;;;;12739:55:1;;;81899:36:0::2;::::0;::::2;12721:74:1::0;12811:18;;;12804:34;;;81832:52:0;;-1:-1:-1;81899:11:0::2;:16:::0;;::::2;::::0;::::2;::::0;12694:18:1;;81899:36:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;81964:6;81950:10;;:20;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;81990:62:0::2;::::0;;82005:1:::2;3832:25:1::0;;-1:-1:-1;;;;;3893:55:1;;3888:2;3873:18;;3866:83;3965:18;;;3958:34;;;4023:2;4008:18;;4001:34;;;82036:15:0::2;4066:3:1::0;4051:19;;4044:35;81990:62:0::2;::::0;3819:3:1;3804:19;81990:62:0::2;;;;;;;81766:298;;81737:825;;;82196:19;::::0;;82130:32:::2;82165:65:::0;;;:12:::2;:65;::::0;;;;;82196:19;82263:21:::2;82196:19:::0;82263:21:::2;:::i;:::-;::::0;;;-1:-1:-1;82247:37:0;;82299:15:::2;::::0;::::2;:22:::0;;;::::2;-1:-1:-1::0;;;;;82299:22:0;::::2;;::::0;;82336:26:::2;::::0;::::2;:35:::0;;;82413:15:::2;82386:24;::::0;::::2;:42:::0;82445:19:::2;:29:::0;;82336:35;;82445:19;-1:-1:-1;;82445:29:0::2;::::0;82336:35;;82445:29:::2;:::i;:::-;::::0;;;-1:-1:-1;;82510:13:0;;82494:56:::2;::::0;;14893:25:1;;;82525:10:0::2;15010:2:1::0;14995:18;;14988:43;-1:-1:-1;;;;;15067:15:1;;15047:18;;;15040:43;15114:2;15099:18;;15092:34;;;82494:56:0;::::2;::::0;;;;14880:3:1;82494:56:0;;::::2;82070:492;81737:825;82574:56;-1:-1:-1::0;;;;;82574:4:0::2;:21;82596:10;82616:4;82623:6:::0;82574:21:::2;:56::i;1105:546::-:0;1226:9;;1192:4;;-1:-1:-1;;;;;1226:9:0;1548:27;;;;;:77;;-1:-1:-1;1579:46:0;;;;;-1:-1:-1;;;;;13377:15:1;;;1579:46:0;;;13359:34:1;1606:4:0;13409:18:1;;;13402:43;13493:66;13481:79;;13461:18;;;13454:107;1579:12:0;;;;;13271:18:1;;1579:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1547:96;;;-1:-1:-1;1638:5:0;;-1:-1:-1;;;;;1630:13:0;;;1638:5;;1630:13;1547:96;1540:103;;;1105:546;;;;;:::o;25735:151::-;25019:15;;;;;;;25333:71;;;25376:16;;;;;;;;;;;;;;25333:71;25811:15:::1;:22:::0;;;::::1;;;::::0;;25849:29:::1;::::0;25867:10:::1;1340:74:1::0;;25849:29:0::1;::::0;1328:2:1;1313:18;25849:29:0::1;;;;;;;;25735:151::o:0;99273:2641::-;99354:16;99373:23;99386:9;99373:12;:23::i;:::-;99354:42;;99512:11;;99500:9;:23;99496:99;;;99547:36;;;;;;;;10956:25:1;;;10997:18;;;10990:34;;;10929:18;;99547:36:0;10782:248:1;99496:99:0;99607:33;99643:24;;;:13;:24;;;;;99698:23;;:28;;;;:134;;-1:-1:-1;99768:23:0;;99743:49;;;;;-1:-1:-1;;;;;99817:14:0;99743:89;;;:12;:24;;;;;;:49;;;;160:25:1;;;148:2;133:18;;14:177;99743:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;99743:89:0;;;99698:134;99680:310;;;99940:23;;99859:119;;;;;-1:-1:-1;;;;;99859:12:0;:20;;;;:119;;99906:14;;99859:119;;-1:-1:-1;;;;;12739:55:1;;;;12721:74;;12826:2;12811:18;;12804:34;12709:2;12694:18;;12547:297;99859:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99680:310;100028:36;;;;;;;;160:25:1;;;100003:19:0;;100028:6;-1:-1:-1;;;;;100028:25:0;;;;133:18:1;;100028:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100002:62;;;100077:21;100101:82;100155:17;;100101:28;100117:11;100101:4;:15;;:28;;;;:::i;:::-;:39;;:82::i;:::-;100077:106;;100209:13;100196:9;;:26;;;;;;;:::i;:::-;;;;-1:-1:-1;;100251:10:0;;100239:9;;:22;100235:199;;;100321:10;;100362:13;100350:9;;:25;;;;:::i;:::-;100285:137;;;;;;;;16239:25:1;;;;16280:18;;;16273:34;16323:18;;;16316:34;;;16212:18;;100285:137:0;16037:319:1;100235:199:0;100444:23;100496:13;100470:12;:23;;;:39;;;;:::i;:::-;100444:65;-1:-1:-1;100522:56:0;-1:-1:-1;;;;;100522:4:0;:16;100547:14;100564:13;100522:16;:56::i;:::-;100591:64;;:::i;:::-;100690:6;-1:-1:-1;;;;;100668:28:0;;;100707:15;;;:27;;;100765:23;;100745:17;;;:43;100819:15;;100799:17;;;:35;100845:22;;;:40;;;100923:23;;;;100896:24;;;:50;76907:41;100957:17;;;76907:41;100957:31;;-1:-1:-1;100999:13:0;;;:20;;;101047:1;101030:14;;;:18;;;101059:14;;;:30;;;101100:18;;;:34;;;-1:-1:-1;;;;;101165:4:0;101145:24;;:17;;;:24;101262:35;;;;;:14;:27;;;;;;:35;;100999:6;;101262:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101182:115;;101334:15;101308:12;:23;;:41;;;;101383:4;101360:12;:19;;;:27;;;;;;;:::i;:::-;;;;-1:-1:-1;;101438:23:0;;;;101398:29;;;:64;;:29;;:64;;101438:23;;101398:64;:::i;:::-;;;;-1:-1:-1;;101505:23:0;;;;101473:21;:56;;:21;;:56;;101505:23;;101473:56;:::i;:::-;;;;-1:-1:-1;;101546:23:0;;101542:153;;101617:24;;;;101591:50;;101656:11;:27;;;;;;;101591:23;101656:27;;;;;;;;;101542:153;101763:23;;101848;;;;;101712:194;;;19216:25:1;;;19272:2;19257:18;;19250:34;;;;19300:18;;19293:34;;;19358:2;19343:18;;19336:34;;;19386:19;;;19379:35;19445:3;19430:19;;19423:35;;;101712:194:0;;19203:3:1;19188:19;101712:194:0;;;;;;;99343:2571;;;;;;;99273:2641;;:::o;10525:166::-;10590:7;10617:21;10628:1;10631;10474:4;10617:10;:21::i;:::-;10610:28;10525:166;-1:-1:-1;;;10525:166:0:o;11041:160::-;11104:7;11131:19;11140:1;10474:4;11148:1;11131:8;:19::i;21576:1485::-;21693:12;21824:4;21818:11;21969:66;21950:17;21943:93;22084:2;22080:1;22061:17;22057:25;22050:37;22165:6;22160:2;22141:17;22137:26;22130:42;22977:2;22974:1;22970:2;22951:17;22948:1;22941:5;22934;22929:51;22493:16;22486:24;22480:2;22462:16;22459:24;22455:1;22451;22445:8;22442:15;22438:46;22435:76;22232:763;22221:774;;;23026:7;23018:35;;;;-1:-1:-1;;;23018:35:0;;19671:2:1;23018:35:0;;;19653:21:1;19710:2;19690:18;;;19683:30;19749:17;19729:18;;;19722:45;19784:18;;23018:35:0;19469:339:1;25894:155:0;24917:7;;;;25202:60;;25239:11;;;;;;;;;;;;;;25202:60;25953:7:::1;:15:::0;;25979:23;;;;26018::::1;::::0;26030:10:::1;1340:74:1::0;;26018:23:0::1;::::0;1328:2:1;1313:18;26018:23:0::1;1181:239:1::0;10867:166:0;10932:7;10959:21;10970:1;10474:4;10978:1;10959:10;:21::i;90256:1635::-;90354:19;90375:18;90426:34;90475:38;90527:6;-1:-1:-1;;;;;90527:24:0;;90552:9;90527:35;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;90527:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90613:66;;;;;90648:20;90613:66;;;160:25:1;90411:151:0;;-1:-1:-1;90411:151:0;-1:-1:-1;90576:17:0;;;;-1:-1:-1;;;;;90613:5:0;:20;;;;133:18:1;;90613:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90575:104;;;;90696:9;90709:1;90696:14;:27;;;;90714:9;90696:27;90692:68;;;90740:8;;;90692:68;90794:5;:12;;;90776:15;:30;90772:1112;;;90872:59;;;;;;;;160:25:1;;;90824:19:0;;;;-1:-1:-1;;;;;90872:6:0;:48;;;;133:18:1;;90872:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90823:108;;;;;90952:13;90969:1;90952:18;90948:86;;;90998:20;;;;;;;;;;;;;;90948:86;91080:11;91064:13;:27;:95;;91158:1;91064:95;;;91111:27;91127:11;91111:13;:27;:::i;:::-;91050:109;;90808:363;;90772:1112;;;91227:8;;91237:10;;91210:38;;;;;;;;10956:25:1;;;;10997:18;;;10990:34;91192:15:0;;91210:6;-1:-1:-1;;;;;91210:16:0;;;;10929:18:1;;91210:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91314:10;;91284:41;;;;;91192:56;;-1:-1:-1;91263:18:0;;-1:-1:-1;;;;;91284:6:0;:18;;;;:41;;91303:9;;91284:41;;10956:25:1;;;11012:2;10997:18;;10990:34;10944:2;10929:18;;10782:248;91284:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91263:62;;91340:49;91392:398;;;;;;;;91500:15;91485:5;:12;;;:30;;;;:::i;:::-;91392:398;;;;91557:30;:7;91576:10;91557:18;:30::i;:::-;91392:398;;;;91623:9;91392:398;;;;91675:6;:18;;;91392:398;;;;91729:6;-1:-1:-1;;;;;91729:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;91392:398;;91835:37;;;;;;23773:13:1;;91835:37:0;;;23755:32:1;23843:4;23831:17;;23825:24;23803:20;;;23796:54;23894:17;;;23888:24;23866:20;;;23859:54;23969:4;23957:17;;23951:24;23929:20;;;23922:54;24032:4;24020:17;;24014:24;23992:20;;;23985:54;91340:450:0;;-1:-1:-1;91835:15:0;;:28;;23727:19:1;;91835:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91807:65;;-1:-1:-1;91807:65:0;-1:-1:-1;;;;90772:1112:0;90400:1491;;;;90256:1635;;;:::o;26057:153::-;25019:15;;;;;;;25472:76;;25517:19;;;;;;;;;;;;;;25472:76;26132:15:::1;:23:::0;;;::::1;::::0;;26171:31:::1;::::0;26191:10:::1;1340:74:1::0;;26171:31:0::1;::::0;1328:2:1;1313:18;26171:31:0::1;1181:239:1::0;25575:152:0;24917:7;;;;25086:56;;;25122:8;;;;;;;;;;;;;;25086:56;25635:7:::1;:14:::0;;25660:22;;;;;;25698:21:::1;::::0;25708:10:::1;1340:74:1::0;;25698:21:0::1;::::0;1328:2:1;1313:18;25698:21:0::1;1181:239:1::0;105055:538:0;105145:4;105132:9;;:17;;;;;;;:::i;:::-;;;;-1:-1:-1;;105178:10:0;;105166:9;;:22;105162:115;;;105230:10;;105254:4;105242:9;;:16;;;;:::i;105162:115::-;105289:33;105325:24;;;:13;:24;;;;;105362:46;-1:-1:-1;;;;;105368:4:0;105362:23;105394:6;105403:4;105362:23;:46::i;:::-;105440:23;;105419:51;;;;;;;;10956:25:1;;;;10997:18;;;10990:34;;;105419:6:0;-1:-1:-1;;;;;105419:20:0;;;;10929:18:1;;105419:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105508:4;105481:12;:23;;;:31;;;;;;;:::i;:::-;;;;-1:-1:-1;;105555:23:0;;105530:55;;;16239:25:1;;;16295:2;16280:18;;16273:34;;;;16323:18;;16316:34;;;105530:55:0;;16227:2:1;16212:18;105530:55:0;;;;;;;105121:472;105055:538;;:::o;101922:3125::-;102059:33;102095:24;;;:13;:24;;;;;102150:23;;:28;;:71;;;102217:4;102195:12;:19;;;:26;102150:71;:132;;;;102260:21;;102238:11;:44;102150:132;102132:251;;;102347:23;;102316:55;;;;;;;102336:9;;102316:55;;10956:25:1;;;11012:2;10997:18;;10990:34;10944:2;10929:18;;10782:248;102132:251:0;102438:23;;102413:49;;;;;-1:-1:-1;;;;;102487:14:0;102413:89;;;:12;:24;;;;;;:49;;;;160:25:1;;;148:2;133:18;;14:177;102413:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;102413:89:0;;102395:265;;102610:23;;102529:119;;;;;-1:-1:-1;;;;;102529:12:0;:20;;;;:119;;102576:14;;102529:119;;-1:-1:-1;;;;;12739:55:1;;;;12721:74;;12826:2;12811:18;;12804:34;12709:2;12694:18;;12547:297;102529:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102395:265;102672:26;102709:23;102744:19;102769:6;-1:-1:-1;;;;;102769:25:0;;102795:9;102769:36;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;102769:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102743:62;;;102830:12;:19;;;102822:4;:27;102818:321;;;102887:12;:23;;;102866:44;;102818:321;;;103018:17;;102964:86;;:26;:4;102978:11;102964:13;:26::i;:::-;:35;;:86::i;:::-;102943:107;;103109:18;103083:12;:23;;;:44;;;;:::i;:::-;103065:62;;102818:321;103151:61;-1:-1:-1;;;;;103157:4:0;103151:23;103183:14;103200:11;103151:23;:61::i;:::-;103225:64;;:::i;:::-;103324:6;-1:-1:-1;;;;;103302:28:0;;;103341:15;;;:27;;;103399:23;;103379:17;;;:43;103453:15;;103433:17;;;:35;103479:22;;;:40;;;103557:23;;;;103530:24;;;:50;76907:41;103591:17;;;76907:41;103591:31;;-1:-1:-1;103633:13:0;;;:20;;;103681:1;103664:14;;;:18;;;103710:17;103693:14;;;:34;103738:18;;;:32;;;-1:-1:-1;;;;;103801:4:0;103781:24;;:17;;;:24;103898:36;;;;;:14;:28;;;;;;:36;;103633:6;;103898:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103818:116;;103945:19;103967:13;:23;;;103945:45;;104029:15;104003:12;:23;;:41;;;;104078:4;104055:12;:19;;;:27;;;;;;;:::i;:::-;;;;;;;;104133:11;104093:12;:29;;;:52;;;;;;;:::i;:::-;;;;-1:-1:-1;;104162:19:0;;;;104158:601;;104239:1;104207:12;:29;;;:33;104203:414;;;104286:29;;;;104372:14;;104261;;104354:33;;104286:29;;104354:17;:33::i;:::-;104431:13;;104335:52;;-1:-1:-1;104406:49:0;;-1:-1:-1;;;;;104412:4:0;104406:24;;;104431:13;104335:52;104406:24;:49::i;:::-;104489:17;104498:8;104489:6;:17;:::i;:::-;104474:10;;:33;;;;;;;:::i;:::-;;;;-1:-1:-1;104203:414:0;;-1:-1:-1;;;104203:414:0;;104571:12;:29;;;104570:30;;;:::i;:::-;104548:10;;:53;;;;;;;:::i;:::-;;;;-1:-1:-1;;104203:414:0;104657:1;104631:27;;;104673:29;;;:33;104721:26;104737:9;104721:15;:26::i;:::-;104803:11;104771:21;;:44;;;;;;;:::i;:::-;;;;;;;;104839:18;104826:9;;:31;;;;;;;:::i;:::-;;;;-1:-1:-1;;104927:23:0;;104875:164;;;24879:25:1;;;24935:2;24920:18;;24913:34;;;;24963:18;;24956:34;;;25021:2;25006:18;;24999:34;;;25064:3;25049:19;;25042:35;;;104875:164:0;;24866:3:1;24851:19;104875:164:0;;;;;;;102048:2999;;;;;;;101922:3125;;;:::o;105922:2525::-;106000:9;105995:2445;106019:10;:17;106015:1;:21;105995:2445;;;106058:33;106094:13;:28;106108:10;106119:1;106108:13;;;;;;;;:::i;:::-;;;;;;;106094:28;;;;;;;;;;;106058:64;;106143:12;:19;;;106166:1;106143:24;106139:89;;;106195:17;;;;;;;;;;;;;;106139:89;106333:23;;106285:72;;;;;106244:38;;-1:-1:-1;;;;;106285:12:0;:47;;;;:72;;;;160:25:1;;;148:2;133:18;;14:177;106285:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;106244:113;-1:-1:-1;106391:34:0;106376:11;:49;;;;;;;;:::i;:::-;;106372:248;;106492:10;106503:1;106492:13;;;;;;;;:::i;:::-;;;;;;;106528:12;:23;;;106574:11;106453:151;;;;;;;;;;;;;:::i;106372:248::-;106637:19;106658:21;106685:6;-1:-1:-1;;;;;106685:48:0;;106734:10;106745:1;106734:13;;;;;;;;:::i;:::-;;;;;;;106685:63;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;106685:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;106636:112;;;;;106769:13;106786:1;106769:18;106765:86;;;106815:20;;;;;;;;;;;;;;106765:86;106867:17;106904:11;106888:13;:27;106887:131;;107017:1;106887:131;;;106977:19;;;;106936:61;;106937:27;106953:11;106937:13;:27;:::i;106936:61::-;106867:151;-1:-1:-1;107039:13:0;;107035:77;;107087:9;107073:10;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;;107035:77:0;107141:12;:23;;;107128:9;;:36;;;;;;;:::i;:::-;;;;-1:-1:-1;;107185:29:0;;;;107217:1;-1:-1:-1;107181:750:0;;;107264:29;;;;107239:14;107352;107348:179;;107420:14;;107402:33;;:6;;:17;:33::i;:::-;107483:13;;107391:44;;-1:-1:-1;107458:49:0;;-1:-1:-1;;;;;107464:4:0;107458:24;;;107483:13;107391:44;107458:24;:49::i;:::-;107560:17;107569:8;107560:6;:17;:::i;:::-;107545:10;;:33;;;;;;;:::i;:::-;;;;;;;;107629:6;107597:21;;:39;;;;;;;:::i;:::-;;;;-1:-1:-1;;107659:21:0;;107683:1;-1:-1:-1;107655:167:0;;;107732:21;;107731:22;;;:::i;:::-;107709:10;;:45;;;;;;;:::i;:::-;;;;-1:-1:-1;;107801:1:0;107777:21;:25;107655:167;107220:617;;107181:750;;;107885:12;:29;;;107884:30;;;:::i;:::-;107862:10;;:53;;;;;;;:::i;:::-;;;;-1:-1:-1;;107181:750:0;107952:257;107983:10;107994:1;107983:13;;;;;;;;:::i;:::-;;;;;;;108015:12;:23;;;108057:12;:19;;;108095:12;:23;;;108137:12;:29;;;108185:9;107952:257;;;;;;;;;;19216:25:1;;;19272:2;19257:18;;19250:34;;;;19315:2;19300:18;;19293:34;;;;19358:2;19343:18;;19336:34;19401:3;19386:19;;19379:35;19445:3;19430:19;;19423:35;19203:3;19188:19;;18931:533;107952:257:0;;;;;;;;108252:1;108226:27;;;108268:29;;;:33;;;108316:19;;;:23;;;-1:-1:-1;108354:23:0;;:27;108414:13;;108398:30;;108414:10;;108425:1;;108414:13;;;;;;:::i;:::-;;;;;;;108398:15;:30::i;:::-;106043:2397;;;;;106038:3;;;;;:::i;:::-;;;;105995:2445;;;;105922:2525;:::o;19964:1604::-;20108:12;20239:4;20233:11;20384:66;20365:17;20358:93;20499:4;20495:1;20476:17;20472:25;20465:39;20584:2;20579;20560:17;20556:26;20549:38;20665:6;20660:2;20641:17;20637:26;20630:42;21479:2;21476:1;21471:3;21452:17;21449:1;21442:5;21435;21430:52;20993:16;20986:24;20980:2;20962:16;20959:24;20955:1;20951;20945:8;20942:15;20938:46;20935:76;20732:765;20721:776;;;21528:7;21520:40;;;;-1:-1:-1;;;21520:40:0;;26507:2:1;21520:40:0;;;26489:21:1;26546:2;26526:18;;;26519:30;26585:22;26565:18;;;26558:50;26625:18;;21520:40:0;26305:344:1;21520:40:0;20097:1471;19964:1604;;;;:::o;92014:1010::-;92105:16;92154:34;92203:38;92255:6;-1:-1:-1;;;;;92255:24:0;;92280:9;92255:35;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;92255:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92341:66;;;;;92376:20;92341:66;;;160:25:1;92139:151:0;;-1:-1:-1;92139:151:0;-1:-1:-1;92304:17:0;;;;-1:-1:-1;;;;;92341:5:0;:20;;;;133:18:1;;92341:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92303:104;;;;92424:9;92437:1;92424:14;:27;;;;92442:9;92424:27;92420:101;;;92475:34;;;;;;;;26822:25:1;;;26890:14;;26883:22;26863:18;;;26856:50;26795:18;;92475:34:0;26654:258:1;92420:101:0;92533:49;92585:372;;;;;;;;92685:15;92670:5;:12;;;:30;;;;:::i;:::-;92585:372;;;;92738:32;92758:6;:11;;;92738:5;:8;;;:19;;:32;;;;:::i;:::-;92585:372;;;;92802:9;92585:372;;;;92850:6;:18;;;92585:372;;;;92900:6;-1:-1:-1;;;;;92900:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;92585:372;;92986:30;;;;;;23773:13:1;;92986:30:0;;;23755:32:1;23843:4;23831:17;;23825:24;23803:20;;;23796:54;23894:17;;;23888:24;23866:20;;;23859:54;23969:4;23957:17;;23951:24;23929:20;;;23922:54;24032:4;24020:17;;24014:24;23992:20;;;23985:54;92533:424:0;;-1:-1:-1;92986:15:0;;:21;;23727:19:1;;92986:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;92970:46:0;92014:1010;-1:-1:-1;;;;;;;92014:1010:0:o;23069:1483::-;23185:12;23316:4;23310:11;23461:66;23442:17;23435:93;23576:2;23572:1;23553:17;23549:25;23542:37;23657:6;23652:2;23633:17;23629:26;23622:42;24469:2;24466:1;24462:2;24443:17;24440:1;24433:5;24426;24421:51;23985:16;23978:24;23972:2;23954:16;23951:24;23947:1;23943;23937:8;23934:15;23930:46;23927:76;23724:763;23713:774;;;24518:7;24510:34;;;;-1:-1:-1;;;24510:34:0;;27367:2:1;24510:34:0;;;27349:21:1;27406:2;27386:18;;;27379:30;27445:16;27425:18;;;27418:44;27479:18;;24510:34:0;27165:338:1;11405:552:0;11618:9;;;11752:19;;11745:27;11777:9;;11791;;;11788:16;;11774:31;11741:65;11731:123;;11837:1;11834;11827:12;11731:123;11920:19;;11405:552;-1:-1:-1;;11405:552:0:o;11965:771::-;12176:9;;;12310:19;;12303:27;12335:9;;12349;;;12346:16;;12332:31;12299:65;12289:123;;12395:1;12392;12385:12;12289:123;12715:1;12701:11;12697:1;12694;12690:9;12686:27;12682:35;12677:1;12670:9;12663:17;12659:59;12654:64;;11965:771;;;;;:::o;10699:160::-;10762:7;10789:19;10798:1;10801;10474:4;10789:8;:19::i;108455:372::-;108551:11;:18;108519:9;;108580:123;108596:1;108592;:5;108580:123;;;108636:11;108648:1;108636:14;;;;;;;;:::i;:::-;;;;;;;;;108623:9;:27;108619:73;;;108671:5;;108619:73;108599:3;;;;:::i;:::-;;;;108580:123;;;108723:1;108719;:5;108715:105;;;108758:11;108770:5;108774:1;108770;:5;:::i;:::-;108758:18;;;;;;;;:::i;:::-;;;;;;;;;108741:11;108753:1;108741:14;;;;;;;;:::i;:::-;;;;;;;;;;:35;108791:11;:17;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;108715:105;108508:319;;108455:372;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;378:248:1:-;446:6;454;507:2;495:9;486:7;482:23;478:32;475:52;;;523:1;520;513:12;475:52;-1:-1:-1;;546:23:1;;;616:2;601:18;;;588:32;;-1:-1:-1;378:248:1:o;631:154::-;-1:-1:-1;;;;;710:5:1;706:54;699:5;696:65;686:93;;775:1;772;765:12;790:247;849:6;902:2;890:9;881:7;877:23;873:32;870:52;;;918:1;915;908:12;870:52;957:9;944:23;976:31;1001:5;976:31;:::i;1425:180::-;1484:6;1537:2;1525:9;1516:7;1512:23;1508:32;1505:52;;;1553:1;1550;1543:12;1505:52;-1:-1:-1;1576:23:1;;1425:180;-1:-1:-1;1425:180:1:o;4090:184::-;4142:77;4139:1;4132:88;4239:4;4236:1;4229:15;4263:4;4260:1;4253:15;4279:141;4361:1;4354:5;4351:12;4341:46;;4367:18;;:::i;:::-;4396;;4279:141::o;4425:210::-;4572:2;4557:18;;4584:45;4561:9;4611:6;4584:45;:::i;4640:456::-;4717:6;4725;4733;4786:2;4774:9;4765:7;4761:23;4757:32;4754:52;;;4802:1;4799;4792:12;4754:52;4841:9;4828:23;4860:31;4885:5;4860:31;:::i;:::-;4910:5;-1:-1:-1;4967:2:1;4952:18;;4939:32;4980:33;4939:32;4980:33;:::i;:::-;4640:456;;5032:7;;-1:-1:-1;;;5086:2:1;5071:18;;;;5058:32;;4640:456::o;5101:632::-;5272:2;5324:21;;;5394:13;;5297:18;;;5416:22;;;5243:4;;5272:2;5495:15;;;;5469:2;5454:18;;;5243:4;5538:169;5552:6;5549:1;5546:13;5538:169;;;5613:13;;5601:26;;5682:15;;;;5647:12;;;;5574:1;5567:9;5538:169;;;-1:-1:-1;5724:3:1;;5101:632;-1:-1:-1;;;;;;5101:632:1:o;5738:316::-;5815:6;5823;5831;5884:2;5872:9;5863:7;5859:23;5855:32;5852:52;;;5900:1;5897;5890:12;5852:52;-1:-1:-1;;5923:23:1;;;5993:2;5978:18;;5965:32;;-1:-1:-1;6044:2:1;6029:18;;;6016:32;;5738:316;-1:-1:-1;5738:316:1:o;6059:184::-;6111:77;6108:1;6101:88;6208:4;6205:1;6198:15;6232:4;6229:1;6222:15;6248:253;6320:2;6314:9;6362:4;6350:17;;6397:18;6382:34;;6418:22;;;6379:62;6376:88;;;6444:18;;:::i;:::-;6480:2;6473:22;6248:253;:::o;6506:255::-;6578:2;6572:9;6620:6;6608:19;;6657:18;6642:34;;6678:22;;;6639:62;6636:88;;;6704:18;;:::i;6766:252::-;6838:2;6832:9;6880:3;6868:16;;6914:18;6899:34;;6935:22;;;6896:62;6893:88;;;6961:18;;:::i;7023:334::-;7094:2;7088:9;7150:2;7140:13;;7155:66;7136:86;7124:99;;7253:18;7238:34;;7274:22;;;7235:62;7232:88;;;7300:18;;:::i;:::-;7336:2;7329:22;7023:334;;-1:-1:-1;7023:334:1:o;7362:183::-;7422:4;7455:18;7447:6;7444:30;7441:56;;;7477:18;;:::i;:::-;-1:-1:-1;7522:1:1;7518:14;7534:4;7514:25;;7362:183::o;7550:891::-;7634:6;7665:2;7708;7696:9;7687:7;7683:23;7679:32;7676:52;;;7724:1;7721;7714:12;7676:52;7764:9;7751:23;7797:18;7789:6;7786:30;7783:50;;;7829:1;7826;7819:12;7783:50;7852:22;;7905:4;7897:13;;7893:27;-1:-1:-1;7883:55:1;;7934:1;7931;7924:12;7883:55;7970:2;7957:16;7993:60;8009:43;8049:2;8009:43;:::i;:::-;7993:60;:::i;:::-;8087:15;;;8169:1;8165:10;;;;8157:19;;8153:28;;;8118:12;;;;8193:19;;;8190:39;;;8225:1;8222;8215:12;8190:39;8249:11;;;;8269:142;8285:6;8280:3;8277:15;8269:142;;;8351:17;;8339:30;;8302:12;;;;8389;;;;8269:142;;;8430:5;7550:891;-1:-1:-1;;;;;;;7550:891:1:o;8694:315::-;8762:6;8770;8823:2;8811:9;8802:7;8798:23;8794:32;8791:52;;;8839:1;8836;8829:12;8791:52;8878:9;8865:23;8897:31;8922:5;8897:31;:::i;:::-;8947:5;8999:2;8984:18;;;;8971:32;;-1:-1:-1;;;8694:315:1:o;11374:184::-;11426:77;11423:1;11416:88;11523:4;11520:1;11513:15;11547:4;11544:1;11537:15;11563:128;11603:3;11634:1;11630:6;11627:1;11624:13;11621:39;;;11640:18;;:::i;:::-;-1:-1:-1;11676:9:1;;11563:128::o;11696:125::-;11736:4;11764:1;11761;11758:8;11755:34;;;11769:18;;:::i;:::-;-1:-1:-1;11806:9:1;;11696:125::o;11826:195::-;11865:3;11896:66;11889:5;11886:77;11883:103;;;11966:18;;:::i;:::-;-1:-1:-1;12013:1:1;12002:13;;11826:195::o;12358:184::-;12410:77;12407:1;12400:88;12507:4;12504:1;12497:15;12531:4;12528:1;12521:15;13572:164;13648:13;;13697;;13690:21;13680:32;;13670:60;;13726:1;13723;13716:12;13670:60;13572:164;;;:::o;13741:202::-;13808:6;13861:2;13849:9;13840:7;13836:23;13832:32;13829:52;;;13877:1;13874;13867:12;13829:52;13900:37;13927:9;13900:37;:::i;13948:184::-;14018:6;14071:2;14059:9;14050:7;14046:23;14042:32;14039:52;;;14087:1;14084;14077:12;14039:52;-1:-1:-1;14110:16:1;;13948:184;-1:-1:-1;13948:184:1:o;15388:138::-;15467:13;;15489:31;15467:13;15489:31;:::i;15531:251::-;15601:6;15654:2;15642:9;15633:7;15629:23;15625:32;15622:52;;;15670:1;15667;15660:12;15622:52;15702:9;15696:16;15721:31;15746:5;15721:31;:::i;15787:245::-;15866:6;15874;15927:2;15915:9;15906:7;15902:23;15898:32;15895:52;;;15943:1;15940;15933:12;15895:52;-1:-1:-1;;15966:16:1;;16022:2;16007:18;;;16001:25;15966:16;;16001:25;;-1:-1:-1;15787:245:1:o;16361:1182::-;16610:13;;-1:-1:-1;;;;;1115:54:1;1103:67;;16571:3;16556:19;;16691:4;16683:6;16679:17;16673:24;16666:4;16655:9;16651:20;16644:54;16754:4;16746:6;16742:17;16736:24;16729:4;16718:9;16714:20;16707:54;16817:4;16809:6;16805:17;16799:24;16792:4;16781:9;16777:20;16770:54;16880:4;16872:6;16868:17;16862:24;16855:4;16844:9;16840:20;16833:54;16943:4;16935:6;16931:17;16925:24;16918:4;16907:9;16903:20;16896:54;16997:4;16989:6;16985:17;16979:24;17012:62;17068:4;17057:9;17053:20;17039:12;17012:62;:::i;:::-;-1:-1:-1;17130:4:1;17118:17;;;17112:24;17090:20;;;17083:54;17156:6;17204:15;;;17198:22;17178:18;;;17171:50;17240:6;17288:15;;;17282:22;17262:18;;;17255:50;17324:6;17372:15;;;17366:22;17346:18;;;17339:50;17408:6;17451:15;;;17445:22;-1:-1:-1;;;;;1115:54:1;17518:18;;;;1103:67;;;;16361:1182;:::o;17548:1006::-;17649:6;17680:3;17724:2;17712:9;17703:7;17699:23;17695:32;17692:52;;;17740:1;17737;17730:12;17692:52;17773:2;17767:9;17803:15;;;;17848:18;17833:34;;17869:22;;;17830:62;17827:88;;;17895:18;;:::i;:::-;17935:10;17931:2;17924:22;17974:9;17968:16;17955:29;;17993:31;18018:5;17993:31;:::i;:::-;18048:5;18040:6;18033:21;18108:2;18097:9;18093:18;18087:25;18082:2;18074:6;18070:15;18063:50;18146:49;18191:2;18180:9;18176:18;18146:49;:::i;:::-;18141:2;18133:6;18129:15;18122:74;18250:2;18239:9;18235:18;18229:25;18224:2;18216:6;18212:15;18205:50;18310:3;18299:9;18295:19;18289:26;18283:3;18275:6;18271:16;18264:52;18371:3;18360:9;18356:19;18350:26;18344:3;18336:6;18332:16;18325:52;18432:3;18421:9;18417:19;18411:26;18405:3;18397:6;18393:16;18386:52;18472:50;18517:3;18506:9;18502:19;18472:50;:::i;:::-;18466:3;18454:16;;18447:76;18458:6;17548:1006;-1:-1:-1;;;;17548:1006:1:o;18559:367::-;18598:3;18633:1;18630;18626:9;18742:1;18674:66;18670:74;18667:1;18663:82;18658:2;18651:10;18647:99;18644:125;;;18749:18;;:::i;:::-;18868:1;18800:66;18796:74;18793:1;18789:82;18785:2;18781:91;18778:117;;;18875:18;;:::i;:::-;-1:-1:-1;;18911:9:1;;18559:367::o;19813:1144::-;19882:5;19930:4;19918:9;19913:3;19909:19;19905:30;19902:50;;;19948:1;19945;19938:12;19902:50;19970:22;;:::i;:::-;19961:31;;20021:9;20015:16;20008:5;20001:31;20051:2;20106;20095:9;20091:18;20085:25;20080:2;20073:5;20069:14;20062:49;20164:2;20153:9;20149:18;20143:25;20138:2;20131:5;20127:14;20120:49;20201:46;20243:2;20232:9;20228:18;20201:46;:::i;:::-;20196:2;20189:5;20185:14;20178:70;20292:3;20281:9;20277:19;20271:26;20320:18;20312:6;20309:30;20306:50;;;20352:1;20349;20342:12;20306:50;20375:22;;20428:4;20420:13;;20416:23;-1:-1:-1;20406:51:1;;20453:1;20450;20443:12;20406:51;20482:2;20476:9;20505:60;20521:43;20561:2;20521:43;:::i;20505:60::-;20599:15;;;20681:1;20677:10;;;;20669:19;;20665:28;;;20630:12;;;;20705:15;;;20702:35;;;20733:1;20730;20723:12;20702:35;20757:11;;;;20777:135;20793:6;20788:3;20785:15;20777:135;;;20859:10;;20847:23;;20810:12;;;;20890;;;;20777:135;;;20939:3;20928:15;;20921:30;-1:-1:-1;20932:5:1;;19813:1144;-1:-1:-1;;;;;19813:1144:1:o;20962:1107::-;21094:6;21102;21146:9;21137:7;21133:23;21176:3;21172:2;21168:12;21165:32;;;21193:1;21190;21183:12;21165:32;21216:6;21242:2;21238;21234:11;21231:31;;;21258:1;21255;21248:12;21231:31;21284:22;;:::i;:::-;21271:35;;21335:9;21329:16;21322:5;21315:31;21399:2;21388:9;21384:18;21378:25;21373:2;21366:5;21362:14;21355:49;21457:2;21446:9;21442:18;21436:25;21431:2;21424:5;21420:14;21413:49;21515:2;21504:9;21500:18;21494:25;21489:2;21482:5;21478:14;21471:49;21574:3;21563:9;21559:19;21553:26;21547:3;21540:5;21536:15;21529:51;21634:3;21623:9;21619:19;21613:26;21607:3;21600:5;21596:15;21589:51;21694:3;21683:9;21679:19;21673:26;21667:3;21660:5;21656:15;21649:51;21754:3;21743:9;21739:19;21733:26;21727:3;21720:5;21716:15;21709:51;21779:3;21835:2;21824:9;21820:18;21814:25;21809:2;21802:5;21798:14;21791:49;;21859:5;21849:15;;21908:2;21897:9;21893:18;21887:25;21873:39;;;21935:18;21927:6;21924:30;21921:50;;;21967:1;21964;21957:12;21921:50;21990:73;22055:7;22046:6;22035:9;22031:22;21990:73;:::i;:::-;21980:83;;;20962:1107;;;;;:::o;22074:263::-;22150:6;22158;22211:2;22199:9;22190:7;22186:23;22182:32;22179:52;;;22227:1;22224;22217:12;22179:52;22256:9;22250:16;22240:26;;22285:46;22327:2;22316:9;22312:18;22285:46;:::i;:::-;22275:56;;22074:263;;;;;:::o;22342:306::-;22430:6;22438;22446;22499:2;22487:9;22478:7;22474:23;22470:32;22467:52;;;22515:1;22512;22505:12;22467:52;22544:9;22538:16;22528:26;;22594:2;22583:9;22579:18;22573:25;22563:35;;22638:2;22627:9;22623:18;22617:25;22607:35;;22342:306;;;;;:::o;22653:870::-;22761:6;22814:3;22802:9;22793:7;22789:23;22785:33;22782:53;;;22831:1;22828;22821:12;22782:53;22857:22;;:::i;:::-;22908:9;22902:16;22895:5;22888:31;22972:2;22961:9;22957:18;22951:25;22946:2;22939:5;22935:14;22928:49;23030:2;23019:9;23015:18;23009:25;23004:2;22997:5;22993:14;22986:49;23088:2;23077:9;23073:18;23067:25;23062:2;23055:5;23051:14;23044:49;23147:3;23136:9;23132:19;23126:26;23120:3;23113:5;23109:15;23102:51;23207:3;23196:9;23192:19;23186:26;23180:3;23173:5;23169:15;23162:51;23267:3;23256:9;23252:19;23246:26;23240:3;23233:5;23229:15;23222:51;23327:3;23316:9;23312:19;23306:26;23300:3;23293:5;23289:15;23282:51;23352:3;23408:2;23397:9;23393:18;23387:25;23382:2;23375:5;23371:14;23364:49;;23432:3;23488:2;23477:9;23473:18;23467:25;23462:2;23455:5;23451:14;23444:49;;23512:5;23502:15;;;22653:870;;;;:::o;24050:369::-;24089:4;24125:1;24122;24118:9;24234:1;24166:66;24162:74;24159:1;24155:82;24150:2;24143:10;24139:99;24136:125;;;24241:18;;:::i;:::-;24360:1;24292:66;24288:74;24285:1;24281:82;24277:2;24273:91;24270:117;;;24367:18;;:::i;:::-;-1:-1:-1;;24404:9:1;;24050:369::o;24424:191::-;24459:3;24490:66;24483:5;24480:77;24477:103;;;24560:18;;:::i;:::-;-1:-1:-1;24600:1:1;24596:13;;24424:191::o;25088:278::-;25176:6;25229:2;25217:9;25208:7;25204:23;25200:32;25197:52;;;25245:1;25242;25235:12;25197:52;25277:9;25271:16;25316:1;25309:5;25306:12;25296:40;;25332:1;25329;25322:12;25371:391;25589:25;;;25645:2;25630:18;;25623:34;;;25577:2;25562:18;;25687:1;25676:13;;25666:47;;25693:18;;:::i;:::-;25749:6;25744:2;25733:9;25729:18;25722:34;25371:391;;;;;;:::o;27508:184::-;27560:77;27557:1;27550:88;27657:4;27654:1;27647:15;27681:4;27678:1;27671:15

Swarm Source

ipfs://8658eba0811b3d065947163ce9e8140feba7a4558037c2af6364122a43041ab0
Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.