Contract 0x965e460bF5cb38BadA79fB2293c6304C799D0b1c 1

 
Txn Hash Method
Index
From
To
Value
0x4fb13989c143ca75b1c1f9c734c9c117ca9e02401b598b30d2775c667f987618Initiate Withdra...260409222022-09-28 15:38:306 hrs 47 mins ago0x004b5427e5cda44eee0e4e94dfa97885c4799fad IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000747129680.00100155
0xf2693c347193cdca736cd0813477bb7a7a429222e72b8225eeaf2ba6ec6bf051Initiate Withdra...259287032022-09-28 7:31:5814 hrs 53 mins ago0x23146a7907987ab0bdcebb3a3824072be077ea48 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000556687280.00100155
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53fOpen Position256833312022-09-27 4:40:101 day 17 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000382419260.00100155
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14eClose Position256569402022-09-27 1:40:011 day 20 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000677619940.00100155
0xd5dd718f9889e9841036de17fef89a57739e59b8b6c21a8df4659aad88039e63Process Withdraw...254635892022-09-26 5:00:372 days 17 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000179804460.00100155
0x6c5fdeda95681af58d5af8e6f0d7cdf5db089637c06becc0ce4bde5db8b1ec14Initiate Withdra...251907422022-09-24 22:13:324 days 12 mins ago0xfcb5a922877683128cc8b52cd7883cab12d21229 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000155560890.00100155
0x9878863ed3efb38376e90ccc7a5133b3b4d65b3b8dc29b6b76a6b92b928213f5Initiate Withdra...250999802022-09-24 11:53:304 days 10 hrs ago0xfcb5a922877683128cc8b52cd7883cab12d21229 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000214804850.00100155
0xc412e9a008801f39e4675e1005c96abb42ef639dc6e485f3b94b6869ee911414Initiate Withdra...250780982022-09-24 9:37:564 days 12 hrs ago0xffa13daf5b32e44758a5c4882f4df2612c0311b2 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000228616180.00100155
0x5f9b7234a7644449483eaa5c912e42eb13958147bf4f60801d6699f1f12cffadInitiate Withdra...250568382022-09-24 7:45:414 days 14 hrs ago0x938a49e24fd7a26149dd537019078d8a8f919290 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000202956760.00100155
0xcad59335e16a08bdfeaf0fc4162ca2f782024d6868492893bb9716dea6b8bb0bOpen Position250022232022-09-24 1:39:564 days 20 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.00002531580.00100155
0x70caa2449a7468897cbe66c3263af41f2fed878e31925c962d8b431854cfa6ddClose Position249794532022-09-23 22:30:144 days 23 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.000027836190.00100155
0x08e58ca6bb10d09a07096327fbdd4c4b2c4c779e62f60fb729f733b162c05f4eInitiate Withdra...249259002022-09-23 17:29:585 days 4 hrs ago0x6f3a8f9fd0da6b3ea4860ad7df347a06f1c65bdb IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000365395220.00100155
0x86e5cd11e259799cfbfc90e4c3deff5c8b2ec0ce04ae790f1aae803e63c6d5a9Process Withdraw...244201752022-09-22 2:45:026 days 19 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000211142160.00100155
0x957ce5dfc0563a0d74f8008d8d8fb04671a7b5ffae18b920c7c406b7badeaac8Initiate Withdra...243268092022-09-21 18:53:247 days 3 hrs ago0x2ce1a66f22a2dc6e410d9021d57aeb8d13d6bfef IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0001063876860.00100155
0x7e8ead9bb87ae2114e2700df081f44393a38c6a9ee6c3f2e7b9276447de84004Initiate Withdra...241652122022-09-21 9:08:347 days 13 hrs ago0x2ce1a66f22a2dc6e410d9021d57aeb8d13d6bfef IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000119665680.001
0x57c23c3601aef5835dffc5b2b08af3ec93e392ef934f8d6dc9d071f67acfdef5Open Position240396622022-09-20 23:04:557 days 23 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000229201960.001
0x5a37e037fa09b826b02d25f20509b624f7875dd1c81a4773f6b809052556e242Close Position240095232022-09-20 20:00:058 days 2 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000274254520.001
0xe704aa87c186a15553d9afad89ef7510c625f6763e82f111a84afa10bf8758f0Initiate Withdra...239733472022-09-20 16:24:038 days 6 hrs ago0xd70a3883f0b851c90cf4662018006ce9aa50fba2 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.000051420350.001
0xf3d2d75ccdea3b6ecf3e26704c27188ae6298674b85af2b734834648df075d90Initiate Withdra...238866082022-09-20 8:26:538 days 13 hrs ago0x0e024cdba8377acf2d83e23090e27f5f8f490497 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000250278770.001
0x5aa9556da3606005f3c21279e3ff9fb4b7194491ec6f9541b48ff9594431c8f8Initiate Withdra...237635122022-09-19 14:24:289 days 8 hrs ago0x432fcd67815d5cc72808a7815a02373fdee7d740 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000619862490.00125
0x79b4e69e2cb0c0c2858cc76c3e61d8856e3cdb4556861dc33f55083dee97b591Initiate Withdra...237418082022-09-19 11:15:409 days 11 hrs ago0x2588253cc1daac3e7d823b9190ec87e75c67f2c4 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000136599010.001
0xfb6a24b47e9c54d32f36fad59bce8dd3ea4e3774f855e3d8f86f4f0f283003ffProcess Withdraw...237107832022-09-19 6:27:059 days 15 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.000016354820.001
0x2c529ee9b76bf83eb3f6178ca8d67698b218bed006ae08fdbbbc735117180485Open Position236462972022-09-18 20:44:5910 days 1 hr ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.000041218430.001
0x4c3c9e30e6eb5fefed396045fa44ea255c289eeaba89a4dfcbfeb1ed54349867Close Position236335972022-09-18 17:45:0010 days 4 hrs ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000489536680.001
0x93aef891a9ce9a76d1f3aaa83540746d0b4b014901e28bc2268e769ab3759331Initiate Withdra...234040482022-09-16 9:34:1412 days 12 hrs ago0x938a49e24fd7a26149dd537019078d8a8f919290 IN  0x965e460bf5cb38bada79fb2293c6304c799d0b1c0 Ether0.0000241976490.001
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xf2693c347193cdca736cd0813477bb7a7a429222e72b8225eeaf2ba6ec6bf051259287032022-09-28 7:31:5814 hrs 53 mins ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x4beffd38832b5f158d5a05d374ae971dd0e326f20 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c Synthetix: Futures Market ETH0 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c Synthetix: Futures Market ETH0 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0xcce7819d65f348c64b7beb205ba367b3fe33763b0 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1cSynthetix: sUSD Token0 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c Synthetix: Futures Market ETH0 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x0052a341bea99c4b452816235fc2216143c5f21c0 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0xbb3e8eac35e649ed1071a9ec42223d474e67b19a0 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x22602469d704bffb0936c7a7cfcd18f7aa2693750 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x1d42a98848e022908069c2c545ae44cc78509bc80 Ether
0x4f02351161afbdbc30b6c37e738cdc11757968cd9356b78c5bc9361d44f7e53f256833312022-09-27 4:40:101 day 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x19828283852a852f8cfff4696038bc19e5070a490 Ether
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14e256569402022-09-27 1:40:011 day 20 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c Synthetix: Futures Market ETH0 Ether
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14e256569402022-09-27 1:40:011 day 20 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c Synthetix: Futures Market ETH0 Ether
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14e256569402022-09-27 1:40:011 day 20 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c Synthetix: Futures Market ETH0 Ether
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14e256569402022-09-27 1:40:011 day 20 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0xcce7819d65f348c64b7beb205ba367b3fe33763b0 Ether
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14e256569402022-09-27 1:40:011 day 20 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0xcfdff4e171133d55de2e45c66a0e144a135d93f20 Ether
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14e256569402022-09-27 1:40:011 day 20 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0xcfdff4e171133d55de2e45c66a0e144a135d93f20 Ether
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14e256569402022-09-27 1:40:011 day 20 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c Synthetix: Futures Market ETH0 Ether
0x9b6aa052b4f4f48b43205e114ba8fb37efb010b0515d41c588b60bfad439a14e256569402022-09-27 1:40:011 day 20 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x19828283852a852f8cfff4696038bc19e5070a490 Ether
0xd5dd718f9889e9841036de17fef89a57739e59b8b6c21a8df4659aad88039e63254635892022-09-26 5:00:372 days 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c Synthetix: Futures Market ETH0 Ether
0xd5dd718f9889e9841036de17fef89a57739e59b8b6c21a8df4659aad88039e63254635892022-09-26 5:00:372 days 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x0052a341bea99c4b452816235fc2216143c5f21c0 Ether
0xd5dd718f9889e9841036de17fef89a57739e59b8b6c21a8df4659aad88039e63254635892022-09-26 5:00:372 days 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0xbb3e8eac35e649ed1071a9ec42223d474e67b19a0 Ether
0xd5dd718f9889e9841036de17fef89a57739e59b8b6c21a8df4659aad88039e63254635892022-09-26 5:00:372 days 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0xbb3e8eac35e649ed1071a9ec42223d474e67b19a0 Ether
0xd5dd718f9889e9841036de17fef89a57739e59b8b6c21a8df4659aad88039e63254635892022-09-26 5:00:372 days 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0xbb3e8eac35e649ed1071a9ec42223d474e67b19a0 Ether
0xd5dd718f9889e9841036de17fef89a57739e59b8b6c21a8df4659aad88039e63254635892022-09-26 5:00:372 days 17 hrs ago 0x965e460bf5cb38bada79fb2293c6304c799d0b1c 0x22602469d704bffb0936c7a7cfcd18f7aa2693750 Ether
[ Download CSV Export 
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
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.