Contract 0xb28Df1b71a5b3a638eCeDf484E0545465a45d2Ec 1

 
Txn Hash Method
Index
From
To
Value
0x00999e8d83c41df760dfe36fc79631e26f1188d3d0c09385351ebdd76c9b071cInitiate Deposit260996162022-09-28 21:49:378 mins ago0xfb15339d187a76af62698f73d700e1f8536f03bd IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000479313890.00100155
0xa8d94a4f75f79601a477397c48da84426a2c189524ae65961f50c8d894d45e31Initiate Deposit260984962022-09-28 21:42:5715 mins ago0xeae5a1314509d4e1fb0066e7b87df8092fe073b3 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000367800040.00100155
0x1305c79315df9114ce186b2d239b6900c7c6e377ed08c9af79c81af665e3aacfInitiate Withdra...260982552022-09-28 21:40:5717 mins ago0xf42b1a25d903489c46f74c79a4cd1c22330d231d IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000370530750.00100155
0x740db6e4155b3142fadb35950ab561527e9275d3bfe886a4dbdef14371a7254aInitiate Deposit260975012022-09-28 21:34:0424 mins ago0x2a26c69c232dac8fa017ab413cec02db61d74c76 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000416439810.00100155
0x5baae5a59ebb9a119c944bc10703269e88b1ab7c7617221c9ac6c0da9bbe3134Initiate Withdra...260954422022-09-28 21:18:0840 mins ago0x1cdc17919b1e050d90b02344de36e05dee6c8696 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000522698910.00100155
0x2b6374c5a7e5c3c648d5465ec2cf867f3525de82501c55525733da2f7bbb9e52Initiate Withdra...260953842022-09-28 21:17:5340 mins ago0xf77e2c9b9ea81843d97a034e50aaa61b54edcc92 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000520817140.00100155
0x75b56b1d40ea623ce648a653b70f99dc1b54cec542b5200bc0e5a81b9f806135Initiate Deposit260953642022-09-28 21:17:3840 mins ago0x547b36b9710b5fdbcd89abf983c2b944bfc6c073 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000522486850.00100155
0x31a370a84733fb4d4a89787bb4c0615dba95543f1179d34fd409be8eb6627e1eInitiate Deposit260947852022-09-28 21:12:0646 mins ago0x5257e9e8123c8de5108d4d871df2d221c4f37f62 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000694796030.00100155
0x345aa3ebff70ddbd7aab0eca850efe5d38034fe7e14890289e967392c9d7d1efInitiate Deposit260947182022-09-28 21:11:5046 mins ago0xd24f5143605f79df9d73e9b9b5969ed201b721a7 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000690408290.00100155
0x7602824b41ae0ff9ddcb6a4260a53ba91269bf4cb3d02c22b2721cb8a1af0ac1Initiate Deposit260934142022-09-28 21:00:5457 mins ago0xa408cb2c8faa0c7d18f451033898fc3c8361939a IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000662423460.00100155
0x46219474dc7a279eac4480625f588d9cbf6b4b17a4783ab1f44604fed122913eProcess Deposit ...260932912022-09-28 21:00:0958 mins ago0x9f76043b23125024ce5f0fb4ae707482107dd2a8 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000523329230.00100155
0x669ef8d6a535428628975f016b271dad1c41e12a4547c3d96005d93e4a3b5298Initiate Withdra...260930332022-09-28 20:58:071 hr ago0xe89fe2f560d8bdd0b8b0786fb5fb7a27909c2005 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000572373470.00100155
0x9888b9a765cfc1fa6c15473d290ba9a495e241b2745461404b50f2ed8dfbc122Initiate Withdra...260928742022-09-28 20:56:371 hr 1 min ago0xc8685e0cd1611671c48cf2d6404df13e00e0ef2f IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000488499740.00100155
0x8ae51bb40953f9b8479efd16c0fafebad34b40620e3cdc0f191db3cfde1e854eInitiate Deposit260920802022-09-28 20:50:501 hr 7 mins ago0xbf3cd4e28ced7f61c588693c018f4f38b4b0444e IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000727182530.00100155
0x22c6f006843fa12a93af4d82b9685a9999e36b8cf2c72ede0ae4101eb3aeb882Initiate Deposit260919642022-09-28 20:50:041 hr 8 mins ago 0x7a38b009f9e176f07978c2e75bab2a5b657ca37a IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000551892910.00100155
0x7b2e20387aab54989c90bf635c58aa12631b67fcaa9cc36c995ac2ae5e3c03ebInitiate Deposit260902662022-09-28 20:42:011 hr 16 mins ago0x9fc24e3439b6e73888af81044cfdb70f659cf6e1 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000472636350.00100155
0x9d19ff5d67fb6002dfc7845c9a9a956f0df382f811a90907bc1c2c0ddb8b9c66Initiate Deposit260901462022-09-28 20:40:461 hr 17 mins ago0xc4f91cdd498a30f8ed1dea3883cba314a7a2a022 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000473917210.00100155
0x7099727e17f0d912abbf3cf1098b4d7e7f4ab64b3a9534e3f598bf29d3850597Initiate Withdra...260900322022-09-28 20:40:011 hr 18 mins ago0xb17f37452ccf77e56062256831d506ed36bd962a IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.00004744690.00100155
0xe1dc328951e73d0bd5d80747192a39509610e022ea22d5590fd831a80834738aInitiate Deposit260895842022-09-28 20:36:451 hr 21 mins ago0x65edbb3d15f054f3e18f6bd441ac5ec84511b3b4 IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000461036280.00100155
0x4561c9610960a5f8c18eb11963aa850303250892284a832a76ff58f3161c2d25Initiate Withdra...260894792022-09-28 20:36:001 hr 22 mins ago0xf40a06d7a93455a67c3177d4940ad2415b70e0ec IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000461557630.00100155
0x5f7c3f4151769ff046b38c5b7fec6280fdb2c08ec313e8710fcd009e97dcf195Initiate Deposit260894722022-09-28 20:36:001 hr 22 mins ago0xc17474c739460a778e5f34821aa9a52461c44fdb IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000461036280.00100155
0x5b69bd6fc27f87a2ec5d0ca9e94239efed6083d547d9ad1e27a6b49f770c6476Initiate Withdra...260889352022-09-28 20:31:581 hr 26 mins ago0xbc50aecfccfa4d7e41925ee8da3672211c6d3ccf IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000517927120.00100155
0xdc6152593473fe691bfe46b48705fec10f39aee1c45fa3591c4221675f6c9fc7Initiate Deposit260888082022-09-28 20:30:581 hr 27 mins ago0x0e4851f6464471004bc9736fe8f66eb82591650e IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.00005158490.00100155
0xe637b48646c71abf466fe34f291cd09fc9fce575a44b6c8f977ae0c2cfb1394eInitiate Deposit260880152022-09-28 20:24:101 hr 34 mins ago0x725479916103c4e094b0c567f24ccbc9e2871c1d IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000466299290.00100155
0x4a10441c7ee9ddc31f5d198e61ce0a781bae171727455a71573ebcd11fca5f41Initiate Withdra...260877782022-09-28 20:21:351 hr 36 mins ago0x8d0ac9ac56757b8dce0772b44a9958096acedf0c IN  0xb28df1b71a5b3a638ecedf484e0545465a45d2ec0 Ether0.0000546447970.00100155
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x1a80e86719197b186bbc596f0c4c74547e0291f8eabbe95f230aa024b422ea0d260154872022-09-28 13:51:568 hrs 6 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ec 0xd81abcdd67c7eb1c67c56c10a2077938037e4b060 Ether
0x0c71a98094d6cec72227890888285b91fe4e18a66176075c2692894af2323f8c260149592022-09-28 13:49:568 hrs 8 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x17039ae2df1dac5502c76299ae83b24324513793ceb02fa3ac49add9492745dc260139782022-09-28 13:47:268 hrs 10 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x3e5f6912e6620a115351364730b9f6e391abaa2b3ce0b7aeda7496ecbeae8fe9260130952022-09-28 13:44:268 hrs 13 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x5f01f7be1ed591558ab97f9cceff655c3d1c27f12212f578e2eb81de1d9deabb260126022022-09-28 13:42:568 hrs 15 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0xb465bdd5e16fdfc04385d0874ff54e18804838cfd62fbed080517844faae8423260118162022-09-28 13:40:118 hrs 18 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ec 0xd81abcdd67c7eb1c67c56c10a2077938037e4b060 Ether
0xd7d99bb2768364ac00f84efcda6b7d309fc436886b243e3427d8c443b89cb278260115472022-09-28 13:38:568 hrs 19 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x68ae3a0c305fea7338b19b5d541756de33e4ccd46b13be0c64c66ed3d3682ca9260113512022-09-28 13:38:118 hrs 20 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x212693fb6d414153653e3b3c741fadf082740b8e535a9ee400cd212e4b2e16ce260110712022-09-28 13:37:118 hrs 21 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x9a4cf199efd33a1aee4df92118d571db556856386d57c9360d56a8ca88d6ceb3260109322022-09-28 13:36:418 hrs 21 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ec 0xd81abcdd67c7eb1c67c56c10a2077938037e4b060 Ether
0x0754f2c10adc9364a4584091fd37ec043c08c62d15eed7920350c31440ecbc4d260106182022-09-28 13:35:418 hrs 22 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x9b84d7a523ded83c64a360a2806dce7707379b53bd272224f8487e791d594c21260103522022-09-28 13:34:418 hrs 23 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x371cf5c039b914ad00af0760a4d39acbcd46cc50abc813dc7d1c9286ac8a687f260100482022-09-28 13:33:568 hrs 24 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x405d46cd0c187b191cf580364e68a303f0fcec578e18557e7f37ddca8baae79c260097202022-09-28 13:32:418 hrs 25 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x776ffb457c61fd2ca968ecfe34624597df948d765fb2b39232deff3708afbb8d260088002022-09-28 13:30:118 hrs 28 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x19e4d0ef07d2597092088bd87bb70fbca77ea0345f67fd6c9e137317c0bf29d5260086922022-09-28 13:29:418 hrs 28 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ec 0xd81abcdd67c7eb1c67c56c10a2077938037e4b060 Ether
0x860047b83e804decfb2e3ec9996e29f44bf41342828f5ce35d2f44b1e208b278260085912022-09-28 13:29:268 hrs 28 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x414f03e90c413ae218c68146f245bf3775f919735b89e46b236eccefb643a22b260080472022-09-28 13:26:408 hrs 31 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x572aa1b9259bb7f36a626f0729901d2a64028e2e392cb61f35550cc96516041c260073462022-09-28 13:23:088 hrs 35 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x9fa8defd223664faaa7d4ba37612bb3a6bf2f68a1aef9b41df19a465d26caffb260073452022-09-28 13:23:088 hrs 35 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x48a2ae86476de31f43cb13f33f9278c2e8c837c535082b413c81ed2b7d9efac9260073312022-09-28 13:23:088 hrs 35 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x16e1382ce7b7192ff96702e556b4fc140dc718fd7f50c9d8feda2389ecd88505260070982022-09-28 13:22:088 hrs 36 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ec 0xd81abcdd67c7eb1c67c56c10a2077938037e4b060 Ether
0x31b720b424ee3b180ddd63c6f2f411d52c0d16acd89a116eb71574b419fb5d5b260067392022-09-28 13:20:238 hrs 37 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0xc399eaa17ca741a38a229aeb95c4ce3a7c04d7db2ea5faf319a0cd61eaf8f944260066502022-09-28 13:19:538 hrs 38 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 Ether
0x83f20171a1c50ae384bff2cefd32934bed7e1d6fe66f55384c9e579fd6c4729d260062552022-09-28 13:17:538 hrs 40 mins ago 0xb28df1b71a5b3a638ecedf484e0545465a45d2ecSynthetix: sUSD Token0 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:
PutSellingVault

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-20
*/

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

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

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

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

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

    address public owner;

    Authority public authority;

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

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

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

        _;
    }

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

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

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

        authority = newAuthority;

        emit AuthorityUpdated(msg.sender, newAuthority);
    }

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

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

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


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

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

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

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

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

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

    string public name;

    string public symbol;

    uint8 public immutable decimals;

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

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

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

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

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

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

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

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

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

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

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

        return true;
    }

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

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

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

        return true;
    }

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

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

        balanceOf[from] -= amount;

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

        emit Transfer(from, to, amount);

        return true;
    }

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

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

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

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

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

        locked = 2;

        _;

        locked = 1;
    }
}


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

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

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

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

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

        require(success, "ETH_TRANSFER_FAILED");
    }

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

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

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

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

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

        require(success, "TRANSFER_FROM_FAILED");
    }

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

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

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

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

        require(success, "TRANSFER_FAILED");
    }

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

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

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

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

        require(success, "APPROVE_FAILED");
    }
}


// File contracts/utils/Pausable.sol

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

abstract contract Pausable {

    bool private _paused;
    bool private _depositsPaused;

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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


// File contracts/interfaces/IPolynomialVaultToken.sol

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

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

    function totalSupply() external view returns (uint256 totalSupply);
}


// File contracts/interfaces/IPolynomialVault.sol

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

interface IPolynomialVault {}


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

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

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

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

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

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

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

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


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

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

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

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

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

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


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

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

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

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

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

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


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

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

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

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

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

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


// File contracts/libraries/DecimalMath.sol

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

pragma solidity ^0.8.9;

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

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

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

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

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

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

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

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

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

    return quotientTimesTen / 10;
  }

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

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

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

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

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

    return resultTimesTen / 10;
  }

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

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

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

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

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

    return quotientTimesTen / 10;
  }
}


// File contracts/libraries/SignedDecimalMath.sol

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

pragma solidity ^0.8.9;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


// File contracts/libraries/HigherMath.sol

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


// File contracts/libraries/BlackScholes.sol

// -License-Identifier: ISC

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

pragma solidity 0.8.9;



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


// File contracts/core/PutSellingVault.sol

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











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

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

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

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

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

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

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

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

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

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

    /// @notice sUSD
    ERC20 public immutable SUSD;

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

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

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

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

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

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

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

    /// @notice Collateralization ratio
    uint256 public collateralization;

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

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

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

    /// @notice GWAV Length
    uint256 public gwavLength;

    /// @notice Trade Iterations
    uint256 public tradeIterations;

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

    /// @notice Fee Receipient
    address public feeReceipient;

    /// @notice Performance Fee 
    uint256 public performanceFee;

    /// @notice Withdrawal Fee
    uint256 public withdrawalFee;
    
    /// @notice Total queued deposits
    uint256 public totalQueuedDeposits;

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

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

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

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

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

    /// @notice Total funds
    uint256 public totalFunds;

    /// @notice Used funds
    uint256 public usedFunds;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            QueuedWithdraw storage current = withdrawalQueue[queuedWithdrawalHead];

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

            uint256 availableFunds = totalFunds - usedFunds;

            if (availableFunds == 0) {
                return;
            }

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

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

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

                totalFunds -= availableFunds;

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

                SUSD.safeTransfer(current.user, availableFunds);

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

                totalFunds -= susdToReturn;

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

                SUSD.safeTransfer(current.user, susdToReturn);

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

            queuedWithdrawalHead++;
        }
    }

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

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

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

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

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

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

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

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

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

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

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

            putPremium = strikePrice > priceAtExpiry ? strikePrice - priceAtExpiry : 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 put option given its strike ID
    /// @param _strikeId Lyra Strike ID
    function getPutDelta(uint256 _strikeId) internal view returns (int256 putDelta) {
        (
            IOptionMarket.Strike memory strike,
            IOptionMarket.OptionBoard memory board
        ) = MARKET.getStrikeAndBoard(_strikeId);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        emit UpdateCollateralization(collateralization, _ratio);

        collateralization = _ratio;
    }

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

        emit UpdateFeeReceipient(feeReceipient, _feeReceipient);

        feeReceipient = _feeReceipient;
    }

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

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

        performanceFee = _performanceFee;
        withdrawalFee = _withdrawalFee;
    }

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

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

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

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

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

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

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

    function _openShortPosition(uint256 _strikeId, uint256 _amt) internal {
        int256 putDelta = getPutDelta(_strikeId);

        // Put options with delta lower than -0.25 should not be traded by the vault
        if (putDelta < deltaCutoff) {
            revert OptionTooRisky(_strikeId, putDelta);
        }

        PositionData storage positionData = positionDatas[_strikeId];

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

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

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

        usedFunds += collateralReq;

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

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

        IOptionMarketWrapperWithSwaps.OptionPositionParams memory params;

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

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

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

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

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

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

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

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


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

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

        IOptionMarketWrapperWithSwaps.OptionPositionParams memory params;

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

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

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

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

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

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

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

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

        PositionData storage positionData = positionDatas[_strikeId];

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

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

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

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

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

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

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

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

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

            usedFunds -= positionData.collateral;

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

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

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

            _removeStrikeId(_strikeIds[i]);
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Contract Security Audit

Contract ABI

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

6101a0604052600160025560016010556001601155600160125560016013553480156200002b57600080fd5b5060405162005a4538038062005a458339810160408190526200004e9162000138565b60008054336001600160a01b03199182168117835560018054909216909155604051909190829081907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908490a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350506003805461ffff191690556001600160a01b0397881660e05295871661010052938616610120529185166101405284166101605283166101805260a052911660c052608052620001f7565b6001600160a01b03811681146200013557600080fd5b50565b60008060008060008060008060006101208a8c0312156200015857600080fd5b895162000165816200011f565b60208b015190995062000178816200011f565b60408b01519098506200018b816200011f565b60608b01519097506200019e816200011f565b60808b0151909650620001b1816200011f565b60a08b0151909550620001c4816200011f565b60c08b0151909450620001d7816200011f565b8093505060e08a015191506101008a015190509295985092959850929598565b60805160a05160c05160e0516101005161012051610140516101605161018051615686620003bf6000396000818161062f015281816132a101526147960152600081816108ca015281816134940152818161354f0152818161362201526148b50152600081816108a301528181612a7301528181612b3f01528181613b1c01528181613be5015261419401526000818161086a01528181612a4f01528181612b6c01528181612d6d01528181612e7101528181613af801528181613c1201528181613d990152613ebc01526000818161090401528181612c0d01528181612d9c015281816131830152818161337c015281816139340152818161399201528181613c8801528181613dc8015281816142900152614678015260008181610503015281816115f00152818161203e01528181612341015261263a01526000818161044b01528181610f9901528181610fe3015281816110ed0152818161113701528181611b3b015281816121a0015281816127ea01528181612d4b01528181612e220152818161391201528181613d7701528181613e6d01528181613fce015261441e01526000818161072b01528181613269015261475e015260006103d901526156866000f3fe608060405234801561001057600080fd5b50600436106103c55760003560e01c80637a9e5e4b116101ff578063bc0d6c571161011a578063deccdf63116100ad578063f46f16c21161007c578063f46f16c2146108ff578063f7164fc714610926578063fc2da41f1461092f578063fd9d40771461093857600080fd5b8063deccdf6314610895578063e3d51ddd1461089e578063e55d1a52146108c5578063ec552346146108ec57600080fd5b8063c8393ba9116100e9578063c8393ba91461083f578063caca00f414610852578063d2450c7614610865578063d91d2f601461088c57600080fd5b8063bc0d6c57146107ca578063bf7e214f146107dd578063c4e41b22146107f0578063c822adda146107f857600080fd5b80638da4e2f9116101925780639cc621df116101615780639cc621df1461077c578063a8f35adf14610791578063b35648d7146107a4578063b41e20d4146107b757600080fd5b80638da4e2f9146107265780638da5cb5b1461074d578063968ed600146107605780639afdb2c21461076957600080fd5b806387788782116101ce57806387788782146106f6578063892df74f146106ff5780638bc7e8c4146107085780638d3ddf771461071157600080fd5b80637a9e5e4b146106515780637f54b4131461066457806383290a3c146106775780638456cb59146106ee57600080fd5b80634499d14b116102ef5780635c975abb1161028257806370f520811161025157806370f52081146105af578063771126af146105c25780637772ba071461061757806379f67c441461062a57600080fd5b80635c975abb1461057757806360da3e831461058e57806363d8882a1461059e578063645006ca146105a657600080fd5b80634b94f50e116102be5780634b94f50e1461054a5780634d8737cb146105525780634ffaa7361461056557806358f67c0b1461056e57600080fd5b80634499d14b146104fe578063481bf0b814610525578063499d75d81461052e5780634b48f20d1461053757600080fd5b8063208e7e9311610367578063342c00b311610336578063342c00b3146104c757806335f748c2146104da5780633740ebb3146104e35780633f4ba83a146104f657600080fd5b8063208e7e93146104855780632a80cda31461048e5780632b6fcf2e146104a15780633012b05c146104b457600080fd5b80630b78f9c0116103a35780630b78f9c01461041757806313af40351461042a57806315a01bc11461043d57806315d8eeba1461044657600080fd5b806302191980146103ca57806306fdde03146103d45780630b2ad0881461040e575b600080fd5b6103d2610941565b005b6103fb7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6103fb60135481565b6103d2610425366004614c6a565b6109b9565b6103d2610438366004614ca1565b610aeb565b6103fb60155481565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610405565b6103fb60105481565b6103d261049c366004614cbe565b610bb7565b6103d26104af366004614cbe565b610c61565b6103d26104c2366004614c6a565b610d0b565b6103d26104d5366004614cbe565b610e1a565b6103fb60065481565b600b5461046d906001600160a01b031681565b6103d26111f9565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103fb600f5481565b6103fb600a5481565b6103d2610545366004614ca1565b61126a565b6103fb611394565b6103d2610560366004614cbe565b6114ac565b6103fb60095481565b6103fb600e5481565b60035460ff165b6040519015158152602001610405565b600354610100900460ff1661057e565b6103d26116f3565b6103fb60055481565b6103d26105bd366004614cbe565b611764565b6105f76105d0366004614cbe565b60186020526000908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610405565b6103d2610625366004614c6a565b61183a565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103d261065f366004614ca1565b6118f9565b6103fb610672366004614cbe565b611a3e565b6106be610685366004614cbe565b6019602052600090815260409020805460018201546002830154600384015460049094015492936001600160a01b039092169290919085565b604080519586526001600160a01b039094166020860152928401919091526060830152608082015260a001610405565b6103d2611a5f565b6103fb600c5481565b6103fb60125481565b6103fb600d5481565b610719600481565b6040516104059190614d1a565b6103fb7f000000000000000000000000000000000000000000000000000000000000000081565b60005461046d906001600160a01b031681565b6103fb60145481565b6103d2610777366004614d28565b611ad0565b610784611c19565b6040516104059190614d69565b6103d261079f366004614c6a565b611c71565b6103d26107b2366004614dad565b611d77565b6103d26107c5366004614cbe565b611e88565b6103d26107d8366004614eec565b611f32565b60015461046d906001600160a01b031681565b6103fb612037565b6106be610806366004614cbe565b601a602052600090815260409020805460018201546002830154600384015460049094015492936001600160a01b039092169290919085565b6103d261084d366004614f82565b6120dc565b6103d2610860366004614cbe565b6123ae565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103fb60045481565b6103fb60085481565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103d26108fa366004614f82565b6124b7565b61046d7f000000000000000000000000000000000000000000000000000000000000000081565b6103fb60165481565b6103fb60115481565b6103fb60075481565b61096f336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b6109af5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b6109b761290d565b565b6109e7336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b610a225760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b67016345785d8a0000821180610a3e5750662386f26fc1000081115b15610a9257600c54600d546040517f0995039e0000000000000000000000000000000000000000000000000000000081526004810192909252602482015260448101839052606481018290526084016109a6565b600c54600d546040805192835260208301919091528101839052606081018290527f5c3aee3d65f7eb02cded951435d06b06ef307bc7f57b98975c4a41dc116e711c9060800160405180910390a1600c91909155600d55565b610b19336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b610b545760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b610be5336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b610c205760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b60055460408051918252602082018390527f915e1f57375bebe5483299c788956d167e46a28a143974dc29bba5a420aa4354910160405180910390a1600555565b610c8f336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b610cca5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b60085460408051918252602082018390527f40777929ad14ec610067fc9c075e20805fe1c57e1879cf2b583355109971c546910160405180910390a1600855565b610d39336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b610d745760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600254600114610dc65760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560035460ff1615610e07576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e1182826129b1565b50506001600255565b600254600114610e6c5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560005b81811015610e11576000610e85611394565b6012546000908152601a602052604090206004810154919250901580610ebb57506007548160040154610eb89190614fdd565b42105b15610ec8575050506111f1565b6000601554601454610eda9190614ff5565b905080610eea57505050506111f1565b6002820154600090610efc9085613002565b90508181111561107757600383018290556000610f19838661301e565b905080600f6000828254610f2d9190614ff5565b9250508190555080846002016000828254610f489190614ff5565b925050819055508260146000828254610f619190614ff5565b9091555050600d5415610fd0576000610f85600d548561300290919063ffffffff16565b600b54909150610fc2906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613033565b610fcc8185614ff5565b9350505b600184015461100c906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911685613033565b835460018501546004860154604080519384526001600160a01b039092166020840152828201849052606083018690526080830152517f36a40db5d5631acd8e2764bd196c60dd82faed72aea6647297ab6af63309b58e9181900360a00190a15050505050506111f1565b600383018190556002830154600f8054600090611095908490614ff5565b9091555050600060028401819055601480548392906110b5908490614ff5565b9091555050600d54156111245760006110d9600d548361300290919063ffffffff16565b600b54909150611116906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613033565b6111208183614ff5565b9150505b6001830154611160906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613033565b8254600184015460028501546004860154604080519485526001600160a01b039093166020850152918301526060820183905260808201527f86dc3fd2a6c267674f2f2ef1b4b7283dcca31e1e2517a55358795c65eca1fe039060a00160405180910390a1601280549060006111d58361500c565b91905055505050505080806111e99061500c565b915050610e73565b506001600255565b611227336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b6112625760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6109b76130d2565b611298336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b6112d35760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6001600160a01b038116611313576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b54604080516001600160a01b03928316815291831660208301527fc8bc890a52e17e373db7ac75d8f97911a18bffc2ef18bd8047ed55770ee6ba8b910160405180910390a1600b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000601454600014156113ae5750670de0b6b3a764000090565b60006113b8612037565b6017549091506113d5576014546113cf9082613166565b91505090565b60006016546014546113e79190614fdd565b905060005b60175481101561149a5760006017828154811061140b5761140b615045565b600091825260208083209091015480835260188252604080842081516080810183528154815260018201549481019490945260028101549184019190915260030154606083015292509061145e8361317b565b91505061147882602001518261300290919063ffffffff16565b6114829086614ff5565b945050505080806114929061500c565b9150506113ec565b506114a58183613166565b9250505090565b6002546001146114fe5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b60028055600061150c611394565b905060005b828110156116e95760105460009081526019602052604090206004810154158061154b575060065481600401546115489190614fdd565b42105b15611558575050506111f1565b600281015460009061156a9085613166565b90508082600301819055508160020154600e600082825461158b9190614ff5565b90915550506002820154601480546000906115a7908490614fdd565b909155505060018201546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152602481018390527f0000000000000000000000000000000000000000000000000000000000000000909116906340c10f1990604401600060405180830381600087803b15801561163657600080fd5b505af115801561164a573d6000803e3d6000fd5b505083546001850154600286015460038701546004880154604080519586526001600160a01b0390941660208601528484019290925260608401526080830152517f4d356a2d534287c80daa3bb725dcc09c0ad1049e50c1e328646c49e5a0b2c6cb93509081900360a0019150a160006002830181905560108054916116cf8361500c565b9190505550505080806116e19061500c565b915050611511565b5050506001600255565b611721336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b61175c5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6109b7613791565b611792336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b6117cd5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b7ffffffffffffffffffffffffffffffffffffffffffffffffff90fa4a62c4e000081131561183757600a5460408051918252602082018390527fbfc81c1ba7d829304f63f4bffe5910955b03f6951f1177ba93883cff15a40567910160405180910390a1600a8190555b50565b611868336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b6118a35760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6006546007546040805192835260208301859052820152606081018290527fc8f5f7dffddfef257dee57a6cd0384a4900f2ab48c3e69766faa5577e6a7cbcb9060800160405180910390a1600691909155600755565b6000546001600160a01b03163314806119d157506001546040517fb70096130000000000000000000000000000000000000000000000000000000081523360048201523060248201526000357fffffffff000000000000000000000000000000000000000000000000000000001660448201526001600160a01b039091169063b70096139060640160206040518083038186803b15801561199957600080fd5b505afa1580156119ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d19190615089565b6119da57600080fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b60178181548110611a4e57600080fd5b600091825260209091200154905081565b611a8d336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b611ac85760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b6109b761382a565b611afe336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b611b395760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161415611b7857600080fd5b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b158015611bdb57600080fd5b505af1158015611bef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c139190615089565b50505050565b60606017805480602002602001604051908101604052809291908181526020018280548015611c6757602002820191906000526020600020905b815481526020019060010190808311611c53575b5050505050905090565b611c9f336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b611cda5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600254600114611d2c5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560035460ff1615611d6d576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e1182826138c3565b611da5336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b611de05760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600254600114611e325760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560035460ff1615611e73576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e7e838383613a57565b5050600160025550565b611eb6336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b611ef15760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b60095460408051918252602082018390527ff53b0be70f27baabf334832258c8da935a270674357a3d0e51ad87896efbc654910160405180910390a1600955565b611f60336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b611f9b5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b600254600114611fed5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b6002805560035460ff161561202e576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111f1816140e4565b6000600f547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561209557600080fd5b505afa1580156120a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cd91906150a4565b6120d79190614fdd565b905090565b60025460011461212e5760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b600280556001600160a01b038216612172576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175461223c576000612183611394565b905060006121918383613002565b90506121c76001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168583613033565b80601460008282546121d99190614ff5565b909155505060408051600081526001600160a01b0386166020820152908101849052606081018290524260808201527f86dc3fd2a6c267674f2f2ef1b4b7283dcca31e1e2517a55358795c65eca1fe039060a00160405180910390a1505061230c565b601380546000818152601a6020526040812092906122598361500c565b9091555081556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03851617905560028101829055426004820155600f80548391906000906122b6908490614fdd565b90915550508054604080519182523360208301526001600160a01b0385168282015260608201849052517f6af4b9a67fcdcb6bdd58b7b26c00492d52c66372d350d228ec6a5420bb13fe329181900360800190a1505b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac90604401600060405180830381600087803b15801561238d57600080fd5b505af11580156123a1573d6000803e3d6000fd5b5050600160025550505050565b6123dc336000357fffffffff0000000000000000000000000000000000000000000000000000000016612812565b6124175760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064016109a6565b670de0b6b3a764000081118061243457506706f05b59d3b2000081105b1561247657600480546040517f618e3d2d00000000000000000000000000000000000000000000000000000000815291820152602481018290526044016109a6565b60045460408051918252602082018390527f7cbf954c53f0cfe32163baacd57a397c9a307b23673e8dbb6e84fe0ea1f5e59d910160405180910390a1600455565b6002546001146125095760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016109a6565b60028055600354610100900460ff161561254f576040517fdeeb694300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03821661258f576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005548110156125d9576005546040517f54443ec40000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016109a6565b60175461270d5760006125ea611394565b905060006125f88383613166565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152602482018390529192507f0000000000000000000000000000000000000000000000000000000000000000909116906340c10f1990604401600060405180830381600087803b15801561268057600080fd5b505af1158015612694573d6000803e3d6000fd5b5050505082601460008282546126aa9190614fdd565b909155505060408051600081526001600160a01b0386166020820152908101849052606081018290524260808201527f4d356a2d534287c80daa3bb725dcc09c0ad1049e50c1e328646c49e5a0b2c6cb9060a00160405180910390a150506127dd565b601180546000818152601960205260408120929061272a8361500c565b9091555081556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03851617905560028101829055426004820155600e8054839190600090612787908490614fdd565b90915550508054604080519182523360208301526001600160a01b0385168282015260608201849052517f1ccb85c4426dacaaa67edc2ae6421283328736c96dd21b82026889d72414832c9181900360800190a1505b610e116001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330846145c5565b6001546000906001600160a01b031680158015906128eb57506040517fb70096130000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301523060248301527fffffffff000000000000000000000000000000000000000000000000000000008516604483015282169063b70096139060640160206040518083038186803b1580156128b357600080fd5b505afa1580156128c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128eb9190615089565b8061290357506000546001600160a01b038581169116145b9150505b92915050565b600354610100900460ff161561294f576040517fdeeb694300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556040513381527fcb92ca4a4d7ab7e82e1f35164d09a91663f3393b45f06fcac5a73f63ae6bf23f906020015b60405180910390a1565b60006129bc83614671565b9050600a54811215612a04576040517fdc818acd00000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044016109a6565b6000838152601860205260409020805415801590612b08575080546040517f081812fc0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116927f00000000000000000000000000000000000000000000000000000000000000009091169163081812fc91612aac9160040190815260200190565b60206040518083038186803b158015612ac457600080fd5b505afa158015612ad8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612afc91906150c8565b6001600160a01b031614155b15612bdb5780546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163095ea7b391612ba8917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015612bc257600080fd5b505af1158015612bd6573d6000803e3d6000fd5b505050505b6040517fcf6bcba0000000000000000000000000000000000000000000000000000000008152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063cf6bcba090602401604080518083038186803b158015612c5657600080fd5b505afa158015612c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8e91906150e5565b5090506000612cb2600454612cac848861300290919063ffffffff16565b90613002565b90508060156000828254612cc69190614fdd565b90915550506014546015541115612d2a5760145481601554612ce89190614ff5565b6040517ff5623b7200000000000000000000000000000000000000000000000000000000815260048101929092526024820152604481018290526064016109a6565b6000818460020154612d3c9190614fdd565b9050612d926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000084614a1e565b612d9a614be6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020810188905284546040820152600954606082015260808101829052600285015460a0820152600460c082018190525060e0810187905260006101008201819052610120820184905261014082018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166101608401526040517f8bc369690000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000090911690638bc3696990612ea8908590600401615109565b61010060405180830381600087803b158015612ec357600080fd5b505af1158015612ed7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efb91906151a6565b905082866002018190555087866001016000828254612f1a9190614fdd565b90915550506080810151600387018054600090612f3890849061524d565b9091555050608081015160168054600090612f5490849061524d565b90915550508554612f9c5760208101518655601780546001810182556000919091527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c15018990555b8554608082810151604080518d8152602081019490945283018b9052606083018790529082015260a081018890527f1bd03927c37312e9dc9bb94d819a9ee53bdbc8ad5a7b6dc25074b02f3908b3539060c00160405180910390a1505050505050505050565b60006130178383670de0b6b3a7640000614abd565b9392505050565b600061301783670de0b6b3a764000084614adc565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611c135760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016109a6565b60035460ff1661310e576040517f6cd6020100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556040513381527f3bd4fb9a28883a4c90034f2cd214c1f94fc09854604f38dee6a87e5455e2123b906020016129a7565b600061301783670de0b6b3a764000084614abd565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4c4a0d0866040518263ffffffff1660e01b81526004016131cf91815260200190565b60006040518083038186803b1580156131e757600080fd5b505afa1580156131fb573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052613241919081019061538c565b6040517f0c71cd230000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152919350915060009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630c71cd2390602401604080518083038186803b1580156132e257600080fd5b505afa1580156132f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061331a9190615446565b91509150816000148061332a5750805b1561333457600080fd5b8260200151421115613457576040517f1fdb6cbd0000000000000000000000000000000000000000000000000000000081526004810188905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631fdb6cbd9060240160606040518083038186803b1580156133be57600080fd5b505afa1580156133d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f69190615472565b50915091508060001415613436576040517f30c7646e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80821161344457600061344e565b61344e8183614ff5565b96505050613788565b82516008546040517ff3fd9b3d000000000000000000000000000000000000000000000000000000008152600481019290925260248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f3fd9b3d9060440160206040518083038186803b1580156134de57600080fd5b505afa1580156134f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351691906150a4565b6008546040517f7df712680000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691637df712689161358d918d91600401918252602082015260400190565b60206040518083038186803b1580156135a557600080fd5b505afa1580156135b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135dd91906150a4565b905060006040518060a001604052804288602001516135fc9190614ff5565b815260200161360b8585613002565b8152602001868152602001886020015181526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f369f2ac6040518163ffffffff1660e01b81526004016101406040518083038186803b15801561367a57600080fd5b505afa15801561368e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136b291906154a0565b61012001519052604080517fbcf1e77900000000000000000000000000000000000000000000000000000000815282516004820152602083015160248201529082015160448201526060820151606482015260808201516084820152909150730052a341bea99c4b452816235fc2216143c5f21c9063bcf1e7799060a401604080518083038186803b15801561374757600080fd5b505af415801561375b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377f91906150e5565b90995097505050505b50505050915091565b600354610100900460ff166137d2576040517fa4d3098c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690556040513381527fd9b17f88c19eed029496a647acd647444182c708871dadb0b13c8db2bbcdff36906020016129a7565b60035460ff1615613867576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790556040513381527ff87d42f34d6dc854596ee7e10d09f6ef97f38e4ab22330c4fcb384c7e7f81d19906020016129a7565b80601560008282546138d59190614fdd565b909155505060145460155411156138f75760145481601554612ce89190614ff5565b60008281526018602052604090206139596001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000084614a1e565b80546040517fa8f35adf0000000000000000000000000000000000000000000000000000000081526004810191909152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a8f35adf90604401600060405180830381600087803b1580156139de57600080fd5b505af11580156139f2573d6000803e3d6000fd5b5050505081816002016000828254613a0a9190614fdd565b9091555050805460408051858152602081019290925281018390527f8dedd193eae1d427fb5f6ae4dcd87fa15d38eabb7ecf00bf9c85a8f692d709dc9060600160405180910390a1505050565b600083815260186020526040902080541580613a765750828160010154105b80613a82575060165482115b15613ac65780546040517f1e61e6a70000000000000000000000000000000000000000000000000000000081526109a6918691600401918252602082015260400190565b80546040517f081812fc0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116927f00000000000000000000000000000000000000000000000000000000000000009091169163081812fc91613b559160040190815260200190565b60206040518083038186803b158015613b6d57600080fd5b505afa158015613b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ba591906150c8565b6001600160a01b031614613c815780546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163095ea7b391613c4e917f0000000000000000000000000000000000000000000000000000000000000000916004016001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015613c6857600080fd5b505af1158015613c7c573d6000803e3d6000fd5b505050505b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cf6bcba0886040518263ffffffff1660e01b8152600401613cd491815260200190565b604080518083038186803b158015613ceb57600080fd5b505afa158015613cff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2391906150e5565b5090508360010154861415613d3e5783600201549250613d6a565b600454613d5590613d4f8884614b0a565b90614b0a565b9250828460020154613d679190614ff5565b91505b613dbe6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000087614a1e565b613dc6614be6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020810188905284546040820152600954606082015260808101839052600285015460a0820152600460c082018190525060e08101879052600061010082018190527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61012083015261014082018790526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166101608401526040517fb738a96b0000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000009091169063b738a96b90613ef3908590600401615109565b61010060405180830381600087803b158015613f0e57600080fd5b505af1158015613f22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f4691906151a6565b905060008160800151905084876002018190555088876001016000828254613f6e9190614ff5565b9250508190555080876003016000828254613f899190615527565b909155505060018701546140575760008760030154131561401f576003870154600c54600090613fba908390613002565b600b54909150613ff7906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613033565b6140018183614ff5565b601460008282546140129190614fdd565b9091555061404492505050565b866003015461402d9061559b565b6014600082825461403e9190614ff5565b90915550505b600080885560038801556140578a614b1f565b80601660008282546140699190615527565b9250508190555085601560008282546140829190614ff5565b90915550508654604080518c8152602081019290925281018a905260608101879052608081018290527fee19d4dcc15e899950ecf28027eee5796688964dc923320a7eedcfc95abfc7a29060a00160405180910390a150505050505050505050565b60005b81518110156145c15760006018600084848151811061410857614108615045565b60200260200101518152602001908152602001600020905080600101546000141561415f576040517f54db0c8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80546040517feb29dc5e0000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163eb29dc5e916141cb9160040190815260200190565b60206040518083038186803b1580156141e357600080fd5b505afa1580156141f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061421b91906155d4565b9050600481600581111561423157614231614cd7565b1461428b5783838151811061424857614248615045565b60200260200101518260000154826040517f25c1b4cf0000000000000000000000000000000000000000000000000000000081526004016109a6939291906155f5565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631fdb6cbd8787815181106142cf576142cf615045565b60200260200101516040518263ffffffff1660e01b81526004016142f591815260200190565b60606040518083038186803b15801561430d57600080fd5b505afa158015614321573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143459190615472565b50915091508060001415614385576040517f30c7646e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008282106143955760006143a8565b60018501546143a890612cac8486614ff5565b905080156143c85780601460008282546143c29190614ff5565b90915550505b8460020154601560008282546143de9190614ff5565b90915550506003850154600012156144ba57600385015460008261444757600c5461440a908390613002565b600b54909150614447906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683613033565b6144518183614ff5565b601460008282546144629190614fdd565b92505081905550816016600082825461447b9190615527565b9091555050601654600013156144b3576016546144979061559b565b601460008282546144a89190614ff5565b909155505060006016555b50506144df565b84600301546144c89061559b565b601460008282546144d99190614ff5565b90915550505b7f5c7fe62083bc914e5249c3b877823e54536d036c26578aa386223d00f9db704c87878151811061451257614512615045565b602002602001015186600001548760010154886002015489600301548660405161456496959493929190958652602086019490945260408501929092526060840152608083015260a082015260c00190565b60405180910390a160008086556003860181905560018601819055600286015586516145a99088908890811061459c5761459c615045565b6020026020010151614b1f565b505050505080806145b99061500c565b9150506140e7565b5050565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d116001600051141617169150508061466a5760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064016109a6565b5050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4c4a0d0856040518263ffffffff1660e01b81526004016146c491815260200190565b60006040518083038186803b1580156146dc57600080fd5b505afa1580156146f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052614736919081019061538c565b6040517f0c71cd230000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152919350915060009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630c71cd2390602401604080518083038186803b1580156147d757600080fd5b505afa1580156147eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061480f9190615446565b91509150816000148061481f5750805b15614861576040517f7ba847270000000000000000000000000000000000000000000000000000000081526004810183905281151560248201526044016109a6565b60006040518060a0016040528042866020015161487e9190614ff5565b815260200161489e8760400151876040015161300290919063ffffffff16565b8152602001848152602001866020015181526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f369f2ac6040518163ffffffff1660e01b81526004016101406040518083038186803b15801561490d57600080fd5b505afa158015614921573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061494591906154a0565b61012001519052604080517fdc1f2cd800000000000000000000000000000000000000000000000000000000815282516004820152602083015160248201529082015160448201526060820151606482015260808201516084820152909150730052a341bea99c4b452816235fc2216143c5f21c9063dc1f2cd89060a401604080518083038186803b1580156149da57600080fd5b505af41580156149ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a1291906150e5565b98975050505050505050565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611c135760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c454400000000000000000000000000000000000060448201526064016109a6565b828202811515841585830485141716614ad557600080fd5b0492915050565b828202811515841585830485141716614af457600080fd5b6001826001830304018115150290509392505050565b60006130178383670de0b6b3a7640000614adc565b6017546000905b80821015614b6a5760178281548110614b4157614b41615045565b9060005260206000200154831415614b5857614b6a565b81614b628161500c565b925050614b26565b80821015614be1576017614b7f600183614ff5565b81548110614b8f57614b8f615045565b906000526020600020015460178381548110614bad57614bad615045565b6000918252602090912001556017805480614bca57614bca615621565b600190038181906000526020600020016000905590555b505050565b60405180610180016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160006004811115614c3857614c38614cd7565b81526020016000815260200160008152602001600081526020016000815260200160006001600160a01b031681525090565b60008060408385031215614c7d57600080fd5b50508035926020909101359150565b6001600160a01b038116811461183757600080fd5b600060208284031215614cb357600080fd5b813561301781614c8c565b600060208284031215614cd057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60058110614d1657614d16614cd7565b9052565b602081016129078284614d06565b600080600060608486031215614d3d57600080fd5b8335614d4881614c8c565b92506020840135614d5881614c8c565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b81811015614da157835183529284019291840191600101614d85565b50909695505050505050565b600080600060608486031215614dc257600080fd5b505081359360208301359350604090920135919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715614e2b57614e2b614dd9565b60405290565b604051610120810167ffffffffffffffff81118282101715614e2b57614e2b614dd9565b604051610140810167ffffffffffffffff81118282101715614e2b57614e2b614dd9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614ec057614ec0614dd9565b604052919050565b600067ffffffffffffffff821115614ee257614ee2614dd9565b5060051b60200190565b60006020808385031215614eff57600080fd5b823567ffffffffffffffff811115614f1657600080fd5b8301601f81018513614f2757600080fd5b8035614f3a614f3582614ec8565b614e79565b81815260059190911b82018301908381019087831115614f5957600080fd5b928401925b82841015614f7757833582529284019290840190614f5e565b979650505050505050565b60008060408385031215614f9557600080fd5b8235614fa081614c8c565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115614ff057614ff0614fae565b500190565b60008282101561500757615007614fae565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561503e5761503e614fae565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051801515811461508457600080fd5b919050565b60006020828403121561509b57600080fd5b61301782615074565b6000602082840312156150b657600080fd5b5051919050565b805161508481614c8c565b6000602082840312156150da57600080fd5b815161301781614c8c565b600080604083850312156150f857600080fd5b505080516020909101519092909150565b81516001600160a01b0316815261018081016020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015161515f60c0840182614d06565b5060e08381015190830152610100808401519083015261012080840151908301526101408084015190830152610160928301516001600160a01b0316929091019190915290565b60006101008083850312156151ba57600080fd5b6040519081019067ffffffffffffffff821181831017156151dd576151dd614dd9565b81604052835191506151ee82614c8c565b81815260208401516020820152615207604085016150bd565b6040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c082015261524060e085016150bd565b60e0820152949350505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561528757615287614fae565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156152bb576152bb614fae565b50500190565b600060a082840312156152d357600080fd5b6152db614e08565b905081518152602080830151818301526040830151604083015261530160608401615074565b6060830152608083015167ffffffffffffffff81111561532057600080fd5b8301601f8101851361533157600080fd5b805161533f614f3582614ec8565b81815260059190911b8201830190838101908783111561535e57600080fd5b928401925b8284101561537c57835182529284019290840190615363565b6080860152509295945050505050565b6000808284036101408112156153a157600080fd5b610120808212156153b157600080fd5b6153b9614e31565b9150845182526020850151602083015260408501516040830152606085015160608301526080850151608083015260a085015160a083015260c085015160c083015260e085015160e08301526101008086015181840152508193508085015191505067ffffffffffffffff81111561543057600080fd5b61543c858286016152c1565b9150509250929050565b6000806040838503121561545957600080fd5b8251915061546960208401615074565b90509250929050565b60008060006060848603121561548757600080fd5b8351925060208401519150604084015190509250925092565b600061014082840312156154b357600080fd5b6154bb614e55565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152506101208084015181830152508091505092915050565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561556157615561614fae565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561559557615595614fae565b50500390565b60007f80000000000000000000000000000000000000000000000000000000000000008214156155cd576155cd614fae565b5060000390565b6000602082840312156155e657600080fd5b81516006811061301757600080fd5b83815260208101839052606081016006831061561357615613614cd7565b826040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea264697066735822122094a13c130193f4f9aaf52bdc605a2127f17c2ed30c49455f1cd761639ae2dd0d64736f6c634300080900330000000000000000000000008c6f28f2f1a3c87f0f938b96d27520d9751ec8d9000000000000000000000000d81abcdd67c7eb1c67c56c10a2077938037e4b060000000000000000000000001d42a98848e022908069c2c545ae44cc78509bc8000000000000000000000000cce7819d65f348c64b7beb205ba367b3fe33763b000000000000000000000000cfdff4e171133d55de2e45c66a0e144a135d93f2000000000000000000000000bb3e8eac35e649ed1071a9ec42223d474e67b19a00000000000000000000000022602469d704bffb0936c7a7cfcd18f7aa269375734554480000000000000000000000000000000000000000000000000000000073455448205075742053656c6c696e6700000000000000000000000000000000

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

0000000000000000000000008c6f28f2f1a3c87f0f938b96d27520d9751ec8d9000000000000000000000000d81abcdd67c7eb1c67c56c10a2077938037e4b060000000000000000000000001d42a98848e022908069c2c545ae44cc78509bc8000000000000000000000000cce7819d65f348c64b7beb205ba367b3fe33763b000000000000000000000000cfdff4e171133d55de2e45c66a0e144a135d93f2000000000000000000000000bb3e8eac35e649ed1071a9ec42223d474e67b19a00000000000000000000000022602469d704bffb0936c7a7cfcd18f7aa269375734554480000000000000000000000000000000000000000000000000000000073455448205075742053656c6c696e6700000000000000000000000000000000

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

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


Library Used

BlackScholesLib : 0x0052a341bea99c4b452816235fc2216143c5f21c

Deployed ByteCode Sourcemap

75495:38909:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93900:82;;;:::i;:::-;;77078:29;;;;;;;;160:25:1;;;148:2;133:18;77078:29:0;;;;;;;;79375:41;;;;;;95212:470;;;;;;:::i;:::-;;:::i;2109:151::-;;;;;;:::i;:::-;;:::i;79516:24::-;;;;;;77253:27;;;;;;;;-1:-1:-1;;;;;1358:55:1;;;1340:74;;1328:2;1313:18;77253:27:0;1181:239:1;79029:36:0;;;;;;95781:172;;;;;;:::i;:::-;;:::i;96470:151::-;;;;;;:::i;:::-;;:::i;92330:160::-;;;;;;:::i;:::-;;:::i;85148:2513::-;;;;;;:::i;:::-;;:::i;78245:30::-;;;;;;78609:28;;;;;-1:-1:-1;;;;;78609:28:0;;;94025:70;;;:::i;77332:50::-;;;;;78915:37;;;;;;78543:25;;;;;;94788:288;;;;;;:::i;:::-;;:::i;87983:743::-;;;:::i;84055:965::-;;;;;;:::i;:::-;;:::i;78463:30::-;;;;;;78830:34;;;;;;24846:86;24917:7;;;;24846:86;;;2446:14:1;;2439:22;2421:41;;2409:2;2394:18;24846:86:0;2281:187:1;24940:102:0;25019:15;;;;;;;24940:102;;94137:86;;;:::i;78166:31::-;;;;;;96983:228;;;;;;:::i;:::-;;:::i;79762:54::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2886:25:1;;;2942:2;2927:18;;2920:34;;;;2970:18;;;2963:34;3028:2;3013:18;;3006:34;2873:3;2858:19;79762:54:0;2657:389:1;96112:276:0;;;;;;:::i;:::-;;:::i;77807:37::-;;;;;1659:442;;;;;;:::i;:::-;;:::i;79681:28::-;;;;;;:::i;:::-;;:::i;79856:54::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;79856:54:0;;;;;;;;;;;;;3832:25:1;;;-1:-1:-1;;;;;3893:55:1;;;3888:2;3873:18;;3866:83;3965:18;;;3958:34;;;;4023:2;4008:18;;4001:34;4066:3;4051:19;;4044:35;3819:3;3804:19;79856:54:0;3573:512:1;93794:66:0;;;:::i;78680:29::-;;;;;;79258:39;;;;;;78750:28;;;;;;76731:95;;76786:40;76731:95;;;;;;;;;:::i;77177:45::-;;;;;680:20;;;;;-1:-1:-1;;;;;680:20:0;;;79454:25;;;;;;97420:184;;;;;;:::i;:::-;;:::i;88978:102::-;;;:::i;:::-;;;;;;;:::i;93151:157::-;;;;;;:::i;:::-;;:::i;92752:200::-;;;;;;:::i;:::-;;:::i;96712:181::-;;;;;;:::i;:::-;;:::i;93422:144::-;;;;;;:::i;:::-;;:::i;709:26::-;;;;;-1:-1:-1;;;;;709:26:0;;;88795:132;;;:::i;79953:58::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;79953:58:0;;;;;;;;;82838:1095;;;;;;:::i;:::-;;:::i;94357:314::-;;;;;;:::i;:::-;;:::i;77517:61::-;;;;;78085:32;;;;;;78395:25;;;;;;77622:42;;;;;77715:41;;;;;81235:1225;;;;;;:::i;:::-;;:::i;77427:37::-;;;;;79590:35;;;;;;79140:38;;;;;;78326:31;;;;;;93900:82;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;;;;;;;;;93958:16:::1;:14;:16::i;:::-;93900:82::o:0;95212:470::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;95333:4:::1;95315:15;:22;:47;;;;95358:4;95341:14;:21;95315:47;95311:162;;;95398:14;::::0;95414:13:::1;::::0;95386:75:::1;::::0;::::1;::::0;;::::1;::::0;::::1;2886:25:1::0;;;;2927:18;;;2920:34;2970:18;;;2963:34;;;3013:18;;;3006:34;;;2858:19;;95386:75:0::1;2657:389:1::0;95311:162:0::1;95515:14;::::0;95531:13:::1;::::0;95490:98:::1;::::0;;2886:25:1;;;2942:2;2927:18;;2920:34;;;;2970:18;;2963:34;;;3028:2;3013:18;;3006:34;;;95490:98:0::1;::::0;2873:3:1;2858:19;95490:98:0::1;;;;;;;95601:14;:32:::0;;;;95644:13:::1;:30:::0;95212:470::o;2109:151::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044: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;95781:172::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;95882:16:::1;::::0;95865:43:::1;::::0;;10955:25:1;;;11011:2;10996:18;;10989:34;;;95865:43:0::1;::::0;10928:18:1;95865:43:0::1;;;;;;;95919:16;:26:::0;95781:172::o;96470:151::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;96564:10:::1;::::0;96547:36:::1;::::0;;10955:25:1;;;11011:2;10996:18;;10989:34;;;96547:36:0::1;::::0;10928:18:1;96547:36:0::1;;;;;;;96594:10;:19:::0;96470:151::o;92330:160::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;11236:2:1;18522:34:0::1;::::0;::::1;11218:21:1::0;11275:2;11255:18;;;11248:30;11314:12;11294:18;;;11287:40;11344:18;;18522:34:0::1;11034:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;92446:36:::3;92465:8;92475:6;92446:18;:36::i;:::-;-1:-1:-1::0;;18615:1:0::1;18606:6;:10:::0;92330:160::o;85148:2513::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;11236:2:1;18522:34:0;;;11218:21:1;11275:2;11255:18;;;11248:30;11314:12;11294:18;;;11287:40;11344:18;;18522:34:0;11034:334:1;18522:34:0;18578:1;18569:10;;85235:9:::1;85230:2424;85254:7;85250:1;:11;85230:2424;;;85283:18;85304:15;:13;:15::i;:::-;85385:20;::::0;85336:30:::1;85369:37:::0;;;:15:::1;:37;::::0;;;;85427:21:::1;::::0;::::1;::::0;85283:36;;-1:-1:-1;85369:37:0;85427:26;;:88:::1;;;85499:16;;85475:7;:21;;;:40;;;;:::i;:::-;85457:15;:58;85427:88;85423:135;;;85536:7;;;;;85423:135;85574:22;85612:9;;85599:10;;:22;;;;:::i;:::-;85574:47:::0;-1:-1:-1;85642:19:0;85638:66:::1;;85682:7;;;;;;85638:66;85743:23;::::0;::::1;::::0;85720:20:::1;::::0;85743:46:::1;::::0;85778:10;85743:34:::1;:46::i;:::-;85720:69;;85948:14;85933:12;:29;85929:1675;;;85983:22;::::0;::::1;:39:::0;;;86041:20:::1;86064:35;86008:14:::0;86088:10;86064:23:::1;:35::i;:::-;86041:58;;86146:12;86120:22;;:38;;;;;;;:::i;:::-;;;;;;;;86204:12;86177:7;:23;;;:39;;;;;;;:::i;:::-;;;;;;;;86251:14;86237:10;;:28;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;86290:13:0::1;::::0;:17;86286:251:::1;;86332:20;86355:40;86381:13;;86355:14;:25;;:40;;;;:::i;:::-;86436:13;::::0;86332:63;;-1:-1:-1;86418:46:0::1;::::0;-1:-1:-1;;;;;86418:4:0::1;:17:::0;::::1;::::0;86436:13:::1;86332:63:::0;86418:17:::1;:46::i;:::-;86487:30;86505:12:::0;86487:30;::::1;:::i;:::-;;;86309:228;86286:251;86575:12;::::0;::::1;::::0;86557:47:::1;::::0;-1:-1:-1;;;;;86557:4:0::1;:17:::0;::::1;::::0;86575:12:::1;86589:14:::0;86557:17:::1;:47::i;:::-;86679:10:::0;;86691:12:::1;::::0;::::1;::::0;86735:21:::1;::::0;::::1;::::0;86630:145:::1;::::0;;3832:25:1;;;-1:-1:-1;;;;;86691:12:0;;::::1;3888:2:1::0;3873:18;;3866:83;3965:18;;;3958:34;;;4023:2;4008:18;;4001:34;;;4066:3;4051:19;;4044:35;86630:145:0;::::1;::::0;;;;3819:3:1;86630:145:0;;::::1;86794:7;;;;;;;;85929:1675;86886:22;::::0;::::1;:37:::0;;;86968:23:::1;::::0;::::1;::::0;86942:22:::1;:49:::0;;:22:::1;::::0;:49:::1;::::0;86968:23;;86942:49:::1;:::i;:::-;::::0;;;-1:-1:-1;;87036:1:0::1;87010:23;::::0;::::1;:27:::0;;;87058:10:::1;:26:::0;;87072:12;;87036:1;87058:26:::1;::::0;87072:12;;87058:26:::1;:::i;:::-;::::0;;;-1:-1:-1;;87109:13:0::1;::::0;:17;87105:247:::1;;87151:20;87174:38;87198:13;;87174:12;:23;;:38;;;;:::i;:::-;87253:13;::::0;87151:61;;-1:-1:-1;87235:46:0::1;::::0;-1:-1:-1;;;;;87235:4:0::1;:17:::0;::::1;::::0;87253:13:::1;87151:61:::0;87235:17:::1;:46::i;:::-;87304:28;87320:12:::0;87304:28;::::1;:::i;:::-;;;87128:224;87105:247;87390:12;::::0;::::1;::::0;87372:45:::1;::::0;-1:-1:-1;;;;;87372:4:0::1;:17:::0;::::1;::::0;87390:12:::1;87404::::0;87372:17:::1;:45::i;:::-;87483:10:::0;;87495:12:::1;::::0;::::1;::::0;87509:23:::1;::::0;::::1;::::0;87548:21:::1;::::0;::::1;::::0;87443:145:::1;::::0;;3832:25:1;;;-1:-1:-1;;;;;87495:12:0;;::::1;3888:2:1::0;3873:18;;3866:83;3965:18;;;3958:34;4023:2;4008:18;;4001:34;;;4066:3;4051:19;;4044:35;87443:145:0::1;::::0;3819:3:1;3804:19;87443:145:0::1;;;;;;;87620:20;:22:::0;;;:20:::1;:22;::::0;::::1;:::i;:::-;;;;;;85268:2386;;;;85263:3;;;;;:::i;:::-;;;;85230:2424;;18592:1;-1:-1:-1::0;18615:1:0;18606:6;:10;85148:2513::o;94025:70::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;94077:10:::1;:8;:10::i;94788:288::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;-1:-1:-1;;;;;94875:30:0;::::1;94871:87;;94929:17;;;;;;;;;;;;;;94871:87;94995:13;::::0;94975:50:::1;::::0;;-1:-1:-1;;;;;94995:13:0;;::::1;12260:34:1::0;;12330:15;;;12325:2;12310:18;;12303:43;94975:50:0::1;::::0;12172:18:1;94975:50:0::1;;;;;;;95038:13;:30:::0;;;::::1;-1:-1:-1::0;;;;;95038:30:0;;;::::1;::::0;;;::::1;::::0;;94788:288::o;87983:743::-;88029:7;88053:10;;88067:1;88053:15;88049:59;;;-1:-1:-1;88092:4:0;;87983:743::o;88049:59::-;88120:19;88142:16;:14;:16::i;:::-;88173:11;:18;88120:38;;-1:-1:-1;88169:97:0;;88220:10;;:34;;88242:11;88220:21;:34::i;:::-;88213:41;;;87983:743;:::o;88169:97::-;88278:18;88320:21;;88299:10;;:43;;;;:::i;:::-;88278:64;;88358:9;88353:314;88377:11;:18;88373:22;;88353:314;;;88417:16;88436:11;88448:1;88436:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;88496:23;;;:13;:23;;;;;;88465:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88436:14;-1:-1:-1;88465:54:0;88559:29;88436:14;88559:19;:29::i;:::-;88534:54;;;88617:38;88639:8;:15;;;88617:10;:21;;:38;;;;:::i;:::-;88603:52;;;;:::i;:::-;;;88402:265;;;88397:3;;;;;:::i;:::-;;;;88353:314;;;-1:-1:-1;88684:34:0;:10;88706:11;88684:21;:34::i;:::-;88677:41;;;;87983:743;:::o;84055:965::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;11236:2:1;18522:34:0;;;11218:21:1;11275:2;11255:18;;;11248:30;11314:12;11294:18;;;11287:40;11344:18;;18522:34:0;11034:334:1;18522:34:0;18578:1;18569:10;;84134:18:::1;84155:15;:13;:15::i;:::-;84134:36;;84188:9;84183:830;84207:7;84203:1;:11;84183:830;;;84281:17;::::0;84236:29:::1;84268:31:::0;;;:12:::1;:31;::::0;;;;84320:21:::1;::::0;::::1;::::0;:26;;:87:::1;;;84392:15;;84368:7;:21;;;:39;;;;:::i;:::-;84350:15;:57;84320:87;84316:134;;;84428:7;;;;;84316:134;84489:23;::::0;::::1;::::0;84466:20:::1;::::0;84489:46:::1;::::0;84524:10;84489:34:::1;:46::i;:::-;84466:69;;84575:12;84552:7;:20;;:35;;;;84625:7;:23;;;84602:19;;:46;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;84677:23:0::1;::::0;::::1;::::0;84663:10:::1;:37:::0;;:10:::1;::::0;:37:::1;::::0;84677:23;;84663:37:::1;:::i;:::-;::::0;;;-1:-1:-1;;84732:12:0::1;::::0;::::1;::::0;84715:44:::1;::::0;;;;-1:-1:-1;;;;;84732:12:0;;::::1;84715:44;::::0;::::1;12720:74:1::0;12810:18;;;12803:34;;;84715:11:0::1;:16:::0;;::::1;::::0;::::1;::::0;12693:18:1;;84715:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;84814:10:0;;84826:12:::1;::::0;::::1;::::0;84840:23:::1;::::0;::::1;::::0;84865:20:::1;::::0;::::1;::::0;84887:21:::1;::::0;::::1;::::0;84781:142:::1;::::0;;3832:25:1;;;-1:-1:-1;;;;;84826:12:0;;::::1;3888:2:1::0;3873:18;;3866:83;3965:18;;;3958:34;;;;4023:2;4008:18;;4001:34;4066:3;4051:19;;4044:35;84781:142:0;::::1;::::0;-1:-1:-1;84781:142:0;;;;3819:3:1;84781:142:0;;-1:-1:-1;84781:142:0::1;84966:1;84940:23;::::0;::::1;:27:::0;;;84982:17:::1;:19:::0;;;::::1;::::0;::::1;:::i;:::-;;;;;;84221:792;;84216:3;;;;;:::i;:::-;;;;84183:830;;;;84123:897;-1:-1:-1::0;18615:1:0;18606:6;:10;84055:965::o;94137:86::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;94197:18:::1;:16;:18::i;96983:228::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;97080:5:::1;97065:12;:20;97061:143;;;97125:11;::::0;97107:44:::1;::::0;;10955:25:1;;;11011:2;10996:18;;10989:34;;;97107:44:0::1;::::0;10928:18:1;97107:44:0::1;;;;;;;97166:11;:26:::0;;;97061:143:::1;96983:228:::0;:::o;96112:276::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;96229:15:::1;::::0;96261:16:::1;::::0;96216:78:::1;::::0;;2886:25:1;;;2942:2;2927:18;;2920:34;;;2970:18;;2963:34;3028:2;3013:18;;3006:34;;;96216:78:0::1;::::0;2873:3:1;2858:19;96216:78:0::1;;;;;;;96305:15;:31:::0;;;;96347:16:::1;:33:::0;96112:276::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;;;13358:34:1;1980:4:0;13408:18:1;;;13401:43;1942:9:0;1987:7;;;13460:18:1;;;13453:107;-1:-1:-1;;;;;1942:9:0;;;;:17;;13270: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;79681:28::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;79681:28:0;:::o;93794:66::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;93844:8:::1;:6;:8::i;97420:184::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;97543:4:::1;-1:-1:-1::0;;;;;97526:22:0::1;:5;-1:-1:-1::0;;;;;97526:22:0::1;;;97518:31;;;::::0;::::1;;97560:36;::::0;;;;-1:-1:-1;;;;;12738:55:1;;;97560:36:0::1;::::0;::::1;12720:74:1::0;12810:18;;;12803:34;;;97560:21:0;::::1;::::0;::::1;::::0;12693:18:1;;97560:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;97420:184:::0;;;:::o;88978:102::-;89025:16;89061:11;89054:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88978:102;:::o;93151:157::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;11236:2:1;18522:34:0::1;::::0;::::1;11218:21:1::0;11275:2;11255:18;;;11248:30;11314:12;11294:18;;;11287:40;11344:18;;18522:34:0::1;11034:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;93268:32:::3;93283:8;93293:6;93268:14;:32::i;92752:200::-:0;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;11236:2:1;18522:34:0::1;::::0;::::1;11218:21:1::0;11275:2;11255:18;;;11248:30;11314:12;11294:18;;;11287:40;11344:18;;18522:34:0::1;11034:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;92892:52:::3;92912:8;92922:6;92930:13;92892:19;:52::i;:::-;-1:-1:-1::0;;18615:1:0::1;18606:6;:10:::0;-1:-1:-1;92752:200:0:o;96712:181::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;96816:15:::1;::::0;96794:51:::1;::::0;;10955:25:1;;;11011:2;10996:18;;10989:34;;;96794:51:0::1;::::0;10928:18:1;96794:51:0::1;;;;;;;96856:15;:29:::0;96712:181::o;93422:144::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;18530:6:::1;;18540:1;18530:11;18522:34;;;::::0;-1:-1:-1;;;18522:34:0;;11236:2:1;18522:34:0::1;::::0;::::1;11218:21:1::0;11275:2;11255:18;;;11248:30;11314:12;11294:18;;;11287:40;11344:18;;18522:34:0::1;11034:334:1::0;18522:34:0::1;18578:1;18569:10:::0;;24917:7;;;;25086:56:::2;;;25122:8;;;;;;;;;;;;;;25086:56;93533:25:::3;93548:9;93533:14;:25::i;88795:132::-:0;88842:7;88897:22;;88869:11;-1:-1:-1;;;;;88869:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;;;;:::i;:::-;88862:57;;88795:132;:::o;82838:1095::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;11236:2:1;18522:34:0;;;11218:21:1;11275:2;11255:18;;;11248:30;11314:12;11294:18;;;11287:40;11344:18;;18522:34:0;11034:334:1;18522:34:0;18578:1;18569:10;;-1:-1:-1;;;;;82933:20:0;::::1;82929:77;;82977:17;;;;;;;;;;;;;;82929:77;83053:11;:18:::0;83049:828:::1;;83093:18;83114:15;:13;:15::i;:::-;83093:36:::0;-1:-1:-1;83144:20:0::1;83167:29;:6:::0;83093:36;83167:17:::1;:29::i;:::-;83144:52:::0;-1:-1:-1;83211:37:0::1;-1:-1:-1::0;;;;;83211:4:0::1;:17;83229:4:::0;83144:52;83211:17:::1;:37::i;:::-;83277:12;83263:10;;:26;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;83309:65:0::1;::::0;;83327:1:::1;3832:25:1::0;;-1:-1:-1;;;;;3893:55:1;;3888:2;3873:18;;3866:83;3965:18;;;3958:34;;;4023:2;4008:18;;4001:34;;;83358:15:0::1;4066:3:1::0;4051:19;;4044:35;83309:65:0::1;::::0;3819:3:1;3804:19;83309:65:0::1;;;;;;;83078:308;;83049:828;;;83508:22;::::0;;83455:34:::1;83492:39:::0;;;:15:::1;:39;::::0;;;;;83508:22;83565:24:::1;83508:22:::0;83565:24:::1;:::i;:::-;::::0;;;-1:-1:-1;83548:41:0;;83604:16:::1;::::0;::::1;:23:::0;;;::::1;-1:-1:-1::0;;;;;83604:23:0;::::1;;::::0;;83642:27:::1;::::0;::::1;:36:::0;;;83721:15:::1;83693:25;::::0;::::1;:43:::0;83753:22:::1;:32:::0;;83642:36;;83753:22;-1:-1:-1;;83753:32:0::1;::::0;83642:36;;83753:32:::1;:::i;:::-;::::0;;;-1:-1:-1;;83824:14:0;;83805:60:::1;::::0;;14892:25:1;;;83840:10:0::1;15009:2:1::0;14994:18;;14987:43;-1:-1:-1;;;;;15066:15:1;;15046:18;;;15039:43;15113:2;15098:18;;15091:34;;;83805:60:0;::::1;::::0;;;;14879:3:1;83805:60:0;;::::1;83392:485;83049:828;83889:36;::::0;;;;83906:10:::1;83889:36;::::0;::::1;12720:74:1::0;12810:18;;;12803:34;;;83889:11:0::1;-1:-1:-1::0;;;;;83889:16:0::1;::::0;::::1;::::0;12693:18:1;;83889:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;18615:1:0;18606:6;:10;-1:-1:-1;;;;82838:1095:0:o;94357:314::-;1025:33;1038:10;1050:7;;;;1025:12;:33::i;:::-;1017:58;;;;-1:-1:-1;;;1017:58:0;;10246:2:1;1017:58:0;;;10228:21:1;10285:2;10265:18;;;10258:30;-1:-1:-1;;;10304:18:1;;;10297:42;10356:18;;1017:58:0;10044:336:1;1017:58:0;94449:4:::1;94440:6;:13;:30;;;;94466:4;94457:6;:13;94440:30;94436:121;;;94519:17;::::0;;94494:51:::1;::::0;::::1;::::0;;;;::::1;10955:25:1::0;10996:18;;;10989:34;;;10928:18;;94494:51:0::1;10781:248:1::0;94436:121:0::1;94598:17;::::0;94574:50:::1;::::0;;10955:25:1;;;11011:2;10996:18;;10989:34;;;94574:50:0::1;::::0;10928:18:1;94574:50:0::1;;;;;;;94637:17;:26:::0;94357:314::o;81235:1225::-;18530:6;;18540:1;18530:11;18522:34;;;;-1:-1:-1;;;18522:34:0;;11236:2:1;18522:34:0;;;11218:21:1;11275:2;11255:18;;;11248:30;11314:12;11294:18;;;11287:40;11344:18;;18522:34:0;11034:334:1;18522:34:0;18578:1;18569:10;;25019:15;;;;;;;25333:71:::1;;;25376:16;;;;;;;;;;;;;;25333:71;-1:-1:-1::0;;;;;81349:20:0;::::2;81345:77;;81393:17;;;;;;;;;;;;;;81345:77;81447:16;;81438:6;:25;81434:113;;;81510:16;::::0;81487:48:::2;::::0;::::2;::::0;;::::2;::::0;::::2;10955:25:1::0;;;;10996:18;;;10989:34;;;10928:18;;81487:48:0::2;10781:248:1::0;81434:113:0::2;81594:11;:18:::0;81590:794:::2;;81634:18;81655:15;:13;:15::i;:::-;81634:36:::0;-1:-1:-1;81685:20:0::2;81708:29;:6:::0;81634:36;81708:17:::2;:29::i;:::-;81752:36;::::0;;;;-1:-1:-1;;;;;12738:55:1;;;81752:36:0::2;::::0;::::2;12720:74:1::0;12810:18;;;12803:34;;;81685:52:0;;-1:-1:-1;81752:11:0::2;:16:::0;;::::2;::::0;::::2;::::0;12693:18:1;;81752:36:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;81817:6;81803:10;;:20;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;81843:62:0::2;::::0;;81858:1:::2;3832:25:1::0;;-1:-1:-1;;;;;3893:55:1;;3888:2;3873:18;;3866:83;3965:18;;;3958:34;;;4023:2;4008:18;;4001:34;;;81889:15:0::2;4066:3:1::0;4051:19;;4044:35;81843:62:0::2;::::0;3819:3:1;3804:19;81843:62:0::2;;;;;;;81619:298;;81590:794;;;82032:19;::::0;;81984:32:::2;82019:33:::0;;;:12:::2;:33;::::0;;;;;82032:19;82085:21:::2;82032:19:::0;82085:21:::2;:::i;:::-;::::0;;;-1:-1:-1;82069:37:0;;82121:15:::2;::::0;::::2;:22:::0;;;::::2;-1:-1:-1::0;;;;;82121:22:0;::::2;;::::0;;82158:26:::2;::::0;::::2;:35:::0;;;82235:15:::2;82208:24;::::0;::::2;:42:::0;82267:19:::2;:29:::0;;82158:35;;82267:19;-1:-1:-1;;82267:29:0::2;::::0;82158:35;;82267:29:::2;:::i;:::-;::::0;;;-1:-1:-1;;82332:13:0;;82316:56:::2;::::0;;14892:25:1;;;82347:10:0::2;15009:2:1::0;14994:18;;14987:43;-1:-1:-1;;;;;15066:15:1;;15046:18;;;15039:43;15113:2;15098:18;;15091:34;;;82316:56:0;::::2;::::0;;;;14879:3:1;82316:56:0;;::::2;81923:461;81590:794;82396:56;-1:-1:-1::0;;;;;82396:4:0::2;:21;82418:10;82438:4;82445:6:::0;82396:21:::2;:56::i;1105:546::-:0;1226:9;;1192:4;;-1:-1:-1;;;;;1226:9:0;1548:27;;;;;:77;;-1:-1:-1;1579:46:0;;;;;-1:-1:-1;;;;;13376:15:1;;;1579:46:0;;;13358:34:1;1606:4:0;13408:18:1;;;13401:43;13492:66;13480:79;;13460:18;;;13453:107;1579:12:0;;;;;13270:18:1;;1579:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1547:96;;;-1:-1:-1;1638:5:0;;-1:-1:-1;;;;;1630:13:0;;;1638:5;;1630:13;1547:96;1540:103;;;1105:546;;;;;:::o;25735:151::-;25019:15;;;;;;;25333:71;;;25376:16;;;;;;;;;;;;;;25333:71;25811:15:::1;:22:::0;;;::::1;;;::::0;;25849:29:::1;::::0;25867:10:::1;1340:74:1::0;;25849:29:0::1;::::0;1328:2:1;1313:18;25849:29:0::1;;;;;;;;25735:151::o:0;97802:2381::-;97883:15;97901:22;97913:9;97901:11;:22::i;:::-;97883:40;;98037:11;;98026:8;:22;98022:97;;;98072:35;;;;;;;;10955:25:1;;;10996:18;;;10989:34;;;10928:18;;98072:35:0;10781:248:1;98022:97:0;98131:33;98167:24;;;:13;:24;;;;;98223:23;;:28;;;;:121;;-1:-1:-1;98293:23:0;;98268:49;;;;;-1:-1:-1;;;;;98329:14:0;98268:76;;;:12;:24;;;;;;:49;;;;160:25:1;;;148:2;133:18;;14:177;98268:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;98268:76:0;;;98223:121;98205:248;;;98417:23;;98371:70;;;;;-1:-1:-1;;;;;98371:12:0;:20;;;;:70;;98400:14;;98371:70;;-1:-1:-1;;;;;12738:55:1;;;;12720:74;;12825:2;12810:18;;12803:34;12708:2;12693:18;;12546:297;98371:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98205:248;98490:36;;;;;;;;160:25:1;;;98466:19:0;;98490:6;-1:-1:-1;;;;;98490:25:0;;;;133:18:1;;98490:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98465:61;;;98539:21;98563:58;98603:17;;98563:28;98579:11;98563:4;:15;;:28;;;;:::i;:::-;:39;;:58::i;:::-;98539:82;;98647:13;98634:9;;:26;;;;;;;:::i;:::-;;;;-1:-1:-1;;98689:10:0;;98677:9;;:22;98673:133;;;98741:10;;98765:13;98753:9;;:25;;;;:::i;:::-;98723:71;;;;;;;;16238:25:1;;;;16279:18;;;16272:34;16322:18;;;16315:34;;;16211:18;;98723:71:0;16036:319:1;98673:133:0;98816:23;98868:13;98842:12;:23;;;:39;;;;:::i;:::-;98816:65;-1:-1:-1;98894:56:0;-1:-1:-1;;;;;98894:4:0;:16;98919:14;98936:13;98894:16;:56::i;:::-;98963:64;;:::i;:::-;99062:6;-1:-1:-1;;;;;99040:28:0;;;99079:15;;;:27;;;99137:23;;99117:17;;;:43;99191:15;;99171:17;;;:35;99217:22;;;:40;;;99295:23;;;;99268:24;;;:50;76786:40;99329:17;;;76786:40;99329:31;;-1:-1:-1;99371:13:0;;;:20;;;99419:1;99402:14;;;:18;;;99431:14;;;:30;;;99472:18;;;:34;;;-1:-1:-1;;;;;99537:4:0;99517:24;;:17;;;:24;99621:35;;;;;:14;:27;;;;;;:35;;99371:6;;99621:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99554:102;;99693:15;99667:12;:23;;:41;;;;99742:4;99719:12;:19;;;:27;;;;;;;:::i;:::-;;;;-1:-1:-1;;99797:23:0;;;;99757:29;;;:64;;:29;;:64;;99797:23;;99757:64;:::i;:::-;;;;-1:-1:-1;;99864:23:0;;;;99832:21;:56;;:21;;:56;;99864:23;;99832:56;:::i;:::-;;;;-1:-1:-1;;99905:23:0;;99901:153;;99976:24;;;;99950:50;;100015:11;:27;;;;;;;99950:23;100015:27;;;;;;;;;99901:153;100095:23;;100141;;;;;100071:104;;;19215:25:1;;;19271:2;19256:18;;19249:34;;;;19299:18;;19292:34;;;19357:2;19342:18;;19335:34;;;19385:19;;;19378:35;19444:3;19429:19;;19422:35;;;100071:104:0;;19202:3:1;19187:19;100071:104:0;;;;;;;97872:2311;;;;;;;97802:2381;;:::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;;19670:2:1;23018:35:0;;;19652:21:1;19709:2;19689:18;;;19682:30;19748:17;19728:18;;;19721:45;19783:18;;23018:35:0;19468: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;89403:1545::-;89474:19;89495:18;89541:34;89590:38;89642:6;-1:-1:-1;;;;;89642:24:0;;89667:9;89642:35;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;89642:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89736:42;;;;;89757:20;89736:42;;;160:25:1;89526:151:0;;-1:-1:-1;89526:151:0;-1:-1:-1;89699:17:0;;;;-1:-1:-1;;;;;89736:5:0;:20;;;;133:18:1;;89736:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89698:80;;;;89795:9;89808:1;89795:14;:27;;;;89813:9;89795:27;89791:68;;;89839:8;;;89791:68;89893:5;:12;;;89875:15;:30;89871:1070;;;90019:41;;;;;;;;160:25:1;;;89941:19:0;;;;-1:-1:-1;;;;;90019:6:0;:30;;;;133:18:1;;90019:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89922:138;;;;;90081:13;90098:1;90081:18;90077:86;;;90127:20;;;;;;;;;;;;;;90077:86;90206:13;90192:11;:27;:61;;90252:1;90192:61;;;90222:27;90236:13;90222:11;:27;:::i;:::-;90179:74;;89907:359;;89871:1070;;;90322:8;;90332:10;;90305:38;;;;;;;;10955:25:1;;;;10996:18;;;10989:34;90287:15:0;;90305:6;-1:-1:-1;;;;;90305:16:0;;;;10928:18:1;;90305:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90409:10;;90379:41;;;;;90287:56;;-1:-1:-1;90358:18:0;;-1:-1:-1;;;;;90379:6:0;:18;;;;:41;;90398:9;;90379:41;;10955:25:1;;;11011:2;10996:18;;10989:34;10943:2;10928:18;;10781:248;90379:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90358:62;;90435:49;90487:356;;;;;;;;90573:15;90558:5;:12;;;:30;;;;:::i;:::-;90487:356;;;;90626:30;:7;90645:10;90626:18;:30::i;:::-;90487:356;;;;90688:9;90487:356;;;;90736:6;:18;;;90487:356;;;;90786:6;-1:-1:-1;;;;;90786:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;90487:356;;90892:37;;;;;;23772:13:1;;90892:37:0;;;23754:32:1;23842:4;23830:17;;23824:24;23802:20;;;23795:54;23893:17;;;23887:24;23865:20;;;23858:54;23968:4;23956:17;;23950:24;23928:20;;;23921:54;24031:4;24019:17;;24013:24;23991:20;;;23984:54;90435:408:0;;-1:-1:-1;90892:15:0;;:28;;23726:19:1;;90892:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90864:65;;-1:-1:-1;90864:65:0;-1:-1:-1;;;;89871:1070:0;89515:1433;;;;89403:1545;;;:::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;103035:548:0;103125:4;103112:9;;:17;;;;;;;:::i;:::-;;;;-1:-1:-1;;103168:10:0;;103156:9;;:22;103152:115;;;103220:10;;103244:4;103232:9;;:16;;;;:::i;103152:115::-;103279:33;103315:24;;;:13;:24;;;;;103352:46;-1:-1:-1;;;;;103358:4:0;103352:23;103384:6;103393:4;103352:23;:46::i;:::-;103430:23;;103409:51;;;;;;;;10955:25:1;;;;10996:18;;;10989:34;;;103409:6:0;-1:-1:-1;;;;;103409:20:0;;;;10928:18:1;;103409:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103498:4;103471:12;:23;;;:31;;;;;;;:::i;:::-;;;;-1:-1:-1;;103545:23:0;;103520:55;;;16238:25:1;;;16294:2;16279:18;;16272:34;;;;16322:18;;16315:34;;;103520:55:0;;16226:2:1;16211:18;103520:55:0;;;;;;;103101:482;103035:548;;:::o;100191:2836::-;100294:33;100330:24;;;:13;:24;;;;;100371:23;;:28;;:58;;;100425:4;100403:12;:19;;;:26;100371:58;:106;;;;100455:21;;100433:11;:44;100371:106;100367:201;;;100532:23;;100501:55;;;;;;;100521:9;;100501:55;;10955:25:1;;;11011:2;10996:18;;10989:34;10943:2;10928:18;;10781:248;100367:201:0;100609:23;;100584:49;;;;;-1:-1:-1;;;;;100645:14:0;100584:76;;;:12;:24;;;;;;:49;;;;160:25:1;;;148:2;133:18;;14:177;100584:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;100584:76:0;;100580:179;;100723:23;;100677:70;;;;;-1:-1:-1;;;;;100677:12:0;:20;;;;:70;;100706:14;;100677:70;;-1:-1:-1;;;;;12738:55:1;;;;12720:74;;12825:2;12810:18;;12803:34;12708:2;12693:18;;12546:297;100677:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100580:179;100771:26;100808:23;100843:19;100867:6;-1:-1:-1;;;;;100867:25:0;;100893:9;100867:36;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;100867:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100842:61;;;100930:12;:19;;;100922:4;:27;100918:289;;;100987:12;:23;;;100966:44;;100918:289;;;101100:17;;101064:54;;:26;:4;101078:11;101064:13;:26::i;:::-;:35;;:54::i;:::-;101043:75;;101177:18;101151:12;:23;;;:44;;;;:::i;:::-;101133:62;;100918:289;101219:61;-1:-1:-1;;;;;101225:4:0;101219:23;101251:14;101268:11;101219:23;:61::i;:::-;101293:64;;:::i;:::-;101392:6;-1:-1:-1;;;;;101370:28:0;;;101409:15;;;:27;;;101467:23;;101447:17;;;:43;101521:15;;101501:17;;;:35;101547:22;;;:40;;;101625:23;;;;101598:24;;;:50;76786:40;101659:17;;;76786:40;101659:31;;-1:-1:-1;101701:13:0;;;:20;;;101749:1;101732:14;;;:18;;;101778:17;101761:14;;;:34;101806:18;;;:32;;;-1:-1:-1;;;;;101869:4:0;101849:24;;:17;;;:24;101953:36;;;;;:14;:28;;;;;;:36;;101701:6;;101953:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101886:103;;102000:19;102022:13;:23;;;102000:45;;102084:15;102058:12;:23;;:41;;;;102133:4;102110:12;:19;;;:27;;;;;;;:::i;:::-;;;;;;;;102189:11;102149:12;:29;;;:52;;;;;;;:::i;:::-;;;;-1:-1:-1;;102218:19:0;;;;102214:601;;102295:1;102263:12;:29;;;:33;102259:414;;;102342:29;;;;102428:14;;102317;;102410:33;;102342:29;;102410:17;:33::i;:::-;102487:13;;102391:52;;-1:-1:-1;102462:49:0;;-1:-1:-1;;;;;102468:4:0;102462:24;;;102487:13;102391:52;102462:24;:49::i;:::-;102545:17;102554:8;102545:6;:17;:::i;:::-;102530:10;;:33;;;;;;;:::i;:::-;;;;-1:-1:-1;102259:414:0;;-1:-1:-1;;;102259:414:0;;102627:12;:29;;;102626:30;;;:::i;:::-;102604:10;;:53;;;;;;;:::i;:::-;;;;-1:-1:-1;;102259:414:0;102713:1;102687:27;;;102729:29;;;:33;102777:26;102793:9;102777:15;:26::i;:::-;102859:11;102827:21;;:44;;;;;;;:::i;:::-;;;;;;;;102895:18;102882:9;;:31;;;;;;;:::i;:::-;;;;-1:-1:-1;;102956:23:0;;102931:88;;;24878:25:1;;;24934:2;24919:18;;24912:34;;;;24962:18;;24955:34;;;25020:2;25005:18;;24998:34;;;25063:3;25048:19;;25041:35;;;102931:88:0;;24865:3:1;24850:19;102931:88:0;;;;;;;100283:2744;;;;;;;100191:2836;;;:::o;103912:2421::-;103990:9;103985:2341;104009:10;:17;104005:1;:21;103985:2341;;;104048:33;104084:13;:28;104098:10;104109:1;104098:13;;;;;;;;:::i;:::-;;;;;;;104084:28;;;;;;;;;;;104048:64;;104133:12;:19;;;104156:1;104133:24;104129:89;;;104185:17;;;;;;;;;;;;;;104129:89;104305:23;;104275:54;;;;;104234:38;;-1:-1:-1;;;;;104275:12:0;:29;;;;:54;;;;160:25:1;;;148:2;133:18;;14:177;104275:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104234:95;-1:-1:-1;104363:34:0;104348:11;:49;;;;;;;;:::i;:::-;;104344:166;;104442:10;104453:1;104442:13;;;;;;;;:::i;:::-;;;;;;;104457:12;:23;;;104482:11;104425:69;;;;;;;;;;;;;:::i;104344:166::-;104545:19;104583:21;104623:6;-1:-1:-1;;;;;104623:30:0;;104654:10;104665:1;104654:13;;;;;;;;:::i;:::-;;;;;;;104623:45;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;104623:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104526:142;;;;;104689:13;104706:1;104689:18;104685:86;;;104735:20;;;;;;;;;;;;;;104685:86;104787:17;104824:11;104808:13;:27;104807:97;;104903:1;104807:97;;;104880:19;;;;104839:61;;104840:27;104854:13;104840:11;:27;:::i;104839:61::-;104787:117;-1:-1:-1;104925:13:0;;104921:77;;104973:9;104959:10;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;;104921:77:0;105027:12;:23;;;105014:9;;:36;;;;;;;:::i;:::-;;;;-1:-1:-1;;105071:29:0;;;;105103:1;-1:-1:-1;105067:750:0;;;105150:29;;;;105125:14;105238;105234:179;;105306:14;;105288:33;;:6;;:17;:33::i;:::-;105369:13;;105277:44;;-1:-1:-1;105344:49:0;;-1:-1:-1;;;;;105350:4:0;105344:24;;;105369:13;105277:44;105344:24;:49::i;:::-;105446:17;105455:8;105446:6;:17;:::i;:::-;105431:10;;:33;;;;;;;:::i;:::-;;;;;;;;105515:6;105483:21;;:39;;;;;;;:::i;:::-;;;;-1:-1:-1;;105545:21:0;;105569:1;-1:-1:-1;105541:167:0;;;105618:21;;105617:22;;;:::i;:::-;105595:10;;:45;;;;;;;:::i;:::-;;;;-1:-1:-1;;105687:1:0;105663:21;:25;105541:167;105106:617;;105067:750;;;105771:12;:29;;;105770:30;;;:::i;:::-;105748:10;;:53;;;;;;;:::i;:::-;;;;-1:-1:-1;;105067:750:0;105838:257;105869:10;105880:1;105869:13;;;;;;;;:::i;:::-;;;;;;;105901:12;:23;;;105943:12;:19;;;105981:12;:23;;;106023:12;:29;;;106071:9;105838:257;;;;;;;;;;19215:25:1;;;19271:2;19256:18;;19249:34;;;;19314:2;19299:18;;19292:34;;;;19357:2;19342:18;;19335:34;19400:3;19385:19;;19378:35;19444:3;19429:19;;19422:35;19202:3;19187:19;;18930:533;105838:257:0;;;;;;;;106138:1;106112:27;;;106154:29;;;:33;;;106202:19;;;:23;;;-1:-1:-1;106240:23:0;;:27;106300:13;;106284:30;;106300:10;;106311:1;;106300:13;;;;;;:::i;:::-;;;;;;;106284:15;:30::i;:::-;104033:2293;;;;;104028:3;;;;;:::i;:::-;;;;103985:2341;;;;103912:2421;:::o;19964:1604::-;20108:12;20239:4;20233:11;20384:66;20365:17;20358:93;20499:4;20495:1;20476:17;20472:25;20465:39;20584:2;20579;20560:17;20556:26;20549:38;20665:6;20660:2;20641:17;20637:26;20630:42;21479:2;21476:1;21471:3;21452:17;21449:1;21442:5;21435;21430:52;20993:16;20986:24;20980:2;20962:16;20959:24;20955:1;20951;20945:8;20942:15;20938:46;20935:76;20732:765;20721:776;;;21528:7;21520:40;;;;-1:-1:-1;;;21520:40:0;;26506:2:1;21520:40:0;;;26488:21:1;26545:2;26525:18;;;26518:30;26584:22;26564:18;;;26557:50;26624:18;;21520:40:0;26304:344:1;21520:40:0;20097:1471;19964:1604;;;;:::o;91070:913::-;91133:15;91176:34;91225:38;91277:6;-1:-1:-1;;;;;91277:24:0;;91302:9;91277:35;;;;;;;;;;;;;160:25:1;;148:2;133:18;;14:177;91277:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91363:42;;;;;91384:20;91363:42;;;160:25:1;91161:151:0;;-1:-1:-1;91161:151:0;-1:-1:-1;91326:17:0;;;;-1:-1:-1;;;;;91363:5:0;:20;;;;133:18:1;;91363:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91325:80;;;;91422:9;91435:1;91422:14;:27;;;;91440:9;91422:27;91418:101;;;91473:34;;;;;;;;26821:25:1;;;26889:14;;26882:22;26862:18;;;26855:50;26794:18;;91473:34:0;26653:258:1;91418:101:0;91531:49;91583:334;;;;;;;;91665:15;91650:5;:12;;;:30;;;;:::i;:::-;91583:334;;;;91714:32;91734:6;:11;;;91714:5;:8;;;:19;;:32;;;;:::i;:::-;91583:334;;;;91774:9;91583:334;;;;91818:6;:18;;;91583:334;;;;91864:6;-1:-1:-1;;;;;91864:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;91583:334;;91945:30;;;;;;23772:13:1;;91945:30:0;;;23754:32:1;23842:4;23830:17;;23824:24;23802:20;;;23795:54;23893:17;;;23887:24;23865:20;;;23858:54;23968:4;23956:17;;23950:24;23928:20;;;23921:54;24031:4;24019:17;;24013:24;23991:20;;;23984:54;91531:386:0;;-1:-1:-1;91945:15:0;;:21;;23726:19:1;;91945:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91930:45;91070:913;-1:-1:-1;;;;;;;;91070:913: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;;27366:2:1;24510:34:0;;;27348:21:1;27405:2;27385:18;;;27378:30;27444:16;27424:18;;;27417:44;27478:18;;24510:34:0;27164:338:1;11405:552:0;11618:9;;;11752:19;;11745:27;11777:9;;11791;;;11788:16;;11774:31;11741:65;11731:123;;11837:1;11834;11827:12;11731:123;11920:19;;11405:552;-1:-1:-1;;11405:552:0:o;11965:771::-;12176:9;;;12310:19;;12303:27;12335:9;;12349;;;12346:16;;12332:31;12299:65;12289:123;;12395:1;12392;12385:12;12289:123;12715:1;12701:11;12697:1;12694;12690:9;12686:27;12682:35;12677:1;12670:9;12663:17;12659:59;12654:64;;11965:771;;;;;:::o;10699:160::-;10762:7;10789:19;10798:1;10801;10474:4;10789:8;:19::i;106341:372::-;106437:11;:18;106405:9;;106466:123;106482:1;106478;:5;106466:123;;;106522:11;106534:1;106522:14;;;;;;;;:::i;:::-;;;;;;;;;106509:9;:27;106505:73;;;106557:5;;106505:73;106485:3;;;;:::i;:::-;;;;106466:123;;;106609:1;106605;:5;106601:105;;;106644:11;106656:5;106660:1;106656;:5;:::i;:::-;106644:18;;;;;;;;:::i;:::-;;;;;;;;;106627:11;106639:1;106627:14;;;;;;;;:::i;:::-;;;;;;;;;;:35;106677:11;:17;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;106601:105;106394:319;;106341:372;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;378:248:1:-;446:6;454;507:2;495:9;486:7;482:23;478:32;475:52;;;523:1;520;513:12;475:52;-1:-1:-1;;546:23:1;;;616:2;601:18;;;588:32;;-1:-1:-1;378:248:1:o;631:154::-;-1:-1:-1;;;;;710:5:1;706:54;699:5;696:65;686:93;;775:1;772;765:12;790:247;849:6;902:2;890:9;881:7;877:23;873:32;870:52;;;918:1;915;908:12;870:52;957:9;944:23;976:31;1001:5;976:31;:::i;1425:180::-;1484:6;1537:2;1525:9;1516:7;1512:23;1508:32;1505:52;;;1553:1;1550;1543:12;1505:52;-1:-1:-1;1576:23:1;;1425:180;-1:-1:-1;1425:180:1:o;4090:184::-;4142:77;4139:1;4132:88;4239:4;4236:1;4229:15;4263:4;4260:1;4253:15;4279:141;4361:1;4354:5;4351:12;4341:46;;4367:18;;:::i;:::-;4396;;4279:141::o;4425:209::-;4571:2;4556:18;;4583:45;4560:9;4610:6;4583:45;:::i;4639:456::-;4716:6;4724;4732;4785:2;4773:9;4764:7;4760:23;4756:32;4753:52;;;4801:1;4798;4791:12;4753:52;4840:9;4827:23;4859:31;4884:5;4859:31;:::i;:::-;4909:5;-1:-1:-1;4966:2:1;4951:18;;4938:32;4979:33;4938:32;4979:33;:::i;:::-;4639:456;;5031:7;;-1:-1:-1;;;5085:2:1;5070:18;;;;5057:32;;4639:456::o;5100:632::-;5271:2;5323:21;;;5393:13;;5296:18;;;5415:22;;;5242:4;;5271:2;5494:15;;;;5468:2;5453:18;;;5242:4;5537:169;5551:6;5548:1;5545:13;5537:169;;;5612:13;;5600:26;;5681:15;;;;5646:12;;;;5573:1;5566:9;5537:169;;;-1:-1:-1;5723:3:1;;5100:632;-1:-1:-1;;;;;;5100:632:1:o;5737:316::-;5814:6;5822;5830;5883:2;5871:9;5862:7;5858:23;5854:32;5851:52;;;5899:1;5896;5889:12;5851:52;-1:-1:-1;;5922:23:1;;;5992:2;5977:18;;5964:32;;-1:-1:-1;6043:2:1;6028:18;;;6015:32;;5737:316;-1:-1:-1;5737:316:1:o;6058:184::-;6110:77;6107:1;6100:88;6207:4;6204:1;6197:15;6231:4;6228:1;6221:15;6247:253;6319:2;6313:9;6361:4;6349:17;;6396:18;6381:34;;6417:22;;;6378:62;6375:88;;;6443:18;;:::i;:::-;6479:2;6472:22;6247:253;:::o;6505:255::-;6577:2;6571:9;6619:6;6607:19;;6656:18;6641:34;;6677:22;;;6638:62;6635:88;;;6703:18;;:::i;6765:252::-;6837:2;6831:9;6879:3;6867:16;;6913:18;6898:34;;6934:22;;;6895:62;6892:88;;;6960:18;;:::i;7022:334::-;7093:2;7087:9;7149:2;7139:13;;7154:66;7135:86;7123:99;;7252:18;7237:34;;7273:22;;;7234:62;7231:88;;;7299:18;;:::i;:::-;7335:2;7328:22;7022:334;;-1:-1:-1;7022:334:1:o;7361:183::-;7421:4;7454:18;7446:6;7443:30;7440:56;;;7476:18;;:::i;:::-;-1:-1:-1;7521:1:1;7517:14;7533:4;7513:25;;7361:183::o;7549:891::-;7633:6;7664:2;7707;7695:9;7686:7;7682:23;7678:32;7675:52;;;7723:1;7720;7713:12;7675:52;7763:9;7750:23;7796:18;7788:6;7785:30;7782:50;;;7828:1;7825;7818:12;7782:50;7851:22;;7904:4;7896:13;;7892:27;-1:-1:-1;7882:55:1;;7933:1;7930;7923:12;7882:55;7969:2;7956:16;7992:60;8008:43;8048:2;8008:43;:::i;:::-;7992:60;:::i;:::-;8086:15;;;8168:1;8164:10;;;;8156:19;;8152:28;;;8117:12;;;;8192:19;;;8189:39;;;8224:1;8221;8214:12;8189:39;8248:11;;;;8268:142;8284:6;8279:3;8276:15;8268:142;;;8350:17;;8338:30;;8301:12;;;;8388;;;;8268:142;;;8429:5;7549:891;-1:-1:-1;;;;;;;7549:891:1:o;8693:315::-;8761:6;8769;8822:2;8810:9;8801:7;8797:23;8793:32;8790:52;;;8838:1;8835;8828:12;8790:52;8877:9;8864:23;8896:31;8921:5;8896:31;:::i;:::-;8946:5;8998:2;8983:18;;;;8970:32;;-1:-1:-1;;;8693:315:1:o;11373:184::-;11425:77;11422:1;11415:88;11522:4;11519:1;11512:15;11546:4;11543:1;11536:15;11562:128;11602:3;11633:1;11629:6;11626:1;11623:13;11620:39;;;11639:18;;:::i;:::-;-1:-1:-1;11675:9:1;;11562:128::o;11695:125::-;11735:4;11763:1;11760;11757:8;11754:34;;;11768:18;;:::i;:::-;-1:-1:-1;11805:9:1;;11695:125::o;11825:195::-;11864:3;11895:66;11888:5;11885:77;11882:103;;;11965:18;;:::i;:::-;-1:-1:-1;12012:1:1;12001:13;;11825:195::o;12357:184::-;12409:77;12406:1;12399:88;12506:4;12503:1;12496:15;12530:4;12527:1;12520:15;13571:164;13647:13;;13696;;13689:21;13679:32;;13669:60;;13725:1;13722;13715:12;13669:60;13571:164;;;:::o;13740:202::-;13807:6;13860:2;13848:9;13839:7;13835:23;13831:32;13828:52;;;13876:1;13873;13866:12;13828:52;13899:37;13926:9;13899:37;:::i;13947:184::-;14017:6;14070:2;14058:9;14049:7;14045:23;14041:32;14038:52;;;14086:1;14083;14076:12;14038:52;-1:-1:-1;14109:16:1;;13947:184;-1:-1:-1;13947:184:1:o;15387:138::-;15466:13;;15488:31;15466:13;15488:31;:::i;15530:251::-;15600:6;15653:2;15641:9;15632:7;15628:23;15624:32;15621:52;;;15669:1;15666;15659:12;15621:52;15701:9;15695:16;15720:31;15745:5;15720:31;:::i;15786:245::-;15865:6;15873;15926:2;15914:9;15905:7;15901:23;15897:32;15894:52;;;15942:1;15939;15932:12;15894:52;-1:-1:-1;;15965:16:1;;16021:2;16006:18;;;16000:25;15965:16;;16000:25;;-1:-1:-1;15786:245:1:o;16360:1182::-;16609:13;;-1:-1:-1;;;;;1115:54:1;1103:67;;16570:3;16555:19;;16690:4;16682:6;16678:17;16672:24;16665:4;16654:9;16650:20;16643:54;16753:4;16745:6;16741:17;16735:24;16728:4;16717:9;16713:20;16706:54;16816:4;16808:6;16804:17;16798:24;16791:4;16780:9;16776:20;16769:54;16879:4;16871:6;16867:17;16861:24;16854:4;16843:9;16839:20;16832:54;16942:4;16934:6;16930:17;16924:24;16917:4;16906:9;16902:20;16895:54;16996:4;16988:6;16984:17;16978:24;17011:62;17067:4;17056:9;17052:20;17038:12;17011:62;:::i;:::-;-1:-1:-1;17129:4:1;17117:17;;;17111:24;17089:20;;;17082:54;17155:6;17203:15;;;17197:22;17177:18;;;17170:50;17239:6;17287:15;;;17281:22;17261:18;;;17254:50;17323:6;17371:15;;;17365:22;17345:18;;;17338:50;17407:6;17450:15;;;17444:22;-1:-1:-1;;;;;1115:54:1;17517:18;;;;1103:67;;;;16360:1182;:::o;17547:1006::-;17648:6;17679:3;17723:2;17711:9;17702:7;17698:23;17694:32;17691:52;;;17739:1;17736;17729:12;17691:52;17772:2;17766:9;17802:15;;;;17847:18;17832:34;;17868:22;;;17829:62;17826:88;;;17894:18;;:::i;:::-;17934:10;17930:2;17923:22;17973:9;17967:16;17954:29;;17992:31;18017:5;17992:31;:::i;:::-;18047:5;18039:6;18032:21;18107:2;18096:9;18092:18;18086:25;18081:2;18073:6;18069:15;18062:50;18145:49;18190:2;18179:9;18175:18;18145:49;:::i;:::-;18140:2;18132:6;18128:15;18121:74;18249:2;18238:9;18234:18;18228:25;18223:2;18215:6;18211:15;18204:50;18309:3;18298:9;18294:19;18288:26;18282:3;18274:6;18270:16;18263:52;18370:3;18359:9;18355:19;18349:26;18343:3;18335:6;18331:16;18324:52;18431:3;18420:9;18416:19;18410:26;18404:3;18396:6;18392:16;18385:52;18471:50;18516:3;18505:9;18501:19;18471:50;:::i;:::-;18465:3;18453:16;;18446:76;18457:6;17547:1006;-1:-1:-1;;;;17547:1006:1:o;18558:367::-;18597:3;18632:1;18629;18625:9;18741:1;18673:66;18669:74;18666:1;18662:82;18657:2;18650:10;18646:99;18643:125;;;18748:18;;:::i;:::-;18867:1;18799:66;18795:74;18792:1;18788:82;18784:2;18780:91;18777:117;;;18874:18;;:::i;:::-;-1:-1:-1;;18910:9:1;;18558:367::o;19812:1144::-;19881:5;19929:4;19917:9;19912:3;19908:19;19904:30;19901:50;;;19947:1;19944;19937:12;19901:50;19969:22;;:::i;:::-;19960:31;;20020:9;20014:16;20007:5;20000:31;20050:2;20105;20094:9;20090:18;20084:25;20079:2;20072:5;20068:14;20061:49;20163:2;20152:9;20148:18;20142:25;20137:2;20130:5;20126:14;20119:49;20200:46;20242:2;20231:9;20227:18;20200:46;:::i;:::-;20195:2;20188:5;20184:14;20177:70;20291:3;20280:9;20276:19;20270:26;20319:18;20311:6;20308:30;20305:50;;;20351:1;20348;20341:12;20305:50;20374:22;;20427:4;20419:13;;20415:23;-1:-1:-1;20405:51:1;;20452:1;20449;20442:12;20405:51;20481:2;20475:9;20504:60;20520:43;20560:2;20520:43;:::i;20504:60::-;20598:15;;;20680:1;20676:10;;;;20668:19;;20664:28;;;20629:12;;;;20704:15;;;20701:35;;;20732:1;20729;20722:12;20701:35;20756:11;;;;20776:135;20792:6;20787:3;20784:15;20776:135;;;20858:10;;20846:23;;20809:12;;;;20889;;;;20776:135;;;20938:3;20927:15;;20920:30;-1:-1:-1;20931:5:1;;19812:1144;-1:-1:-1;;;;;19812:1144:1:o;20961:1107::-;21093:6;21101;21145:9;21136:7;21132:23;21175:3;21171:2;21167:12;21164:32;;;21192:1;21189;21182:12;21164:32;21215:6;21241:2;21237;21233:11;21230:31;;;21257:1;21254;21247:12;21230:31;21283:22;;:::i;:::-;21270:35;;21334:9;21328:16;21321:5;21314:31;21398:2;21387:9;21383:18;21377:25;21372:2;21365:5;21361:14;21354:49;21456:2;21445:9;21441:18;21435:25;21430:2;21423:5;21419:14;21412:49;21514:2;21503:9;21499:18;21493:25;21488:2;21481:5;21477:14;21470:49;21573:3;21562:9;21558:19;21552:26;21546:3;21539:5;21535:15;21528:51;21633:3;21622:9;21618:19;21612:26;21606:3;21599:5;21595:15;21588:51;21693:3;21682:9;21678:19;21672:26;21666:3;21659:5;21655:15;21648:51;21753:3;21742:9;21738:19;21732:26;21726:3;21719:5;21715:15;21708:51;21778:3;21834:2;21823:9;21819:18;21813:25;21808:2;21801:5;21797:14;21790:49;;21858:5;21848:15;;21907:2;21896:9;21892:18;21886:25;21872:39;;;21934:18;21926:6;21923:30;21920:50;;;21966:1;21963;21956:12;21920:50;21989:73;22054:7;22045:6;22034:9;22030:22;21989:73;:::i;:::-;21979:83;;;20961:1107;;;;;:::o;22073:263::-;22149:6;22157;22210:2;22198:9;22189:7;22185:23;22181:32;22178:52;;;22226:1;22223;22216:12;22178:52;22255:9;22249:16;22239:26;;22284:46;22326:2;22315:9;22311:18;22284:46;:::i;:::-;22274:56;;22073:263;;;;;:::o;22341:306::-;22429:6;22437;22445;22498:2;22486:9;22477:7;22473:23;22469:32;22466:52;;;22514:1;22511;22504:12;22466:52;22543:9;22537:16;22527:26;;22593:2;22582:9;22578:18;22572:25;22562:35;;22637:2;22626:9;22622:18;22616:25;22606:35;;22341:306;;;;;:::o;22652:870::-;22760:6;22813:3;22801:9;22792:7;22788:23;22784:33;22781:53;;;22830:1;22827;22820:12;22781:53;22856:22;;:::i;:::-;22907:9;22901:16;22894:5;22887:31;22971:2;22960:9;22956:18;22950:25;22945:2;22938:5;22934:14;22927:49;23029:2;23018:9;23014:18;23008:25;23003:2;22996:5;22992:14;22985:49;23087:2;23076:9;23072:18;23066:25;23061:2;23054:5;23050:14;23043:49;23146:3;23135:9;23131:19;23125:26;23119:3;23112:5;23108:15;23101:51;23206:3;23195:9;23191:19;23185:26;23179:3;23172:5;23168:15;23161:51;23266:3;23255:9;23251:19;23245:26;23239:3;23232:5;23228:15;23221:51;23326:3;23315:9;23311:19;23305:26;23299:3;23292:5;23288:15;23281:51;23351:3;23407:2;23396:9;23392:18;23386:25;23381:2;23374:5;23370:14;23363:49;;23431:3;23487:2;23476:9;23472:18;23466:25;23461:2;23454:5;23450:14;23443:49;;23511:5;23501:15;;;22652:870;;;;:::o;24049:369::-;24088:4;24124:1;24121;24117:9;24233:1;24165:66;24161:74;24158:1;24154:82;24149:2;24142:10;24138:99;24135:125;;;24240:18;;:::i;:::-;24359:1;24291:66;24287:74;24284:1;24280:82;24276:2;24272:91;24269:117;;;24366:18;;:::i;:::-;-1:-1:-1;;24403:9:1;;24049:369::o;24423:191::-;24458:3;24489:66;24482:5;24479:77;24476:103;;;24559:18;;:::i;:::-;-1:-1:-1;24599:1:1;24595:13;;24423:191::o;25087:278::-;25175:6;25228:2;25216:9;25207:7;25203:23;25199:32;25196:52;;;25244:1;25241;25234:12;25196:52;25276:9;25270:16;25315:1;25308:5;25305:12;25295:40;;25331:1;25328;25321:12;25370:391;25588:25;;;25644:2;25629:18;;25622:34;;;25576:2;25561:18;;25686:1;25675:13;;25665:47;;25692:18;;:::i;:::-;25748:6;25743:2;25732:9;25728:18;25721:34;25370:391;;;;;;:::o;27507:184::-;27559:77;27556:1;27549:88;27656:4;27653:1;27646:15;27680:4;27677:1;27670:15

Swarm Source

ipfs://94a13c130193f4f9aaf52bdc605a2127f17c2ed30c49455f1cd761639ae2dd0d
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.