Contract 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e 1

Contract Overview

Balance:
0 BNB
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xe5562f1c547291b973c0400f04de6fb98be36cdfee526863969a7cb146a8b7780x60806040106931122021-07-18 7:45:05134 days 22 hrs ago0xbee397129374d0b4db7bf1654936951e5bdfe5a6 IN  Contract Creation0 BNB0.03040435
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x3daf2f32973ba1b149c521b6ce5e97b8bead658f053fd5ffbf47abd8424c8579145334202021-11-29 9:28:3721 hrs 5 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x21411d5d9280a96329e07dab70ce147b9cfc5e7fda52ea4f9f8517338d0afe1d145333832021-11-29 9:26:4621 hrs 7 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x21411d5d9280a96329e07dab70ce147b9cfc5e7fda52ea4f9f8517338d0afe1d145333832021-11-29 9:26:4621 hrs 7 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x21411d5d9280a96329e07dab70ce147b9cfc5e7fda52ea4f9f8517338d0afe1d145333832021-11-29 9:26:4621 hrs 7 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x21411d5d9280a96329e07dab70ce147b9cfc5e7fda52ea4f9f8517338d0afe1d145333832021-11-29 9:26:4621 hrs 7 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x866f66300fa1bc4825d701f8c518999d0a762e7bfabf9929101a05da784085ad145333762021-11-29 9:26:2521 hrs 7 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x08f9a4d739c99e4cf851b9fa7c4d0530008c23aebb84a94ee50148be7338724e145333632021-11-29 9:25:4621 hrs 8 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0xde442bb396bb497c775552edfe238eb616b0a0d9f79f5f2b7842181c0d73ca5c145333552021-11-29 9:25:2221 hrs 9 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0xde442bb396bb497c775552edfe238eb616b0a0d9f79f5f2b7842181c0d73ca5c145333552021-11-29 9:25:2221 hrs 9 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0xde442bb396bb497c775552edfe238eb616b0a0d9f79f5f2b7842181c0d73ca5c145333552021-11-29 9:25:2221 hrs 9 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0xde442bb396bb497c775552edfe238eb616b0a0d9f79f5f2b7842181c0d73ca5c145333552021-11-29 9:25:2221 hrs 9 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x5f168d5c6be39920f1803ccc40af5c4335b8c9e98a8929dd4be3f871d3c2bc6a145333422021-11-29 9:24:4321 hrs 9 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x5f168d5c6be39920f1803ccc40af5c4335b8c9e98a8929dd4be3f871d3c2bc6a145333422021-11-29 9:24:4321 hrs 9 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x5f168d5c6be39920f1803ccc40af5c4335b8c9e98a8929dd4be3f871d3c2bc6a145333422021-11-29 9:24:4321 hrs 9 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x5f168d5c6be39920f1803ccc40af5c4335b8c9e98a8929dd4be3f871d3c2bc6a145333422021-11-29 9:24:4321 hrs 9 mins ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x36fa094635ca8f4b602c8923646ba9dd66dc1cecab8a10f172f803a89c2654b1139894422021-11-10 10:40:0219 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x3a68a1ac07b41976d8711c444f1c934d97b8eb8e485c64d5eee6105ab31fb79a139894132021-11-10 10:38:3519 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x3a68a1ac07b41976d8711c444f1c934d97b8eb8e485c64d5eee6105ab31fb79a139894132021-11-10 10:38:3519 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x3a68a1ac07b41976d8711c444f1c934d97b8eb8e485c64d5eee6105ab31fb79a139894132021-11-10 10:38:3519 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x3a68a1ac07b41976d8711c444f1c934d97b8eb8e485c64d5eee6105ab31fb79a139894132021-11-10 10:38:3519 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0xad99e7a18b69c423a21658ea3d55b7f365c40160ea6ffa9bc80c71117c0fbea9139893832021-11-10 10:37:0519 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x9dd604f726a7383c4c730bf366e05b8ba4b3c55452b8f7afe7c87b0d132057b2139893582021-11-10 10:35:5019 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x9dd604f726a7383c4c730bf366e05b8ba4b3c55452b8f7afe7c87b0d132057b2139893582021-11-10 10:35:5019 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x9dd604f726a7383c4c730bf366e05b8ba4b3c55452b8f7afe7c87b0d132057b2139893582021-11-10 10:35:5019 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
0x9dd604f726a7383c4c730bf366e05b8ba4b3c55452b8f7afe7c87b0d132057b2139893582021-11-10 10:35:5019 days 19 hrs ago 0xb3f98a31a02d133f65da961086ecda4133bdf48e 0x7d58a7ecc1812e097601eabcc58a33dfe966e17e0 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Qore

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 14 : Qore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

/*
      ___       ___       ___       ___       ___
     /\  \     /\__\     /\  \     /\  \     /\  \
    /::\  \   /:/ _/_   /::\  \   _\:\  \    \:\  \
    \:\:\__\ /:/_/\__\ /::\:\__\ /\/::\__\   /::\__\
     \::/  / \:\/:/  / \:\::/  / \::/\/__/  /:/\/__/
     /:/  /   \::/  /   \::/  /   \:\__\    \/__/
     \/__/     \/__/     \/__/     \/__/

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

import "@openzeppelin/contracts/math/SafeMath.sol";
import "./interfaces/IQToken.sol";
import "./interfaces/IQValidator.sol";

import "./QoreAdmin.sol";


contract Qore is QoreAdmin {
    using SafeMath for uint;

    /* ========== CONSTANT VARIABLES ========== */

    address internal constant WBNB = 0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd;

    /* ========== STATE VARIABLES ========== */

    mapping(address => address[]) public marketListOfUsers; // (account => qTokenAddress[])
    mapping(address => mapping(address => bool)) public usersOfMarket; // (qTokenAddress => (account => joined))
    address[] public totalUserList;

    /* ========== INITIALIZER ========== */

    function initialize() external initializer {
        __Qore_init();
    }

    /* ========== MODIFIERS ========== */

    modifier onlyMemberOfMarket(address qToken) {
        require(usersOfMarket[qToken][msg.sender], "Qore: must enter market");
        _;
    }

    /* ========== VIEWS ========== */

    function allMarkets() external view override returns (address[] memory) {
        return markets;
    }

    function marketInfoOf(address qToken) external view override returns (QConstant.MarketInfo memory) {
        return marketInfos[qToken];
    }

    function marketListOf(address account) external view override returns (address[] memory) {
        return marketListOfUsers[account];
    }

    function checkMembership(address account, address qToken) external view override returns (bool) {
        return usersOfMarket[qToken][account];
    }

    function getTotalUserList() external view override returns (address[] memory) {
        return totalUserList;
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    function enterMarkets(address[] memory qTokens) public override {
        for (uint i = 0; i < qTokens.length; i++) {
            _enterMarket(payable(qTokens[i]), msg.sender);
        }
    }

    function exitMarket(address qToken) external override onlyListedMarket(qToken) onlyMemberOfMarket(qToken) {
        QConstant.AccountSnapshot memory snapshot = IQToken(qToken).accruedAccountSnapshot(msg.sender);
        require(snapshot.borrowBalance == 0, "Qore: borrow balance must be zero");
        require(IQValidator(qValidator).redeemAllowed(qToken, msg.sender, snapshot.qTokenBalance), "Qore: cannot redeem");

        delete usersOfMarket[qToken][msg.sender];
        _removeUserMarket(qToken, msg.sender);
        emit MarketExited(qToken, msg.sender);
    }

    function supply(address qToken, uint uAmount) external override payable onlyListedMarket(qToken) returns (uint) {
        uAmount = IQToken(qToken).underlying() == address(WBNB) ? msg.value : uAmount;

        uint qAmount = IQToken(qToken).supply{value : msg.value}(msg.sender, uAmount);
        qDistributor.notifySupplyUpdated(qToken, msg.sender);

        return qAmount;
    }

    function redeemToken(address qToken, uint qAmount) external override onlyListedMarket(qToken) returns (uint) {
        uint uAmountRedeem = IQToken(qToken).redeemToken(msg.sender, qAmount);
        qDistributor.notifySupplyUpdated(qToken, msg.sender);

        return uAmountRedeem;
    }

    function redeemUnderlying(address qToken, uint uAmount) external override onlyListedMarket(qToken) returns (uint) {
        uint uAmountRedeem = IQToken(qToken).redeemUnderlying(msg.sender, uAmount);
        qDistributor.notifySupplyUpdated(qToken, msg.sender);

        return uAmountRedeem;
    }

    function borrow(address qToken, uint amount) external override onlyListedMarket(qToken) {
        _enterMarket(qToken, msg.sender);
        require(IQValidator(qValidator).borrowAllowed(qToken, msg.sender, amount), "Qore: cannot borrow");

        IQToken(payable(qToken)).borrow(msg.sender, amount);
        qDistributor.notifyBorrowUpdated(qToken, msg.sender);
    }

    function repayBorrow(address qToken, uint amount) external override payable onlyListedMarket(qToken) {
        IQToken(payable(qToken)).repayBorrow{value : msg.value}(msg.sender, amount);
        qDistributor.notifyBorrowUpdated(qToken, msg.sender);
    }

    function repayBorrowBehalf(address qToken, address borrower, uint amount) external override payable onlyListedMarket(qToken) {
        IQToken(payable(qToken)).repayBorrowBehalf{value : msg.value}(msg.sender, borrower, amount);
        qDistributor.notifyBorrowUpdated(qToken, borrower);
    }

    function liquidateBorrow(address qTokenBorrowed, address qTokenCollateral, address borrower, uint amount) external override payable {
        require(marketInfos[qTokenBorrowed].isListed && marketInfos[qTokenCollateral].isListed, "Qore: invalid market");
        require(IQValidator(qValidator).liquidateAllowed(qTokenBorrowed, borrower, amount, closeFactor), "Qore: cannot liquidate borrow");

        uint qAmountToSeize = IQToken(qTokenBorrowed).liquidateBorrow{value : msg.value}(qTokenCollateral, msg.sender, borrower, amount);
        IQToken(qTokenCollateral).seize(msg.sender, borrower, qAmountToSeize);
        qDistributor.notifyBorrowUpdated(qTokenBorrowed, borrower);
    }

    function removeUserFromList(address _account) external onlyKeeper {
        require(marketListOfUsers[_account].length == 0, "Qore: cannot remove user");
        address[] memory updateUserList = new address[](totalUserList.length - 1);

        uint counter = 0;
        for (uint i = 0; i < totalUserList.length; i++) {
            if (totalUserList[i] != _account) {
                updateUserList[counter++] = totalUserList[i];
            }
        }
        totalUserList = updateUserList;
    }

    /* ========== PRIVATE FUNCTIONS ========== */

    function _enterMarket(address qToken, address _account) internal onlyListedMarket(qToken) {
        if (!usersOfMarket[qToken][_account]) {
            usersOfMarket[qToken][_account] = true;
            if (marketListOfUsers[_account].length == 0) {
                totalUserList.push(_account);
            }
            marketListOfUsers[_account].push(qToken);
            emit MarketEntered(qToken, _account);
        }
    }

    function _removeUserMarket(address qTokenToExit, address _account) private {
        require(marketListOfUsers[_account].length > 0, "Qore: cannot pop user market");

        address[] memory updatedMarkets = new address[](marketListOfUsers[_account].length - 1);
        uint counter = 0;
        for (uint i = 0; i < marketListOfUsers[_account].length; i++) {
            if (marketListOfUsers[_account][i] != qTokenToExit) {
                updatedMarkets[counter++] = marketListOfUsers[_account][i];
            }
        }
        marketListOfUsers[_account] = updatedMarkets;
    }
}

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
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) {
        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) {
        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) {
        // 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) {
        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) {
        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) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        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) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @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. 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) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        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) {
        require(b > 0, "SafeMath: modulo by zero");
        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) {
        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.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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) {
        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) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

File 3 of 14 : IQToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

/*
      ___       ___       ___       ___       ___
     /\  \     /\__\     /\  \     /\  \     /\  \
    /::\  \   /:/ _/_   /::\  \   _\:\  \    \:\  \
    \:\:\__\ /:/_/\__\ /::\:\__\ /\/::\__\   /::\__\
     \::/  / \:\/:/  / \:\::/  / \::/\/__/  /:/\/__/
     /:/  /   \::/  /   \::/  /   \:\__\    \/__/
     \/__/     \/__/     \/__/     \/__/

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

import "../library/QConstant.sol";


interface IQToken {
    function underlying() external view returns (address);
    function totalSupply() external view returns (uint);

    function accountSnapshot(address account) external view returns (QConstant.AccountSnapshot memory);
    function underlyingBalanceOf(address account) external view returns (uint);
    function borrowBalanceOf(address account) external view returns (uint);
    function borrowRatePerSec() external view returns (uint);
    function supplyRatePerSec() external view returns (uint);
    function totalBorrow() external view returns (uint);
    function exchangeRate() external view returns (uint);
    function getCash() external view returns (uint);
    function getAccInterestIndex() external view returns (uint);

    function accruedAccountSnapshot(address account) external returns (QConstant.AccountSnapshot memory);
    function accruedUnderlyingBalanceOf(address account) external returns (uint);
    function accruedBorrowBalanceOf(address account) external returns (uint);
    function accruedTotalBorrow() external returns (uint);
    function accruedExchangeRate() external returns (uint);

    function approve(address spender, uint amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint);
    function balanceOf(address account) external view returns (uint);
    function transfer(address dst, uint amount) external returns (bool);
    function transferFrom(address src, address dst, uint amount) external returns (bool);

    function supply(address account, uint underlyingAmount) external payable returns (uint);
    function redeemToken(address account, uint qTokenAmount) external returns (uint);
    function redeemUnderlying(address account, uint underlyingAmount) external returns (uint);

    function borrow(address account, uint amount) external returns (uint);
    function repayBorrow(address account, uint amount) external payable returns (uint);
    function repayBorrowBehalf(address payer, address borrower, uint amount) external payable returns (uint);

    function liquidateBorrow(address qTokenCollateral, address liquidator, address borrower, uint amount) payable external returns (uint qAmountToSeize);
    function seize(address liquidator, address borrower, uint qTokenAmount) external;
}

File 4 of 14 : IQValidator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

/*
      ___       ___       ___       ___       ___
     /\  \     /\__\     /\  \     /\  \     /\  \
    /::\  \   /:/ _/_   /::\  \   _\:\  \    \:\  \
    \:\:\__\ /:/_/\__\ /::\:\__\ /\/::\__\   /::\__\
     \::/  / \:\/:/  / \:\::/  / \::/\/__/  /:/\/__/
     /:/  /   \::/  /   \::/  /   \:\__\    \/__/
     \/__/     \/__/     \/__/     \/__/

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


interface IQValidator {
    function redeemAllowed(address qToken, address redeemer, uint redeemAmount) external returns (bool);
    function borrowAllowed(address qToken, address borrower, uint borrowAmount) external returns (bool);
    function liquidateAllowed(address qTokenBorrowed, address borrower, uint repayAmount, uint closeFactor) external returns (bool);
    function qTokenAmountToSeize(address qTokenBorrowed, address qTokenCollateral, uint actualRepayAmount) external returns (uint qTokenAmount);
    function getAccountLiquidity(address account, address qToken, uint redeemAmount, uint borrowAmount) external view returns (uint liquidity, uint shortfall);
    function getAccountLiquidityValue(address account) external view returns (uint collateralUSD, uint borrowUSD);
}

File 5 of 14 : QoreAdmin.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

/*
      ___       ___       ___       ___       ___
     /\  \     /\__\     /\  \     /\  \     /\  \
    /::\  \   /:/ _/_   /::\  \   _\:\  \    \:\  \
    \:\:\__\ /:/_/\__\ /::\:\__\ /\/::\__\   /::\__\
     \::/  / \:\/:/  / \:\::/  / \::/\/__/  /:/\/__/
     /:/  /   \::/  /   \::/  /   \:\__\    \/__/
     \/__/     \/__/     \/__/     \/__/

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

import "./interfaces/IQore.sol";
import "./interfaces/IQDistributor.sol";
import "./interfaces/IPriceCalculator.sol";
import "./library/WhitelistUpgradeable.sol";
import {QConstant} from "./library/QConstant.sol";
import "./interfaces/IQToken.sol";


abstract contract QoreAdmin is IQore, WhitelistUpgradeable {

    /* ========== CONSTANT VARIABLES ========== */

    IPriceCalculator public constant priceCalculator = IPriceCalculator(0x20E5E35ba29dC3B540a1aee781D0814D5c77Bce6);

    /* ========== STATE VARIABLES ========== */

    address public keeper;
    address public override qValidator;
    IQDistributor public qDistributor;

    address[] public markets; // qTokenAddress[]
    mapping(address => QConstant.MarketInfo) public marketInfos; // (qTokenAddress => MarketInfo)

    uint public closeFactor;
    uint public override liquidationIncentive;

    /* ========== Event ========== */

    event MarketListed(address qToken);
    event MarketEntered(address qToken, address account);
    event MarketExited(address qToken, address account);

    event CloseFactorUpdated(uint newCloseFactor);
    event CollateralFactorUpdated(address qToken, uint newCollateralFactor);
    event LiquidationIncentiveUpdated(uint newLiquidationIncentive);
    event BorrowCapUpdated(address indexed qToken, uint newBorrowCap);

    /* ========== MODIFIERS ========== */

    modifier onlyKeeper {
        require(msg.sender == keeper || msg.sender == owner(), 'Qore: caller is not the owner or keeper');
        _;
    }

    modifier onlyListedMarket(address qToken) {
        require(marketInfos[qToken].isListed, "Qore: invalid market");
        _;
    }

    /* ========== INITIALIZER ========== */

    function __Qore_init() internal initializer {
        __WhitelistUpgradeable_init();

        closeFactor = 5e17;
        liquidationIncentive = 11e17;
    }

    /* ========== RESTRICTED FUNCTIONS ========== */

    function setKeeper(address _keeper) external onlyKeeper {
        require(_keeper != address(0), "Qore: invalid keeper address");
        keeper = _keeper;
    }

    function setQValidator(address _qValidator) external onlyKeeper {
        require(_qValidator != address(0), "Qore: invalid qValidator address");
        qValidator = _qValidator;
    }

    function setQDistributor(address _qDistributor) external onlyKeeper {
        require(_qDistributor != address(0), "Qore: invalid qDistributor address");
        qDistributor = IQDistributor(_qDistributor);
    }

    function setCloseFactor(uint newCloseFactor) external onlyKeeper {
        require(newCloseFactor >= QConstant.CLOSE_FACTOR_MIN && newCloseFactor <= QConstant.CLOSE_FACTOR_MAX, "Qore: invalid close factor");
        closeFactor = newCloseFactor;
        emit CloseFactorUpdated(newCloseFactor);
    }

    function setCollateralFactor(address qToken, uint newCollateralFactor) external onlyKeeper onlyListedMarket(qToken) {
        require(newCollateralFactor <= QConstant.COLLATERAL_FACTOR_MAX, "Qore: invalid collateral factor");
        if (newCollateralFactor != 0 && priceCalculator.getUnderlyingPrice(qToken) == 0) {
            revert("Qore: invalid underlying price");
        }

        marketInfos[qToken].collateralFactor = newCollateralFactor;
        emit CollateralFactorUpdated(qToken, newCollateralFactor);
    }

    function setLiquidationIncentive(uint newLiquidationIncentive) external onlyKeeper {
        liquidationIncentive = newLiquidationIncentive;
        emit LiquidationIncentiveUpdated(newLiquidationIncentive);
    }

    function setMarketBorrowCaps(address[] calldata qTokens, uint[] calldata newBorrowCaps) external onlyKeeper {
        require(qTokens.length != 0 && qTokens.length == newBorrowCaps.length, "Qore: invalid data");

        for (uint i = 0; i < qTokens.length; i++) {
            marketInfos[qTokens[i]].borrowCap = newBorrowCaps[i];
            emit BorrowCapUpdated(qTokens[i], newBorrowCaps[i]);
        }
    }

    function listMarket(address payable qToken, uint borrowCap, uint collateralFactor) external onlyKeeper {
        require(!marketInfos[qToken].isListed, "Qore: already listed market");
        for (uint i = 0; i < markets.length; i ++) {
            require(markets[i] != qToken, "Qore: already listed market");
        }

        marketInfos[qToken] = QConstant.MarketInfo({isListed : true, borrowCap : borrowCap, collateralFactor : collateralFactor});
        markets.push(qToken);
        emit MarketListed(qToken);
    }

    function removeMarket(address payable qToken) external onlyKeeper {
        require(marketInfos[qToken].isListed, "Qore: unlisted market");
        require(IQToken(qToken).totalSupply() == 0 && IQToken(qToken).totalBorrow() == 0, "Qore: cannot remove market");

        address[] memory updatedMarkets = new address[](markets.length - 1);
        uint counter = 0;
        for (uint i = 0; i < markets.length; i++) {
            if (markets[i] != qToken) {
                updatedMarkets[counter++] = markets[i];
            }
        }
        markets = updatedMarkets;
        delete marketInfos[qToken];
    }
}

File 6 of 14 : QConstant.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;

/*
      ___       ___       ___       ___       ___
     /\  \     /\__\     /\  \     /\  \     /\  \
    /::\  \   /:/ _/_   /::\  \   _\:\  \    \:\  \
    \:\:\__\ /:/_/\__\ /::\:\__\ /\/::\__\   /::\__\
     \::/  / \:\/:/  / \:\::/  / \::/\/__/  /:/\/__/
     /:/  /   \::/  /   \::/  /   \:\__\    \/__/
     \/__/     \/__/     \/__/     \/__/

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


library QConstant {
    uint public constant CLOSE_FACTOR_MIN = 5e16;
    uint public constant CLOSE_FACTOR_MAX = 9e17;
    uint public constant COLLATERAL_FACTOR_MAX = 9e17;

    struct MarketInfo {
        bool isListed;
        uint borrowCap;
        uint collateralFactor;
    }

    struct BorrowInfo {
        uint borrow;
        uint interestIndex;
    }

    struct AccountSnapshot {
        uint qTokenBalance;
        uint borrowBalance;
        uint exchangeRate;
    }

    struct AccrueSnapshot {
        uint totalBorrow;
        uint totalReserve;
        uint accInterestIndex;
    }
}

File 7 of 14 : IQore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

import "../library/QConstant.sol";


interface IQore {
    function qValidator() external view returns (address);
    function getTotalUserList() external view returns (address[] memory);

    function allMarkets() external view returns (address[] memory);
    function marketListOf(address account) external view returns (address[] memory);
    function marketInfoOf(address qToken) external view returns (QConstant.MarketInfo memory);
    function liquidationIncentive() external view returns (uint);
    function checkMembership(address account, address qToken) external view returns (bool);

    function enterMarkets(address[] memory qTokens) external;
    function exitMarket(address qToken) external;

    function supply(address qToken, uint underlyingAmount) external payable returns (uint);
    function redeemToken(address qToken, uint qTokenAmount) external returns (uint);
    function redeemUnderlying(address qToken, uint underlyingAmount) external returns (uint);

    function borrow(address qToken, uint amount) external;

    function repayBorrow(address qToken, uint amount) external payable;
    function repayBorrowBehalf(address qToken, address borrower, uint amount) external payable;

    function liquidateBorrow(address qTokenBorrowed, address qTokenCollateral, address borrower, uint amount) external payable;
}

File 8 of 14 : IQDistributor.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

/*
      ___       ___       ___       ___       ___
     /\  \     /\__\     /\  \     /\  \     /\  \
    /::\  \   /:/ _/_   /::\  \   _\:\  \    \:\  \
    \:\:\__\ /:/_/\__\ /::\:\__\ /\/::\__\   /::\__\
     \::/  / \:\/:/  / \:\::/  / \::/\/__/  /:/\/__/
     /:/  /   \::/  /   \::/  /   \:\__\    \/__/
     \/__/     \/__/     \/__/     \/__/

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

interface IQDistributor {

    struct UserInfo {
        uint accruedQubit;
        uint boostedSupply;    // effective(boosted) supply balance of user  (since last_action)
        uint boostedBorrow;    // effective(boosted) borrow balance of user  (since last_action)
        uint accPerShareSupply;  // Last integral value of Qubit rewards per share. ∫(qubitRate(t) / totalShare(t) dt) from 0 till (last_action)
        uint accPerShareBorrow;  // Last integral value of Qubit rewards per share. ∫(qubitRate(t) / totalShare(t) dt) from 0 till (last_action)
    }

    struct DistributionInfo {
        uint supplyRate;
        uint borrowRate;
        uint totalBoostedSupply;
        uint totalBoostedBorrow;
        uint accPerShareSupply;
        uint accPerShareBorrow;
        uint accruedAt;
    }

    function accruedQubit(address market, address user) external view returns (uint);
    function qubitRatesOf(address market) external view returns (uint supplyRate, uint borrowRate);
    function totalBoosted(address market) external view returns (uint boostedSupply, uint boostedBorrow);
    function boostedBalanceOf(address market, address account) external view returns (uint boostedSupply, uint boostedBorrow);

    function notifySupplyUpdated(address market, address user) external;
    function notifyBorrowUpdated(address market, address user) external;
    function notifyTransferred(address qToken, address sender, address receiver) external;
    function claimQubit(address user) external;
    function kick(address user) external;
}

File 9 of 14 : IPriceCalculator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;

/*
      ___       ___       ___       ___       ___
     /\  \     /\__\     /\  \     /\  \     /\  \
    /::\  \   /:/ _/_   /::\  \   _\:\  \    \:\  \
    \:\:\__\ /:/_/\__\ /::\:\__\ /\/::\__\   /::\__\
     \::/  / \:\/:/  / \:\::/  / \::/\/__/  /:/\/__/
     /:/  /   \::/  /   \::/  /   \:\__\    \/__/
     \/__/     \/__/     \/__/     \/__/

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


interface IPriceCalculator {
    struct ReferenceData {
        uint lastData;
        uint lastUpdated;
    }

    function priceOf(address asset) external view returns (uint);
    function pricesOf(address[] memory assets) external view returns (uint[] memory);
    function getUnderlyingPrice(address qToken) external view returns (uint);
    function getUnderlyingPrices(address[] memory qTokens) external view returns (uint[] memory);
    function valueOfAsset(address asset, uint amount) external view returns (uint valueInBNB, uint valueInUSD);
}

File 10 of 14 : WhitelistUpgradeable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;

/*
      ___       ___       ___       ___       ___
     /\  \     /\__\     /\  \     /\  \     /\  \
    /::\  \   /:/ _/_   /::\  \   _\:\  \    \:\  \
    \:\:\__\ /:/_/\__\ /::\:\__\ /\/::\__\   /::\__\
     \::/  / \:\/:/  / \:\::/  / \::/\/__/  /:/\/__/
     /:/  /   \::/  /   \::/  /   \:\__\    \/__/
     \/__/     \/__/     \/__/     \/__/

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

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";


contract WhitelistUpgradeable is OwnableUpgradeable {
    mapping (address => bool) private _whitelist;
    bool private _disable;                      // default - false means whitelist feature is working on. if true no more use of whitelist

    event Whitelisted(address indexed _address, bool whitelist);
    event EnableWhitelist();
    event DisableWhitelist();

    modifier onlyWhitelisted {
        require(_disable || _whitelist[msg.sender], "Whitelist: caller is not on the whitelist");
        _;
    }

    function __WhitelistUpgradeable_init() internal initializer {
        __Ownable_init();
    }

    function isWhitelist(address _address) public view returns(bool) {
        return _whitelist[_address];
    }

    function setWhitelist(address _address, bool _on) external onlyOwner {
        _whitelist[_address] = _on;

        emit Whitelisted(_address, _on);
    }

    function disableWhitelist(bool disable) external onlyOwner {
        _disable = disable;
        if (disable) {
            emit DisableWhitelist();
        } else {
            emit EnableWhitelist();
        }
    }

    uint256[49] private __gap;
}

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

pragma solidity >=0.6.0 <0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/Initializable.sol";
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
    uint256[49] private __gap;
}

File 12 of 14 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;
import "../proxy/Initializable.sol";

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

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
    uint256[50] private __gap;
}

File 13 of 14 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;

import "../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

File 14 of 14 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @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;
        // solhint-disable-next-line no-inline-assembly
        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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

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

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"qToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"newBorrowCap","type":"uint256"}],"name":"BorrowCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newCloseFactor","type":"uint256"}],"name":"CloseFactorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"qToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"newCollateralFactor","type":"uint256"}],"name":"CollateralFactorUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"DisableWhitelist","type":"event"},{"anonymous":false,"inputs":[],"name":"EnableWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newLiquidationIncentive","type":"uint256"}],"name":"LiquidationIncentiveUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"qToken","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"MarketEntered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"qToken","type":"address"},{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"MarketExited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"qToken","type":"address"}],"name":"MarketListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_address","type":"address"},{"indexed":false,"internalType":"bool","name":"whitelist","type":"bool"}],"name":"Whitelisted","type":"event"},{"inputs":[],"name":"allMarkets","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"qToken","type":"address"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"disable","type":"bool"}],"name":"disableWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"qTokens","type":"address[]"}],"name":"enterMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"}],"name":"exitMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getTotalUserList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"qTokenBorrowed","type":"address"},{"internalType":"address","name":"qTokenCollateral","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"liquidateBorrow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"liquidationIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"qToken","type":"address"},{"internalType":"uint256","name":"borrowCap","type":"uint256"},{"internalType":"uint256","name":"collateralFactor","type":"uint256"}],"name":"listMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"}],"name":"marketInfoOf","outputs":[{"components":[{"internalType":"bool","name":"isListed","type":"bool"},{"internalType":"uint256","name":"borrowCap","type":"uint256"},{"internalType":"uint256","name":"collateralFactor","type":"uint256"}],"internalType":"struct QConstant.MarketInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"marketInfos","outputs":[{"internalType":"bool","name":"isListed","type":"bool"},{"internalType":"uint256","name":"borrowCap","type":"uint256"},{"internalType":"uint256","name":"collateralFactor","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"marketListOf","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketListOfUsers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"markets","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":"priceCalculator","outputs":[{"internalType":"contract IPriceCalculator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"qDistributor","outputs":[{"internalType":"contract IQDistributor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"qValidator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"},{"internalType":"uint256","name":"qAmount","type":"uint256"}],"name":"redeemToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"},{"internalType":"uint256","name":"uAmount","type":"uint256"}],"name":"redeemUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"qToken","type":"address"}],"name":"removeMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"removeUserFromList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayBorrow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayBorrowBehalf","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCloseFactor","type":"uint256"}],"name":"setCloseFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"},{"internalType":"uint256","name":"newCollateralFactor","type":"uint256"}],"name":"setCollateralFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLiquidationIncentive","type":"uint256"}],"name":"setLiquidationIncentive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"qTokens","type":"address[]"},{"internalType":"uint256[]","name":"newBorrowCaps","type":"uint256[]"}],"name":"setMarketBorrowCaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_qDistributor","type":"address"}],"name":"setQDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_qValidator","type":"address"}],"name":"setQValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bool","name":"_on","type":"bool"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"qToken","type":"address"},{"internalType":"uint256","name":"uAmount","type":"uint256"}],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalUserList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"usersOfMarket","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b5061360a806100206000396000f3fe6080604052600436106102515760003560e01c80638c765e9411610139578063aced1661116100b6578063c683630d1161007a578063c683630d1461069e578063db913236146106be578063e61604cf146106de578063ede4edd0146106f1578063f2b9fdb814610711578063f2fde38b1461072457610251565b8063aced166114610614578063b1283e7714610629578063bd8f948114610649578063c04f31ff1461065e578063c29982381461067e57610251565b806396294178116100fd57806396294178146105815780639c60c85d146105a1578063a2a2d5bb146105c1578063a8431081146105e1578063abdb5ea81461060157610251565b80638c765e94146104f55780638da5cb5b1461050a578063928fe4771461051f578063929fe9a11461054c578063940ced9e1461056c57610251565b806353d6fd59116101d2578063715018a611610196578063715018a614610461578063748747e6146104765780637bc2c30e146104965780638129fc1c146104ab578063830cbbbd146104c05780638b95e335146104e057610251565b806353d6fd59146103b457806359086a5e146103d45780635b7f8251146103e75780635fbcdd1c146104075780636e8584fd1461043457610251565b8063375a7cba11610219578063375a7cba1461031257806339492e7d1461033457806349ba1b49146103545780634b8a3529146103745780635189e1101461039457610251565b806305308b9f1461025657806312348e96146102815780631488ca08146102a3578063186db48f146102d257806325ebf7b1146102f2575b600080fd5b34801561026257600080fd5b5061026b610744565b6040516102789190613561565b60405180910390f35b34801561028d57600080fd5b506102a161029c366004612f0f565b61074a565b005b3480156102af57600080fd5b506102c36102be366004612c01565b61081b565b60405161027893929190613055565b3480156102de57600080fd5b506102a16102ed366004612d94565b610840565b3480156102fe57600080fd5b506102a161030d366004612c01565b610999565b34801561031e57600080fd5b50610327610b21565b6040516102789190612ffd565b34801561034057600080fd5b506102a161034f366004612c40565b610b83565b34801561036057600080fd5b506102a161036f366004612e9a565b610d34565b34801561038057600080fd5b506102a161038f366004612d69565b610de5565b3480156103a057600080fd5b506103276103af366004612c01565b610fb5565b3480156103c057600080fd5b506102a16103cf366004612d3c565b61102b565b6102a16103e2366004612cfc565b6110ca565b3480156103f357600080fd5b506102a1610402366004612c01565b6111f3565b34801561041357600080fd5b50610427610422366004612f0f565b611288565b6040516102789190612f3f565b34801561044057600080fd5b5061045461044f366004612c01565b6112af565b604051610278919061353e565b34801561046d57600080fd5b506102a16112fe565b34801561048257600080fd5b506102a1610491366004612c01565b611387565b3480156104a257600080fd5b5061042761141c565b3480156104b757600080fd5b506102a161142b565b3480156104cc57600080fd5b5061026b6104db366004612d69565b6114b5565b3480156104ec57600080fd5b506104276115e0565b34801561050157600080fd5b5061026b6115f8565b34801561051657600080fd5b506104276115fe565b34801561052b57600080fd5b5061053f61053a366004612c74565b61160d565b604051610278919061304a565b34801561055857600080fd5b5061053f610567366004612c74565b61162d565b34801561057857600080fd5b5061042761165d565b34801561058d57600080fd5b5061026b61059c366004612d69565b61166c565b3480156105ad57600080fd5b506102a16105bc366004612c01565b6116d7565b3480156105cd57600080fd5b506104276105dc366004612d69565b61176c565b3480156105ed57600080fd5b506102a16105fc366004612f0f565b6117a1565b6102a161060f366004612d69565b611823565b34801561062057600080fd5b506104276118df565b34801561063557600080fd5b50610427610644366004612f0f565b6118ee565b34801561065557600080fd5b506103276118fb565b34801561066a57600080fd5b506102a1610679366004612d69565b61195b565b34801561068a57600080fd5b506102a1610699366004612dfd565b611b0a565b3480156106aa57600080fd5b5061053f6106b9366004612c01565b611b3f565b3480156106ca57600080fd5b506102a16106d9366004612c01565b611b5d565b6102a16106ec366004612cac565b611e18565b3480156106fd57600080fd5b506102a161070c366004612c01565b612071565b61026b61071f366004612d69565b6122b4565b34801561073057600080fd5b506102a161073f366004612c01565b612418565b609d5481565b6098546001600160a01b031633148061077b57506107666115fe565b6001600160a01b0316336001600160a01b0316145b6107a05760405162461bcd60e51b8152600401610797906131ea565b60405180910390fd5b66b1a2bc2ec5000081101580156107bf5750670c7d713b49da00008111155b6107db5760405162461bcd60e51b81526004016107979061306d565b609d8190556040517fd88469f5aa8525dce9ae07fa2d8df83e2ec766fc060483b66a0082ff36d6582d90610810908390613561565b60405180910390a150565b609c6020526000908152604090208054600182015460029092015460ff909116919083565b6098546001600160a01b0316331480610871575061085c6115fe565b6001600160a01b0316336001600160a01b0316145b61088d5760405162461bcd60e51b8152600401610797906131ea565b821580159061089b57508281145b6108b75760405162461bcd60e51b815260040161079790613512565b60005b83811015610992578282828181106108ce57fe5b90506020020135609c60008787858181106108e557fe5b90506020020160208101906108fa9190612c01565b6001600160a01b0316815260208101919091526040016000206001015584848281811061092357fe5b90506020020160208101906109389190612c01565b6001600160a01b03167f84d2db42497fc6f1882756be420935d982025ad8a2a903dfb83638a09e49a77584848481811061096e57fe5b905060200201356040516109829190613561565b60405180910390a26001016108ba565b5050505050565b6098546001600160a01b03163314806109ca57506109b56115fe565b6001600160a01b0316336001600160a01b0316145b6109e65760405162461bcd60e51b8152600401610797906131ea565b6001600160a01b0381166000908152609f602052604090205415610a1c5760405162461bcd60e51b81526004016107979061331a565b60a1546060906000190167ffffffffffffffff81118015610a3c57600080fd5b50604051908082528060200260200182016040528015610a66578160200160208202803683370190505b5090506000805b60a154811015610b0757836001600160a01b031660a18281548110610a8e57fe5b6000918252602090912001546001600160a01b031614610aff5760a18181548110610ab557fe5b600091825260209091200154835160018401936001600160a01b039092169185918110610ade57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101610a6d565b508151610b1b9060a1906020850190612ae5565b50505050565b6060609b805480602002602001604051908101604052809291908181526020018280548015610b7957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b5b575b5050505050905090565b6098546001600160a01b0316331480610bb45750610b9f6115fe565b6001600160a01b0316336001600160a01b0316145b610bd05760405162461bcd60e51b8152600401610797906131ea565b6001600160a01b0383166000908152609c602052604090205460ff1615610c095760405162461bcd60e51b8152600401610797906134db565b60005b609b54811015610c6857836001600160a01b0316609b8281548110610c2d57fe5b6000918252602090912001546001600160a01b03161415610c605760405162461bcd60e51b8152600401610797906134db565b600101610c0c565b5060408051606081018252600180825260208083018681528385018681526001600160a01b0389166000818152609c9094528684209551865460ff191690151517865591518585015551600290940193909355609b8054928301815590527fbba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc3490180546001600160a01b0319169091179055517fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f90610d27908590612f3f565b60405180910390a1505050565b610d3c6124d9565b6001600160a01b0316610d4d6115fe565b6001600160a01b031614610d735760405162461bcd60e51b815260040161079790613351565b6066805460ff19168215801591909117909155610db8576040517f508560e15717a4e9058b9a19d806cb679004a1bd953376f71fda71c141e5dc5390600090a1610de2565b6040517fa2927d972f7cfc5ff8b7ad79f9adf0bdb885d0e569f40d0037df2e1299616ae090600090a15b50565b6001600160a01b0382166000908152609c6020526040902054829060ff16610e1f5760405162461bcd60e51b815260040161079790613121565b610e2983336124dd565b60995460405163368f515360e21b81526001600160a01b039091169063da3d454c90610e5d90869033908790600401612f53565b602060405180830381600087803b158015610e7757600080fd5b505af1158015610e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eaf9190612eb6565b610ecb5760405162461bcd60e51b8152600401610797906132b6565b604051634b8a352960e01b81526001600160a01b03841690634b8a352990610ef99033908690600401612f77565b602060405180830381600087803b158015610f1357600080fd5b505af1158015610f27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4b9190612f27565b50609a546040516359debb6760e11b81526001600160a01b039091169063b3bd76ce90610f7e9086903390600401612f90565b600060405180830381600087803b158015610f9857600080fd5b505af1158015610fac573d6000803e3d6000fd5b50505050505050565b6001600160a01b0381166000908152609f602090815260409182902080548351818402810184019094528084526060939283018282801561101f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611001575b50505050509050919050565b6110336124d9565b6001600160a01b03166110446115fe565b6001600160a01b03161461106a5760405162461bcd60e51b815260040161079790613351565b6001600160a01b03821660008181526065602052604090819020805460ff1916841515179055517fa54714518c5d275fdcd3d2a461e4858e4e8cb04fb93cd0bca9d6d34115f26440906110be90849061304a565b60405180910390a25050565b6001600160a01b0383166000908152609c6020526040902054839060ff166111045760405162461bcd60e51b815260040161079790613121565b604051632c84352f60e11b81526001600160a01b038516906359086a5e90349061113690339088908890600401612f53565b6020604051808303818588803b15801561114f57600080fd5b505af1158015611163573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906111889190612f27565b50609a546040516359debb6760e11b81526001600160a01b039091169063b3bd76ce906111bb9087908790600401612f90565b600060405180830381600087803b1580156111d557600080fd5b505af11580156111e9573d6000803e3d6000fd5b5050505050505050565b6098546001600160a01b0316331480611224575061120f6115fe565b6001600160a01b0316336001600160a01b0316145b6112405760405162461bcd60e51b8152600401610797906131ea565b6001600160a01b0381166112665760405162461bcd60e51b815260040161079790613386565b609a80546001600160a01b0319166001600160a01b0392909216919091179055565b60a1818154811061129557fe5b6000918252602090912001546001600160a01b0316905081565b6112b7612b4a565b506001600160a01b03166000908152609c60209081526040918290208251606081018452815460ff1615158152600182015492810192909252600201549181019190915290565b6113066124d9565b6001600160a01b03166113176115fe565b6001600160a01b03161461133d5760405162461bcd60e51b815260040161079790613351565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b6098546001600160a01b03163314806113b857506113a36115fe565b6001600160a01b0316336001600160a01b0316145b6113d45760405162461bcd60e51b8152600401610797906131ea565b6001600160a01b0381166113fa5760405162461bcd60e51b8152600401610797906132e3565b609880546001600160a01b0319166001600160a01b0392909216919091179055565b609a546001600160a01b031681565b600054610100900460ff16806114445750611444612643565b80611452575060005460ff16155b61146e5760405162461bcd60e51b815260040161079790613231565b600054610100900460ff16158015611499576000805460ff1961ff0019909116610100171660011790555b6114a1612654565b8015610de2576000805461ff001916905550565b6001600160a01b0382166000908152609c6020526040812054839060ff166114ef5760405162461bcd60e51b815260040161079790613121565b60405163830cbbbd60e01b81526000906001600160a01b0386169063830cbbbd906115209033908890600401612f77565b602060405180830381600087803b15801561153a57600080fd5b505af115801561154e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115729190612f27565b609a54604051639ba24c9b60e01b81529192506001600160a01b031690639ba24c9b906115a59088903390600401612f90565b600060405180830381600087803b1580156115bf57600080fd5b505af11580156115d3573d6000803e3d6000fd5b5092979650505050505050565b7320e5e35ba29dc3b540a1aee781d0814d5c77bce681565b609e5481565b6033546001600160a01b031690565b60a060209081526000928352604080842090915290825290205460ff1681565b6001600160a01b03808216600090815260a0602090815260408083209386168352929052205460ff165b92915050565b6099546001600160a01b031681565b6001600160a01b0382166000908152609c6020526040812054839060ff166116a65760405162461bcd60e51b815260040161079790613121565b6040516312c5282f60e31b81526000906001600160a01b038616906396294178906115209033908890600401612f77565b6098546001600160a01b031633148061170857506116f36115fe565b6001600160a01b0316336001600160a01b0316145b6117245760405162461bcd60e51b8152600401610797906131ea565b6001600160a01b03811661174a5760405162461bcd60e51b8152600401610797906133c8565b609980546001600160a01b0319166001600160a01b0392909216919091179055565b609f602052816000526040600020818154811061178557fe5b6000918252602090912001546001600160a01b03169150829050565b6098546001600160a01b03163314806117d257506117bd6115fe565b6001600160a01b0316336001600160a01b0316145b6117ee5760405162461bcd60e51b8152600401610797906131ea565b609e8190556040517f6791c9b68799eda502f8f7808e4ab556a632237eea58a66c4f7e4e6f94574d0d90610810908390613561565b6001600160a01b0382166000908152609c6020526040902054829060ff1661185d5760405162461bcd60e51b815260040161079790613121565b60405163157b6bd560e31b81526001600160a01b0384169063abdb5ea890349061188d9033908790600401612f77565b6020604051808303818588803b1580156118a657600080fd5b505af11580156118ba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610f4b9190612f27565b6098546001600160a01b031681565b609b818154811061129557fe5b606060a1805480602002602001604051908101604052809291908181526020018280548015610b79576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610b5b575050505050905090565b6098546001600160a01b031633148061198c57506119776115fe565b6001600160a01b0316336001600160a01b0316145b6119a85760405162461bcd60e51b8152600401610797906131ea565b6001600160a01b0382166000908152609c6020526040902054829060ff166119e25760405162461bcd60e51b815260040161079790613121565b670c7d713b49da0000821115611a0a5760405162461bcd60e51b815260040161079790613186565b8115801590611a9d575060405163fc57d4df60e01b81527320e5e35ba29dc3b540a1aee781d0814d5c77bce69063fc57d4df90611a4b908690600401612f3f565b60206040518083038186803b158015611a6357600080fd5b505afa158015611a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9b9190612f27565b155b15611aba5760405162461bcd60e51b81526004016107979061314f565b6001600160a01b0383166000908152609c602052604090819020600201839055517f275d6207ccd4271a12c584febf2bcf32254205dfb4639ce1a9184d2e2609e2d090610d279085908590612f77565b60005b8151811015611b3b57611b33828281518110611b2557fe5b6020026020010151336124dd565b600101611b0d565b5050565b6001600160a01b031660009081526065602052604090205460ff1690565b6098546001600160a01b0316331480611b8e5750611b796115fe565b6001600160a01b0316336001600160a01b0316145b611baa5760405162461bcd60e51b8152600401610797906131ea565b6001600160a01b0381166000908152609c602052604090205460ff16611be25760405162461bcd60e51b8152600401610797906133fd565b806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c1b57600080fd5b505afa158015611c2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c539190612f27565b158015611cce5750806001600160a01b0316638285ef406040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9457600080fd5b505afa158015611ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ccc9190612f27565b155b611cea5760405162461bcd60e51b8152600401610797906134a4565b609b546060906000190167ffffffffffffffff81118015611d0a57600080fd5b50604051908082528060200260200182016040528015611d34578160200160208202803683370190505b5090506000805b609b54811015611dd557836001600160a01b0316609b8281548110611d5c57fe5b6000918252602090912001546001600160a01b031614611dcd57609b8181548110611d8357fe5b600091825260209091200154835160018401936001600160a01b039092169185918110611dac57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101611d3b565b508151611de990609b906020850190612ae5565b5050506001600160a01b03166000908152609c60205260408120805460ff191681556001810182905560020155565b6001600160a01b0384166000908152609c602052604090205460ff168015611e5857506001600160a01b0383166000908152609c602052604090205460ff165b611e745760405162461bcd60e51b815260040161079790613121565b609954609d546040516312e8123160e11b81526001600160a01b03909216916325d0246291611eac9188918791879190600401612fd4565b602060405180830381600087803b158015611ec657600080fd5b505af1158015611eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efe9190612eb6565b611f1a5760405162461bcd60e51b81526004016107979061346d565b6000846001600160a01b031663e61604cf34863387876040518663ffffffff1660e01b8152600401611f4f9493929190612faa565b6020604051808303818588803b158015611f6857600080fd5b505af1158015611f7c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611fa19190612f27565b60405163b2a02ff160e01b81529091506001600160a01b0385169063b2a02ff190611fd490339087908690600401612f53565b600060405180830381600087803b158015611fee57600080fd5b505af1158015612002573d6000803e3d6000fd5b5050609a546040516359debb6760e11b81526001600160a01b03909116925063b3bd76ce91506120389088908790600401612f90565b600060405180830381600087803b15801561205257600080fd5b505af1158015612066573d6000803e3d6000fd5b505050505050505050565b6001600160a01b0381166000908152609c6020526040902054819060ff166120ab5760405162461bcd60e51b815260040161079790613121565b6001600160a01b038216600090815260a060209081526040808320338452909152902054829060ff166120f05760405162461bcd60e51b8152600401610797906130a4565b6120f8612b6d565b60405163497d274760e11b81526001600160a01b038516906392fa4e8e90612124903390600401612f3f565b606060405180830381600087803b15801561213e57600080fd5b505af1158015612152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121769190612ed2565b9050806020015160001461219c5760405162461bcd60e51b81526004016107979061342c565b609954815160405163eabe7d9160e01b81526001600160a01b039092169163eabe7d91916121d09188913391600401612f53565b602060405180830381600087803b1580156121ea57600080fd5b505af11580156121fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122229190612eb6565b61223e5760405162461bcd60e51b8152600401610797906131bd565b6001600160a01b038416600090815260a060209081526040808320338085529252909120805460ff191690556122759085906126f6565b7fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d84336040516122a6929190612f90565b60405180910390a150505050565b6001600160a01b0382166000908152609c6020526040812054839060ff166122ee5760405162461bcd60e51b815260040161079790613121565b73ae13d989dac2f0debff460ac112a837c89baa7cd6001600160a01b0316846001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561234557600080fd5b505afa158015612359573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237d9190612c24565b6001600160a01b0316146123915782612393565b345b92506000846001600160a01b031663f2b9fdb83433876040518463ffffffff1660e01b81526004016123c6929190612f77565b6020604051808303818588803b1580156123df57600080fd5b505af11580156123f3573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906115729190612f27565b6124206124d9565b6001600160a01b03166124316115fe565b6001600160a01b0316146124575760405162461bcd60e51b815260040161079790613351565b6001600160a01b03811661247d5760405162461bcd60e51b8152600401610797906130db565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b6001600160a01b0382166000908152609c6020526040902054829060ff166125175760405162461bcd60e51b815260040161079790613121565b6001600160a01b03808416600090815260a0602090815260408083209386168352929052205460ff1661263e576001600160a01b03808416600090815260a0602090815260408083209386168352928152828220805460ff19166001179055609f905220546125cc5760a180546001810182556000919091527faadc37b8ba5645e62f4546802db221593a94729ccbfc5a97d01365a88f6498780180546001600160a01b0319166001600160a01b0384161790555b6001600160a01b038281166000908152609f602090815260408083208054600181018255908452919092200180546001600160a01b03191692861692909217909155517f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a590610d279085908590612f90565b505050565b600061264e30612895565b15905090565b600054610100900460ff168061266d575061266d612643565b8061267b575060005460ff16155b6126975760405162461bcd60e51b815260040161079790613231565b600054610100900460ff161580156126c2576000805460ff1961ff0019909116610100171660011790555b6126ca61289b565b6706f05b59d3b20000609d55670f43fc2c04ee0000609e558015610de2576000805461ff001916905550565b6001600160a01b0381166000908152609f602052604090205461272b5760405162461bcd60e51b81526004016107979061327f565b6001600160a01b0381166000908152609f60205260409020546060906000190167ffffffffffffffff8111801561276157600080fd5b5060405190808252806020026020018201604052801561278b578160200160208202803683370190505b5090506000805b6001600160a01b0384166000908152609f602052604090205481101561286b576001600160a01b038481166000908152609f60205260409020805491871691839081106127db57fe5b6000918252602090912001546001600160a01b031614612863576001600160a01b0384166000908152609f6020526040902080548290811061281957fe5b600091825260209091200154835160018401936001600160a01b03909216918591811061284257fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101612792565b506001600160a01b0383166000908152609f60209081526040909120835161099292850190612ae5565b3b151590565b600054610100900460ff16806128b457506128b4612643565b806128c2575060005460ff16155b6128de5760405162461bcd60e51b815260040161079790613231565b600054610100900460ff16158015612909576000805460ff1961ff0019909116610100171660011790555b6114a1600054610100900460ff16806129255750612925612643565b80612933575060005460ff16155b61294f5760405162461bcd60e51b815260040161079790613231565b600054610100900460ff1615801561297a576000805460ff1961ff0019909116610100171660011790555b61298261298a565b6114a1612a0b565b600054610100900460ff16806129a357506129a3612643565b806129b1575060005460ff16155b6129cd5760405162461bcd60e51b815260040161079790613231565b600054610100900460ff161580156114a1576000805460ff1961ff0019909116610100171660011790558015610de2576000805461ff001916905550565b600054610100900460ff1680612a245750612a24612643565b80612a32575060005460ff16155b612a4e5760405162461bcd60e51b815260040161079790613231565b600054610100900460ff16158015612a79576000805460ff1961ff0019909116610100171660011790555b6000612a836124d9565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015610de2576000805461ff001916905550565b828054828255906000526020600020908101928215612b3a579160200282015b82811115612b3a57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612b05565b50612b46929150612b8e565b5090565b604051806060016040528060001515815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b5b80821115612b465780546001600160a01b0319168155600101612b8f565b8035611657816135b1565b60008083601f840112612bc9578182fd5b50813567ffffffffffffffff811115612be0578182fd5b6020830191508360208083028501011115612bfa57600080fd5b9250929050565b600060208284031215612c12578081fd5b8135612c1d816135b1565b9392505050565b600060208284031215612c35578081fd5b8151612c1d816135b1565b600080600060608486031215612c54578182fd5b8335612c5f816135b1565b95602085013595506040909401359392505050565b60008060408385031215612c86578182fd5b8235612c91816135b1565b91506020830135612ca1816135b1565b809150509250929050565b60008060008060808587031215612cc1578081fd5b8435612ccc816135b1565b93506020850135612cdc816135b1565b92506040850135612cec816135b1565b9396929550929360600135925050565b600080600060608486031215612d10578283fd5b8335612d1b816135b1565b92506020840135612d2b816135b1565b929592945050506040919091013590565b60008060408385031215612d4e578182fd5b8235612d59816135b1565b91506020830135612ca1816135c6565b60008060408385031215612d7b578182fd5b8235612d86816135b1565b946020939093013593505050565b60008060008060408587031215612da9578384fd5b843567ffffffffffffffff80821115612dc0578586fd5b612dcc88838901612bb8565b90965094506020870135915080821115612de4578384fd5b50612df187828801612bb8565b95989497509550505050565b60006020808385031215612e0f578182fd5b823567ffffffffffffffff811115612e25578283fd5b8301601f81018513612e35578283fd5b8035612e48612e4382613591565b61356a565b8181528381019083850185840285018601891015612e64578687fd5b8694505b83851015612e8e57612e7a8982612bad565b835260019490940193918501918501612e68565b50979650505050505050565b600060208284031215612eab578081fd5b8135612c1d816135c6565b600060208284031215612ec7578081fd5b8151612c1d816135c6565b600060608284031215612ee3578081fd5b612eed606061356a565b8251815260208301516020820152604083015160408201528091505092915050565b600060208284031215612f20578081fd5b5035919050565b600060208284031215612f38578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6020808252825182820181905260009190848201906040850190845b8181101561303e5783516001600160a01b031683529284019291840191600101613019565b50909695505050505050565b901515815260200190565b92151583526020830191909152604082015260600190565b6020808252601a908201527f516f72653a20696e76616c696420636c6f736520666163746f72000000000000604082015260600190565b60208082526017908201527f516f72653a206d75737420656e746572206d61726b6574000000000000000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b602080825260149082015273145bdc994e881a5b9d985b1a59081b585c9ad95d60621b604082015260600190565b6020808252601e908201527f516f72653a20696e76616c696420756e6465726c79696e672070726963650000604082015260600190565b6020808252601f908201527f516f72653a20696e76616c696420636f6c6c61746572616c20666163746f7200604082015260600190565b602080825260139082015272516f72653a2063616e6e6f742072656465656d60681b604082015260600190565b60208082526027908201527f516f72653a2063616c6c6572206973206e6f7420746865206f776e6572206f726040820152661035b2b2b832b960c91b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252601c908201527f516f72653a2063616e6e6f7420706f702075736572206d61726b657400000000604082015260600190565b602080825260139082015272516f72653a2063616e6e6f7420626f72726f7760681b604082015260600190565b6020808252601c908201527f516f72653a20696e76616c6964206b6565706572206164647265737300000000604082015260600190565b60208082526018908201527f516f72653a2063616e6e6f742072656d6f766520757365720000000000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526022908201527f516f72653a20696e76616c696420714469737472696275746f72206164647265604082015261737360f01b606082015260800190565b6020808252818101527f516f72653a20696e76616c6964207156616c696461746f722061646472657373604082015260600190565b602080825260159082015274145bdc994e881d5b9b1a5cdd1959081b585c9ad95d605a1b604082015260600190565b60208082526021908201527f516f72653a20626f72726f772062616c616e6365206d757374206265207a65726040820152606f60f81b606082015260800190565b6020808252601d908201527f516f72653a2063616e6e6f74206c697175696461746520626f72726f77000000604082015260600190565b6020808252601a908201527f516f72653a2063616e6e6f742072656d6f7665206d61726b6574000000000000604082015260600190565b6020808252601b908201527f516f72653a20616c7265616479206c6973746564206d61726b65740000000000604082015260600190565b602080825260129082015271516f72653a20696e76616c6964206461746160701b604082015260600190565b815115158152602080830151908201526040918201519181019190915260600190565b90815260200190565b60405181810167ffffffffffffffff8111828210171561358957600080fd5b604052919050565b600067ffffffffffffffff8211156135a7578081fd5b5060209081020190565b6001600160a01b0381168114610de257600080fd5b8015158114610de257600080fdfea2646970667358221220c13f2f83468753e578736ea77617d0865397058f45e85c6567a7cbf4c0edccb064736f6c634300060c0033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading