Contract 0x2e2153fd13459eba1f277ab9acd624f045d676ce

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x7ca4b89852a7dfc9c80daf7018f62407d7760f46fdb0486f4e64562c2d0a9f4cTransfer386365692022-11-16 19:41:2411 days 16 hrs ago0xa7e21065ba8b95457c67a42f57ec366d2333a49f IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00004756
0xd17a43a90f16229009730946ae3989d590022d43ccad35b6a6db6dd42fefbb54Transfer371692242022-11-11 9:25:5017 days 3 hrs ago0x9e37f47b63a40417a3638efb6e2aa5deca74f5a8 IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00002428
0xe8e8e801f2d30dbea7b641c160776b53111200766e3fef61493211fc779c2447Transfer371684992022-11-11 9:22:4117 days 3 hrs ago0x9e37f47b63a40417a3638efb6e2aa5deca74f5a8 IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00002317
0xc7aa6d89748d8b7ecfb715b174252b33f8f62843152fffefbc580d967db3ada1Transfer371684262022-11-11 9:22:2217 days 3 hrs ago0x9e37f47b63a40417a3638efb6e2aa5deca74f5a8 IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00002681
0x7df73199b4adfaadc953d54cd9cde183f2992ab78070e084d7bf236361adac09Transfer370586242022-11-11 0:36:1717 days 11 hrs ago0xf860a6e476e7c17491f4e278fc7df84a185d771a IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00002906
0x4fc7812ca6acda7ffbcbf9923953dbb3f5d8802f4c4551ef05cafe6d876d7dfaComplete Withdra...333520962022-10-28 13:49:3030 days 22 hrs ago0xc32e449e67a00f2b07022cf3ac60e8989d24c611 IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00002389
0xfd098cf970472c18eecc631f0a8b01863aa37e71bcbe24d33640f0041c7f467fComplete Withdra...327471482022-10-26 12:40:4832 days 23 hrs ago0xf73d395c1a024860bfa06e449f37120c348760fa IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00003951
0x0ce5152c364f3ddf753e8ae240dc1e498486f5eba71aa490161655741125cad7Complete Withdra...326778432022-10-26 7:29:5133 days 5 hrs ago0x14ab9f431b7d25fcad366ec9511dce38e229745c IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00005476
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853fRoll To Next Pos...326235892022-10-26 2:57:5933 days 9 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.0029041
0x8c037378859ff81be5ad267830730e398ac1327bee56e9261487047ba6c85a9aCommit And Close326235562022-10-26 2:57:4733 days 9 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00228429
0x89c5d0b1619bb224e39d00af5012a90b3ed3d364d3ff7006ad2cac3e677b3207Roll To Next Pos...326125582022-10-26 1:57:4533 days 10 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00289215
0x9bc7e289cd4243d5e6bdfa2cb5f55033fa385243fca7e840eaa2108a4359de42Commit And Close326125262022-10-26 1:57:3333 days 10 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00225437
0x5a308a7d96c058c9205a6ec801779634bfb42511bd6a43f17ee7dfadb58c77c1Roll To Next Pos...326035412022-10-26 0:57:3133 days 11 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00295375
0xbfc21ca80b429cc3c75aeaaf99885679afdba44974d00fa9eb89d37def3e961cCommit And Close326035122022-10-26 0:57:1933 days 11 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00238329
0x8f3b73bca1ab75cbd888e059c33baa45636947acbcde78ea05cf27f197c4c650Roll To Next Pos...325945902022-10-25 23:57:1733 days 12 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00303971
0x78e7028271799aaa45e5357336028788712195e88c4068e8f9ac407590b03d28Commit And Close325945432022-10-25 23:57:0533 days 12 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00260885
0xb6a9f22f1f27786ab5ac9b1113a79b5f327229792c31c84e6ff18c593bd4657aRoll To Next Pos...325864092022-10-25 22:57:0333 days 13 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00313797
0xe6bd666daae83dcd2ba3ed835fbd3417cc33c37d0ece8fb8d3fc035b8fda8f43Commit And Close325863892022-10-25 22:56:5133 days 13 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00277662
0x7219cc6a08e3997679a3b3ce09eff1a7792c092105eb0af3c0190bd62f25fb36Roll To Next Pos...325769782022-10-25 21:56:4933 days 14 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00308044
0xe51e28d0119bc282321d743ba655cd2b14fa9b11d16ab5c33f0d08d55b0b2baaCommit And Close325769442022-10-25 21:56:3733 days 14 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00265566
0x3a5fe4f217d8cb2d854e075df4cbcf3efdd89cea4c0a87c0217a6cf45b395fbcRoll To Next Pos...325664292022-10-25 20:56:3533 days 15 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00329804
0x5d33cd2d37b60d8dec90662907776692e06678990582f752a6c6a6060f0aebeeCommit And Close325663992022-10-25 20:56:2333 days 15 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00307513
0x5b56ce6d30a50cbfadccc5beeab05c4d8f39b6e57abe18fc050ce669ef77d7b0Roll To Next Pos...325546882022-10-25 19:56:2033 days 16 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00332396
0x4eda475c881a4d7bd20f18851dc81bafbcc1ec9e71137fb41f9702d7cd65ffdfCommit And Close325546532022-10-25 19:56:0833 days 16 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00315643
0x203463b86f6309f26d54c55d51ad24f001b24e4e15ecddf526d71632e4f80ba2Roll To Next Pos...325429182022-10-25 18:56:0633 days 17 hrs ago0x003a189d19cd0b26144dece0034d7b9a141a738d IN 0x2e2153fd13459eba1f277ab9acd624f045d676ce0 ETH0.00336013
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x4fc7812ca6acda7ffbcbf9923953dbb3f5d8802f4c4551ef05cafe6d876d7dfa333520962022-10-28 13:49:3030 days 22 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0xff970a61a04b1ca14834a43f5de4533ebddb5cc80 ETH
0xfd098cf970472c18eecc631f0a8b01863aa37e71bcbe24d33640f0041c7f467f327471482022-10-26 12:40:4832 days 23 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0xff970a61a04b1ca14834a43f5de4533ebddb5cc80 ETH
0x0ce5152c364f3ddf753e8ae240dc1e498486f5eba71aa490161655741125cad7326778432022-10-26 7:29:5133 days 5 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0xff970a61a04b1ca14834a43f5de4533ebddb5cc80 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x391e6d4e3aa6e05dfaff05b8c5a52fe2762b92b40 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x35d33c8f9d78214409709ea9c1d031a8f5b22daf0 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x35d33c8f9d78214409709ea9c1d031a8f5b22daf0 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x16c457fc0f5d5981574ed2baed81c625bd91b6330 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x6e5f70e345b4afd271491290e026dd3d34cbb9f20 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x489da242a948d1978673fef8836740c11732ec0b0 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x7ff6132ef2abf89b6ec509947eb2c1ee9da29f260 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x1addd80e6039594ee970e5872d247bf0414c89030 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0xff970a61a04b1ca14834a43f5de4533ebddb5cc80 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x391e6d4e3aa6e05dfaff05b8c5a52fe2762b92b40 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x1addd80e6039594ee970e5872d247bf0414c89030 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0xb0b49c3c76f92d629278fde6ad48d3ea877d2c0d0 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x391e6d4e3aa6e05dfaff05b8c5a52fe2762b92b40 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x35d33c8f9d78214409709ea9c1d031a8f5b22daf0 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x35d33c8f9d78214409709ea9c1d031a8f5b22daf0 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x16c457fc0f5d5981574ed2baed81c625bd91b6330 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x6e5f70e345b4afd271491290e026dd3d34cbb9f20 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x489da242a948d1978673fef8836740c11732ec0b0 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x7ff6132ef2abf89b6ec509947eb2c1ee9da29f260 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x1addd80e6039594ee970e5872d247bf0414c89030 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0xff970a61a04b1ca14834a43f5de4533ebddb5cc80 ETH
0x9d64664737c1aca3f078b757b0540e0a097dd3f21c9b6bfaed15ad8ed969853f326235892022-10-26 2:57:5933 days 9 hrs ago 0x2e2153fd13459eba1f277ab9acd624f045d676ce 0x6e5f70e345b4afd271491290e026dd3d34cbb9f20 ETH
[ Download CSV Export 
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
GlpUSDCVault

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 888 runs

Other Settings:
default evmVersion
File 1 of 32 : GlpUSDCVault.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                              #@@@@@@@@@@@@&,                               //
//                      [email protected]@@@@   [email protected]@@@@@@@@@@@@@@@@@@*                        //
//                  %@@@,    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@                    //
//               @@@@     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                 //
//             @@@@     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@               //
//           *@@@#    [email protected]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@             //
//          *@@@%    &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@            //
//          @@@@     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@           //
//          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@           //
//                                                                            //
//          (@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@,           //
//          (@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@,           //
//                                                                            //
//               @@   @@     @   @      @       @   @       @                 //
//               @@   @@    @@@ @@@    @[email protected]     @@@ @@@     @@@                //
//                &@@@@   @@  @@  @@ @@ ^ @@  @@  @@  @@   @@@                //
//                                                                            //
//          @@@@@      @@@%    *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@           //
//          @@@@@      @@@@    %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@           //
//          [email protected]@@@      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@            //
//            @@@@@  &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@             //
//                (&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(                 //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { VaultStorage } from "../storage/VaultStorage.sol";
import { BaseVault } from "../base/BaseVault.sol";
import { ISwapRouter } from "../interfaces/ISwapRouter.sol";
import { IStakingRewards } from "../interfaces/IStakingRewards.sol";
import { IPoolCommitter } from "../interfaces/IPoolCommitter.sol";
import { IGlpManager } from "../interfaces/IGlpManager.sol";
import { IRewardRouterV2 } from "../interfaces/IRewardRouterV2.sol";
import { IGlpPricing } from "../interfaces/IGlpPricing.sol";
import { ITcrPricing } from "../interfaces/ITcrPricing.sol";
import { ITcrStrategy } from "../interfaces/ITcrStrategy.sol";
import { IChainlinkWrapper } from "../interfaces/IChainlinkWrapper.sol";
import { Vault } from "../libraries/Vault.sol";
import { ShareMath } from "../libraries/ShareMath.sol";
import { L2Encoder } from "../lib/L2Encoder.sol";

/// @title Delta Minimised GLP-USDC Vault
/// @author 0xtoki
contract GlpUSDCVault is BaseVault, VaultStorage {
    using SafeERC20 for IERC20;

    /************************************************
     *  STORAGE
     ***********************************************/

    /// @notice the timestamp migration window
    uint256 public migrationTimestamp;

    /// @notice slippage amount for closing a glp position
    uint256 public glpCloseSlippage;

    /// @notice tcr staking active
    bool public hedgeStakingActive;

    /// @notice contract library used for pricing glp
    address public glpPricing;

    /// @notice contract library address used for pricing the tcr hedges
    address public hedgePricing;

    /// @notice tcr emission strategy
    address public tcrStrategy;

    /// @notice glp reward router
    uint256 public swapSlippage;

    /// @notice GLP_MANAGER is used for managing GMX Liquidity
    /// https://github.com/gmx-io/gmx-contracts/blob/master/contracts/core/GlpManager.sol
    address public GLP_MANAGER;

    /// @notice GLP_REWARD_ROUTER is used for minting, burning and handling GLP and rewards earnt
    /// https://github.com/gmx-io/gmx-contracts/blob/master/contracts/staking/RewardRouterV2.sol
    address public GLP_REWARD_ROUTER;

    /// @notice tcr token
    address public TCR = 0xA72159FC390f0E3C6D415e658264c7c4051E9b87;

    /// @notice wrapper for the chainlink oracle used for swap pricing
    IChainlinkWrapper public chainlinkOracle;

    /// @notice shortMint commit type for minting shorts in Tracer Finance
    IPoolCommitter.CommitType public shortMint = IPoolCommitter.CommitType.ShortMint;

    /// @notice shortBurn commit type for burning shorts in Tracer Finance
    IPoolCommitter.CommitType public shortBurn = IPoolCommitter.CommitType.ShortBurn;

    /// @notice Tracer Finance encoder used for encoding paramsfor short burns/mints
    /// https://github.com/tracer-protocol/perpetual-pools-contracts/blob/pools-v2/contracts/implementation/L2Encoder.sol
    L2Encoder public encoder;

    /// @notice UniV3 router for calling swaps
    /// https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol
    ISwapRouter public router;

    /// @notice hedge actions for rebalancing
    enum HedgeAction {
        increase,
        decrease,
        flat
    }

    /// @dev MAX INT
    uint256 public constant MAX_INT = 2**256 - 1;

    /************************************************
     *  EVENTS
     ***********************************************/

    event UpdatePricePerShare(uint104 _round, uint256 _pricePerShare);

    event CommitAndClose(
        uint104 _round,
        uint256 _timestamp,
        uint256 _profitAmount,
        uint256 _glpAllocation,
        uint256 _sbtcAllocation,
        uint256 _sethAllocation
    );

    event RollToNextPosition(uint256 _lockedInStrategy, uint256 _queuedWithdrawAmount);

    event TracerOpen(uint256 _sbtcAllocation, uint256 _sethAllocation);

    event TracerClose(uint256 _sbtcAllocation, uint256 _sethAllocation);

    event InitiateVaultMigration(uint256 _timestamp, uint256 _migrationActiveTimestamp);

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

    /**
     * @notice Consttuctor
     * @param _asset is the underlying asset deposited to the vault
     * @param _feeRecipient is the recipient of the fees generated by the vault
     * @param _keeper the vault keeper
     * @param _managementFee vault management fee
     * @param _performanceFee performance fee
     * @param _depositFee deposit fee
     * @param _vaultParams vault params
     * @param _glpRouter glp reward router
     * @param _glpManager glp manager
     * @param _uniswapRouter uniV3 router
     */
    constructor(
        address _asset,
        address _feeRecipient,
        address _keeper,
        uint256 _managementFee,
        uint256 _performanceFee,
        uint256 _depositFee,
        uint104 _vaultRound,
        Vault.VaultParams memory _vaultParams,
        address _glpRouter,
        address _glpManager,
        address _uniswapRouter
    )
        BaseVault(
            _asset,
            _feeRecipient,
            _keeper,
            _managementFee,
            _performanceFee,
            _depositFee,
            _vaultRound,
            _vaultParams,
            "glpUSDC",
            "glpUSDC"
        )
    {
        require(_glpManager != address(0), "!_glpManager");
        require(_glpRouter != address(0), "!_glpRouter");
        require(_uniswapRouter != address(0), "!_uniswapRouter");
        require(_vaultParams.hedgePricing != address(0), "!hedgePricing");
        require(_vaultParams.glpPricing != address(0), "!glpPricing");

        encoder = new L2Encoder();
        roundPricePerShare[_vaultRound] = ShareMath.pricePerShare(
            totalSupply(),
            IERC20(_vaultParams.asset).balanceOf(address(this)),
            _vaultParams.decimals
        );

        GLP_MANAGER = _glpManager;
        GLP_REWARD_ROUTER = _glpRouter;
        router = ISwapRouter(_uniswapRouter);
        hedgePricing = _vaultParams.hedgePricing;
        glpPricing = _vaultParams.glpPricing;
        hedgeStakingActive = false;
        swapSlippage = 100; // 10%
        glpCloseSlippage = 3; // 0.3%
        migrationTimestamp = MAX_INT;
    }

    /************************************************
     *  VAULT OPERATIONS
     ***********************************************/

    /**
     * @notice Completes a scheduled withdrawal from a past round. Uses finalized pps for the round
     */
    function completeWithdraw() external nonReentrant {
        uint256 withdrawAmount = _completeWithdraw();
        lastQueuedWithdrawAmount = uint128(uint256(lastQueuedWithdrawAmount) - withdrawAmount);
    }

    /**
     * @notice Marks the close of the existing vault round and sets the allocations for the next round.
     * This function will, if required to accomadate the new hedge sizing, close some of the GLP position to USDC.
     * @param nextSbtcAllocation the allocation to sbtc for the next epoch in usdc
     * @param nextSethAllocation the allocation to seth for the next epoch in usdc
     * @param nextGlpAllocation the allocation to glp for the next epoch in usdc
     * @param _settlePositions whether the vault should settle positions this epoch
     * @param _handleTcrEmissions whether the vault should handle the tcr emissions this epoch
     * @return profit the profit amount made from claiming rewards
     */
    function commitAndClose(
        uint112 nextSbtcAllocation,
        uint112 nextSethAllocation,
        uint112 nextGlpAllocation,
        bool _settlePositions,
        bool _handleTcrEmissions
    ) external nonReentrant onlyKeeper returns (uint256) {
        // get the existing glp balance and allocation in USDC
        uint256 glpBal = IERC20(vaultParams.stakedGlp).balanceOf(address(this));
        uint256 existingGlpAllocation = IGlpPricing(glpPricing).glpToUsd(glpBal, false);

        // set next allocations
        strategyState.nextSbtcAllocation = nextSbtcAllocation;
        strategyState.nextSethAllocation = nextSethAllocation;
        strategyState.nextGlpAllocation = nextGlpAllocation;

        vaultState.lastLockedAmount = uint104(lockedInStrategy);
        uint256 profitAmount = 0;

        // unstake tracer hedges and handle emissions
        if (
            (strategyState.activeSbtcAllocation > 0 || strategyState.activeSethAllocation > 0) &&
            hedgeStakingActive &&
            _handleTcrEmissions
        ) {
            profitAmount += collectTcrEmissions();
        }

        // start late withdrawal period
        lateWithdrawPeriod = true;

        // settle glp
        if (_settlePositions) {
            if (existingGlpAllocation > nextGlpAllocation) {
                profitAmount += settleGlpPosition(existingGlpAllocation - nextGlpAllocation);
                strategyState.activeGlpAllocation = nextGlpAllocation;
            } else {
                profitAmount += handleGlpRewards();
            }
        }
        uint256 sEthVal = ITcrPricing(hedgePricing).sEthToUsd(totalSethBalance());
        uint256 sBtcVal = ITcrPricing(hedgePricing).sBtcToUsd(totalSbtcBalance());

        emit CommitAndClose(
            vaultState.round,
            block.timestamp,
            profitAmount,
            IGlpPricing(glpPricing).glpToUsd(glpBal, false),
            sBtcVal,
            sEthVal
        );
        return profitAmount;
    }

    /**
     * @notice Rolls the vault's funds into a new strategy position.
     * Same decimals as `asset` this function should be called immediatly after the short positions have been committed and minted
     */
    function rollToNextPosition() external onlyKeeper nonReentrant {
        // claim short tokens
        claimShorts();
        // stake tracer hedge
        if (hedgeStakingActive) stakeHedges();
        // get the next glp allocation
        uint256 nextGlpAllocation = strategyState.nextGlpAllocation;

        // get the vaults next round params
        (uint256 lockedBalance, uint256 queuedWithdrawAmount) = _rollToNextEpoch(
            uint256(lastQueuedWithdrawAmount),
            uint256(roundQueuedWithdrawalShares[vaultState.round]),
            totalAssets()
        );

        // get new queued withdrawal shares before rollover
        uint256 newQueuedWithdrawShares = uint256(vaultState.queuedWithdrawShares) +
            roundQueuedWithdrawalShares[vaultState.round - 1];

        ShareMath.assertUint128(newQueuedWithdrawShares);

        vaultState.queuedWithdrawShares = uint128(newQueuedWithdrawShares);

        // set globals
        lastQueuedWithdrawAmount = uint128(queuedWithdrawAmount);
        lockedInStrategy = lockedBalance;

        uint256 sbtcAllocation = strategyState.activeSbtcAllocation;
        uint256 sethAllocation = strategyState.activeSethAllocation;
        uint256 existingGlpPosition = IGlpPricing(glpPricing).glpToUsd(
            IERC20(vaultParams.stakedGlp).balanceOf(address(this)),
            false
        );

        uint256 totalUtilised = sbtcAllocation + sethAllocation + nextGlpAllocation + lastQueuedWithdrawAmount;
        require(totalUtilised <= totalAssets(), "TCRGMX: !allocation");

        if (nextGlpAllocation > existingGlpPosition) openGlpPosition(nextGlpAllocation - existingGlpPosition);

        emit RollToNextPosition(lockedInStrategy, lastQueuedWithdrawAmount);
    }

    /**
     * @notice withdraws funds from GMX in GLP, claiming the rewards and executing any swaps. 
     * This is done in the case some capital is needed to open new hedges or cover next round withdrawals.
     * @param glpAllocation value in usdc to be settled in glp
     * @return amount of asset received in profit at the end of the epoch
     */
    function settleGlpPosition(uint256 glpAllocation) internal returns (uint256) {
        // usd to glp at current price
        uint256 glpAmount = IGlpPricing(glpPricing).usdToGlp(glpAllocation, false);

        // subtract 0.3% buffer for onchain mispricing
        glpAmount -= (glpAmount * glpCloseSlippage) / SCALE;

        // burn glp amount
        IRewardRouterV2(GLP_REWARD_ROUTER).unstakeAndRedeemGlp(vaultParams.asset, glpAmount, 0, address(this));

        // handle glp rewards and return profit in usdc, add tcr yield when built
        return handleGlpRewards();
    }

    /**
     * @notice deposits and stakes glpAllocation in GLP
     * @param glpAllocation value in usdc to mint GLP
     */
    function openGlpPosition(uint256 glpAllocation) public onlyKeeper {
        IERC20(vaultParams.asset).safeIncreaseAllowance(GLP_MANAGER, glpAllocation);
        uint256 amountWithSlippage = getSlippageAdjustedAmount(glpAllocation, 10);
        IRewardRouterV2(GLP_REWARD_ROUTER).mintAndStakeGlp(vaultParams.asset, glpAllocation, amountWithSlippage, 0);
    }

    /**
     * @notice uses the allocations passed in or the vault state to queue a rebalance of the tracer hedges
     * @param sbtcAllocation usdc allocation for sbtc
     * @param sethAllocation usdc allocation for seth
     * @param sethAction action to rebalance seth
     * @param sbtcAction action to rebalance sbtc
     */
    function queueHedgeRebalance(
        uint256 sbtcAllocation,
        uint256 sethAllocation,
        HedgeAction sethAction,
        HedgeAction sbtcAction
    ) external onlyKeeper nonReentrant {
        uint256 sEthChange;
        uint256 sBtcChange;
        (, uint256 queuedWithdrawAmount) = getNextLockedQueued();
        uint256 availableBal = IERC20(vaultParams.asset).balanceOf(address(this)) - queuedWithdrawAmount;

        uint256 sEthVal = ITcrPricing(hedgePricing).sEthToUsd(totalSethBalance());
        uint256 sBtcVal = ITcrPricing(hedgePricing).sBtcToUsd(totalSbtcBalance());

        if (sethAction == HedgeAction.increase) {
            require(sethAllocation >= sEthVal, "TCRGMX: !allocation");
            sEthChange = sethAllocation - sEthVal;
            require(availableBal > sEthChange, "TCRGMX: Over allocation");
            strategyState.activeSethAllocation = sethAllocation;
            queueTracerOpen(0, sEthChange);
        } else if (sethAction == HedgeAction.decrease) {
            require(sethAllocation <= sEthVal, "TCRGMX: !allocation");
            sEthChange = sEthVal - sethAllocation;
            uint256 sEthAmount = ITcrPricing(hedgePricing).usdToSeth(sEthChange);
            strategyState.activeSethAllocation = sethAllocation;
            if (hedgeStakingActive) unstakePartialHedges(0, sEthAmount);
            queueTracerClose(0, sEthAmount);
        }

        if (sbtcAction == HedgeAction.increase) {
            require(sbtcAllocation >= sBtcVal, "TCRGMX: !allocation");
            sBtcChange = sbtcAllocation - sBtcVal;
            availableBal = IERC20(vaultParams.asset).balanceOf(address(this)) - queuedWithdrawAmount;
            require(availableBal > sBtcChange, "TCRGMX: Over allocation");
            strategyState.activeSbtcAllocation = sbtcAllocation;
            queueTracerOpen(sBtcChange, 0);
        } else if (sbtcAction == HedgeAction.decrease) {
            require(sbtcAllocation <= sBtcVal, "TCRGMX: !allocation");
            sBtcChange = sBtcVal - sbtcAllocation;
            uint256 sBtcAmount = ITcrPricing(hedgePricing).usdToSbtc(sBtcChange);
            strategyState.activeSbtcAllocation = sbtcAllocation;
            if (hedgeStakingActive) unstakePartialHedges(sBtcAmount, 0);
            queueTracerClose(sBtcAmount, 0);
        }
    }

    /**
     * @notice This function withdraws tracer shorts from staking and queues them for closing on the next rebalance
     * @param sbtcAllocation amount of sbtc tokens to burn
     * @param sethAllocation amount of seth tokens to burn
     */
    function queueTracerClose(uint256 sbtcAllocation, uint256 sethAllocation) public onlyKeeper {
        uint256 ethLeverageindex = strategyState.activeEthLeverageIndex;
        uint256 btcLeverageIndex = strategyState.activeBtcLeverageIndex;
        uint256 sEthBal = IERC20(ethLeverageSets[ethLeverageindex].token).balanceOf(address(this));
        uint256 sBtcBal = IERC20(btcLeverageSets[btcLeverageIndex].token).balanceOf(address(this));
        require(sBtcBal >= sbtcAllocation, "TCRGMX: !available sbtc balance");
        require(sEthBal >= sethAllocation, "TCRGMX: !available seth balance");

        if (sbtcAllocation != 0) {
            IERC20(btcLeverageSets[btcLeverageIndex].token).safeIncreaseAllowance(
                btcLeverageSets[btcLeverageIndex].leveragePool,
                sbtcAllocation
            );
            IPoolCommitter(btcLeverageSets[btcLeverageIndex].poolCommitter).commit(
                encoder.encodeCommitParams(sbtcAllocation, shortBurn, false, false)
            );
        }
        if (sethAllocation != 0) {
            IERC20(ethLeverageSets[ethLeverageindex].token).safeIncreaseAllowance(
                ethLeverageSets[ethLeverageindex].leveragePool,
                sethAllocation
            );
            IPoolCommitter(ethLeverageSets[ethLeverageindex].poolCommitter).commit(
                encoder.encodeCommitParams(sethAllocation, shortBurn, false, false)
            );
        }

        emit TracerClose(sbtcAllocation, sethAllocation);
    }

    /**
     * @notice This function withdraws tracer shorts from staking and queues them for closing on the next rebalance
     * @param sbtcAllocation usdc amount to open in sbtc
     * @param sethAllocation usdc amount to open in seth
     */
    function queueTracerOpen(uint256 sbtcAllocation, uint256 sethAllocation) public onlyKeeper {
        uint256 usdcBal = IERC20(vaultParams.asset).balanceOf(address(this)) - lastQueuedWithdrawAmount;
        require(sethAllocation + sbtcAllocation <= usdcBal, "TCRGMX: !available balance");
        uint256 ethLeverageindex = strategyState.activeEthLeverageIndex;
        uint256 btcLeverageIndex = strategyState.activeBtcLeverageIndex;

        // mint hedges
        if (sbtcAllocation != 0) {
            IERC20(vaultParams.asset).safeIncreaseAllowance(btcLeverageSets[btcLeverageIndex].leveragePool, sbtcAllocation);
            IPoolCommitter(btcLeverageSets[btcLeverageIndex].poolCommitter).commit(
                encoder.encodeCommitParams(sbtcAllocation, shortMint, false, false)
            );
        }
        if (sethAllocation != 0) {
            IERC20(vaultParams.asset).safeIncreaseAllowance(ethLeverageSets[ethLeverageindex].leveragePool, sethAllocation);
            IPoolCommitter(ethLeverageSets[ethLeverageindex].poolCommitter).commit(
                encoder.encodeCommitParams(sethAllocation, shortMint, false, false)
            );
        }
        emit TracerOpen(sbtcAllocation, sethAllocation);
    }

    /**
     * @notice Handle the GLP rewards according to the strategy. Claim esGMX + multiplier points and stake.
     * Claim WETH and swap to USDC paid as profit to the vault
     * @return profit the amount of USDC recieved in exchange for the WETH claimed
     */
    function handleGlpRewards() internal returns (uint256) {
        IRewardRouterV2(GLP_REWARD_ROUTER).handleRewards(true, true, true, true, true, true, false);
        return swapToStable();
    }

    /**
     * @notice Swaps the WETH claimed from the strategy to USDC
     * @return recieved amount of USDC recieved
     */
    function swapToStable() internal returns (uint256) {
        uint256 wethBalance = IERC20(WETH).balanceOf(address(this));
        if (wethBalance > 0) {
            uint256 ethPrice = chainlinkOracle.getCurrentPrice(WETH);
            uint256 minOut = (ethPrice * wethBalance) / 1e30; // USDC decimals convertion
            IERC20(WETH).safeIncreaseAllowance(address(router), wethBalance);
            uint24 poolFee = 500;
            bytes memory route = abi.encodePacked(WETH, poolFee, vaultParams.asset);
            ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
                path: route,
                recipient: address(this),
                deadline: block.timestamp,
                amountIn: wethBalance,
                amountOutMinimum: getSlippageAdjustedAmount(minOut, swapSlippage)
            });
            return router.exactInput(params);
        }
        return 0;
    }

    /**
     * @notice Total asset value in the vault. Valued in USDC. This call will under report assets held in the vault
     * when commits to Tracer Finance are pending
     * @return totalBal the total balance of the assets held
     */
    function totalAssets() public view returns (uint256 totalBal) {
        uint256 usdcBal = IERC20(vaultParams.asset).balanceOf(address(this));
        uint256 glpBal = IERC20(vaultParams.stakedGlp).balanceOf(address(this));
        uint256 sEthBal = totalSethBalance();
        uint256 sBtcBal = totalSbtcBalance();
        totalBal =
            usdcBal +
            IGlpPricing(glpPricing).glpToUsd(glpBal, false) +
            ITcrPricing(hedgePricing).sEthToUsd(sEthBal) +
            ITcrPricing(hedgePricing).sBtcToUsd(sBtcBal);
    }

    /**
     * @notice Returns the total balance of seth held by the vault
     * @return balance of seth
     */
    function totalSethBalance() public view returns (uint256) {
        uint256 sEthBal = IERC20(ethLeverageSets[strategyState.activeEthLeverageIndex].token).balanceOf(address(this));
        if (hedgeStakingActive) {
            return sEthBal + IStakingRewards(vaultParams.sethStake).balanceOf(address(this));
        }
        return sEthBal;
    }

    /**
     * @notice Returns the total balance of sbtc held by the vault
     * @return balance of sbtc
     */
    function totalSbtcBalance() public view returns (uint256) {
        uint256 sBtcBal = IERC20(btcLeverageSets[strategyState.activeBtcLeverageIndex].token).balanceOf(address(this));
        if (hedgeStakingActive) {
            return sBtcBal + IStakingRewards(vaultParams.sbtcStake).balanceOf(address(this));
        }
        return sBtcBal;
    }

    /**
     * @notice Returns a slippage adjusted amount for calculations where slippage is accounted
     * @param amount of the asset
     * @param slippage %
     * @return value of the slippage adjusted amount
     */
    function getSlippageAdjustedAmount(uint256 amount, uint256 slippage) internal view returns (uint256) {
        return (amount * (1 * SCALE - slippage)) / SCALE;
    }

    /**
     * @notice Returns the next locked and withdrawal amount queued
     * @return lockedBalance that is available for use in the strategy next epoch
     * @return queuedWithdrawAmount next withdrawal amount queued
     */
    function getNextLockedQueued() public view returns (uint256 lockedBalance, uint256 queuedWithdrawAmount) {
        (lockedBalance, queuedWithdrawAmount) = previewNextBalances(
            uint256(lastQueuedWithdrawAmount),
            roundQueuedWithdrawalShares[vaultState.round],
            totalAssets()
        );
    }

    /**
     * @notice Sets the active leverage index to be used if configured for a different leverage multiplier
     * @param _btcLeverageSet the index for btc leverage set
     * @param _ethLeverageSet the index for eth leverage set
     */
    function setLeverageSetIndex(uint256 _btcLeverageSet, uint256 _ethLeverageSet) external onlyAdmin {
        require(btcLeverageSets[_btcLeverageSet].poolCommitter != address(0), "TCRGMX: btc leverage set");
        require(ethLeverageSets[_ethLeverageSet].poolCommitter != address(0), "TCRGMX: eth leverage set");
        strategyState.activeBtcLeverageIndex = _btcLeverageSet;
        strategyState.activeEthLeverageIndex = _ethLeverageSet;
    }

    /**
     * @notice Updates the slippage tolerance for swapping rewards to USDC
     * @param _newSlippage the new slippage tolerance
     */
    function updateSwapSlippage(uint256 _newSlippage) external onlyAdmin {
        require(_newSlippage != 0, "TCRGMX: ! _newSlippage is zero");
        swapSlippage = _newSlippage;
    }

    /**
     * @notice Updates the chainlink oracle wrapper implementation
     * @param _chainlinkWrapper the address of the new implementation
     */
    function updateChainlinkWrapper(address _chainlinkWrapper) external onlyAdmin {
        require(_chainlinkWrapper != address(0), "TCRGMX: ! chainlinkWrapper address");
        chainlinkOracle = IChainlinkWrapper(_chainlinkWrapper);
    }

    /**
     * @notice Updates the hedge pricing implementation for Tracer Finance
     * @param _hedgePricing the address of the new implementation
     */
    function updateHedgePricing(address _hedgePricing) external onlyAdmin {
        require(_hedgePricing != address(0), "TCRGMX: ! hedgePricing address");
        hedgePricing = _hedgePricing;
    }

    /**
     * @notice Updates the GLP pricing implementation
     * @param _glpPricing the address of the new implementation
     */
    function updateGlpPricing(address _glpPricing) external onlyAdmin {
        require(_glpPricing != address(0), "TCRGMX: ! glpPricing address");
        glpPricing = _glpPricing;
    }

    /**
     * @notice Updates the seth staking contract address for TCR emissions
     * @param _sethStaking the new staking contract
     */
    function updateSethStaking(address _sethStaking) external onlyAdmin {
        require(_sethStaking != address(0), "TCRGMX: ! seth address");
        vaultParams.sethStake = _sethStaking;
    }

    /**
     * @notice Updates the sbtc staking contract address for TCR emissions
     * @param _sbtcStaking the new staking contract
     */
    function updateSbtcStaking(address _sbtcStaking) external onlyAdmin {
        require(_sbtcStaking != address(0), "TCRGMX: ! sbtc address");
        vaultParams.sbtcStake = _sbtcStaking;
    }

    /**
     * @notice Updates the TCR emissions token strategy for how the vault should handle emissions
     * @param _tcrStrategy the new strategy address
     */
    function setTcrStrategy(address _tcrStrategy) external onlyAdmin {
        tcrStrategy = _tcrStrategy;
    }

    /**
     * @notice Sets the Tracer Finance hedge staking
     * @param _stakingActive the value to set it to
     */
    function setHedgeStakingActive(bool _stakingActive) external onlyAdmin {
        hedgeStakingActive = _stakingActive;
    }

    /**
     * @notice Claims the short tokens from Tracer Finance
     */
    function claimShorts() public onlyKeeper {
        uint256 ethLeverageindex = strategyState.activeEthLeverageIndex;
        uint256 btcLeverageindex = strategyState.activeBtcLeverageIndex;
        IPoolCommitter(ethLeverageSets[ethLeverageindex].poolCommitter).claim(address(this));
        IPoolCommitter(btcLeverageSets[btcLeverageindex].poolCommitter).claim(address(this));
    }

    /**
     * @notice Stakes the short tokens in the emissions contract
     */
    function stakeHedges() internal {
        uint256 ethLeverageindex = strategyState.activeEthLeverageIndex;
        uint256 btcLeverageindex = strategyState.activeBtcLeverageIndex;
        uint256 sEthBal = IERC20(ethLeverageSets[ethLeverageindex].token).balanceOf(address(this));
        uint256 sBtcBal = IERC20(btcLeverageSets[btcLeverageindex].token).balanceOf(address(this));

        if (sEthBal > 0) {
            IERC20(ethLeverageSets[ethLeverageindex].token).safeIncreaseAllowance(vaultParams.sethStake, sEthBal);
            IStakingRewards(vaultParams.sethStake).stake(sEthBal);
        }
        if (sBtcBal > 0) {
            IERC20(btcLeverageSets[btcLeverageindex].token).safeIncreaseAllowance(vaultParams.sbtcStake, sBtcBal);
            IStakingRewards(vaultParams.sbtcStake).stake(sBtcBal);
        }
    }

    /**
     * @notice Collect Tcr emissions from the staking contract
     * @return profit in USDC recieved from TCR emissions
     */
    function collectTcrEmissions() internal returns (uint256) {
        IStakingRewards(vaultParams.sbtcStake).getReward();
        IStakingRewards(vaultParams.sethStake).getReward();
        uint256 tcrBalance = IERC20(TCR).balanceOf(address(this));
        if (tcrStrategy != address(0) && tcrBalance > 0) {
            IERC20(TCR).safeIncreaseAllowance(tcrStrategy, tcrBalance);
            return ITcrStrategy(tcrStrategy).handleTcr(tcrBalance);
        }
        return 0;
    }

    /**
     * @notice Unstakes the short tokens from the emissions contract
     */
    function unstakePartialHedges(uint256 _sbtcAmount, uint256 _sethAmount) public onlyKeeper {
        if (_sbtcAmount > 0) IStakingRewards(vaultParams.sbtcStake).withdraw(_sbtcAmount);
        if (_sethAmount > 0) IStakingRewards(vaultParams.sethStake).withdraw(_sethAmount);
    }

    /**
     * @notice Unstakes the short tokens from the emissions contract
     */
    function unstakeAllHedges() public onlyKeeper {
        IStakingRewards(vaultParams.sbtcStake).exit();
        IStakingRewards(vaultParams.sethStake).exit();
    }

    /**
     * @notice Initiates the vault migration of multiplier points and esGMX to a new vault
     * a 14 day grace period is given to warn users this has been triggered
     */
    function initiateMigration() public onlyAdmin {
        require(migrationTimestamp == MAX_INT, "already initiated");
        migrationTimestamp = block.timestamp + 14 days;
        emit InitiateVaultMigration(block.timestamp, migrationTimestamp);
    }

    /**
     * @notice Calls the migration of the esGMX and multiplier points to a new vault
     * @param _receiver the address to migrate to
     */
    function migrateVault(address _receiver) public onlyAdmin {
        require(tx.origin == msg.sender, "onlyEOA");
        require(block.timestamp > migrationTimestamp, "migration not ready");
        IRewardRouterV2(GLP_REWARD_ROUTER).signalTransfer(_receiver);
    }

    /**
     * @notice Revoke allowances to all external contracts
     */
    function revokeAllowances() public onlyAdmin {
        uint256 ethLeverageindex = strategyState.activeEthLeverageIndex;
        uint256 btcLeverageindex = strategyState.activeBtcLeverageIndex;
        IERC20(ethLeverageSets[ethLeverageindex].token).approve(vaultParams.sethStake, 0);
        IERC20(btcLeverageSets[btcLeverageindex].token).approve(vaultParams.sbtcStake, 0);
        IERC20(vaultParams.asset).approve(btcLeverageSets[btcLeverageindex].leveragePool, 0);
        IERC20(vaultParams.asset).approve(ethLeverageSets[ethLeverageindex].leveragePool, 0);
        IERC20(WETH).approve(address(router), 0);
        IERC20(vaultParams.asset).approve(GLP_MANAGER, 0);
    }
}

File 2 of 32 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 3 of 32 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 4 of 32 : VaultStorage.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

import { Vault } from "../libraries/Vault.sol";

abstract contract VaultStorage {
    // usdc value locked in delta neutral strategy
    uint256 public lockedInStrategy;
    // Amount locked for scheduled withdrawals last week;
    uint128 public lastQueuedWithdrawAmount;
}

File 5 of 32 : BaseVault.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { Pausable } from "@openzeppelin/contracts/security/Pausable.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
import { Vault } from "../libraries/Vault.sol";
import { ShareMath } from "../libraries/ShareMath.sol";
import { IWETH } from "../interfaces/IWETH.sol";
import { IWhitelist } from "../interfaces/IWhitelist.sol";
import { VaultLifecycle } from "../libraries/VaultLifecycle.sol";

contract BaseVault is AccessControl, ERC20, ReentrancyGuard, Pausable {
    using SafeERC20 for IERC20;

    /************************************************
     *  STORAGE
     ***********************************************/

    /// @notice On every round's close, the pricePerShare value of a vault token is stored
    /// This is used to determine the number of shares to be returned
    mapping(uint256 => uint256) public roundPricePerShare;

    /// @notice Stores pending user withdrawals
    mapping(address => Vault.Withdrawal) public withdrawals;

    /// @notice Stores the eth leverage set
    mapping(uint256 => Vault.LeverageSet) public ethLeverageSets;

    /// @notice Stores the btc leverage set
    mapping(uint256 => Vault.LeverageSet) public btcLeverageSets;

    /// @notice Stores the current round queued withdrawal share amount
    mapping(uint256 => uint128) public roundQueuedWithdrawalShares;

    /// @notice Vault's parameters like cap, decimals
    Vault.VaultParams public vaultParams;

    /// @notice Vault's lifecycle state like round and locked amounts
    Vault.VaultState public vaultState;

    /// @notice Vault's state of the hedges deployed and glp allocation
    Vault.StrategyState public strategyState;

    /// @notice Asset used in the vault
    address public asset;

    /// @notice Fee recipient for the performance and management fees
    address public feeRecipient;

    /// @notice Role for vault operations such as rollToNextPosition.
    address public keeper;

    /// @notice Whitelist implimentation
    address public whitelistLibrary;

    /// @notice Performance fee collected on premiums earned in rollToNextPosition. Only when there is no loss.
    uint256 public performanceFee;

    /// @notice Management fee collected on roll to next. This fee is collected each epoch
    uint256 public managementFee;

    /// @notice Deposit fee charged on entering of the vault
    uint256 public depositFee;

    /// @notice Withdrawal fee charged on exit of the vault
    uint256 public withdrawalFee;

    /// @notice If the vault is in a late withdrawal period while rebalancing
    bool public lateWithdrawPeriod;

    /// @notice The expected duration of each epoch
    uint256 public epochDuration;

    /// @notice Scale for slippage
    uint256 public SCALE = 1000;

    /************************************************
     *  IMMUTABLES & CONSTANTS
     ***********************************************/

    /// @notice WETH9
    address public immutable WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;

    /// @notice admin role hash
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    /// @notice keeper role hash
    bytes32 public constant KEEPER_ROLE = keccak256("KEEPER_ROLE");

    /// @notice Day in seconds
    uint32 public constant DAY = 86400;

    /************************************************
     *  EVENTS
     ***********************************************/

    event DepositRound(address indexed account, uint256 amount, uint256 round);

    event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);

    event InitiateWithdraw(address indexed account, uint256 shares, uint256 round);

    event ManagementFeeSet(uint256 managementFee, uint256 newManagementFee);

    event PerformanceFeeSet(uint256 performanceFee, uint256 newPerformanceFee);

    event DepositFeeSet(uint256 depositFee, uint256 newDepositFee);

    event WithdrawalFeeSet(uint256 withdrawalFee, uint256 newWithdrawalFee);

    event CapSet(uint256 oldCap, uint256 newCap);

    event Withdraw(address indexed account, uint256 amount, uint256 shares);

    event CollectVaultFees(uint256 performanceFee, uint256 vaultFee, uint256 round, address indexed feeRecipient);

    /************************************************
     *  CONSTRUCTOR & INITIALIZATION
     ***********************************************/
    /**
     * @notice Initializes the contract with immutable variables
     */
    constructor(
        address _asset,
        address _feeRecipient,
        address _keeper,
        uint256 _managementFee,
        uint256 _performanceFee,
        uint256 _depositFee,
        uint104 _vaultRound,
        Vault.VaultParams memory _vaultParams,
        string memory _name,
        string memory _symbol
    ) ERC20(_name, _symbol) {
        require(_asset != address(0), "!_asset");
        require(_feeRecipient != address(0), "!_feeRecipient");
        require(_keeper != address(0), "!_keeper");
        require(_performanceFee < 100 * Vault.FEE_MULTIPLIER, "_performanceFee >= 100%");
        require(_managementFee < 100 * Vault.FEE_MULTIPLIER, "_managementFee >= 100%");
        require(_depositFee < 100 * Vault.FEE_MULTIPLIER, "_depositFee >= 100%");
        require(_vaultParams.minimumSupply > 0, "!_minimumSupply");
        require(_vaultParams.cap > 0, "!_cap");
        require(_vaultParams.cap > _vaultParams.minimumSupply, "_cap <= _minimumSupply");
        require(bytes(_name).length > 0, "!_name");
        require(bytes(_symbol).length > 0, "!_symbol");

        asset = _asset;
        feeRecipient = _feeRecipient;
        keeper = _keeper;
        performanceFee = _performanceFee;
        managementFee = _managementFee;
        depositFee = _depositFee;
        withdrawalFee = 0;
        vaultParams = _vaultParams;
        vaultState.round = _vaultRound;
        whitelistLibrary = address(0);
        lateWithdrawPeriod = false;
        epochDuration = DAY;

        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _setupRole(KEEPER_ROLE, _keeper);
        _setupRole(ADMIN_ROLE, msg.sender);
    }

    /************************************************
     *  MODIFIERS
     ***********************************************/

    /**
     * @dev Throws if called by any account other than the keeper.
     */
    modifier onlyKeeper() {
        require(hasRole(KEEPER_ROLE, msg.sender), "!keeper");
        _;
    }

    /**
     * @dev Throws if called by any account other than the admin.
     */
    modifier onlyAdmin() {
        require(hasRole(ADMIN_ROLE, msg.sender), "Caller is not an admin");
        _;
    }

    /************************************************
     *  SETTERS
     ***********************************************/

    /**
     * @notice Sets the whitelist implementation
     * @param _newWhitelistLibrary address to the whitelist implementation
     */
    function setWhitelistLibrary(address _newWhitelistLibrary) external onlyAdmin {
        whitelistLibrary = _newWhitelistLibrary;
    }

    /**
     * @notice Sets the epoch duration
     * @param _newEpochDuration new epoch duration
     */
    function setEpochDuration(uint256 _newEpochDuration) external onlyAdmin {
        epochDuration = _newEpochDuration;
    }

    /**
     * @notice Sets the SCALE value for resolution of calcs
     * @param _newScale epoch duration
     */
    function setScale(uint256 _newScale) external onlyAdmin {
        SCALE = _newScale;
    }

    /**
     * @notice Sets a new eth leverage pool
     * @param _leverageSet the leverage set to be set
     * @param _index the index to set it at
     */
    function setEthLeveragePool(Vault.LeverageSet memory _leverageSet, uint256 _index) external onlyAdmin {
        require(_leverageSet.poolCommitter != address(0), "!addNewLeveragePool");
        require(_leverageSet.leveragePool != address(0), "!addNewLeveragePool");
        ethLeverageSets[_index] = _leverageSet;
    }

    /**
     * @notice Sets a new btc leverage pool
     * @param _leverageSet the leverage set to be set
     * @param _index the index to set it at
     */
    function setBtcLeveragePool(Vault.LeverageSet memory _leverageSet, uint256 _index) external onlyAdmin {
        require(_leverageSet.poolCommitter != address(0), "!addNewLeveragePool");
        require(_leverageSet.leveragePool != address(0), "!addNewLeveragePool");
        btcLeverageSets[_index] = _leverageSet;
    }

    /**
     * @notice Sets the new fee recipient
     * @param newFeeRecipient is the address of the new fee recipient
     */
    function setFeeRecipient(address newFeeRecipient) external onlyAdmin {
        require(newFeeRecipient != address(0), "!newFeeRecipient");
        require(newFeeRecipient != feeRecipient, "Must be new feeRecipient");
        feeRecipient = newFeeRecipient;
    }

    /**
     * @notice Sets the management fee for the vault
     * @param newManagementFee is the management fee (6 decimals). ex: 2 * 10 ** 6 = 2%
     */
    function setManagementFee(uint256 newManagementFee) external onlyAdmin {
        require(newManagementFee < 10 * Vault.FEE_MULTIPLIER, "Invalid management fee");
        uint256 hourlyRate = newManagementFee / 8760; // hours per year
        uint256 epochRate = (hourlyRate * epochDuration) / 3600;
        emit ManagementFeeSet(managementFee, newManagementFee);
        managementFee = epochRate; // % per epoch
    }

    /**
     * @notice Sets the performance fee for the vault
     * @param newPerformanceFee is the performance fee (6 decimals). ex: 20 * 10 ** 6 = 20%
     */
    function setPerformanceFee(uint256 newPerformanceFee) external onlyAdmin {
        require(newPerformanceFee < 100 * Vault.FEE_MULTIPLIER, "Invalid performance fee");
        emit PerformanceFeeSet(performanceFee, newPerformanceFee);
        performanceFee = newPerformanceFee;
    }

    /**
     * @notice Sets the deposit fee for the vault
     * @param newDepositFee is the deposit fee (6 decimals). ex: 20 * 10 ** 6 = 20%
     */
    function setDepositFee(uint256 newDepositFee) external onlyAdmin {
        require(newDepositFee < 20 * Vault.FEE_MULTIPLIER, "Invalid deposit fee");
        emit DepositFeeSet(depositFee, newDepositFee);
        depositFee = newDepositFee;
    }

    /**
     * @notice Sets the withdrawal fee for the vault
     * @param newWithdrawalFee is the withdrawal fee (6 decimals). ex: 20 * 10 ** 6 = 20%
     */
    function setWithdrawalFee(uint256 newWithdrawalFee) external onlyAdmin {
        require(newWithdrawalFee < 20 * Vault.FEE_MULTIPLIER, "Invalid withdrawal fee");
        emit WithdrawalFeeSet(withdrawalFee, newWithdrawalFee);
        withdrawalFee = newWithdrawalFee;
    }

    /**
     * @notice Sets a new cap for deposits
     * @param newCap is the new cap for deposits
     */
    function setCap(uint256 newCap) external onlyAdmin {
        require(newCap >= 0, "!newCap");
        ShareMath.assertUint104(newCap);
        emit CapSet(vaultParams.cap, newCap);
        vaultParams.cap = uint104(newCap);
    }

    /**
     * @notice Pauses deposits for the vault
     */
    function pauseDeposits() external onlyAdmin {
        _pause();
    }

    /**
     * @notice unpauses deposits for the vault
     */
    function unpauseDeposits() external onlyAdmin {
        _unpause();
    }

    /************************************************
     *  DEPOSIT & WITHDRAWALS
     ***********************************************/

    /**
     * @notice Deposits the `asset` from msg.sender.
     * @param amount is the amount of `asset` to deposit
     */
    function deposit(uint256 amount) external nonReentrant {
        require(amount > 0, "!amount");
        require(whitelistLibrary == address(0), "whitelist enabled");
        _depositFor(amount, msg.sender);
    }

    /**
     * @notice Deposits the `asset` from msg.sender added to `creditor`'s deposit.
     * @notice Used for vault -> vault deposits on the user's behalf
     * @param amount is the amount of `asset` to deposit
     * @param creditor is the address that can claim/withdraw deposited amount
     */
    function deposit(uint256 amount, address creditor) external nonReentrant returns (uint256 mintShares) {
        require(amount > 0, "!amount");
        require(creditor != address(0), "!creditor");
        require(whitelistLibrary == address(0), "whitelist enabled");
        mintShares = _depositFor(amount, creditor);
    }

    /**
     * @notice Deposits the `asset` from msg.sender. Whitelist must be enabled
     * @param amount is the amount of `asset` to deposit
     */
    function whitelistDeposit(uint256 amount, bytes32[] calldata merkleproof) external nonReentrant {
        require(amount > 0, "!amount");
        require(whitelistLibrary != address(0), "whitelist not enabled");
        uint256 checkpointBalance = checkpointTotalBalance();
        require(IWhitelist(whitelistLibrary).isWhitelisted(msg.sender, checkpointBalance, amount, merkleproof), "!whitelist");
        _depositFor(amount, msg.sender);
    }

    /**
     * @notice Mints the vault shares to the creditor
     * @param amount is the amount of `asset` deposited
     * @param creditor is the address to receieve the deposit
     * @return mintShares the shares minted
     */
    function _depositFor(uint256 amount, address creditor) private whenNotPaused returns (uint256 mintShares) {
        uint256 checkpointBalance = checkpointTotalBalance();

        uint256 currentRound = vaultState.round;
        uint256 totalWithDepositedAmount = checkpointBalance + amount;

        require(totalWithDepositedAmount <= vaultParams.cap, "Exceed cap");
        require(totalWithDepositedAmount >= vaultParams.minimumSupply, "Insufficient balance");

        emit DepositRound(creditor, amount, currentRound);

        uint256 depositFeeAmount = (amount * depositFee) / (100 * Vault.FEE_MULTIPLIER);
        uint256 depositAmount = amount - depositFeeAmount;

        uint256 newTotalPending = uint256(vaultState.totalPending) + depositAmount;

        vaultState.totalPending = uint128(newTotalPending);

        uint256 assetPerShare = roundPricePerShare[currentRound];

        mintShares = ShareMath.assetToShares(depositAmount, assetPerShare, vaultParams.decimals);

        emit Deposit(msg.sender, creditor, depositAmount, mintShares);

        IERC20(vaultParams.asset).safeTransferFrom(msg.sender, address(this), amount);
        transferAsset(feeRecipient, depositFeeAmount);

        _mint(creditor, mintShares);
    }

    /**
     * @notice Initiates a withdrawal that can be processed once the round completes
     * @param numShares is the number of shares to withdraw
     */
    function initiateWithdraw(uint256 numShares) external nonReentrant {
        if (lateWithdrawPeriod) {
            _initiateWithdraw(numShares, vaultState.round + 1);
        } else {
            _initiateWithdraw(numShares, vaultState.round);
        }
    }

    /**
     * @notice Initiates a withdrawal queued for the specified round
     * @param _numShares is the number of shares to withdraw
     * @param _round is the round to queue the withdrawal for
     */
    function _initiateWithdraw(uint256 _numShares, uint256 _round) internal {
        require(_numShares > 0, "!_numShares");

        // This caches the `round` variable used in shareBalances
        uint256 withdrawalRound = _round;
        Vault.Withdrawal storage withdrawal = withdrawals[msg.sender];

        bool withdrawalIsSameRound = withdrawal.round >= withdrawalRound;

        emit InitiateWithdraw(msg.sender, _numShares, withdrawalRound);

        uint256 existingShares = uint256(withdrawal.shares);

        uint256 withdrawalShares;
        if (withdrawalIsSameRound) {
            withdrawalShares = existingShares + _numShares;
        } else {
            require(existingShares == 0, "Existing withdraw");
            withdrawalShares = _numShares;
            withdrawals[msg.sender].round = uint16(withdrawalRound);
        }

        ShareMath.assertUint128(withdrawalShares);
        withdrawals[msg.sender].shares = uint128(withdrawalShares);

        uint256 newQueuedWithdrawShares = uint256(roundQueuedWithdrawalShares[withdrawalRound]) + _numShares;
        ShareMath.assertUint128(newQueuedWithdrawShares);
        roundQueuedWithdrawalShares[withdrawalRound] = uint128(newQueuedWithdrawShares);

        _transfer(msg.sender, address(this), _numShares);
    }

    /**
     * @notice Completes a scheduled withdrawal from a past round. Uses finalized pps for the round
     * @return withdrawAmount the current withdrawal amount
     */
    function _completeWithdraw() internal returns (uint256) {
        Vault.Withdrawal storage withdrawal = withdrawals[msg.sender];

        uint256 withdrawalShares = withdrawal.shares;
        uint256 withdrawalRound = withdrawal.round;

        // This checks if there is a withdrawal
        require(withdrawalShares > 0, "Not initiated");

        require(withdrawalRound < vaultState.round, "Round not closed");

        // We leave the round number as non-zero to save on gas for subsequent writes
        withdrawals[msg.sender].shares = 0;
        vaultState.queuedWithdrawShares = uint128(uint256(vaultState.queuedWithdrawShares) - withdrawalShares);

        uint256 withdrawAmount = ShareMath.sharesToAsset(
            withdrawalShares,
            roundPricePerShare[withdrawalRound],
            vaultParams.decimals
        );

        if (withdrawalFee > 0) {
            uint256 withdrawFeeAmount = (withdrawAmount * withdrawalFee) / (100 * Vault.FEE_MULTIPLIER);
            withdrawAmount -= withdrawFeeAmount;
        }

        emit Withdraw(msg.sender, withdrawAmount, withdrawalShares);

        _burn(address(this), withdrawalShares);
        require(withdrawAmount > 0, "!withdrawAmount");

        transferAsset(msg.sender, withdrawAmount);

        return withdrawAmount;
    }

    /**
     * @notice Mints a number of shares to the receiver
     * @param _shares is the number of shares to mint
     * @param _receiver is account recieving the shares
     */
    function mint(uint256 _shares, address _receiver) external nonReentrant {
        require(_shares > 0, "!_shares");
        require(_receiver != address(0), "!_receiver");

        uint256 currentRound = vaultState.round;
        uint256 assetPerShare = roundPricePerShare[currentRound];
        uint256 assetAmount = ShareMath.sharesToAsset(_shares, assetPerShare, vaultParams.decimals);

        _depositFor(assetAmount, _receiver);
    }

    /************************************************
     *  VAULT OPERATIONS
     ***********************************************/

    /*
     * @notice Helper function that helps to save gas for writing values into the roundPricePerShare map.
     *         Writing `1` into the map makes subsequent writes warm, reducing the gas from 20k to 5k.
     *         Having 1 initialized beforehand will not be an issue as long as we round down share calculations to 0.
     * @param numRounds is the number of rounds to initialize in the map
     */
    function initRounds(uint256 numRounds) external nonReentrant {
        require(numRounds > 0, "!numRounds");

        uint256 _round = vaultState.round;
        for (uint256 i = 0; i < numRounds; i++) {
            uint256 index = _round + i;
            require(roundPricePerShare[index] == 0, "Initialized"); // AVOID OVERWRITING ACTUAL VALUES
            roundPricePerShare[index] = ShareMath.PLACEHOLDER_UINT;
        }
    }

    /*
     * @notice Helper function that performs most administrative tasks
     * such as setting next strategy params, depositing to tracer and GMX, getting vault fees, etc.
     */
    function _rollToNextEpoch(
        uint256 lastQueuedWithdrawAmount,
        uint256 currentQueuedWithdrawalShares,
        uint256 totalAssetValue
    ) internal returns (uint256 lockedBalance, uint256 queuedWithdrawAmount) {
        uint256 newSbtcAllocation = strategyState.nextSbtcAllocation;
        uint256 newSethAllocation = strategyState.nextSethAllocation;
        uint256 newGlpAllocation = strategyState.nextGlpAllocation;

        uint256 performanceFeeInAsset;
        uint256 totalVaultFee;
        {
            uint256 newPricePerShare;
            (lockedBalance, queuedWithdrawAmount, newPricePerShare, performanceFeeInAsset, totalVaultFee) = VaultLifecycle
                .rollover(
                    vaultState,
                    VaultLifecycle.RolloverParams(
                        vaultParams.decimals,
                        totalAssetValue,
                        totalSupply(),
                        lastQueuedWithdrawAmount,
                        currentQueuedWithdrawalShares,
                        performanceFee,
                        managementFee,
                        (block.timestamp - vaultState.epochStart) / epochDuration
                    )
                );

            strategyState.activeSbtcAllocation = newSbtcAllocation;
            strategyState.activeSethAllocation = newSethAllocation;
            strategyState.activeGlpAllocation = newGlpAllocation;

            strategyState.nextSbtcAllocation = 0;
            strategyState.nextSethAllocation = 0;
            strategyState.nextGlpAllocation = 0;

            uint256 currentRound = vaultState.round;
            roundPricePerShare[currentRound] = newPricePerShare;

            // close the late withdrawal period for rebalancing
            lateWithdrawPeriod = false;

            emit CollectVaultFees(performanceFeeInAsset, totalVaultFee, currentRound, feeRecipient);

            vaultState.totalPending = 0;
            vaultState.round = uint104(currentRound + 1);
            vaultState.epochStart = block.timestamp;
            vaultState.epochEnd = vaultState.epochStart + epochDuration;
            roundPricePerShare[vaultState.round] = newPricePerShare;
        }

        if (totalVaultFee > 0) {
            transferAsset(payable(feeRecipient), totalVaultFee);
        }
        return (lockedBalance, queuedWithdrawAmount);
    }

    /**
     * @notice Helper function to make either an ETH transfer or ERC20 transfer
     * @param recipient is the receiving address
     * @param amount is the transfer amount
     */
    function transferAsset(address recipient, uint256 amount) internal {
        if (asset == WETH) {
            IWETH(WETH).withdraw(amount);
            (bool success, ) = recipient.call{ value: amount }("");
            require(success, "Transfer failed");
            return;
        }
        IERC20(asset).safeTransfer(recipient, amount);
    }

    /************************************************
     *  GETTERS
     ***********************************************/

    /**
     * @notice Returns the asset balance held on the vault for the account
     * @param account is the address to lookup balance for
     * @return the amount of `asset` custodied by the vault for the user
     */
    function accountVaultBalance(address account) external view returns (uint256) {
        uint256 _decimals = vaultParams.decimals;
        uint256 assetPerShare = roundPricePerShare[vaultState.round];
        return ShareMath.sharesToAsset(shares(account), assetPerShare, _decimals);
    }

    /**
     * @notice Getter for returning the account's share balance
     * @param _account is the account to lookup share balance for
     * @return heldByAccount share balance
     */
    function shares(address _account) public view returns (uint256) {
        uint256 heldByAccount = balanceOf(_account);
        return heldByAccount;
    }

    /**
     * @notice The price of a unit of share denominated in the `asset`
     * @return
     */
    function pricePerShare() external view returns (uint256) {
        return roundPricePerShare[vaultState.round];
    }

    /**
     * @notice Returns the vault's balance with realtime deposits and the locked value at the start of the epoch
     * @return total balance of the vault, including the amounts locked in third party protocols
     */
    function checkpointTotalBalance() public view returns (uint256) {
        return uint256(vaultState.lastLockedAmount) + IERC20(vaultParams.asset).balanceOf(address(this));
    }

    /**
     * @notice Returns the token decimals
     * @return
     */
    function decimals() public view override returns (uint8) {
        return vaultParams.decimals;
    }

    /**
     * @notice Returns the vault cap
     * @return
     */
    function cap() external view returns (uint256) {
        return vaultParams.cap;
    }

    /**
     * @notice Returns the value of deposits not yet used in the strategy
     * @return
     */
    function totalPending() external view returns (uint256) {
        return vaultState.totalPending;
    }

    /**
     * @notice Converts the vault asset to shares at the current rate for this epoch
     * @param _assets the amount of the vault asset to convert
     * @return shares amount of shares for the asset
     */
    function convertToShares(uint256 _assets) public view virtual returns (uint256) {
        uint256 assetPerShare = roundPricePerShare[vaultState.round];
        return ShareMath.assetToShares(_assets, assetPerShare, vaultParams.decimals);
    }

    /**
     * @notice Converts the vault shares to assets at the current rate for this epoch
     * @param _shares the amount of vault shares to convert
     * @return asset amount of asset for the shares
     */
    function convertToAssets(uint256 _shares) public view virtual returns (uint256) {
        uint256 assetPerShare = roundPricePerShare[vaultState.round];
        return ShareMath.sharesToAsset(_shares, assetPerShare, vaultParams.decimals);
    }

    /**
     * @notice Previews a deposit to the vault for the number of assets
     * @param _assets to be deposited
     * @return shares amount of shares recieved after fees
     */
    function previewDeposit(uint256 _assets) public view virtual returns (uint256) {
        uint256 amountLessDepositFee = _assets - ((_assets * depositFee) / (100 * Vault.FEE_MULTIPLIER));
        return convertToShares(amountLessDepositFee);
    }

    /**
     * @notice Previews a mint of vault shares
     * @param _shares amount of shares to be minted
     * @return asset amount of asset required to mint the shares after fees
     */
    function previewMint(uint256 _shares) public view virtual returns (uint256) {
        uint256 amountLessDepositFee = _shares - ((_shares * depositFee) / (100 * Vault.FEE_MULTIPLIER));
        return convertToAssets(amountLessDepositFee);
    }

    /**
     * @notice Previews a withdrawal from the vault at the current price per share
     * @param _shares the amount of shares to withdraw
     * @return asset the amount of asset recieved after fees
     */
    function previewWithdraw(uint256 _shares) public view virtual returns (uint256) {
        uint256 amountLessWithdrawalFee = _shares - ((_shares * withdrawalFee) / (100 * Vault.FEE_MULTIPLIER));
        return convertToAssets(amountLessWithdrawalFee);
    }

    /**
     * @notice Previews the next balances for the epoch with queued withdrawals
     * @param lastQueuedWithdrawAmount the amount last queued for withdrawal
     * @param currentQueuedWithdrawalShares the amount queued for withdrawal this round
     * @param totalAssetValue total asset value of the vault
     * @return lockedBalance balance locked for the next strategy epoch
     * @return queuedWithdrawAmount next queued withdrawal amount to be set aside for withdrawals
     */
    function previewNextBalances(
        uint256 lastQueuedWithdrawAmount,
        uint256 currentQueuedWithdrawalShares,
        uint256 totalAssetValue
    ) internal view virtual returns (uint256 lockedBalance, uint256 queuedWithdrawAmount) {
        uint256 epochSeconds = (block.timestamp - vaultState.epochStart) / epochDuration;

        (lockedBalance, queuedWithdrawAmount, , , ) = VaultLifecycle.rollover(
            vaultState,
            VaultLifecycle.RolloverParams(
                vaultParams.decimals,
                totalAssetValue,
                totalSupply(),
                lastQueuedWithdrawAmount,
                currentQueuedWithdrawalShares,
                performanceFee,
                managementFee,
                epochSeconds
            )
        );
    }

    /**
     * @notice recover eth
     */
    function recoverEth() external onlyAdmin {
        (bool success, ) = msg.sender.call{ value: address(this).balance }("");
        require(success, "Withdraw failed");
    }
}

File 6 of 32 : ISwapRouter.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
pragma abicoder v2;

/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }

    /// @notice Swaps `amountIn` of one token for as much as possible of another token
    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
    /// @return amountOut The amount of the received token
    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);

    struct ExactInputParams {
        bytes path;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
    }

    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
    /// @return amountOut The amount of the received token
    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);

    struct ExactOutputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
        uint160 sqrtPriceLimitX96;
    }

    /// @notice Swaps as little as possible of one token for `amountOut` of another token
    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
    /// @return amountIn The amount of the input token
    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);

    struct ExactOutputParams {
        bytes path;
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
    }

    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
    /// @return amountIn The amount of the input token
    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}

File 7 of 32 : IStakingRewards.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface IStakingRewards {
    // Views
    function balanceOf(address account) external view returns (uint256);

    function earned(address account) external view returns (uint256);

    function getRewardForDuration() external view returns (uint256);

    function lastTimeRewardApplicable() external view returns (uint256);

    function rewardPerToken() external view returns (uint256);

    function rewardsDistribution() external view returns (address);

    function rewardsToken() external view returns (address);

    function totalSupply() external view returns (uint256);

    // Mutative
    function exit() external;

    function getReward() external;

    function stake(uint256 amount) external;

    function withdraw(uint256 amount) external;
}

File 8 of 32 : IPoolCommitter.sol
//SPDX-License-Identifier: CC-BY-NC-ND-4.0
pragma solidity 0.8.7;

/// @title The interface for the contract that handles pool commitments
interface IPoolCommitter {
    /// Type of commit
    enum CommitType {
        ShortMint, // Mint short tokens
        ShortBurn, // Burn short tokens
        LongMint, // Mint long tokens
        LongBurn, // Burn long tokens
        LongBurnShortMint, // Burn Long tokens, then instantly mint in same upkeep
        ShortBurnLongMint // Burn Short tokens, then instantly mint in same upkeep
    }

    function isMint(CommitType t) external pure returns (bool);

    function isBurn(CommitType t) external pure returns (bool);

    function isLong(CommitType t) external pure returns (bool);

    function isShort(CommitType t) external pure returns (bool);

    // Pool balances and supplies
    struct BalancesAndSupplies {
        uint256 newShortBalance;
        uint256 newLongBalance;
        uint256 longMintPoolTokens;
        uint256 shortMintPoolTokens;
        uint256 longBurnInstantMintSettlement;
        uint256 shortBurnInstantMintSettlement;
        uint256 totalLongBurnPoolTokens;
        uint256 totalShortBurnPoolTokens;
    }

    // User aggregate balance
    struct Balance {
        uint256 longTokens;
        uint256 shortTokens;
        uint256 settlementTokens;
    }

    // Token Prices
    struct Prices {
        bytes16 longPrice;
        bytes16 shortPrice;
    }

    // Commit information
    struct Commit {
        uint256 amount;
        CommitType commitType;
        uint40 created;
        address owner;
    }

    // Commit information
    struct TotalCommitment {
        uint256 longMintSettlement;
        uint256 longBurnPoolTokens;
        uint256 shortMintSettlement;
        uint256 shortBurnPoolTokens;
        uint256 shortBurnLongMintPoolTokens;
        uint256 longBurnShortMintPoolTokens;
    }

    // User updated aggregate balance
    struct BalanceUpdate {
        uint256 _updateIntervalId;
        uint256 _newLongTokensSum;
        uint256 _newShortTokensSum;
        uint256 _newSettlementTokensSum;
        uint256 _longSettlementFee;
        uint256 _shortSettlementFee;
        uint8 _maxIterations;
    }

    // Track how much of a user's commitments are being done from their aggregate balance
    struct UserCommitment {
        uint256 longMintSettlement;
        uint256 longBurnPoolTokens;
        uint256 shortMintSettlement;
        uint256 shortBurnPoolTokens;
        uint256 shortBurnLongMintPoolTokens;
        uint256 longBurnShortMintPoolTokens;
        uint256 updateIntervalId;
    }

    // Track the relevant data when executing a range of update interval's commitments (stack too deep)
    struct CommitmentExecutionTracking {
        uint256 longTotalSupply;
        uint256 shortTotalSupply;
        uint256 longTotalSupplyBefore;
        uint256 shortTotalSupplyBefore;
        uint256 _updateIntervalId;
    }

    /**
     * @notice Creates a notification when a commit is created
     * @param user The user making the commitment
     * @param amount Amount of the commit
     * @param commitType Type of the commit (Short v Long, Mint v Burn)
     * @param appropriateUpdateIntervalId Id of update interval where this commit can be executed as part of upkeep
     * @param fromAggregateBalance whether or not to commit from aggregate (unclaimed) balance
     * @param payForClaim whether or not to request this commit be claimed automatically
     * @param mintingFee Minting fee at time of commit creation
     */
    event CreateCommit(
        address indexed user,
        uint256 indexed amount,
        CommitType indexed commitType,
        uint256 appropriateUpdateIntervalId,
        bool fromAggregateBalance,
        bool payForClaim,
        bytes16 mintingFee
    );

    /**
     * @notice Creates a notification when a user's aggregate balance is updated
     */
    event AggregateBalanceUpdated(address indexed user);

    /**
     * @notice Creates a notification when the PoolCommitter's leveragedPool address has been updated.
     * @param newPool the address of the new leveraged pool
     */
    event PoolChanged(address indexed newPool);

    /**
     * @notice Creates a notification when commits for a given update interval are executed
     * @param updateIntervalId Unique identifier for the relevant update interval
     * @param burningFee Burning fee at the time of commit execution
     */
    event ExecutedCommitsForInterval(uint256 indexed updateIntervalId, bytes16 burningFee);

    /**
     * @notice Creates a notification when a claim is made, depositing pool tokens in user's wallet
     */
    event Claim(address indexed user);

    /*
     * @notice Creates a notification when the burningFee is updated
     */
    event BurningFeeSet(uint256 indexed _burningFee);

    /**
     * @notice Creates a notification when the mintingFee is updated
     */
    event MintingFeeSet(uint256 indexed _mintingFee);

    /**
     * @notice Creates a notification when the changeInterval is updated
     */
    event ChangeIntervalSet(uint256 indexed _changeInterval);

    /**
     * @notice Creates a notification when the feeController is updated
     */
    event FeeControllerSet(address indexed _feeController);

    // #### Functions

    function initialize(
        address _factory,
        address _autoClaim,
        address _factoryOwner,
        address _feeController,
        address _invariantCheck,
        uint256 mintingFee,
        uint256 burningFee,
        uint256 _changeInterval
    ) external;

    function commit(bytes32 args) external payable;

    function updateIntervalId() external view returns (uint128);

    function pendingMintSettlementAmount() external view returns (uint256);

    function pendingShortBurnPoolTokens() external view returns (uint256);

    function pendingLongBurnPoolTokens() external view returns (uint256);

    function claim(address user) external;

    function executeCommitments(
        uint256 lastPriceTimestamp,
        uint256 updateInterval,
        uint256 longBalance,
        uint256 shortBalance
    )
        external
        returns (
            uint256,
            uint256,
            uint256,
            uint256,
            uint256
        );

    function updateAggregateBalance(address user) external;

    function getAggregateBalance(address user) external view returns (Balance memory _balance);

    function getAppropriateUpdateIntervalId() external view returns (uint128);

    function setPool(address _leveragedPool) external;

    function setBurningFee(uint256 _burningFee) external;

    function setMintingFee(uint256 _mintingFee) external;

    function setChangeInterval(uint256 _changeInterval) external;

    function setFeeController(address _feeController) external;
}

File 9 of 32 : IGlpManager.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface IGlpManager {
    function addLiquidity(
        address _token,
        uint256 _amount,
        uint256 _minUsdg,
        uint256 _minGlp
    ) external returns (uint256);

    function addLiquidityForAccount(
        address _fundingAccount,
        address _account,
        address _token,
        uint256 _amount,
        uint256 _minUsdg,
        uint256 _minGlp
    ) external returns (uint256);

    function removeLiquidity(
        address _tokenOut,
        uint256 _glpAmount,
        uint256 _minOut,
        address _receiver
    ) external returns (uint256);

    function removeLiquidityForAccount(
        address _account,
        address _tokenOut,
        uint256 _glpAmount,
        uint256 _minOut,
        address _receiver
    ) external returns (uint256);

    function getAum(bool maximise) external view returns (uint256);
}

File 10 of 32 : IRewardRouterV2.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface IRewardRouterV2 {
    function unstakeAndRedeemGlp(
        address _tokenOut,
        uint256 _glpAmount,
        uint256 _minOut,
        address _receiver
    ) external returns (uint256);

    function mintAndStakeGlp(
        address _token,
        uint256 _amount,
        uint256 _minUsdg,
        uint256 _minGlp
    ) external returns (uint256);

    function handleRewards(
        bool _shouldClaimGmx,
        bool _shouldStakeGmx,
        bool _shouldClaimEsGmx,
        bool _shouldStakeEsGmx,
        bool _shouldStakeMultiplierPoints,
        bool _shouldClaimWeth,
        bool _shouldConvertWethToEth
    ) external;

    function claimEsGmx() external;

    function signalTransfer(address _receiver) external;
}

File 11 of 32 : IGlpPricing.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface IGlpPricing {
    function setPrice(uint256 _glpPrice) external;

    function glpPrice(bool _buy) external view returns (uint256);

    function usdToGlp(uint256 usdAmount, bool maximise) external view returns (uint256);

    function glpToUsd(uint256 glpAmount, bool maximise) external view returns (uint256);
}

File 12 of 32 : ITcrPricing.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface ITcrPricing {
    function setSEthPrice(uint256 _price) external;

    function setSbtcPrice(uint256 _price) external;

    function sEthPrice() external view returns (uint256);

    function sBtcPrice() external view returns (uint256);

    function sEthToUsd(uint256 sethAmount) external view returns (uint256);

    function sBtcToUsd(uint256 sbtcAmount) external view returns (uint256);

    function usdToSeth(uint256 usd) external view returns (uint256);

    function usdToSbtc(uint256 usd) external view returns (uint256);
}

File 13 of 32 : ITcrStrategy.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface ITcrStrategy {
    function handleTcr(uint256 _amount) external returns (uint256);
}

File 14 of 32 : IChainlinkWrapper.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface IChainlinkWrapper {
    function getExternalPrice(address _token) external view returns (uint256);

    function getLastPrice(address _token) external view returns (uint256);

    function getCurrentPrice(address _token) external view returns (uint256);
}

File 15 of 32 : Vault.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0;

library Vault {
    // Fees are 6-decimal places. For example: 20 * 10**6 = 20%
    uint256 internal constant FEE_MULTIPLIER = 10**6;

    // Placeholder uint value to prevent cold writes
    uint256 internal constant PLACEHOLDER_UINT = 1;

    struct VaultParams {
        // Token decimals for vault shares
        uint8 decimals;
        // Minimum supply of the vault shares issued, for ETH it's 10**10
        uint56 minimumSupply;
        // Vault cap
        uint104 cap;
        // Vault asset
        address asset;
        // staked glp
        address stakedGlp;
        // esGMX
        address esGMX;
        // glp pricing library
        address glpPricing;
        // tracer hedge pricing library
        address hedgePricing;
        // sbtc tcr emissions staking
        address sbtcStake;
        // seth tcr emissions staking
        address sethStake;
    }

    struct StrategyState {
        // the allocation of sbtc this epoch
        uint256 activeSbtcAllocation;
        // the allocation of seth this epoch
        uint256 activeSethAllocation;
        // the allocation of glp this epoch
        uint256 activeGlpAllocation;
        // The index of the leverage for btc shorts
        uint256 activeBtcLeverageIndex;
        // The index of the leverage for eth shorts
        uint256 activeEthLeverageIndex;
        // the allocation of sbtc next epoch
        uint256 nextSbtcAllocation;
        // the allocation of seth next epoch
        uint256 nextSethAllocation;
        // the allocation of glp next epoch
        uint256 nextGlpAllocation;
    }

    struct VaultState {
        // 32 byte slot 1
        //  Current round number. `round` represents the number of `period`s elapsed.
        uint104 round;
        // Amount that is currently locked for the strategy
        uint104 lockedAmount;
        // Amount that was locked for the strategy
        // used for calculating performance fee deduction
        uint104 lastLockedAmount;
        // 32 byte slot 2
        // Stores the total tally of how much of `asset` there is
        uint128 totalPending;
        // Total amount of queued withdrawal shares from previous rounds not including the current round
        uint128 queuedWithdrawShares;
        // Start time of the last epoch
        uint256 epochStart;
        // Epoch end time
        uint256 epochEnd;
    }

    struct LeverageSet {
        // The tokenised leverage position
        address token;
        // The committer for the leverage position
        address poolCommitter;
        // Leverage pool holding the deposit tokens
        address leveragePool;
    }

    struct Withdrawal {
        // Maximum of 65535 rounds. Assuming 1 round is 7 days, maximum is 1256 years.
        uint16 round;
        // Number of shares withdrawn
        uint128 shares;
    }
}

File 16 of 32 : ShareMath.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

import { Vault } from "./Vault.sol";

library ShareMath {
    uint256 internal constant PLACEHOLDER_UINT = 1;

    function assetToShares(
        uint256 assetAmount,
        uint256 assetPerShare,
        uint256 decimals
    ) internal pure returns (uint256) {
        // If this throws, it means that vault's roundPricePerShare[currentRound] has not been set yet
        // which should never happen.
        // Has to be larger than 1 because `1` is used in `initRoundPricePerShares` to prevent cold writes.
        require(assetPerShare > PLACEHOLDER_UINT, "Invalid assetPerShare");

        return (assetAmount * 10**decimals) / assetPerShare;
    }

    function sharesToAsset(
        uint256 shares,
        uint256 assetPerShare,
        uint256 decimals
    ) internal pure returns (uint256) {
        // If this throws, it means that vault's roundPricePerShare[currentRound] has not been set yet
        // which should never happen.
        // Has to be larger than 1 because `1` is used in `initRoundPricePerShares` to prevent cold writes.
        require(assetPerShare > PLACEHOLDER_UINT, "Invalid assetPerShare");

        return (shares * assetPerShare) / 10**decimals;
    }

    function pricePerShare(
        uint256 totalSupply,
        uint256 totalBalance,
        uint256 decimals
    ) internal pure returns (uint256) {
        uint256 singleShare = 10**decimals;
        return totalSupply > 0 ? (singleShare * totalBalance) / totalSupply : singleShare;
    }

    /************************************************
     *  HELPERS
     ***********************************************/

    function assertUint104(uint256 num) internal pure {
        require(num <= type(uint104).max, "Overflow uint104");
    }

    function assertUint128(uint256 num) internal pure {
        require(num <= type(uint128).max, "Overflow uint128");
    }
}

File 17 of 32 : L2Encoder.sol
//SPDX-License-Identifier: CC-BY-NC-ND-4.0
pragma solidity 0.8.7;

import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../interfaces/IPoolCommitter.sol";

/**
 * @title L2Encoder
 * @notice Helper contract to encode calldata, used to optimize calldata size
 * only indented to help generate calldata for uses/frontends.
 */
contract L2Encoder {
    using SafeCast for uint256;

    /**
     * @notice Encodes an array of addresses to compact representation as a bytes array
     * @param args The array of LeveragedPool addresses to perform upkeep on
     * @return compact bytes array of addresses
     */
    function encodeAddressArray(address[] calldata args) external pure returns (bytes memory) {
        bytes memory encoded;
        uint256 len = args.length;
        for (uint256 i = 0; i < len; i++) {
            encoded = bytes.concat(encoded, abi.encodePacked(args[i]));
        }
        return encoded;
    }

    /**
     * @notice Encodes commit parameters from standard input to compact representation of 1 bytes32
     * @param amount Amount of settlement tokens you want to commit to minting; OR amount of pool
     *               tokens you want to burn
     * @param commitType Type of commit you're doing (Long vs Short, Mint vs Burn)
     * @param fromAggregateBalance If minting, burning, or rebalancing into a delta neutral position,
     *                             will tokens be taken from user's aggregate balance?
     * @param payForClaim True if user wants to pay for the commit to be claimed
     * @return compact representation of commit parameters
     */
    function encodeCommitParams(
        uint256 amount,
        IPoolCommitter.CommitType commitType,
        bool fromAggregateBalance,
        bool payForClaim
    ) external pure returns (bytes32) {
        uint128 shortenedAmount = amount.toUint128();

        bytes32 res;

        assembly {
            res := add(shortenedAmount, add(shl(128, commitType), add(shl(136, fromAggregateBalance), shl(144, payForClaim))))
        }
        return res;
    }
}

File 18 of 32 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 19 of 32 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

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

File 20 of 32 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 21 of 32 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 22 of 32 : AccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 23 of 32 : IWETH.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface IWETH {
    function deposit() external payable;

    function withdraw(uint256) external;

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

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

File 24 of 32 : IWhitelist.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

interface IWhitelist {
    function isWhitelisted(
        address _account,
        uint256 _currentAssets,
        uint256 _amount,
        bytes32[] calldata _merkleproof
    ) external returns (bool);
}

File 25 of 32 : VaultLifecycle.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.7;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Vault } from "./Vault.sol";
import { ShareMath } from "./ShareMath.sol";

library VaultLifecycle {
    /**
     * @param decimals is the decimals of the asset
     * @param totalBalance is the total value held by the vault priced in USDC
     * @param currentShareSupply is the supply of the shares invoked with totalSupply()
     * @param lastQueuedWithdrawAmount is the amount queued for withdrawals from all rounds excluding the last
     * @param currentQueuedWithdrawShares is the amount queued for withdrawals from last round
     * @param performanceFee is the performance fee percent
     * @param managementFee is the management fee percent
     * @param epochsElapsed is the number of epochs elapsed measured by the duration
     */
    struct RolloverParams {
        uint256 decimals;
        uint256 totalBalance;
        uint256 currentShareSupply;
        uint256 lastQueuedWithdrawAmount;
        uint256 currentQueuedWithdrawShares;
        uint256 performanceFee;
        uint256 managementFee;
        uint256 epochsElapsed;
    }

    /**
     * @notice Calculate the new price per share and
      amount of funds to re-allocate as collateral for the new epoch
     * @param vaultState is the storage variable vaultState
     * @param params is the rollover parameters passed to compute the next state
     * @return newLockedAmount is the amount of funds to allocate for the new round
     * @return queuedWithdrawAmount is the amount of funds set aside for withdrawal
     * @return newPricePerShare is the price per share of the new round
     * @return performanceFeeInAsset is the performance fee charged by vault
     * @return totalVaultFee is the total amount of fee charged by vault
     */
    function rollover(Vault.VaultState storage vaultState, RolloverParams calldata params)
        external
        view
        returns (
            uint256 newLockedAmount,
            uint256 queuedWithdrawAmount,
            uint256 newPricePerShare,
            uint256 performanceFeeInAsset,
            uint256 totalVaultFee
        )
    {
        uint256 currentBalance = params.totalBalance;
        // Total amount of queued withdrawal shares from previous rounds (doesn't include the current round)
        uint256 lastQueuedWithdrawShares = vaultState.queuedWithdrawShares;
        uint256 epochManagementFee = params.epochsElapsed > 0 ? params.managementFee * params.epochsElapsed : params.managementFee;

        // Deduct older queued withdraws so we don't charge fees on them
        uint256 balanceForVaultFees = currentBalance - params.lastQueuedWithdrawAmount;

        {
            // no performance fee on first round
            balanceForVaultFees = vaultState.round == 1 ? vaultState.totalPending : balanceForVaultFees;

            (performanceFeeInAsset, , totalVaultFee) = VaultLifecycle.getVaultFees(
                balanceForVaultFees,
                vaultState.lastLockedAmount,
                vaultState.totalPending,
                params.performanceFee,
                epochManagementFee
            );
        }

        // Take into account the fee
        // so we can calculate the newPricePerShare
        currentBalance = currentBalance - totalVaultFee;

        {
            newPricePerShare = ShareMath.pricePerShare(
                params.currentShareSupply - lastQueuedWithdrawShares,
                currentBalance - params.lastQueuedWithdrawAmount,
                params.decimals
            );

            queuedWithdrawAmount =
                params.lastQueuedWithdrawAmount +
                ShareMath.sharesToAsset(params.currentQueuedWithdrawShares, newPricePerShare, params.decimals);
        }

        return (
            currentBalance - queuedWithdrawAmount, // new locked balance subtracts the queued withdrawals
            queuedWithdrawAmount,
            newPricePerShare,
            performanceFeeInAsset,
            totalVaultFee
        );
    }

    /**
     * @notice Calculates the performance and management fee for this round
     * @param currentBalance is the balance of funds held on the vault after closing short
     * @param lastLockedAmount is the amount of funds locked from the previous round
     * @param pendingAmount is the pending deposit amount
     * @param performanceFeePercent is the performance fee pct.
     * @param managementFeePercent is the management fee pct.
     * @return performanceFeeInAsset is the performance fee
     * @return managementFeeInAsset is the management fee
     * @return vaultFee is the total fees
     */
    function getVaultFees(
        uint256 currentBalance,
        uint256 lastLockedAmount,
        uint256 pendingAmount,
        uint256 performanceFeePercent,
        uint256 managementFeePercent
    )
        internal
        pure
        returns (
            uint256 performanceFeeInAsset,
            uint256 managementFeeInAsset,
            uint256 vaultFee
        )
    {
        // At the first round, currentBalance=0, pendingAmount>0
        // so we just do not charge anything on the first round
        uint256 lockedBalanceSansPending = currentBalance > pendingAmount ? currentBalance - pendingAmount : 0;

        uint256 _performanceFeeInAsset;
        uint256 _managementFeeInAsset;
        uint256 _vaultFee;

        // Take performance fee ONLY if difference between
        // last epoch and this epoch's vault deposits, taking into account pending
        // deposits and withdrawals, is positive. If it is negative, last round
        // was not profitable and the vault took a loss on assets
        if (lockedBalanceSansPending > lastLockedAmount) {
            _performanceFeeInAsset = performanceFeePercent > 0
                ? ((lockedBalanceSansPending - lastLockedAmount) * performanceFeePercent) / (100 * Vault.FEE_MULTIPLIER)
                : 0;
        }
        // Take management fee on each epoch
        _managementFeeInAsset = managementFeePercent > 0
            ? (lockedBalanceSansPending * managementFeePercent) / (100 * Vault.FEE_MULTIPLIER)
            : 0;

        _vaultFee = _performanceFeeInAsset + _managementFeeInAsset;

        return (_performanceFeeInAsset, _managementFeeInAsset, _vaultFee);
    }
}

File 26 of 32 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 27 of 32 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 28 of 32 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

File 29 of 32 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 30 of 32 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 31 of 32 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 32 of 32 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 888
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {
    "contracts/libraries/VaultLifecycle.sol": {
      "VaultLifecycle": "0xb0b49c3c76f92d629278fde6ad48d3ea877d2c0d"
    }
  }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_feeRecipient","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"uint256","name":"_managementFee","type":"uint256"},{"internalType":"uint256","name":"_performanceFee","type":"uint256"},{"internalType":"uint256","name":"_depositFee","type":"uint256"},{"internalType":"uint104","name":"_vaultRound","type":"uint104"},{"components":[{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint56","name":"minimumSupply","type":"uint56"},{"internalType":"uint104","name":"cap","type":"uint104"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"stakedGlp","type":"address"},{"internalType":"address","name":"esGMX","type":"address"},{"internalType":"address","name":"glpPricing","type":"address"},{"internalType":"address","name":"hedgePricing","type":"address"},{"internalType":"address","name":"sbtcStake","type":"address"},{"internalType":"address","name":"sethStake","type":"address"}],"internalType":"struct Vault.VaultParams","name":"_vaultParams","type":"tuple"},{"internalType":"address","name":"_glpRouter","type":"address"},{"internalType":"address","name":"_glpManager","type":"address"},{"internalType":"address","name":"_uniswapRouter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"CapSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"performanceFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"},{"indexed":true,"internalType":"address","name":"feeRecipient","type":"address"}],"name":"CollectVaultFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint104","name":"_round","type":"uint104"},{"indexed":false,"internalType":"uint256","name":"_timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_profitAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_glpAllocation","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_sbtcAllocation","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_sethAllocation","type":"uint256"}],"name":"CommitAndClose","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"depositFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDepositFee","type":"uint256"}],"name":"DepositFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"}],"name":"DepositRound","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_migrationActiveTimestamp","type":"uint256"}],"name":"InitiateVaultMigration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"}],"name":"InitiateWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"managementFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newManagementFee","type":"uint256"}],"name":"ManagementFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"performanceFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPerformanceFee","type":"uint256"}],"name":"PerformanceFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_lockedInStrategy","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_queuedWithdrawAmount","type":"uint256"}],"name":"RollToNextPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sbtcAllocation","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_sethAllocation","type":"uint256"}],"name":"TracerClose","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sbtcAllocation","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_sethAllocation","type":"uint256"}],"name":"TracerOpen","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint104","name":"_round","type":"uint104"},{"indexed":false,"internalType":"uint256","name":"_pricePerShare","type":"uint256"}],"name":"UpdatePricePerShare","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"withdrawalFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newWithdrawalFee","type":"uint256"}],"name":"WithdrawalFeeSet","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAY","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GLP_MANAGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GLP_REWARD_ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KEEPER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_INT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TCR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"accountVaultBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"btcLeverageSets","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"poolCommitter","type":"address"},{"internalType":"address","name":"leveragePool","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainlinkOracle","outputs":[{"internalType":"contract IChainlinkWrapper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpointTotalBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimShorts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint112","name":"nextSbtcAllocation","type":"uint112"},{"internalType":"uint112","name":"nextSethAllocation","type":"uint112"},{"internalType":"uint112","name":"nextGlpAllocation","type":"uint112"},{"internalType":"bool","name":"_settlePositions","type":"bool"},{"internalType":"bool","name":"_handleTcrEmissions","type":"bool"}],"name":"commitAndClose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"completeWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"creditor","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"mintShares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"encoder","outputs":[{"internalType":"contract L2Encoder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ethLeverageSets","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"poolCommitter","type":"address"},{"internalType":"address","name":"leveragePool","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextLockedQueued","outputs":[{"internalType":"uint256","name":"lockedBalance","type":"uint256"},{"internalType":"uint256","name":"queuedWithdrawAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"glpCloseSlippage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"glpPricing","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hedgePricing","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hedgeStakingActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numRounds","type":"uint256"}],"name":"initRounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initiateMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numShares","type":"uint256"}],"name":"initiateWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastQueuedWithdrawAmount","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lateWithdrawPeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockedInStrategy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managementFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"migrateVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrationTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"glpAllocation","type":"uint256"}],"name":"openGlpPosition","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":"_assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"sbtcAllocation","type":"uint256"},{"internalType":"uint256","name":"sethAllocation","type":"uint256"},{"internalType":"enum GlpUSDCVault.HedgeAction","name":"sethAction","type":"uint8"},{"internalType":"enum GlpUSDCVault.HedgeAction","name":"sbtcAction","type":"uint8"}],"name":"queueHedgeRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"sbtcAllocation","type":"uint256"},{"internalType":"uint256","name":"sethAllocation","type":"uint256"}],"name":"queueTracerClose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"sbtcAllocation","type":"uint256"},{"internalType":"uint256","name":"sethAllocation","type":"uint256"}],"name":"queueTracerOpen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeAllowances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rollToNextPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roundPricePerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roundQueuedWithdrawalShares","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"poolCommitter","type":"address"},{"internalType":"address","name":"leveragePool","type":"address"}],"internalType":"struct Vault.LeverageSet","name":"_leverageSet","type":"tuple"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"setBtcLeveragePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCap","type":"uint256"}],"name":"setCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newDepositFee","type":"uint256"}],"name":"setDepositFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newEpochDuration","type":"uint256"}],"name":"setEpochDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"poolCommitter","type":"address"},{"internalType":"address","name":"leveragePool","type":"address"}],"internalType":"struct Vault.LeverageSet","name":"_leverageSet","type":"tuple"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"setEthLeveragePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_stakingActive","type":"bool"}],"name":"setHedgeStakingActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_btcLeverageSet","type":"uint256"},{"internalType":"uint256","name":"_ethLeverageSet","type":"uint256"}],"name":"setLeverageSetIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newManagementFee","type":"uint256"}],"name":"setManagementFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPerformanceFee","type":"uint256"}],"name":"setPerformanceFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newScale","type":"uint256"}],"name":"setScale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tcrStrategy","type":"address"}],"name":"setTcrStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newWhitelistLibrary","type":"address"}],"name":"setWhitelistLibrary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newWithdrawalFee","type":"uint256"}],"name":"setWithdrawalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shortBurn","outputs":[{"internalType":"enum IPoolCommitter.CommitType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shortMint","outputs":[{"internalType":"enum IPoolCommitter.CommitType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategyState","outputs":[{"internalType":"uint256","name":"activeSbtcAllocation","type":"uint256"},{"internalType":"uint256","name":"activeSethAllocation","type":"uint256"},{"internalType":"uint256","name":"activeGlpAllocation","type":"uint256"},{"internalType":"uint256","name":"activeBtcLeverageIndex","type":"uint256"},{"internalType":"uint256","name":"activeEthLeverageIndex","type":"uint256"},{"internalType":"uint256","name":"nextSbtcAllocation","type":"uint256"},{"internalType":"uint256","name":"nextSethAllocation","type":"uint256"},{"internalType":"uint256","name":"nextGlpAllocation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapSlippage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tcrStrategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"totalBal","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPending","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSbtcBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSethBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakeAllHedges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sbtcAmount","type":"uint256"},{"internalType":"uint256","name":"_sethAmount","type":"uint256"}],"name":"unstakePartialHedges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_chainlinkWrapper","type":"address"}],"name":"updateChainlinkWrapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_glpPricing","type":"address"}],"name":"updateGlpPricing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_hedgePricing","type":"address"}],"name":"updateHedgePricing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sbtcStaking","type":"address"}],"name":"updateSbtcStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sethStaking","type":"address"}],"name":"updateSethStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newSlippage","type":"uint256"}],"name":"updateSwapSlippage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultParams","outputs":[{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint56","name":"minimumSupply","type":"uint56"},{"internalType":"uint104","name":"cap","type":"uint104"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"stakedGlp","type":"address"},{"internalType":"address","name":"esGMX","type":"address"},{"internalType":"address","name":"glpPricing","type":"address"},{"internalType":"address","name":"hedgePricing","type":"address"},{"internalType":"address","name":"sbtcStake","type":"address"},{"internalType":"address","name":"sethStake","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultState","outputs":[{"internalType":"uint104","name":"round","type":"uint104"},{"internalType":"uint104","name":"lockedAmount","type":"uint104"},{"internalType":"uint104","name":"lastLockedAmount","type":"uint104"},{"internalType":"uint128","name":"totalPending","type":"uint128"},{"internalType":"uint128","name":"queuedWithdrawShares","type":"uint128"},{"internalType":"uint256","name":"epochStart","type":"uint256"},{"internalType":"uint256","name":"epochEnd","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleproof","type":"bytes32[]"}],"name":"whitelistDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelistLibrary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"withdrawals","outputs":[{"internalType":"uint16","name":"round","type":"uint16"},{"internalType":"uint128","name":"shares","type":"uint128"}],"stateMutability":"view","type":"function"}]

60a06040526103e8602c557f82af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000608052603780546001600160a01b03191673a72159fc390f0e3c6d415e658264c7c4051e9b871790556038805461ffff60a01b1916600160a81b1790553480156200007557600080fd5b5060405162009e3938038062009e39833981016040819052620000989162000b99565b8a8a8a8a8a8a8a8a60405180604001604052806007815260200166676c705553444360c81b81525060405180604001604052806007815260200166676c705553444360c81b81525081818160049080519060200190620000fa92919062000a86565b5080516200011090600590602084019062000a86565b50506001600655506007805460ff191690556001600160a01b038a16620001685760405162461bcd60e51b81526020600482015260076024820152660857d85cdcd95d60ca1b60448201526064015b60405180910390fd5b6001600160a01b038916620001b15760405162461bcd60e51b815260206004820152600e60248201526d0857d99959549958da5c1a595b9d60921b60448201526064016200015f565b6001600160a01b038816620001f45760405162461bcd60e51b815260206004820152600860248201526710afb5b2b2b832b960c11b60448201526064016200015f565b62000204620f4240606462000ebf565b8610620002545760405162461bcd60e51b815260206004820152601760248201527f5f706572666f726d616e6365466565203e3d203130302500000000000000000060448201526064016200015f565b62000264620f4240606462000ebf565b8710620002b45760405162461bcd60e51b815260206004820152601660248201527f5f6d616e6167656d656e74466565203e3d20313030250000000000000000000060448201526064016200015f565b620002c4620f4240606462000ebf565b8510620003145760405162461bcd60e51b815260206004820152601360248201527f5f6465706f736974466565203e3d20313030250000000000000000000000000060448201526064016200015f565b6000836020015166ffffffffffffff1611620003655760405162461bcd60e51b815260206004820152600f60248201526e215f6d696e696d756d537570706c7960881b60448201526064016200015f565b600083604001516001600160681b031611620003ac5760405162461bcd60e51b81526020600482015260056024820152640215f6361760dc1b60448201526064016200015f565b826020015166ffffffffffffff1683604001516001600160681b031611620004175760405162461bcd60e51b815260206004820152601660248201527f5f636170203c3d205f6d696e696d756d537570706c790000000000000000000060448201526064016200015f565b6000825111620004535760405162461bcd60e51b8152602060048201526006602482015265215f6e616d6560d01b60448201526064016200015f565b6000815111620004915760405162461bcd60e51b81526020600482015260086024820152670857dcde5b589bdb60c21b60448201526064016200015f565b602280546001600160a01b03199081166001600160a01b038d8116919091179092556023805482168c84161790556024805482168b8416179055602688905560278990556028879055600060298190558551600d8054602089015160408a015160ff9094166001600160401b03199092169190911761010066ffffffffffffff909216820217600160401b600160a81b031916680100000000000000006001600160681b0394851602179091556060880151600e805486169187169190911790556080880151600f8054861691871691909117905560a088015160108054861691871691909117905560c088015160118054861691871691909117905560e08801516012805486169187169190911790558701516013805485169186169190911790556101208701516014805485169190951617909355601580546001600160681b03191693881693909317909255602580549091169055602a805460ff1916905562015180602b556200060690336200097f565b620006327ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab896200097f565b6200065e7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775336200097f565b50505050506001600160a01b03871615159450620006b393505050505760405162461bcd60e51b815260206004820152600c60248201526b10afb3b63826b0b730b3b2b960a11b60448201526064016200015f565b6001600160a01b038316620006f95760405162461bcd60e51b815260206004820152600b60248201526a10afb3b6382937baba32b960a91b60448201526064016200015f565b6001600160a01b038116620007435760405162461bcd60e51b815260206004820152600f60248201526e10afbab734b9bbb0b82937baba32b960891b60448201526064016200015f565b60e08401516001600160a01b03166200078f5760405162461bcd60e51b815260206004820152600d60248201526c21686564676550726963696e6760981b60448201526064016200015f565b60c08401516001600160a01b0316620007d95760405162461bcd60e51b815260206004820152600b60248201526a21676c7050726963696e6760a81b60448201526064016200015f565b604051620007e79062000b15565b604051809103906000f08015801562000804573d6000803e3d6000fd5b50603980546001600160a01b0319166001600160a01b0392909216919091179055620008cd6200083360035490565b60608601516040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b1580156200087957600080fd5b505afa1580156200088e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008b4919062000d38565b866000015160ff166200098f60201b62005b531760201c565b6001600160681b0395909516600090815260086020526040902094909455603580546001600160a01b03199081166001600160a01b039384161790915560368054821693831693909317909255603a805483169482169490941790935560e08201516032805490921690841617905560c00151603180546001600160a81b031916610100929093169190910260ff191691909117905550506064603455505060036030555050600019602f5562000f34565b6200098b8282620009d3565b5050565b6000806200099f83600a62000df6565b905060008511620009b15780620009ca565b84620009be858362000ebf565b620009ca919062000d8a565b95945050505050565b620009df828262000a5b565b6200098b576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905562000a173390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff165b92915050565b82805462000a949062000ee1565b90600052602060002090601f01602090048101928262000ab8576000855562000b03565b82601f1062000ad357805160ff191683800117855562000b03565b8280016001018555821562000b03579182015b8281111562000b0357825182559160200191906001019062000ae6565b5062000b1192915062000b23565b5090565b61044080620099f983390190565b5b8082111562000b11576000815560010162000b24565b80516001600160a01b038116811462000b5257600080fd5b919050565b80516001600160681b038116811462000b5257600080fd5b805166ffffffffffffff8116811462000b5257600080fd5b805160ff8116811462000b5257600080fd5b60008060008060008060008060008060008b8d0361028081121562000bbd57600080fd5b62000bc88d62000b3a565b9b5062000bd860208e0162000b3a565b9a5062000be860408e0162000b3a565b995060608d0151985060808d0151975060a08d0151965062000c0d60c08e0162000b57565b955061014060df198201121562000c2357600080fd5b5062000c2e62000d52565b62000c3c60e08e0162000b87565b815261010062000c4e818f0162000b6f565b602083015262000c626101208f0162000b57565b604083015262000c766101408f0162000b3a565b606083015262000c8a6101608f0162000b3a565b608083015262000c9e6101808f0162000b3a565b60a083015262000cb26101a08f0162000b3a565b60c083015262000cc66101c08f0162000b3a565b60e083015262000cda6101e08f0162000b3a565b9082015262000ced6102008e0162000b3a565b610120820152935062000d046102208d0162000b3a565b925062000d156102408d0162000b3a565b915062000d266102608d0162000b3a565b90509295989b509295989b9093969950565b60006020828403121562000d4b57600080fd5b5051919050565b60405161014081016001600160401b038111828210171562000d8457634e487b7160e01b600052604160045260246000fd5b60405290565b60008262000da857634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111562000dee57816000190482111562000dd25762000dd262000f1e565b8085161562000de057918102915b93841c939080029062000db2565b509250929050565b600062000e04838362000e0b565b9392505050565b60008262000e1c5750600162000a80565b8162000e2b5750600062000a80565b816001811462000e44576002811462000e4f5762000e6f565b600191505062000a80565b60ff84111562000e635762000e6362000f1e565b50506001821b62000a80565b5060208310610133831016604e8410600b841016171562000e94575081810a62000a80565b62000ea0838362000dad565b806000190482111562000eb75762000eb762000f1e565b029392505050565b600081600019048311821515161562000edc5762000edc62000f1e565b500290565b600181811c9082168062000ef657607f821691505b6020821081141562000f1857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60805160601c618a7562000f846000396000818161104a01528181613ead01528181617622015281816176d701528181617795015281816177d401528181617ba60152617bee0152618a756000f3fe608060405234801561001057600080fd5b50600436106107165760003560e01c806370a08231116103a8578063a9059cbb116101f4578063d57773f71161011a578063eb13fa6c116100b8578063f5d3cf8b11610087578063f5d3cf8b1461122a578063f756fa2114611232578063f887ea401461123a578063fe56e2321461124d57600080fd5b8063eb13fa6c146111e8578063eced5526146111fb578063ef06e72c14611204578063ef8b30f71461121757600080fd5b8063dfcbacf0116100f4578063dfcbacf01461119c578063e10dfa57146111af578063e1393747146111c2578063e74b981b146111d557600080fd5b8063d57773f714611152578063dd62ed3e1461115b578063df7cc6181461119457600080fd5b8063b97f8c0911610192578063cd56e5ab11610161578063cd56e5ab146110dd578063cdcae7ef146110f0578063ce7c2ac21461112c578063d547741f1461113f57600080fd5b8063b97f8c091461109b578063bcdb446b146110af578063c099a9e3146110b7578063c6e6f592146110ca57600080fd5b8063ad5c4648116101ce578063ad5c464814611045578063b3d7f6b91461106c578063b6b55f251461107f578063b8c50b2d1461109257600080fd5b8063a9059cbb1461100c578063ac1e50251461101f578063aced16611461103257600080fd5b80638c93c39b116102d95780639be43daa11610277578063a6d99f2411610246578063a6d99f2414610fca578063a6f7f5d614610fdd578063a7956e4914610fe6578063a80b0a7d14610ff957600080fd5b80639be43daa14610ebe5780639fcc2d7514610ed1578063a217fddf14610faf578063a457c2d714610fb757600080fd5b806394bf804d116102b357806394bf804d14610e5a57806395d89b4114610e6d57806399530b0614610e755780639baa5aa614610e9557600080fd5b80638c93c39b14610dfd57806391b4c82714610e1057806391d1485414610e2357600080fd5b80637ebdcda711610346578063867432fe11610320578063867432fe14610dc357806387153eb114610dcb5780638778878214610deb5780638bc7e8c414610df457600080fd5b80637ebdcda714610d3757806381b80a0214610d4a5780638429180514610db057600080fd5b806378d01b961161038257806378d01b9614610cb25780637a9262a214610cba5780637c8ddecb14610d115780637e108d5214610d2457600080fd5b806370a0823114610c5a5780637309a6c014610c8357806375b238fc14610c8b57600080fd5b806338d52e0f116105675780634ff0876a116104985780635f81bbcb116104365780636cecbc26116104055780636cecbc2614610c145780636e0f9fdf14610c215780636e553f6514610c3457806370897b2314610c4757600080fd5b80635f81bbcb14610bd357806363d8882a14610bf057806367a5279314610bf857806367f5e4b814610c0157600080fd5b806358c700a31161047257806358c700a314610baf5780635c975abb14610bb85780635cb180b014610bc35780635f4d490714610bcb57600080fd5b80634ff0876a14610b68578063503c70aa14610b7157806352f8b1b614610b9c57600080fd5b80634690484011610505578063490ae210116104df578063490ae21014610b2257806349ce1f6f14610b355780634cbc93be14610b425780634d54b2d914610b5557600080fd5b80634690484014610ae457806346ec5d3c14610af757806347786d3714610b0f57600080fd5b80633edc3519116105415780633edc351914610a9e5780633f23bb7314610ab15780633f90916a14610ac4578063421c308714610adc57600080fd5b806338d52e0f14610a655780633950935114610a785780633aeb78c214610a8b57600080fd5b806318160ddd1161064c57806327cfe856116105ea578063355274ea116105b9578063355274ea146109ed578063364bc15a14610a0a57806336568abe14610a31578063389b12cb14610a4457600080fd5b806327cfe856146109935780632f2ff15d146109b257806330024dfe146109c5578063313ce567146109d857600080fd5b806323b872dd1161062657806323b872dd146108b6578063248a9ca3146108c95780632712b539146108ec5780632728f333146108ff57600080fd5b806318160ddd146108925780631aedeabe1461089a578063220bd2ce146108a357600080fd5b8063095ea7b3116106b95780630a28a477116106935780630a28a477146107f85780630ce69f701461080b57806311b4e2531461081e57806316a1c14f1461087f57600080fd5b8063095ea7b3146107c9578063098d3228146107dc57806309f88266146107e557600080fd5b806302191980116106f5578063021919801461076c57806306df14161461077657806306fdde03146107a157806307a2d13a146107b657600080fd5b80627e21921461071b57806301e1d1141461074157806301ffc9a714610749575b600080fd5b61072e61072936600461839d565b611260565b6040519081526020015b60405180910390f35b61072e611758565b61075c6107573660046182e1565b611a4a565b6040519015158152602001610738565b610774611ab3565b005b603954610789906001600160a01b031681565b6040516001600160a01b039091168152602001610738565b6107a9611b17565b604051610738919061869b565b61072e6107c436600461828c565b611ba9565b61075c6107d7366004618228565b611bde565b61072e60001981565b6107746107f3366004618487565b611bf4565b61072e61080636600461828c565b6120ba565b6107746108193660046184a9565b6120f7565b601a54601b54601c54601d54601e54601f54602054602154610844979695949392919088565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e082015261010001610738565b61077461088d36600461819e565b6127f6565b60035461072e565b61072e60345481565b603754610789906001600160a01b031681565b61075c6108c43660046181ec565b6128c8565b61072e6108d736600461828c565b60009081526020819052604090206001015490565b6107746108fa36600461819e565b612987565b601554601654601754601854601954610944946001600160681b0380821695600160681b92839004821695918116949290046001600160801b03908116939116919087565b604080516001600160681b039889168152968816602088015294909616938501939093526001600160801b03918216606085015216608083015260a082015260c081019190915260e001610738565b61099d6201518081565b60405163ffffffff9091168152602001610738565b6107746109c03660046182be565b612afc565b6107746109d336600461828c565b612b27565b600d5460405160ff9091168152602001610738565b600d546801000000000000000090046001600160681b031661072e565b61072e7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab81565b610774610a3f3660046182be565b612b86565b603854610a5890600160a01b900460ff1681565b604051610738919061868d565b602254610789906001600160a01b031681565b61075c610a86366004618228565b612c12565b610774610a99366004618252565b612c4e565b610774610aac36600461828c565b612cbb565b61072e610abf36600461819e565b612d1a565b601654600160681b90046001600160801b031661072e565b61072e612d59565b602354610789906001600160a01b031681565b6031546107899061010090046001600160a01b031681565b610774610b1d36600461828c565b612df0565b610774610b3036600461828c565b612eea565b602a5461075c9060ff1681565b610774610b50366004618487565b612fe1565b602554610789906001600160a01b031681565b61072e602b5481565b602e54610b84906001600160801b031681565b6040516001600160801b039091168152602001610738565b603654610789906001600160a01b031681565b61072e602f5481565b60075460ff1661075c565b610774613117565b6107746134bb565b610bdb6135b7565b60408051928352602083019190915201610738565b610774613600565b61072e60285481565b610774610c0f36600461828c565b613662565b60315461075c9060ff1681565b610774610c2f36600461830b565b61370e565b61072e610c423660046182be565b613865565b610774610c5536600461828c565b6139a9565b61072e610c6836600461819e565b6001600160a01b031660009081526001602052604090205490565b610774613aa0565b61072e7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b610774613bc6565b610cef610cc836600461819e565b60096020526000908152604090205461ffff8116906201000090046001600160801b031682565b6040805161ffff90931683526001600160801b03909116602083015201610738565b610774610d1f36600461828c565b613fb4565b610774610d3236600461828c565b6140f7565b610774610d4536600461819e565b614197565b610d86610d5836600461828c565b600a602052600090815260409020805460018201546002909201546001600160a01b03918216928216911683565b604080516001600160a01b0394851681529284166020840152921691810191909152606001610738565b610774610dbe36600461819e565b614274565b61072e6142f0565b61072e610dd936600461828c565b60086020526000908152604090205481565b61072e60265481565b61072e60295481565b610774610e0b36600461819e565b614419565b610774610e1e36600461830b565b6144eb565b61075c610e313660046182be565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b610774610e683660046182be565b614642565b6107a9614775565b6015546001600160681b031660009081526008602052604090205461072e565b610b84610ea336600461828c565b600c602052600090815260409020546001600160801b031681565b610774610ecc36600461828c565b614784565b600d54600e54600f54601054601154601254601354601454610f3b9760ff811697610100820466ffffffffffffff1697680100000000000000009092046001600160681b0316966001600160a01b039182169692821695908216949282169390821692821691168a565b6040805160ff909b168b5266ffffffffffffff90991660208b01526001600160681b03909716978901979097526001600160a01b039485166060890152928416608088015290831660a0870152821660c0860152811660e08501529182166101008401521661012082015261014001610738565b61072e600081565b61075c610fc5366004618228565b6148c7565b603354610789906001600160a01b031681565b61072e60275481565b610774610ff4366004618487565b614978565b61077461100736600461819e565b614d76565b61075c61101a366004618228565b614e65565b61077461102d36600461828c565b614e72565b602454610789906001600160a01b031681565b6107897f000000000000000000000000000000000000000000000000000000000000000081565b61072e61107a36600461828c565b614f69565b61077461108d36600461828c565b614f87565b61072e60305481565b603854610a5890600160a81b900460ff1681565b610774615070565b603254610789906001600160a01b031681565b61072e6110d836600461828c565b615165565b603554610789906001600160a01b031681565b610d866110fe36600461828c565b600b602052600090815260409020805460018201546002909201546001600160a01b03918216928216911683565b61072e61113a36600461819e565b615193565b61077461114d3660046182be565b6151b3565b61072e602d5481565b61072e6111693660046181b9565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b61072e6151d9565b6107746111aa36600461819e565b6152a1565b6107746111bd366004618408565b615373565b6107746111d0366004618487565b615558565b6107746111e336600461819e565b61568b565b6107746111f636600461819e565b6157bb565b61072e602c5481565b603854610789906001600160a01b031681565b61072e61122536600461828c565b615837565b610774615874565b61077461598f565b603a54610789906001600160a01b031681565b61077461125b36600461828c565b615a2a565b6000600260065414156112a85760405162461bcd60e51b815260206004820152601f60248201526000805160206189e083398151915260448201526064015b60405180910390fd5b60026006553360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff166113155760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b600f546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561135957600080fd5b505afa15801561136d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139191906182a5565b6031546040516307106dbd60e41b8152600481018390526000602482018190529293506101009091046001600160a01b031690637106dbd09060440160206040518083038186803b1580156113e557600080fd5b505afa1580156113f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141d91906182a5565b6dffffffffffffffffffffffffffff898116601f558881166020558716602155602d54601680546cffffffffffffffffffffffffff19166001600160681b03909216919091179055601a5490915060009015158061147c5750601b5415155b801561148a575060315460ff165b80156114935750845b156114ad576114a0615b8f565b6114aa908261875d565b90505b602a805460ff19166001179055851561153457866dffffffffffffffffffffffffffff1682111561151f576114fa6114f56dffffffffffffffffffffffffffff8916846188c9565b615da6565b611504908261875d565b6dffffffffffffffffffffffffffff8816601c559050611534565b611527615f27565b611531908261875d565b90505b6032546000906001600160a01b03166395dc67cc6115506142f0565b6040518263ffffffff1660e01b815260040161156e91815260200190565b60206040518083038186803b15801561158657600080fd5b505afa15801561159a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115be91906182a5565b6032549091506000906001600160a01b031663e4317a116115dd6151d9565b6040518263ffffffff1660e01b81526004016115fb91815260200190565b60206040518083038186803b15801561161357600080fd5b505afa158015611627573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164b91906182a5565b6015546031546040516307106dbd60e41b815260048101899052600060248201529293507f05400c5314f99bd15635b7aa9f39d4b3b3f6c6367b73c2c72a1c798b0a706cb2926001600160681b0390921691429187916101009091046001600160a01b031690637106dbd09060440160206040518083038186803b1580156116d257600080fd5b505afa1580156116e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170a91906182a5565b604080516001600160681b03909516855260208501939093529183015260608201526080810183905260a0810184905260c00160405180910390a15050600160065598975050505050505050565b600e546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a082319060240160206040518083038186803b1580156117a057600080fd5b505afa1580156117b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d891906182a5565b600f546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b15801561182157600080fd5b505afa158015611835573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185991906182a5565b905060006118656142f0565b905060006118716151d9565b6032546040517fe4317a11000000000000000000000000000000000000000000000000000000008152600481018390529192506001600160a01b03169063e4317a119060240160206040518083038186803b1580156118cf57600080fd5b505afa1580156118e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190791906182a5565b6032546040517f95dc67cc000000000000000000000000000000000000000000000000000000008152600481018590526001600160a01b03909116906395dc67cc9060240160206040518083038186803b15801561196457600080fd5b505afa158015611978573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199c91906182a5565b6031546040516307106dbd60e41b815260048101879052600060248201526101009091046001600160a01b031690637106dbd09060440160206040518083038186803b1580156119eb57600080fd5b505afa1580156119ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2391906182a5565b611a2d908761875d565b611a37919061875d565b611a41919061875d565b94505050505090565b60006001600160e01b031982167f7965db0b000000000000000000000000000000000000000000000000000000001480611aad57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b336000908152600080516020618a00833981519152602052604090205460ff16611b0d5760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b611b15615fd1565b565b606060048054611b2690618923565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5290618923565b8015611b9f5780601f10611b7457610100808354040283529160200191611b9f565b820191906000526020600020905b815481529060010190602001808311611b8257829003601f168201915b5050505050905090565b6015546001600160681b0316600090815260086020526040812054600d54611bd7908490839060ff16616071565b9392505050565b6000611beb3384846160e2565b50600192915050565b3360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff16611c5c5760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b601e54601d546000828152600a60205260408082205490516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015611cb157600080fd5b505afa158015611cc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce991906182a5565b6000838152600b60205260408082205490516370a0823160e01b815230600482015292935090916001600160a01b03909116906370a082319060240160206040518083038186803b158015611d3d57600080fd5b505afa158015611d51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7591906182a5565b905085811015611dc75760405162461bcd60e51b815260206004820152601f60248201527f544352474d583a2021617661696c61626c6520736274632062616c616e636500604482015260640161129f565b84821015611e175760405162461bcd60e51b815260206004820152601f60248201527f544352474d583a2021617661696c61626c6520736574682062616c616e636500604482015260640161129f565b8515611f48576000838152600b6020526040902060028101549054611e49916001600160a01b0391821691168861621f565b6000838152600b6020526040808220600101546039546038549251630112af1560e11b81526001600160a01b039283169463f14fcbc89493909216926302255e2a92611ea7928d92600160a81b900460ff1691908190600401618707565b60206040518083038186803b158015611ebf57600080fd5b505afa158015611ed3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef791906182a5565b6040518263ffffffff1660e01b8152600401611f1591815260200190565b600060405180830381600087803b158015611f2f57600080fd5b505af1158015611f43573d6000803e3d6000fd5b505050505b8415612079576000848152600a6020526040902060028101549054611f7a916001600160a01b0391821691168761621f565b6000848152600a6020526040808220600101546039546038549251630112af1560e11b81526001600160a01b039283169463f14fcbc89493909216926302255e2a92611fd8928c92600160a81b900460ff1691908190600401618707565b60206040518083038186803b158015611ff057600080fd5b505afa158015612004573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202891906182a5565b6040518263ffffffff1660e01b815260040161204691815260200190565b600060405180830381600087803b15801561206057600080fd5b505af1158015612074573d6000803e3d6000fd5b505050505b60408051878152602081018790527fd0fbb40564f5f489884ffa78fe7d986f43c365ff7e233587b7cbea70c7e3bf31910160405180910390a1505050505050565b6000806120cb620f42406064618882565b6029546120d89085618882565b6120e29190618775565b6120ec90846188c9565b9050611bd781611ba9565b3360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff1661215f5760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b600260065414156121a05760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b6002600655600080806121b16135b7565b600e546040516370a0823160e01b81523060048201529193506000925083916001600160a01b03909116906370a082319060240160206040518083038186803b1580156121fd57600080fd5b505afa158015612211573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223591906182a5565b61223f91906188c9565b6032549091506000906001600160a01b03166395dc67cc61225e6142f0565b6040518263ffffffff1660e01b815260040161227c91815260200190565b60206040518083038186803b15801561229457600080fd5b505afa1580156122a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122cc91906182a5565b6032549091506000906001600160a01b031663e4317a116122eb6151d9565b6040518263ffffffff1660e01b815260040161230991815260200190565b60206040518083038186803b15801561232157600080fd5b505afa158015612335573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235991906182a5565b9050600088600281111561236f5761236f61898f565b141561242b57818910156123bb5760405162461bcd60e51b81526020600482015260136024820152722a21a923a6ac1d1010b0b63637b1b0ba34b7b760691b604482015260640161129f565b6123c5828a6188c9565b95508583116124165760405162461bcd60e51b815260206004820152601760248201527f544352474d583a204f76657220616c6c6f636174696f6e000000000000000000604482015260640161129f565b601b899055612426600087614978565b61255b565b600188600281111561243f5761243f61898f565b141561255b578189111561248b5760405162461bcd60e51b81526020600482015260136024820152722a21a923a6ac1d1010b0b63637b1b0ba34b7b760691b604482015260640161129f565b61249589836188c9565b6032546040517f6ad41c53000000000000000000000000000000000000000000000000000000008152600481018390529197506000916001600160a01b0390911690636ad41c539060240160206040518083038186803b1580156124f857600080fd5b505afa15801561250c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253091906182a5565b601b8b905560315490915060ff161561254e5761254e600082612fe1565b612559600082611bf4565b505b600087600281111561256f5761256f61898f565b14156126b557808a10156125bb5760405162461bcd60e51b81526020600482015260136024820152722a21a923a6ac1d1010b0b63637b1b0ba34b7b760691b604482015260640161129f565b6125c5818b6188c9565b600e546040516370a0823160e01b815230600482015291965085916001600160a01b03909116906370a082319060240160206040518083038186803b15801561260d57600080fd5b505afa158015612621573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264591906182a5565b61264f91906188c9565b92508483116126a05760405162461bcd60e51b815260206004820152601760248201527f544352474d583a204f76657220616c6c6f636174696f6e000000000000000000604482015260640161129f565b601a8a90556126b0856000614978565b6127e5565b60018760028111156126c9576126c961898f565b14156127e557808a11156127155760405162461bcd60e51b81526020600482015260136024820152722a21a923a6ac1d1010b0b63637b1b0ba34b7b760691b604482015260640161129f565b61271f8a826188c9565b6032546040517f8e9ff6de000000000000000000000000000000000000000000000000000000008152600481018390529196506000916001600160a01b0390911690638e9ff6de9060240160206040518083038186803b15801561278257600080fd5b505afa158015612796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ba91906182a5565b601a8c905560315490915060ff16156127d8576127d8816000612fe1565b6127e3816000611bf4565b505b505060016006555050505050505050565b336000908152600080516020618a00833981519152602052604090205460ff166128505760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b6001600160a01b0381166128a65760405162461bcd60e51b815260206004820152601660248201527f544352474d583a20212073627463206164647265737300000000000000000000604482015260640161129f565b601380546001600160a01b0319166001600160a01b0392909216919091179055565b60006128d5848484616341565b6001600160a01b03841660009081526002602090815260408083203384529091529020548281101561296f5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000606482015260840161129f565b61297c85338584036160e2565b506001949350505050565b336000908152600080516020618a00833981519152602052604090205460ff166129e15760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b323314612a305760405162461bcd60e51b815260206004820152600760248201527f6f6e6c79454f4100000000000000000000000000000000000000000000000000604482015260640161129f565b602f544211612a815760405162461bcd60e51b815260206004820152601360248201527f6d6967726174696f6e206e6f7420726561647900000000000000000000000000604482015260640161129f565b6036546040517fef9aacfd0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063ef9aacfd90602401600060405180830381600087803b158015612ae157600080fd5b505af1158015612af5573d6000803e3d6000fd5b5050505050565b600082815260208190526040902060010154612b188133616558565b612b2283836165d6565b505050565b336000908152600080516020618a00833981519152602052604090205460ff16612b815760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b602b55565b6001600160a01b0381163314612c045760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c660000000000000000000000000000000000606482015260840161129f565b612c0e8282616674565b5050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091611beb918590612c4990869061875d565b6160e2565b336000908152600080516020618a00833981519152602052604090205460ff16612ca85760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b6031805460ff1916911515919091179055565b336000908152600080516020618a00833981519152602052604090205460ff16612d155760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b602c55565b600d546015546001600160681b0316600090815260086020526040812054909160ff1690612d51612d4a85615193565b8284616071565b949350505050565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015612d9d57600080fd5b505afa158015612db1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd591906182a5565b601654612deb91906001600160681b031661875d565b905090565b336000908152600080516020618a00833981519152602052604090205460ff16612e4a5760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b612e53816166f3565b600d5460408051680100000000000000009092046001600160681b03168252602082018390527f5f86edbb9d92228a9edc3f0ebc0f001bda1ea345ac7335e0eeef3504b31d1a1c910160405180910390a1600d80546001600160681b0390921668010000000000000000027fffffffffffffffffffffff00000000000000000000000000ffffffffffffffff909216919091179055565b336000908152600080516020618a00833981519152602052604090205460ff16612f445760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b612f52620f42406014618882565b8110612fa05760405162461bcd60e51b815260206004820152601360248201527f496e76616c6964206465706f7369742066656500000000000000000000000000604482015260640161129f565b60285460408051918252602082018390527ff1aec186c439f8430fe16b74b0ea6e2bb43228b3357c59efd9132775bd6c704b910160405180910390a1602855565b3360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff166130495760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b81156130ae57601354604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561309557600080fd5b505af11580156130a9573d6000803e3d6000fd5b505050505b8015612c0e57601454604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d906024015b600060405180830381600087803b1580156130fb57600080fd5b505af115801561310f573d6000803e3d6000fd5b505050505050565b3360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff1661317f5760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b600260065414156131c05760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b60026006556131cd615874565b60315460ff16156131e0576131e061674a565b602154602e546015546001600160681b03166000908152600c602052604081205490918291613223916001600160801b03908116911661321e611758565b616986565b6015549193509150600090600c908290613248906001906001600160681b03166188a1565b6001600160681b0316815260208101919091526040016000205460175461327b916001600160801b03908116911661875d565b905061328681616c31565b601780546001600160801b038381166fffffffffffffffffffffffffffffffff1992831617909255602e805492851692909116919091179055602d839055601a54601b54603154600f546040516370a0823160e01b81523060048201526000926001600160a01b03610100909104811692637106dbd0929116906370a082319060240160206040518083038186803b15801561332157600080fd5b505afa158015613335573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061335991906182a5565b6040516001600160e01b031960e084901b16815260048101919091526000602482015260440160206040518083038186803b15801561339757600080fd5b505afa1580156133ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cf91906182a5565b602e549091506000906001600160801b0316886133ec858761875d565b6133f6919061875d565b613400919061875d565b905061340a611758565b81111561344f5760405162461bcd60e51b81526020600482015260136024820152722a21a923a6ac1d1010b0b63637b1b0ba34b7b760691b604482015260640161129f565b8188111561346457613464610d1f838a6188c9565b602d54602e54604080519283526001600160801b0390911660208301527f4f1cb89ff72ff185e8715403bbe7a7fefdd1688d3b1f0e31b72287c1e543ee0e910160405180910390a150506001600655505050505050565b336000908152600080516020618a00833981519152602052604090205460ff166135155760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b600019602f54146135685760405162461bcd60e51b815260206004820152601160248201527f616c726561647920696e69746961746564000000000000000000000000000000604482015260640161129f565b613575426212750061875d565b602f8190556040805142815260208101929092527f1940d1e39a763cc5a036d3c63573b9e076dfbca3847dd1b1726fbdff524f6cc391015b60405180910390a1565b602e546015546001600160681b03166000908152600c6020526040812054909182916135f7916001600160801b0390811691166135f2611758565b616c88565b90939092509050565b336000908152600080516020618a00833981519152602052604090205460ff1661365a5760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b611b15616df2565b336000908152600080516020618a00833981519152602052604090205460ff166136bc5760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b806137095760405162461bcd60e51b815260206004820152601e60248201527f544352474d583a2021205f6e6577536c697070616765206973207a65726f0000604482015260640161129f565b603455565b336000908152600080516020618a00833981519152602052604090205460ff166137685760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b60208201516001600160a01b03166137b85760405162461bcd60e51b81526020600482015260136024820152720858591913995dd3195d995c9859d9541bdbdb606a1b604482015260640161129f565b60408201516001600160a01b03166138085760405162461bcd60e51b81526020600482015260136024820152720858591913995dd3195d995c9859d9541bdbdb606a1b604482015260640161129f565b6000908152600b6020908152604091829020835181546001600160a01b03199081166001600160a01b0392831617835592850151600183018054851691831691909117905593909201516002909201805490911691909216179055565b6000600260065414156138a85760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b6002600655826138e45760405162461bcd60e51b815260206004820152600760248201526608585b5bdd5b9d60ca1b604482015260640161129f565b6001600160a01b03821661393a5760405162461bcd60e51b815260206004820152600960248201527f216372656469746f720000000000000000000000000000000000000000000000604482015260640161129f565b6025546001600160a01b0316156139935760405162461bcd60e51b815260206004820152601160248201527f77686974656c69737420656e61626c6564000000000000000000000000000000604482015260640161129f565b61399d8383616e75565b60016006559392505050565b336000908152600080516020618a00833981519152602052604090205460ff16613a035760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b613a11620f42406064618882565b8110613a5f5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420706572666f726d616e636520666565000000000000000000604482015260640161129f565b60265460408051918252602082018390527f24867dfb6fcb9970a07be21024956524abe7a1837faa903ff0e99aaa40cf893e910160405180910390a1602655565b3360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff16613b085760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b601354604080516374fd6c7760e11b815290516001600160a01b039092169163e9fad8ee9160048082019260009290919082900301818387803b158015613b4e57600080fd5b505af1158015613b62573d6000803e3d6000fd5b5050601454604080516374fd6c7760e11b815290516001600160a01b03909216935063e9fad8ee925060048082019260009290919082900301818387803b158015613bac57600080fd5b505af1158015613bc0573d6000803e3d6000fd5b50505050565b336000908152600080516020618a00833981519152602052604090205460ff16613c205760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b601e54601d546000828152600a602052604080822054601454915163095ea7b360e01b81526001600160a01b0392831660048201526024810193909352169063095ea7b390604401602060405180830381600087803b158015613c8257600080fd5b505af1158015613c96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cba919061826f565b506000818152600b602052604080822054601354915163095ea7b360e01b81526001600160a01b0392831660048201526024810193909352169063095ea7b390604401602060405180830381600087803b158015613d1757600080fd5b505af1158015613d2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d4f919061826f565b50600e546000828152600b602052604080822060020154905163095ea7b360e01b81526001600160a01b03918216600482015260248101929092529091169063095ea7b390604401602060405180830381600087803b158015613db157600080fd5b505af1158015613dc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613de9919061826f565b50600e546000838152600a602052604080822060020154905163095ea7b360e01b81526001600160a01b03918216600482015260248101929092529091169063095ea7b390604401602060405180830381600087803b158015613e4b57600080fd5b505af1158015613e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e83919061826f565b50603a5460405163095ea7b360e01b81526001600160a01b039182166004820152600060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b390604401602060405180830381600087803b158015613ef357600080fd5b505af1158015613f07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f2b919061826f565b50600e5460355460405163095ea7b360e01b81526001600160a01b0391821660048201526000602482015291169063095ea7b390604401602060405180830381600087803b158015613f7c57600080fd5b505af1158015613f90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b22919061826f565b3360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff1661401c5760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b603554600e54614039916001600160a01b0391821691168361621f565b600061404682600a617149565b603654600e546040517f364e23110000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152602481018690526044810184905260006064820152929350169063364e231190608401602060405180830381600087803b1580156140bf57600080fd5b505af11580156140d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2291906182a5565b600260065414156141385760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b6002600655602a5460ff161561417857601554614173908290614165906001600160681b03166001618732565b6001600160681b0316617179565b61418f565b60155461418f9082906001600160681b0316617179565b506001600655565b336000908152600080516020618a00833981519152602052604090205460ff166141f15760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b6001600160a01b0381166142525760405162461bcd60e51b815260206004820152602260248201527f544352474d583a202120636861696e6c696e6b57726170706572206164647265604482015261737360f01b606482015260840161129f565b603880546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600080516020618a00833981519152602052604090205460ff166142ce5760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b601e546000908152600a60205260408082205490516370a0823160e01b815230600482015282916001600160a01b0316906370a082319060240160206040518083038186803b15801561434257600080fd5b505afa158015614356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061437a91906182a5565b60315490915060ff1615614414576014546040516370a0823160e01b81523060048201526001600160a01b03909116906370a08231906024015b60206040518083038186803b1580156143cc57600080fd5b505afa1580156143e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061440491906182a5565b61440e908261875d565b91505090565b919050565b336000908152600080516020618a00833981519152602052604090205460ff166144735760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b6001600160a01b0381166144c95760405162461bcd60e51b815260206004820152601660248201527f544352474d583a20212073657468206164647265737300000000000000000000604482015260640161129f565b601480546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600080516020618a00833981519152602052604090205460ff166145455760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b60208201516001600160a01b03166145955760405162461bcd60e51b81526020600482015260136024820152720858591913995dd3195d995c9859d9541bdbdb606a1b604482015260640161129f565b60408201516001600160a01b03166145e55760405162461bcd60e51b81526020600482015260136024820152720858591913995dd3195d995c9859d9541bdbdb606a1b604482015260640161129f565b6000908152600a6020908152604091829020835181546001600160a01b03199081166001600160a01b0392831617835592850151600183018054851691831691909117905593909201516002909201805490911691909216179055565b600260065414156146835760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b6002600655816146d55760405162461bcd60e51b815260206004820152600860248201527f215f736861726573000000000000000000000000000000000000000000000000604482015260640161129f565b6001600160a01b03811661472b5760405162461bcd60e51b815260206004820152600a60248201527f215f726563656976657200000000000000000000000000000000000000000000604482015260640161129f565b6015546001600160681b0316600081815260086020526040812054600d5490919061475c908690849060ff16616071565b90506147688185616e75565b5050600160065550505050565b606060058054611b2690618923565b600260065414156147c55760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b6002600655806148175760405162461bcd60e51b815260206004820152600a60248201527f216e756d526f756e647300000000000000000000000000000000000000000000604482015260640161129f565b6015546001600160681b031660005b828110156148bd57600061483a828461875d565b600081815260086020526040902054909150156148995760405162461bcd60e51b815260206004820152600b60248201527f496e697469616c697a6564000000000000000000000000000000000000000000604482015260640161129f565b600090815260086020526040902060019055806148b58161895e565b915050614826565b5050600160065550565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156149615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161129f565b61496e33858584036160e2565b5060019392505050565b3360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff166149e05760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b602e54600e546040516370a0823160e01b81523060048201526000926001600160801b0316916001600160a01b0316906370a082319060240160206040518083038186803b158015614a3157600080fd5b505afa158015614a45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a6991906182a5565b614a7391906188c9565b905080614a80848461875d565b1115614ace5760405162461bcd60e51b815260206004820152601a60248201527f544352474d583a2021617661696c61626c652062616c616e6365000000000000604482015260640161129f565b601e54601d548415614c05576000818152600b6020526040902060020154600e54614b06916001600160a01b0391821691168761621f565b6000818152600b6020526040808220600101546039546038549251630112af1560e11b81526001600160a01b039283169463f14fcbc89493909216926302255e2a92614b64928c92600160a01b900460ff1691908190600401618707565b60206040518083038186803b158015614b7c57600080fd5b505afa158015614b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bb491906182a5565b6040518263ffffffff1660e01b8152600401614bd291815260200190565b600060405180830381600087803b158015614bec57600080fd5b505af1158015614c00573d6000803e3d6000fd5b505050505b8315614d36576000828152600a6020526040902060020154600e54614c37916001600160a01b0391821691168661621f565b6000828152600a6020526040808220600101546039546038549251630112af1560e11b81526001600160a01b039283169463f14fcbc89493909216926302255e2a92614c95928b92600160a01b900460ff1691908190600401618707565b60206040518083038186803b158015614cad57600080fd5b505afa158015614cc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ce591906182a5565b6040518263ffffffff1660e01b8152600401614d0391815260200190565b600060405180830381600087803b158015614d1d57600080fd5b505af1158015614d31573d6000803e3d6000fd5b505050505b60408051868152602081018690527f741d96f63d1b2e26958f7c5a2a14498c362ad5e8ef76b5f845f9625335c455ae910160405180910390a15050505050565b336000908152600080516020618a00833981519152602052604090205460ff16614dd05760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b6001600160a01b038116614e265760405162461bcd60e51b815260206004820152601c60248201527f544352474d583a202120676c7050726963696e67206164647265737300000000604482015260640161129f565b603180546001600160a01b03909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b6000611beb338484616341565b336000908152600080516020618a00833981519152602052604090205460ff16614ecc5760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b614eda620f42406014618882565b8110614f285760405162461bcd60e51b815260206004820152601660248201527f496e76616c6964207769746864726177616c2066656500000000000000000000604482015260640161129f565b60295460408051918252602082018390527f28a572c8c759d40c2d26dcdaaefd9650e9e37ff11ee147ce0f645cd7664048cb910160405180910390a1602955565b600080614f7a620f42406064618882565b6028546120d89085618882565b60026006541415614fc85760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b6002600655806150045760405162461bcd60e51b815260206004820152600760248201526608585b5bdd5b9d60ca1b604482015260640161129f565b6025546001600160a01b03161561505d5760405162461bcd60e51b815260206004820152601160248201527f77686974656c69737420656e61626c6564000000000000000000000000000000604482015260640161129f565b6150678133616e75565b50506001600655565b336000908152600080516020618a00833981519152602052604090205460ff166150ca5760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b604051600090339047908381818185875af1925050503d806000811461510c576040519150601f19603f3d011682016040523d82523d6000602084013e615111565b606091505b50509050806151625760405162461bcd60e51b815260206004820152600f60248201527f5769746864726177206661696c65640000000000000000000000000000000000604482015260640161129f565b50565b6015546001600160681b0316600090815260086020526040812054600d54611bd7908490839060ff16617363565b6001600160a01b0381166000908152600160205260408120548190611bd7565b6000828152602081905260409020600101546151cf8133616558565b612b228383616674565b601d546000908152600b60205260408082205490516370a0823160e01b815230600482015282916001600160a01b0316906370a082319060240160206040518083038186803b15801561522b57600080fd5b505afa15801561523f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061526391906182a5565b60315490915060ff1615614414576013546040516370a0823160e01b81523060048201526001600160a01b03909116906370a08231906024016143b4565b336000908152600080516020618a00833981519152602052604090205460ff166152fb5760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b6001600160a01b0381166153515760405162461bcd60e51b815260206004820152601e60248201527f544352474d583a202120686564676550726963696e6720616464726573730000604482015260640161129f565b603280546001600160a01b0319166001600160a01b0392909216919091179055565b600260065414156153b45760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b6002600655826153f05760405162461bcd60e51b815260206004820152600760248201526608585b5bdd5b9d60ca1b604482015260640161129f565b6025546001600160a01b03166154485760405162461bcd60e51b815260206004820152601560248201527f77686974656c697374206e6f7420656e61626c65640000000000000000000000604482015260640161129f565b6000615452612d59565b6025546040517ff1e9770b0000000000000000000000000000000000000000000000000000000081529192506001600160a01b03169063f1e9770b906154a4903390859089908990899060040161861a565b602060405180830381600087803b1580156154be57600080fd5b505af11580156154d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906154f6919061826f565b6155425760405162461bcd60e51b815260206004820152600a60248201527f2177686974656c69737400000000000000000000000000000000000000000000604482015260640161129f565b61554c8433616e75565b50506001600655505050565b336000908152600080516020618a00833981519152602052604090205460ff166155b25760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b6000828152600b60205260409020600101546001600160a01b03166156195760405162461bcd60e51b815260206004820152601860248201527f544352474d583a20627463206c65766572616765207365740000000000000000604482015260640161129f565b6000818152600a60205260409020600101546001600160a01b03166156805760405162461bcd60e51b815260206004820152601860248201527f544352474d583a20657468206c65766572616765207365740000000000000000604482015260640161129f565b601d91909155601e55565b336000908152600080516020618a00833981519152602052604090205460ff166156e55760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b6001600160a01b03811661573b5760405162461bcd60e51b815260206004820152601060248201527f216e6577466565526563697069656e7400000000000000000000000000000000604482015260640161129f565b6023546001600160a01b03828116911614156157995760405162461bcd60e51b815260206004820152601860248201527f4d757374206265206e657720666565526563697069656e740000000000000000604482015260640161129f565b602380546001600160a01b0319166001600160a01b0392909216919091179055565b336000908152600080516020618a00833981519152602052604090205460ff166158155760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b602580546001600160a01b0319166001600160a01b0392909216919091179055565b600080615848620f42406064618882565b6028546158559085618882565b61585f9190618775565b61586990846188c9565b9050611bd781615165565b3360009081527f0363fc6b1c9d3a5e0ab0c2ddc08deb0f30108829db06e84f370d2858ffe78c46602052604090205460ff166158dc5760405162461bcd60e51b815260206004820152600760248201526610b5b2b2b832b960c91b604482015260640161129f565b601e54601d546000828152600a602052604090819020600101549051630f41a04d60e11b81523060048201526001600160a01b0390911690631e83409a90602401600060405180830381600087803b15801561593757600080fd5b505af115801561594b573d6000803e3d6000fd5b5050506000828152600b602052604090819020600101549051630f41a04d60e11b81523060048201526001600160a01b039091169150631e83409a906024016130e1565b600260065414156159d05760405162461bcd60e51b815260206004820152601f60248201526000805160206189e0833981519152604482015260640161129f565b600260065560006159df6173cb565b602e549091506159f99082906001600160801b03166188c9565b602e80546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055506001600655565b336000908152600080516020618a00833981519152602052604090205460ff16615a845760405162461bcd60e51b81526020600482015260166024820152600080516020618a20833981519152604482015260640161129f565b615a92620f4240600a618882565b8110615ae05760405162461bcd60e51b815260206004820152601660248201527f496e76616c6964206d616e6167656d656e742066656500000000000000000000604482015260640161129f565b6000615aee61223883618775565b90506000610e10602b5483615b039190618882565b615b0d9190618775565b60275460408051918252602082018690529192507f4e874b007ab14f7e263baefd44951834c8266f4f224d1092e49e9c254354cc54910160405180910390a16027555050565b600080615b6183600a6187da565b905060008511615b715780615b86565b84615b7c8583618882565b615b869190618775565b95945050505050565b60135460408051631e8c5c8960e11b815290516000926001600160a01b031691633d18b912916004808301928692919082900301818387803b158015615bd457600080fd5b505af1158015615be8573d6000803e3d6000fd5b505060145460408051631e8c5c8960e11b815290516001600160a01b039092169350633d18b912925060048082019260009290919082900301818387803b158015615c3257600080fd5b505af1158015615c46573d6000803e3d6000fd5b50506037546040516370a0823160e01b8152306004820152600093506001600160a01b0390911691506370a082319060240160206040518083038186803b158015615c9057600080fd5b505afa158015615ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615cc891906182a5565b6033549091506001600160a01b031615801590615ce55750600081115b15615d9e57603354603754615d07916001600160a01b0391821691168361621f565b6033546040517fe0489f6a000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b039091169063e0489f6a90602401602060405180830381600087803b158015615d6657600080fd5b505af1158015615d7a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061440e91906182a5565b600091505090565b6031546040517f328ee290000000000000000000000000000000000000000000000000000000008152600481018390526000602482018190529182916101009091046001600160a01b03169063328ee2909060440160206040518083038186803b158015615e1357600080fd5b505afa158015615e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615e4b91906182a5565b9050602c5460305482615e5e9190618882565b615e689190618775565b615e7290826188c9565b603654600e546040517f0f3aa5540000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260248101849052600060448201523060648201529293501690630f3aa55490608401602060405180830381600087803b158015615eea57600080fd5b505af1158015615efe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615f2291906182a5565b50611bd75b6036546040517f30b700020000000000000000000000000000000000000000000000000000000081526001600482018190526024820181905260448201819052606482018190526084820181905260a4820152600060c48201819052916001600160a01b0316906330b700029060e401600060405180830381600087803b158015615fb157600080fd5b505af1158015615fc5573d6000803e3d6000fd5b50505050612deb617600565b60075460ff16156160245760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161129f565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586160593390565b6040516001600160a01b0390911681526020016135ad565b6000600183116160c35760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420617373657450657253686172650000000000000000000000604482015260640161129f565b6160ce82600a6187da565b6160d88486618882565b612d519190618775565b6001600160a01b03831661615d5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161129f565b6001600160a01b0382166161be5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161129f565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b15801561628457600080fd5b505afa158015616298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906162bc91906182a5565b6162c6919061875d565b6040516001600160a01b038516602482015260448101829052909150613bc090859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152617913565b6001600160a01b0383166163bd5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161129f565b6001600160a01b0382166164395760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161129f565b6001600160a01b038316600090815260016020526040902054818110156164c85760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161129f565b6001600160a01b038085166000908152600160205260408082208585039055918516815290812080548492906164ff90849061875d565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161654b91815260200190565b60405180910390a3613bc0565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16612c0e57616594816001600160a01b031660146179f8565b61659f8360206179f8565b6040516020016165b0929190618599565b60408051601f198184030181529082905262461bcd60e51b825261129f9160040161869b565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16612c0e576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556166303390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615612c0e576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160681b038111156151625760405162461bcd60e51b815260206004820152601060248201527f4f766572666c6f772075696e7431303400000000000000000000000000000000604482015260640161129f565b601e54601d546000828152600a60205260408082205490516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561679f57600080fd5b505afa1580156167b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906167d791906182a5565b6000838152600b60205260408082205490516370a0823160e01b815230600482015292935090916001600160a01b03909116906370a082319060240160206040518083038186803b15801561682b57600080fd5b505afa15801561683f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061686391906182a5565b905081156168f3576014546000858152600a6020526040902054616894916001600160a01b0391821691168461621f565b60145460405163534a7e1d60e11b8152600481018490526001600160a01b039091169063a694fc3a90602401600060405180830381600087803b1580156168da57600080fd5b505af11580156168ee573d6000803e3d6000fd5b505050505b8015613bc0576013546000848152600b6020526040902054616922916001600160a01b0391821691168361621f565b60135460405163534a7e1d60e11b8152600481018390526001600160a01b039091169063a694fc3a90602401600060405180830381600087803b15801561696857600080fd5b505af115801561697c573d6000803e3d6000fd5b5050505050505050565b601f54602080546021546040805161010081018252600d5460ff16815293840186905260009485949093929185918291829173b0b49c3c76f92d629278fde6ad48d3ea877d2c0d9163633c14269160159181016169e260035490565b81526020018f81526020018e815260200160265481526020016027548152602001602b5460156003015442616a1791906188c9565b616a219190618775565b90526040805160e085811b6001600160e01b03191682526004820194909452825160248201526020830151604482015290820151606482015260608201516084820152608082015160a482015260a082015160c482015260c082015160e48201529101516101048201526101240160a06040518083038186803b158015616aa757600080fd5b505af4158015616abb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616adf91906184ef565b601a8b9055601b8a9055601c8990556000601f819055602081815560218290556015546001600160681b031680835260088252604092839020869055602a805460ff191690556023548351868152928301859052928201819052969e50949c5091975095509093506001600160a01b0316907f0a242f7ecaf711036ca770774ceffae28e60ef042ac113ddd187f2631db0c0069060600160405180910390a2601680547fffffff00000000000000000000000000000000ffffffffffffffffffffffffff169055616bb181600161875d565b601580546cffffffffffffffffffffffffff19166001600160681b0392909216919091179055426018819055602b54616be99161875d565b601955506015546001600160681b03166000908152600860205260409020558015616c2457602354616c24906001600160a01b031682617ba1565b5050505050935093915050565b6001600160801b038111156151625760405162461bcd60e51b815260206004820152601060248201527f4f766572666c6f772075696e7431323800000000000000000000000000000000604482015260640161129f565b6000806000602b5460156003015442616ca191906188c9565b616cab9190618775565b6040805161010081018252600d5460ff1681526020810187905291925073b0b49c3c76f92d629278fde6ad48d3ea877d2c0d9163633c142691601591908101616cf360035490565b81526020018a815260200189815260200160265481526020016027548152602001858152506040518363ffffffff1660e01b8152600401616d9192919060006101208201905083825282516020830152602083015160408301526040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e08301516101008301529392505050565b60a06040518083038186803b158015616da957600080fd5b505af4158015616dbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616de191906184ef565b509299919850909650505050505050565b60075460ff16616e445760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161129f565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33616059565b6000616e8360075460ff1690565b15616ed05760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161129f565b6000616eda612d59565b6015549091506001600160681b03166000616ef5868461875d565b600d549091506801000000000000000090046001600160681b0316811115616f5f5760405162461bcd60e51b815260206004820152600a60248201527f4578636565642063617000000000000000000000000000000000000000000000604482015260640161129f565b600d54610100900466ffffffffffffff16811015616fbf5760405162461bcd60e51b815260206004820152601460248201527f496e73756666696369656e742062616c616e6365000000000000000000000000604482015260640161129f565b60408051878152602081018490526001600160a01b038716917fcec20e13b34d2d18a6f7858d257bc54c46f1ddd7602ea44ef65bab53a613ac02910160405180910390a26000617013620f42406064618882565b6028546170209089618882565b61702a9190618775565b9050600061703882896188c9565b60165490915060009061705c908390600160681b90046001600160801b031661875d565b601680547fffffff00000000000000000000000000000000ffffffffffffffffffffffffff16600160681b6001600160801b03841602179055600086815260086020526040902054600d54919250906170bb908490839060ff16617363565b60408051858152602081018390529199506001600160a01b038b169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3600e5461711c906001600160a01b031633308d617d0c565b602354617132906001600160a01b031685617ba1565b61713c8989617d5d565b5050505050505092915050565b602c546000908261715b826001618882565b61716591906188c9565b61716f9085618882565b611bd79190618775565b600082116171c95760405162461bcd60e51b815260206004820152600b60248201527f215f6e756d536861726573000000000000000000000000000000000000000000604482015260640161129f565b33600081815260096020908152604091829020805483518781529283018690528594919361ffff909116851115927f0c53c82ad07e2d592d88ece3b066777dd60f1118e2a081b380efc4358f0d9e2a910160405180910390a281546201000090046001600160801b03166000821561724c57617245878361875d565b90506172bb565b811561729a5760405162461bcd60e51b815260206004820152601160248201527f4578697374696e67207769746864726177000000000000000000000000000000604482015260640161129f565b50336000908152600960205260409020805461ffff191661ffff8616179055855b6172c481616c31565b33600090815260096020908152604080832080546001600160801b03808716620100000271ffffffffffffffffffffffffffffffff00001990921691909117909155888452600c90925282205461731d918a911661875d565b905061732881616c31565b6000868152600c6020526040902080546fffffffffffffffffffffffffffffffff19166001600160801b03831617905561697c33308a616341565b6000600183116173b55760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420617373657450657253686172650000000000000000000000604482015260640161129f565b826173c183600a6187da565b6160d89086618882565b33600090815260096020526040812080546001600160801b03620100008204169061ffff168161743d5760405162461bcd60e51b815260206004820152600d60248201527f4e6f7420696e6974696174656400000000000000000000000000000000000000604482015260640161129f565b6015546001600160681b031681106174975760405162461bcd60e51b815260206004820152601060248201527f526f756e64206e6f7420636c6f73656400000000000000000000000000000000604482015260640161129f565b336000908152600960205260409020805471ffffffffffffffffffffffffffffffff0000191690556017546174d69083906001600160801b03166188c9565b601780546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055600081815260086020526040812054600d5461751f91859160ff16616071565b6029549091501561756157600061753a620f42406064618882565b6029546175479084618882565b6175519190618775565b905061755d81836188c9565b9150505b604080518281526020810185905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a26175a63084617e3c565b600081116175f65760405162461bcd60e51b815260206004820152600f60248201527f217769746864726177416d6f756e740000000000000000000000000000000000604482015260640161129f565b612d513382617ba1565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b15801561766457600080fd5b505afa158015617678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061769c91906182a5565b90508015615d9e576038546040517f84cc315b0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260009216906384cc315b9060240160206040518083038186803b15801561772357600080fd5b505afa158015617737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061775b91906182a5565b905060006c0c9f2c9cd04674edea400000006177778484618882565b6177819190618775565b603a549091506177be906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168561621f565b600e546040516bffffffffffffffffffffffff197f0000000000000000000000000000000000000000000000000000000000000000606090811b82166020840152607d60ea1b60348401529290921b90911660378201526101f490600090604b01604051602081830303815290604052905060006040518060a00160405280838152602001306001600160a01b0316815260200142815260200187815260200161786a86603454617149565b9052603a546040517fc04b8d590000000000000000000000000000000000000000000000000000000081529192506001600160a01b03169063c04b8d59906178b69084906004016186ae565b602060405180830381600087803b1580156178d057600080fd5b505af11580156178e4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061790891906182a5565b965050505050505090565b6000617968826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316617f8a9092919063ffffffff16565b805190915015612b225780806020019051810190617986919061826f565b612b225760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161129f565b60606000617a07836002618882565b617a1290600261875d565b67ffffffffffffffff811115617a2a57617a2a6189bb565b6040519080825280601f01601f191660200182016040528015617a54576020820181803683370190505b509050600360fc1b81600081518110617a6f57617a6f6189a5565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110617a9e57617a9e6189a5565b60200101906001600160f81b031916908160001a9053506000617ac2846002618882565b617acd90600161875d565b90505b6001811115617b52577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110617b0e57617b0e6189a5565b1a60f81b828281518110617b2457617b246189a5565b60200101906001600160f81b031916908160001a90535060049490941c93617b4b8161890c565b9050617ad0565b508315611bd75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161129f565b6022547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161415617cf557604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015617c3a57600080fd5b505af1158015617c4e573d6000803e3d6000fd5b505050506000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114617c9f576040519150601f19603f3d011682016040523d82523d6000602084013e617ca4565b606091505b5050905080612b225760405162461bcd60e51b815260206004820152600f60248201527f5472616e73666572206661696c65640000000000000000000000000000000000604482015260640161129f565b602254612c0e906001600160a01b03168383617f99565b6040516001600160a01b0380851660248301528316604482015260648101829052613bc09085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016162f5565b6001600160a01b038216617db35760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161129f565b8060036000828254617dc5919061875d565b90915550506001600160a01b03821660009081526001602052604081208054839290617df290849061875d565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216617e9c5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161129f565b6001600160a01b03821660009081526001602052604090205481811015617f105760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161129f565b6001600160a01b0383166000908152600160205260408120838303905560038054849290617f3f9084906188c9565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6060612d518484600085617fe2565b6040516001600160a01b038316602482015260448101829052612b229084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016162f5565b60608247101561805a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161129f565b843b6180a85760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161129f565b600080866001600160a01b031685876040516180c4919061857d565b60006040518083038185875af1925050503d8060008114618101576040519150601f19603f3d011682016040523d82523d6000602084013e618106565b606091505b5091509150618116828286618121565b979650505050505050565b60608315618130575081611bd7565b8251156181405782518084602001fd5b8160405162461bcd60e51b815260040161129f919061869b565b80356001600160a01b038116811461441457600080fd5b80356003811061441457600080fd5b80356dffffffffffffffffffffffffffff8116811461441457600080fd5b6000602082840312156181b057600080fd5b611bd78261815a565b600080604083850312156181cc57600080fd5b6181d58361815a565b91506181e36020840161815a565b90509250929050565b60008060006060848603121561820157600080fd5b61820a8461815a565b92506182186020850161815a565b9150604084013590509250925092565b6000806040838503121561823b57600080fd5b6182448361815a565b946020939093013593505050565b60006020828403121561826457600080fd5b8135611bd7816189d1565b60006020828403121561828157600080fd5b8151611bd7816189d1565b60006020828403121561829e57600080fd5b5035919050565b6000602082840312156182b757600080fd5b5051919050565b600080604083850312156182d157600080fd5b823591506181e36020840161815a565b6000602082840312156182f357600080fd5b81356001600160e01b031981168114611bd757600080fd5b600080828403608081121561831f57600080fd5b606081121561832d57600080fd5b506040516060810181811067ffffffffffffffff8211171561835f57634e487b7160e01b600052604160045260246000fd5b60405261836b8461815a565b81526183796020850161815a565b602082015261838a6040850161815a565b6040820152946060939093013593505050565b600080600080600060a086880312156183b557600080fd5b6183be86618180565b94506183cc60208701618180565b93506183da60408701618180565b925060608601356183ea816189d1565b915060808601356183fa816189d1565b809150509295509295909350565b60008060006040848603121561841d57600080fd5b83359250602084013567ffffffffffffffff8082111561843c57600080fd5b818601915086601f83011261845057600080fd5b81358181111561845f57600080fd5b8760208260051b850101111561847457600080fd5b6020830194508093505050509250925092565b6000806040838503121561849a57600080fd5b50508035926020909101359150565b600080600080608085870312156184bf57600080fd5b84359350602085013592506184d660408601618171565b91506184e460608601618171565b905092959194509250565b600080600080600060a0868803121561850757600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b600081518084526185478160208601602086016188e0565b601f01601f19169290920160200192915050565b6006811061857957634e487b7160e01b600052602160045260246000fd5b9052565b6000825161858f8184602087016188e0565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516185d18160178501602088016188e0565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161860e8160288401602088016188e0565b01602801949350505050565b6001600160a01b03861681528460208201528360408201526080606082015281608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561866e57600080fd5b8260051b808560a08501376000920160a0019182525095945050505050565b60208101611aad828461855b565b602081526000611bd7602083018461852f565b602081526000825160a060208401526186ca60c084018261852f565b90506001600160a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b8481526080810161871b602083018661855b565b921515604082015290151560609091015292915050565b60006001600160681b0380831681851680830382111561875457618754618979565b01949350505050565b6000821982111561877057618770618979565b500190565b60008261879257634e487b7160e01b600052601260045260246000fd5b500490565b600181815b808511156187d25781600019048211156187b8576187b8618979565b808516156187c557918102915b93841c939080029061879c565b509250929050565b6000611bd783836000826187f057506001611aad565b816187fd57506000611aad565b8160018114618813576002811461881d57618839565b6001915050611aad565b60ff84111561882e5761882e618979565b50506001821b611aad565b5060208310610133831016604e8410600b841016171561885c575081810a611aad565b6188668383618797565b806000190482111561887a5761887a618979565b029392505050565b600081600019048311821515161561889c5761889c618979565b500290565b60006001600160681b03838116908316818110156188c1576188c1618979565b039392505050565b6000828210156188db576188db618979565b500390565b60005b838110156188fb5781810151838201526020016188e3565b83811115613bc05750506000910152565b60008161891b5761891b618979565b506000190190565b600181811c9082168061893757607f821691505b6020821081141561895857634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561897257618972618979565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461516257600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c007d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec43616c6c6572206973206e6f7420616e2061646d696e00000000000000000000a264697066735822122067e39b30856648ad9a6de45271344c1748b98202334240896fa3643bd752ebbb64736f6c63430008070033608060405234801561001057600080fd5b50610420806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806302255e2a1461003b5780638da92a5d14610061575b600080fd5b61004e6100493660046102c6565b610081565b6040519081526020015b60405180910390f35b61007461006f366004610251565b6100aa565b6040516100589190610348565b60008061008d86610155565b608086901b608886901b609086901b010101915050949350505050565b6060808260005b8181101561014b57828686838181106100cc576100cc6103d4565b90506020020160208101906100e19190610214565b604051602001610109919060609190911b6bffffffffffffffffffffffff1916815260140190565b60408051601f19818403018152908290526101279291602001610319565b60405160208183030381529060405292508080610143906103ab565b9150506100b1565b5090949350505050565b60006fffffffffffffffffffffffffffffffff8211156101fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f3238206269747300000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b5090565b8035801515811461020f57600080fd5b919050565b60006020828403121561022657600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461024a57600080fd5b9392505050565b6000806020838503121561026457600080fd5b823567ffffffffffffffff8082111561027c57600080fd5b818501915085601f83011261029057600080fd5b81358181111561029f57600080fd5b8660208260051b85010111156102b457600080fd5b60209290920196919550909350505050565b600080600080608085870312156102dc57600080fd5b843593506020850135600681106102f257600080fd5b9250610300604086016101ff565b915061030e606086016101ff565b905092959194509250565b6000835161032b81846020880161037b565b83519083019061033f81836020880161037b565b01949350505050565b602081526000825180602084015261036781604085016020870161037b565b601f01601f19169190910160400192915050565b60005b8381101561039657818101518382015260200161037e565b838111156103a5576000848401525b50505050565b60006000198214156103cd57634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052603260045260246000fdfea2646970667358221220d6dba819f7fdba9ba10891f5b9ae0df21063cbcee489592e0ac372c1c74f51fc64736f6c63430008070033000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000007466bbde36975842851cbff8c67f9bbaa9c6ea240000000000000000000000007466bbde36975842851cbff8c67f9bbaa9c6ea2400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000e4e1c0000000000000000000000000000000000000000000000000000000000007a12000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000001addd80e6039594ee970e5872d247bf0414c8903000000000000000000000000f42ae1d54fd613c9bb14810b0588faaa09a426ca000000000000000000000000391e6d4e3aa6e05dfaff05b8c5a52fe2762b92b400000000000000000000000035d33c8f9d78214409709ea9c1d031a8f5b22daf00000000000000000000000016c457fc0f5d5981574ed2baed81c625bd91b633000000000000000000000000489da242a948d1978673fef8836740c11732ec0b000000000000000000000000a906f338cb21815cbc4bc87ace9e68c87ef8d8f1000000000000000000000000321f653eed006ad1c29d174e17d96351bde22649000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564

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

000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000007466bbde36975842851cbff8c67f9bbaa9c6ea240000000000000000000000007466bbde36975842851cbff8c67f9bbaa9c6ea2400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000e4e1c0000000000000000000000000000000000000000000000000000000000007a12000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000001addd80e6039594ee970e5872d247bf0414c8903000000000000000000000000f42ae1d54fd613c9bb14810b0588faaa09a426ca000000000000000000000000391e6d4e3aa6e05dfaff05b8c5a52fe2762b92b400000000000000000000000035d33c8f9d78214409709ea9c1d031a8f5b22daf00000000000000000000000016c457fc0f5d5981574ed2baed81c625bd91b633000000000000000000000000489da242a948d1978673fef8836740c11732ec0b000000000000000000000000a906f338cb21815cbc4bc87ace9e68c87ef8d8f1000000000000000000000000321f653eed006ad1c29d174e17d96351bde22649000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564

-----Decoded View---------------
Arg [0] : _asset (address): 0xff970a61a04b1ca14834a43f5de4533ebddb5cc8
Arg [1] : _feeRecipient (address): 0x7466bbde36975842851cbff8c67f9bbaa9c6ea24
Arg [2] : _keeper (address): 0x7466bbde36975842851cbff8c67f9bbaa9c6ea24
Arg [3] : _managementFee (uint256): 1
Arg [4] : _performanceFee (uint256): 15000000
Arg [5] : _depositFee (uint256): 500000
Arg [6] : _vaultRound (uint104): 1
Arg [7] : _vaultParams (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [8] : _glpRouter (address): 0xa906f338cb21815cbc4bc87ace9e68c87ef8d8f1
Arg [9] : _glpManager (address): 0x321f653eed006ad1c29d174e17d96351bde22649
Arg [10] : _uniswapRouter (address): 0xe592427a0aece92de3edee1f18e0157c05861564

-----Encoded View---------------
20 Constructor Arguments found :
Arg [0] : 000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8
Arg [1] : 0000000000000000000000007466bbde36975842851cbff8c67f9bbaa9c6ea24
Arg [2] : 0000000000000000000000007466bbde36975842851cbff8c67f9bbaa9c6ea24
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000000000000000000000000000000000000000e4e1c0
Arg [5] : 000000000000000000000000000000000000000000000000000000000007a120
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [9] : 00000000000000000000000000000000000000000000000000000000000f4240
Arg [10] : 000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8
Arg [11] : 0000000000000000000000001addd80e6039594ee970e5872d247bf0414c8903
Arg [12] : 000000000000000000000000f42ae1d54fd613c9bb14810b0588faaa09a426ca
Arg [13] : 000000000000000000000000391e6d4e3aa6e05dfaff05b8c5a52fe2762b92b4
Arg [14] : 00000000000000000000000035d33c8f9d78214409709ea9c1d031a8f5b22daf
Arg [15] : 00000000000000000000000016c457fc0f5d5981574ed2baed81c625bd91b633
Arg [16] : 000000000000000000000000489da242a948d1978673fef8836740c11732ec0b
Arg [17] : 000000000000000000000000a906f338cb21815cbc4bc87ace9e68c87ef8d8f1
Arg [18] : 000000000000000000000000321f653eed006ad1c29d174e17d96351bde22649
Arg [19] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.