Contract 0x965e460bF5cb38BadA79fB2293c6304C799D0b1c 7

 

Contract Overview

Balance:
0 ETH

EtherValue:
$0.00

Token:
Txn Hash Method
Block
From
To
Value
0xdf175e41c143d3a13f2858aa9ae7847463b03c8ad8897202a0acbb03bcb8a2aaInitiate Withdra...1077273942023-08-03 9:06:0556 days 5 hrs ago0x2d1ef4acf4cae6a38950971aaaa15f88d9b3f165 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000452181440.100049293
0xa5056dc148650bcb24ece14bc07817d23b3795e371235a08cd79fdf41d5698abInitiate Withdra...1075782892023-07-30 22:15:5559 days 16 hrs ago 0x391985fdf0f28de092027d52763621221684cadf IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000271332210.000008328
0x64cbf9a648e8aa95157240a9f418ec0d62511a8fa02e7b08bc17309a969dbf12Initiate Withdra...1053692422023-06-09 19:01:01110 days 19 hrs ago0x049808d5eaa90a2665b9703d2246dded34f1eb73 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000299365130.000000082
0x333cf19d887e929df62354c670124dc1e6e0e8b30945e896975d93a1638433bcInitiate Withdra...1053684192023-06-09 18:33:35110 days 19 hrs ago0xcd7f6b72049c3b54416f9f26392cb271e74ca3fd IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000324219020.000000077
0x89709d09b805c4b3f4f6e1760234ea0497a299c2c5749bd790936fa24c95c9ceInitiate Withdra...1053684122023-06-09 18:33:21110 days 19 hrs ago0x0a8f4e308b17f836eab6493f42e48ac07d30946d IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000286407920.000000076
0xf1b3a251391253ea2633784721c28cf56272546ceb864520e73ccde0308552f1Initiate Withdra...1053683972023-06-09 18:32:51110 days 19 hrs ago0x0ae3d5949202165584a270cbac7a733b0307a766 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000303150460.000000075
0x33873402ca54e75ad5bb9cef7794d2a7f8e40e5ecaf399d8b78567cb2f13b80fInitiate Withdra...1053683962023-06-09 18:32:49110 days 19 hrs ago0x7565deddcb83a14b185eb9520914bb918cdfe983 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000306534920.000000075
0x3d4a10fe523b9ba8fcd57d224a147f9a516bd9b40319eb82b603a4f35efd2ac6Initiate Withdra...1053661942023-06-09 17:19:25110 days 21 hrs ago0xe64d330cc8654520815aa3ce90613d89b855e3a0 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000353698220.000000124
0x4adb4bdef2f0dec70b2cc12e7bb8780b044297e7dd58ba74ca4cb5bd9478dc6aInitiate Withdra...1053661882023-06-09 17:19:13110 days 21 hrs ago0x468c2dac680f0600bf8c86b6a8bbffc81f82f159 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000324000580.000000128
0x692a8d156b4391aaf0d074a152db2d61c685f84d8b174f58953cf196e385f77bInitiate Withdra...1053661712023-06-09 17:18:39110 days 21 hrs ago0xfba674dbbbfafed6da9895051e5204de824325b9 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000357990160.000000131
0x672b71c4fff9a8f3e6b34f064d8e1f6ee97a184311c9dfa10ac0cac34d61b8cdInitiate Withdra...1053376302023-06-09 1:27:17111 days 12 hrs ago0xaf6e292b39a429927c7ee68f7b9bfc04ede69f79 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000333751750.000000065
0x8a366eb79aa6c7ed0f8e4fa293b0cb601fc1700604a6773930413863af22680dInitiate Withdra...1053376182023-06-09 1:26:53111 days 12 hrs ago0xdfbc69683095fea6910cb570e8457071f876349c IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0002821883081.500000051
0xd9a166ab049b85847dbe6a83e110016dcaad9a03e10ee4e19f300d6a3c90deb4Initiate Withdra...1053365912023-06-09 0:52:39111 days 13 hrs ago0x74de40808d4eb76c480c882a3f8e4fc0a4701d01 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000328244040.000000152
0x18764d9241628454310e9c7af852819f7b42b5e2fb3cff4181c40d133cc5af28Initiate Withdra...1053365432023-06-09 0:51:03111 days 13 hrs ago0x0b7f9d46f0084503ad7b9e9266af2134da8ad596 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.00003381530.000000074
0xa27ab3780e761176654e1b77ef425fe0b2a5c27def8f6dacf67fbbda08c817f9Initiate Withdra...1053296192023-06-08 21:00:15111 days 17 hrs ago0x44bf69e0f457972d2840722cf8d422e86930a720 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000493379520.000000057
0x05ba574015118347ed7b857ccdb8e178b9c66ebe7f6bada6e2ba3668428d7167Initiate Withdra...1018731892023-05-27 1:41:47124 days 12 hrs ago0x3b2534b8ea1f9a8bf9d9915b91bae673d161f2a5 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0001113566310.001
0x4eb8e1dc91c4c557a6522ce4d691d562a05c0a28e01b3b3db4705cbb0acd9b8dInitiate Withdra...1018719912023-05-27 1:34:30124 days 12 hrs ago 0xf9107317b0ff77ed5b7adea15e50514a3564002b IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.000098947370.001
0x8cb18db90397a24f5bffbeeb752126288ca369c56ae3d33a064277c1ef77d2a0Initiate Withdra...877305672023-04-08 14:48:59172 days 23 hrs ago0x193f0ee42a199a0cecd479a9f09ba293eb1ca357 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000931242950.001
0x09610b2dfa00e3bc41c46d908ce506ef6fa3de0242aa1e1f3d42e0d7f9d49213Initiate Withdra...845023042023-03-29 6:25:32183 days 7 hrs ago0x64ac697f84bcddfacab514f07dd147c6958a7915 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0001049634610.001
0x986523aa18df3c32b654cd18de7efa9197a1cbd4595468501203862e262cc2b4Initiate Withdra...837468082023-03-26 5:50:18186 days 8 hrs ago0x7245a2b04b3360456c997fc79fa9d8881b82b8db IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.000053968320.001
0xb170d56d9828eec2bc26d322002f5909b0704288845572b74ccc054865ea3216Initiate Withdra...836530252023-03-25 16:30:48186 days 21 hrs ago0x651c636fc2adbb79fb2c8fbb1cf3a6f76ff1fdd9 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000915212070.001
0x0121cf18c22cce105b91935c2f37e5aa3beb6f0b2b25dbb6eddbcf0bec7efc57Initiate Withdra...750770242023-02-18 2:28:07222 days 11 hrs ago0x0e024cdba8377acf2d83e23090e27f5f8f490497 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0001086081030.001
0x4adbb40602953e62860eb0a655e252a5eed412ed97320a6facdcfcdde58b3729Initiate Withdra...660138142023-01-13 20:10:57257 days 18 hrs ago 0x8f804dec80028cb5bbc5537762b27629a4ab6c94 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.00018311330.001
0x5c843229c7683eb0a6408e8edc155a69ce4153a709ae1783296bb49e2a75468aInitiate Withdra...483917102022-12-12 10:28:35290 days 3 hrs ago0x696d181a7961ee66c42f1ebeddc0b48b106c45ad IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0001185932170.001
0x46b81565ed92fee453201437a8c4315e9a275bb00a21c20f857b803defd66b17Initiate Withdra...393125392022-11-18 10:34:08314 days 3 hrs ago0xd2033db9c5370ac76abd80823b5c5adc097e2fbf IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 ETH0.0000505914180.001
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x64cbf9a648e8aa95157240a9f418ec0d62511a8fa02e7b08bc17309a969dbf121053692422023-06-09 19:01:01110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x64cbf9a648e8aa95157240a9f418ec0d62511a8fa02e7b08bc17309a969dbf121053692422023-06-09 19:01:01110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 ETH
0x64cbf9a648e8aa95157240a9f418ec0d62511a8fa02e7b08bc17309a969dbf121053692422023-06-09 19:01:01110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x333cf19d887e929df62354c670124dc1e6e0e8b30945e896975d93a1638433bc1053684192023-06-09 18:33:35110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x333cf19d887e929df62354c670124dc1e6e0e8b30945e896975d93a1638433bc1053684192023-06-09 18:33:35110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 ETH
0x333cf19d887e929df62354c670124dc1e6e0e8b30945e896975d93a1638433bc1053684192023-06-09 18:33:35110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x89709d09b805c4b3f4f6e1760234ea0497a299c2c5749bd790936fa24c95c9ce1053684122023-06-09 18:33:21110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x89709d09b805c4b3f4f6e1760234ea0497a299c2c5749bd790936fa24c95c9ce1053684122023-06-09 18:33:21110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 ETH
0x89709d09b805c4b3f4f6e1760234ea0497a299c2c5749bd790936fa24c95c9ce1053684122023-06-09 18:33:21110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0xf1b3a251391253ea2633784721c28cf56272546ceb864520e73ccde0308552f11053683972023-06-09 18:32:51110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0xf1b3a251391253ea2633784721c28cf56272546ceb864520e73ccde0308552f11053683972023-06-09 18:32:51110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 ETH
0xf1b3a251391253ea2633784721c28cf56272546ceb864520e73ccde0308552f11053683972023-06-09 18:32:51110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x33873402ca54e75ad5bb9cef7794d2a7f8e40e5ecaf399d8b78567cb2f13b80f1053683962023-06-09 18:32:49110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x33873402ca54e75ad5bb9cef7794d2a7f8e40e5ecaf399d8b78567cb2f13b80f1053683962023-06-09 18:32:49110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 ETH
0x33873402ca54e75ad5bb9cef7794d2a7f8e40e5ecaf399d8b78567cb2f13b80f1053683962023-06-09 18:32:49110 days 19 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x3d4a10fe523b9ba8fcd57d224a147f9a516bd9b40319eb82b603a4f35efd2ac61053661942023-06-09 17:19:25110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x3d4a10fe523b9ba8fcd57d224a147f9a516bd9b40319eb82b603a4f35efd2ac61053661942023-06-09 17:19:25110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 ETH
0x3d4a10fe523b9ba8fcd57d224a147f9a516bd9b40319eb82b603a4f35efd2ac61053661942023-06-09 17:19:25110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x4adb4bdef2f0dec70b2cc12e7bb8780b044297e7dd58ba74ca4cb5bd9478dc6a1053661882023-06-09 17:19:13110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x4adb4bdef2f0dec70b2cc12e7bb8780b044297e7dd58ba74ca4cb5bd9478dc6a1053661882023-06-09 17:19:13110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 ETH
0x4adb4bdef2f0dec70b2cc12e7bb8780b044297e7dd58ba74ca4cb5bd9478dc6a1053661882023-06-09 17:19:13110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x692a8d156b4391aaf0d074a152db2d61c685f84d8b174f58953cf196e385f77b1053661712023-06-09 17:18:39110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x692a8d156b4391aaf0d074a152db2d61c685f84d8b174f58953cf196e385f77b1053661712023-06-09 17:18:39110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 ETH
0x692a8d156b4391aaf0d074a152db2d61c685f84d8b174f58953cf196e385f77b1053661712023-06-09 17:18:39110 days 21 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
0x672b71c4fff9a8f3e6b34f064d8e1f6ee97a184311c9dfa10ac0cac34d61b8cd1053376302023-06-09 1:27:17111 days 12 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 ETH
[ Download CSV Export 
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
GammaVault

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-08-25
*/

// 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/IAllowList.sol

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

interface IAllowList {
    function isAllowed(address) external view returns (bool);
}


// 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/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/synthetix/IFuturesMarket.sol

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

interface IFuturesMarket {
    function assetPrice() external view returns (uint256 price, bool invalid);

    function baseAsset() external view returns (bytes32 key);

    function remainingMargin(address account) external view returns (uint256 marginRemaining, bool invalid);

    function transferMargin(int256 marginDelta) external;

    function withdrawAllMargin() external;

    function modifyPositionWithTracking(int256 sizeDelta, bytes32 trackingCode) external;
}


// 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/GammaVault.sol

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













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

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

    struct PositionData {
        uint256 strikeId;
        uint256 positionId;
        uint256 optionAmount;
        uint256 premiumPaid;
        uint256 shortAmount;
        uint256 totalMargin;
    }

    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 private constant OPTION_TYPE = IOptionMarket.OptionType.LONG_CALL;

    /// -----------------------------------------------------------------------
    /// 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 OPTION_MARKET;

    /// @notice Synthetix Futures Market
    IFuturesMarket public immutable FUTURES_MARKET;

    /// @notice Lyra Option Market Wrapper
    IOptionMarketWrapperWithSwaps public immutable OPTION_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 Minimum deposit amount
    uint256 public minDepositAmount;

    /// @notice Maximum deposit amount
    uint256 public maxDepositAmount;

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

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

    /// @notice GWAV Length
    uint256 public gwavLength;

    /// @notice Leverage used for Futures positions
    uint256 public leverage;

    /// @notice Fee Receipient
    address public feeReceipient;

    /// @notice Performance Fee 
    uint256 public performanceFee;

    /// @notice Withdrawal Fee
    uint256 public withdrawalFee;

    /// @notice Synthetix Tracking Code
    bytes32 public synthetixTrackingCode;

    /// @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 Boolean flag to stop from opening new position if closing has started
    bool public hasClosingStarted;

    /// @notice Position Data
    PositionData public positionData;

    /// @notice Allow List
    IAllowList public allowList;

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

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

    constructor(
        ERC20 _susd,
        IPolynomialVaultToken _vaultToken,
        IOptionMarket _optionMarket,
        IFuturesMarket _futuresMarket,
        IOptionMarketWrapperWithSwaps _optionMarketWrapper,
        IOptionToken _optionToken,
        IOptionGreekCache _greeks,
        IExchangeRates _rates,
        bytes32 _underlyingKey,
        bytes32 _name
    ) Auth(msg.sender, Authority(address(0x0))) {
        VAULT_TOKEN = _vaultToken;
        OPTION_MARKET = _optionMarket;
        FUTURES_MARKET = _futuresMarket;
        OPTION_MARKET_WRAPPER = _optionMarketWrapper;
        OPTION_TOKEN = _optionToken;
        RATES = _rates;
        GREEKS = _greeks;
        UNDERLYING_SYNTH_KEY = _underlyingKey;
        name = _name;
        SUSD = _susd;
    }

    /// -----------------------------------------------------------------------
    /// 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 (positionData.optionAmount == 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 (positionData.optionAmount == 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, tokensToMint, 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 {
                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 and margin value of the positions
    function getTokenPrice() public view returns (uint256) {
        if (totalFunds == 0) {
            return 1e18;
        }

        uint256 totalSupply = getTotalSupply();
        if (positionData.optionAmount == 0) {
            return totalFunds.divWadDown(totalSupply);
        }

        (uint256 callPremium, ) = getPremiumForStrike(positionData.strikeId);
        (uint256 totalMargin, ) = FUTURES_MARKET.remainingMargin(address(this));
        uint256 usedValue = callPremium.mulWadDown(positionData.optionAmount) + totalMargin;

        return (totalFunds + usedValue - usedFunds).divWadDown(totalSupply);
    }

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

    /// -----------------------------------------------------------------------    
    /// 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
        ) = OPTION_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,
            ) = OPTION_MARKET.getSettlementParameters(_strikeId);

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

            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
        ) = OPTION_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 delta neutral position of a call option (of delta 0.4-0.6) and short futures
    /// @param strikeId Lyra strike ID of the call option
    /// @param amount Amount of options to buy
    /// @param maxPremiumAmount Maximum amount paid for purchasing the options
    function openPosition(uint256 strikeId, uint256 amount, uint256 maxPremiumAmount) external requiresAuth nonReentrant whenNotPaused {
        _openPosition(strikeId, amount, maxPremiumAmount);
    }

    /// @notice Close position (futures positions are closed propotional to total options size)
    /// @param amount Amount of options to close
    /// @param minPremium Minimum premium amount collected from each option closed
    function closePosition(uint256 amount, uint256 minPremium) external requiresAuth nonReentrant whenNotPaused {
        _closePosition(amount, minPremium);
    }

    /// -----------------------------------------------------------------------
    /// 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 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 Synthetix Volume Program Tracking Code
    /// @param _code New tracking code
    function setSynthetixTracking(bytes32 _code) external requiresAuth {
        emit UpdateSynthetixTrackingCode(synthetixTrackingCode, _code);
        synthetixTrackingCode = _code;
    }

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

    /// @notice Set Maximum deposit amount
    /// @param _maxAmt Maximum deposit amount
    function setMaxDepositAmount(uint256 _maxAmt) external requiresAuth {
        emit UpdateMaxDeposit(maxDepositAmount, _maxAmt);
        maxDepositAmount = _maxAmt;
    }

    /// @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 leverage used for futures positions
    /// @param _lev Leverage in 18 decimals
    function setLeverage(uint256 _lev) external requiresAuth {
        if (_lev > 5e18 || _lev < 1e18) {
            revert InvalidLeverage(leverage, _lev);
        }
        emit UpdateLeverage(leverage, _lev);
        leverage = _lev;
    }

    function setAllowList(IAllowList _list) external requiresAuth {
        emit UpdateAllowList(address(allowList), address(_list));
        allowList = _list;
    }

    /// @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 _openPosition(uint256 _strikeId, uint256 _amt, uint256 _maxPremium) internal {
        if ((positionData.positionId != 0 && positionData.strikeId != _strikeId) || hasClosingStarted) {
            revert InvalidRequest();
        }

        int256 callDelta = getCallDelta(_strikeId);

        if (callDelta < 4e17 || callDelta > 6e17) {
            revert InvalidOption(_strikeId, uint256(callDelta));
        }

        (uint256 spotPrice, bool isInvalid) = FUTURES_MARKET.assetPrice();

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

        uint256 _shortPosition = _amt.mulWadDown(uint256(callDelta));
        uint256 marginRequired = _shortPosition.mulDivDown(spotPrice, leverage);
        int256 shortPosition = -int256(_shortPosition);

        if (usedFunds + _maxPremium + marginRequired > totalFunds) {
            revert InsufficientFunds(totalFunds, usedFunds, _maxPremium + marginRequired);
        }

        ERC20(SUSD).safeApprove(address(OPTION_MARKET_WRAPPER), _maxPremium);

        IOptionMarketWrapperWithSwaps.OptionPositionParams memory params;

        params.optionMarket = OPTION_MARKET;
        params.strikeId = _strikeId;
        params.positionId = positionData.positionId;
        params.iterations = 4;
        // params.setCollateralTo = 0;
        // params.currentCollateral = 0;
        params.optionType = OPTION_TYPE;
        params.amount = _amt;
        // params.minCost = 0;
        params.maxCost = _maxPremium;
        params.inputAmount = _maxPremium;
        params.inputAsset = SUSD;

        IOptionMarketWrapperWithSwaps.ReturnDetails memory returnDetails = OPTION_MARKET_WRAPPER.openPosition(params);

        FUTURES_MARKET.transferMargin(int256(marginRequired));
        FUTURES_MARKET.modifyPositionWithTracking(shortPosition, synthetixTrackingCode);

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

        positionData.optionAmount += _amt;
        positionData.premiumPaid += returnDetails.totalCost;
        positionData.shortAmount += _shortPosition;
        positionData.totalMargin += marginRequired;

        usedFunds += marginRequired + returnDetails.totalCost;

        emit OpenPosition(
            _strikeId,
            positionData.positionId,
            _amt,
            returnDetails.totalCost,
            uint256(callDelta),
            _shortPosition,
            marginRequired
        );
    }

    function _closePosition(uint256 _amt, uint256 _minPremium) internal {
        if (positionData.positionId == 0) {
            revert ExpectedNonZero();
        }

        (uint256 spotPrice, bool isInvalid) = FUTURES_MARKET.assetPrice();

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

        if (!hasClosingStarted) {
            hasClosingStarted = true;
        }

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

        if (_amt >= positionData.optionAmount) {
            hasClosingStarted = false;

            IOptionMarketWrapperWithSwaps.OptionPositionParams memory params;

            params.optionMarket = OPTION_MARKET;
            params.strikeId = positionData.strikeId;
            params.positionId = positionData.positionId;
            params.iterations = 4;
            // params.setCollateralTo = 0;
            // params.currentCollateral = 0;
            params.optionType = OPTION_TYPE;
            params.amount = positionData.optionAmount;
            params.minCost = _minPremium.mulWadDown(params.amount);
            params.maxCost = type(uint256).max;
            // params.inputAmount = 0;
            params.inputAsset = SUSD;

            IOptionMarketWrapperWithSwaps.ReturnDetails memory returnDetails = OPTION_MARKET_WRAPPER.closePosition(params);

            FUTURES_MARKET.modifyPositionWithTracking(int256(positionData.shortAmount), synthetixTrackingCode);

            // No need to check for invalid since already done above
            (uint256 finalMargin, ) = FUTURES_MARKET.remainingMargin(address(this));

            FUTURES_MARKET.withdrawAllMargin();

            uint256 totalReceived = finalMargin + returnDetails.totalCost;

            if (totalReceived > usedFunds) {
                uint256 profit = totalReceived - usedFunds;
                uint256 perfFees = profit.mulWadDown(performanceFee);
                ERC20(SUSD).safeTransfer(feeReceipient, perfFees);
                totalFunds += (profit - perfFees);
            } else {
                totalFunds -= (usedFunds - totalReceived);
            }

            emit ClosePosition(
                positionData.strikeId,
                positionData.positionId,
                positionData.optionAmount,
                returnDetails.totalCost,
                positionData.shortAmount,
                finalMargin
            );

            usedFunds = 0;
            positionData.optionAmount = 0;
            positionData.positionId = 0;
            positionData.strikeId = 0;
            positionData.premiumPaid = 0;
            positionData.shortAmount = 0;
            positionData.totalMargin = 0;
        } else {
            IOptionMarketWrapperWithSwaps.OptionPositionParams memory params;

            params.optionMarket = OPTION_MARKET;
            params.strikeId = positionData.strikeId;
            params.positionId = positionData.positionId;
            params.iterations = 4;
            // params.setCollateralTo = 0;
            // params.currentCollateral = 0;
            params.optionType = OPTION_TYPE;
            params.amount = _amt;
            params.minCost = _minPremium.mulWadDown(_amt);
            params.maxCost = type(uint256).max;
            // params.inputAmount = 0;
            params.inputAsset = SUSD;

            IOptionMarketWrapperWithSwaps.ReturnDetails memory returnDetails = OPTION_MARKET_WRAPPER.closePosition(params);

            uint256 shortPositionToClose = _amt.mulDivDown(positionData.shortAmount, positionData.optionAmount);

            FUTURES_MARKET.modifyPositionWithTracking(int256(shortPositionToClose), synthetixTrackingCode);

            emit ClosePosition(
                positionData.strikeId,
                positionData.positionId,
                _amt,
                returnDetails.totalCost,
                shortPositionToClose,
                0
            );

            usedFunds -= returnDetails.totalCost;

            positionData.optionAmount -= _amt;
            positionData.shortAmount -= shortPositionToClose;
        }
    }

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

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

    /// Trading errors
    error InvalidPrice(uint256 spotPrice, bool isInvalid);
    error InvalidOption(uint256 strikeId, uint256 callDelta);
    error InvalidRequest();

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

    /// Owner actions
    error InvalidLeverage(uint256 currentLeverage, uint256 requestedLeverage);
    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 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 Synthetix Tracking Code Event
    /// @param oldCode Existing code
    /// @param newCode New code
    event UpdateSynthetixTrackingCode(bytes32 oldCode, bytes32 newCode);

    /// @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 Maximum Deposit Amount Event
    /// @param oldMax Previous maximum deposit amount
    /// @param newMax New maximum deposit amount
    event UpdateMaxDeposit(uint256 oldMax, uint256 newMax);

    /// @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 Leverage Event
    /// @param oldLeverage Old leverage
    /// @param newLeverage New leverage
    event UpdateLeverage(
        uint256 oldLeverage,
        uint256 newLeverage
    );

    /// @notice Update AllowList Event
    /// @param oldList Old AllowList
    /// @param newList New AllowList
    event UpdateAllowList(
        address oldList,
        address newList
    );

    /// @notice Open Position Event
    /// @param strikeId Lyra Option Strike ID
    /// @param positionId Corresponding Position ID
    /// @param amount Amount of options purchased
    /// @param premiumPaid Total premium paid
    /// @param callDelta Delta of the option
    /// @param shortPosition Amount of UNDERLYING shorted
    /// @param marginUsed Margin used for opening the short position
    event OpenPosition(
        uint256 strikeId,
        uint256 positionId,
        uint256 amount,
        uint256 premiumPaid,
        uint256 callDelta,
        uint256 shortPosition,
        uint256 marginUsed
    );

    /// @notice Close Position Event
    /// @param strikeId Lyra Option Strike ID
    /// @param positionId Corresponding Position ID
    /// @param amount Amount of options closed
    /// @param premiumCollected Total premium collected
    /// @param shortPosition Amount of futures position closed
    /// @param marginWithdrawn Margin withdrawn
    event ClosePosition(
        uint256 strikeId,
        uint256 positionId,
        uint256 amount,
        uint256 premiumCollected,
        uint256 shortPosition,
        uint256 marginWithdrawn
    );
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract ERC20","name":"_susd","type":"address"},{"internalType":"contract IPolynomialVaultToken","name":"_vaultToken","type":"address"},{"internalType":"contract IOptionMarket","name":"_optionMarket","type":"address"},{"internalType":"contract IFuturesMarket","name":"_futuresMarket","type":"address"},{"internalType":"contract IOptionMarketWrapperWithSwaps","name":"_optionMarketWrapper","type":"address"},{"internalType":"contract IOptionToken","name":"_optionToken","type":"address"},{"internalType":"contract IOptionGreekCache","name":"_greeks","type":"address"},{"internalType":"contract IExchangeRates","name":"_rates","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":"currentLeverage","type":"uint256"},{"internalType":"uint256","name":"requestedLeverage","type":"uint256"}],"name":"InvalidLeverage","type":"error"},{"inputs":[{"internalType":"uint256","name":"strikeId","type":"uint256"},{"internalType":"uint256","name":"callDelta","type":"uint256"}],"name":"InvalidOption","type":"error"},{"inputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"},{"internalType":"bool","name":"isInvalid","type":"bool"}],"name":"InvalidPrice","type":"error"},{"inputs":[],"name":"InvalidRequest","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":[],"name":"Paused","type":"error"},{"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":"premiumCollected","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shortPosition","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"marginWithdrawn","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":"premiumPaid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"callDelta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shortPosition","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"marginUsed","type":"uint256"}],"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":"address","name":"oldList","type":"address"},{"indexed":false,"internalType":"address","name":"newList","type":"address"}],"name":"UpdateAllowList","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":"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":"oldLeverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLeverage","type":"uint256"}],"name":"UpdateLeverage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMax","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMax","type":"uint256"}],"name":"UpdateMaxDeposit","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":"bytes32","name":"oldCode","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"newCode","type":"bytes32"}],"name":"UpdateSynthetixTrackingCode","type":"event"},{"inputs":[],"name":"FUTURES_MARKET","outputs":[{"internalType":"contract IFuturesMarket","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GREEKS","outputs":[{"internalType":"contract IOptionGreekCache","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTION_MARKET","outputs":[{"internalType":"contract IOptionMarket","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTION_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":"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":[],"name":"allowList","outputs":[{"internalType":"contract IAllowList","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minPremium","type":"uint256"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","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":"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":[],"name":"hasClosingStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"leverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDepositAmount","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"},{"internalType":"uint256","name":"maxPremiumAmount","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":[],"name":"positionData","outputs":[{"internalType":"uint256","name":"strikeId","type":"uint256"},{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"uint256","name":"optionAmount","type":"uint256"},{"internalType":"uint256","name":"premiumPaid","type":"uint256"},{"internalType":"uint256","name":"shortAmount","type":"uint256"},{"internalType":"uint256","name":"totalMargin","type":"uint256"}],"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 IAllowList","name":"_list","type":"address"}],"name":"setAllowList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","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":"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":"_lev","type":"uint256"}],"name":"setLeverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAmt","type":"uint256"}],"name":"setMaxDepositAmount","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":"bytes32","name":"_code","type":"bytes32"}],"name":"setSynthetixTracking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"synthetixTrackingCode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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"}]

6101c0604052600160025560016010556001601155600160125560016013553480156200002b57600080fd5b5060405162005446380380620054468339810160408190526200004e916200013f565b60008054336001600160a01b03199182168117835560018054909216909155604051909190829081907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908490a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350506003805461ffff191690556001600160a01b0398891660e052968816610100529487166101205292861661014052908516610160529084166101a05283166101805260a0526080521660c05262000215565b6001600160a01b03811681146200013c57600080fd5b50565b6000806000806000806000806000806101408b8d0312156200016057600080fd5b8a516200016d8162000126565b60208c0151909a50620001808162000126565b60408c0151909950620001938162000126565b60608c0151909850620001a68162000126565b60808c0151909750620001b98162000126565b60a08c0151909650620001cc8162000126565b60c08c0151909550620001df8162000126565b60e08c0151909450620001f28162000126565b809350506101008b015191506101208b015190509295989b9194979a5092959850565b60805160a05160c05160e05161010051610120516101405161016051610180516101a05161506c620003da6000396000818161064001528181613680015261450501526000818161089f015281816138730152818161392e01528181613a01015261462401526000818161087801528181612ac60152612b900152600081816105f301528181612aa201528181612bbd01528181612d4d015281816131eb01528181613df10152613edd015260008181610848015281816114780152818161295901528181612e1301528181612ea701528181612f2e015281816132c701528181613c3701528181613f97015261402c01526000818161078601528181612c6f01528181613111015281816135620152818161375b01528181613e2001526143e70152600081816104f60152818161168d01528181611f000152818161220301526124ab01526000818161043501528181610fcd01528181611017015281816111210152818161116b01528181611d60015281816120620152818161265b01528181612cfb01528181612ffa0152818161319901528181613dcf0152613e8b0152600081816107270152818161364801526144cd015260006103c3015261506c6000f3fe608060405234801561001057600080fd5b50600436106103af5760003560e01c806379575b23116101f4578063bf7e214f1161011a578063e3d51ddd116100ad578063ed6d06c01161007c578063ed6d06c0146108e1578063f6011230146108f4578063fc2da41f146108fd578063fd9d40771461090657600080fd5b8063e3d51ddd14610873578063e55d1a521461089a578063eb899c68146108c1578063ec552346146108ce57600080fd5b8063c8393ba9116100e9578063c8393ba91461081d578063ccf3aed214610830578063d3e6f7f314610843578063deccdf631461086a57600080fd5b8063bf7e214f146107a8578063c4511c6a146107bb578063c4e41b22146107ce578063c822adda146107d657600080fd5b8063892df74f116101925780638ed83271116101615780638ed832711461075c578063968ed600146107655780639afdb2c21461076e5780639be75fb71461078157600080fd5b8063892df74f146107105780638bc7e8c4146107195780638da4e2f9146107225780638da5cb5b1461074957600080fd5b806383290a3c116101ce57806383290a3c146106755780638456cb59146106ec57806387788782146106f457806387b9d25c146106fd57600080fd5b806379575b231461062857806379f67c441461063b5780637a9e5e4b1461066257600080fd5b80633f4ba83a116102d957806358f67c0b1161027757806363d8882a1161024657806363d8882a146105dd578063645006ca146105e557806366d0cb91146105ee5780637772ba071461061557600080fd5b806358f67c0b1461059a5780635c975abb146105a35780635ece09c5146105ba57806360da3e83146105cd57600080fd5b80634aab90f8116102b35780634aab90f8146105215780634b48f20d1461056c5780634b94f50e1461057f5780634d8737cb1461058757600080fd5b80633f4ba83a146104e95780634499d14b146104f1578063481bf0b81461051857600080fd5b8063208e7e93116103515780632d6ce61d116103205780632d6ce61d146104a7578063342c00b3146104ba57806335f748c2146104cd5780633740ebb3146104d657600080fd5b8063208e7e931461046f5780632a80cda3146104785780632b6fcf2e1461048b5780632c86d98e1461049e57600080fd5b80630b78f9c01161038d5780630b78f9c01461040157806313af40351461041457806315a01bc11461042757806315d8eeba1461043057600080fd5b806302191980146103b457806306fdde03146103be5780630b2ad088146103f8575b600080fd5b6103bc61090f565b005b6103e57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6103e560135481565b6103bc61040f3660046148b0565b610998565b6103bc6104223660046148ea565b610adb565b6103e560155481565b6104577f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103ef565b6103e560105481565b6103bc610486366004614907565b610bb8565b6103bc610499366004614907565b610c73565b6103e560095481565b6103bc6104b53660046148b0565b610d2e565b6103bc6104c8366004614907565b610e4e565b6103e560065481565b600a54610457906001600160a01b031681565b6103bc61122d565b6104577f000000000000000000000000000000000000000000000000000000000000000081565b6103e5600f5481565b601754601854601954601a54601b54601c5461053f95949392919086565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0016103ef565b6103bc61057a3660046148ea565b6112af565b6103e56113ea565b6103bc610595366004614907565b611549565b6103e5600e5481565b60035460ff165b60405190151581526020016103ef565b6103bc6105c8366004614920565b61178c565b600354610100900460ff166105aa565b6103bc6118ae565b6103e560045481565b6104577f000000000000000000000000000000000000000000000000000000000000000081565b6103bc6106233660046148b0565b611930565b6103bc610636366004614907565b611a00565b6104577f000000000000000000000000000000000000000000000000000000000000000081565b6103bc6106703660046148ea565b611b1d565b6106bc610683366004614907565b601e602052600090815260409020805460018201546002830154600384015460049094015492936001600160a01b039092169290919085565b604080519586526001600160a01b039094166020860152928401919091526060830152608082015260a0016103ef565b6103bc611c62565b6103e5600b5481565b601d54610457906001600160a01b031681565b6103e560125481565b6103e5600c5481565b6103e57f000000000000000000000000000000000000000000000000000000000000000081565b600054610457906001600160a01b031681565b6103e560055481565b6103e560145481565b6103bc61077c36600461494c565b611ce4565b6104577f000000000000000000000000000000000000000000000000000000000000000081565b600154610457906001600160a01b031681565b6103bc6107c9366004614907565b611e3e565b6103e5611ef9565b6106bc6107e4366004614907565b601f602052600090815260409020805460018201546002830154600384015460049094015492936001600160a01b039092169290919085565b6103bc61082b36600461498d565b611f9e565b6103bc61083e366004614907565b612270565b6104577f000000000000000000000000000000000000000000000000000000000000000081565b6103e560085481565b6104577f000000000000000000000000000000000000000000000000000000000000000081565b6104577f000000000000000000000000000000000000000000000000000000000000000081565b6016546105aa9060ff1681565b6103bc6108dc36600461498d565b61232b565b6103bc6108ef3660046148ea565b612683565b6103e5600d5481565b6103e560115481565b6103e560075481565b61093d336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b61098e5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b610996612877565b565b6109c6336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b610a125760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b67016345785d8a0000821180610a2e5750662386f26fc1000081115b15610a8257600b54600c546040517f0995039e000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044810183905260648101829052608401610985565b600b54600c546040805192835260208301919091528101839052606081018290527f5c3aee3d65f7eb02cded951435d06b06ef307bc7f57b98975c4a41dc116e711c9060800160405180910390a1600b91909155600c55565b610b09336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b610b555760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b610be6336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b610c325760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b60045460408051918252602082018390527f915e1f57375bebe5483299c788956d167e46a28a143974dc29bba5a420aa4354910160405180910390a1600455565b610ca1336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b610ced5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b60085460408051918252602082018390527f40777929ad14ec610067fc9c075e20805fe1c57e1879cf2b583355109971c546910160405180910390a1600855565b610d5c336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b610da85760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b600254600114610dfa5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610985565b6002805560035460ff1615610e3b576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e45828261291b565b50506001600255565b600254600114610ea05760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610985565b6002805560005b81811015610e45576000610eb96113ea565b6012546000908152601f602052604090206004810154919250901580610eef57506007548160040154610eec91906149e8565b42105b15610efc57505050611225565b6000601554601454610f0e9190614a00565b905080610f1e5750505050611225565b6002820154600090610f3090856133e1565b9050818111156110ab57600383018290556000610f4d83866133fd565b905080600f6000828254610f619190614a00565b9250508190555080846002016000828254610f7c9190614a00565b925050819055508260146000828254610f959190614a00565b9091555050600c5415611004576000610fb9600c54856133e190919063ffffffff16565b600a54909150610ff6906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613412565b6110008185614a00565b9350505b6001840154611040906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911685613412565b835460018501546004860154604080519384526001600160a01b039092166020840152828201849052606083018690526080830152517f36a40db5d5631acd8e2764bd196c60dd82faed72aea6647297ab6af63309b58e9181900360a00190a1505050505050611225565b600383018190556002830154600f80546000906110c9908490614a00565b9091555050600060028401819055601480548392906110e9908490614a00565b9091555050600c541561115857600061110d600c54836133e190919063ffffffff16565b600a5490915061114a906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613412565b6111548183614a00565b9150505b6001830154611194906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613412565b8254600184015460028501546004860154604080519485526001600160a01b039093166020850152918301526060820183905260808201527f86dc3fd2a6c267674f2f2ef1b4b7283dcca31e1e2517a55358795c65eca1fe039060a00160405180910390a16012805490600061120983614a17565b919050555050505050808061121d90614a17565b915050610ea7565b506001600255565b61125b336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b6112a75760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b6109966134b1565b6112dd336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b6113295760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b6001600160a01b038116611369576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a54604080516001600160a01b03928316815291831660208301527fc8bc890a52e17e373db7ac75d8f97911a18bffc2ef18bd8047ed55770ee6ba8b910160405180910390a1600a80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000601454600014156114045750670de0b6b3a764000090565b600061140e611ef9565b60195490915061142b576014546114259082613545565b91505090565b600061143b60176000015461355a565b506040517f9cfbf4e40000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639cfbf4e490602401604080518083038186803b1580156114b957600080fd5b505afa1580156114cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f19190614a65565b50905060008161150f601760020154856133e190919063ffffffff16565b61151991906149e8565b9050611540846015548360145461153091906149e8565b61153a9190614a00565b90613545565b94505050505090565b60025460011461159b5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610985565b6002805560006115a96113ea565b905060005b82811015611782576010546000908152601e60205260409020600481015415806115e8575060065481600401546115e591906149e8565b42105b156115f557505050611225565b60028101546000906116079085613545565b90508082600301819055508160020154600e60008282546116289190614a00565b90915550506002820154601480546000906116449084906149e8565b909155505060018201546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152602481018390527f0000000000000000000000000000000000000000000000000000000000000000909116906340c10f1990604401600060405180830381600087803b1580156116d357600080fd5b505af11580156116e7573d6000803e3d6000fd5b50508354600185015460028601546004870154604080519485526001600160a01b039093166020850152918301526060820185905260808201527f4d356a2d534287c80daa3bb725dcc09c0ad1049e50c1e328646c49e5a0b2c6cb925060a001905060405180910390a1600060028301819055601080549161176883614a17565b91905055505050808061177a90614a17565b9150506115ae565b5050506001600255565b6117ba336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b6118065760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b6002546001146118585760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610985565b6002805560035460ff1615611899576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118a4838383613b70565b5050600160025550565b6118dc336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b6119285760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b6109966141b5565b61195e336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b6119aa5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b6006546007546040805192835260208301859052820152606081018290527fc8f5f7dffddfef257dee57a6cd0384a4900f2ab48c3e69766faa5577e6a7cbcb9060800160405180910390a1600691909155600755565b611a2e336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b611a7a5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b674563918244f40000811180611a975750670de0b6b3a764000081105b15611adc576009546040517f3a997bfc000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610985565b60095460408051918252602082018390527f0994a4aef927e586cf27b92c43c2e63b627e9a4892c704b4d73170655e6e6cf9910160405180910390a1600955565b6000546001600160a01b0316331480611bf557506001546040517fb70096130000000000000000000000000000000000000000000000000000000081523360048201523060248201526000357fffffffff000000000000000000000000000000000000000000000000000000001660448201526001600160a01b039091169063b70096139060640160206040518083038186803b158015611bbd57600080fd5b505afa158015611bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf59190614a91565b611bfe57600080fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b611c90336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b611cdc5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b61099661424e565b611d12336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b611d5e5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161415611d9d57600080fd5b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b158015611e0057600080fd5b505af1158015611e14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e389190614a91565b50505050565b611e6c336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b611eb85760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b60055460408051918252602082018390527f37396aa6d615d710c40a1a725316294e4ff3ba20b5544b517a84d89f08178ad8910160405180910390a1600555565b6000600f547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5757600080fd5b505afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190614aac565b611f9991906149e8565b905090565b600254600114611ff05760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610985565b600280556001600160a01b038216612034576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6019546120fe5760006120456113ea565b9050600061205383836133e1565b90506120896001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168583613412565b806014600082825461209b9190614a00565b909155505060408051600081526001600160a01b0386166020820152908101849052606081018290524260808201527f86dc3fd2a6c267674f2f2ef1b4b7283dcca31e1e2517a55358795c65eca1fe039060a00160405180910390a150506121ce565b601380546000818152601f60205260408120929061211b83614a17565b9091555081556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03851617905560028101829055426004820155600f80548391906000906121789084906149e8565b90915550508054604080519182523360208301526001600160a01b0385168282015260608201849052517f6af4b9a67fcdcb6bdd58b7b26c00492d52c66372d350d228ec6a5420bb13fe329181900360800190a1505b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac90604401600060405180830381600087803b15801561224f57600080fd5b505af1158015612263573d6000803e3d6000fd5b5050600160025550505050565b61229e336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b6122ea5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b600d5460408051918252602082018390527fe6a80d2c46fa6481cec16136a0a5b4f293bf679480d7790883589d7f54ce91d1910160405180910390a1600d55565b60025460011461237d5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610985565b60028055600354610100900460ff16156123c3576040517fdeeb694300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038216612403576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045481101561244a57600480546040517f54443ec40000000000000000000000000000000000000000000000000000000081529182015260248101829052604401610985565b60195461257e57600061245b6113ea565b905060006124698383613545565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152602482018390529192507f0000000000000000000000000000000000000000000000000000000000000000909116906340c10f1990604401600060405180830381600087803b1580156124f157600080fd5b505af1158015612505573d6000803e3d6000fd5b50505050826014600082825461251b91906149e8565b909155505060408051600081526001600160a01b0386166020820152908101849052606081018290524260808201527f4d356a2d534287c80daa3bb725dcc09c0ad1049e50c1e328646c49e5a0b2c6cb9060a00160405180910390a1505061264e565b601180546000818152601e60205260408120929061259b83614a17565b9091555081556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03851617905560028101829055426004820155600e80548391906000906125f89084906149e8565b90915550508054604080519182523360208301526001600160a01b0385168282015260608201849052517f1ccb85c4426dacaaa67edc2ae6421283328736c96dd21b82026889d72414832c9181900360800190a1505b610e456001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330846142e7565b6126b1336000357fffffffff000000000000000000000000000000000000000000000000000000001661277e565b6126fd5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610985565b601d54604080516001600160a01b03928316815291831660208301527f1926d1b6d5bb49538b382b82a523f908b1d71147ac6efdca65337bfc00adbefc910160405180910390a1601d80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001546000906001600160a01b0316801580159061285757506040517fb70096130000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301523060248301527fffffffff000000000000000000000000000000000000000000000000000000008516604483015282169063b70096139060640160206040518083038186803b15801561281f57600080fd5b505afa158015612833573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128579190614a91565b8061286f57506000546001600160a01b038581169116145b949350505050565b600354610100900460ff16156128b9576040517fdeeb694300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556040513381527fcb92ca4a4d7ab7e82e1f35164d09a91663f3393b45f06fcac5a73f63ae6bf23f906020015b60405180910390a1565b601854612954576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d24378eb6040518163ffffffff1660e01b8152600401604080518083038186803b1580156129af57600080fd5b505afa1580156129c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e79190614a65565b9150915081600014806129f75750805b15612a39576040517f7ba84727000000000000000000000000000000000000000000000000000000008152600481018390528115156024820152604401610985565b60165460ff16612a6f57601680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b6018546040517f081812fc0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116927f00000000000000000000000000000000000000000000000000000000000000009091169163081812fc91612aff9160040190815260200190565b60206040518083038186803b158015612b1757600080fd5b505afa158015612b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4f9190614ad0565b6001600160a01b031614612c2c576018546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163095ea7b391612bf9917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015612c1357600080fd5b505af1158015612c27573d6000803e3d6000fd5b505050505b60195484106130ff57601680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055612c6561482c565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001681526017546020820152601854604082015260046060820152600060c082015260195460e08201819052612cc49085906133e1565b6101008201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101208201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166101608301526040517fb738a96b0000000000000000000000000000000000000000000000000000000081526000917f0000000000000000000000000000000000000000000000000000000000000000169063b738a96b90612d82908590600401614b57565b61010060405180830381600087803b158015612d9d57600080fd5b505af1158015612db1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd59190614ce3565b601b54600d546040517fa28a2bc0000000000000000000000000000000000000000000000000000000008152600481019290925260248201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a28a2bc090604401600060405180830381600087803b158015612e5f57600080fd5b505af1158015612e73573d6000803e3d6000fd5b50506040517f9cfbf4e4000000000000000000000000000000000000000000000000000000008152306004820152600092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169150639cfbf4e490602401604080518083038186803b158015612ef157600080fd5b505afa158015612f05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f299190614a65565b5090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635a1cbd2b6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612f8757600080fd5b505af1158015612f9b573d6000803e3d6000fd5b505050506000826080015182612fb191906149e8565b905060155481111561304b57600060155482612fcd9190614a00565b90506000612fe6600b54836133e190919063ffffffff16565b600a54909150613023906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613412565b61302d8183614a00565b6014600082825461303e91906149e8565b9091555061307092505050565b806015546130599190614a00565b6014600082825461306a9190614a00565b90915550505b601754601854601954608086810151601b5460408051968752602087019590955285850193909352606085015283015260a08201849052517f9741bf68d4078249163675971e787afff796b7de3d42127e74eb3a541c1d14ca9181900360c00190a1505060006015819055601981905560188190556017819055601a819055601b819055601c5550611e389050565b61310761482c565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001681526017546020820152601854604082015260046060820152600060c082015260e0810185905261316284866133e1565b6101008201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101208201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166101608301526040517fb738a96b0000000000000000000000000000000000000000000000000000000081526000917f0000000000000000000000000000000000000000000000000000000000000000169063b738a96b90613220908590600401614b57565b61010060405180830381600087803b15801561323b57600080fd5b505af115801561324f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132739190614ce3565b601b5460195491925060009161328a918991614393565b600d546040517fa28a2bc00000000000000000000000000000000000000000000000000000000081526004810183905260248101919091529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a28a2bc090604401600060405180830381600087803b15801561331357600080fd5b505af1158015613327573d6000803e3d6000fd5b50506017546018546080868101516040805194855260208501939093528383018d905260608401528201859052600060a0830152517f9741bf68d4078249163675971e787afff796b7de3d42127e74eb3a541c1d14ca93509081900360c0019150a181608001516015600082825461339f9190614a00565b9091555050601980548891906000906133b9908490614a00565b9091555050601b80548291906000906133d3908490614a00565b909155505050505050505050565b60006133f68383670de0b6b3a7640000614393565b9392505050565b60006133f683670de0b6b3a7640000846143b2565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611e385760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610985565b60035460ff166134ed576040517f6cd6020100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556040513381527f3bd4fb9a28883a4c90034f2cd214c1f94fc09854604f38dee6a87e5455e2123b90602001612911565b60006133f683670de0b6b3a764000084614393565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4c4a0d0866040518263ffffffff1660e01b81526004016135ae91815260200190565b60006040518083038186803b1580156135c657600080fd5b505afa1580156135da573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526136209190810190614e6a565b6040517f0c71cd230000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152919350915060009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630c71cd2390602401604080518083038186803b1580156136c157600080fd5b505afa1580156136d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136f99190614a65565b9150915081600014806137095750805b1561371357600080fd5b8260200151421115613836576040517f1fdb6cbd0000000000000000000000000000000000000000000000000000000081526004810188905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631fdb6cbd9060240160606040518083038186803b15801561379d57600080fd5b505afa1580156137b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137d59190614f24565b50915091508060001415613815576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81811161382357600061382d565b61382d8282614a00565b97505050613b67565b82516008546040517ff3fd9b3d000000000000000000000000000000000000000000000000000000008152600481019290925260248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f3fd9b3d9060440160206040518083038186803b1580156138bd57600080fd5b505afa1580156138d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f59190614aac565b6008546040517f7df712680000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691637df712689161396c918d91600401918252602082015260400190565b60206040518083038186803b15801561398457600080fd5b505afa158015613998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139bc9190614aac565b905060006040518060a001604052804288602001516139db9190614a00565b81526020016139ea85856133e1565b8152602001868152602001886020015181526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f369f2ac6040518163ffffffff1660e01b81526004016101406040518083038186803b158015613a5957600080fd5b505afa158015613a6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a919190614f52565b61012001519052604080517fbcf1e77900000000000000000000000000000000000000000000000000000000815282516004820152602083015160248201529082015160448201526060820151606482015260808201516084820152909150730052a341bea99c4b452816235fc2216143c5f21c9063bcf1e7799060a401604080518083038186803b158015613b2657600080fd5b505af4158015613b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b5e9190614fd9565b90995097505050505b50505050915091565b60185415801590613b8357506017548314155b80613b90575060165460ff165b15613bc7576040517f41abc80100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613bd2846143e0565b905067058d15e176280000811280613bf15750670853a0d2313c000081135b15613c32576040517ffbf7b2e80000000000000000000000000000000000000000000000000000000081526004810185905260248101829052604401610985565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d24378eb6040518163ffffffff1660e01b8152600401604080518083038186803b158015613c8d57600080fd5b505afa158015613ca1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc59190614a65565b915091508160001480613cd55750805b15613d17576040517f7ba84727000000000000000000000000000000000000000000000000000000008152600481018390528115156024820152604401610985565b6000613d2386856133e1565b90506000613d3e84600954846143939092919063ffffffff16565b90506000613d4b83614ffd565b90506014548288601554613d5f91906149e8565b613d6991906149e8565b1115613dc257601454601554613d7f848a6149e8565b6040517ff5623b72000000000000000000000000000000000000000000000000000000008152600481019390935260248301919091526044820152606401610985565b613e166001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008961478d565b613e1e61482c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602081018a9052601854604082015260046060820152600060c082018190525060e08101899052610120810188905261014081018890526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166101608301526040517f8bc369690000000000000000000000000000000000000000000000000000000081526000917f00000000000000000000000000000000000000000000000000000000000000001690638bc3696990613f12908590600401614b57565b61010060405180830381600087803b158015613f2d57600080fd5b505af1158015613f41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f659190614ce3565b6040517f88a3c848000000000000000000000000000000000000000000000000000000008152600481018690529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906388a3c84890602401600060405180830381600087803b158015613fe357600080fd5b505af1158015613ff7573d6000803e3d6000fd5b5050600d546040517fa28a2bc00000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a28a2bc0925061406c918791600401918252602082015260400190565b600060405180830381600087803b15801561408657600080fd5b505af115801561409a573d6000803e3d6000fd5b5050601854151591506140b7905057602081015160185560178b90555b89601760020160008282546140cc91906149e8565b90915550506080810151601a80546000906140e89084906149e8565b9091555050601b80548691906000906141029084906149e8565b9091555050601c805485919060009061411c9084906149e8565b9091555050608081015161413090856149e8565b6015600082825461414191906149e8565b9091555050601854608082810151604080518f8152602081019490945283018d90526060830152810189905260a0810186905260c081018590527f119df371ee542c429dd5298bb603872532a3e9dfdc1c794ad226298126f295a19060e00160405180910390a15050505050505050505050565b600354610100900460ff166141f6576040517fa4d3098c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690556040513381527fd9b17f88c19eed029496a647acd647444182c708871dadb0b13c8db2bbcdff3690602001612911565b60035460ff161561428b576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790556040513381527ff87d42f34d6dc854596ee7e10d09f6ef97f38e4ab22330c4fcb384c7e7f81d1990602001612911565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d116001600051141617169150508061438c5760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610985565b5050505050565b8282028115158415858304851417166143ab57600080fd5b0492915050565b8282028115158415858304851417166143ca57600080fd5b6001826001830304018115150290509392505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4c4a0d0856040518263ffffffff1660e01b815260040161443391815260200190565b60006040518083038186803b15801561444b57600080fd5b505afa15801561445f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526144a59190810190614e6a565b6040517f0c71cd230000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152919350915060009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630c71cd2390602401604080518083038186803b15801561454657600080fd5b505afa15801561455a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061457e9190614a65565b91509150816000148061458e5750805b156145d0576040517f7ba84727000000000000000000000000000000000000000000000000000000008152600481018390528115156024820152604401610985565b60006040518060a001604052804286602001516145ed9190614a00565b815260200161460d876040015187604001516133e190919063ffffffff16565b8152602001848152602001866020015181526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f369f2ac6040518163ffffffff1660e01b81526004016101406040518083038186803b15801561467c57600080fd5b505afa158015614690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146b49190614f52565b61012001519052604080517fdc1f2cd800000000000000000000000000000000000000000000000000000000815282516004820152602083015160248201529082015160448201526060820151606482015260808201516084820152909150730052a341bea99c4b452816235fc2216143c5f21c9063dc1f2cd89060a401604080518083038186803b15801561474957600080fd5b505af415801561475d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147819190614fd9565b50979650505050505050565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611e385760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610985565b60405180610180016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000600481111561487e5761487e614aed565b81526020016000815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b600080604083850312156148c357600080fd5b50508035926020909101359150565b6001600160a01b03811681146148e757600080fd5b50565b6000602082840312156148fc57600080fd5b81356133f6816148d2565b60006020828403121561491957600080fd5b5035919050565b60008060006060848603121561493557600080fd5b505081359360208301359350604090920135919050565b60008060006060848603121561496157600080fd5b833561496c816148d2565b9250602084013561497c816148d2565b929592945050506040919091013590565b600080604083850312156149a057600080fd5b82356149ab816148d2565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156149fb576149fb6149b9565b500190565b600082821015614a1257614a126149b9565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614a4957614a496149b9565b5060010190565b80518015158114614a6057600080fd5b919050565b60008060408385031215614a7857600080fd5b82519150614a8860208401614a50565b90509250929050565b600060208284031215614aa357600080fd5b6133f682614a50565b600060208284031215614abe57600080fd5b5051919050565b8051614a60816148d2565b600060208284031215614ae257600080fd5b81516133f6816148d2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60058110614b53577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b81516001600160a01b0316815261018081016020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c0830151614bad60c0840182614b1c565b5060e08381015190830152610100808401519083015261012080840151908301526101408084015190830152610160928301516001600160a01b0316929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715614c4657614c46614bf4565b60405290565b604051610120810167ffffffffffffffff81118282101715614c4657614c46614bf4565b604051610140810167ffffffffffffffff81118282101715614c4657614c46614bf4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614cdb57614cdb614bf4565b604052919050565b6000610100808385031215614cf757600080fd5b6040519081019067ffffffffffffffff82118183101715614d1a57614d1a614bf4565b8160405283519150614d2b826148d2565b81815260208401516020820152614d4460408501614ac5565b6040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c0820152614d7d60e08501614ac5565b60e0820152949350505050565b600060a08284031215614d9c57600080fd5b614da4614c23565b9050815181526020808301518183015260408301516040830152614dca60608401614a50565b6060830152608083015167ffffffffffffffff80821115614dea57600080fd5b818501915085601f830112614dfe57600080fd5b815181811115614e1057614e10614bf4565b8060051b9150614e21848301614c94565b8181529183018401918481019088841115614e3b57600080fd5b938501935b83851015614e5957845182529385019390850190614e40565b608087015250939695505050505050565b600080828403610140811215614e7f57600080fd5b61012080821215614e8f57600080fd5b614e97614c4c565b9150845182526020850151602083015260408501516040830152606085015160608301526080850151608083015260a085015160a083015260c085015160c083015260e085015160e08301526101008086015181840152508193508085015191505067ffffffffffffffff811115614f0e57600080fd5b614f1a85828601614d8a565b9150509250929050565b600080600060608486031215614f3957600080fd5b8351925060208401519150604084015190509250925092565b60006101408284031215614f6557600080fd5b614f6d614c70565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152508091505092915050565b60008060408385031215614fec57600080fd5b505080516020909101519092909150565b60007f800000000000000000000000000000000000000000000000000000000000000082141561502f5761502f6149b9565b506000039056fea26469706673582212209d64b807adb35d317264c56167137a0c4c4c88d5a7bba2cbef2295c46501ced164736f6c634300080900330000000000000000000000008c6f28f2f1a3c87f0f938b96d27520d9751ec8d90000000000000000000000004beffd38832b5f158d5a05d374ae971dd0e326f20000000000000000000000001d42a98848e022908069c2c545ae44cc78509bc8000000000000000000000000f86048dff23cf130107dfb4e6386f574231a5c65000000000000000000000000cce7819d65f348c64b7beb205ba367b3fe33763b000000000000000000000000cfdff4e171133d55de2e45c66a0e144a135d93f2000000000000000000000000bb3e8eac35e649ed1071a9ec42223d474e67b19a00000000000000000000000022602469d704bffb0936c7a7cfcd18f7aa2693757345544800000000000000000000000000000000000000000000000000000000734554482047616d6d61205661756c7400000000000000000000000000000000

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

0000000000000000000000008c6f28f2f1a3c87f0f938b96d27520d9751ec8d90000000000000000000000004beffd38832b5f158d5a05d374ae971dd0e326f20000000000000000000000001d42a98848e022908069c2c545ae44cc78509bc8000000000000000000000000f86048dff23cf130107dfb4e6386f574231a5c65000000000000000000000000cce7819d65f348c64b7beb205ba367b3fe33763b000000000000000000000000cfdff4e171133d55de2e45c66a0e144a135d93f2000000000000000000000000bb3e8eac35e649ed1071a9ec42223d474e67b19a00000000000000000000000022602469d704bffb0936c7a7cfcd18f7aa2693757345544800000000000000000000000000000000000000000000000000000000734554482047616d6d61205661756c7400000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _susd (address): 0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9
Arg [1] : _vaultToken (address): 0x4bEFFd38832b5F158d5a05D374AE971DD0e326F2
Arg [2] : _optionMarket (address): 0x1d42a98848e022908069c2c545aE44Cc78509Bc8
Arg [3] : _futuresMarket (address): 0xf86048DFf23cF130107dfB4e6386f574231a5C65
Arg [4] : _optionMarketWrapper (address): 0xCCE7819d65f348c64B7Beb205BA367b3fE33763B
Arg [5] : _optionToken (address): 0xCfDfF4E171133D55dE2e45c66a0E144a135D93f2
Arg [6] : _greeks (address): 0xbb3e8Eac35e649ed1071A9Ec42223d474e67b19A
Arg [7] : _rates (address): 0x22602469d704BfFb0936c7A7cfcD18f7aA269375
Arg [8] : _underlyingKey (bytes32): 0x7345544800000000000000000000000000000000000000000000000000000000
Arg [9] : _name (bytes32): 0x734554482047616d6d61205661756c7400000000000000000000000000000000

-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000008c6f28f2f1a3c87f0f938b96d27520d9751ec8d9
Arg [1] : 0000000000000000000000004beffd38832b5f158d5a05d374ae971dd0e326f2
Arg [2] : 0000000000000000000000001d42a98848e022908069c2c545ae44cc78509bc8
Arg [3] : 000000000000000000000000f86048dff23cf130107dfb4e6386f574231a5c65
Arg [4] : 000000000000000000000000cce7819d65f348c64b7beb205ba367b3fe33763b
Arg [5] : 000000000000000000000000cfdff4e171133d55de2e45c66a0e144a135d93f2
Arg [6] : 000000000000000000000000bb3e8eac35e649ed1071a9ec42223d474e67b19a
Arg [7] : 00000000000000000000000022602469d704bffb0936c7a7cfcd18f7aa269375
Arg [8] : 7345544800000000000000000000000000000000000000000000000000000000
Arg [9] : 734554482047616d6d61205661756c7400000000000000000000000000000000


Library Used

BlackScholesLib : 0x0052a341bea99c4b452816235fc2216143c5f21c

Deployed ByteCode Sourcemap

76377:35759:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94240:82;;;:::i;:::-;;78011:29;;;;;;;;160:25:1;;;148:2;133:18;78011:29:0;;;;;;;;80436:41;;;;;;95104:470;;;;;;:::i;:::-;;:::i;2109:151::-;;;;;;:::i;:::-;;:::i;80577:24::-;;;;;;78186:27;;;;;;;;-1:-1:-1;;;;;1358:55:1;;;1340:74;;1328:2;1313:18;78186:27:0;1181:239:1;80090:36:0;;;;;;95969:172;;;;;;:::i;:::-;;:::i;96929:151::-;;;;;;:::i;:::-;;:::i;79524:23::-;;;;;;93745:161;;;;;;:::i;:::-;;:::i;86272:2468::-;;;;;;:::i;:::-;;:::i;79287:30::-;;;;;;79588:28;;;;;-1:-1:-1;;;;;79588:28:0;;;94365:70;;;:::i;78265:50::-;;;;;79976:37;;;;;;80766:32;;;;;;;;;;;;;;;;;;;;;;;;;;2388:25:1;;;2444:2;2429:18;;2422:34;;;;2472:18;;;2465:34;;;;2530:2;2515:18;;2508:34;2573:3;2558:19;;2551:35;2617:3;2602:19;;2595:35;2375:3;2360:19;80766:32:0;2101:535:1;94680:288:0;;;;;;:::i;:::-;;:::i;89063:634::-;;;:::i;85219:925::-;;;;;;:::i;:::-;;:::i;79891:34::-;;;;;;24846:86;24917:7;;;;24846:86;;;2806:14:1;;2799:22;2781:41;;2769:2;2754:18;24846:86:0;2641:187:1;93307:199:0;;;;;;:::i;:::-;;:::i;24940:102::-;25019:15;;;;;;;24940:102;;94477:86;;;:::i;79128:31::-;;;;;;78554:68;;;;;96571:276;;;;;;:::i;:::-;;:::i;97190:244::-;;;;;;:::i;:::-;;:::i;78851:37::-;;;;;1659:442;;;;;;:::i;:::-;;:::i;80902:54::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;80902:54:0;;;;;;;;;;;;;4205:25:1;;;-1:-1:-1;;;;;4266:55:1;;;4261:2;4246:18;;4239:83;4338:18;;;4331:34;;;;4396:2;4381:18;;4374:34;4439:3;4424:19;;4417:35;4192:3;4177:19;80902:54:0;3946:512:1;94134:66:0;;;:::i;79659:29::-;;;;;;80835:27;;;;;-1:-1:-1;;;;;80835:27:0;;;80319:39;;;;;;79729:28;;;;;;78110:45;;;;;680:20;;;;;-1:-1:-1;;;;;680:20:0;;;79208:31;;;;;;80515:25;;;;;;97816:184;;;;;;:::i;:::-;;:::i;78360:44::-;;;;;709:26;;;;;-1:-1:-1;;;;;709:26:0;;;96240:172;;;;;;:::i;:::-;;:::i;89766:132::-;;;:::i;80999:58::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;80999:58:0;;;;;;;;;83995:1102;;;;;;:::i;:::-;;:::i;95682:188::-;;;;;;:::i;:::-;;:::i;78455:46::-;;;;;79437:25;;;;;;78666:42;;;;;78759:41;;;;;80697:29;;;;;;;;;82385:1232;;;;;;:::i;:::-;;:::i;97442:165::-;;;;;;:::i;:::-;;:::i;79807:36::-;;;;;;80201:38;;;;;;79368:31;;;;;;94240:82;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;;;;;;;;;94298:16:::1;:14;:16::i;:::-;94240:82::o:0;95104:470::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;95225:4:::1;95207:15;:22;:47;;;;95250:4;95233:14;:21;95207:47;95203:162;;;95290:14;::::0;95306:13:::1;::::0;95278:75:::1;::::0;::::1;::::0;;::::1;::::0;::::1;7784:25:1::0;;;;7825:18;;;7818:34;7868:18;;;7861:34;;;7911:18;;;7904:34;;;7756:19;;95278:75:0::1;7553:391:1::0;95203:162:0::1;95407:14;::::0;95423:13:::1;::::0;95382:98:::1;::::0;;7784:25:1;;;7840:2;7825:18;;7818:34;;;;7868:18;;7861:34;;;7926:2;7911:18;;7904:34;;;95382:98:0::1;::::0;7771:3:1;7756:19;95382:98:0::1;;;;;;;95493:14;:32:::0;;;;95536:13:::1;:30:::0;95104:470::o;2109:151::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212: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;95969:172::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;96070:16:::1;::::0;96053:43:::1;::::0;;8123:25:1;;;8179:2;8164:18;;8157:34;;;96053:43:0::1;::::0;8096:18:1;96053:43:0::1;;;;;;;96107:16;:26:::0;95969:172::o;96929:151::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;97023:10:::1;::::0;97006:36:::1;::::0;;8123:25:1;;;8179:2;8164:18;;8157:34;;;97006:36:0::1;::::0;8096:18:1;97006:36:0::1;;;;;;;97053:10;:19:::0;96929:151::o;93745:161::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;8404:2:1;18522:34:0::1;::::0;::::1;8386:21:1::0;8443:2;8423:18;;;8416:30;8482:12;8462:18;;;8455:40;8512:18;;18522:34:0::1;8202:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;93864:34:::3;93879:6;93887:10;93864:14;:34::i;:::-;-1:-1:-1::0;;18615:1:0::1;18606:6;:10:::0;93745:161::o;86272:2468::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;8404:2:1;18522:34:0;;;8386:21:1;8443:2;8423:18;;;8416:30;8482:12;8462:18;;;8455:40;8512:18;;18522:34:0;8202:334:1;18522:34:0;18578:1;18569:10;;86359:9:::1;86354:2379;86378:7;86374:1;:11;86354:2379;;;86407:18;86428:15;:13;:15::i;:::-;86509:20;::::0;86460:30:::1;86493:37:::0;;;:15:::1;:37;::::0;;;;86551:21:::1;::::0;::::1;::::0;86407:36;;-1:-1:-1;86493:37:0;86551:26;;:88:::1;;;86623:16;;86599:7;:21;;;:40;;;;:::i;:::-;86581:15;:58;86551:88;86547:135;;;86660:7;;;;;86547:135;86698:22;86736:9;;86723:10;;:22;;;;:::i;:::-;86698:47:::0;-1:-1:-1;86766:19:0;86762:66:::1;;86806:7;;;;;;86762:66;86867:23;::::0;::::1;::::0;86844:20:::1;::::0;86867:46:::1;::::0;86902:10;86867:34:::1;:46::i;:::-;86844:69;;87072:14;87057:12;:29;87053:1630;;;87107:22;::::0;::::1;:39:::0;;;87165:20:::1;87188:35;87132:14:::0;87212:10;87188:23:::1;:35::i;:::-;87165:58;;87270:12;87244:22;;:38;;;;;;;:::i;:::-;;;;;;;;87328:12;87301:7;:23;;;:39;;;;;;;:::i;:::-;;;;;;;;87375:14;87361:10;;:28;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;87414:13:0::1;::::0;:17;87410:251:::1;;87456:20;87479:40;87505:13;;87479:14;:25;;:40;;;;:::i;:::-;87560:13;::::0;87456:63;;-1:-1:-1;87542:46:0::1;::::0;-1:-1:-1;;;;;87542:4:0::1;:17:::0;::::1;::::0;87560:13:::1;87456:63:::0;87542:17:::1;:46::i;:::-;87611:30;87629:12:::0;87611:30;::::1;:::i;:::-;;;87433:228;87410:251;87699:12;::::0;::::1;::::0;87681:47:::1;::::0;-1:-1:-1;;;;;87681:4:0::1;:17:::0;::::1;::::0;87699:12:::1;87713:14:::0;87681:17:::1;:47::i;:::-;87803:10:::0;;87815:12:::1;::::0;::::1;::::0;87859:21:::1;::::0;::::1;::::0;87754:145:::1;::::0;;4205:25:1;;;-1:-1:-1;;;;;87815:12:0;;::::1;4261:2:1::0;4246:18;;4239:83;4338:18;;;4331:34;;;4396:2;4381:18;;4374:34;;;4439:3;4424:19;;4417:35;87754:145:0;::::1;::::0;;;;4192:3:1;87754:145:0;;::::1;87918:7;;;;;;;;87053:1630;87965:22;::::0;::::1;:37:::0;;;88047:23:::1;::::0;::::1;::::0;88021:22:::1;:49:::0;;:22:::1;::::0;:49:::1;::::0;88047:23;;88021:49:::1;:::i;:::-;::::0;;;-1:-1:-1;;88115:1:0::1;88089:23;::::0;::::1;:27:::0;;;88137:10:::1;:26:::0;;88151:12;;88115:1;88137:26:::1;::::0;88151:12;;88137:26:::1;:::i;:::-;::::0;;;-1:-1:-1;;88188:13:0::1;::::0;:17;88184:247:::1;;88230:20;88253:38;88277:13;;88253:12;:23;;:38;;;;:::i;:::-;88332:13;::::0;88230:61;;-1:-1:-1;88314:46:0::1;::::0;-1:-1:-1;;;;;88314:4:0::1;:17:::0;::::1;::::0;88332:13:::1;88230:61:::0;88314:17:::1;:46::i;:::-;88383:28;88399:12:::0;88383:28;::::1;:::i;:::-;;;88207:224;88184:247;88469:12;::::0;::::1;::::0;88451:45:::1;::::0;-1:-1:-1;;;;;88451:4:0::1;:17:::0;::::1;::::0;88469:12:::1;88483::::0;88451:17:::1;:45::i;:::-;88562:10:::0;;88574:12:::1;::::0;::::1;::::0;88588:23:::1;::::0;::::1;::::0;88627:21:::1;::::0;::::1;::::0;88522:145:::1;::::0;;4205:25:1;;;-1:-1:-1;;;;;88574:12:0;;::::1;4261:2:1::0;4246:18;;4239:83;4338:18;;;4331:34;4396:2;4381:18;;4374:34;;;4439:3;4424:19;;4417:35;88522:145:0::1;::::0;4192:3:1;4177:19;88522:145:0::1;;;;;;;88699:20;:22:::0;;;:20:::1;:22;::::0;::::1;:::i;:::-;;;;;;86392:2341;;;;86387:3;;;;;:::i;:::-;;;;86354:2379;;18592:1;-1:-1:-1::0;18615:1:0;18606:6;:10;86272:2468::o;94365:70::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;94417:10:::1;:8;:10::i;94680:288::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;-1:-1:-1;;;;;94767:30:0;::::1;94763:87;;94821:17;;;;;;;;;;;;;;94763:87;94887:13;::::0;94867:50:::1;::::0;;-1:-1:-1;;;;;94887:13:0;;::::1;9428:34:1::0;;9498:15;;;9493:2;9478:18;;9471:43;94867:50:0::1;::::0;9340:18:1;94867:50:0::1;;;;;;;94930:13;:30:::0;;;::::1;-1:-1:-1::0;;;;;94930:30:0;;;::::1;::::0;;;::::1;::::0;;94680:288::o;89063:634::-;89109:7;89133:10;;89147:1;89133:15;89129:59;;;-1:-1:-1;89172:4:0;;89063:634::o;89129:59::-;89200:19;89222:16;:14;:16::i;:::-;89253:25;;89200:38;;-1:-1:-1;89249:104:0;;89307:10;;:34;;89329:11;89307:21;:34::i;:::-;89300:41;;;89063:634;:::o;89249:104::-;89366:19;89391:42;89411:12;:21;;;89391:19;:42::i;:::-;-1:-1:-1;89470:45:0;;;;;89509:4;89470:45;;;1340:74:1;89365:68:0;;-1:-1:-1;89445:19:0;;-1:-1:-1;;;;;89470:14:0;:30;;;;1313:18:1;;89470:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89444:71;;;89526:17;89598:11;89546:49;89569:12;:25;;;89546:11;:22;;:49;;;;:::i;:::-;:63;;;;:::i;:::-;89526:83;;89629:60;89677:11;89655:9;;89643;89630:10;;:22;;;;:::i;:::-;:34;;;;:::i;:::-;89629:47;;:60::i;:::-;89622:67;;;;;;89063:634;:::o;85219:925::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;8404:2:1;18522:34:0;;;8386:21:1;8443:2;8423:18;;;8416:30;8482:12;8462:18;;;8455:40;8512:18;;18522:34:0;8202:334:1;18522:34:0;18578:1;18569:10;;85298:18:::1;85319:15;:13;:15::i;:::-;85298:36;;85352:9;85347:790;85371:7;85367:1;:11;85347:790;;;85445:17;::::0;85400:29:::1;85432:31:::0;;;:12:::1;:31;::::0;;;;85484:21:::1;::::0;::::1;::::0;:26;;:87:::1;;;85556:15;;85532:7;:21;;;:39;;;;:::i;:::-;85514:15;:57;85484:87;85480:134;;;85592:7;;;;;85480:134;85653:23;::::0;::::1;::::0;85630:20:::1;::::0;85653:46:::1;::::0;85688:10;85653:34:::1;:46::i;:::-;85630:69;;85739:12;85716:7;:20;;:35;;;;85789:7;:23;;;85766:19;;:46;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;85841:23:0::1;::::0;::::1;::::0;85827:10:::1;:37:::0;;:10:::1;::::0;:37:::1;::::0;85841:23;;85827:37:::1;:::i;:::-;::::0;;;-1:-1:-1;;85896:12:0::1;::::0;::::1;::::0;85879:44:::1;::::0;;;;-1:-1:-1;;;;;85896:12:0;;::::1;85879:44;::::0;::::1;10136:74:1::0;10226:18;;;10219:34;;;85879:11:0::1;:16:::0;;::::1;::::0;::::1;::::0;10109:18:1;;85879:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;85960:10:0;;85972:12:::1;::::0;::::1;::::0;85986:23:::1;::::0;::::1;::::0;86025:21:::1;::::0;::::1;::::0;85945:102:::1;::::0;;4205:25:1;;;-1:-1:-1;;;;;85972:12:0;;::::1;4261:2:1::0;4246:18;;4239:83;4338:18;;;4331:34;4396:2;4381:18;;4374:34;;;4439:3;4424:19;;4417:35;85945:102:0::1;::::0;-1:-1:-1;4192:3:1;4177:19;;-1:-1:-1;85945:102:0::1;;;;;;;86090:1;86064:23;::::0;::::1;:27:::0;;;86106:17:::1;:19:::0;;;::::1;::::0;::::1;:::i;:::-;;;;;;85385:752;;85380:3;;;;;:::i;:::-;;;;85347:790;;;;85287:857;-1:-1:-1::0;18615:1:0;18606:6;:10;85219:925::o;93307:199::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;8404:2:1;18522:34:0::1;::::0;::::1;8386:21:1::0;8443:2;8423:18;;;8416:30;8482:12;8462:18;;;8455:40;8512:18;;18522:34:0::1;8202:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;93449:49:::3;93463:8;93473:6;93481:16;93449:13;:49::i;:::-;-1:-1:-1::0;;18615:1:0::1;18606:6;:10:::0;-1:-1:-1;93307:199:0:o;94477:86::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;94537:18:::1;:16;:18::i;96571:276::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;96688:15:::1;::::0;96720:16:::1;::::0;96675:78:::1;::::0;;7784:25:1;;;7840:2;7825:18;;7818:34;;;7868:18;;7861:34;7926:2;7911:18;;7904:34;;;96675:78:0::1;::::0;7771:3:1;7756:19;96675:78:0::1;;;;;;;96764:15;:31:::0;;;;96806:16:::1;:33:::0;96571:276::o;97190:244::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;97269:4:::1;97262;:11;:26;;;;97284:4;97277;:11;97262:26;97258:97;;;97328:8;::::0;97312:31:::1;::::0;::::1;::::0;;::::1;::::0;::::1;8123:25:1::0;;;;8164:18;;;8157:34;;;8096:18;;97312:31:0::1;7949:248:1::0;97258:97:0::1;97385:8;::::0;97370:30:::1;::::0;;8123:25:1;;;8179:2;8164:18;;8157:34;;;97370:30:0::1;::::0;8096:18:1;97370:30:0::1;;;;;;;97411:8;:15:::0;97190:244::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;;;10525:34:1;1980:4:0;10575:18:1;;;10568:43;1942:9:0;1987:7;;;10627:18:1;;;10620:107;-1:-1:-1;;;;;1942:9:0;;;;:17;;10437: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;94134:66::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;94184:8:::1;:6;:8::i;97816:184::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;97939:4:::1;-1:-1:-1::0;;;;;97922:22:0::1;:5;-1:-1:-1::0;;;;;97922:22:0::1;;;97914:31;;;::::0;::::1;;97956:36;::::0;;;;-1:-1:-1;;;;;10154:55:1;;;97956:36:0::1;::::0;::::1;10136:74:1::0;10226:18;;;10219:34;;;97956:21:0;::::1;::::0;::::1;::::0;10109:18:1;;97956:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;97816:184:::0;;;:::o;96240:172::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;96341:16:::1;::::0;96324:43:::1;::::0;;8123:25:1;;;8179:2;8164:18;;8157:34;;;96324:43:0::1;::::0;8096:18:1;96324:43:0::1;;;;;;;96378:16;:26:::0;96240:172::o;89766:132::-;89813:7;89868:22;;89840:11;-1:-1:-1;;;;;89840:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;;;;:::i;:::-;89833:57;;89766:132;:::o;83995:1102::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;8404:2:1;18522:34:0;;;8386:21:1;8443:2;8423:18;;;8416:30;8482:12;8462:18;;;8455:40;8512:18;;18522:34:0;8202:334:1;18522:34:0;18578:1;18569:10;;-1:-1:-1;;;;;84090:20:0;::::1;84086:77;;84134:17;;;;;;;;;;;;;;84086:77;84210:25:::0;;84206:835:::1;;84257:18;84278:15;:13;:15::i;:::-;84257:36:::0;-1:-1:-1;84308:20:0::1;84331:29;:6:::0;84257:36;84331:17:::1;:29::i;:::-;84308:52:::0;-1:-1:-1;84375:37:0::1;-1:-1:-1::0;;;;;84375:4:0::1;:17;84393:4:::0;84308:52;84375:17:::1;:37::i;:::-;84441:12;84427:10;;:26;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;84473:65:0::1;::::0;;84491:1:::1;4205:25:1::0;;-1:-1:-1;;;;;4266:55:1;;4261:2;4246:18;;4239:83;4338:18;;;4331:34;;;4396:2;4381:18;;4374:34;;;84522:15:0::1;4439:3:1::0;4424:19;;4417:35;84473:65:0::1;::::0;4192:3:1;4177:19;84473:65:0::1;;;;;;;84242:308;;84206:835;;;84672:22;::::0;;84619:34:::1;84656:39:::0;;;:15:::1;:39;::::0;;;;;84672:22;84729:24:::1;84672:22:::0;84729:24:::1;:::i;:::-;::::0;;;-1:-1:-1;84712:41:0;;84768:16:::1;::::0;::::1;:23:::0;;;::::1;-1:-1:-1::0;;;;;84768:23:0;::::1;;::::0;;84806:27:::1;::::0;::::1;:36:::0;;;84885:15:::1;84857:25;::::0;::::1;:43:::0;84917:22:::1;:32:::0;;84806:36;;84917:22;-1:-1:-1;;84917:32:0::1;::::0;84806:36;;84917:32:::1;:::i;:::-;::::0;;;-1:-1:-1;;84988:14:0;;84969:60:::1;::::0;;11890:25:1;;;85004:10:0::1;12007:2:1::0;11992:18;;11985:43;-1:-1:-1;;;;;12064:15:1;;12044:18;;;12037:43;12111:2;12096:18;;12089:34;;;84969:60:0;::::1;::::0;;;;11877:3:1;84969:60:0;;::::1;84556:485;84206:835;85053:36;::::0;;;;85070:10:::1;85053:36;::::0;::::1;10136:74:1::0;10226:18;;;10219:34;;;85053:11:0::1;-1:-1:-1::0;;;;;85053:16:0::1;::::0;::::1;::::0;10109:18:1;;85053:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;18615:1:0;18606:6;:10;-1:-1:-1;;;;83995:1102:0:o;95682:188::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;95793:21:::1;::::0;95765:57:::1;::::0;;8123:25:1;;;8179:2;8164:18;;8157:34;;;95765:57:0::1;::::0;8096:18:1;95765:57:0::1;;;;;;;95833:21;:29:::0;95682:188::o;82385:1232::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;8404:2:1;18522:34:0;;;8386:21:1;8443:2;8423:18;;;8416:30;8482:12;8462:18;;;8455:40;8512:18;;18522:34:0;8202:334:1;18522:34:0;18578:1;18569:10;;25019:15;;;;;;;25333:71:::1;;;25376:16;;;;;;;;;;;;;;25333:71;-1:-1:-1::0;;;;;82499:20:0;::::2;82495:77;;82543:17;;;;;;;;;;;;;;82495:77;82597:16;;82588:6;:25;82584:113;;;82660:16;::::0;;82637:48:::2;::::0;::::2;::::0;;;;::::2;8123:25:1::0;8164:18;;;8157:34;;;8096:18;;82637:48:0::2;7949:248:1::0;82584:113:0::2;82744:25:::0;;82740:801:::2;;82791:18;82812:15;:13;:15::i;:::-;82791:36:::0;-1:-1:-1;82842:20:0::2;82865:29;:6:::0;82791:36;82865:17:::2;:29::i;:::-;82909:36;::::0;;;;-1:-1:-1;;;;;10154:55:1;;;82909:36:0::2;::::0;::::2;10136:74:1::0;10226:18;;;10219:34;;;82842:52:0;;-1:-1:-1;82909:11:0::2;:16:::0;;::::2;::::0;::::2;::::0;10109:18:1;;82909:36:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;82974:6;82960:10;;:20;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;83000:62:0::2;::::0;;83015:1:::2;4205:25:1::0;;-1:-1:-1;;;;;4266:55:1;;4261:2;4246:18;;4239:83;4338:18;;;4331:34;;;4396:2;4381:18;;4374:34;;;83046:15:0::2;4439:3:1::0;4424:19;;4417:35;83000:62:0::2;::::0;4192:3:1;4177:19;83000:62:0::2;;;;;;;82776:298;;82740:801;;;83189:19;::::0;;83141:32:::2;83176:33:::0;;;:12:::2;:33;::::0;;;;;83189:19;83242:21:::2;83189:19:::0;83242:21:::2;:::i;:::-;::::0;;;-1:-1:-1;83226:37:0;;83278:15:::2;::::0;::::2;:22:::0;;;::::2;-1:-1:-1::0;;;;;83278:22:0;::::2;;::::0;;83315:26:::2;::::0;::::2;:35:::0;;;83392:15:::2;83365:24;::::0;::::2;:42:::0;83424:19:::2;:29:::0;;83315:35;;83424:19;-1:-1:-1;;83424:29:0::2;::::0;83315:35;;83424:29:::2;:::i;:::-;::::0;;;-1:-1:-1;;83489:13:0;;83473:56:::2;::::0;;11890:25:1;;;83504:10:0::2;12007:2:1::0;11992:18;;11985:43;-1:-1:-1;;;;;12064:15:1;;12044:18;;;12037:43;12111:2;12096:18;;12089:34;;;83473:56:0;::::2;::::0;;;;11877:3:1;83473:56:0;;::::2;83080:461;82740:801;83553:56;-1:-1:-1::0;;;;;83553:4:0::2;:21;83575:10;83595:4;83602:6:::0;83553:21:::2;:56::i;97442:165::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;7414:2:1;1017:58:0;;;7396:21:1;7453:2;7433:18;;;7426:30;7492:14;7472:18;;;7465:42;7524:18;;1017:58:0;7212:336:1;1017:58:0;97544:9:::1;::::0;97520:51:::1;::::0;;-1:-1:-1;;;;;97544:9:0;;::::1;9428:34:1::0;;9498:15;;;9493:2;9478:18;;9471:43;97520:51:0::1;::::0;9340:18:1;97520:51:0::1;;;;;;;97582:9;:17:::0;;;::::1;-1:-1:-1::0;;;;;97582:17:0;;;::::1;::::0;;;::::1;::::0;;97442:165::o;1105:546::-;1226:9;;1192:4;;-1:-1:-1;;;;;1226:9:0;1548:27;;;;;:77;;-1:-1:-1;1579:46:0;;;;;-1:-1:-1;;;;;10543:15:1;;;1579:46:0;;;10525:34:1;1606:4:0;10575:18:1;;;10568:43;10659:66;10647:79;;10627:18;;;10620:107;1579:12:0;;;;;10437: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;-1:-1:-1;;;;1105:546:0: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;100834:4361::-;100917:23;;100913:85;;100969:17;;;;;;;;;;;;;;100913:85;101011:17;101030:14;101048;-1:-1:-1;;;;;101048:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101010:65;;;;101092:9;101105:1;101092:14;:27;;;;101110:9;101092:27;101088:101;;;101143:34;;;;;;;;12555:25:1;;;12623:14;;12616:22;12596:18;;;12589:50;12528:18;;101143:34:0;12387:258:1;101088:101:0;101206:17;;;;101201:75;;101240:17;:24;;;;101260:4;101240:24;;;101201:75;101317:23;;101292:49;;;;;-1:-1:-1;;;;;101353:21:0;101292:83;;;:12;:24;;;;;;:49;;;;160:25:1;;;148:2;133:18;;14:177;101292:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;101292:83:0;;101288:193;;101445:23;;101392:77;;;;;-1:-1:-1;;;;;101392:12:0;:20;;;;:77;;101421:21;;101392:77;;-1:-1:-1;;;;;10154:55:1;;;;10136:74;;10241:2;10226:18;;10219:34;10124:2;10109:18;;9962:297;101392:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101288:193;101505:25;;101497:33;;101493:3695;;101547:17;:25;;;;;;101589:64;;:::i;:::-;-1:-1:-1;;;;;101692:13:0;101670:35;;;101738:12;:21;101720:15;;;:39;101794:23;;101774:17;;;:43;101852:1;101832:17;;;:21;-1:-1:-1;101958:17:0;;;:31;102020:25;;102004:13;;;:41;;;102077:37;;:11;;:22;:37::i;:::-;102060:14;;;:54;102146:17;102129:14;;;:34;-1:-1:-1;;;;;102238:4:0;102218:24;;:17;;;:24;102326:43;;;;;-1:-1:-1;;102326:21:0;:35;;;;:43;;102060:6;;102326:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102435:24;;102462:21;;102386:98;;;;;102435:24;102386:98;;8123:25:1;;;;8164:18;;;8157:34;102259:110:0;;-1:-1:-1;102386:14:0;-1:-1:-1;;;;;102386:41:0;;;;8096:18:1;;102386:98:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;102597:45:0;;;;;102636:4;102597:45;;;1340:74:1;102572:19:0;;-1:-1:-1;102597:14:0;-1:-1:-1;;;;;102597:30:0;;-1:-1:-1;102597:30:0;;1313:18:1;;102597:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102571:71;;;102659:14;-1:-1:-1;;;;;102659:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102710:21;102748:13;:23;;;102734:11;:37;;;;:::i;:::-;102710:61;;102808:9;;102792:13;:25;102788:381;;;102838:14;102871:9;;102855:13;:25;;;;:::i;:::-;102838:42;;102899:16;102918:33;102936:14;;102918:6;:17;;:33;;;;:::i;:::-;102995:13;;102899:52;;-1:-1:-1;102970:49:0;;-1:-1:-1;;;;;102976:4:0;102970:24;;;102995:13;102899:52;102970:24;:49::i;:::-;103053:17;103062:8;103053:6;:17;:::i;:::-;103038:10;;:33;;;;;;;:::i;:::-;;;;-1:-1:-1;102788:381:0;;-1:-1:-1;;;102788:381:0;;103139:13;103127:9;;:25;;;;:::i;:::-;103112:10;;:41;;;;;;;:::i;:::-;;;;-1:-1:-1;;102788:381:0;103222:12;:21;103262:23;;103304:25;;103348:23;;;;;103390:24;;103190:269;;;2388:25:1;;;2444:2;2429:18;;2422:34;;;;2472:18;;;2465:34;;;;2530:2;2515:18;;2508:34;2558:19;;2551:35;2617:3;2602:19;;2595:35;;;103190:269:0;;;;;;2375:3:1;103190:269:0;;;-1:-1:-1;;103488:1:0;103476:9;:13;;;103504:25;:29;;;103548:23;:27;;;103504:12;103590:25;;;103630:24;:28;;;103673:24;:28;;;103716:24;:28;-1:-1:-1;101493:3695:0;;-1:-1:-1;101493:3695:0;;103777:64;;:::i;:::-;-1:-1:-1;;;;;103880:13:0;103858:35;;;103926:12;:21;103908:15;;;:39;103982:23;;103962:17;;;:43;104040:1;104020:17;;;:21;-1:-1:-1;104146:17:0;;;:31;104192:13;;;:20;;;104244:28;:11;104192:20;104244:22;:28::i;:::-;104227:14;;;:45;104304:17;104287:14;;;:34;-1:-1:-1;;;;;104396:4:0;104376:24;;:17;;;:24;104484:43;;;;;-1:-1:-1;;104484:21:0;:35;;;;:43;;104227:6;;104484:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104591:24;;104617:25;;104417:110;;-1:-1:-1;104544:28:0;;104575:68;;:4;;:15;:68::i;:::-;104732:21;;104660:94;;;;;;;;8123:25:1;;;8164:18;;;8157:34;;;;104544:99:0;;-1:-1:-1;104660:14:0;-1:-1:-1;;;;;104660:41:0;;;;8096:18:1;;104660:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;104808:12:0;:21;104848:23;;104913;;;;;104776:234;;;2388:25:1;;;2444:2;2429:18;;2422:34;;;;2472:18;;;2465:34;;;2530:2;2515:18;;2508:34;2558:19;;2551:35;;;-1:-1:-1;2617:3:1;2602:19;;2595:35;104776:234:0;;;-1:-1:-1;104776:234:0;;;;2375:3:1;104776:234:0;;-1:-1:-1;104776:234:0;105040:13;:23;;;105027:9;;:36;;;;;;;:::i;:::-;;;;-1:-1:-1;;105080:25:0;:33;;105109:4;;105080:25;;;:33;;105109:4;;105080:33;:::i;:::-;;;;-1:-1:-1;;105128:24:0;:48;;105156:20;;105128:24;;;:48;;105156:20;;105128:48;:::i;:::-;;;;-1:-1:-1;;;;;100902:4293:0;;100834:4361;;:::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;;18040:2:1;23018:35:0;;;18022:21:1;18079:2;18059:18;;;18052:30;18118:17;18098:18;;;18091:45;18153:18;;23018:35:0;17838: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;90221:1556::-;90292:19;90313:18;90359:34;90408:38;90460:13;-1:-1:-1;;;;;90460:31:0;;90492:9;90460:42;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;90460:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90561;;;;;90582:20;90561:42;;;160:25:1;90344:158:0;;-1:-1:-1;90344:158:0;-1:-1:-1;90524:17:0;;;;-1:-1:-1;;;;;90561:5:0;:20;;;;133:18:1;;90561:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90523:80;;;;90620:9;90633:1;90620:14;:27;;;;90638:9;90620:27;90616:68;;;90664:8;;;90616:68;90718:5;:12;;;90700:15;:30;90696:1074;;;90844:48;;;;;;;;160:25:1;;;90766:19:0;;;;-1:-1:-1;;;;;90844:13:0;:37;;;;133:18:1;;90844:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90747:145;;;;;90913:13;90930:1;90913:18;90909:83;;;90959:17;;;;;;;;;;;;;;90909:83;91038:11;91022:13;:27;:61;;91082:1;91022:61;;;91052:27;91068:11;91052:13;:27;:::i;:::-;91008:75;;90732:363;;90696:1074;;;91151:8;;91161:10;;91134:38;;;;;;;;8123:25:1;;;;8164:18;;;8157:34;91116:15:0;;91134:6;-1:-1:-1;;;;;91134:16:0;;;;8096:18:1;;91134:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91238:10;;91208:41;;;;;91116:56;;-1:-1:-1;91187:18:0;;-1:-1:-1;;;;;91208:6:0;:18;;;;:41;;91227:9;;91208:41;;8123:25:1;;;8179:2;8164:18;;8157:34;8111:2;8096:18;;7949:248;91208:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91187:62;;91264:49;91316:356;;;;;;;;91402:15;91387:5;:12;;;:30;;;;:::i;:::-;91316:356;;;;91455:30;:7;91474:10;91455:18;:30::i;:::-;91316:356;;;;91517:9;91316:356;;;;91565:6;:18;;;91316:356;;;;91615:6;-1:-1:-1;;;;;91615:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;91316:356;;91721:37;;;;;;21929:13:1;;91721:37:0;;;21911:32:1;21999:4;21987:17;;21981:24;21959:20;;;21952:54;22050:17;;;22044:24;22022:20;;;22015:54;22125:4;22113:17;;22107:24;22085:20;;;22078:54;22188:4;22176:17;;22170:24;22148:20;;;22141:54;91264:408:0;;-1:-1:-1;91721:15:0;;:28;;21883:19:1;;91721:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91693:65;;-1:-1:-1;91693:65:0;-1:-1:-1;;;;90696:1074:0;90333:1444;;;;90221:1556;;;:::o;98198:2628::-;98300:23;;:28;;;;:66;;-1:-1:-1;98332:12:0;:21;:34;;;98300:66;98299:89;;;-1:-1:-1;98371:17:0;;;;98299:89;98295:145;;;98412:16;;;;;;;;;;;;;;98295:145;98452:16;98471:23;98484:9;98471:12;:23::i;:::-;98452:42;;98523:4;98511:9;:16;:36;;;;98543:4;98531:9;:16;98511:36;98507:120;;;98571:44;;;;;;;;8123:25:1;;;8164:18;;;8157:34;;;8096:18;;98571:44:0;7949:248:1;98507:120:0;98640:17;98659:14;98677;-1:-1:-1;;;;;98677:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98639:65;;;;98721:9;98734:1;98721:14;:27;;;;98739:9;98721:27;98717:101;;;98772:34;;;;;;;;12555:25:1;;;12623:14;;12616:22;12596:18;;;12589:50;12528:18;;98772:34:0;12387:258:1;98717:101:0;98830:22;98855:35;:4;98879:9;98855:15;:35::i;:::-;98830:60;;98901:22;98926:46;98952:9;98963:8;;98926:14;:25;;:46;;;;;:::i;:::-;98901:71;-1:-1:-1;98983:20:0;99006:23;99014:14;99006:23;:::i;:::-;98983:46;;99089:10;;99072:14;99058:11;99046:9;;:23;;;;:::i;:::-;:40;;;;:::i;:::-;:53;99042:163;;;99141:10;;99153:9;;99164:28;99178:14;99164:11;:28;:::i;:::-;99123:70;;;;;;;;22854:25:1;;;;22895:18;;;22888:34;;;;22938:18;;;22931:34;22827:18;;99123:70:0;22652:319:1;99042:163:0;99217:68;-1:-1:-1;;;;;99223:4:0;99217:23;99249:21;99273:11;99217:23;:68::i;:::-;99298:64;;:::i;:::-;99397:13;-1:-1:-1;;;;;99375:35:0;;;99421:15;;;:27;;;99479:23;;99459:17;;;:43;99533:1;99513:17;;;:21;-1:-1:-1;99627:17:0;;;-1:-1:-1;99627:31:0;;-1:-1:-1;99669:13:0;;;:20;;;99732:14;;;:28;;;99771:18;;;:32;;;-1:-1:-1;;;;;99834:4:0;99814:24;;:17;;;:24;99918:42;;;;;-1:-1:-1;;99918:21:0;:34;;;;:42;;99669:6;;99918:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99973:53;;;;;;;;160:25:1;;;99851:109:0;;-1:-1:-1;99973:14:0;-1:-1:-1;;;;;99973:29:0;;;;133:18:1;;99973:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;100094:21:0;;100037:79;;;;;-1:-1:-1;;;;;100037:14:0;:41;;-1:-1:-1;100037:41:0;;-1:-1:-1;100037:79:0;;100079:13;;100037:79;;8123:25:1;;;8179:2;8164:18;;8157:34;8111:2;8096:18;;7949:248;100037:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;100133:23:0;;:28;100129:159;;-1:-1:-1;100129:159:0;;-1:-1:-1;100129:159:0;100204:24;;;;100178:23;:50;:12;100243:33;;;100129:159;100329:4;100300:12;:25;;;:33;;;;;;;:::i;:::-;;;;-1:-1:-1;;100372:23:0;;;;100344:24;:51;;:24;;:51;;100372:23;;100344:51;:::i;:::-;;;;-1:-1:-1;;100406:24:0;:42;;100434:14;;100406:24;;;:42;;100434:14;;100406:42;:::i;:::-;;;;-1:-1:-1;;100459:24:0;:42;;100487:14;;100459:24;;;:42;;100487:14;;100459:42;:::i;:::-;;;;-1:-1:-1;;100544:23:0;;;;100527:40;;:14;:40;:::i;:::-;100514:9;;:53;;;;;;;:::i;:::-;;;;-1:-1:-1;;100636:23:0;;100693;;;;;100585:233;;;23471:25:1;;;23527:2;23512:18;;23505:34;;;;23555:18;;23548:34;;;23613:2;23598:18;;23591:34;23641:19;;23634:35;;;23700:3;23685:19;;23678:35;;;23744:3;23729:19;;23722:35;;;100585:233:0;;23458:3:1;23443:19;100585:233:0;;;;;;;98284:2542;;;;;;;;98198:2628;;;:::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;19964:1604:0;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;;23970:2:1;21520:40:0;;;23952:21:1;24009:2;23989:18;;;23982:30;24048:22;24028:18;;;24021:50;24088:18;;21520:40:0;23768:344:1;21520:40:0;20097:1471;19964:1604;;;;:::o;11405:552::-;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;91900:923::-;91964:16;92008:34;92057:38;92109:13;-1:-1:-1;;;;;92109:31:0;;92141:9;92109:42;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;92109:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92202;;;;;92223:20;92202:42;;;160:25:1;91993:158:0;;-1:-1:-1;91993:158:0;-1:-1:-1;92165:17:0;;;;-1:-1:-1;;;;;92202:5:0;:20;;;;133:18:1;;92202:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92164:80;;;;92261:9;92274:1;92261:14;:27;;;;92279:9;92261:27;92257:101;;;92312:34;;;;;;;;12555:25:1;;;12623:14;;12616:22;12596:18;;;12589:50;12528:18;;92312:34:0;12387:258:1;92257:101:0;92370:49;92422:334;;;;;;;;92504:15;92489:5;:12;;;:30;;;;:::i;:::-;92422:334;;;;92553:32;92573:6;:11;;;92553:5;:8;;;:19;;:32;;;;:::i;:::-;92422:334;;;;92613:9;92422:334;;;;92657:6;:18;;;92422:334;;;;92703:6;-1:-1:-1;;;;;92703:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;92422:334;;92785:30;;;;;;21929:13:1;;92785:30:0;;;21911:32:1;21999:4;21987:17;;21981:24;21959:20;;;21952:54;22050:17;;;22044:24;22022:20;;;22015:54;22125:4;22113:17;;22107:24;22085:20;;;22078:54;22188:4;22176:17;;22170:24;22148:20;;;22141:54;92370:386:0;;-1:-1:-1;92785:15:0;;:21;;21883:19:1;;92785:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;92769:46:0;91900:923;-1:-1:-1;;;;;;;91900:923: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;;24567:2:1;24510:34:0;;;24549:21:1;24606:2;24586:18;;;24579:30;24645:16;24625:18;;;24618:44;24679:18;;24510:34:0;24365:338:1;-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;686:93;631:154;:::o;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;2833:316::-;2910:6;2918;2926;2979:2;2967:9;2958:7;2954:23;2950:32;2947:52;;;2995:1;2992;2985:12;2947:52;-1:-1:-1;;3018:23:1;;;3088:2;3073:18;;3060:32;;-1:-1:-1;3139:2:1;3124:18;;;3111:32;;2833:316;-1:-1:-1;2833:316:1:o;4712:456::-;4789:6;4797;4805;4858:2;4846:9;4837:7;4833:23;4829:32;4826:52;;;4874:1;4871;4864:12;4826:52;4913:9;4900:23;4932:31;4957:5;4932:31;:::i;:::-;4982:5;-1:-1:-1;5039:2:1;5024:18;;5011:32;5052:33;5011:32;5052:33;:::i;:::-;4712:456;;5104:7;;-1:-1:-1;;;5158:2:1;5143:18;;;;5130:32;;4712:456::o;5674:315::-;5742:6;5750;5803:2;5791:9;5782:7;5778:23;5774:32;5771:52;;;5819:1;5816;5809:12;5771:52;5858:9;5845:23;5877:31;5902:5;5877:31;:::i;:::-;5927:5;5979:2;5964:18;;;;5951:32;;-1:-1:-1;;;5674:315:1:o;8541:184::-;8593:77;8590:1;8583:88;8690:4;8687:1;8680:15;8714:4;8711:1;8704:15;8730:128;8770:3;8801:1;8797:6;8794:1;8791:13;8788:39;;;8807:18;;:::i;:::-;-1:-1:-1;8843:9:1;;8730:128::o;8863:125::-;8903:4;8931:1;8928;8925:8;8922:34;;;8936:18;;:::i;:::-;-1:-1:-1;8973:9:1;;8863:125::o;8993:195::-;9032:3;9063:66;9056:5;9053:77;9050:103;;;9133:18;;:::i;:::-;-1:-1:-1;9180:1:1;9169:13;;8993:195::o;9525:164::-;9601:13;;9650;;9643:21;9633:32;;9623:60;;9679:1;9676;9669:12;9623:60;9525:164;;;:::o;9694:263::-;9770:6;9778;9831:2;9819:9;9810:7;9806:23;9802:32;9799:52;;;9847:1;9844;9837:12;9799:52;9876:9;9870:16;9860:26;;9905:46;9947:2;9936:9;9932:18;9905:46;:::i;:::-;9895:56;;9694:263;;;;;:::o;10738:202::-;10805:6;10858:2;10846:9;10837:7;10833:23;10829:32;10826:52;;;10874:1;10871;10864:12;10826:52;10897:37;10924:9;10897:37;:::i;10945:184::-;11015:6;11068:2;11056:9;11047:7;11043:23;11039:32;11036:52;;;11084:1;11081;11074:12;11036:52;-1:-1:-1;11107:16:1;;10945:184;-1:-1:-1;10945:184:1:o;12650:138::-;12729:13;;12751:31;12729:13;12751:31;:::i;12793:251::-;12863:6;12916:2;12904:9;12895:7;12891:23;12887:32;12884:52;;;12932:1;12929;12922:12;12884:52;12964:9;12958:16;12983:31;13008:5;12983:31;:::i;13049:184::-;13101:77;13098:1;13091:88;13198:4;13195:1;13188:15;13222:4;13219:1;13212:15;13238:295;13320:1;13313:5;13310:12;13300:200;;13356:77;13353:1;13346:88;13457:4;13454:1;13447:15;13485:4;13482:1;13475:15;13300:200;13509:18;;13238:295::o;13538:1182::-;13787:13;;-1:-1:-1;;;;;1115:54:1;1103:67;;13748:3;13733:19;;13868:4;13860:6;13856:17;13850:24;13843:4;13832:9;13828:20;13821:54;13931:4;13923:6;13919:17;13913:24;13906:4;13895:9;13891:20;13884:54;13994:4;13986:6;13982:17;13976:24;13969:4;13958:9;13954:20;13947:54;14057:4;14049:6;14045:17;14039:24;14032:4;14021:9;14017:20;14010:54;14120:4;14112:6;14108:17;14102:24;14095:4;14084:9;14080:20;14073:54;14174:4;14166:6;14162:17;14156:24;14189:62;14245:4;14234:9;14230:20;14216:12;14189:62;:::i;:::-;-1:-1:-1;14307:4:1;14295:17;;;14289:24;14267:20;;;14260:54;14333:6;14381:15;;;14375:22;14355:18;;;14348:50;14417:6;14465:15;;;14459:22;14439:18;;;14432:50;14501:6;14549:15;;;14543:22;14523:18;;;14516:50;14585:6;14628:15;;;14622:22;-1:-1:-1;;;;;1115:54:1;14695:18;;;;1103:67;;;;13538:1182;:::o;14725:184::-;14777:77;14774:1;14767:88;14874:4;14871:1;14864:15;14898:4;14895:1;14888:15;14914:253;14986:2;14980:9;15028:4;15016:17;;15063:18;15048:34;;15084:22;;;15045:62;15042:88;;;15110:18;;:::i;:::-;15146:2;15139:22;14914:253;:::o;15172:255::-;15244:2;15238:9;15286:6;15274:19;;15323:18;15308:34;;15344:22;;;15305:62;15302:88;;;15370:18;;:::i;15432:252::-;15504:2;15498:9;15546:3;15534:16;;15580:18;15565:34;;15601:22;;;15562:62;15559:88;;;15627:18;;:::i;15689:334::-;15760:2;15754:9;15816:2;15806:13;;15821:66;15802:86;15790:99;;15919:18;15904:34;;15940:22;;;15901:62;15898:88;;;15966:18;;:::i;:::-;16002:2;15995:22;15689:334;;-1:-1:-1;15689:334:1:o;16028:1006::-;16129:6;16160:3;16204:2;16192:9;16183:7;16179:23;16175:32;16172:52;;;16220:1;16217;16210:12;16172:52;16253:2;16247:9;16283:15;;;;16328:18;16313:34;;16349:22;;;16310:62;16307:88;;;16375:18;;:::i;:::-;16415:10;16411:2;16404:22;16454:9;16448:16;16435:29;;16473:31;16498:5;16473:31;:::i;:::-;16528:5;16520:6;16513:21;16588:2;16577:9;16573:18;16567:25;16562:2;16554:6;16550:15;16543:50;16626:49;16671:2;16660:9;16656:18;16626:49;:::i;:::-;16621:2;16613:6;16609:15;16602:74;16730:2;16719:9;16715:18;16709:25;16704:2;16696:6;16692:15;16685:50;16790:3;16779:9;16775:19;16769:26;16763:3;16755:6;16751:16;16744:52;16851:3;16840:9;16836:19;16830:26;16824:3;16816:6;16812:16;16805:52;16912:3;16901:9;16897:19;16891:26;16885:3;16877:6;16873:16;16866:52;16952:50;16997:3;16986:9;16982:19;16952:50;:::i;:::-;16946:3;16934:16;;16927:76;16938:6;16028:1006;-1:-1:-1;;;;16028:1006:1:o;18182:1199::-;18251:5;18299:4;18287:9;18282:3;18278:19;18274:30;18271:50;;;18317:1;18314;18307:12;18271:50;18339:22;;:::i;:::-;18330:31;;18390:9;18384:16;18377:5;18370:31;18420:2;18475;18464:9;18460:18;18454:25;18449:2;18442:5;18438:14;18431:49;18533:2;18522:9;18518:18;18512:25;18507:2;18500:5;18496:14;18489:49;18570:46;18612:2;18601:9;18597:18;18570:46;:::i;:::-;18565:2;18558:5;18554:14;18547:70;18661:3;18650:9;18646:19;18640:26;18685:18;18726:2;18718:6;18715:14;18712:34;;;18742:1;18739;18732:12;18712:34;18780:6;18769:9;18765:22;18755:32;;18825:3;18818:4;18814:2;18810:13;18806:23;18796:51;;18843:1;18840;18833:12;18796:51;18872:2;18866:9;18894:2;18890;18887:10;18884:36;;;18900:18;;:::i;:::-;18946:2;18943:1;18939:10;18929:20;;18969:28;18993:2;18989;18985:11;18969:28;:::i;:::-;19031:15;;;19101:11;;;19097:20;;;19062:12;;;;19129:15;;;19126:35;;;19157:1;19154;19147:12;19126:35;19181:11;;;;19201:135;19217:6;19212:3;19209:15;19201:135;;;19283:10;;19271:23;;19234:12;;;;19314;;;;19201:135;;;19363:3;19352:15;;19345:30;-1:-1:-1;19356:5:1;;18182:1199;-1:-1:-1;;;;;;18182:1199:1:o;19386:1107::-;19518:6;19526;19570:9;19561:7;19557:23;19600:3;19596:2;19592:12;19589:32;;;19617:1;19614;19607:12;19589:32;19640:6;19666:2;19662;19658:11;19655:31;;;19682:1;19679;19672:12;19655:31;19708:22;;:::i;:::-;19695:35;;19759:9;19753:16;19746:5;19739:31;19823:2;19812:9;19808:18;19802:25;19797:2;19790:5;19786:14;19779:49;19881:2;19870:9;19866:18;19860:25;19855:2;19848:5;19844:14;19837:49;19939:2;19928:9;19924:18;19918:25;19913:2;19906:5;19902:14;19895:49;19998:3;19987:9;19983:19;19977:26;19971:3;19964:5;19960:15;19953:51;20058:3;20047:9;20043:19;20037:26;20031:3;20024:5;20020:15;20013:51;20118:3;20107:9;20103:19;20097:26;20091:3;20084:5;20080:15;20073:51;20178:3;20167:9;20163:19;20157:26;20151:3;20144:5;20140:15;20133:51;20203:3;20259:2;20248:9;20244:18;20238:25;20233:2;20226:5;20222:14;20215:49;;20283:5;20273:15;;20332:2;20321:9;20317:18;20311:25;20297:39;;;20359:18;20351:6;20348:30;20345:50;;;20391:1;20388;20381:12;20345:50;20414:73;20479:7;20470:6;20459:9;20455:22;20414:73;:::i;:::-;20404:83;;;19386:1107;;;;;:::o;20498:306::-;20586:6;20594;20602;20655:2;20643:9;20634:7;20630:23;20626:32;20623:52;;;20671:1;20668;20661:12;20623:52;20700:9;20694:16;20684:26;;20750:2;20739:9;20735:18;20729:25;20719:35;;20794:2;20783:9;20779:18;20773:25;20763:35;;20498:306;;;;;:::o;20809:870::-;20917:6;20970:3;20958:9;20949:7;20945:23;20941:33;20938:53;;;20987:1;20984;20977:12;20938:53;21013:22;;:::i;:::-;21064:9;21058:16;21051:5;21044:31;21128:2;21117:9;21113:18;21107:25;21102:2;21095:5;21091:14;21084:49;21186:2;21175:9;21171:18;21165:25;21160:2;21153:5;21149:14;21142:49;21244:2;21233:9;21229:18;21223:25;21218:2;21211:5;21207:14;21200:49;21303:3;21292:9;21288:19;21282:26;21276:3;21269:5;21265:15;21258:51;21363:3;21352:9;21348:19;21342:26;21336:3;21329:5;21325:15;21318:51;21423:3;21412:9;21408:19;21402:26;21396:3;21389:5;21385:15;21378:51;21483:3;21472:9;21468:19;21462:26;21456:3;21449:5;21445:15;21438:51;21508:3;21564:2;21553:9;21549:18;21543:25;21538:2;21531:5;21527:14;21520:49;;21588:3;21644:2;21633:9;21629:18;21623:25;21618:2;21611:5;21607:14;21600:49;;21668:5;21658:15;;;20809:870;;;;:::o;22206:245::-;22285:6;22293;22346:2;22334:9;22325:7;22321:23;22317:32;22314:52;;;22362:1;22359;22352:12;22314:52;-1:-1:-1;;22385:16:1;;22441:2;22426:18;;;22420:25;22385:16;;22420:25;;-1:-1:-1;22206:245:1:o;22456:191::-;22491:3;22522:66;22515:5;22512:77;22509:103;;;22592:18;;:::i;:::-;-1:-1:-1;22632:1:1;22628:13;;22456:191::o

Swarm Source

ipfs://9d64b807adb35d317264c56167137a0c4c4c88d5a7bba2cbef2295c46501ced1
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.