Contract 0x2FaE8C7Edd26213cA1A88fC57B65352dbe353698 12

 
Txn Hash Method
Block
From
To
Value
0xb67b08277e68fb9a196ea6e56921b6ea33523a1ecc3d64fae8dbd9f2efbddcfdRedeem1178460022024-03-24 14:33:014 days 15 hrs ago0x8c04e289eaff3beb2ff49f7d237580b66394b50b IN  Pika Protocol: Perpetual V20 ETH0.0000014678030.010056118
0x93de9de6e04ba00d7ea5a8c30bf7a42b10f5a13c61f43262ffa96a10e9cd493aRedeem1177215352024-03-21 17:24:077 days 12 hrs ago 0x442ed3e7d89d44180ea826675c5d6e5b350e0f4c IN  Pika Protocol: Perpetual V20 ETH0.0000010117720.006223832
0x56cb1ddad1e4d89300744567463c6f1247ca0e5a00d20a745264640e50b85e4cRedeem1176969712024-03-21 3:45:198 days 2 hrs ago0xe258cfda93e8bd42b95fd91f09f73f44c18b9a44 IN  Pika Protocol: Perpetual V20 ETH0.0000009284690.0069052
0x057c75bb82dd3ba2fbbea62f9d42ea9b314b80cfa21662df90c8f823744bdab0Redeem1176860322024-03-20 21:40:418 days 8 hrs ago0x87c4c5994e94e0317ce7a4c2ea25a66bfa1979dc IN  Pika Protocol: Perpetual V20 ETH0.0000022916740.013292277
0xe5bd5b049c378df8828eb82bedb3e7e82235a48c2fece3fa22c33dabbc64ad14Redeem1176223382024-03-19 10:17:339 days 19 hrs ago0x46edb85d2046c6fd59ff58cf7287d1a20cddb059 IN  Pika Protocol: Perpetual V20 ETH0.0000024177330.014289297
0x1a8602f2165735c743861bf132b4e2b05a0d4d7267440d66903fa4dac650302eRedeem1176221242024-03-19 10:10:259 days 19 hrs ago0x8282fc96b1077ea1cfeba4703c8b24f81e442a6c IN  Pika Protocol: Perpetual V20 ETH0.0000061325490.04056513
0x9c91aa031b58e8c655b642104360a2cfcb6c90aa532747c962ae2b911a68f49eRedeem1176220862024-03-19 10:09:099 days 19 hrs ago0x6c877621e4b208dde767074667f98cdc4bf8b79f IN  Pika Protocol: Perpetual V20 ETH0.0000061851510.04094318
0x9d79ad4766c7987ba2ede15467253c3ca448389ba27c8dc43b4790e65e701e51Redeem1176220642024-03-19 10:08:259 days 19 hrs ago0x541df59e2ccf9a3124d77ec4767d4f2041a8ec3f IN  Pika Protocol: Perpetual V20 ETH0.0000062568650.04129046
0x7308480eaf9cd74d3f8d86da25cb29681f659e2f4af7c1fc71dc5cbed74979b5Redeem1176220332024-03-19 10:07:239 days 19 hrs ago0xc2af7be033533ed02f844ad63becd363e7869b1c IN  Pika Protocol: Perpetual V20 ETH0.0000063117280.041709138
0xc567e6e7d6be142aa1b4ea4cf56c22bf7acdbe5786de3cba003c77015ebbb9baRedeem1176220102024-03-19 10:06:379 days 19 hrs ago0x2988c822248cf18438e2153457a426d6c2418088 IN  Pika Protocol: Perpetual V20 ETH0.0000063681030.042003871
0xc72f24bd73cded459736861f348de095ed55d47b723c1df734e0ba90610cd336Redeem1176219852024-03-19 10:05:479 days 19 hrs ago0x323bfb955a94456e091eb0b592b531886a8fab2b IN  Pika Protocol: Perpetual V20 ETH0.0000047846690.031178594
0x82b10db808ea5734794860f1bb2afb65e1bf19e21273ef1d90265771a0299ef0Redeem1176219612024-03-19 10:04:599 days 19 hrs ago0x0bc77726c5f907f29ad0b2617c249bcdc4771705 IN  Pika Protocol: Perpetual V20 ETH0.0000030208450.019316478
0x27b4fb49f15f758b619e31683ce3c4c6842f626deb03c33c99c4d588fb47cbe3Redeem1176219352024-03-19 10:04:079 days 19 hrs ago0x7fc655304c67aed7158a1d01e0000149eab0d77e IN  Pika Protocol: Perpetual V20 ETH0.0000021331970.012973898
0xad9ac267613a9ab715f95e52bc7ec8b5e21e987d8bf5114613c63710adf8ce3cRedeem1176219092024-03-19 10:03:159 days 19 hrs ago0x088358cce2d9f8b0f68588d30501f28e45b9312a IN  Pika Protocol: Perpetual V20 ETH0.0000021836320.013424417
0x94bd97e11eba43b16eedc58afc134c384ba651b93b3bd46d180b7b42c8a86640Redeem1176218822024-03-19 10:02:219 days 19 hrs ago0x53ac3a5bc987a03dde92138e0bf1cb9c6ba81722 IN  Pika Protocol: Perpetual V20 ETH0.0000022435690.013799986
0x26d40f9fa3e49d18af2d36b9ecd48385f20109a61ccf068650d440486fdfbd67Redeem1176218542024-03-19 10:01:259 days 19 hrs ago0x20b54fc4cb1a8d0eedf9c4d1748d1d6686a14858 IN  Pika Protocol: Perpetual V20 ETH0.0000023068550.014217295
0xcd71e6d0759d44a823b431440b0fa0dc6f45803e10679fbf44e0540e5377a84dRedeem1176218292024-03-19 10:00:359 days 19 hrs ago0xc0caf9d72a4aa0ac29d9ed0c00840584e1bc1bab IN  Pika Protocol: Perpetual V20 ETH0.0000023185040.014175317
0xd50fe4a411beec92cb1f9ddc21d79291e1fb9216245cc51149b6ba8727965af0Redeem1176218042024-03-19 9:59:459 days 19 hrs ago0x36429dd6e7a74186f3c9deab20e5176acae8479a IN  Pika Protocol: Perpetual V20 ETH0.0000022928330.01411141
0xc721bd103fbf174e693d184e994e0b2d95b6556d7cffab5bffefea7c893a02ffRedeem1176217792024-03-19 9:58:559 days 19 hrs ago0xb85c5124259937e1f1a48cee629965b28ecbd1ad IN  Pika Protocol: Perpetual V20 ETH0.0000025147990.015521898
0xd6f94a77544cdfbebb34941c440d971027220e07032d06e18218c5e197e5b643Redeem1176217572024-03-19 9:58:119 days 19 hrs ago0x9b2ef9cae522c235b9f08672604abbe7fd1a70f8 IN  Pika Protocol: Perpetual V20 ETH0.0000025572820.015870194
0x54afe5147437572ff52d16070dbf74c10ba40c59260f3a5108dbed9dbeec5f7cRedeem1176217332024-03-19 9:57:239 days 19 hrs ago0xdd5ece2fa4a15d1ba29bb241ddfb24c9a7fa0359 IN  Pika Protocol: Perpetual V20 ETH0.000002637740.016342065
0x11ce3afc2d3aeca45df8857380bd43f3261e807e0e69ce48ab54775a2a855086Redeem1176217092024-03-19 9:56:359 days 19 hrs ago0xc7e08fbab78e6c21510c3005de6464adf73828c9 IN  Pika Protocol: Perpetual V20 ETH0.0000026691040.016687036
0x6b72806f125e4a127e2e66b8cfc63a8cca58bd7031c550c47f644d7db038b815Redeem1176216822024-03-19 9:55:419 days 19 hrs ago0x561bce83988f653d79c47bc8329e7d47cdd70358 IN  Pika Protocol: Perpetual V20 ETH0.0000026995120.016705049
0xce13236004a40c4993a94e2722da3935ce88ae51c26390dc07020d393a32ace9Redeem1176216572024-03-19 9:54:519 days 19 hrs ago0xd99fc45d5e62aafc56c3ed916c99964f385eef1a IN  Pika Protocol: Perpetual V20 ETH0.0000026661550.01668396
0xe2ea14d4917db1df810b9076741e01c11b02e7b72591cd433fbe833fcb66b3b1Redeem1176216332024-03-19 9:54:039 days 19 hrs ago0x8066af8075b281bd438b443205a987a04b8d6bed IN  Pika Protocol: Perpetual V20 ETH0.0000028010480.01749223
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x0644ae335f434666a2781fb4ec99bade4dcc490fae50175e8a7004ee70d59edc1074932542023-07-28 23:01:25244 days 6 hrs ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0x0644ae335f434666a2781fb4ec99bade4dcc490fae50175e8a7004ee70d59edc1074932542023-07-28 23:01:25244 days 6 hrs ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0x0644ae335f434666a2781fb4ec99bade4dcc490fae50175e8a7004ee70d59edc1074932542023-07-28 23:01:25244 days 6 hrs ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago Pika Protocol: Perpetual V2 0x7f5c764cbc14f9669b88837ca1490cca17c316070 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago 0x7bbe1342b8a3bf3dfcc645fc89b4b1c71ce2ee80 Pika Protocol: Perpetual V20 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago 0x7bbe1342b8a3bf3dfcc645fc89b4b1c71ce2ee80 Pika Protocol: Perpetual V20 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago 0x7bbe1342b8a3bf3dfcc645fc89b4b1c71ce2ee80 Pika Protocol: Perpetual V20 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago Pika Protocol: Perpetual V2 0x7bbe1342b8a3bf3dfcc645fc89b4b1c71ce2ee800 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0xbf831ad0a22afa70d12125bd513ecbd5a1b375909cb666495eb92455a02e42601074932512023-07-28 23:01:19244 days 6 hrs ago Pika Protocol: Perpetual V2 0x58488bb666d2da33f8e8938dbdd582d2481d41830 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago Pika Protocol: Perpetual V2 0x7f5c764cbc14f9669b88837ca1490cca17c316070 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago 0x7bbe1342b8a3bf3dfcc645fc89b4b1c71ce2ee80 Pika Protocol: Perpetual V20 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago 0x7bbe1342b8a3bf3dfcc645fc89b4b1c71ce2ee80 Pika Protocol: Perpetual V20 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago 0x7bbe1342b8a3bf3dfcc645fc89b4b1c71ce2ee80 Pika Protocol: Perpetual V20 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago Pika Protocol: Perpetual V2 0x7bbe1342b8a3bf3dfcc645fc89b4b1c71ce2ee800 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0x543a0af076187a7dd43c766d8ce0909559a283b2f6406b3f13c61a33111cc0df1074606832023-07-28 4:55:43245 days 51 mins ago Pika Protocol: Perpetual V2 0x58488bb666d2da33f8e8938dbdd582d2481d41830 ETH
0xdab9452dd989335d2fc7acbad3fff77553583143fc8c181465673d2e02fa0ca81074606552023-07-28 4:54:47245 days 52 mins ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0xdab9452dd989335d2fc7acbad3fff77553583143fc8c181465673d2e02fa0ca81074606552023-07-28 4:54:47245 days 52 mins ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0xdab9452dd989335d2fc7acbad3fff77553583143fc8c181465673d2e02fa0ca81074606552023-07-28 4:54:47245 days 52 mins ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
0xb79304245fa995fa124b9312f95721993aa0b0f14e3bd45e08f1ae5dfc37ec791074606472023-07-28 4:54:31245 days 52 mins ago 0x58488bb666d2da33f8e8938dbdd582d2481d4183 Pika Protocol: Perpetual V20 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PikaPerpV2

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : PikaPerpV2.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/math/SignedSafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../oracle/IOracle.sol";
import '../lib/UniERC20.sol';
import './IPikaPerp.sol';
import "../staking/IVaultReward.sol";

contract PikaPerpV2 is ReentrancyGuard {
    using SafeMath for uint256;
    using SignedSafeMath for int256;
    using SafeERC20 for IERC20;
    using UniERC20 for IERC20;
    // All amounts are stored with 8 decimals

    // Structs

    struct Vault {
        // 32 bytes
        uint96 cap; // Maximum capacity. 12 bytes
        uint96 balance; // 12 bytes
        uint64 staked; // Total staked by users. 8 bytes
        uint64 shares; // Total ownership shares. 8 bytes
        // 32 bytes
        uint32 stakingPeriod; // Time required to lock stake (seconds). 4 bytes
    }

    struct Stake {
        // 32 bytes
        address owner; // 20 bytes
        uint64 amount; // 8 bytes
        uint64 shares; // 8 bytes
        uint32 timestamp; // 4 bytes
    }

    struct Product {
        // 32 bytes
        address feed; // Chainlink feed. 20 bytes
        uint72 maxLeverage; // 9 bytes
        uint16 fee; // In bps. 0.5% = 50. 2 bytes
        bool isActive; // 1 byte
        // 32 bytes
        uint64 openInterestLong; // 6 bytes
        uint64 openInterestShort; // 6 bytes
        uint16 interest; // For 360 days, in bps. 10% = 1000. 2 bytes
        uint16 liquidationThreshold; // In bps. 8000 = 80%. 2 bytes
        uint16 liquidationBounty; // In bps. 500 = 5%. 2 bytes
        uint16 minPriceChange; // 1.5%, the minimum oracle price up change for trader to close trade with profit
        uint16 weight; // share of the max exposure
        uint64 reserve; // Virtual reserve in USDC. Used to calculate slippage
    }

    struct Position {
        // 32 bytes
        uint64 productId; // 8 bytes
        uint64 leverage; // 8 bytes
        uint64 price; // 8 bytes
        uint64 oraclePrice; // 8 bytes
        uint64 margin; // 8 bytes
        // 32 bytes
        address owner; // 20 bytes
        uint80 timestamp; // 10 bytes
        bool isLong; // 1 byte
    }

    // Variables

    address public owner; // Contract owner
    address public liquidator;
    address public token;
    uint256 public tokenDecimal;
    uint256 public tokenBase;
    address public oracle;
    uint256 public minMargin;
    uint256 public protocolRewardRatio = 2000;  // 20%
    uint256 public pikaRewardRatio = 3000;  // 30%
    uint256 public maxShift = 0.003e8; // max shift (shift is used adjust the price to balance the longs and shorts)
    uint256 public minProfitTime = 12 hours; // the time window where minProfit is effective
    uint256 public maxPositionMargin; // for guarded launch
    uint256 public totalWeight; // total exposure weights of all product
    uint256 public exposureMultiplier = 10000; // exposure multiplier
    uint256 public utilizationMultiplier = 10000; // exposure multiplier
    uint256 public pendingProtocolReward; // protocol reward collected
    uint256 public pendingPikaReward; // pika reward collected
    uint256 public pendingVaultReward; // vault reward collected
    address public protocolRewardDistributor;
    address public pikaRewardDistributor;
    address public vaultRewardDistributor;
    address public vaultTokenReward;
    uint256 public totalOpenInterest;
    uint256 public constant BASE_DECIMALS = 8;
    uint256 public constant BASE = 10**BASE_DECIMALS;
    bool canUserStake = false;
    bool allowPublicLiquidator = false;
    Vault private vault;

    mapping(uint256 => Product) private products;
    mapping(address => Stake) private stakes;
    mapping(uint256 => Position) private positions;

    // Events

    event Staked(
        address indexed user,
        uint256 amount,
        uint256 shares
    );
    event Redeemed(
        address indexed user,
        uint256 amount,
        uint256 shares,
        uint256 shareBalance,
        bool isFullRedeem
    );
    event NewPosition(
        uint256 indexed positionId,
        address indexed user,
        uint256 indexed productId,
        bool isLong,
        uint256 price,
        uint256 oraclePrice,
        uint256 margin,
        uint256 leverage,
        uint256 fee
    );

    event AddMargin(
        uint256 indexed positionId,
        address indexed user,
        uint256 margin,
        uint256 newMargin,
        uint256 newLeverage
    );
    event ClosePosition(
        uint256 indexed positionId,
        address indexed user,
        uint256 indexed productId,
        uint256 price,
        uint256 entryPrice,
        uint256 margin,
        uint256 leverage,
        uint256 fee,
        int256 pnl,
        bool wasLiquidated
    );
    event PositionLiquidated(
        uint256 indexed positionId,
        address indexed liquidator,
        uint256 liquidatorReward,
        uint256 remainingReward
    );
    event ProtocolRewardDistributed(
        address to,
        uint256 amount
    );
    event PikaRewardDistributed(
        address to,
        uint256 amount
    );
    event VaultRewardDistributed(
        address to,
        uint256 amount
    );
    event VaultUpdated(
        Vault vault
    );
    event ProductAdded(
        uint256 productId,
        Product product
    );
    event ProductUpdated(
        uint256 productId,
        Product product
    );
    event RewardRatioUpdated(
        uint256 protocolRewardRatio,
        uint256 pikaRewardRatio
    );
    event OracleUpdated(
        address newOracle
    );
    event OwnerUpdated(
        address newOwner
    );

    // Constructor

    constructor(address _token, uint256 _tokenDecimal, address _oracle, uint256 _minMargin) {
        owner = msg.sender;
        liquidator = msg.sender;
        token = _token;
        tokenDecimal = _tokenDecimal;
        tokenBase = 10**_tokenDecimal;
        oracle = _oracle;
        minMargin = _minMargin;
        vault = Vault({
        cap: 0,
        balance: 0,
        staked: 0,
        shares: 0,
        stakingPeriod: uint32(24 * 3600)
        });
    }

    // Methods

    // Stakes amount of usdc in the vault for user
    function stakeForUser(uint256 amount, address user) public payable nonReentrant {
        require(canUserStake || msg.sender == owner, "!stake");
        IVaultReward(vaultRewardDistributor).updateReward(user);
        IVaultReward(vaultTokenReward).updateReward(user);
        IERC20(token).uniTransferFromSenderToThis(amount.mul(tokenBase).div(BASE));
        require(uint256(vault.staked) + amount <= uint256(vault.cap), "!cap");
        uint256 shares = vault.staked > 0 ? amount.mul(uint256(vault.shares)).div(uint256(vault.balance)) : amount;
        vault.balance += uint96(amount);
        vault.staked += uint64(amount);
        vault.shares += uint64(shares);

        if (stakes[user].amount == 0) {
            stakes[user] = Stake({
            owner: user,
            amount: uint64(amount),
            shares: uint64(shares),
            timestamp: uint32(block.timestamp)
            });
        } else {
            stakes[user].amount += uint64(amount);
            stakes[user].shares += uint64(shares);
            stakes[user].timestamp = uint32(block.timestamp);
        }

        emit Staked(
            user,
            amount,
            shares
        );

    }

    function stake(uint256 amount) external payable {
        stakeForUser(amount, msg.sender);
    }

    // Redeems amount from Stake with id = stakeId
    function redeem(
        uint256 shares
    ) external {

        require(shares <= uint256(vault.shares), "!staked");

        address user = msg.sender;
        IVaultReward(vaultRewardDistributor).updateReward(user);
        IVaultReward(vaultTokenReward).updateReward(user);
        Stake storage _stake = stakes[user];
        bool isFullRedeem = shares >= uint256(_stake.shares);
        if (isFullRedeem) {
            shares = uint256(_stake.shares);
        }

        if (user != owner) {
            uint256 timeDiff = block.timestamp.sub(uint256(_stake.timestamp));
            require(timeDiff > uint256(vault.stakingPeriod), "!period");
        }

        uint256 shareBalance = shares.mul(uint256(vault.balance)).div(uint256(vault.shares));

        uint256 amount = shares.mul(_stake.amount).div(uint256(_stake.shares));

        _stake.amount -= uint64(amount);
        _stake.shares -= uint64(shares);
        vault.staked -= uint64(amount);
        vault.shares -= uint64(shares);
        vault.balance -= uint96(shareBalance);

        require(totalOpenInterest <= uint256(vault.balance).mul(utilizationMultiplier).div(10**4), "!utilized");

        if (isFullRedeem) {
            delete stakes[user];
        }
        IERC20(token).uniTransfer(user, shareBalance.mul(tokenBase).div(BASE));

        emit Redeemed(
            user,
            amount,
            shares,
            shareBalance,
            isFullRedeem
        );
    }

    function openPosition(
        uint256 productId,
        uint256 margin,
        bool isLong,
        uint256 leverage
    ) external payable returns(uint256) {
        return openPositionForUser(msg.sender, productId, margin, isLong, leverage);
    }

    function openPositionForUser(
        address user,
        uint256 productId,
        uint256 margin,
        bool isLong,
        uint256 leverage
    ) public payable nonReentrant returns(uint256 positionId) {
        // Check params
        require(margin >= minMargin, "!margin");
        require(leverage >= 1 * BASE, "!leverage");

        // Check product
        Product storage product = products[productId];
        require(product.isActive, "!product-active");
        require(leverage <= uint256(product.maxLeverage), "!max-leverage");

        // Transfer margin plus fee
        uint256 tradeFee = _getTradeFee(margin, leverage, uint256(product.fee));
        IERC20(token).uniTransferFromSenderToThis((margin.add(tradeFee)).mul(tokenBase).div(BASE));
        pendingProtocolReward = pendingProtocolReward.add(tradeFee.mul(protocolRewardRatio).div(10**4));
        pendingPikaReward = pendingPikaReward.add(tradeFee.mul(pikaRewardRatio).div(10**4));
        pendingVaultReward = pendingVaultReward.add(tradeFee.mul(10**4 - protocolRewardRatio - pikaRewardRatio).div(10**4));

        uint256 amount = margin.mul(leverage).div(BASE);
        uint256 price = _calculatePrice(product.feed, isLong, product.openInterestLong,
            product.openInterestShort, uint256(vault.balance).mul(uint256(product.weight)).mul(exposureMultiplier).div(uint256(totalWeight)).div(10**4),
            uint256(product.reserve), amount);

        _updateOpenInterest(productId, amount, isLong, true);

        positionId = getPositionId(user, productId, isLong);
        Position storage position = positions[positionId];
        if (position.margin > 0) {
            price = (uint256(position.margin).mul(position.leverage).mul(uint256(position.price)).add(margin.mul(leverage).mul(price))).div(
                uint256(position.margin).mul(position.leverage).add(margin.mul(leverage)));
            leverage = (uint256(position.margin).mul(uint256(position.leverage)).add(margin.mul(leverage))).div(uint256(position.margin).add(margin));
            margin = uint256(position.margin).add(margin);
        }
        require(margin < maxPositionMargin, "!max margin");

        positions[positionId] = Position({
        owner: user,
        productId: uint64(productId),
        margin: uint64(margin),
        leverage: uint64(leverage),
        price: uint64(price),
        oraclePrice: uint64(IOracle(oracle).getPrice(product.feed)),
        timestamp: uint80(block.timestamp),
        isLong: isLong
        });
        emit NewPosition(
            positionId,
            user,
            productId,
            isLong,
            price,
            IOracle(oracle).getPrice(product.feed),
            margin,
            leverage,
            tradeFee
        );
    }

    // Add margin to Position with positionId
    function addMargin(uint256 positionId, uint256 margin) external payable nonReentrant {

        IERC20(token).uniTransferFromSenderToThis(margin.mul(tokenBase).div(BASE));

        // Check params
        require(margin >= minMargin, "!margin");

        // Check position
        Position storage position = positions[positionId];
        require(msg.sender == position.owner, "!owner");

        // New position params
        uint256 newMargin = uint256(position.margin).add(margin);
        uint256 newLeverage = uint256(position.leverage).mul(uint256(position.margin)).div(newMargin);
        require(newLeverage >= 1 * BASE, "!low-leverage");

        position.margin = uint64(newMargin);
        position.leverage = uint64(newLeverage);

        emit AddMargin(
            positionId,
            position.owner,
            margin,
            newMargin,
            newLeverage
        );

    }

    // Closes margin from Position with productId and direction
    function closePosition(
        uint256 productId,
        uint256 margin,
        bool isLong
    ) external {
        return closePositionWithId(getPositionId(msg.sender, productId, isLong), margin);
    }

    // Closes position from Position with id = positionId
    function closePositionWithId(
        uint256 positionId,
        uint256 margin
    ) public nonReentrant {
        // Check params
        require(margin >= minMargin, "!margin");

        // Check position
        Position storage position = positions[positionId];
        require(msg.sender == position.owner, "!owner");

        // Check product
        Product storage product = products[uint256(position.productId)];

        bool isFullClose;
        if (margin >= uint256(position.margin)) {
            margin = uint256(position.margin);
            isFullClose = true;
        }
        uint256 maxExposure = uint256(vault.balance).mul(uint256(product.weight)).mul(exposureMultiplier).div(uint256(totalWeight)).div(10**4);
        uint256 price = _calculatePrice(product.feed, !position.isLong, product.openInterestLong, product.openInterestShort,
            maxExposure, uint256(product.reserve), margin * position.leverage / BASE);

        bool isLiquidatable;
        int256 pnl = _getPnl(position, margin, price);
        if (pnl < 0 && uint256(-1 * pnl) >= margin.mul(uint256(product.liquidationThreshold)).div(10**4)) {
            margin = uint256(position.margin);
            pnl = -1 * int256(uint256(position.margin));
            isLiquidatable = true;
        } else {
            // front running protection: if oracle price up change is smaller than threshold and minProfitTime has not passed, the pnl is be set to 0
            if (pnl > 0 && !_canTakeProfit(position, IOracle(oracle).getPrice(product.feed), product.minPriceChange)) {
                pnl = 0;
            }
        }

        uint256 totalFee = _updateVaultAndGetFee(pnl, position, margin, uint256(product.fee), uint256(product.interest));
        _updateOpenInterest(uint256(position.productId), margin.mul(uint256(position.leverage)).div(BASE), position.isLong, false);

        emit ClosePosition(
            positionId,
            position.owner,
            uint256(position.productId),
            price,
            uint256(position.price),
            margin,
            uint256(position.leverage),
            totalFee,
            pnl,
            isLiquidatable
        );

        if (isFullClose) {
            delete positions[positionId];
        } else {
            position.margin -= uint64(margin);
        }
    }

    function _updateVaultAndGetFee(
        int256 pnl,
        Position memory position,
        uint256 margin,
        uint256 fee,
        uint256 interest
    ) internal returns(uint256) {

        (int256 pnlAfterFee, uint256 totalFee) = _getPnlWithFee(pnl, position, margin, fee, interest);
        // Update vault
        if (pnlAfterFee < 0) {
            uint256 _pnlAfterFee = uint256(-1 * pnlAfterFee);
            if (_pnlAfterFee < margin) {
                IERC20(token).uniTransfer(position.owner, (margin.sub(_pnlAfterFee)).mul(tokenBase).div(BASE));
                vault.balance += uint96(_pnlAfterFee);
            } else {
                vault.balance += uint96(margin);
                return totalFee;
            }

        } else {
            uint256 _pnlAfterFee = uint256(pnlAfterFee);
            // Check vault
            require(uint256(vault.balance) >= _pnlAfterFee, "!vault-insufficient");
            vault.balance -= uint96(_pnlAfterFee);

            IERC20(token).uniTransfer(position.owner, (margin.add(_pnlAfterFee)).mul(tokenBase).div(BASE));
        }

        pendingProtocolReward = pendingProtocolReward.add(totalFee.mul(protocolRewardRatio).div(10**4));
        pendingPikaReward = pendingPikaReward.add(totalFee.mul(pikaRewardRatio).div(10**4));
        pendingVaultReward = pendingVaultReward.add(totalFee.mul(10**4 - protocolRewardRatio - pikaRewardRatio).div(10**4));
        vault.balance -= uint96(totalFee);

        return totalFee;
    }

    function releaseMargin(uint256 positionId) external onlyOwner {

        Position storage position = positions[positionId];
        require(position.margin > 0, "!position");

        uint256 margin = position.margin;
        address positionOwner = position.owner;

        uint256 amount = margin.mul(uint256(position.leverage)).div(BASE);

        _updateOpenInterest(uint256(position.productId), amount, position.isLong, false);

        emit ClosePosition(
            positionId,
            positionOwner,
            position.productId,
            position.price,
            position.price,
            margin,
            position.leverage,
            0,
            0,
            false
        );

        delete positions[positionId];

        IERC20(token).uniTransfer(positionOwner, margin.mul(tokenBase).div(BASE));
    }


    // Liquidate positionIds
    function liquidatePositions(uint256[] calldata positionIds) external {
        require(msg.sender == liquidator || allowPublicLiquidator, "!liquidator");

        uint256 totalLiquidatorReward;
        for (uint256 i = 0; i < positionIds.length; i++) {
            uint256 positionId = positionIds[i];
            uint256 liquidatorReward = liquidatePosition(positionId);
            totalLiquidatorReward = totalLiquidatorReward.add(liquidatorReward);
        }
        if (totalLiquidatorReward > 0) {
            IERC20(token).uniTransfer(msg.sender, totalLiquidatorReward.mul(tokenBase).div(BASE));
        }
    }


    function liquidatePosition(
        uint256 positionId
    ) internal returns(uint256 liquidatorReward) {
        Position storage position = positions[positionId];
        if (position.productId == 0) {
            return 0;
        }
        Product storage product = products[uint256(position.productId)];
        uint256 price = IOracle(oracle).getPrice(product.feed); // use oracle price for liquidation

        uint256 remainingReward;
        if (_checkLiquidation(position, price, uint256(product.liquidationThreshold))) {
            int256 pnl = _getPnl(position, position.margin, price);
            if (pnl < 0 && uint256(position.margin) > uint256(-1*pnl)) {
                uint256 _pnl = uint256(-1*pnl);
                liquidatorReward = (uint256(position.margin).sub(_pnl)).mul(uint256(product.liquidationBounty)).div(10**4);
                remainingReward = (uint256(position.margin).sub(_pnl).sub(liquidatorReward));
                pendingProtocolReward = pendingProtocolReward.add(remainingReward.mul(protocolRewardRatio).div(10**4));
                pendingPikaReward = pendingPikaReward.add(remainingReward.mul(pikaRewardRatio).div(10**4));
                pendingVaultReward = pendingVaultReward.add(remainingReward.mul(10**4 - protocolRewardRatio - pikaRewardRatio).div(10**4));
                vault.balance += uint96(_pnl);
            } else {
                vault.balance += uint96(position.margin);
            }

            uint256 amount = uint256(position.margin).mul(uint256(position.leverage)).div(BASE);

            _updateOpenInterest(uint256(position.productId), amount, position.isLong, false);

            emit ClosePosition(
                positionId,
                position.owner,
                uint256(position.productId),
                price,
                uint256(position.price),
                uint256(position.margin),
                uint256(position.leverage),
                0,
                int256(uint256(position.margin)),
                true
            );

            delete positions[positionId];

            emit PositionLiquidated(
                positionId,
                msg.sender,
                liquidatorReward,
                remainingReward
            );
        }
        return liquidatorReward;
    }

    function _updateOpenInterest(uint256 productId, uint256 amount, bool isLong, bool isIncrease) internal {
        Product storage product = products[productId];
        if (isIncrease) {
            totalOpenInterest = totalOpenInterest.add(amount);
            require(totalOpenInterest <= uint256(vault.balance).mul(utilizationMultiplier).div(10**4), "!maxOpenInterest");
            uint256 maxExposure = uint256(vault.balance).mul(uint256(product.weight)).mul(exposureMultiplier).div(uint256(totalWeight)).div(10**4);
            if (isLong) {
                product.openInterestLong += uint64(amount);
                require(uint256(product.openInterestLong) <= uint256(maxExposure).add(uint256(product.openInterestShort)), "!exposure-long");
            } else {
                product.openInterestShort += uint64(amount);
                require(uint256(product.openInterestShort) <= uint256(maxExposure).add(uint256(product.openInterestLong)), "!exposure-short");
            }
        } else {
            totalOpenInterest = totalOpenInterest.sub(amount);
            if (isLong) {
                if (uint256(product.openInterestLong) >= amount) {
                    product.openInterestLong -= uint64(amount);
                } else {
                    product.openInterestLong = 0;
                }
            } else {
                if (uint256(product.openInterestShort) >= amount) {
                    product.openInterestShort -= uint64(amount);
                } else {
                    product.openInterestShort = 0;
                }
            }
        }
    }

    function distributeProtocolReward() external returns(uint256) {
        require(msg.sender == protocolRewardDistributor, "!distributor");
        uint256 _pendingProtocolReward = pendingProtocolReward.mul(tokenBase).div(BASE);
        if (pendingProtocolReward > 0) {
            pendingProtocolReward = 0;
            IERC20(token).uniTransfer(protocolRewardDistributor, _pendingProtocolReward);
            emit ProtocolRewardDistributed(protocolRewardDistributor, _pendingProtocolReward);
        }
        return _pendingProtocolReward;
    }

    function distributePikaReward() external returns(uint256) {
        require(msg.sender == pikaRewardDistributor, "!distributor");
        uint256 _pendingPikaReward = pendingPikaReward.mul(tokenBase).div(BASE);
        if (pendingPikaReward > 0) {
            pendingPikaReward = 0;
            IERC20(token).uniTransfer(pikaRewardDistributor, _pendingPikaReward);
            emit PikaRewardDistributed(pikaRewardDistributor, _pendingPikaReward);
        }
        return _pendingPikaReward;
    }

    function distributeVaultReward() external returns(uint256) {
        require(msg.sender == vaultRewardDistributor, "!distributor");
        uint256 _pendingVaultReward = pendingVaultReward.mul(tokenBase).div(BASE);
        if (pendingVaultReward > 0) {
            pendingVaultReward = 0;
            IERC20(token).uniTransfer(vaultRewardDistributor, _pendingVaultReward);
            emit VaultRewardDistributed(vaultRewardDistributor, _pendingVaultReward);
        }
        return _pendingVaultReward;
    }

    // Getters

    function getPendingPikaReward() external view returns(uint256) {
        return pendingPikaReward.mul(tokenBase).div(BASE);
    }

    function getPendingProtocolReward() external view returns(uint256) {
        return pendingProtocolReward.mul(tokenBase).div(BASE);
    }

    function getPendingVaultReward() external view returns(uint256) {
        return pendingVaultReward.mul(tokenBase).div(BASE);
    }

    function getVault() external view returns(Vault memory) {
        return vault;
    }

    function getProduct(uint256 productId) external view returns(Product memory) {
        return products[productId];
    }

    function getPositionId(
        address account,
        uint256 productId,
        bool isLong
    ) public pure returns (uint256) {
        return uint256(keccak256(abi.encodePacked(account, productId, isLong)));
    }

    function getPosition(
        address account,
        uint256 productId,
        bool isLong
    ) external view returns(Position memory position) {
        position = positions[getPositionId(account, productId, isLong)];
    }

    function getPositions(uint256[] calldata positionIds) external view returns(Position[] memory _positions) {
        uint256 length = positionIds.length;
        _positions = new Position[](length);
        for (uint256 i=0; i < length; i++) {
            _positions[i] = positions[positionIds[i]];
        }
    }

    function getTotalShare() external view returns(uint256) {
        return uint256(vault.shares);
    }

    function getShare(address stakeOwner) external view returns(uint256) {
        return uint256(stakes[stakeOwner].shares);
    }

    function getShareBalance(address stakeOwner) external view returns(uint256) {
        if (vault.shares == 0) {
            return 0;
        }
        return (uint256(stakes[stakeOwner].shares)).mul(uint256(vault.balance)).div(uint256(vault.shares));
    }

    function getStake(address stakeOwner) external view returns(Stake memory) {
        return stakes[stakeOwner];
    }

    function canLiquidate(
        uint256 positionId
    ) external view returns(bool) {
        Position memory position = positions[positionId];
        Product storage product = products[uint256(position.productId)];
        uint256 price = IOracle(oracle).getPrice(product.feed);
        return _checkLiquidation(position, price, product.liquidationThreshold);
    }

    // Internal methods

    function _canTakeProfit(
        Position memory position,
        uint256 oraclePrice,
        uint256 minPriceChange
    ) internal view returns(bool) {
        if (block.timestamp > uint256(position.timestamp).add(minProfitTime)) {
            return true;
        } else if (position.isLong && oraclePrice > uint256(position.oraclePrice).mul(uint256(1e4).add(minPriceChange)).div(1e4)) {
            return true;
        } else if (!position.isLong && oraclePrice < uint256(position.oraclePrice).mul(uint256(1e4).sub(minPriceChange)).div(1e4)) {
            return true;
        }
        return false;
    }

    function _calculatePrice(
        address feed,
        bool isLong,
        uint256 openInterestLong,
        uint256 openInterestShort,
        uint256 maxExposure,
        uint256 reserve,
        uint256 amount
    ) internal view returns(uint256) {
        uint256 oraclePrice = IOracle(oracle).getPrice(feed);
        int256 shift = (int256(openInterestLong) - int256(openInterestShort)) * int256(maxShift) / int256(maxExposure);
        if (isLong) {
            uint256 slippage = (reserve.mul(reserve).div(reserve.sub(amount)).sub(reserve)).mul(BASE).div(amount);
            slippage = shift >= 0 ? slippage.add(uint256(shift)) : slippage.sub(uint256(-1 * shift).div(2));
            return oraclePrice.mul(slippage).div(BASE);
        } else {
            uint256 slippage = (reserve.sub(reserve.mul(reserve).div(reserve.add(amount)))).mul(BASE).div(amount);
            slippage = shift >= 0 ? slippage.add(uint256(shift).div(2)) : slippage.sub(uint256(-1 * shift));
            return oraclePrice.mul(slippage).div(BASE);
        }
    }

    function _getInterest(
        Position memory position,
        uint256 margin,
        uint256 interest
    ) internal view returns(uint256) {
        return margin.mul(uint256(position.leverage)).mul(interest)
        .mul(block.timestamp.sub(uint256(position.timestamp))).div(uint256(10**12).mul(365 days));
    }

    function _getPnl(
        Position memory position,
        uint256 margin,
        uint256 price
    ) internal view returns(int256 _pnl) {
        bool pnlIsNegative;
        uint256 pnl;
        if (position.isLong) {
            if (price >= uint256(position.price)) {
                pnl = margin.mul(uint256(position.leverage)).mul(price.sub(uint256(position.price))).div(uint256(position.price)).div(BASE);
            } else {
                pnl = margin.mul(uint256(position.leverage)).mul(uint256(position.price).sub(price)).div(uint256(position.price)).div(BASE);
                pnlIsNegative = true;
            }
        } else {
            if (price > uint256(position.price)) {
                pnl = margin.mul(uint256(position.leverage)).mul(price - uint256(position.price)).div(uint256(position.price)).div(BASE);
                pnlIsNegative = true;
            } else {
                pnl = margin.mul(uint256(position.leverage)).mul(uint256(position.price).sub(price)).div(uint256(position.price)).div(BASE);
            }
        }

        if (pnlIsNegative) {
            _pnl = -1 * int256(pnl);
        } else {
            _pnl = int256(pnl);
        }

        return _pnl;
    }

    function _getPnlWithFee(
        int256 pnl,
        Position memory position,
        uint256 margin,
        uint256 fee,
        uint256 interest
    ) internal view returns(int256 pnlAfterFee, uint256 totalFee) {
        // Subtract trade fee from P/L
        uint256 tradeFee = _getTradeFee(margin, uint256(position.leverage), fee);
        pnlAfterFee = pnl.sub(int256(tradeFee));

        // Subtract interest from P/L
        uint256 interestFee = _getInterest(position, margin, interest);
        pnlAfterFee = pnlAfterFee.sub(int256(interestFee));
        totalFee = tradeFee.add(interestFee);
    }

    function _getTradeFee(
        uint256 margin,
        uint256 leverage,
        uint256 fee
    ) internal pure returns(uint256) {
        return margin.mul(leverage).div(BASE).mul(fee).div(10**4);
    }

    function _checkLiquidation(
        Position memory position,
        uint256 price,
        uint256 liquidationThreshold
    ) internal pure returns (bool) {

        uint256 liquidationPrice;

        if (position.isLong) {
            liquidationPrice = position.price - position.price * liquidationThreshold * 10**4 / uint256(position.leverage);
        } else {
            liquidationPrice = position.price + position.price * liquidationThreshold * 10**4 / uint256(position.leverage);
        }

        if (position.isLong && price <= liquidationPrice || !position.isLong && price >= liquidationPrice) {
            return true;
        } else {
            return false;
        }
    }

    // Owner methods

    function updateVault(Vault memory _vault) external onlyOwner {
        require(_vault.cap > 0, "!cap");
        require(_vault.stakingPeriod > 0 && _vault.stakingPeriod < 30 days, "!stakingPeriod");

        vault.cap = _vault.cap;
        vault.stakingPeriod = _vault.stakingPeriod;

        emit VaultUpdated(vault);

    }

    function addProduct(uint256 productId, Product memory _product) external onlyOwner {
        require(productId > 0, "!productId");
        Product memory product = products[productId];
        require(product.maxLeverage == 0, "!product-exists");

        require(_product.maxLeverage > 1 * BASE, "!max-leverage");
        require(_product.feed != address(0), "!feed");
        require(_product.liquidationThreshold > 0, "!liquidationThreshold");

        products[productId] = Product({
        feed: _product.feed,
        maxLeverage: _product.maxLeverage,
        fee: _product.fee,
        isActive: true,
        openInterestLong: 0,
        openInterestShort: 0,
        interest: _product.interest,
        liquidationThreshold: _product.liquidationThreshold,
        liquidationBounty: _product.liquidationBounty,
        minPriceChange: _product.minPriceChange,
        weight: _product.weight,
        reserve: _product.reserve
        });
        totalWeight += _product.weight;

        emit ProductAdded(productId, products[productId]);

    }

    function updateProduct(uint256 productId, Product memory _product) external onlyOwner {
        require(productId > 0, "!productId");
        Product storage product = products[productId];
        require(product.maxLeverage > 0, "!product-exists");

        require(_product.maxLeverage >= 1 * BASE, "!max-leverage");
        require(_product.feed != address(0), "!feed");
        require(_product.liquidationThreshold > 0, "!liquidationThreshold");

        product.feed = _product.feed;
        product.maxLeverage = _product.maxLeverage;
        product.fee = _product.fee;
        product.isActive = _product.isActive;
        product.interest = _product.interest;
        product.liquidationThreshold = _product.liquidationThreshold;
        product.liquidationBounty = _product.liquidationBounty;
        totalWeight = totalWeight - product.weight + _product.weight;
        product.weight = _product.weight;

        emit ProductUpdated(productId, product);

    }

    function setDistributors(
        address _protocolRewardDistributor,
        address _pikaRewardDistributor,
        address _vaultRewardDistributor,
        address _vaultTokenReward
    ) external onlyOwner {
        protocolRewardDistributor = _protocolRewardDistributor;
        pikaRewardDistributor = _pikaRewardDistributor;
        vaultRewardDistributor = _vaultRewardDistributor;
        vaultTokenReward = _vaultTokenReward;
    }

    function setRewardRatio(uint256 _protocolRewardRatio, uint256 _pikaRewardRatio) external onlyOwner {
        require(_protocolRewardRatio + _pikaRewardRatio <= 10000, "!too-much");
        protocolRewardRatio = _protocolRewardRatio;
        pikaRewardRatio = _pikaRewardRatio;
        emit RewardRatioUpdated(protocolRewardRatio, pikaRewardRatio);
    }

    function setMargin(uint256 _minMargin, uint256 _maxPositionMargin) external onlyOwner {
        minMargin = _minMargin;
        maxPositionMargin = _maxPositionMargin;
    }

    function setMaxShiftAndMinProfitTime(uint256 _maxShift, uint256 _minProfitTime) external onlyOwner {
        require(_maxShift >= 0 && _maxShift <= 0.01e8 && _minProfitTime >= 0 && _minProfitTime <= 24 hours);
        maxShift = _maxShift;
        minProfitTime = _minProfitTime;
    }

    function setCanUserStakeAndAllowPublicLiquidator(bool _canUserStake, bool _allowPublicLiquidator) external onlyOwner {
        canUserStake = _canUserStake;
        allowPublicLiquidator = _allowPublicLiquidator;
    }

    function setExposureMultiplier(uint256 _exposureMultiplier) external onlyOwner {
        exposureMultiplier = _exposureMultiplier;
    }

    function setOracle(address _oracle) external onlyOwner {
        oracle = _oracle;
        emit OracleUpdated(_oracle);
    }

    function setLiquidator(address _liquidator) external onlyOwner {
        liquidator = _liquidator;
    }

    function setOwner(address _owner) external onlyOwner {
        owner = _owner;
        emit OwnerUpdated(_owner);
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "!owner");
        _;
    }

}

File 2 of 11 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 3 of 11 : SignedSafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SignedSafeMath {
    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        return a / b;
    }

    /**
     * @dev Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        return a - b;
    }

    /**
     * @dev Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        return a + b;
    }
}

File 4 of 11 : IERC20.sol
// SPDX-License-Identifier: MIT

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 5 of 11 : SafeERC20.sol
// SPDX-License-Identifier: MIT

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 6 of 11 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

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 make 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 7 of 11 : IOracle.sol
pragma solidity ^0.8.0;

interface IOracle {
    function getPrice(address feed) external view returns (uint256);
}

File 8 of 11 : UniERC20.sol
// SPDX-License-Identifier: MIT

// Originally: https://github.com/CryptoManiacsZone/mooniswap/blob/master/contracts/libraries/UniERC20.sol

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

library UniERC20 {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    function isETH(IERC20 token) internal pure returns (bool) {
        return (address(token) == address(0));
    }

    function uniBalanceOf(IERC20 token, address account) internal view returns (uint256) {
        if (isETH(token)) {
            return account.balance;
        } else {
            return token.balanceOf(account);
        }
    }

    function uniTransfer(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        if (amount > 0) {
            if (isETH(token)) {
                (bool success, ) = payable(to).call{value: amount}("");
                require(success, "Transfer failed");
            } else {
                token.safeTransfer(to, amount);
            }
        }
    }

    function uniTransferFromSenderToThis(IERC20 token, uint256 amount) internal {
        if (amount > 0) {
            if (isETH(token)) {
                require(msg.value >= amount, "UniERC20: not enough value");
                if (msg.value > amount) {
                    // Return remainder if exist
                    uint256 refundAmount = msg.value.sub(amount);
                    (bool success, ) = msg.sender.call{value: refundAmount}("");
                    require(success, "Transfer failed");
                }
            } else {
                token.safeTransferFrom(msg.sender, address(this), amount);
            }
        }
    }
}

File 9 of 11 : IPikaPerp.sol
//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IPikaPerp {
    function getTotalShare() external view returns(uint256);
    function getShare(address stakeOwner) external view returns(uint256);
    function distributeProtocolReward() external returns(uint256);
    function distributePikaReward() external returns(uint256);
    function distributeVaultReward() external returns(uint256);
    function getPendingPikaReward() external view returns(uint256);
    function getPendingProtocolReward() external view returns(uint256);
    function getPendingVaultReward() external view returns(uint256);
    function stake(uint256 amount) external;
    function stakeForUser(uint256 amount, address user) external;
    function redeem(uint256 shares) external;
}

File 10 of 11 : IVaultReward.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

interface IVaultReward {
    function updateReward(address account) external;
}

File 11 of 11 : Address.sol
// SPDX-License-Identifier: MIT

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);
            }
        }
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenDecimal","type":"uint256"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"uint256","name":"_minMargin","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"margin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMargin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLeverage","type":"uint256"}],"name":"AddMargin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"productId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"entryPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"margin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"leverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"int256","name":"pnl","type":"int256"},{"indexed":false,"internalType":"bool","name":"wasLiquidated","type":"bool"}],"name":"ClosePosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"productId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isLong","type":"bool"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oraclePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"margin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"leverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"NewPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOracle","type":"address"}],"name":"OracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PikaRewardDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"uint256","name":"liquidatorReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingReward","type":"uint256"}],"name":"PositionLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"productId","type":"uint256"},{"components":[{"internalType":"address","name":"feed","type":"address"},{"internalType":"uint72","name":"maxLeverage","type":"uint72"},{"internalType":"uint16","name":"fee","type":"uint16"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint64","name":"openInterestLong","type":"uint64"},{"internalType":"uint64","name":"openInterestShort","type":"uint64"},{"internalType":"uint16","name":"interest","type":"uint16"},{"internalType":"uint16","name":"liquidationThreshold","type":"uint16"},{"internalType":"uint16","name":"liquidationBounty","type":"uint16"},{"internalType":"uint16","name":"minPriceChange","type":"uint16"},{"internalType":"uint16","name":"weight","type":"uint16"},{"internalType":"uint64","name":"reserve","type":"uint64"}],"indexed":false,"internalType":"struct PikaPerpV2.Product","name":"product","type":"tuple"}],"name":"ProductAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"productId","type":"uint256"},{"components":[{"internalType":"address","name":"feed","type":"address"},{"internalType":"uint72","name":"maxLeverage","type":"uint72"},{"internalType":"uint16","name":"fee","type":"uint16"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint64","name":"openInterestLong","type":"uint64"},{"internalType":"uint64","name":"openInterestShort","type":"uint64"},{"internalType":"uint16","name":"interest","type":"uint16"},{"internalType":"uint16","name":"liquidationThreshold","type":"uint16"},{"internalType":"uint16","name":"liquidationBounty","type":"uint16"},{"internalType":"uint16","name":"minPriceChange","type":"uint16"},{"internalType":"uint16","name":"weight","type":"uint16"},{"internalType":"uint64","name":"reserve","type":"uint64"}],"indexed":false,"internalType":"struct PikaPerpV2.Product","name":"product","type":"tuple"}],"name":"ProductUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ProtocolRewardDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareBalance","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isFullRedeem","type":"bool"}],"name":"Redeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"protocolRewardRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pikaRewardRatio","type":"uint256"}],"name":"RewardRatioUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VaultRewardDistributed","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint96","name":"cap","type":"uint96"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint64","name":"staked","type":"uint64"},{"internalType":"uint64","name":"shares","type":"uint64"},{"internalType":"uint32","name":"stakingPeriod","type":"uint32"}],"indexed":false,"internalType":"struct PikaPerpV2.Vault","name":"vault","type":"tuple"}],"name":"VaultUpdated","type":"event"},{"inputs":[],"name":"BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"uint256","name":"margin","type":"uint256"}],"name":"addMargin","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"productId","type":"uint256"},{"components":[{"internalType":"address","name":"feed","type":"address"},{"internalType":"uint72","name":"maxLeverage","type":"uint72"},{"internalType":"uint16","name":"fee","type":"uint16"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint64","name":"openInterestLong","type":"uint64"},{"internalType":"uint64","name":"openInterestShort","type":"uint64"},{"internalType":"uint16","name":"interest","type":"uint16"},{"internalType":"uint16","name":"liquidationThreshold","type":"uint16"},{"internalType":"uint16","name":"liquidationBounty","type":"uint16"},{"internalType":"uint16","name":"minPriceChange","type":"uint16"},{"internalType":"uint16","name":"weight","type":"uint16"},{"internalType":"uint64","name":"reserve","type":"uint64"}],"internalType":"struct PikaPerpV2.Product","name":"_product","type":"tuple"}],"name":"addProduct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"positionId","type":"uint256"}],"name":"canLiquidate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"productId","type":"uint256"},{"internalType":"uint256","name":"margin","type":"uint256"},{"internalType":"bool","name":"isLong","type":"bool"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"uint256","name":"margin","type":"uint256"}],"name":"closePositionWithId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distributePikaReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distributeProtocolReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distributeVaultReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exposureMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingPikaReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingProtocolReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingVaultReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"productId","type":"uint256"},{"internalType":"bool","name":"isLong","type":"bool"}],"name":"getPosition","outputs":[{"components":[{"internalType":"uint64","name":"productId","type":"uint64"},{"internalType":"uint64","name":"leverage","type":"uint64"},{"internalType":"uint64","name":"price","type":"uint64"},{"internalType":"uint64","name":"oraclePrice","type":"uint64"},{"internalType":"uint64","name":"margin","type":"uint64"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint80","name":"timestamp","type":"uint80"},{"internalType":"bool","name":"isLong","type":"bool"}],"internalType":"struct PikaPerpV2.Position","name":"position","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"productId","type":"uint256"},{"internalType":"bool","name":"isLong","type":"bool"}],"name":"getPositionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"positionIds","type":"uint256[]"}],"name":"getPositions","outputs":[{"components":[{"internalType":"uint64","name":"productId","type":"uint64"},{"internalType":"uint64","name":"leverage","type":"uint64"},{"internalType":"uint64","name":"price","type":"uint64"},{"internalType":"uint64","name":"oraclePrice","type":"uint64"},{"internalType":"uint64","name":"margin","type":"uint64"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint80","name":"timestamp","type":"uint80"},{"internalType":"bool","name":"isLong","type":"bool"}],"internalType":"struct PikaPerpV2.Position[]","name":"_positions","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"productId","type":"uint256"}],"name":"getProduct","outputs":[{"components":[{"internalType":"address","name":"feed","type":"address"},{"internalType":"uint72","name":"maxLeverage","type":"uint72"},{"internalType":"uint16","name":"fee","type":"uint16"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint64","name":"openInterestLong","type":"uint64"},{"internalType":"uint64","name":"openInterestShort","type":"uint64"},{"internalType":"uint16","name":"interest","type":"uint16"},{"internalType":"uint16","name":"liquidationThreshold","type":"uint16"},{"internalType":"uint16","name":"liquidationBounty","type":"uint16"},{"internalType":"uint16","name":"minPriceChange","type":"uint16"},{"internalType":"uint16","name":"weight","type":"uint16"},{"internalType":"uint64","name":"reserve","type":"uint64"}],"internalType":"struct PikaPerpV2.Product","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakeOwner","type":"address"}],"name":"getShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakeOwner","type":"address"}],"name":"getShareBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakeOwner","type":"address"}],"name":"getStake","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint64","name":"amount","type":"uint64"},{"internalType":"uint64","name":"shares","type":"uint64"},{"internalType":"uint32","name":"timestamp","type":"uint32"}],"internalType":"struct PikaPerpV2.Stake","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVault","outputs":[{"components":[{"internalType":"uint96","name":"cap","type":"uint96"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint64","name":"staked","type":"uint64"},{"internalType":"uint64","name":"shares","type":"uint64"},{"internalType":"uint32","name":"stakingPeriod","type":"uint32"}],"internalType":"struct PikaPerpV2.Vault","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"positionIds","type":"uint256[]"}],"name":"liquidatePositions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPositionMargin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxShift","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minMargin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minProfitTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"productId","type":"uint256"},{"internalType":"uint256","name":"margin","type":"uint256"},{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"uint256","name":"leverage","type":"uint256"}],"name":"openPosition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"productId","type":"uint256"},{"internalType":"uint256","name":"margin","type":"uint256"},{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"uint256","name":"leverage","type":"uint256"}],"name":"openPositionForUser","outputs":[{"internalType":"uint256","name":"positionId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingPikaReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingProtocolReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingVaultReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pikaRewardDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pikaRewardRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolRewardDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolRewardRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"positionId","type":"uint256"}],"name":"releaseMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_canUserStake","type":"bool"},{"internalType":"bool","name":"_allowPublicLiquidator","type":"bool"}],"name":"setCanUserStakeAndAllowPublicLiquidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_protocolRewardDistributor","type":"address"},{"internalType":"address","name":"_pikaRewardDistributor","type":"address"},{"internalType":"address","name":"_vaultRewardDistributor","type":"address"},{"internalType":"address","name":"_vaultTokenReward","type":"address"}],"name":"setDistributors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exposureMultiplier","type":"uint256"}],"name":"setExposureMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_liquidator","type":"address"}],"name":"setLiquidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minMargin","type":"uint256"},{"internalType":"uint256","name":"_maxPositionMargin","type":"uint256"}],"name":"setMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShift","type":"uint256"},{"internalType":"uint256","name":"_minProfitTime","type":"uint256"}],"name":"setMaxShiftAndMinProfitTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracle","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_protocolRewardRatio","type":"uint256"},{"internalType":"uint256","name":"_pikaRewardRatio","type":"uint256"}],"name":"setRewardRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"stakeForUser","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenDecimal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalOpenInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"productId","type":"uint256"},{"components":[{"internalType":"address","name":"feed","type":"address"},{"internalType":"uint72","name":"maxLeverage","type":"uint72"},{"internalType":"uint16","name":"fee","type":"uint16"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint64","name":"openInterestLong","type":"uint64"},{"internalType":"uint64","name":"openInterestShort","type":"uint64"},{"internalType":"uint16","name":"interest","type":"uint16"},{"internalType":"uint16","name":"liquidationThreshold","type":"uint16"},{"internalType":"uint16","name":"liquidationBounty","type":"uint16"},{"internalType":"uint16","name":"minPriceChange","type":"uint16"},{"internalType":"uint16","name":"weight","type":"uint16"},{"internalType":"uint64","name":"reserve","type":"uint64"}],"internalType":"struct PikaPerpV2.Product","name":"_product","type":"tuple"}],"name":"updateProduct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint96","name":"cap","type":"uint96"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint64","name":"staked","type":"uint64"},{"internalType":"uint64","name":"shares","type":"uint64"},{"internalType":"uint32","name":"stakingPeriod","type":"uint32"}],"internalType":"struct PikaPerpV2.Vault","name":"_vault","type":"tuple"}],"name":"updateVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"utilizationMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultRewardDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultTokenReward","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60806040526107d0600855610bb8600955620493e0600a5561a8c0600b55612710600e819055600f556018805461ffff191690553480156200004057600080fd5b50604051620062b7380380620062b7833981016040819052620000639162000149565b600160008190558054336001600160a01b03199182168117909255600280548216909217909155600380549091166001600160a01b0386161790556004839055620000b083600a620001db565b600555600680546001600160a01b0319166001600160a01b03939093169290921790915560075550506040805160a0810182526000808252602082018190529181018290526060810182905262015180608090910152601955601a80546001600160601b0319166a0151800000000000000000179055620002bc565b80516001600160a01b03811681146200014457600080fd5b919050565b600080600080608085870312156200016057600080fd5b6200016b856200012c565b93506020850151925062000182604086016200012c565b6060959095015193969295505050565b600181815b80851115620001d3578160001904821115620001b757620001b7620002a6565b80851615620001c557918102915b93841c939080029062000197565b509250929050565b6000620001e98383620001f0565b9392505050565b6000826200020157506001620002a0565b816200021057506000620002a0565b8160018114620002295760028114620002345762000254565b6001915050620002a0565b60ff841115620002485762000248620002a6565b50506001821b620002a0565b5060208310610133831016604e8410600b841016171562000279575081810a620002a0565b62000285838362000192565b80600019048211156200029c576200029c620002a6565b0290505b92915050565b634e487b7160e01b600052601160045260246000fd5b615feb80620002cc6000396000f3fe6080604052600436106103b55760003560e01c806381a3daca116101f2578063b9db15b41161010d578063d65fe355116100a0578063ec342ad01161006f578063ec342ad014610d79578063f4b1559514610d8e578063fbb48bc114610dae578063fc0c546a14610dc357600080fd5b8063d65fe35514610d0d578063d9ac422514610d2d578063db006a7514610d43578063e19a60e114610d6357600080fd5b8063d32bb3e9116100dc578063d32bb3e914610ca4578063d41194b814610cc4578063d468e2a914610cd7578063d48788b914610ced57600080fd5b8063b9db15b414610ad0578063bc95baad14610c37578063bed5755414610c64578063cd84db0914610c8457600080fd5b806396c82e5711610185578063a576d8ad11610154578063a576d8ad14610a67578063a694fc3a14610a87578063b26d97e914610a9a578063b61daaee14610aba57600080fd5b806396c82e57146109eb5780639df411ee14610a01578063a0448fc514610a31578063a082cdd214610a4757600080fd5b80638d928af8116101c15780638d928af8146108945780638da5cb5b146109955780638ea8f7fc146109b5578063904a53b6146109cb57600080fd5b806381a3daca14610834578063841a4b51146108545780638b09578d1461086a5780638c10ad1b1461087f57600080fd5b80633ee19763116102e25780635f3b21801161027557806378d7fb7f1161024457806378d7fb7f146106e85780637a766460146106fb5780637adbf973146107f45780637dc0d1d01461081457600080fd5b80635f3b21801461068a57806367d3ef9a146106a05780636e20c3b4146106c057806370607f5d146106d557600080fd5b80634c723c28116102b15780634c723c28146106115780634d452ec01461063e5780635b3829891461065e5780635caed0291461067457600080fd5b80633ee197631461057c5780633f06cd66146105915780634046ebae146105af5780634b3ab9c5146105cf57600080fd5b80631ba938441161035a5780632dc9265e116103295780632dc9265e1461051d57806333af0efa1461053d57806339c294be146105535780633dc8f1441461056957600080fd5b80631ba93844146104a55780631ea8c3a7146104dd5780631fbeef4e146104f2578063228f524e1461050757600080fd5b806301c76f811161039657806301c76f81146104255780630904c2db14610445578063114379411461046557806313af40351461048557600080fd5b80620b15a3146103ba5780621b7934146103dc578062eb5b62146103fc575b600080fd5b3480156103c657600080fd5b506103da6103d5366004615672565b610de3565b005b3480156103e857600080fd5b506103da6103f7366004615783565b6110e6565b34801561040857600080fd5b5061041260125481565b6040519081526020015b60405180910390f35b34801561043157600080fd5b506103da6104403660046153a5565b61119e565b34801561045157600080fd5b506103da610460366004615614565b6111ea565b34801561047157600080fd5b506104126104803660046153a5565b611219565b34801561049157600080fd5b506103da6104a03660046153a5565b611290565b3480156104b157600080fd5b506015546104c5906001600160a01b031681565b6040516001600160a01b03909116815260200161041c565b3480156104e957600080fd5b5061041261130f565b3480156104fe57600080fd5b506104126113d6565b34801561051357600080fd5b50610412600c5481565b34801561052957600080fd5b506103da610538366004615783565b611493565b34801561054957600080fd5b5061041260115481565b34801561055f57600080fd5b5061041260075481565b6104126105773660046157d3565b6114c8565b34801561058857600080fd5b506104126114e0565b34801561059d57600080fd5b50601a546001600160401b0316610412565b3480156105bb57600080fd5b506002546104c5906001600160a01b031681565b3480156105db57600080fd5b506104126105ea3660046153a5565b6001600160a01b03166000908152601c60205260409020600101546001600160401b031690565b34801561061d57600080fd5b5061063161062c3660046154a4565b611505565b60405161041c9190615990565b34801561064a57600080fd5b506103da6106593660046154a4565b61165d565b34801561066a57600080fd5b50610412600f5481565b34801561068057600080fd5b5061041260045481565b34801561069657600080fd5b5061041260085481565b3480156106ac57600080fd5b506103da6106bb3660046157a5565b61174e565b3480156106cc57600080fd5b50610412611762565b6103da6106e3366004615646565b611773565b6104126106f6366004615454565b611c59565b34801561070757600080fd5b506107a46107163660046153a5565b604080516080810182526000808252602082018190529181018290526060810191909152506001600160a01b039081166000908152601c6020908152604091829020825160808101845281549485168152600160a01b9094046001600160401b03908116928501929092526001015490811691830191909152600160401b900463ffffffff16606082015290565b6040805182516001600160a01b031681526020808401516001600160401b039081169183019190915283830151169181019190915260609182015163ffffffff169181019190915260800161041c565b34801561080057600080fd5b506103da61080f3660046153a5565b6123ef565b34801561082057600080fd5b506006546104c5906001600160a01b031681565b34801561084057600080fd5b506014546104c5906001600160a01b031681565b34801561086057600080fd5b50610412600e5481565b34801561087657600080fd5b50610412600881565b34801561088b57600080fd5b50610412612467565b3480156108a057600080fd5b506109316040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526019546001600160601b038082168352600160601b8204166020830152600160c01b90046001600160401b0390811692820192909252601a549182166060820152600160401b90910463ffffffff16608082015290565b60405161041c9190600060a0820190506001600160601b038084511683528060208501511660208401525060408301516001600160401b038082166040850152806060860151166060850152505063ffffffff608084015116608083015292915050565b3480156109a157600080fd5b506001546104c5906001600160a01b031681565b3480156109c157600080fd5b5061041260105481565b3480156109d757600080fd5b506103da6109e6366004615783565b612478565b3480156109f757600080fd5b50610412600d5481565b348015610a0d57600080fd5b50610a21610a1c366004615614565b6124d6565b604051901515815260200161041c565b348015610a3d57600080fd5b50610412600a5481565b348015610a5357600080fd5b506103da610a623660046153c0565b612615565b348015610a7357600080fd5b506103da610a82366004615614565b61268f565b6103da610a95366004615614565b61286d565b348015610aa657600080fd5b506103da610ab5366004615672565b61287a565b348015610ac657600080fd5b5061041260055481565b348015610adc57600080fd5b50610c2a610aeb366004615614565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810191909152506000908152601b602090815260409182902082516101808101845281546001600160a01b0381168252600160a01b8082046001600160481b031694830194909452600160e81b810461ffff90811695830195909552600160f81b900460ff161515606082015260018201546001600160401b038082166080840152600160401b8204811660a0840152600160801b8204861660c0840152600160901b8204861660e08401529381048516610100830152600160b01b81048516610120830152600160c01b9004909316610140840152600201541661016082015290565b60405161041c9190615ae6565b348015610c4357600080fd5b50610c57610c52366004615414565b612de0565b60405161041c9190615ad7565b348015610c7057600080fd5b506013546104c5906001600160a01b031681565b348015610c9057600080fd5b506103da610c9f366004615783565b612e9c565b348015610cb057600080fd5b506103da610cbf36600461556e565b613495565b6103da610cd2366004615783565b613616565b348015610ce357600080fd5b5061041260175481565b348015610cf957600080fd5b506016546104c5906001600160a01b031681565b348015610d1957600080fd5b50610412610d28366004615414565b613800565b348015610d3957600080fd5b50610412600b5481565b348015610d4f57600080fd5b506103da610d5e366004615614565b613852565b348015610d6f57600080fd5b5061041260095481565b348015610d8557600080fd5b50610412613d28565b348015610d9a57600080fd5b506103da610da9366004615535565b613d37565b348015610dba57600080fd5b50610412613d85565b348015610dcf57600080fd5b506003546104c5906001600160a01b031681565b6001546001600160a01b03163314610e165760405162461bcd60e51b8152600401610e0d90615ab7565b60405180910390fd5b60008211610e535760405162461bcd60e51b815260206004820152600a602482015269085c1c9bd91d58dd125960b21b6044820152606401610e0d565b6000828152601b602052604090208054600160a01b90046001600160481b0316610eb15760405162461bcd60e51b815260206004820152600f60248201526e2170726f647563742d65786973747360881b6044820152606401610e0d565b610ebd6008600a615d1e565b610ec8906001615e4b565b82602001516001600160481b03161015610ef45760405162461bcd60e51b8152600401610e0d90615a59565b81516001600160a01b0316610f335760405162461bcd60e51b8152602060048201526005602482015264085999595960da1b6044820152606401610e0d565b60008260e0015161ffff1611610f835760405162461bcd60e51b8152602060048201526015602482015274085b1a5c5d5a59185d1a5bdb951a1c995cda1bdb19605a1b6044820152606401610e0d565b815181546020840151604085015160608601516001600160a01b039094166001600160e81b031990931692909217600160a01b6001600160481b039092168202176001600160e81b0316600160e81b61ffff938416026001600160f81b031617600160f81b9315159390930292909217835560c084015160018401805460e087015161010088015163ffffffff60801b19909216600160801b9486169490940261ffff60901b191693909317600160901b938516939093029290921761ffff60a01b19169183169093021791829055610140840151600d549082169261107292600160c01b9091041690615ea9565b61107c9190615c34565b600d5561014082015160018201805461ffff909216600160c01b0261ffff60c01b199092169190911790556040517ff67c96d097a316014b351edfed880cf93784164f445f0bbb26cde56fb89fa2fc906110d99085908490615be8565b60405180910390a1505050565b6001546001600160a01b031633146111105760405162461bcd60e51b8152600401610e0d90615ab7565b61271061111d8284615c34565b11156111575760405162461bcd60e51b8152602060048201526009602482015268042e8dede5adaeac6d60bb1b6044820152606401610e0d565b6008829055600981905560408051838152602081018390527f2cda5f90308a6ed0aad400f6ddc7575e31b5f1428c50c054ae54e1939ff164b8910160405180910390a15050565b6001546001600160a01b031633146111c85760405162461bcd60e51b8152600401610e0d90615ab7565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146112145760405162461bcd60e51b8152600401610e0d90615ab7565b600e55565b601a546000906001600160401b031661123457506000919050565b601a546019546001600160a01b0384166000908152601c602052604090206001015461128a926001600160401b039081169261128492909116906001600160601b03600160601b90910416613e33565b90613e3f565b92915050565b6001546001600160a01b031633146112ba5760405162461bcd60e51b8152600401610e0d90615ab7565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b906020015b60405180910390a150565b6014546000906001600160a01b0316331461133c5760405162461bcd60e51b8152600401610e0d90615a12565b600061135c61134d6008600a615d1e565b60055460115461128491613e33565b601154909150156113d1576000601155601454600354611389916001600160a01b03918216911683613e4b565b601454604080516001600160a01b039092168252602082018390527f304116b7df0fff49d35547e731489e0e2f288bf99c5293f5fb4697671108280d91015b60405180910390a15b919050565b6013546000906001600160a01b031633146114035760405162461bcd60e51b8152600401610e0d90615a12565b60006114236114146008600a615d1e565b60055460105461128491613e33565b601054909150156113d1576000601055601354600354611450916001600160a01b03918216911683613e4b565b601354604080516001600160a01b039092168252602082018390527ffbbb21b60e499f2366d8f9dbdb1884e047dcf008673ee2c189b6153bfacc06e891016113c8565b6001546001600160a01b031633146114bd5760405162461bcd60e51b8152600401610e0d90615ab7565b600791909155600c55565b60006114d73386868686611c59565b95945050505050565b60006115006114f16008600a615d1e565b60055460125461128491613e33565b905090565b606081806001600160401b0381111561152057611520615f91565b60405190808252806020026020018201604052801561155957816020015b6115466152e8565b81526020019060019003908161153e5790505b50915060005b8181101561165557601d600086868481811061157d5761157d615f7b565b6020908102929092013583525081810192909252604090810160002081516101008101835281546001600160401b038082168352600160401b808304821696840196909652600160801b8204811694830194909452600160c01b90048316606082015260018201549283166080820152929091046001600160a01b031660a0830152600201546001600160501b03811660c0830152600160501b900460ff16151560e0820152835184908390811061163757611637615f7b565b6020026020010181905250808061164d90615f34565b91505061155f565b505092915050565b6002546001600160a01b031633148061167d5750601854610100900460ff165b6116b75760405162461bcd60e51b815260206004820152600b60248201526a10b634b8bab4b230ba37b960a91b6044820152606401610e0d565b6000805b8281101561170e5760008484838181106116d7576116d7615f7b565b90506020020135905060006116eb82613f0e565b90506116f7848261444d565b93505050808061170690615f34565b9150506116bb565b50801561174957611749336117366117286008600a615d1e565b600554611284908690613e33565b6003546001600160a01b03169190613e4b565b505050565b61174961175c338584613800565b83612e9c565b600061150061134d6008600a615d1e565b600260005414156117965760405162461bcd60e51b8152600401610e0d90615a80565b600260005560185460ff16806117b657506001546001600160a01b031633145b6117eb5760405162461bcd60e51b8152602060048201526006602482015265217374616b6560d01b6044820152606401610e0d565b60155460405163632447c960e01b81526001600160a01b0383811660048301529091169063632447c990602401600060405180830381600087803b15801561183257600080fd5b505af1158015611846573d6000803e3d6000fd5b505060165460405163632447c960e01b81526001600160a01b038581166004830152909116925063632447c99150602401600060405180830381600087803b15801561189157600080fd5b505af11580156118a5573d6000803e3d6000fd5b505050506118cf6118bd6008600a6117289190615d1e565b6003546001600160a01b031690614459565b6019546001600160601b038116906118f8908490600160c01b90046001600160401b0316615c34565b111561192f5760405162461bcd60e51b8152600401610e0d906020808252600490820152630216361760e41b604082015260600190565b601954600090600160c01b90046001600160401b031661194f578261197e565b601954601a5461197e91600160601b90046001600160601b0316906112849086906001600160401b0316613e33565b601980549192508491600c906119a5908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555082601960000160188282829054906101000a90046001600160401b03166119f09190615c4c565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555080601960010160008282829054906101000a90046001600160401b0316611a3b9190615c4c565b82546101009290920a6001600160401b038181021990931691831602179091556001600160a01b0384166000908152601c6020526040902054600160a01b90041615159050611b2657604080516080810182526001600160a01b038085168083526001600160401b03808816602080860191825287831686880190815263ffffffff428116606089019081526000968752601c909352979094209551865492518416600160a01b026001600160e01b03199093169516949094171784559051600190930180549251909416600160401b026001600160601b0319909216921691909117179055611c0b565b6001600160a01b0382166000908152601c602052604090208054849190601490611b61908490600160a01b90046001600160401b0316615c4c565b82546101009290920a6001600160401b038181021990931691831602179091556001600160a01b0384166000908152601c6020526040812060010180548594509092611baf91859116615c4c565b82546101009290920a6001600160401b03818102199093169190921691909102179055506001600160a01b0382166000908152601c60205260409020600101805463ffffffff60401b1916600160401b4263ffffffff16021790555b60408051848152602081018390526001600160a01b038416917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90910160405180910390a25050600160005550565b600060026000541415611c7e5760405162461bcd60e51b8152600401610e0d90615a80565b6002600055600754841015611ca55760405162461bcd60e51b8152600401610e0d90615a38565b611cb16008600a615d1e565b611cbc906001615e4b565b821015611cf75760405162461bcd60e51b8152602060048201526009602482015268216c6576657261676560b81b6044820152606401610e0d565b6000858152601b602052604090208054600160f81b900460ff16611d4f5760405162461bcd60e51b815260206004820152600f60248201526e2170726f647563742d61637469766560881b6044820152606401610e0d565b8054600160a01b90046001600160481b0316831115611d805760405162461bcd60e51b8152600401610e0d90615a59565b8054600090611d9d9087908690600160e81b900461ffff1661452f565b9050611dc86118bd611db16008600a615d1e565b60055461128490611dc28b8761444d565b90613e33565b611def611de661271061128460085485613e3390919063ffffffff16565b6010549061444d565b601055600954611e1590611e0c9061271090611284908590613e33565b6011549061444d565b601181905550611e54611e4b612710611284600954600854612710611e3a9190615ea9565b611e449190615ea9565b8590613e33565b6012549061444d565b6012556000611e72611e686008600a615d1e565b6112848988613e33565b83546001850154600d54600e54601954949550600094611ef8946001600160a01b0316938c936001600160401b0380831694600160401b840490911693611ee493612710936112849390928492611dc291600160601b90046001600160601b031690600160c01b900461ffff16613e33565b60028a01546001600160401b03168861455c565b9050611f078983896001614707565b611f128a8a89613800565b6000818152601d602052604090206001810154919650906001600160401b03161561202557611fb6611f72611f478b8a613e33565b83546001850154611f6c916001600160401b0391821691600160401b90910416613e33565b9061444d565b611284611f8385611dc28e8d613e33565b84546001860154611f6c916001600160401b03600160801b8204811692611dc29290821691600160401b90910416613e33565b600182015490925061200790611fd5906001600160401b03168b61444d565b611284611fe28c8b613e33565b84546001860154611f6c916001600160401b0391821691600160401b90910416613e33565b6001820154909750612022906001600160401b03168a61444d565b98505b600c5489106120645760405162461bcd60e51b815260206004820152600b60248201526a10b6b0bc1036b0b933b4b760a91b6044820152606401610e0d565b60408051610100810182526001600160401b038c811682528981166020830152841681830152600654875492516341976e0960e01b81526001600160a01b039384166004820152919260608401929116906341976e099060240160206040518083038186803b1580156120d657600080fd5b505afa1580156120ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210e919061562d565b6001600160401b031681526020018a6001600160401b031681526020018c6001600160a01b03168152602001426001600160501b03168152602001891515815250601d600088815260200190815260200160002060008201518160000160006101000a8154816001600160401b0302191690836001600160401b0316021790555060208201518160000160086101000a8154816001600160401b0302191690836001600160401b0316021790555060408201518160000160106101000a8154816001600160401b0302191690836001600160401b0316021790555060608201518160000160186101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060a08201518160010160086101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c08201518160020160006101000a8154816001600160501b0302191690836001600160501b0316021790555060e082015181600201600a6101000a81548160ff021916908315150217905550905050898b6001600160a01b0316877f340ad004f2cc7f2adb2ebb38a9900cbc5888c8c67aeab767e74b16dbe1c87a4a8b86600660009054906101000a90046001600160a01b03166001600160a01b03166341976e098c60000160009054906101000a90046001600160a01b03166040518263ffffffff1660e01b815260040161235691906001600160a01b0391909116815260200190565b60206040518083038186803b15801561236e57600080fd5b505afa158015612382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a6919061562d565b604080519315158452602084019290925290820152606081018e9052608081018c905260a0810189905260c00160405180910390a4505060016000555091979650505050505050565b6001546001600160a01b031633146124195760405162461bcd60e51b8152600401610e0d90615ab7565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f3df77beb5db05fcdd70a30fc8adf3f83f9501b68579455adbd100b818094039490602001611304565b60006115006114146008600a615d1e565b6001546001600160a01b031633146124a25760405162461bcd60e51b8152600401610e0d90615ab7565b620f424082111580156124b3575060015b80156124c25750620151808111155b6124cb57600080fd5b600a91909155600b55565b6000818152601d6020908152604080832081516101008101835281546001600160401b03808216808452600160401b808404831685890152600160801b8404831685880152600160c01b90930482166060850152600185015491821660808501529190046001600160a01b0390811660a08401526002909301546001600160501b03811660c0840152600160501b900460ff16151560e08301528552601b909352818420600654815493516341976e0960e01b815293831660048501529092859291909116906341976e099060240160206040518083038186803b1580156125bd57600080fd5b505afa1580156125d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f5919061562d565b60018301549091506114d79084908390600160901b900461ffff16614a48565b6001546001600160a01b0316331461263f5760405162461bcd60e51b8152600401610e0d90615ab7565b601380546001600160a01b039586166001600160a01b0319918216179091556014805494861694821694909417909355601580549285169284169290921790915560168054919093169116179055565b6001546001600160a01b031633146126b95760405162461bcd60e51b8152600401610e0d90615ab7565b6000818152601d6020526040902060018101546001600160401b031661270d5760405162461bcd60e51b815260206004820152600960248201526810b837b9b4ba34b7b760b91b6044820152606401610e0d565b60018101546001600160401b03811690600160401b90046001600160a01b0316600061275b61273e6008600a615d1e565b8554611284908690600160401b90046001600160401b0316613e33565b84546002860154919250612788916001600160401b03909116908390600160501b900460ff166000614707565b8354604080516001600160401b03600160801b840481168083526020830152918101869052600160401b83048216606082015260006080820181905260a0820181905260c08201529116906001600160a01b0384169087907f36b11e691447eee9c5d7286d5c0db51ec49fde6c88b2e4931328a15b554312be9060e00160405180910390a46000858152601d602052604081209081556001810180546001600160e01b031916905560020180546affffffffffffffffffffff19169055612866826117366128586008600a615d1e565b600554611284908890613e33565b5050505050565b6128778133611773565b50565b6001546001600160a01b031633146128a45760405162461bcd60e51b8152600401610e0d90615ab7565b600082116128e15760405162461bcd60e51b815260206004820152600a602482015269085c1c9bd91d58dd125960b21b6044820152606401610e0d565b6000828152601b602090815260409182902082516101808101845281546001600160a01b0381168252600160a01b8082046001600160481b0316948301859052600160e81b820461ffff90811696840196909652600160f81b90910460ff161515606083015260018301546001600160401b038082166080850152600160401b8204811660a0850152600160801b8204871660c0850152600160901b8204871660e08501529181048616610100840152600160b01b81048616610120840152600160c01b9004909416610140820152600290910154909216610160830152156129fe5760405162461bcd60e51b815260206004820152600f60248201526e2170726f647563742d65786973747360881b6044820152606401610e0d565b612a0a6008600a615d1e565b612a15906001615e4b565b82602001516001600160481b031611612a405760405162461bcd60e51b8152600401610e0d90615a59565b81516001600160a01b0316612a7f5760405162461bcd60e51b8152602060048201526005602482015264085999595960da1b6044820152606401610e0d565b60008260e0015161ffff1611612acf5760405162461bcd60e51b8152602060048201526015602482015274085b1a5c5d5a59185d1a5bdb951a1c995cda1bdb19605a1b6044820152606401610e0d565b60405180610180016040528083600001516001600160a01b0316815260200183602001516001600160481b03168152602001836040015161ffff16815260200160011515815260200160006001600160401b0316815260200160006001600160401b031681526020018360c0015161ffff1681526020018360e0015161ffff16815260200183610100015161ffff16815260200183610120015161ffff16815260200183610140015161ffff1681526020018361016001516001600160401b0316815250601b600085815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a8154816001600160481b0302191690836001600160481b03160217905550604082015181600001601d6101000a81548161ffff021916908361ffff160217905550606082015181600001601f6101000a81548160ff02191690831515021790555060808201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060a08201518160010160086101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160010160106101000a81548161ffff021916908361ffff16021790555060e08201518160010160126101000a81548161ffff021916908361ffff1602179055506101008201518160010160146101000a81548161ffff021916908361ffff1602179055506101208201518160010160166101000a81548161ffff021916908361ffff1602179055506101408201518160010160186101000a81548161ffff021916908361ffff1602179055506101608201518160020160006101000a8154816001600160401b0302191690836001600160401b0316021790555090505081610140015161ffff16600d6000828254612d9b9190615c34565b90915550506000838152601b60205260409081902090517fe1bc4dae2db817ece6daf52cd2b267924bd2427a16d157ada9d40383ce6a16e8916110d991869190615be8565b612de86152e8565b601d6000612df7868686613800565b8152602080820192909252604090810160002081516101008101835281546001600160401b038082168352600160401b808304821696840196909652600160801b8204811694830194909452600160c01b90048316606082015260018201549283166080820152929091046001600160a01b031660a0830152600201546001600160501b03811660c0830152600160501b900460ff16151560e0820152949350505050565b60026000541415612ebf5760405162461bcd60e51b8152600401610e0d90615a80565b6002600055600754811015612ee65760405162461bcd60e51b8152600401610e0d90615a38565b6000828152601d602052604090206001810154600160401b90046001600160a01b03163314612f275760405162461bcd60e51b8152600401610e0d90615ab7565b80546001600160401b039081166000908152601b6020526040812060018401549092168410612f6357506001808301546001600160401b031693505b600d54600e546001840154601954600093612fa8936127109361128493849291611dc291600160601b90046001600160601b031690600160c01b900461ffff16613e33565b835460028681015460018701549187015493945060009361302b936001600160a01b031692600160501b90920460ff1615916001600160401b0380821692600160401b9092048116918891166130006008600a615d1e565b8c5461301c90600160401b90046001600160401b03168f615e4b565b6130269190615cc7565b61455c565b604080516101008101825287546001600160401b038082168352600160401b80830482166020850152600160801b8304821694840194909452600160c01b9091048116606083015260018901549081166080830152919091046001600160a01b031660a082015260028701546001600160501b03811660c0830152600160501b900460ff16151560e082015290915060009081906130ca908985614b4b565b9050600081128015613109575060018601546130fa9061271090611284908b90600160901b900461ffff16613e33565b61310682600019615dc6565b10155b156131355760018701546001600160401b0316975061312a88600019615dc6565b905060019150613261565b6000811380156132585750604080516101008101825288546001600160401b038082168352600160401b80830482166020850152600160801b8304821684860152600160c01b9092048116606084015260018b01549081166080840152046001600160a01b0390811660a083015260028a01546001600160501b03811660c0840152600160501b900460ff16151560e0830152600654895493516341976e0960e01b81529382166004850152613256939116906341976e099060240160206040518083038186803b15801561320957600080fd5b505afa15801561321d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613241919061562d565b6001890154600160b01b900461ffff16614c6a565b155b15613261575060005b604080516101008101825288546001600160401b038082168352600160401b80830482166020850152600160801b808404831695850195909552600160c01b909204811660608401526001808c015491821660808501529190046001600160a01b031660a083015260028a01546001600160501b03811660c0840152600160501b900460ff16151560e083015288549089015460009361331993869390928e92600160e81b90920461ffff9081169290910416614d1a565b885490915061336d906001600160401b031661335761333a6008600a615d1e565b8b54611284908e90600160401b90046001600160401b0316613e33565b60028b0154600160501b900460ff166000614707565b87546001890154604080518781526001600160401b03600160801b8504811660208301529181018d9052600160401b808504831660608301526080820186905260a0820187905287151560c0830152919093169291046001600160a01b0316908c907f36b11e691447eee9c5d7286d5c0db51ec49fde6c88b2e4931328a15b554312be9060e00160405180910390a4851561343f5760008a8152601d602052604081209081556001810180546001600160e01b031916905560020180546affffffffffffffffffffff19169055613484565b6001880180548a919060009061345f9084906001600160401b0316615ec0565b92506101000a8154816001600160401b0302191690836001600160401b031602179055505b505060016000555050505050505050565b6001546001600160a01b031633146134bf5760405162461bcd60e51b8152600401610e0d90615ab7565b80516001600160601b03166134ff5760405162461bcd60e51b8152600401610e0d906020808252600490820152630216361760e41b604082015260600190565b6000816080015163ffffffff16118015613525575062278d00816080015163ffffffff16105b6135625760405162461bcd60e51b815260206004820152600e60248201526d085cdd185ada5b99d4195c9a5bd960921b6044820152606401610e0d565b8051601980546001600160601b0319166001600160601b0392831690811791829055608080850151601a805463ffffffff60401b198116600160401b63ffffffff948516029081179283905560408051968752606088811c909916602088015260c09790971c868801526001600160401b03908116911617958401959095529390921c909216908201527fe065d479bcd6a90bffb826e7a706adf8190a71be3596fc227088af379a93510b9060a001611304565b600260005414156136395760405162461bcd60e51b8152600401610e0d90615a80565b600260005561365e6118bd6136506008600a615d1e565b600554611284908590613e33565b6007548110156136805760405162461bcd60e51b8152600401610e0d90615a38565b6000828152601d602052604090206001810154600160401b90046001600160a01b031633146136c15760405162461bcd60e51b8152600401610e0d90615ab7565b60018101546000906136dc906001600160401b03168461444d565b6001830154835491925060009161370c918491611284916001600160401b03600160401b90920482169116613e33565b905061371a6008600a615d1e565b613725906001615e4b565b8110156137645760405162461bcd60e51b815260206004820152600d60248201526c216c6f772d6c6576657261676560981b6044820152606401610e0d565b60018301805467ffffffffffffffff19166001600160401b038481169190911791829055845467ffffffffffffffff60401b1916600160401b9184168202178555604080518781526020810186905290810184905291046001600160a01b03169086907f8bd26f20a052ff42ee3d1f3e02f0d7c447371c96dfc7d3a14b6fa5c89df272179060600160405180910390a350506001600055505050565b6040516001600160601b0319606085901b1660208201526034810183905281151560f81b60548201526000906055016040516020818303038152906040528051906020012060001c90505b9392505050565b601a546001600160401b03168111156138975760405162461bcd60e51b8152602060048201526007602482015266085cdd185ad95960ca1b6044820152606401610e0d565b60155460405163632447c960e01b81523360048201819052916001600160a01b03169063632447c990602401600060405180830381600087803b1580156138dd57600080fd5b505af11580156138f1573d6000803e3d6000fd5b505060165460405163632447c960e01b81526001600160a01b038581166004830152909116925063632447c99150602401600060405180830381600087803b15801561393c57600080fd5b505af1158015613950573d6000803e3d6000fd5b505050506001600160a01b0381166000908152601c6020526040902060018101546001600160401b031683108015906139945760018201546001600160401b031693505b6001546001600160a01b03848116911614613a1a5760018201546000906139cd90429063ffffffff600160401b909104811690614fab16565b601a54909150600160401b900463ffffffff168111613a185760405162461bcd60e51b8152602060048201526007602482015266085c195c9a5bd960ca1b6044820152606401610e0d565b505b601a54601954600091613a4e916001600160401b0390911690611284908890600160601b90046001600160601b0316613e33565b60018401548454919250600091613a7e916001600160401b0390811691611284918a91600160a01b900416613e33565b845490915081908590601490613aa5908490600160a01b90046001600160401b0316615ec0565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550858460010160008282829054906101000a90046001600160401b0316613aef9190615ec0565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555080601960000160188282829054906101000a90046001600160401b0316613b3a9190615ec0565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555085601960010160008282829054906101000a90046001600160401b0316613b859190615ec0565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550816019600001600c8282829054906101000a90046001600160601b0316613bd09190615ee8565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550613c30612710611284600f546019600001600c9054906101000a90046001600160601b03166001600160601b0316613e3390919063ffffffff16565b6017541115613c6d5760405162461bcd60e51b8152602060048201526009602482015268085d5d1a5b1a5e995960ba1b6044820152606401610e0d565b8215613cab576001600160a01b0385166000908152601c6020526040902080546001600160e01b031916815560010180546001600160601b03191690555b613ccc85611736613cbe6008600a615d1e565b600554611284908790613e33565b604080518281526020810188905290810183905283151560608201526001600160a01b038616907f81ff784935ffa11d6a1785237495788f94842be763045286ed403b1f2e619d189060800160405180910390a2505050505050565b613d346008600a615d1e565b81565b6001546001600160a01b03163314613d615760405162461bcd60e51b8152600401610e0d90615ab7565b6018805461ffff191692151561ff0019169290921761010091151591909102179055565b6015546000906001600160a01b03163314613db25760405162461bcd60e51b8152600401610e0d90615a12565b6000613dc36114f16008600a615d1e565b601254909150156113d1576000601255601554600354613df0916001600160a01b03918216911683613e4b565b601554604080516001600160a01b039092168252602082018390527f19ffdf6391d49bb1730b3f4d19c279b1275dddf2a4e981af93b1099c111369e691016113c8565b600061384b8284615e4b565b600061384b8284615cc7565b8015611749576001600160a01b038316613efa576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613eac576040519150601f19603f3d011682016040523d82523d6000602084013e613eb1565b606091505b5050905080613ef45760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610e0d565b50505050565b6117496001600160a01b0384168383614fb7565b6000818152601d6020526040812080546001600160401b0316613f345750600092915050565b80546001600160401b03166000908152601b6020526040808220600654815492516341976e0960e01b81526001600160a01b03938416600482015291939216906341976e099060240160206040518083038186803b158015613f9557600080fd5b505afa158015613fa9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fcd919061562d565b604080516101008101825285546001600160401b038082168352600160401b80830482166020850152600160801b8304821694840194909452600160c01b9091048116606083015260018088015491821660808401529290046001600160a01b031660a082015260028601546001600160501b03811660c0830152600160501b900460ff16151560e08201529084015491925060009161407a91908490600160901b900461ffff16614a48565b1561444457604080516101008101825285546001600160401b038082168352600160401b80830482166020850152600160801b8304821694840194909452600160c01b909104811660608301526001870154908116608083018190529290046001600160a01b031660a082015260028601546001600160501b03811660c0830152600160501b900460ff16151560e082015260009161411a919085614b4b565b9050600081128015614143575061413381600019615dc6565b60018601546001600160401b0316115b1561427b57600061415682600019615dc6565b6001868101549088015491925061418f916127109161128491600160a01b90910461ffff1690611dc2906001600160401b031686614fab565b60018701549097506141b69088906141b0906001600160401b031684614fab565b90614fab565b92506141d6611de661271061128460085487613e3390919063ffffffff16565b6010556009546141f390611e0c9061271090611284908790613e33565b601181905550614229611e4b6127106112846009546008546127106142189190615ea9565b6142229190615ea9565b8790613e33565b60125560198054829190600c90614251908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550506142d3565b6001850154601980546001600160401b0390921691600c906142ae908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b60006143096142e46008600a615d1e565b87546001890154611284916001600160401b0391821691600160401b90910416613e33565b86546002880154919250614336916001600160401b03909116908390600160501b900460ff166000614707565b8554600180880154604080518881526001600160401b03600160801b860481166020830152808416928201839052600160401b808704821660608401526000608084015260a083019390935260c082019490945292909316926001600160a01b03910416908a907f36b11e691447eee9c5d7286d5c0db51ec49fde6c88b2e4931328a15b554312be9060e00160405180910390a46000888152601d602090815260408083209283556001830180546001600160e01b0319169055600290920180546affffffffffffffffffffff19169055815189815290810185905233918a917f6f7734c2b603545392ede46279193d0b944bffb5d4c822bb78cd37eb6c2aadc9910160405180910390a350505b50505050919050565b600061384b8284615c34565b8015614516576001600160a01b03821661451a57803410156144bd5760405162461bcd60e51b815260206004820152601a60248201527f556e6945524332303a206e6f7420656e6f7567682076616c75650000000000006044820152606401610e0d565b803411156145165760006144d13483614fab565b604051909150600090339083908381818185875af1925050503d8060008114613eac576040519150601f19603f3d011682016040523d82523d6000602084013e613eb1565b5050565b6145166001600160a01b03831633308461501a565b600061455461271061128484611dc261454a6008600a615d1e565b6112848a8a613e33565b949350505050565b6006546040516341976e0960e01b81526001600160a01b03898116600483015260009283929116906341976e099060240160206040518083038186803b1580156145a557600080fd5b505afa1580156145b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145dd919061562d565b9050600085600a54888a6145f19190615e6a565b6145fb9190615dc6565b6146059190615c99565b9050881561469757600061463d856112846146226008600a615d1e565b611dc28a6141b0614633828d614fab565b6112848e80613e33565b905060008212156146685761466361465c600261128485600019615dc6565b8290614fab565b614672565b614672818361444d565b905061468d6146836008600a615d1e565b6112848584613e33565b93505050506146fc565b60006146cd856112846146ac6008600a615d1e565b611dc26146c66146bc8c8c61444d565b6112848d80613e33565b8b90614fab565b905060008212156146e75761466361465c83600019615dc6565b6146726146f5836002613e3f565b829061444d565b979650505050505050565b6000848152601b60205260409020811561496157601754614728908561444d565b601755600f54601954614754916127109161128491600160601b9091046001600160601b031690613e33565b60175411156147985760405162461bcd60e51b815260206004820152601060248201526f085b585e13dc195b925b9d195c995cdd60821b6044820152606401610e0d565b600d54600e5460018301546019546000936147dd936127109361128493849291611dc291600160601b90046001600160601b031690600160c01b900461ffff16613e33565b905083156148ae576001820180548691906000906148059084906001600160401b0316615c4c565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555061485c8260010160089054906101000a90046001600160401b03166001600160401b03168261444d90919063ffffffff16565b60018301546001600160401b031611156148a95760405162461bcd60e51b815260206004820152600e60248201526d216578706f737572652d6c6f6e6760901b6044820152606401610e0d565b61495b565b848260010160088282829054906101000a90046001600160401b03166148d49190615c4c565b82546101009290920a6001600160401b038181021990931691831602179091556001840154614906925083911661444d565b6001830154600160401b90046001600160401b0316111561495b5760405162461bcd60e51b815260206004820152600f60248201526e08595e1c1bdcdd5c994b5cda1bdc9d608a1b6044820152606401610e0d565b50612866565b60175461496e9085614fab565b60175582156149ec5760018101546001600160401b031684116149d4576001810180548591906000906149ab9084906001600160401b0316615ec0565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550612866565b60018101805467ffffffffffffffff19169055612866565b6001810154600160401b90046001600160401b03168411614a2d57838160010160088282829054906101000a90046001600160401b03166149ab9190615ec0565b600101805467ffffffffffffffff60401b1916905550505050565b6000808460e0015115614ab15784602001516001600160401b03168386604001516001600160401b0316614a7c9190615e4b565b614a8890612710615e4b565b614a929190615cc7565b85604001516001600160401b0316614aaa9190615ea9565b9050614b09565b84602001516001600160401b03168386604001516001600160401b0316614ad89190615e4b565b614ae490612710615e4b565b614aee9190615cc7565b85604001516001600160401b0316614b069190615c34565b90505b8460e001518015614b1a5750808411155b80614b3257508460e00151158015614b325750808410155b15614b4157600191505061384b565b600091505061384b565b60008060008560e0015115614bf15785604001516001600160401b03168410614bba57614bb3614b7d6008600a615d1e565b6040880151611284906001600160401b031681614b9a8983614fab565b60208c0151611dc2908c906001600160401b0316613e33565b9050614c44565b614be6614bc96008600a615d1e565b6040880151611284906001600160401b031681614b9a828a614fab565b905060019150614c44565b85604001516001600160401b0316841115614c3257614be6614c156008600a615d1e565b6040880151611284906001600160401b031681614b9a828a615ea9565b614c41614bc96008600a615d1e565b90505b8115614c5d57614c5681600019615dc6565b9250614c61565b8092505b50509392505050565b6000614c8e600b548560c001516001600160501b031661444d90919063ffffffff16565b421115614c9d5750600161384b565b8360e001518015614cd35750614cd0612710611284614cbc828661444d565b60608801516001600160401b031690613e33565b83115b15614ce05750600161384b565b8360e00151158015614d035750614d00612710611284614cbc8286614fab565b83105b15614d105750600161384b565b5060009392505050565b6000806000614d2c8888888888615052565b915091506000821215614e22576000614d4783600019615dc6565b905086811015614dc85760a0880151614d7a90611736614d696008600a615d1e565b60055461128490611dc28d88614fab565b60198054829190600c90614d9f908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550614e1c565b60198054889190600c90614ded908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b031602179055508193505050506114d7565b50614ef1565b6019548290600160601b90046001600160601b0316811115614e7c5760405162461bcd60e51b8152602060048201526013602482015272085d985d5b1d0b5a5b9cdd59999a58da595b9d606a1b6044820152606401610e0d565b60198054829190600c90614ea1908490600160601b90046001600160601b0316615ee8565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550614eef8860a001516117366008600a614ede9190615d1e565b60055461128490611dc28d8861444d565b505b614f0f611de661271061128460085485613e3390919063ffffffff16565b601055600954614f2c90611e0c9061271090611284908590613e33565b601181905550614f51611e4b612710611284600954600854612710611e3a9190615ea9565b60125560198054829190600c90614f79908490600160601b90046001600160601b0316615ee8565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550809250505095945050505050565b600061384b8284615ea9565b6040516001600160a01b03831660248201526044810182905261174990849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526150b0565b6040516001600160a01b0380851660248301528316604482015260648101829052613ef49085906323b872dd60e01b90608401614fe3565b600080600061506f8688602001516001600160401b03168761452f565b905061507b8882615182565b9250600061508a88888761518e565b90506150968482615182565b93506150a2828261444d565b925050509550959350505050565b6000615105826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166151ed9092919063ffffffff16565b80519091501561174957808060200190518101906151239190615518565b6117495760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e0d565b600061384b8284615e6a565b60006145546151a664e8d4a510006301e13380613e33565b6112846151c98760c001516001600160501b031642614fab90919063ffffffff16565b611dc286611dc28a602001516001600160401b03168a613e3390919063ffffffff16565b6060614554848460008585843b6152465760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e0d565b600080866001600160a01b031685876040516152629190615974565b60006040518083038185875af1925050503d806000811461529f576040519150601f19603f3d011682016040523d82523d6000602084013e6152a4565b606091505b50915091506146fc828286606083156152be57508161384b565b8251156152ce5782518084602001fd5b8160405162461bcd60e51b8152600401610e0d91906159df565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b80356001600160a01b03811681146113d157600080fd5b80356113d181615fa7565b803561ffff811681146113d157600080fd5b80356001600160401b03811681146113d157600080fd5b80356001600160481b03811681146113d157600080fd5b80356001600160601b03811681146113d157600080fd5b6000602082840312156153b757600080fd5b61384b8261532c565b600080600080608085870312156153d657600080fd5b6153df8561532c565b93506153ed6020860161532c565b92506153fb6040860161532c565b91506154096060860161532c565b905092959194509250565b60008060006060848603121561542957600080fd5b6154328461532c565b925060208401359150604084013561544981615fa7565b809150509250925092565b600080600080600060a0868803121561546c57600080fd5b6154758661532c565b94506020860135935060408601359250606086013561549381615fa7565b949793965091946080013592915050565b600080602083850312156154b757600080fd5b82356001600160401b03808211156154ce57600080fd5b818501915085601f8301126154e257600080fd5b8135818111156154f157600080fd5b8660208260051b850101111561550657600080fd5b60209290920196919550909350505050565b60006020828403121561552a57600080fd5b815161384b81615fa7565b6000806040838503121561554857600080fd5b823561555381615fa7565b9150602083013561556381615fa7565b809150509250929050565b600060a0828403121561558057600080fd5b60405160a081018181106001600160401b03821117156155b057634e487b7160e01b600052604160045260246000fd5b6040526155bc8361538e565b81526155ca6020840161538e565b60208201526155db60408401615360565b60408201526155ec60608401615360565b6060820152608083013563ffffffff8116811461560857600080fd5b60808201529392505050565b60006020828403121561562657600080fd5b5035919050565b60006020828403121561563f57600080fd5b5051919050565b6000806040838503121561565957600080fd5b823591506156696020840161532c565b90509250929050565b6000808284036101a081121561568757600080fd5b8335925061018080601f198301121561569f57600080fd5b6156a7615bfd565b91506156b56020860161532c565b82526156c360408601615377565b60208301526156d46060860161534e565b60408301526156e560808601615343565b60608301526156f660a08601615360565b608083015261570760c08601615360565b60a083015261571860e0860161534e565b60c083015261010061572b81870161534e565b60e084015261012061573e81880161534e565b82850152610140915061575282880161534e565b9084015261016061576487820161534e565b82850152615773838801615360565b9084015250929590945092505050565b6000806040838503121561579657600080fd5b50508035926020909101359150565b6000806000606084860312156157ba57600080fd5b8335925060208401359150604084013561544981615fa7565b600080600080608085870312156157e957600080fd5b8435935060208501359250604085013561580281615fa7565b9396929550929360600135925050565b6001600160401b038082511683528060208301511660208401528060408301511660408401528060608301511660608401528060808301511660808401525060018060a01b0360a08201511660a08301526001600160501b0360c08201511660c083015260e081015161174960e084018215159052565b80546001600160a01b038116835260a081901c6001600160481b0316602084015261ffff60e882901c811660408501526158ca606085018360f81c15159052565b60018301546001600160401b038082166080870152604082901c811660a08701529092505061590460c08501828460801c1661ffff169052565b61591960e08501828460901c1661ffff169052565b61592f6101008501828460a01c1661ffff169052565b6159456101208501828460b01c1661ffff169052565b61595b6101408501828460c01c1661ffff169052565b5050600201546001600160401b03166101609190910152565b60008251615986818460208701615f08565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b818110156159d3576159bf838551615812565b9284019261010092909201916001016159ac565b50909695505050505050565b60208152600082518060208401526159fe816040850160208701615f08565b601f01601f19169190910160400192915050565b6020808252600c908201526b10b234b9ba3934b13aba37b960a11b604082015260600190565b60208082526007908201526610b6b0b933b4b760c91b604082015260600190565b6020808252600d908201526c216d61782d6c6576657261676560981b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526006908201526510b7bbb732b960d11b604082015260600190565b610100810161128a8284615812565b81516001600160a01b0316815261018081016020830151615b1260208401826001600160481b03169052565b506040830151615b28604084018261ffff169052565b506060830151615b3c606084018215159052565b506080830151615b5760808401826001600160401b03169052565b5060a0830151615b7260a08401826001600160401b03169052565b5060c0830151615b8860c084018261ffff169052565b5060e0830151615b9e60e084018261ffff169052565b506101008381015161ffff90811691840191909152610120808501518216908401526101408085015190911690830152610160808401516001600160401b03811682850152611655565b8281526101a0810161384b6020830184615889565b60405161018081016001600160401b0381118282101715615c2e57634e487b7160e01b600052604160045260246000fd5b60405290565b60008219821115615c4757615c47615f4f565b500190565b60006001600160401b03808316818516808303821115615c6e57615c6e615f4f565b01949350505050565b60006001600160601b03808316818516808303821115615c6e57615c6e615f4f565b600082615ca857615ca8615f65565b600160ff1b821460001984141615615cc257615cc2615f4f565b500590565b600082615cd657615cd6615f65565b500490565b600181815b80851115615d16578160001904821115615cfc57615cfc615f4f565b80851615615d0957918102915b93841c9390800290615ce0565b509250929050565b600061384b8383600082615d345750600161128a565b81615d415750600061128a565b8160018114615d575760028114615d6157615d7d565b600191505061128a565b60ff841115615d7257615d72615f4f565b50506001821b61128a565b5060208310610133831016604e8410600b8410161715615da0575081810a61128a565b615daa8383615cdb565b8060001904821115615dbe57615dbe615f4f565b029392505050565b60006001600160ff1b0381841382841380821686840486111615615dec57615dec615f4f565b600160ff1b6000871282811687830589121615615e0b57615e0b615f4f565b60008712925087820587128484161615615e2757615e27615f4f565b87850587128184161615615e3d57615e3d615f4f565b505050929093029392505050565b6000816000190483118215151615615e6557615e65615f4f565b500290565b60008083128015600160ff1b850184121615615e8857615e88615f4f565b6001600160ff1b0384018313811615615ea357615ea3615f4f565b50500390565b600082821015615ebb57615ebb615f4f565b500390565b60006001600160401b0383811690831681811015615ee057615ee0615f4f565b039392505050565b60006001600160601b0383811690831681811015615ee057615ee0615f4f565b60005b83811015615f23578181015183820152602001615f0b565b83811115613ef45750506000910152565b6000600019821415615f4857615f48615f4f565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461287757600080fdfea2646970667358221220ca2a3eafb2b2cff0d911a5d3992ecd445edb765a2c24592c3593752f3d43459d64736f6c634300080700330000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000000000000000000000000000000000000000006000000000000000000000000250e7ab9b5ea0e95bf68f9fbe2f4f9dc5c8af74600000000000000000000000000000000000000000000000000000002540be400

Deployed Bytecode

0x6080604052600436106103b55760003560e01c806381a3daca116101f2578063b9db15b41161010d578063d65fe355116100a0578063ec342ad01161006f578063ec342ad014610d79578063f4b1559514610d8e578063fbb48bc114610dae578063fc0c546a14610dc357600080fd5b8063d65fe35514610d0d578063d9ac422514610d2d578063db006a7514610d43578063e19a60e114610d6357600080fd5b8063d32bb3e9116100dc578063d32bb3e914610ca4578063d41194b814610cc4578063d468e2a914610cd7578063d48788b914610ced57600080fd5b8063b9db15b414610ad0578063bc95baad14610c37578063bed5755414610c64578063cd84db0914610c8457600080fd5b806396c82e5711610185578063a576d8ad11610154578063a576d8ad14610a67578063a694fc3a14610a87578063b26d97e914610a9a578063b61daaee14610aba57600080fd5b806396c82e57146109eb5780639df411ee14610a01578063a0448fc514610a31578063a082cdd214610a4757600080fd5b80638d928af8116101c15780638d928af8146108945780638da5cb5b146109955780638ea8f7fc146109b5578063904a53b6146109cb57600080fd5b806381a3daca14610834578063841a4b51146108545780638b09578d1461086a5780638c10ad1b1461087f57600080fd5b80633ee19763116102e25780635f3b21801161027557806378d7fb7f1161024457806378d7fb7f146106e85780637a766460146106fb5780637adbf973146107f45780637dc0d1d01461081457600080fd5b80635f3b21801461068a57806367d3ef9a146106a05780636e20c3b4146106c057806370607f5d146106d557600080fd5b80634c723c28116102b15780634c723c28146106115780634d452ec01461063e5780635b3829891461065e5780635caed0291461067457600080fd5b80633ee197631461057c5780633f06cd66146105915780634046ebae146105af5780634b3ab9c5146105cf57600080fd5b80631ba938441161035a5780632dc9265e116103295780632dc9265e1461051d57806333af0efa1461053d57806339c294be146105535780633dc8f1441461056957600080fd5b80631ba93844146104a55780631ea8c3a7146104dd5780631fbeef4e146104f2578063228f524e1461050757600080fd5b806301c76f811161039657806301c76f81146104255780630904c2db14610445578063114379411461046557806313af40351461048557600080fd5b80620b15a3146103ba5780621b7934146103dc578062eb5b62146103fc575b600080fd5b3480156103c657600080fd5b506103da6103d5366004615672565b610de3565b005b3480156103e857600080fd5b506103da6103f7366004615783565b6110e6565b34801561040857600080fd5b5061041260125481565b6040519081526020015b60405180910390f35b34801561043157600080fd5b506103da6104403660046153a5565b61119e565b34801561045157600080fd5b506103da610460366004615614565b6111ea565b34801561047157600080fd5b506104126104803660046153a5565b611219565b34801561049157600080fd5b506103da6104a03660046153a5565b611290565b3480156104b157600080fd5b506015546104c5906001600160a01b031681565b6040516001600160a01b03909116815260200161041c565b3480156104e957600080fd5b5061041261130f565b3480156104fe57600080fd5b506104126113d6565b34801561051357600080fd5b50610412600c5481565b34801561052957600080fd5b506103da610538366004615783565b611493565b34801561054957600080fd5b5061041260115481565b34801561055f57600080fd5b5061041260075481565b6104126105773660046157d3565b6114c8565b34801561058857600080fd5b506104126114e0565b34801561059d57600080fd5b50601a546001600160401b0316610412565b3480156105bb57600080fd5b506002546104c5906001600160a01b031681565b3480156105db57600080fd5b506104126105ea3660046153a5565b6001600160a01b03166000908152601c60205260409020600101546001600160401b031690565b34801561061d57600080fd5b5061063161062c3660046154a4565b611505565b60405161041c9190615990565b34801561064a57600080fd5b506103da6106593660046154a4565b61165d565b34801561066a57600080fd5b50610412600f5481565b34801561068057600080fd5b5061041260045481565b34801561069657600080fd5b5061041260085481565b3480156106ac57600080fd5b506103da6106bb3660046157a5565b61174e565b3480156106cc57600080fd5b50610412611762565b6103da6106e3366004615646565b611773565b6104126106f6366004615454565b611c59565b34801561070757600080fd5b506107a46107163660046153a5565b604080516080810182526000808252602082018190529181018290526060810191909152506001600160a01b039081166000908152601c6020908152604091829020825160808101845281549485168152600160a01b9094046001600160401b03908116928501929092526001015490811691830191909152600160401b900463ffffffff16606082015290565b6040805182516001600160a01b031681526020808401516001600160401b039081169183019190915283830151169181019190915260609182015163ffffffff169181019190915260800161041c565b34801561080057600080fd5b506103da61080f3660046153a5565b6123ef565b34801561082057600080fd5b506006546104c5906001600160a01b031681565b34801561084057600080fd5b506014546104c5906001600160a01b031681565b34801561086057600080fd5b50610412600e5481565b34801561087657600080fd5b50610412600881565b34801561088b57600080fd5b50610412612467565b3480156108a057600080fd5b506109316040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526019546001600160601b038082168352600160601b8204166020830152600160c01b90046001600160401b0390811692820192909252601a549182166060820152600160401b90910463ffffffff16608082015290565b60405161041c9190600060a0820190506001600160601b038084511683528060208501511660208401525060408301516001600160401b038082166040850152806060860151166060850152505063ffffffff608084015116608083015292915050565b3480156109a157600080fd5b506001546104c5906001600160a01b031681565b3480156109c157600080fd5b5061041260105481565b3480156109d757600080fd5b506103da6109e6366004615783565b612478565b3480156109f757600080fd5b50610412600d5481565b348015610a0d57600080fd5b50610a21610a1c366004615614565b6124d6565b604051901515815260200161041c565b348015610a3d57600080fd5b50610412600a5481565b348015610a5357600080fd5b506103da610a623660046153c0565b612615565b348015610a7357600080fd5b506103da610a82366004615614565b61268f565b6103da610a95366004615614565b61286d565b348015610aa657600080fd5b506103da610ab5366004615672565b61287a565b348015610ac657600080fd5b5061041260055481565b348015610adc57600080fd5b50610c2a610aeb366004615614565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810191909152506000908152601b602090815260409182902082516101808101845281546001600160a01b0381168252600160a01b8082046001600160481b031694830194909452600160e81b810461ffff90811695830195909552600160f81b900460ff161515606082015260018201546001600160401b038082166080840152600160401b8204811660a0840152600160801b8204861660c0840152600160901b8204861660e08401529381048516610100830152600160b01b81048516610120830152600160c01b9004909316610140840152600201541661016082015290565b60405161041c9190615ae6565b348015610c4357600080fd5b50610c57610c52366004615414565b612de0565b60405161041c9190615ad7565b348015610c7057600080fd5b506013546104c5906001600160a01b031681565b348015610c9057600080fd5b506103da610c9f366004615783565b612e9c565b348015610cb057600080fd5b506103da610cbf36600461556e565b613495565b6103da610cd2366004615783565b613616565b348015610ce357600080fd5b5061041260175481565b348015610cf957600080fd5b506016546104c5906001600160a01b031681565b348015610d1957600080fd5b50610412610d28366004615414565b613800565b348015610d3957600080fd5b50610412600b5481565b348015610d4f57600080fd5b506103da610d5e366004615614565b613852565b348015610d6f57600080fd5b5061041260095481565b348015610d8557600080fd5b50610412613d28565b348015610d9a57600080fd5b506103da610da9366004615535565b613d37565b348015610dba57600080fd5b50610412613d85565b348015610dcf57600080fd5b506003546104c5906001600160a01b031681565b6001546001600160a01b03163314610e165760405162461bcd60e51b8152600401610e0d90615ab7565b60405180910390fd5b60008211610e535760405162461bcd60e51b815260206004820152600a602482015269085c1c9bd91d58dd125960b21b6044820152606401610e0d565b6000828152601b602052604090208054600160a01b90046001600160481b0316610eb15760405162461bcd60e51b815260206004820152600f60248201526e2170726f647563742d65786973747360881b6044820152606401610e0d565b610ebd6008600a615d1e565b610ec8906001615e4b565b82602001516001600160481b03161015610ef45760405162461bcd60e51b8152600401610e0d90615a59565b81516001600160a01b0316610f335760405162461bcd60e51b8152602060048201526005602482015264085999595960da1b6044820152606401610e0d565b60008260e0015161ffff1611610f835760405162461bcd60e51b8152602060048201526015602482015274085b1a5c5d5a59185d1a5bdb951a1c995cda1bdb19605a1b6044820152606401610e0d565b815181546020840151604085015160608601516001600160a01b039094166001600160e81b031990931692909217600160a01b6001600160481b039092168202176001600160e81b0316600160e81b61ffff938416026001600160f81b031617600160f81b9315159390930292909217835560c084015160018401805460e087015161010088015163ffffffff60801b19909216600160801b9486169490940261ffff60901b191693909317600160901b938516939093029290921761ffff60a01b19169183169093021791829055610140840151600d549082169261107292600160c01b9091041690615ea9565b61107c9190615c34565b600d5561014082015160018201805461ffff909216600160c01b0261ffff60c01b199092169190911790556040517ff67c96d097a316014b351edfed880cf93784164f445f0bbb26cde56fb89fa2fc906110d99085908490615be8565b60405180910390a1505050565b6001546001600160a01b031633146111105760405162461bcd60e51b8152600401610e0d90615ab7565b61271061111d8284615c34565b11156111575760405162461bcd60e51b8152602060048201526009602482015268042e8dede5adaeac6d60bb1b6044820152606401610e0d565b6008829055600981905560408051838152602081018390527f2cda5f90308a6ed0aad400f6ddc7575e31b5f1428c50c054ae54e1939ff164b8910160405180910390a15050565b6001546001600160a01b031633146111c85760405162461bcd60e51b8152600401610e0d90615ab7565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146112145760405162461bcd60e51b8152600401610e0d90615ab7565b600e55565b601a546000906001600160401b031661123457506000919050565b601a546019546001600160a01b0384166000908152601c602052604090206001015461128a926001600160401b039081169261128492909116906001600160601b03600160601b90910416613e33565b90613e3f565b92915050565b6001546001600160a01b031633146112ba5760405162461bcd60e51b8152600401610e0d90615ab7565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b906020015b60405180910390a150565b6014546000906001600160a01b0316331461133c5760405162461bcd60e51b8152600401610e0d90615a12565b600061135c61134d6008600a615d1e565b60055460115461128491613e33565b601154909150156113d1576000601155601454600354611389916001600160a01b03918216911683613e4b565b601454604080516001600160a01b039092168252602082018390527f304116b7df0fff49d35547e731489e0e2f288bf99c5293f5fb4697671108280d91015b60405180910390a15b919050565b6013546000906001600160a01b031633146114035760405162461bcd60e51b8152600401610e0d90615a12565b60006114236114146008600a615d1e565b60055460105461128491613e33565b601054909150156113d1576000601055601354600354611450916001600160a01b03918216911683613e4b565b601354604080516001600160a01b039092168252602082018390527ffbbb21b60e499f2366d8f9dbdb1884e047dcf008673ee2c189b6153bfacc06e891016113c8565b6001546001600160a01b031633146114bd5760405162461bcd60e51b8152600401610e0d90615ab7565b600791909155600c55565b60006114d73386868686611c59565b95945050505050565b60006115006114f16008600a615d1e565b60055460125461128491613e33565b905090565b606081806001600160401b0381111561152057611520615f91565b60405190808252806020026020018201604052801561155957816020015b6115466152e8565b81526020019060019003908161153e5790505b50915060005b8181101561165557601d600086868481811061157d5761157d615f7b565b6020908102929092013583525081810192909252604090810160002081516101008101835281546001600160401b038082168352600160401b808304821696840196909652600160801b8204811694830194909452600160c01b90048316606082015260018201549283166080820152929091046001600160a01b031660a0830152600201546001600160501b03811660c0830152600160501b900460ff16151560e0820152835184908390811061163757611637615f7b565b6020026020010181905250808061164d90615f34565b91505061155f565b505092915050565b6002546001600160a01b031633148061167d5750601854610100900460ff165b6116b75760405162461bcd60e51b815260206004820152600b60248201526a10b634b8bab4b230ba37b960a91b6044820152606401610e0d565b6000805b8281101561170e5760008484838181106116d7576116d7615f7b565b90506020020135905060006116eb82613f0e565b90506116f7848261444d565b93505050808061170690615f34565b9150506116bb565b50801561174957611749336117366117286008600a615d1e565b600554611284908690613e33565b6003546001600160a01b03169190613e4b565b505050565b61174961175c338584613800565b83612e9c565b600061150061134d6008600a615d1e565b600260005414156117965760405162461bcd60e51b8152600401610e0d90615a80565b600260005560185460ff16806117b657506001546001600160a01b031633145b6117eb5760405162461bcd60e51b8152602060048201526006602482015265217374616b6560d01b6044820152606401610e0d565b60155460405163632447c960e01b81526001600160a01b0383811660048301529091169063632447c990602401600060405180830381600087803b15801561183257600080fd5b505af1158015611846573d6000803e3d6000fd5b505060165460405163632447c960e01b81526001600160a01b038581166004830152909116925063632447c99150602401600060405180830381600087803b15801561189157600080fd5b505af11580156118a5573d6000803e3d6000fd5b505050506118cf6118bd6008600a6117289190615d1e565b6003546001600160a01b031690614459565b6019546001600160601b038116906118f8908490600160c01b90046001600160401b0316615c34565b111561192f5760405162461bcd60e51b8152600401610e0d906020808252600490820152630216361760e41b604082015260600190565b601954600090600160c01b90046001600160401b031661194f578261197e565b601954601a5461197e91600160601b90046001600160601b0316906112849086906001600160401b0316613e33565b601980549192508491600c906119a5908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555082601960000160188282829054906101000a90046001600160401b03166119f09190615c4c565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555080601960010160008282829054906101000a90046001600160401b0316611a3b9190615c4c565b82546101009290920a6001600160401b038181021990931691831602179091556001600160a01b0384166000908152601c6020526040902054600160a01b90041615159050611b2657604080516080810182526001600160a01b038085168083526001600160401b03808816602080860191825287831686880190815263ffffffff428116606089019081526000968752601c909352979094209551865492518416600160a01b026001600160e01b03199093169516949094171784559051600190930180549251909416600160401b026001600160601b0319909216921691909117179055611c0b565b6001600160a01b0382166000908152601c602052604090208054849190601490611b61908490600160a01b90046001600160401b0316615c4c565b82546101009290920a6001600160401b038181021990931691831602179091556001600160a01b0384166000908152601c6020526040812060010180548594509092611baf91859116615c4c565b82546101009290920a6001600160401b03818102199093169190921691909102179055506001600160a01b0382166000908152601c60205260409020600101805463ffffffff60401b1916600160401b4263ffffffff16021790555b60408051848152602081018390526001600160a01b038416917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90910160405180910390a25050600160005550565b600060026000541415611c7e5760405162461bcd60e51b8152600401610e0d90615a80565b6002600055600754841015611ca55760405162461bcd60e51b8152600401610e0d90615a38565b611cb16008600a615d1e565b611cbc906001615e4b565b821015611cf75760405162461bcd60e51b8152602060048201526009602482015268216c6576657261676560b81b6044820152606401610e0d565b6000858152601b602052604090208054600160f81b900460ff16611d4f5760405162461bcd60e51b815260206004820152600f60248201526e2170726f647563742d61637469766560881b6044820152606401610e0d565b8054600160a01b90046001600160481b0316831115611d805760405162461bcd60e51b8152600401610e0d90615a59565b8054600090611d9d9087908690600160e81b900461ffff1661452f565b9050611dc86118bd611db16008600a615d1e565b60055461128490611dc28b8761444d565b90613e33565b611def611de661271061128460085485613e3390919063ffffffff16565b6010549061444d565b601055600954611e1590611e0c9061271090611284908590613e33565b6011549061444d565b601181905550611e54611e4b612710611284600954600854612710611e3a9190615ea9565b611e449190615ea9565b8590613e33565b6012549061444d565b6012556000611e72611e686008600a615d1e565b6112848988613e33565b83546001850154600d54600e54601954949550600094611ef8946001600160a01b0316938c936001600160401b0380831694600160401b840490911693611ee493612710936112849390928492611dc291600160601b90046001600160601b031690600160c01b900461ffff16613e33565b60028a01546001600160401b03168861455c565b9050611f078983896001614707565b611f128a8a89613800565b6000818152601d602052604090206001810154919650906001600160401b03161561202557611fb6611f72611f478b8a613e33565b83546001850154611f6c916001600160401b0391821691600160401b90910416613e33565b9061444d565b611284611f8385611dc28e8d613e33565b84546001860154611f6c916001600160401b03600160801b8204811692611dc29290821691600160401b90910416613e33565b600182015490925061200790611fd5906001600160401b03168b61444d565b611284611fe28c8b613e33565b84546001860154611f6c916001600160401b0391821691600160401b90910416613e33565b6001820154909750612022906001600160401b03168a61444d565b98505b600c5489106120645760405162461bcd60e51b815260206004820152600b60248201526a10b6b0bc1036b0b933b4b760a91b6044820152606401610e0d565b60408051610100810182526001600160401b038c811682528981166020830152841681830152600654875492516341976e0960e01b81526001600160a01b039384166004820152919260608401929116906341976e099060240160206040518083038186803b1580156120d657600080fd5b505afa1580156120ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210e919061562d565b6001600160401b031681526020018a6001600160401b031681526020018c6001600160a01b03168152602001426001600160501b03168152602001891515815250601d600088815260200190815260200160002060008201518160000160006101000a8154816001600160401b0302191690836001600160401b0316021790555060208201518160000160086101000a8154816001600160401b0302191690836001600160401b0316021790555060408201518160000160106101000a8154816001600160401b0302191690836001600160401b0316021790555060608201518160000160186101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060a08201518160010160086101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c08201518160020160006101000a8154816001600160501b0302191690836001600160501b0316021790555060e082015181600201600a6101000a81548160ff021916908315150217905550905050898b6001600160a01b0316877f340ad004f2cc7f2adb2ebb38a9900cbc5888c8c67aeab767e74b16dbe1c87a4a8b86600660009054906101000a90046001600160a01b03166001600160a01b03166341976e098c60000160009054906101000a90046001600160a01b03166040518263ffffffff1660e01b815260040161235691906001600160a01b0391909116815260200190565b60206040518083038186803b15801561236e57600080fd5b505afa158015612382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a6919061562d565b604080519315158452602084019290925290820152606081018e9052608081018c905260a0810189905260c00160405180910390a4505060016000555091979650505050505050565b6001546001600160a01b031633146124195760405162461bcd60e51b8152600401610e0d90615ab7565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f3df77beb5db05fcdd70a30fc8adf3f83f9501b68579455adbd100b818094039490602001611304565b60006115006114146008600a615d1e565b6001546001600160a01b031633146124a25760405162461bcd60e51b8152600401610e0d90615ab7565b620f424082111580156124b3575060015b80156124c25750620151808111155b6124cb57600080fd5b600a91909155600b55565b6000818152601d6020908152604080832081516101008101835281546001600160401b03808216808452600160401b808404831685890152600160801b8404831685880152600160c01b90930482166060850152600185015491821660808501529190046001600160a01b0390811660a08401526002909301546001600160501b03811660c0840152600160501b900460ff16151560e08301528552601b909352818420600654815493516341976e0960e01b815293831660048501529092859291909116906341976e099060240160206040518083038186803b1580156125bd57600080fd5b505afa1580156125d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f5919061562d565b60018301549091506114d79084908390600160901b900461ffff16614a48565b6001546001600160a01b0316331461263f5760405162461bcd60e51b8152600401610e0d90615ab7565b601380546001600160a01b039586166001600160a01b0319918216179091556014805494861694821694909417909355601580549285169284169290921790915560168054919093169116179055565b6001546001600160a01b031633146126b95760405162461bcd60e51b8152600401610e0d90615ab7565b6000818152601d6020526040902060018101546001600160401b031661270d5760405162461bcd60e51b815260206004820152600960248201526810b837b9b4ba34b7b760b91b6044820152606401610e0d565b60018101546001600160401b03811690600160401b90046001600160a01b0316600061275b61273e6008600a615d1e565b8554611284908690600160401b90046001600160401b0316613e33565b84546002860154919250612788916001600160401b03909116908390600160501b900460ff166000614707565b8354604080516001600160401b03600160801b840481168083526020830152918101869052600160401b83048216606082015260006080820181905260a0820181905260c08201529116906001600160a01b0384169087907f36b11e691447eee9c5d7286d5c0db51ec49fde6c88b2e4931328a15b554312be9060e00160405180910390a46000858152601d602052604081209081556001810180546001600160e01b031916905560020180546affffffffffffffffffffff19169055612866826117366128586008600a615d1e565b600554611284908890613e33565b5050505050565b6128778133611773565b50565b6001546001600160a01b031633146128a45760405162461bcd60e51b8152600401610e0d90615ab7565b600082116128e15760405162461bcd60e51b815260206004820152600a602482015269085c1c9bd91d58dd125960b21b6044820152606401610e0d565b6000828152601b602090815260409182902082516101808101845281546001600160a01b0381168252600160a01b8082046001600160481b0316948301859052600160e81b820461ffff90811696840196909652600160f81b90910460ff161515606083015260018301546001600160401b038082166080850152600160401b8204811660a0850152600160801b8204871660c0850152600160901b8204871660e08501529181048616610100840152600160b01b81048616610120840152600160c01b9004909416610140820152600290910154909216610160830152156129fe5760405162461bcd60e51b815260206004820152600f60248201526e2170726f647563742d65786973747360881b6044820152606401610e0d565b612a0a6008600a615d1e565b612a15906001615e4b565b82602001516001600160481b031611612a405760405162461bcd60e51b8152600401610e0d90615a59565b81516001600160a01b0316612a7f5760405162461bcd60e51b8152602060048201526005602482015264085999595960da1b6044820152606401610e0d565b60008260e0015161ffff1611612acf5760405162461bcd60e51b8152602060048201526015602482015274085b1a5c5d5a59185d1a5bdb951a1c995cda1bdb19605a1b6044820152606401610e0d565b60405180610180016040528083600001516001600160a01b0316815260200183602001516001600160481b03168152602001836040015161ffff16815260200160011515815260200160006001600160401b0316815260200160006001600160401b031681526020018360c0015161ffff1681526020018360e0015161ffff16815260200183610100015161ffff16815260200183610120015161ffff16815260200183610140015161ffff1681526020018361016001516001600160401b0316815250601b600085815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a8154816001600160481b0302191690836001600160481b03160217905550604082015181600001601d6101000a81548161ffff021916908361ffff160217905550606082015181600001601f6101000a81548160ff02191690831515021790555060808201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060a08201518160010160086101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160010160106101000a81548161ffff021916908361ffff16021790555060e08201518160010160126101000a81548161ffff021916908361ffff1602179055506101008201518160010160146101000a81548161ffff021916908361ffff1602179055506101208201518160010160166101000a81548161ffff021916908361ffff1602179055506101408201518160010160186101000a81548161ffff021916908361ffff1602179055506101608201518160020160006101000a8154816001600160401b0302191690836001600160401b0316021790555090505081610140015161ffff16600d6000828254612d9b9190615c34565b90915550506000838152601b60205260409081902090517fe1bc4dae2db817ece6daf52cd2b267924bd2427a16d157ada9d40383ce6a16e8916110d991869190615be8565b612de86152e8565b601d6000612df7868686613800565b8152602080820192909252604090810160002081516101008101835281546001600160401b038082168352600160401b808304821696840196909652600160801b8204811694830194909452600160c01b90048316606082015260018201549283166080820152929091046001600160a01b031660a0830152600201546001600160501b03811660c0830152600160501b900460ff16151560e0820152949350505050565b60026000541415612ebf5760405162461bcd60e51b8152600401610e0d90615a80565b6002600055600754811015612ee65760405162461bcd60e51b8152600401610e0d90615a38565b6000828152601d602052604090206001810154600160401b90046001600160a01b03163314612f275760405162461bcd60e51b8152600401610e0d90615ab7565b80546001600160401b039081166000908152601b6020526040812060018401549092168410612f6357506001808301546001600160401b031693505b600d54600e546001840154601954600093612fa8936127109361128493849291611dc291600160601b90046001600160601b031690600160c01b900461ffff16613e33565b835460028681015460018701549187015493945060009361302b936001600160a01b031692600160501b90920460ff1615916001600160401b0380821692600160401b9092048116918891166130006008600a615d1e565b8c5461301c90600160401b90046001600160401b03168f615e4b565b6130269190615cc7565b61455c565b604080516101008101825287546001600160401b038082168352600160401b80830482166020850152600160801b8304821694840194909452600160c01b9091048116606083015260018901549081166080830152919091046001600160a01b031660a082015260028701546001600160501b03811660c0830152600160501b900460ff16151560e082015290915060009081906130ca908985614b4b565b9050600081128015613109575060018601546130fa9061271090611284908b90600160901b900461ffff16613e33565b61310682600019615dc6565b10155b156131355760018701546001600160401b0316975061312a88600019615dc6565b905060019150613261565b6000811380156132585750604080516101008101825288546001600160401b038082168352600160401b80830482166020850152600160801b8304821684860152600160c01b9092048116606084015260018b01549081166080840152046001600160a01b0390811660a083015260028a01546001600160501b03811660c0840152600160501b900460ff16151560e0830152600654895493516341976e0960e01b81529382166004850152613256939116906341976e099060240160206040518083038186803b15801561320957600080fd5b505afa15801561321d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613241919061562d565b6001890154600160b01b900461ffff16614c6a565b155b15613261575060005b604080516101008101825288546001600160401b038082168352600160401b80830482166020850152600160801b808404831695850195909552600160c01b909204811660608401526001808c015491821660808501529190046001600160a01b031660a083015260028a01546001600160501b03811660c0840152600160501b900460ff16151560e083015288549089015460009361331993869390928e92600160e81b90920461ffff9081169290910416614d1a565b885490915061336d906001600160401b031661335761333a6008600a615d1e565b8b54611284908e90600160401b90046001600160401b0316613e33565b60028b0154600160501b900460ff166000614707565b87546001890154604080518781526001600160401b03600160801b8504811660208301529181018d9052600160401b808504831660608301526080820186905260a0820187905287151560c0830152919093169291046001600160a01b0316908c907f36b11e691447eee9c5d7286d5c0db51ec49fde6c88b2e4931328a15b554312be9060e00160405180910390a4851561343f5760008a8152601d602052604081209081556001810180546001600160e01b031916905560020180546affffffffffffffffffffff19169055613484565b6001880180548a919060009061345f9084906001600160401b0316615ec0565b92506101000a8154816001600160401b0302191690836001600160401b031602179055505b505060016000555050505050505050565b6001546001600160a01b031633146134bf5760405162461bcd60e51b8152600401610e0d90615ab7565b80516001600160601b03166134ff5760405162461bcd60e51b8152600401610e0d906020808252600490820152630216361760e41b604082015260600190565b6000816080015163ffffffff16118015613525575062278d00816080015163ffffffff16105b6135625760405162461bcd60e51b815260206004820152600e60248201526d085cdd185ada5b99d4195c9a5bd960921b6044820152606401610e0d565b8051601980546001600160601b0319166001600160601b0392831690811791829055608080850151601a805463ffffffff60401b198116600160401b63ffffffff948516029081179283905560408051968752606088811c909916602088015260c09790971c868801526001600160401b03908116911617958401959095529390921c909216908201527fe065d479bcd6a90bffb826e7a706adf8190a71be3596fc227088af379a93510b9060a001611304565b600260005414156136395760405162461bcd60e51b8152600401610e0d90615a80565b600260005561365e6118bd6136506008600a615d1e565b600554611284908590613e33565b6007548110156136805760405162461bcd60e51b8152600401610e0d90615a38565b6000828152601d602052604090206001810154600160401b90046001600160a01b031633146136c15760405162461bcd60e51b8152600401610e0d90615ab7565b60018101546000906136dc906001600160401b03168461444d565b6001830154835491925060009161370c918491611284916001600160401b03600160401b90920482169116613e33565b905061371a6008600a615d1e565b613725906001615e4b565b8110156137645760405162461bcd60e51b815260206004820152600d60248201526c216c6f772d6c6576657261676560981b6044820152606401610e0d565b60018301805467ffffffffffffffff19166001600160401b038481169190911791829055845467ffffffffffffffff60401b1916600160401b9184168202178555604080518781526020810186905290810184905291046001600160a01b03169086907f8bd26f20a052ff42ee3d1f3e02f0d7c447371c96dfc7d3a14b6fa5c89df272179060600160405180910390a350506001600055505050565b6040516001600160601b0319606085901b1660208201526034810183905281151560f81b60548201526000906055016040516020818303038152906040528051906020012060001c90505b9392505050565b601a546001600160401b03168111156138975760405162461bcd60e51b8152602060048201526007602482015266085cdd185ad95960ca1b6044820152606401610e0d565b60155460405163632447c960e01b81523360048201819052916001600160a01b03169063632447c990602401600060405180830381600087803b1580156138dd57600080fd5b505af11580156138f1573d6000803e3d6000fd5b505060165460405163632447c960e01b81526001600160a01b038581166004830152909116925063632447c99150602401600060405180830381600087803b15801561393c57600080fd5b505af1158015613950573d6000803e3d6000fd5b505050506001600160a01b0381166000908152601c6020526040902060018101546001600160401b031683108015906139945760018201546001600160401b031693505b6001546001600160a01b03848116911614613a1a5760018201546000906139cd90429063ffffffff600160401b909104811690614fab16565b601a54909150600160401b900463ffffffff168111613a185760405162461bcd60e51b8152602060048201526007602482015266085c195c9a5bd960ca1b6044820152606401610e0d565b505b601a54601954600091613a4e916001600160401b0390911690611284908890600160601b90046001600160601b0316613e33565b60018401548454919250600091613a7e916001600160401b0390811691611284918a91600160a01b900416613e33565b845490915081908590601490613aa5908490600160a01b90046001600160401b0316615ec0565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550858460010160008282829054906101000a90046001600160401b0316613aef9190615ec0565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555080601960000160188282829054906101000a90046001600160401b0316613b3a9190615ec0565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555085601960010160008282829054906101000a90046001600160401b0316613b859190615ec0565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550816019600001600c8282829054906101000a90046001600160601b0316613bd09190615ee8565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550613c30612710611284600f546019600001600c9054906101000a90046001600160601b03166001600160601b0316613e3390919063ffffffff16565b6017541115613c6d5760405162461bcd60e51b8152602060048201526009602482015268085d5d1a5b1a5e995960ba1b6044820152606401610e0d565b8215613cab576001600160a01b0385166000908152601c6020526040902080546001600160e01b031916815560010180546001600160601b03191690555b613ccc85611736613cbe6008600a615d1e565b600554611284908790613e33565b604080518281526020810188905290810183905283151560608201526001600160a01b038616907f81ff784935ffa11d6a1785237495788f94842be763045286ed403b1f2e619d189060800160405180910390a2505050505050565b613d346008600a615d1e565b81565b6001546001600160a01b03163314613d615760405162461bcd60e51b8152600401610e0d90615ab7565b6018805461ffff191692151561ff0019169290921761010091151591909102179055565b6015546000906001600160a01b03163314613db25760405162461bcd60e51b8152600401610e0d90615a12565b6000613dc36114f16008600a615d1e565b601254909150156113d1576000601255601554600354613df0916001600160a01b03918216911683613e4b565b601554604080516001600160a01b039092168252602082018390527f19ffdf6391d49bb1730b3f4d19c279b1275dddf2a4e981af93b1099c111369e691016113c8565b600061384b8284615e4b565b600061384b8284615cc7565b8015611749576001600160a01b038316613efa576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613eac576040519150601f19603f3d011682016040523d82523d6000602084013e613eb1565b606091505b5050905080613ef45760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610e0d565b50505050565b6117496001600160a01b0384168383614fb7565b6000818152601d6020526040812080546001600160401b0316613f345750600092915050565b80546001600160401b03166000908152601b6020526040808220600654815492516341976e0960e01b81526001600160a01b03938416600482015291939216906341976e099060240160206040518083038186803b158015613f9557600080fd5b505afa158015613fa9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fcd919061562d565b604080516101008101825285546001600160401b038082168352600160401b80830482166020850152600160801b8304821694840194909452600160c01b9091048116606083015260018088015491821660808401529290046001600160a01b031660a082015260028601546001600160501b03811660c0830152600160501b900460ff16151560e08201529084015491925060009161407a91908490600160901b900461ffff16614a48565b1561444457604080516101008101825285546001600160401b038082168352600160401b80830482166020850152600160801b8304821694840194909452600160c01b909104811660608301526001870154908116608083018190529290046001600160a01b031660a082015260028601546001600160501b03811660c0830152600160501b900460ff16151560e082015260009161411a919085614b4b565b9050600081128015614143575061413381600019615dc6565b60018601546001600160401b0316115b1561427b57600061415682600019615dc6565b6001868101549088015491925061418f916127109161128491600160a01b90910461ffff1690611dc2906001600160401b031686614fab565b60018701549097506141b69088906141b0906001600160401b031684614fab565b90614fab565b92506141d6611de661271061128460085487613e3390919063ffffffff16565b6010556009546141f390611e0c9061271090611284908790613e33565b601181905550614229611e4b6127106112846009546008546127106142189190615ea9565b6142229190615ea9565b8790613e33565b60125560198054829190600c90614251908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550506142d3565b6001850154601980546001600160401b0390921691600c906142ae908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b60006143096142e46008600a615d1e565b87546001890154611284916001600160401b0391821691600160401b90910416613e33565b86546002880154919250614336916001600160401b03909116908390600160501b900460ff166000614707565b8554600180880154604080518881526001600160401b03600160801b860481166020830152808416928201839052600160401b808704821660608401526000608084015260a083019390935260c082019490945292909316926001600160a01b03910416908a907f36b11e691447eee9c5d7286d5c0db51ec49fde6c88b2e4931328a15b554312be9060e00160405180910390a46000888152601d602090815260408083209283556001830180546001600160e01b0319169055600290920180546affffffffffffffffffffff19169055815189815290810185905233918a917f6f7734c2b603545392ede46279193d0b944bffb5d4c822bb78cd37eb6c2aadc9910160405180910390a350505b50505050919050565b600061384b8284615c34565b8015614516576001600160a01b03821661451a57803410156144bd5760405162461bcd60e51b815260206004820152601a60248201527f556e6945524332303a206e6f7420656e6f7567682076616c75650000000000006044820152606401610e0d565b803411156145165760006144d13483614fab565b604051909150600090339083908381818185875af1925050503d8060008114613eac576040519150601f19603f3d011682016040523d82523d6000602084013e613eb1565b5050565b6145166001600160a01b03831633308461501a565b600061455461271061128484611dc261454a6008600a615d1e565b6112848a8a613e33565b949350505050565b6006546040516341976e0960e01b81526001600160a01b03898116600483015260009283929116906341976e099060240160206040518083038186803b1580156145a557600080fd5b505afa1580156145b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145dd919061562d565b9050600085600a54888a6145f19190615e6a565b6145fb9190615dc6565b6146059190615c99565b9050881561469757600061463d856112846146226008600a615d1e565b611dc28a6141b0614633828d614fab565b6112848e80613e33565b905060008212156146685761466361465c600261128485600019615dc6565b8290614fab565b614672565b614672818361444d565b905061468d6146836008600a615d1e565b6112848584613e33565b93505050506146fc565b60006146cd856112846146ac6008600a615d1e565b611dc26146c66146bc8c8c61444d565b6112848d80613e33565b8b90614fab565b905060008212156146e75761466361465c83600019615dc6565b6146726146f5836002613e3f565b829061444d565b979650505050505050565b6000848152601b60205260409020811561496157601754614728908561444d565b601755600f54601954614754916127109161128491600160601b9091046001600160601b031690613e33565b60175411156147985760405162461bcd60e51b815260206004820152601060248201526f085b585e13dc195b925b9d195c995cdd60821b6044820152606401610e0d565b600d54600e5460018301546019546000936147dd936127109361128493849291611dc291600160601b90046001600160601b031690600160c01b900461ffff16613e33565b905083156148ae576001820180548691906000906148059084906001600160401b0316615c4c565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555061485c8260010160089054906101000a90046001600160401b03166001600160401b03168261444d90919063ffffffff16565b60018301546001600160401b031611156148a95760405162461bcd60e51b815260206004820152600e60248201526d216578706f737572652d6c6f6e6760901b6044820152606401610e0d565b61495b565b848260010160088282829054906101000a90046001600160401b03166148d49190615c4c565b82546101009290920a6001600160401b038181021990931691831602179091556001840154614906925083911661444d565b6001830154600160401b90046001600160401b0316111561495b5760405162461bcd60e51b815260206004820152600f60248201526e08595e1c1bdcdd5c994b5cda1bdc9d608a1b6044820152606401610e0d565b50612866565b60175461496e9085614fab565b60175582156149ec5760018101546001600160401b031684116149d4576001810180548591906000906149ab9084906001600160401b0316615ec0565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550612866565b60018101805467ffffffffffffffff19169055612866565b6001810154600160401b90046001600160401b03168411614a2d57838160010160088282829054906101000a90046001600160401b03166149ab9190615ec0565b600101805467ffffffffffffffff60401b1916905550505050565b6000808460e0015115614ab15784602001516001600160401b03168386604001516001600160401b0316614a7c9190615e4b565b614a8890612710615e4b565b614a929190615cc7565b85604001516001600160401b0316614aaa9190615ea9565b9050614b09565b84602001516001600160401b03168386604001516001600160401b0316614ad89190615e4b565b614ae490612710615e4b565b614aee9190615cc7565b85604001516001600160401b0316614b069190615c34565b90505b8460e001518015614b1a5750808411155b80614b3257508460e00151158015614b325750808410155b15614b4157600191505061384b565b600091505061384b565b60008060008560e0015115614bf15785604001516001600160401b03168410614bba57614bb3614b7d6008600a615d1e565b6040880151611284906001600160401b031681614b9a8983614fab565b60208c0151611dc2908c906001600160401b0316613e33565b9050614c44565b614be6614bc96008600a615d1e565b6040880151611284906001600160401b031681614b9a828a614fab565b905060019150614c44565b85604001516001600160401b0316841115614c3257614be6614c156008600a615d1e565b6040880151611284906001600160401b031681614b9a828a615ea9565b614c41614bc96008600a615d1e565b90505b8115614c5d57614c5681600019615dc6565b9250614c61565b8092505b50509392505050565b6000614c8e600b548560c001516001600160501b031661444d90919063ffffffff16565b421115614c9d5750600161384b565b8360e001518015614cd35750614cd0612710611284614cbc828661444d565b60608801516001600160401b031690613e33565b83115b15614ce05750600161384b565b8360e00151158015614d035750614d00612710611284614cbc8286614fab565b83105b15614d105750600161384b565b5060009392505050565b6000806000614d2c8888888888615052565b915091506000821215614e22576000614d4783600019615dc6565b905086811015614dc85760a0880151614d7a90611736614d696008600a615d1e565b60055461128490611dc28d88614fab565b60198054829190600c90614d9f908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550614e1c565b60198054889190600c90614ded908490600160601b90046001600160601b0316615c77565b92506101000a8154816001600160601b0302191690836001600160601b031602179055508193505050506114d7565b50614ef1565b6019548290600160601b90046001600160601b0316811115614e7c5760405162461bcd60e51b8152602060048201526013602482015272085d985d5b1d0b5a5b9cdd59999a58da595b9d606a1b6044820152606401610e0d565b60198054829190600c90614ea1908490600160601b90046001600160601b0316615ee8565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550614eef8860a001516117366008600a614ede9190615d1e565b60055461128490611dc28d8861444d565b505b614f0f611de661271061128460085485613e3390919063ffffffff16565b601055600954614f2c90611e0c9061271090611284908590613e33565b601181905550614f51611e4b612710611284600954600854612710611e3a9190615ea9565b60125560198054829190600c90614f79908490600160601b90046001600160601b0316615ee8565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550809250505095945050505050565b600061384b8284615ea9565b6040516001600160a01b03831660248201526044810182905261174990849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526150b0565b6040516001600160a01b0380851660248301528316604482015260648101829052613ef49085906323b872dd60e01b90608401614fe3565b600080600061506f8688602001516001600160401b03168761452f565b905061507b8882615182565b9250600061508a88888761518e565b90506150968482615182565b93506150a2828261444d565b925050509550959350505050565b6000615105826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166151ed9092919063ffffffff16565b80519091501561174957808060200190518101906151239190615518565b6117495760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e0d565b600061384b8284615e6a565b60006145546151a664e8d4a510006301e13380613e33565b6112846151c98760c001516001600160501b031642614fab90919063ffffffff16565b611dc286611dc28a602001516001600160401b03168a613e3390919063ffffffff16565b6060614554848460008585843b6152465760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e0d565b600080866001600160a01b031685876040516152629190615974565b60006040518083038185875af1925050503d806000811461529f576040519150601f19603f3d011682016040523d82523d6000602084013e6152a4565b606091505b50915091506146fc828286606083156152be57508161384b565b8251156152ce5782518084602001fd5b8160405162461bcd60e51b8152600401610e0d91906159df565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b80356001600160a01b03811681146113d157600080fd5b80356113d181615fa7565b803561ffff811681146113d157600080fd5b80356001600160401b03811681146113d157600080fd5b80356001600160481b03811681146113d157600080fd5b80356001600160601b03811681146113d157600080fd5b6000602082840312156153b757600080fd5b61384b8261532c565b600080600080608085870312156153d657600080fd5b6153df8561532c565b93506153ed6020860161532c565b92506153fb6040860161532c565b91506154096060860161532c565b905092959194509250565b60008060006060848603121561542957600080fd5b6154328461532c565b925060208401359150604084013561544981615fa7565b809150509250925092565b600080600080600060a0868803121561546c57600080fd5b6154758661532c565b94506020860135935060408601359250606086013561549381615fa7565b949793965091946080013592915050565b600080602083850312156154b757600080fd5b82356001600160401b03808211156154ce57600080fd5b818501915085601f8301126154e257600080fd5b8135818111156154f157600080fd5b8660208260051b850101111561550657600080fd5b60209290920196919550909350505050565b60006020828403121561552a57600080fd5b815161384b81615fa7565b6000806040838503121561554857600080fd5b823561555381615fa7565b9150602083013561556381615fa7565b809150509250929050565b600060a0828403121561558057600080fd5b60405160a081018181106001600160401b03821117156155b057634e487b7160e01b600052604160045260246000fd5b6040526155bc8361538e565b81526155ca6020840161538e565b60208201526155db60408401615360565b60408201526155ec60608401615360565b6060820152608083013563ffffffff8116811461560857600080fd5b60808201529392505050565b60006020828403121561562657600080fd5b5035919050565b60006020828403121561563f57600080fd5b5051919050565b6000806040838503121561565957600080fd5b823591506156696020840161532c565b90509250929050565b6000808284036101a081121561568757600080fd5b8335925061018080601f198301121561569f57600080fd5b6156a7615bfd565b91506156b56020860161532c565b82526156c360408601615377565b60208301526156d46060860161534e565b60408301526156e560808601615343565b60608301526156f660a08601615360565b608083015261570760c08601615360565b60a083015261571860e0860161534e565b60c083015261010061572b81870161534e565b60e084015261012061573e81880161534e565b82850152610140915061575282880161534e565b9084015261016061576487820161534e565b82850152615773838801615360565b9084015250929590945092505050565b6000806040838503121561579657600080fd5b50508035926020909101359150565b6000806000606084860312156157ba57600080fd5b8335925060208401359150604084013561544981615fa7565b600080600080608085870312156157e957600080fd5b8435935060208501359250604085013561580281615fa7565b9396929550929360600135925050565b6001600160401b038082511683528060208301511660208401528060408301511660408401528060608301511660608401528060808301511660808401525060018060a01b0360a08201511660a08301526001600160501b0360c08201511660c083015260e081015161174960e084018215159052565b80546001600160a01b038116835260a081901c6001600160481b0316602084015261ffff60e882901c811660408501526158ca606085018360f81c15159052565b60018301546001600160401b038082166080870152604082901c811660a08701529092505061590460c08501828460801c1661ffff169052565b61591960e08501828460901c1661ffff169052565b61592f6101008501828460a01c1661ffff169052565b6159456101208501828460b01c1661ffff169052565b61595b6101408501828460c01c1661ffff169052565b5050600201546001600160401b03166101609190910152565b60008251615986818460208701615f08565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b818110156159d3576159bf838551615812565b9284019261010092909201916001016159ac565b50909695505050505050565b60208152600082518060208401526159fe816040850160208701615f08565b601f01601f19169190910160400192915050565b6020808252600c908201526b10b234b9ba3934b13aba37b960a11b604082015260600190565b60208082526007908201526610b6b0b933b4b760c91b604082015260600190565b6020808252600d908201526c216d61782d6c6576657261676560981b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526006908201526510b7bbb732b960d11b604082015260600190565b610100810161128a8284615812565b81516001600160a01b0316815261018081016020830151615b1260208401826001600160481b03169052565b506040830151615b28604084018261ffff169052565b506060830151615b3c606084018215159052565b506080830151615b5760808401826001600160401b03169052565b5060a0830151615b7260a08401826001600160401b03169052565b5060c0830151615b8860c084018261ffff169052565b5060e0830151615b9e60e084018261ffff169052565b506101008381015161ffff90811691840191909152610120808501518216908401526101408085015190911690830152610160808401516001600160401b03811682850152611655565b8281526101a0810161384b6020830184615889565b60405161018081016001600160401b0381118282101715615c2e57634e487b7160e01b600052604160045260246000fd5b60405290565b60008219821115615c4757615c47615f4f565b500190565b60006001600160401b03808316818516808303821115615c6e57615c6e615f4f565b01949350505050565b60006001600160601b03808316818516808303821115615c6e57615c6e615f4f565b600082615ca857615ca8615f65565b600160ff1b821460001984141615615cc257615cc2615f4f565b500590565b600082615cd657615cd6615f65565b500490565b600181815b80851115615d16578160001904821115615cfc57615cfc615f4f565b80851615615d0957918102915b93841c9390800290615ce0565b509250929050565b600061384b8383600082615d345750600161128a565b81615d415750600061128a565b8160018114615d575760028114615d6157615d7d565b600191505061128a565b60ff841115615d7257615d72615f4f565b50506001821b61128a565b5060208310610133831016604e8410600b8410161715615da0575081810a61128a565b615daa8383615cdb565b8060001904821115615dbe57615dbe615f4f565b029392505050565b60006001600160ff1b0381841382841380821686840486111615615dec57615dec615f4f565b600160ff1b6000871282811687830589121615615e0b57615e0b615f4f565b60008712925087820587128484161615615e2757615e27615f4f565b87850587128184161615615e3d57615e3d615f4f565b505050929093029392505050565b6000816000190483118215151615615e6557615e65615f4f565b500290565b60008083128015600160ff1b850184121615615e8857615e88615f4f565b6001600160ff1b0384018313811615615ea357615ea3615f4f565b50500390565b600082821015615ebb57615ebb615f4f565b500390565b60006001600160401b0383811690831681811015615ee057615ee0615f4f565b039392505050565b60006001600160601b0383811690831681811015615ee057615ee0615f4f565b60005b83811015615f23578181015183820152602001615f0b565b83811115613ef45750506000910152565b6000600019821415615f4857615f48615f4f565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461287757600080fdfea2646970667358221220ca2a3eafb2b2cff0d911a5d3992ecd445edb765a2c24592c3593752f3d43459d64736f6c63430008070033

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

0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000000000000000000000000000000000000000006000000000000000000000000250e7ab9b5ea0e95bf68f9fbe2f4f9dc5c8af74600000000000000000000000000000000000000000000000000000002540be400

-----Decoded View---------------
Arg [0] : _token (address): 0x7F5c764cBc14f9669B88837ca1490cCa17c31607
Arg [1] : _tokenDecimal (uint256): 6
Arg [2] : _oracle (address): 0x250e7AB9b5EA0e95bF68F9Fbe2f4F9DC5C8af746
Arg [3] : _minMargin (uint256): 10000000000

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [2] : 000000000000000000000000250e7ab9b5ea0e95bf68f9fbe2f4f9dc5c8af746
Arg [3] : 00000000000000000000000000000000000000000000000000000002540be400


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