ETH Price: $3,753.94 (-1.95%)
Gas: 9 Gwei

Token

 

Overview

Max Total Supply

0

Holders

0

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Core

Compiler Version
v0.6.6+commit.6c089d02

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU AGPLv3 license
File 1 of 20 : Core.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/proxy/Initializable.sol";
import "./Permissions.sol";
import "./ICore.sol";
import "../token/Fei.sol";
import "../dao/Tribe.sol";

/// @title Source of truth for Fei Protocol
/// @author Fei Protocol
/// @notice maintains roles, access control, fei, tribe, genesisGroup, and the TRIBE treasury
contract Core is ICore, Permissions, Initializable {

    /// @notice the address of the FEI contract
    IFei public override fei;
    
    /// @notice the address of the TRIBE contract
    IERC20 public override tribe;

    /// @notice the address of the GenesisGroup contract
    address public override genesisGroup;
    /// @notice determines whether in genesis period or not
    bool public override hasGenesisGroupCompleted;

    function init() external override initializer {
        _setupGovernor(msg.sender);
        
        Fei _fei = new Fei(address(this));
        _setFei(address(_fei));

        Tribe _tribe = new Tribe(address(this), msg.sender);
        _setTribe(address(_tribe));
    }

    /// @notice sets Fei address to a new address
    /// @param token new fei address
    function setFei(address token) external override onlyGovernor {
        _setFei(token);
    }

    /// @notice sets Tribe address to a new address
    /// @param token new tribe address
    function setTribe(address token) external override onlyGovernor {
        _setTribe(token);
    }

    /// @notice sets Genesis Group address
    /// @param _genesisGroup new genesis group address
    function setGenesisGroup(address _genesisGroup)
        external
        override
        onlyGovernor
    {
        genesisGroup = _genesisGroup;
        emit GenesisGroupUpdate(_genesisGroup);
    }

    /// @notice sends TRIBE tokens from treasury to an address
    /// @param to the address to send TRIBE to
    /// @param amount the amount of TRIBE to send
    function allocateTribe(address to, uint256 amount)
        external
        override
        onlyGovernor
    {
        IERC20 _tribe = tribe;
        require(
            _tribe.balanceOf(address(this)) >= amount,
            "Core: Not enough Tribe"
        );

        _tribe.transfer(to, amount);

        emit TribeAllocation(to, amount);
    }

    /// @notice marks the end of the genesis period
    /// @dev can only be called once
    function completeGenesisGroup() external override {
        require(
            !hasGenesisGroupCompleted,
            "Core: Genesis Group already complete"
        );
        require(
            msg.sender == genesisGroup,
            "Core: Caller is not Genesis Group"
        );

        hasGenesisGroupCompleted = true;

        // solhint-disable-next-line not-rely-on-time
        emit GenesisPeriodComplete(block.timestamp);
    }

    function _setFei(address token) internal {
        fei = IFei(token);
        emit FeiUpdate(token);
    }

    function _setTribe(address token) internal {
        tribe = IERC20(token);
        emit TribeUpdate(token);
    }
}

File 2 of 20 : Permissions.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "./IPermissions.sol";

/// @title Access control module for Core
/// @author Fei Protocol
contract Permissions is IPermissions, AccessControl {
    bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PCV_CONTROLLER_ROLE = keccak256("PCV_CONTROLLER_ROLE");
    bytes32 public constant GOVERN_ROLE = keccak256("GOVERN_ROLE");
    bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");

    constructor() public {
        // Appointed as a governor so guardian can have indirect access to revoke ability
        _setupGovernor(address(this));

        _setRoleAdmin(MINTER_ROLE, GOVERN_ROLE);
        _setRoleAdmin(BURNER_ROLE, GOVERN_ROLE);
        _setRoleAdmin(PCV_CONTROLLER_ROLE, GOVERN_ROLE);
        _setRoleAdmin(GOVERN_ROLE, GOVERN_ROLE);
        _setRoleAdmin(GUARDIAN_ROLE, GOVERN_ROLE);
    }

    modifier onlyGovernor() {
        require(
            isGovernor(msg.sender),
            "Permissions: Caller is not a governor"
        );
        _;
    }

    modifier onlyGuardian() {
        require(isGuardian(msg.sender), "Permissions: Caller is not a guardian");
        _;
    }

    /// @notice creates a new role to be maintained
    /// @param role the new role id
    /// @param adminRole the admin role id for `role`
    /// @dev can also be used to update admin of existing role
    function createRole(bytes32 role, bytes32 adminRole)
        external
        override
        onlyGovernor
    {
        _setRoleAdmin(role, adminRole);
    }

    /// @notice grants minter role to address
    /// @param minter new minter
    function grantMinter(address minter) external override onlyGovernor {
        grantRole(MINTER_ROLE, minter);
    }

    /// @notice grants burner role to address
    /// @param burner new burner
    function grantBurner(address burner) external override onlyGovernor {
        grantRole(BURNER_ROLE, burner);
    }

    /// @notice grants controller role to address
    /// @param pcvController new controller
    function grantPCVController(address pcvController)
        external
        override
        onlyGovernor
    {
        grantRole(PCV_CONTROLLER_ROLE, pcvController);
    }

    /// @notice grants governor role to address
    /// @param governor new governor
    function grantGovernor(address governor) external override onlyGovernor {
        grantRole(GOVERN_ROLE, governor);
    }

    /// @notice grants guardian role to address
    /// @param guardian new guardian
    function grantGuardian(address guardian) external override onlyGovernor {
        grantRole(GUARDIAN_ROLE, guardian);
    }

    /// @notice revokes minter role from address
    /// @param minter ex minter
    function revokeMinter(address minter) external override onlyGovernor {
        revokeRole(MINTER_ROLE, minter);
    }

    /// @notice revokes burner role from address
    /// @param burner ex burner
    function revokeBurner(address burner) external override onlyGovernor {
        revokeRole(BURNER_ROLE, burner);
    }

    /// @notice revokes pcvController role from address
    /// @param pcvController ex pcvController
    function revokePCVController(address pcvController)
        external
        override
        onlyGovernor
    {
        revokeRole(PCV_CONTROLLER_ROLE, pcvController);
    }

    /// @notice revokes governor role from address
    /// @param governor ex governor
    function revokeGovernor(address governor) external override onlyGovernor {
        revokeRole(GOVERN_ROLE, governor);
    }

    /// @notice revokes guardian role from address
    /// @param guardian ex guardian
    function revokeGuardian(address guardian) external override onlyGovernor {
        revokeRole(GUARDIAN_ROLE, guardian);
    }

    /// @notice revokes a role from address
    /// @param role the role to revoke
    /// @param account the address to revoke the role from
    function revokeOverride(bytes32 role, address account)
        external
        override
        onlyGuardian
    {
        require(role != GOVERN_ROLE, "Permissions: Guardian cannot revoke governor");

        // External call because this contract is appointed as a governor and has access to revoke
        this.revokeRole(role, account);
    }


    /// @notice checks if address is a minter
    /// @param _address address to check
    /// @return true _address is a minter
    function isMinter(address _address) external view override returns (bool) {
        return hasRole(MINTER_ROLE, _address);
    }

    /// @notice checks if address is a burner
    /// @param _address address to check
    /// @return true _address is a burner
    function isBurner(address _address) external view override returns (bool) {
        return hasRole(BURNER_ROLE, _address);
    }

    /// @notice checks if address is a controller
    /// @param _address address to check
    /// @return true _address is a controller
    function isPCVController(address _address)
        external
        view
        override
        returns (bool)
    {
        return hasRole(PCV_CONTROLLER_ROLE, _address);
    }

    /// @notice checks if address is a governor
    /// @param _address address to check
    /// @return true _address is a governor
    // only virtual for testing mock override
    function isGovernor(address _address)
        public
        view
        virtual
        override
        returns (bool)
    {
        return hasRole(GOVERN_ROLE, _address);
    }

    /// @notice checks if address is a guardian
    /// @param _address address to check
    /// @return true _address is a guardian
    function isGuardian(address _address) public view override returns (bool) {
        return hasRole(GUARDIAN_ROLE, _address);
    }

    function _setupGovernor(address governor) internal {
        _setupRole(GOVERN_ROLE, governor);
    }
}

File 3 of 20 : IPermissions.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

/// @title Permissions interface
/// @author Fei Protocol
interface IPermissions {
    // ----------- Governor only state changing api -----------

    function createRole(bytes32 role, bytes32 adminRole) external;

    function grantMinter(address minter) external;

    function grantBurner(address burner) external;

    function grantPCVController(address pcvController) external;

    function grantGovernor(address governor) external;

    function grantGuardian(address guardian) external;

    function revokeMinter(address minter) external;

    function revokeBurner(address burner) external;

    function revokePCVController(address pcvController) external;

    function revokeGovernor(address governor) external;

    function revokeGuardian(address guardian) external;

    // ----------- Revoker only state changing api -----------

    function revokeOverride(bytes32 role, address account) external;

    // ----------- Getters -----------

    function isBurner(address _address) external view returns (bool);

    function isMinter(address _address) external view returns (bool);

    function isGovernor(address _address) external view returns (bool);

    function isGuardian(address _address) external view returns (bool);

    function isPCVController(address _address) external view returns (bool);
}

File 4 of 20 : ICore.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./IPermissions.sol";
import "../token/IFei.sol";

/// @title Core Interface
/// @author Fei Protocol
interface ICore is IPermissions {
    // ----------- Events -----------

    event FeiUpdate(address indexed _fei);
    event TribeUpdate(address indexed _tribe);
    event GenesisGroupUpdate(address indexed _genesisGroup);
    event TribeAllocation(address indexed _to, uint256 _amount);
    event GenesisPeriodComplete(uint256 _timestamp);

    // ----------- Governor only state changing api -----------

    function init() external;

    // ----------- Governor only state changing api -----------

    function setFei(address token) external;

    function setTribe(address token) external;

    function setGenesisGroup(address _genesisGroup) external;

    function allocateTribe(address to, uint256 amount) external;

    // ----------- Genesis Group only state changing api -----------

    function completeGenesisGroup() external;

    // ----------- Getters -----------

    function fei() external view returns (IFei);

    function tribe() external view returns (IERC20);

    function genesisGroup() external view returns (address);

    function hasGenesisGroupCompleted() external view returns (bool);
}

File 5 of 20 : IFei.sol
pragma solidity ^0.6.2;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/// @title FEI stablecoin interface
/// @author Fei Protocol
interface IFei is IERC20 {
    // ----------- Events -----------

    event Minting(
        address indexed _to,
        address indexed _minter,
        uint256 _amount
    );

    event Burning(
        address indexed _to,
        address indexed _burner,
        uint256 _amount
    );

    event IncentiveContractUpdate(
        address indexed _incentivized,
        address indexed _incentiveContract
    );

    // ----------- State changing api -----------

    function burn(uint256 amount) external;

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    // ----------- Burner only state changing api -----------

    function burnFrom(address account, uint256 amount) external;

    // ----------- Minter only state changing api -----------

    function mint(address account, uint256 amount) external;

    // ----------- Governor only state changing api -----------

    function setIncentiveContract(address account, address incentive) external;

    // ----------- Getters -----------

    function incentiveContract(address account) external view returns (address);
}

File 6 of 20 : Fei.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./IIncentive.sol";
import "./IFei.sol";
import "../refs/CoreRef.sol";

/// @title FEI stablecoin
/// @author Fei Protocol
contract Fei is IFei, ERC20Burnable, CoreRef {
    
    /// @notice get associated incentive contract, 0 address if N/A
    mapping(address => address) public override incentiveContract;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 public DOMAIN_SEPARATOR;
    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 public constant PERMIT_TYPEHASH =
        0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
    mapping(address => uint256) public nonces;

    /// @notice Fei token constructor
    /// @param core Fei Core address to reference
    constructor(address core) public ERC20("Fei USD", "FEI") CoreRef(core) {
        uint256 chainId;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256(
                    "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
                ),
                keccak256(bytes(name())),
                keccak256(bytes("1")),
                chainId,
                address(this)
            )
        );
    }

    /// @param account the account to incentivize
    /// @param incentive the associated incentive contract
    function setIncentiveContract(address account, address incentive)
        external
        override
        onlyGovernor
    {
        incentiveContract[account] = incentive;
        emit IncentiveContractUpdate(account, incentive);
    }

    /// @notice mint FEI tokens
    /// @param account the account to mint to
    /// @param amount the amount to mint
    function mint(address account, uint256 amount)
        external
        override
        onlyMinter
        whenNotPaused
    {
        _mint(account, amount);
        emit Minting(account, msg.sender, amount);
    }

    /// @notice burn FEI tokens from caller
    /// @param amount the amount to burn
    function burn(uint256 amount) public override(IFei, ERC20Burnable) {
        super.burn(amount);
        emit Burning(msg.sender, msg.sender, amount);
    }

    /// @notice burn FEI tokens from specified account
    /// @param account the account to burn from
    /// @param amount the amount to burn
    function burnFrom(address account, uint256 amount)
        public
        override(IFei, ERC20Burnable)
        onlyBurner
        whenNotPaused
    {
        _burn(account, amount);
        emit Burning(account, msg.sender, amount);
    }

    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal override {
        super._transfer(sender, recipient, amount);
        _checkAndApplyIncentives(sender, recipient, amount);
    }

    function _checkAndApplyIncentives(
        address sender,
        address recipient,
        uint256 amount
    ) internal {
        // incentive on sender
        address senderIncentive = incentiveContract[sender];
        if (senderIncentive != address(0)) {
            IIncentive(senderIncentive).incentivize(
                sender,
                recipient,
                msg.sender,
                amount
            );
        }

        // incentive on recipient
        address recipientIncentive = incentiveContract[recipient];
        if (recipientIncentive != address(0)) {
            IIncentive(recipientIncentive).incentivize(
                sender,
                recipient,
                msg.sender,
                amount
            );
        }

        // incentive on operator
        address operatorIncentive = incentiveContract[msg.sender];
        if (
            msg.sender != sender &&
            msg.sender != recipient &&
            operatorIncentive != address(0)
        ) {
            IIncentive(operatorIncentive).incentivize(
                sender,
                recipient,
                msg.sender,
                amount
            );
        }

        // all incentive, if active applies to every transfer
        address allIncentive = incentiveContract[address(0)];
        if (allIncentive != address(0)) {
            IIncentive(allIncentive).incentivize(
                sender,
                recipient,
                msg.sender,
                amount
            );
        }
    }

    /// @notice permit spending of FEI
    /// @param owner the FEI holder
    /// @param spender the approved operator
    /// @param value the amount approved
    /// @param deadline the deadline after which the approval is no longer valid
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external override {
        // solhint-disable-next-line not-rely-on-time
        require(deadline >= block.timestamp, "Fei: EXPIRED");
        bytes32 digest =
            keccak256(
                abi.encodePacked(
                    "\x19\x01",
                    DOMAIN_SEPARATOR,
                    keccak256(
                        abi.encode(
                            PERMIT_TYPEHASH,
                            owner,
                            spender,
                            value,
                            nonces[owner]++,
                            deadline
                        )
                    )
                )
            );
        address recoveredAddress = ecrecover(digest, v, r, s);
        require(
            recoveredAddress != address(0) && recoveredAddress == owner,
            "Fei: INVALID_SIGNATURE"
        );
        _approve(owner, spender, value);
    }
}

File 7 of 20 : IIncentive.sol
pragma solidity ^0.6.2;

/// @title incentive contract interface
/// @author Fei Protocol
/// @notice Called by FEI token contract when transferring with an incentivized address
/// @dev should be appointed as a Minter or Burner as needed
interface IIncentive {
    // ----------- Fei only state changing api -----------

    /// @notice apply incentives on transfer
    /// @param sender the sender address of the FEI
    /// @param receiver the receiver address of the FEI
    /// @param operator the operator (msg.sender) of the transfer
    /// @param amount the amount of FEI transferred
    function incentivize(
        address sender,
        address receiver,
        address operator,
        uint256 amount
    ) external;
}

File 8 of 20 : CoreRef.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./ICoreRef.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/utils/Address.sol";

/// @title A Reference to Core
/// @author Fei Protocol
/// @notice defines some modifiers and utilities around interacting with Core
abstract contract CoreRef is ICoreRef, Pausable {
    ICore private _core;

    /// @notice CoreRef constructor
    /// @param core Fei Core to reference
    constructor(address core) public {
        _core = ICore(core);
    }

    modifier ifMinterSelf() {
        if (_core.isMinter(address(this))) {
            _;
        }
    }

    modifier ifBurnerSelf() {
        if (_core.isBurner(address(this))) {
            _;
        }
    }

    modifier onlyMinter() {
        require(_core.isMinter(msg.sender), "CoreRef: Caller is not a minter");
        _;
    }

    modifier onlyBurner() {
        require(_core.isBurner(msg.sender), "CoreRef: Caller is not a burner");
        _;
    }

    modifier onlyPCVController() {
        require(
            _core.isPCVController(msg.sender),
            "CoreRef: Caller is not a PCV controller"
        );
        _;
    }

    modifier onlyGovernor() {
        require(
            _core.isGovernor(msg.sender),
            "CoreRef: Caller is not a governor"
        );
        _;
    }

    modifier onlyGuardianOrGovernor() {
        require(
            _core.isGovernor(msg.sender) ||
            _core.isGuardian(msg.sender),
            "CoreRef: Caller is not a guardian or governor"
        );
        _;
    }

    modifier onlyFei() {
        require(msg.sender == address(fei()), "CoreRef: Caller is not FEI");
        _;
    }

    modifier onlyGenesisGroup() {
        require(
            msg.sender == _core.genesisGroup(),
            "CoreRef: Caller is not GenesisGroup"
        );
        _;
    }

    modifier postGenesis() {
        require(
            _core.hasGenesisGroupCompleted(),
            "CoreRef: Still in Genesis Period"
        );
        _;
    }

    modifier nonContract() {
        require(!Address.isContract(msg.sender), "CoreRef: Caller is a contract");
        _;
    }

    /// @notice set new Core reference address
    /// @param core the new core address
    function setCore(address core) external override onlyGovernor {
        _core = ICore(core);
        emit CoreUpdate(core);
    }

    /// @notice set pausable methods to paused
    function pause() public override onlyGuardianOrGovernor {
        _pause();
    }

    /// @notice set pausable methods to unpaused
    function unpause() public override onlyGuardianOrGovernor {
        _unpause();
    }

    /// @notice address of the Core contract referenced
    /// @return ICore implementation address
    function core() public view override returns (ICore) {
        return _core;
    }

    /// @notice address of the Fei contract referenced by Core
    /// @return IFei implementation address
    function fei() public view override returns (IFei) {
        return _core.fei();
    }

    /// @notice address of the Tribe contract referenced by Core
    /// @return IERC20 implementation address
    function tribe() public view override returns (IERC20) {
        return _core.tribe();
    }

    /// @notice fei balance of contract
    /// @return fei amount held
    function feiBalance() public view override returns (uint256) {
        return fei().balanceOf(address(this));
    }

    /// @notice tribe balance of contract
    /// @return tribe amount held
    function tribeBalance() public view override returns (uint256) {
        return tribe().balanceOf(address(this));
    }

    function _burnFeiHeld() internal {
        fei().burn(feiBalance());
    }

    function _mintFei(uint256 amount) internal {
        fei().mint(address(this), amount);
    }
}

File 9 of 20 : ICoreRef.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "../core/ICore.sol";

/// @title CoreRef interface
/// @author Fei Protocol
interface ICoreRef {
    // ----------- Events -----------

    event CoreUpdate(address indexed _core);

    // ----------- Governor only state changing api -----------

    function setCore(address core) external;

    function pause() external;

    function unpause() external;

    // ----------- Getters -----------

    function core() external view returns (ICore);

    function fei() external view returns (IFei);

    function tribe() external view returns (IERC20);

    function feiBalance() external view returns (uint256);

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

File 10 of 20 : Tribe.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

// Forked from Uniswap's UNI
// Reference: https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code

contract Tribe {
    /// @notice EIP-20 token name for this token
    // solhint-disable-next-line const-name-snakecase
    string public constant name = "Tribe";

    /// @notice EIP-20 token symbol for this token
    // solhint-disable-next-line const-name-snakecase
    string public constant symbol = "TRIBE";

    /// @notice EIP-20 token decimals for this token
    // solhint-disable-next-line const-name-snakecase
    uint8 public constant decimals = 18;

    /// @notice Total number of tokens in circulation
    // solhint-disable-next-line const-name-snakecase
    uint public totalSupply = 1_000_000_000e18; // 1 billion Tribe

    /// @notice Address which may mint new tokens
    address public minter;

    /// @notice Allowance amounts on behalf of others
    mapping (address => mapping (address => uint96)) internal allowances;

    /// @notice Official record of token balances for each account
    mapping (address => uint96) internal balances;

    /// @notice A record of each accounts delegate
    mapping (address => address) public delegates;

    /// @notice A checkpoint for marking number of votes from a given block
    struct Checkpoint {
        uint32 fromBlock;
        uint96 votes;
    }

    /// @notice A record of votes checkpoints for each account, by index
    mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;

    /// @notice The number of checkpoints for each account
    mapping (address => uint32) public numCheckpoints;

    /// @notice The EIP-712 typehash for the contract's domain
    bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");

    /// @notice The EIP-712 typehash for the delegation struct used by the contract
    bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    /// @notice The EIP-712 typehash for the permit struct used by the contract
    bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    /// @notice A record of states for signing / validating signatures
    mapping (address => uint) public nonces;

    /// @notice An event thats emitted when the minter address is changed
    event MinterChanged(address minter, address newMinter);

    /// @notice An event thats emitted when an account changes its delegate
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /// @notice An event thats emitted when a delegate account's vote balance changes
    event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);

    /// @notice The standard EIP-20 transfer event
    event Transfer(address indexed from, address indexed to, uint256 amount);

    /// @notice The standard EIP-20 approval event
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /**
     * @notice Construct a new Tribe token
     * @param account The initial account to grant all the tokens
     * @param minter_ The account with minting ability
     */
    constructor(address account, address minter_) public {
        balances[account] = uint96(totalSupply);
        emit Transfer(address(0), account, totalSupply);
        minter = minter_;
        emit MinterChanged(address(0), minter);
    }

    /**
     * @notice Change the minter address
     * @param minter_ The address of the new minter
     */
    function setMinter(address minter_) external {
        require(msg.sender == minter, "Tribe: only the minter can change the minter address");
        emit MinterChanged(minter, minter_);
        minter = minter_;
    }

    /**
     * @notice Mint new tokens
     * @param dst The address of the destination account
     * @param rawAmount The number of tokens to be minted
     */
    function mint(address dst, uint rawAmount) external {
        require(msg.sender == minter, "Tribe: only the minter can mint");
        require(dst != address(0), "Tribe: cannot transfer to the zero address");

        // mint the amount
        uint96 amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
        uint96 safeSupply = safe96(totalSupply, "Tribe: totalSupply exceeds 96 bits");
        totalSupply = add96(safeSupply, amount, "Tribe: totalSupply exceeds 96 bits");

        // transfer the amount to the recipient
        balances[dst] = add96(balances[dst], amount, "Tribe: transfer amount overflows");
        emit Transfer(address(0), dst, amount);

        // move delegates
        _moveDelegates(address(0), delegates[dst], amount);
    }

    /**
     * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`
     * @param account The address of the account holding the funds
     * @param spender The address of the account spending the funds
     * @return The number of tokens approved
     */
    function allowance(address account, address spender) external view returns (uint) {
        return allowances[account][spender];
    }

    /**
     * @notice Approve `spender` to transfer up to `amount` from `src`
     * @dev This will overwrite the approval amount for `spender`
     *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
     * @param spender The address of the account which may transfer tokens
     * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)
     * @return Whether or not the approval succeeded
     */
    function approve(address spender, uint rawAmount) external returns (bool) {
        uint96 amount;
        if (rawAmount == uint(-1)) {
            amount = uint96(-1);
        } else {
            amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
        }

        allowances[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);
        return true;
    }

    /**
     * @notice Triggers an approval from owner to spends
     * @param owner The address to approve from
     * @param spender The address to be approved
     * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)
     * @param deadline The time at which to expire the signature
     * @param v The recovery byte of the signature
     * @param r Half of the ECDSA signature pair
     * @param s Half of the ECDSA signature pair
     */
    function permit(address owner, address spender, uint rawAmount, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
        uint96 amount;
        if (rawAmount == uint(-1)) {
            amount = uint96(-1);
        } else {
            amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
        }

        bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));
        bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, rawAmount, nonces[owner]++, deadline));
        bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
        address signatory = ecrecover(digest, v, r, s);
        require(signatory != address(0), "Tribe: invalid signature");
        require(signatory == owner, "Tribe: unauthorized");
        // solhint-disable-next-line not-rely-on-time
        require(block.timestamp <= deadline, "Tribe: signature expired");

        allowances[owner][spender] = amount;

        emit Approval(owner, spender, amount);
    }

    /**
     * @notice Get the number of tokens held by the `account`
     * @param account The address of the account to get the balance of
     * @return The number of tokens held
     */
    function balanceOf(address account) external view returns (uint) {
        return balances[account];
    }

    /**
     * @notice Transfer `amount` tokens from `msg.sender` to `dst`
     * @param dst The address of the destination account
     * @param rawAmount The number of tokens to transfer
     * @return Whether or not the transfer succeeded
     */
    function transfer(address dst, uint rawAmount) external returns (bool) {
        uint96 amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
        _transferTokens(msg.sender, dst, amount);
        return true;
    }

    /**
     * @notice Transfer `amount` tokens from `src` to `dst`
     * @param src The address of the source account
     * @param dst The address of the destination account
     * @param rawAmount The number of tokens to transfer
     * @return Whether or not the transfer succeeded
     */
    function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {
        address spender = msg.sender;
        uint96 spenderAllowance = allowances[src][spender];
        uint96 amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");

        if (spender != src && spenderAllowance != uint96(-1)) {
            uint96 newAllowance = sub96(spenderAllowance, amount, "Tribe: transfer amount exceeds spender allowance");
            allowances[src][spender] = newAllowance;

            emit Approval(src, spender, newAllowance);
        }

        _transferTokens(src, dst, amount);
        return true;
    }

    /**
     * @notice Delegate votes from `msg.sender` to `delegatee`
     * @param delegatee The address to delegate votes to
     */
    function delegate(address delegatee) public {
        return _delegate(msg.sender, delegatee);
    }

    /**
     * @notice Delegates votes from signatory to `delegatee`
     * @param delegatee The address to delegate votes to
     * @param nonce The contract state required to match the signature
     * @param expiry The time at which to expire the signature
     * @param v The recovery byte of the signature
     * @param r Half of the ECDSA signature pair
     * @param s Half of the ECDSA signature pair
     */
    function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {
        bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));
        bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));
        bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
        address signatory = ecrecover(digest, v, r, s);
        require(signatory != address(0), "Tribe: invalid signature");
        require(nonce == nonces[signatory]++, "Tribe: invalid nonce");
        // solhint-disable-next-line not-rely-on-time
        require(block.timestamp <= expiry, "Tribe: signature expired");
        return _delegate(signatory, delegatee);
    }

    /**
     * @notice Gets the current votes balance for `account`
     * @param account The address to get votes balance
     * @return The number of current votes for `account`
     */
    function getCurrentVotes(address account) external view returns (uint96) {
        uint32 nCheckpoints = numCheckpoints[account];
        return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
    }

    /**
     * @notice Determine the prior number of votes for an account as of a block number
     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
     * @param account The address of the account to check
     * @param blockNumber The block number to get the vote balance at
     * @return The number of votes the account had as of the given block
     */
    function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {
        require(blockNumber < block.number, "Tribe: not yet determined");

        uint32 nCheckpoints = numCheckpoints[account];
        if (nCheckpoints == 0) {
            return 0;
        }

        // First check most recent balance
        if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
            return checkpoints[account][nCheckpoints - 1].votes;
        }

        // Next check implicit zero balance
        if (checkpoints[account][0].fromBlock > blockNumber) {
            return 0;
        }

        uint32 lower = 0;
        uint32 upper = nCheckpoints - 1;
        while (upper > lower) {
            uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
            Checkpoint memory cp = checkpoints[account][center];
            if (cp.fromBlock == blockNumber) {
                return cp.votes;
            } else if (cp.fromBlock < blockNumber) {
                lower = center;
            } else {
                upper = center - 1;
            }
        }
        return checkpoints[account][lower].votes;
    }

    function _delegate(address delegator, address delegatee) internal {
        address currentDelegate = delegates[delegator];
        uint96 delegatorBalance = balances[delegator];
        delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);

        _moveDelegates(currentDelegate, delegatee, delegatorBalance);
    }

    function _transferTokens(address src, address dst, uint96 amount) internal {
        require(src != address(0), "Tribe: cannot transfer from the zero address");
        require(dst != address(0), "Tribe: cannot transfer to the zero address");

        balances[src] = sub96(balances[src], amount, "Tribe: transfer amount exceeds balance");
        balances[dst] = add96(balances[dst], amount, "Tribe: transfer amount overflows");
        emit Transfer(src, dst, amount);

        _moveDelegates(delegates[src], delegates[dst], amount);
    }

    function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {
        if (srcRep != dstRep && amount > 0) {
            if (srcRep != address(0)) {
                uint32 srcRepNum = numCheckpoints[srcRep];
                uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
                uint96 srcRepNew = sub96(srcRepOld, amount, "Tribe: vote amount underflows");
                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
            }

            if (dstRep != address(0)) {
                uint32 dstRepNum = numCheckpoints[dstRep];
                uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
                uint96 dstRepNew = add96(dstRepOld, amount, "Tribe: vote amount overflows");
                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
            }
        }
    }

    function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {
      uint32 blockNumber = safe32(block.number, "Tribe: block number exceeds 32 bits");

      if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
          checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
      } else {
          checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
          numCheckpoints[delegatee] = nCheckpoints + 1;
      }

      emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
    }

    function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
        require(n < 2**32, errorMessage);
        return uint32(n);
    }

    function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {
        require(n < 2**96, errorMessage);
        return uint96(n);
    }

    function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
        uint96 c = a + b;
        require(c >= a, errorMessage);
        return c;
    }

    function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
        require(b <= a, errorMessage);
        return a - b;
    }

    function getChainId() internal pure returns (uint) {
        uint256 chainId;
        // solhint-disable-next-line no-inline-assembly
        assembly { chainId := chainid() }
        return chainId;
    }
}

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

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

import "../utils/Address.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 !Address.isContract(address(this));
    }
}

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

pragma solidity >=0.6.2 <0.8.0;

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

        uint256 size;
        // 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);
    }

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(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);
            }
        }
    }
}

File 13 of 20 : AccessControl.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context {
    using EnumerableSet for EnumerableSet.AddressSet;
    using Address for address;

    struct RoleData {
        EnumerableSet.AddressSet members;
        bytes32 adminRole;
    }

    mapping (bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

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

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

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

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

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view returns (uint256) {
        return _roles[role].members.length();
    }

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
        return _roles[role].members.at(index);
    }

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

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");

        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");

        _revokeRole(role, account);
    }

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

        _revokeRole(role, account);
    }

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

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

    function _grantRole(bytes32 role, address account) private {
        if (_roles[role].members.add(account)) {
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (_roles[role].members.remove(account)) {
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 15 of 20 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with 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 Context {
    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;
    }
}

File 16 of 20 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

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

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

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

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

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

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

File 17 of 20 : ERC20Burnable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    using SafeMath for uint256;

    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public virtual {
        uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");

        _approve(account, _msgSender(), decreasedAllowance);
        _burn(account, amount);
    }
}

File 18 of 20 : ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../../utils/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";

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

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) public {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

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

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

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

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

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

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

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

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

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

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

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

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

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

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

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

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

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

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

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

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

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

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal virtual {
        _decimals = decimals_;
    }

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

File 19 of 20 : 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 20 of 20 : Pausable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";

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

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

    bool private _paused;

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

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

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

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

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

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

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

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_fei","type":"address"}],"name":"FeiUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_genesisGroup","type":"address"}],"name":"GenesisGroupUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"GenesisPeriodComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"TribeAllocation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tribe","type":"address"}],"name":"TribeUpdate","type":"event"},{"inputs":[],"name":"BURNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARDIAN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PCV_CONTROLLER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"allocateTribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"completeGenesisGroup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"bytes32","name":"adminRole","type":"bytes32"}],"name":"createRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fei","outputs":[{"internalType":"contract IFei","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisGroup","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"burner","type":"address"}],"name":"grantBurner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"grantGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guardian","type":"address"}],"name":"grantGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"grantMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pcvController","type":"address"}],"name":"grantPCVController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hasGenesisGroupCompleted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isBurner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isPCVController","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"burner","type":"address"}],"name":"revokeBurner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"revokeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guardian","type":"address"}],"name":"revokeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"revokeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeOverride","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pcvController","type":"address"}],"name":"revokePCVController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"setFei","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_genesisGroup","type":"address"}],"name":"setGenesisGroup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"setTribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tribe","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405262000018306001600160e01b03620000a616565b620000586040516200002a90620002ce565b60405180910390206040516200004090620002b7565b6040519081900390206001600160e01b03620000d416565b6200006a6040516200002a9062000287565b6200007c6040516200002a906200025e565b6200008e6040516200002a90620002b7565b620000a06040516200002a906200029e565b620002e5565b620000d1604051620000b890620002b7565b604051908190039020826001600160e01b036200012616565b50565b600082815260208190526040808220600201549051839285917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a460009182526020829052604090912060020155565b6200013b82826001600160e01b036200013f16565b5050565b6000828152602081815260409091206200016491839062001228620001c1821b17901c565b156200013b576200017d6001600160e01b03620001ea16565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620001e1836001600160a01b0384166001600160e01b03620001ee16565b90505b92915050565b3390565b60006200020583836001600160e01b036200024616565b6200023d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620001e4565b506000620001e4565b60009081526001919091016020526040902054151590565b7f5043565f434f4e54524f4c4c45525f524f4c4500000000000000000000000000815260130190565b6a4255524e45525f524f4c4560a81b8152600b0190565b6c475541524449414e5f524f4c4560981b8152600d0190565b6a474f5645524e5f524f4c4560a81b8152600b0190565b6a4d494e5445525f524f4c4560a81b8152600b0190565b615d0880620002f56000396000f3fe60806040523480156200001157600080fd5b5060043610620002805760003560e01c80639010d07c1162000159578063c1ef303a11620000c9578063e0a200461162000087578063e0a200461462000560578063e1c7392a146200056a578063e43581b81462000574578063e6eb982f146200058b578063eacdd9e814620005a25762000280565b8063c1ef303a14620004fa578063ca15c8731462000511578063cfbd48851462000528578063d5391393146200053f578063d547741f14620005495762000280565b8063a217fddf1162000117578063a217fddf14620004a1578063aa271e1a14620004ab578063af648c3d14620004c2578063b86677fe14620004d9578063b9022dc014620004e35762000280565b80639010d07c146200044857806391d14854146200045f57806394b1d2c014620004765780639711ac34146200048d5780639a9ba4da14620004975762000280565b806336568abe11620001f55780635f06d76111620001b35780635f06d76114620003d3578063611cf19b14620003ea5780636186943e146200040157806384bb0a6b14620004185780638dd9227614620004315762000280565b806336568abe146200036d57806338b7f4461462000384578063395c62e8146200038e5780634334614a14620003a55780634c9f938414620003bc5762000280565b8063248a9ca31162000243578063248a9ca3146200030557806324ea54f4146200032b578063261707fa1462000335578063282c51f3146200034c5780632f2ff15d14620003565762000280565b8063080bf57c14620002855780630900cc33146200029e5780630c68ba2114620002b557806310511f9614620002e4578063201175c214620002fb575b600080fd5b6200029c6200029636600462001496565b620005b9565b005b6200029c620002af36600462001410565b62000683565b620002cc620002c636600462001410565b620006d1565b604051620002db9190620015d1565b60405180910390f35b6200029c620002f536600462001410565b620006fa565b6200029c62000745565b6200031c620003163660046200147d565b620007ee565b604051620002db9190620015dc565b6200031c62000803565b6200029c6200034636600462001410565b6200081c565b6200031c62000858565b6200029c6200036736600462001496565b62000866565b6200029c6200037e36600462001496565b620008b6565b6200031c620008ff565b6200029c6200039f36600462001410565b6200090d565b620002cc620003b636600462001410565b62000949565b6200029c620003cd366004620014d2565b6200095d565b6200029c620003e436600462001410565b62000993565b6200029c620003fb36600462001410565b620009c8565b620002cc6200041236600462001410565b62000a3c565b6200042262000a50565b604051620002db91906200158a565b6200029c6200044236600462001410565b62000a5f565b6200042262000459366004620014d2565b62000a9b565b620002cc6200047036600462001496565b62000ac2565b6200029c6200048736600462001410565b62000ae2565b620002cc62000b1e565b6200042262000b2e565b6200031c62000b43565b620002cc620004bc36600462001410565b62000b48565b6200029c620004d336600462001410565b62000b5c565b6200042262000b98565b6200029c620004f436600462001410565b62000ba7565b6200029c6200050b36600462001410565b62000bdc565b6200031c620005223660046200147d565b62000c18565b6200029c6200053936600462001410565b62000c31565b6200031c62000c6d565b6200029c6200055a36600462001496565b62000c7b565b6200031c62000cbb565b6200029c62000cc9565b620002cc6200058536600462001410565b62000df2565b6200029c6200059c36600462001410565b62000e06565b6200029c620005b33660046200142e565b62000e42565b620005c433620006d1565b620005ec5760405162461bcd60e51b8152600401620005e39062001825565b60405180910390fd5b604051620005fa906200155c565b6040518091039020821415620006245760405162461bcd60e51b8152600401620005e3906200186a565b60405163d547741f60e01b8152309063d547741f906200064b9085908590600401620015e5565b600060405180830381600087803b1580156200066657600080fd5b505af11580156200067b573d6000803e3d6000fd5b505050505050565b6200068e3362000df2565b620006ad5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200152c565b60405180910390208262000c7b565b50565b6000620006f4604051620006e59062001543565b60405180910390208362000ac2565b92915050565b620007053362000df2565b620007245760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200152c565b60405180910390208262000866565b600354600160a01b900460ff1615620007725760405162461bcd60e51b8152600401620005e39062001743565b6003546001600160a01b031633146200079f5760405162461bcd60e51b8152600401620005e39062001702565b6003805460ff60a01b1916600160a01b1790556040517f55728014a7cf4447d0a7e11503cf9ab1ca633624fa3150f8fe149b56e3c026fb90620007e4904290620015dc565b60405180910390a1565b60009081526020819052604090206002015490565b604051620008119062001543565b604051809103902081565b620008273362000df2565b620008465760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620007369062001573565b60405162000811906200152c565b60008281526020819052604090206002015462000887906200047062000fe6565b620008a65760405162461bcd60e51b8152600401620005e39062001683565b620008b2828262000fea565b5050565b620008c062000fe6565b6001600160a01b0316816001600160a01b031614620008f35760405162461bcd60e51b8152600401620005e390620018b6565b620008b282826200105e565b60405162000811906200155c565b620009183362000df2565b620009375760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200155c565b6000620006f4604051620006e5906200152c565b620009683362000df2565b620009875760405162461bcd60e51b8152600401620005e3906200163e565b620008b28282620010d2565b6200099e3362000df2565b620009bd5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce8162001124565b620009d33362000df2565b620009f25760405162461bcd60e51b8152600401620005e3906200163e565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f815cf7ef55cab2e0662e0739c044d60e9a897f882091d48baa1b0b30d28f8a3090600090a250565b6000620006f4604051620006e5906200150d565b6003546001600160a01b031681565b62000a6a3362000df2565b62000a895760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200150d565b600082815260208190526040812062000abb908363ffffffff6200117816565b9392505050565b600082815260208190526040812062000abb908363ffffffff6200118616565b62000aed3362000df2565b62000b0c5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620007369062001543565b600354600160a01b900460ff1681565b6001546201000090046001600160a01b031681565b600081565b6000620006f4604051620006e59062001573565b62000b673362000df2565b62000b865760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf9062001543565b6002546001600160a01b031681565b62000bb23362000df2565b62000bd15760405162461bcd60e51b8152600401620005e3906200163e565b620006ce816200119d565b62000be73362000df2565b62000c065760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200150d565b6000818152602081905260408120620006f490620011e7565b62000c3c3362000df2565b62000c5b5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf9062001573565b604051620008119062001573565b60008281526020819052604090206002015462000c9c906200047062000fe6565b620008f35760405162461bcd60e51b8152600401620005e39062001787565b60405162000811906200150d565b600154610100900460ff168062000ce5575062000ce5620011f4565b8062000cf4575060015460ff16155b62000d135760405162461bcd60e51b8152600401620005e390620017d7565b600154610100900460ff1615801562000d3e576001805460ff1961ff00199091166101001716811790555b62000d493362001207565b60003060405162000d5a90620013dc565b62000d6691906200158a565b604051809103906000f08015801562000d83573d6000803e3d6000fd5b50905062000d918162001124565b6000303360405162000da390620013ea565b62000db09291906200159e565b604051809103906000f08015801562000dcd573d6000803e3d6000fd5b50905062000ddb816200119d565b50508015620006ce576001805461ff001916905550565b6000620006f4604051620006e5906200155c565b62000e113362000df2565b62000e305760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200155c565b62000e4d3362000df2565b62000e6c5760405162461bcd60e51b8152600401620005e3906200163e565b6002546040516370a0823160e01b81526001600160a01b0390911690829082906370a082319062000ea29030906004016200158a565b60206040518083038186803b15801562000ebb57600080fd5b505afa15801562000ed0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ef69190620014f4565b101562000f175760405162461bcd60e51b8152600401620005e390620016d2565b60405163a9059cbb60e01b81526001600160a01b0382169063a9059cbb9062000f479086908690600401620015b8565b602060405180830381600087803b15801562000f6257600080fd5b505af115801562000f77573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f9d91906200145b565b50826001600160a01b03167ffd90a2bc2c0c3cf07693529b256c4173a944fe9f55c1984c09a10a1ad28c11648360405162000fd99190620015dc565b60405180910390a2505050565b3390565b60008281526020819052604090206200100a908263ffffffff6200122816565b15620008b2576200101a62000fe6565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020819052604090206200107e908263ffffffff6200123f16565b15620008b2576200108e62000fe6565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082815260208190526040808220600201549051839285917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a460009182526020829052604090912060020155565b6001805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517fb382b2a2d84e1d7542e0d58950e00d33ddc7a4b379a265768bf3e8640dde4ef190600090a250565b600062000abb838362001256565b600062000abb836001600160a01b0384166200129f565b600280546001600160a01b0319166001600160a01b0383169081179091556040517f9675664499c8d4f09c5268d1696ba833416ed56d870558fa7a722bb8aff5d90f90600090a250565b6000620006f482620012b7565b60006200120130620012bb565b15905090565b620006ce60405162001219906200155c565b604051809103902082620008a6565b600062000abb836001600160a01b038416620012c1565b600062000abb836001600160a01b03841662001310565b815460009082106200127c5760405162461bcd60e51b8152600401620005e390620015fc565b8260000182815481106200128c57fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b3b151590565b6000620012cf83836200129f565b6200130757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620006f4565b506000620006f4565b60008181526001830160205260408120548015620013d157835460001980830191908101906000908790839081106200134557fe5b90600052602060002001549050808760000184815481106200136357fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806200139457fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050620006f4565b6000915050620006f4565b6122c4806200190683390190565b6121098062003bca83390190565b80356001600160a01b0381168114620006f457600080fd5b60006020828403121562001422578081fd5b62000abb8383620013f8565b6000806040838503121562001441578081fd5b6200144d8484620013f8565b946020939093013593505050565b6000602082840312156200146d578081fd5b8151801515811462000abb578182fd5b6000602082840312156200148f578081fd5b5035919050565b60008060408385031215620014a9578182fd5b8235915060208301356001600160a01b0381168114620014c7578182fd5b809150509250929050565b60008060408385031215620014e5578182fd5b50508035926020909101359150565b60006020828403121562001506578081fd5b5051919050565b725043565f434f4e54524f4c4c45525f524f4c4560681b815260130190565b6a4255524e45525f524f4c4560a81b8152600b0190565b6c475541524449414e5f524f4c4560981b8152600d0190565b6a474f5645524e5f524f4c4560a81b8152600b0190565b6a4d494e5445525f524f4c4560a81b8152600b0190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9182526001600160a01b0316602082015260400190565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b60208082526025908201527f5065726d697373696f6e733a2043616c6c6572206973206e6f74206120676f7660408201526432b93737b960d91b606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60408201526e0818591b5a5b881d1bc819dc985b9d608a1b606082015260800190565b602080825260169082015275436f72653a204e6f7420656e6f75676820547269626560501b604082015260600190565b60208082526021908201527f436f72653a2043616c6c6572206973206e6f742047656e657369732047726f756040820152600760fc1b606082015260800190565b60208082526024908201527f436f72653a2047656e657369732047726f757020616c726561647920636f6d706040820152636c65746560e01b606082015260800190565b60208082526030908201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60408201526f2061646d696e20746f207265766f6b6560801b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526025908201527f5065726d697373696f6e733a2043616c6c6572206973206e6f74206120677561604082015264393234b0b760d91b606082015260800190565b6020808252602c908201527f5065726d697373696f6e733a20477561726469616e2063616e6e6f742072657660408201526b37b5b29033b7bb32b93737b960a11b606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560408201526e103937b632b9903337b91039b2b63360891b60608201526080019056fe60806040523480156200001157600080fd5b50604051620022c4380380620022c48339810160408190526200003491620002aa565b604080518082018252600781526611995a481554d160ca1b6020808301918252835180850190945260038085526246454960e81b91850191909152825185949262000080929162000208565b5080516200009690600490602084019062000208565b5050600580546001600160a01b039093166201000002610100600160b01b031960ff199094166012179390931692909217909155506040514690620000db90620002da565b604051908190039020620000f76001600160e01b036200016d16565b805160209182012060408051808201825260018152603160f81b90840152516200014993927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc691869130910162000344565b60405160208183030381529060405280519060200120600781905550505062000370565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620001fd5780601f10620001d157610100808354040283529160200191620001fd565b820191906000526020600020905b815481529060010190602001808311620001df57829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024b57805160ff19168380011785556200027b565b828001600101855582156200027b579182015b828111156200027b5782518255916020019190600101906200025e565b50620002899291506200028d565b5090565b6200020591905b8082111562000289576000815560010162000294565b600060208284031215620002bc578081fd5b81516001600160a01b0381168114620002d3578182fd5b9392505050565b7f454950373132446f6d61696e28737472696e67206e616d652c737472696e672081527f76657273696f6e2c75696e7432353620636861696e49642c6164647265737320602082015271766572696679696e67436f6e74726163742960701b604082015260520190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b611f4480620003806000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806379cc679011610104578063a9059cbb116100a2578063bc701e7511610071578063bc701e751461036c578063d505accf1461037f578063dd62ed3e14610392578063f2f4eb26146103a5576101cf565b8063a9059cbb14610336578063b490589714610349578063b6232c9914610351578063b86677fe14610364576101cf565b80638456cb59116100de5780638456cb59146102fe57806395d89b41146103065780639a9ba4da1461030e578063a457c2d714610323576101cf565b806379cc6790146102c55780637ecebe00146102d857806380009630146102eb576101cf565b8063395093511161017157806342966c681161014b57806342966c681461028f5780635c975abb146102a25780636b6dff0a146102aa57806370a08231146102b2576101cf565b8063395093511461025f5780633f4ba83a1461027257806340c10f191461027c576101cf565b806323b872dd116101ad57806323b872dd1461022757806330adf81f1461023a578063313ce567146102425780633644e51514610257576101cf565b806306fdde03146101d4578063095ea7b3146101f257806318160ddd14610212575b600080fd5b6101dc6103ad565b6040516101e99190611a65565b60405180910390f35b61020561020036600461190f565b610443565b6040516101e991906119ff565b61021a610460565b6040516101e99190611a0a565b61020561023536600461185a565b610466565b61021a6104f3565b61024a610517565b6040516101e99190611e56565b61021a610520565b61020561026d36600461190f565b610526565b61027a61057a565b005b61027a61028a36600461190f565b6106b9565b61027a61029d366004611976565b6107d8565b610205610820565b61021a61082e565b61021a6102c0366004611806565b6108b8565b61027a6102d336600461190f565b6108d3565b61021a6102e6366004611806565b6109e6565b61027a6102f9366004611806565b6109f8565b61027a610aed565b6101dc610c21565b610316610c82565b6040516101e991906119c1565b61020561033136600461190f565b610d0a565b61020561034436600461190f565b610d78565b61021a610d8c565b61027a61035f366004611822565b610d96565b610316610e8e565b61031661037a366004611806565b610ede565b61027a61038d36600461189a565b610ef9565b61021a6103a0366004611822565b611068565b610316611093565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104395780601f1061040e57610100808354040283529160200191610439565b820191906000526020600020905b81548152906001019060200180831161041c57829003601f168201915b5050505050905090565b60006104576104506110a8565b84846110ac565b50600192915050565b60025490565b6000610473848484611160565b6104e98461047f6110a8565b6104e485604051806060016040528060288152602001611ec2602891396001600160a01b038a166000908152600160205260408120906104bd6110a8565b6001600160a01b03168152602081019190915260400160002054919063ffffffff61117b16565b6110ac565b5060019392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b60075481565b60006104576105336110a8565b846104e485600160006105446110a8565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6111a716565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b8906105af9033906004016119c1565b60206040518083038186803b1580156105c757600080fd5b505afa1580156105db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ff919061193a565b8061068a5750600554604051630c68ba2160e01b8152620100009091046001600160a01b031690630c68ba219061063a9033906004016119c1565b60206040518083038186803b15801561065257600080fd5b505afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a919061193a565b6106af5760405162461bcd60e51b81526004016106a690611ba2565b60405180910390fd5b6106b76111d3565b565b6005546040516355138f0d60e11b8152620100009091046001600160a01b03169063aa271e1a906106ee9033906004016119c1565b60206040518083038186803b15801561070657600080fd5b505afa15801561071a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073e919061193a565b61075a5760405162461bcd60e51b81526004016106a690611b29565b610762610820565b1561077f5760405162461bcd60e51b81526004016106a690611cba565b6107898282611242565b336001600160a01b0316826001600160a01b03167fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca836040516107cc9190611a0a565b60405180910390a35050565b6107e181611302565b604051339081907f227fb4b3aae8331f21af5167739c291fefe3afd3c2e08cea44f499e564f486ef90610815908590611a0a565b60405180910390a350565b600554610100900460ff1690565b6000610838610e8e565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161086391906119c1565b60206040518083038186803b15801561087b57600080fd5b505afa15801561088f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061198e565b905090565b6001600160a01b031660009081526020819052604090205490565b60055460405163219a30a560e11b8152620100009091046001600160a01b031690634334614a906109089033906004016119c1565b60206040518083038186803b15801561092057600080fd5b505afa158015610934573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610958919061193a565b6109745760405162461bcd60e51b81526004016106a690611c26565b61097c610820565b156109995760405162461bcd60e51b81526004016106a690611cba565b6109a38282611316565b336001600160a01b0316826001600160a01b03167f227fb4b3aae8331f21af5167739c291fefe3afd3c2e08cea44f499e564f486ef836040516107cc9190611a0a565b60086020526000908152604090205481565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610a2d9033906004016119c1565b60206040518083038186803b158015610a4557600080fd5b505afa158015610a59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7d919061193a565b610a995760405162461bcd60e51b81526004016106a690611dde565b6005805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517fad9400e618eb1344fde53db22397a1b82c765527ecbba3a5c86bcac15090828b90600090a250565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610b229033906004016119c1565b60206040518083038186803b158015610b3a57600080fd5b505afa158015610b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b72919061193a565b80610bfd5750600554604051630c68ba2160e01b8152620100009091046001600160a01b031690630c68ba2190610bad9033906004016119c1565b60206040518083038186803b158015610bc557600080fd5b505afa158015610bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfd919061193a565b610c195760405162461bcd60e51b81526004016106a690611ba2565b6106b76113f8565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104395780601f1061040e57610100808354040283529160200191610439565b6000600560029054906101000a90046001600160a01b03166001600160a01b0316639a9ba4da6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cd257600080fd5b505afa158015610ce6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061195a565b6000610457610d176110a8565b846104e485604051806060016040528060258152602001611eea6025913960016000610d416110a8565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61117b16565b6000610457610d856110a8565b8484611160565b6000610838610c82565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610dcb9033906004016119c1565b60206040518083038186803b158015610de357600080fd5b505afa158015610df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1b919061193a565b610e375760405162461bcd60e51b81526004016106a690611dde565b6001600160a01b0382811660008181526006602052604080822080546001600160a01b0319169486169485179055517f88bb9e877881758e827c849b8a0e38421bd5ff916f4ef79ed65aec74cc04a5da9190a35050565b6000600560029054906101000a90046001600160a01b03166001600160a01b031663b86677fe6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cd257600080fd5b6006602052600090815260409020546001600160a01b031681565b42841015610f195760405162461bcd60e51b81526004016106a690611c5d565b6007546001600160a01b03881660009081526008602090815260408083208054600181019091559051929392610f7a927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d92918d9101611a13565b60405160208183030381529060405280519060200120604051602001610fa19291906119a6565b604051602081830303815290604052805190602001209050600060018286868660405160008152602001604052604051610fde9493929190611a47565b6020604051602081039080840390855afa158015611000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906110365750886001600160a01b0316816001600160a01b0316145b6110525760405162461bcd60e51b81526004016106a690611ce4565b61105d8989896110ac565b505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6005546201000090046001600160a01b031690565b3390565b6001600160a01b0383166110d25760405162461bcd60e51b81526004016106a690611d9a565b6001600160a01b0382166110f85760405162461bcd60e51b81526004016106a690611b60565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590611153908590611a0a565b60405180910390a3505050565b61116b838383611455565b611176838383611576565b505050565b6000818484111561119f5760405162461bcd60e51b81526004016106a69190611a65565b505050900390565b6000828201838110156111cc5760405162461bcd60e51b81526004016106a690611bef565b9392505050565b6111db610820565b6111f75760405162461bcd60e51b81526004016106a690611afb565b6005805461ff00191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61122b6110a8565b60405161123891906119c1565b60405180910390a1565b6001600160a01b0382166112685760405162461bcd60e51b81526004016106a690611e1f565b61127460008383611176565b600254611287908263ffffffff6111a716565b6002556001600160a01b0382166000908152602081905260409020546112b3908263ffffffff6111a716565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107cc908590611a0a565b61131361130d6110a8565b82611316565b50565b6001600160a01b03821661133c5760405162461bcd60e51b81526004016106a690611d14565b61134882600083611176565b61138b81604051806060016040528060228152602001611e7a602291396001600160a01b038516600090815260208190526040902054919063ffffffff61117b16565b6001600160a01b0383166000908152602081905260409020556002546113b7908263ffffffff6117de16565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107cc908590611a0a565b611400610820565b1561141d5760405162461bcd60e51b81526004016106a690611cba565b6005805461ff0019166101001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861122b6110a8565b6001600160a01b03831661147b5760405162461bcd60e51b81526004016106a690611d55565b6001600160a01b0382166114a15760405162461bcd60e51b81526004016106a690611ab8565b6114ac838383611176565b6114ef81604051806060016040528060268152602001611e9c602691396001600160a01b038616600090815260208190526040902054919063ffffffff61117b16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611524908263ffffffff6111a716565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611153908590611a0a565b6001600160a01b038084166000908152600660205260409020541680156115fc57604051636e22230d60e01b81526001600160a01b03821690636e22230d906115c99087908790339088906004016119d5565b600060405180830381600087803b1580156115e357600080fd5b505af11580156115f7573d6000803e3d6000fd5b505050505b6001600160a01b0380841660009081526006602052604090205416801561168257604051636e22230d60e01b81526001600160a01b03821690636e22230d9061164f9088908890339089906004016119d5565b600060405180830381600087803b15801561166957600080fd5b505af115801561167d573d6000803e3d6000fd5b505050505b336000818152600660205260409020546001600160a01b0390811691908716148015906116b85750336001600160a01b03861614155b80156116cc57506001600160a01b03811615155b1561173657604051636e22230d60e01b81526001600160a01b03821690636e22230d90611703908990899033908a906004016119d5565b600060405180830381600087803b15801561171d57600080fd5b505af1158015611731573d6000803e3d6000fd5b505050505b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8546001600160a01b031680156117d557604051636e22230d60e01b81526001600160a01b03821690636e22230d906117a2908a908a9033908b906004016119d5565b600060405180830381600087803b1580156117bc57600080fd5b505af11580156117d0573d6000803e3d6000fd5b505050505b50505050505050565b6000828211156118005760405162461bcd60e51b81526004016106a690611c83565b50900390565b600060208284031215611817578081fd5b81356111cc81611e64565b60008060408385031215611834578081fd5b823561183f81611e64565b9150602083013561184f81611e64565b809150509250929050565b60008060006060848603121561186e578081fd5b833561187981611e64565b9250602084013561188981611e64565b929592945050506040919091013590565b600080600080600080600060e0888a0312156118b4578283fd5b87356118bf81611e64565b965060208801356118cf81611e64565b95506040880135945060608801359350608088013560ff811681146118f2578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611921578182fd5b823561192c81611e64565b946020939093013593505050565b60006020828403121561194b578081fd5b815180151581146111cc578182fd5b60006020828403121561196b578081fd5b81516111cc81611e64565b600060208284031215611987578081fd5b5035919050565b60006020828403121561199f578081fd5b5051919050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611a9157858101830151858201604001528201611a75565b81811115611aa25783604083870101525b50601f01601f1916929092016040019392505050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601f908201527f436f72655265663a2043616c6c6572206973206e6f742061206d696e74657200604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602d908201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160408201526c371037b91033b7bb32b93737b960991b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601f908201527f436f72655265663a2043616c6c6572206973206e6f742061206275726e657200604082015260600190565b6020808252600c908201526b11995a4e881156141254915160a21b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601690820152754665693a20494e56414c49445f5349474e415455524560501b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526021908201527f436f72655265663a2043616c6c6572206973206e6f74206120676f7665726e6f6040820152603960f91b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b60ff91909116815260200190565b6001600160a01b038116811461131357600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122050e890c3b2545b3935ee59eb10f843e1ae9421c4c123c2534bea07e27e8ff0f164736f6c6343000606003360806040526b033b2e3c9fd0803ce80000006000553480156200002157600080fd5b506040516200210938038062002109833981016040819052620000449162000121565b600080546001600160a01b0384168083526003602052604080842080546001600160601b0319166001600160601b0390941693909317909255825491519092917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91620000b2919062000179565b60405180910390a3600180546001600160a01b0319166001600160a01b0383811691909117918290556040517f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f69262000111926000929116906200015f565b60405180910390a150506200019b565b6000806040838503121562000134578182fd5b8251620001418162000182565b6020840151909250620001548162000182565b809150509250929050565b6001600160a01b0392831681529116602082015260400190565b90815260200190565b6001600160a01b03811681146200019857600080fd5b50565b611f5e80620001ab6000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c806370a08231116100c3578063c3cda5201161007c578063c3cda520146102cc578063d505accf146102df578063dd62ed3e146102f2578063e7a324dc14610305578063f1127ed81461030d578063fca3b5aa1461032e57610158565b806370a0823114610258578063782d6fe11461026b5780637ecebe001461028b57806395d89b411461029e578063a9059cbb146102a6578063b4b5ea57146102b957610158565b806330adf81f1161011557806330adf81f146101e0578063313ce567146101e857806340c10f19146101fd578063587cde1e146102125780635c19a95c146102255780636fcfff451461023857610158565b806306fdde031461015d578063075461721461017b578063095ea7b31461019057806318160ddd146101b057806320606b70146101c557806323b872dd146101cd575b600080fd5b610165610341565b6040516101729190611b78565b60405180910390f35b610183610362565b6040516101729190611a9c565b6101a361019e3660046118ab565b610371565b6040516101729190611aca565b6101b861043b565b6040516101729190611ad5565b6101b8610441565b6101a36101db3660046117ff565b610458565b6101b86105a7565b6101f06105b3565b6040516101729190611e1c565b61021061020b3660046118ab565b6105b8565b005b6101836102203660046117b0565b610794565b6102106102333660046117b0565b6107af565b61024b6102463660046117b0565b6107bc565b6040516101729190611dec565b6101b86102663660046117b0565b6107d4565b61027e6102793660046118ab565b6107f8565b6040516101729190611e2a565b6101b86102993660046117b0565b610a06565b610165610a18565b6101a36102b43660046118ab565b610a39565b61027e6102c73660046117b0565b610a80565b6102106102da3660046118d5565b610af1565b6102106102ed36600461183f565b610cd8565b6101b86103003660046117cb565b610fcc565b6101b8611000565b61032061031b36600461192e565b61100c565b604051610172929190611dfd565b61021061033c3660046117b0565b611041565b60405180604001604052806005815260200164547269626560d81b81525081565b6001546001600160a01b031681565b60008060001983141561038757506000196103b7565b6103b4836040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90505b3360008181526002602090815260408083206001600160a01b03891680855292529182902080546001600160601b0319166001600160601b03861617905590519091907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610427908590611e2a565b60405180910390a360019150505b92915050565b60005481565b60405161044d906119f2565b604051809103902081565b6001600160a01b038316600090815260026020908152604080832033808552908352818420548251808401909352601d8352600080516020611f0983398151915293830193909352916001600160601b03169083906104b89086906110d4565b9050866001600160a01b0316836001600160a01b0316141580156104e557506001600160601b0382811614155b1561058f57600061050f8383604051806060016040528060308152602001611eb360309139611103565b6001600160a01b038981166000818152600260209081526040808320948a16808452949091529081902080546001600160601b0319166001600160601b0386161790555192935090917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610585908590611e2a565b60405180910390a3505b61059a878783611142565b5060019695505050505050565b60405161044d90611988565b601281565b6001546001600160a01b031633146105eb5760405162461bcd60e51b81526004016105e290611bcb565b60405180910390fd5b6001600160a01b0382166106115760405162461bcd60e51b81526004016105e290611c02565b6000610640826040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90506000610668600054604051806060016040528060228152602001611e91602291396110d4565b905061068d8183604051806060016040528060228152602001611e9160229139611305565b6001600160601b0390811660009081556001600160a01b0386168152600360209081526040918290205482518084019093528183527f54726962653a207472616e7366657220616d6f756e74206f766572666c6f7773918301919091526106f79216908490611305565b6001600160a01b03851660008181526003602052604080822080546001600160601b0319166001600160601b03959095169490941790935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610761908690611e2a565b60405180910390a36001600160a01b0380851660009081526004602052604081205461078e921684611341565b50505050565b6004602052600090815260409020546001600160a01b031681565b6107b9338261150d565b50565b60066020526000908152604090205463ffffffff1681565b6001600160a01b03166000908152600360205260409020546001600160601b031690565b60004382106108195760405162461bcd60e51b81526004016105e290611db5565b6001600160a01b03831660009081526006602052604090205463ffffffff1680610847576000915050610435565b6001600160a01b038416600090815260056020908152604080832063ffffffff6000198601811685529252909120541683106108c3576001600160a01b03841660009081526005602090815260408083206000199490940163ffffffff1683529290522054600160201b90046001600160601b03169050610435565b6001600160a01b038416600090815260056020908152604080832083805290915290205463ffffffff168310156108fe576000915050610435565b600060001982015b8163ffffffff168163ffffffff1611156109c157600282820363ffffffff16048103610930611771565b506001600160a01b038716600090815260056020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b0316918101919091529087141561099c576020015194506104359350505050565b805163ffffffff168711156109b3578193506109ba565b6001820392505b5050610906565b506001600160a01b038516600090815260056020908152604080832063ffffffff909416835292905220546001600160601b03600160201b9091041691505092915050565b60076020526000908152604090205481565b60405180604001604052806005815260200164545249424560d81b81525081565b600080610a69836040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b9050610a76338583611142565b5060019392505050565b6001600160a01b03811660009081526006602052604081205463ffffffff1680610aab576000610aea565b6001600160a01b0383166000908152600560209081526040808320600019850163ffffffff168452909152902054600160201b90046001600160601b03165b9392505050565b6000604051610aff906119f2565b604080519182900382208282019091526005825264547269626560d81b6020909201919091527febed0dee75115424b4c6084a9ab165e0c99bcf5a44403d7510e1ad1caeaea506610b4e611591565b30604051602001610b629493929190611b36565b6040516020818303038152906040528051906020012090506000604051610b8890611a4d565b604051908190038120610ba3918a908a908a90602001611b12565b60405160208183030381529060405280519060200120905060008282604051602001610bd092919061196d565b604051602081830303815290604052805190602001209050600060018288888860405160008152602001604052604051610c0d9493929190611b5a565b6020604051602081039080840390855afa158015610c2f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610c625760405162461bcd60e51b81526004016105e290611cfc565b6001600160a01b03811660009081526007602052604090208054600181019091558914610ca15760405162461bcd60e51b81526004016105e290611d33565b87421115610cc15760405162461bcd60e51b81526004016105e290611c4c565b610ccb818b61150d565b505050505b505050505050565b6000600019861415610ced5750600019610d1d565b610d1a866040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90505b6000604051610d2b906119f2565b604080519182900382208282019091526005825264547269626560d81b6020909201919091527febed0dee75115424b4c6084a9ab165e0c99bcf5a44403d7510e1ad1caeaea506610d7a611591565b30604051602001610d8e9493929190611b36565b6040516020818303038152906040528051906020012090506000604051610db490611988565b604080519182900382206001600160a01b038d16600090815260076020908152929020805460018101909155610df69391928e928e928e9290918e9101611ade565b60405160208183030381529060405280519060200120905060008282604051602001610e2392919061196d565b604051602081830303815290604052805190602001209050600060018289898960405160008152602001604052604051610e609493929190611b5a565b6020604051602081039080840390855afa158015610e82573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610eb55760405162461bcd60e51b81526004016105e290611cfc565b8b6001600160a01b0316816001600160a01b031614610ee65760405162461bcd60e51b81526004016105e290611ccf565b88421115610f065760405162461bcd60e51b81526004016105e290611c4c565b84600260008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160601b0302191690836001600160601b031602179055508a6001600160a01b03168c6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92587604051610fb69190611e2a565b60405180910390a3505050505050505050505050565b6001600160a01b0391821660009081526002602090815260408083209390941682529190915220546001600160601b031690565b60405161044d90611a4d565b600560209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6001546001600160a01b0316331461106b5760405162461bcd60e51b81526004016105e290611d61565b6001546040517f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f6916110aa916001600160a01b03909116908490611ab0565b60405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b600081600160601b84106110fb5760405162461bcd60e51b81526004016105e29190611b78565b509192915050565b6000836001600160601b0316836001600160601b03161115829061113a5760405162461bcd60e51b81526004016105e29190611b78565b505050900390565b6001600160a01b0383166111685760405162461bcd60e51b81526004016105e290611c83565b6001600160a01b03821661118e5760405162461bcd60e51b81526004016105e290611c02565b6001600160a01b0383166000908152600360209081526040918290205482516060810190935260268084526111d9936001600160601b039092169285929190611ee390830139611103565b6001600160a01b03848116600090815260036020908152604080832080546001600160601b0319166001600160601b039687161790559286168252908290205482518084019093528183527f54726962653a207472616e7366657220616d6f756e74206f766572666c6f7773918301919091526112599216908390611305565b6001600160a01b038381166000818152600360205260409081902080546001600160601b0319166001600160601b0395909516949094179093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906112c6908590611e2a565b60405180910390a36001600160a01b0380841660009081526004602052604080822054858416835291205461130092918216911683611341565b505050565b6000838301826001600160601b0380871690831610156113385760405162461bcd60e51b81526004016105e29190611b78565b50949350505050565b816001600160a01b0316836001600160a01b03161415801561136c57506000816001600160601b0316115b15611300576001600160a01b03831615611441576001600160a01b03831660009081526006602052604081205463ffffffff1690816113ac5760006113eb565b6001600160a01b0385166000908152600560209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b9050600061142f82856040518060400160405280601d81526020017f54726962653a20766f746520616d6f756e7420756e646572666c6f7773000000815250611103565b905061143d86848484611595565b5050505b6001600160a01b03821615611300576001600160a01b03821660009081526006602052604081205463ffffffff16908161147c5760006114bb565b6001600160a01b0384166000908152600560209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b905060006114ff82856040518060400160405280601c81526020017f54726962653a20766f746520616d6f756e74206f766572666c6f777300000000815250611305565b9050610cd085848484611595565b6001600160a01b03808316600081815260046020818152604080842080546003845282862054949093528787166001600160a01b031984168117909155905191909516946001600160601b039092169391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a461078e828483611341565b4690565b60006115b943604051806060016040528060238152602001611e6e6023913961174a565b905060008463ffffffff1611801561160257506001600160a01b038516600090815260056020908152604080832063ffffffff6000198901811685529252909120548282169116145b15611661576001600160a01b0385166000908152600560209081526040808320600019880163ffffffff168452909152902080546fffffffffffffffffffffffff000000001916600160201b6001600160601b03851602179055611700565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000818152600583528781208c871682528352878120965187549451909516600160201b026fffffffffffffffffffffffff000000001995871663ffffffff19958616179590951694909417909555938252600690935292909220805460018801909316929091169190911790555b846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724848460405161173b929190611e3e565b60405180910390a25050505050565b600081600160201b84106110fb5760405162461bcd60e51b81526004016105e29190611b78565b604080518082019091526000808252602082015290565b80356001600160a01b038116811461043557600080fd5b803560ff8116811461043557600080fd5b6000602082840312156117c1578081fd5b610aea8383611788565b600080604083850312156117dd578081fd5b6117e78484611788565b91506117f68460208501611788565b90509250929050565b600080600060608486031215611813578081fd5b833561181e81611e58565b9250602084013561182e81611e58565b929592945050506040919091013590565b600080600080600080600060e0888a031215611859578283fd5b6118638989611788565b96506118728960208a01611788565b9550604088013594506060880135935061188f8960808a0161179f565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156118bd578182fd5b6118c78484611788565b946020939093013593505050565b60008060008060008060c087890312156118ed578182fd5b6118f78888611788565b95506020870135945060408701359350611914886060890161179f565b92506080870135915060a087013590509295509295509295565b60008060408385031215611940578182fd5b61194a8484611788565b9150602083013563ffffffff81168114611962578182fd5b809150509250929050565b61190160f01b81526002810192909252602282015260420190565b7f5065726d69742861646472657373206f776e65722c616464726573732073706581527f6e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63656020820152712c75696e7432353620646561646c696e652960701b604082015260520190565b7f454950373132446f6d61696e28737472696e67206e616d652c75696e7432353681527f20636861696e49642c6164647265737320766572696679696e67436f6e74726160208201526263742960e81b604082015260430190565b7f44656c65676174696f6e28616464726573732064656c6567617465652c75696e81527f74323536206e6f6e63652c75696e7432353620657870697279290000000000006020820152603a0190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611ba457858101830151858201604001528201611b88565b81811115611bb55783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601f908201527f54726962653a206f6e6c7920746865206d696e7465722063616e206d696e7400604082015260600190565b6020808252602a908201527f54726962653a2063616e6e6f74207472616e7366657220746f20746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526018908201527f54726962653a207369676e617475726520657870697265640000000000000000604082015260600190565b6020808252602c908201527f54726962653a2063616e6e6f74207472616e736665722066726f6d207468652060408201526b7a65726f206164647265737360a01b606082015260800190565b602080825260139082015272151c9a58994e881d5b985d5d1a1bdc9a5e9959606a1b604082015260600190565b60208082526018908201527f54726962653a20696e76616c6964207369676e61747572650000000000000000604082015260600190565b60208082526014908201527354726962653a20696e76616c6964206e6f6e636560601b604082015260600190565b60208082526034908201527f54726962653a206f6e6c7920746865206d696e7465722063616e206368616e676040820152736520746865206d696e746572206164647265737360601b606082015260800190565b60208082526019908201527f54726962653a206e6f74207965742064657465726d696e656400000000000000604082015260600190565b63ffffffff91909116815260200190565b63ffffffff9290921682526001600160601b0316602082015260400190565b60ff91909116815260200190565b6001600160601b0391909116815260200190565b6001600160601b0392831681529116602082015260400190565b6001600160a01b03811681146107b957600080fdfe54726962653a20626c6f636b206e756d6265722065786365656473203332206269747354726962653a20746f74616c537570706c792065786365656473203936206269747354726962653a207472616e7366657220616d6f756e742065786365656473207370656e64657220616c6c6f77616e636554726962653a207472616e7366657220616d6f756e7420657863656564732062616c616e636554726962653a20616d6f756e7420657863656564732039362062697473000000a26469706673582212204b5ab84c8ee5befcd5fba2745834ef385b0d07beb1f852bc25562eb10a137ac064736f6c63430006060033a2646970667358221220062ff29caa9fb83e030acb922feb057204cd2a5c38816a82f996dd0f7178683c64736f6c63430006060033

Deployed Bytecode

0x60806040523480156200001157600080fd5b5060043610620002805760003560e01c80639010d07c1162000159578063c1ef303a11620000c9578063e0a200461162000087578063e0a200461462000560578063e1c7392a146200056a578063e43581b81462000574578063e6eb982f146200058b578063eacdd9e814620005a25762000280565b8063c1ef303a14620004fa578063ca15c8731462000511578063cfbd48851462000528578063d5391393146200053f578063d547741f14620005495762000280565b8063a217fddf1162000117578063a217fddf14620004a1578063aa271e1a14620004ab578063af648c3d14620004c2578063b86677fe14620004d9578063b9022dc014620004e35762000280565b80639010d07c146200044857806391d14854146200045f57806394b1d2c014620004765780639711ac34146200048d5780639a9ba4da14620004975762000280565b806336568abe11620001f55780635f06d76111620001b35780635f06d76114620003d3578063611cf19b14620003ea5780636186943e146200040157806384bb0a6b14620004185780638dd9227614620004315762000280565b806336568abe146200036d57806338b7f4461462000384578063395c62e8146200038e5780634334614a14620003a55780634c9f938414620003bc5762000280565b8063248a9ca31162000243578063248a9ca3146200030557806324ea54f4146200032b578063261707fa1462000335578063282c51f3146200034c5780632f2ff15d14620003565762000280565b8063080bf57c14620002855780630900cc33146200029e5780630c68ba2114620002b557806310511f9614620002e4578063201175c214620002fb575b600080fd5b6200029c6200029636600462001496565b620005b9565b005b6200029c620002af36600462001410565b62000683565b620002cc620002c636600462001410565b620006d1565b604051620002db9190620015d1565b60405180910390f35b6200029c620002f536600462001410565b620006fa565b6200029c62000745565b6200031c620003163660046200147d565b620007ee565b604051620002db9190620015dc565b6200031c62000803565b6200029c6200034636600462001410565b6200081c565b6200031c62000858565b6200029c6200036736600462001496565b62000866565b6200029c6200037e36600462001496565b620008b6565b6200031c620008ff565b6200029c6200039f36600462001410565b6200090d565b620002cc620003b636600462001410565b62000949565b6200029c620003cd366004620014d2565b6200095d565b6200029c620003e436600462001410565b62000993565b6200029c620003fb36600462001410565b620009c8565b620002cc6200041236600462001410565b62000a3c565b6200042262000a50565b604051620002db91906200158a565b6200029c6200044236600462001410565b62000a5f565b6200042262000459366004620014d2565b62000a9b565b620002cc6200047036600462001496565b62000ac2565b6200029c6200048736600462001410565b62000ae2565b620002cc62000b1e565b6200042262000b2e565b6200031c62000b43565b620002cc620004bc36600462001410565b62000b48565b6200029c620004d336600462001410565b62000b5c565b6200042262000b98565b6200029c620004f436600462001410565b62000ba7565b6200029c6200050b36600462001410565b62000bdc565b6200031c620005223660046200147d565b62000c18565b6200029c6200053936600462001410565b62000c31565b6200031c62000c6d565b6200029c6200055a36600462001496565b62000c7b565b6200031c62000cbb565b6200029c62000cc9565b620002cc6200058536600462001410565b62000df2565b6200029c6200059c36600462001410565b62000e06565b6200029c620005b33660046200142e565b62000e42565b620005c433620006d1565b620005ec5760405162461bcd60e51b8152600401620005e39062001825565b60405180910390fd5b604051620005fa906200155c565b6040518091039020821415620006245760405162461bcd60e51b8152600401620005e3906200186a565b60405163d547741f60e01b8152309063d547741f906200064b9085908590600401620015e5565b600060405180830381600087803b1580156200066657600080fd5b505af11580156200067b573d6000803e3d6000fd5b505050505050565b6200068e3362000df2565b620006ad5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200152c565b60405180910390208262000c7b565b50565b6000620006f4604051620006e59062001543565b60405180910390208362000ac2565b92915050565b620007053362000df2565b620007245760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200152c565b60405180910390208262000866565b600354600160a01b900460ff1615620007725760405162461bcd60e51b8152600401620005e39062001743565b6003546001600160a01b031633146200079f5760405162461bcd60e51b8152600401620005e39062001702565b6003805460ff60a01b1916600160a01b1790556040517f55728014a7cf4447d0a7e11503cf9ab1ca633624fa3150f8fe149b56e3c026fb90620007e4904290620015dc565b60405180910390a1565b60009081526020819052604090206002015490565b604051620008119062001543565b604051809103902081565b620008273362000df2565b620008465760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620007369062001573565b60405162000811906200152c565b60008281526020819052604090206002015462000887906200047062000fe6565b620008a65760405162461bcd60e51b8152600401620005e39062001683565b620008b2828262000fea565b5050565b620008c062000fe6565b6001600160a01b0316816001600160a01b031614620008f35760405162461bcd60e51b8152600401620005e390620018b6565b620008b282826200105e565b60405162000811906200155c565b620009183362000df2565b620009375760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200155c565b6000620006f4604051620006e5906200152c565b620009683362000df2565b620009875760405162461bcd60e51b8152600401620005e3906200163e565b620008b28282620010d2565b6200099e3362000df2565b620009bd5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce8162001124565b620009d33362000df2565b620009f25760405162461bcd60e51b8152600401620005e3906200163e565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f815cf7ef55cab2e0662e0739c044d60e9a897f882091d48baa1b0b30d28f8a3090600090a250565b6000620006f4604051620006e5906200150d565b6003546001600160a01b031681565b62000a6a3362000df2565b62000a895760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200150d565b600082815260208190526040812062000abb908363ffffffff6200117816565b9392505050565b600082815260208190526040812062000abb908363ffffffff6200118616565b62000aed3362000df2565b62000b0c5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620007369062001543565b600354600160a01b900460ff1681565b6001546201000090046001600160a01b031681565b600081565b6000620006f4604051620006e59062001573565b62000b673362000df2565b62000b865760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf9062001543565b6002546001600160a01b031681565b62000bb23362000df2565b62000bd15760405162461bcd60e51b8152600401620005e3906200163e565b620006ce816200119d565b62000be73362000df2565b62000c065760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200150d565b6000818152602081905260408120620006f490620011e7565b62000c3c3362000df2565b62000c5b5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf9062001573565b604051620008119062001573565b60008281526020819052604090206002015462000c9c906200047062000fe6565b620008f35760405162461bcd60e51b8152600401620005e39062001787565b60405162000811906200150d565b600154610100900460ff168062000ce5575062000ce5620011f4565b8062000cf4575060015460ff16155b62000d135760405162461bcd60e51b8152600401620005e390620017d7565b600154610100900460ff1615801562000d3e576001805460ff1961ff00199091166101001716811790555b62000d493362001207565b60003060405162000d5a90620013dc565b62000d6691906200158a565b604051809103906000f08015801562000d83573d6000803e3d6000fd5b50905062000d918162001124565b6000303360405162000da390620013ea565b62000db09291906200159e565b604051809103906000f08015801562000dcd573d6000803e3d6000fd5b50905062000ddb816200119d565b50508015620006ce576001805461ff001916905550565b6000620006f4604051620006e5906200155c565b62000e113362000df2565b62000e305760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200155c565b62000e4d3362000df2565b62000e6c5760405162461bcd60e51b8152600401620005e3906200163e565b6002546040516370a0823160e01b81526001600160a01b0390911690829082906370a082319062000ea29030906004016200158a565b60206040518083038186803b15801562000ebb57600080fd5b505afa15801562000ed0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ef69190620014f4565b101562000f175760405162461bcd60e51b8152600401620005e390620016d2565b60405163a9059cbb60e01b81526001600160a01b0382169063a9059cbb9062000f479086908690600401620015b8565b602060405180830381600087803b15801562000f6257600080fd5b505af115801562000f77573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f9d91906200145b565b50826001600160a01b03167ffd90a2bc2c0c3cf07693529b256c4173a944fe9f55c1984c09a10a1ad28c11648360405162000fd99190620015dc565b60405180910390a2505050565b3390565b60008281526020819052604090206200100a908263ffffffff6200122816565b15620008b2576200101a62000fe6565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020819052604090206200107e908263ffffffff6200123f16565b15620008b2576200108e62000fe6565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082815260208190526040808220600201549051839285917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a460009182526020829052604090912060020155565b6001805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517fb382b2a2d84e1d7542e0d58950e00d33ddc7a4b379a265768bf3e8640dde4ef190600090a250565b600062000abb838362001256565b600062000abb836001600160a01b0384166200129f565b600280546001600160a01b0319166001600160a01b0383169081179091556040517f9675664499c8d4f09c5268d1696ba833416ed56d870558fa7a722bb8aff5d90f90600090a250565b6000620006f482620012b7565b60006200120130620012bb565b15905090565b620006ce60405162001219906200155c565b604051809103902082620008a6565b600062000abb836001600160a01b038416620012c1565b600062000abb836001600160a01b03841662001310565b815460009082106200127c5760405162461bcd60e51b8152600401620005e390620015fc565b8260000182815481106200128c57fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b3b151590565b6000620012cf83836200129f565b6200130757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620006f4565b506000620006f4565b60008181526001830160205260408120548015620013d157835460001980830191908101906000908790839081106200134557fe5b90600052602060002001549050808760000184815481106200136357fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806200139457fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050620006f4565b6000915050620006f4565b6122c4806200190683390190565b6121098062003bca83390190565b80356001600160a01b0381168114620006f457600080fd5b60006020828403121562001422578081fd5b62000abb8383620013f8565b6000806040838503121562001441578081fd5b6200144d8484620013f8565b946020939093013593505050565b6000602082840312156200146d578081fd5b8151801515811462000abb578182fd5b6000602082840312156200148f578081fd5b5035919050565b60008060408385031215620014a9578182fd5b8235915060208301356001600160a01b0381168114620014c7578182fd5b809150509250929050565b60008060408385031215620014e5578182fd5b50508035926020909101359150565b60006020828403121562001506578081fd5b5051919050565b725043565f434f4e54524f4c4c45525f524f4c4560681b815260130190565b6a4255524e45525f524f4c4560a81b8152600b0190565b6c475541524449414e5f524f4c4560981b8152600d0190565b6a474f5645524e5f524f4c4560a81b8152600b0190565b6a4d494e5445525f524f4c4560a81b8152600b0190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9182526001600160a01b0316602082015260400190565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b60208082526025908201527f5065726d697373696f6e733a2043616c6c6572206973206e6f74206120676f7660408201526432b93737b960d91b606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60408201526e0818591b5a5b881d1bc819dc985b9d608a1b606082015260800190565b602080825260169082015275436f72653a204e6f7420656e6f75676820547269626560501b604082015260600190565b60208082526021908201527f436f72653a2043616c6c6572206973206e6f742047656e657369732047726f756040820152600760fc1b606082015260800190565b60208082526024908201527f436f72653a2047656e657369732047726f757020616c726561647920636f6d706040820152636c65746560e01b606082015260800190565b60208082526030908201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60408201526f2061646d696e20746f207265766f6b6560801b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526025908201527f5065726d697373696f6e733a2043616c6c6572206973206e6f74206120677561604082015264393234b0b760d91b606082015260800190565b6020808252602c908201527f5065726d697373696f6e733a20477561726469616e2063616e6e6f742072657660408201526b37b5b29033b7bb32b93737b960a11b606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560408201526e103937b632b9903337b91039b2b63360891b60608201526080019056fe60806040523480156200001157600080fd5b50604051620022c4380380620022c48339810160408190526200003491620002aa565b604080518082018252600781526611995a481554d160ca1b6020808301918252835180850190945260038085526246454960e81b91850191909152825185949262000080929162000208565b5080516200009690600490602084019062000208565b5050600580546001600160a01b039093166201000002610100600160b01b031960ff199094166012179390931692909217909155506040514690620000db90620002da565b604051908190039020620000f76001600160e01b036200016d16565b805160209182012060408051808201825260018152603160f81b90840152516200014993927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc691869130910162000344565b60405160208183030381529060405280519060200120600781905550505062000370565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620001fd5780601f10620001d157610100808354040283529160200191620001fd565b820191906000526020600020905b815481529060010190602001808311620001df57829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024b57805160ff19168380011785556200027b565b828001600101855582156200027b579182015b828111156200027b5782518255916020019190600101906200025e565b50620002899291506200028d565b5090565b6200020591905b8082111562000289576000815560010162000294565b600060208284031215620002bc578081fd5b81516001600160a01b0381168114620002d3578182fd5b9392505050565b7f454950373132446f6d61696e28737472696e67206e616d652c737472696e672081527f76657273696f6e2c75696e7432353620636861696e49642c6164647265737320602082015271766572696679696e67436f6e74726163742960701b604082015260520190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b611f4480620003806000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806379cc679011610104578063a9059cbb116100a2578063bc701e7511610071578063bc701e751461036c578063d505accf1461037f578063dd62ed3e14610392578063f2f4eb26146103a5576101cf565b8063a9059cbb14610336578063b490589714610349578063b6232c9914610351578063b86677fe14610364576101cf565b80638456cb59116100de5780638456cb59146102fe57806395d89b41146103065780639a9ba4da1461030e578063a457c2d714610323576101cf565b806379cc6790146102c55780637ecebe00146102d857806380009630146102eb576101cf565b8063395093511161017157806342966c681161014b57806342966c681461028f5780635c975abb146102a25780636b6dff0a146102aa57806370a08231146102b2576101cf565b8063395093511461025f5780633f4ba83a1461027257806340c10f191461027c576101cf565b806323b872dd116101ad57806323b872dd1461022757806330adf81f1461023a578063313ce567146102425780633644e51514610257576101cf565b806306fdde03146101d4578063095ea7b3146101f257806318160ddd14610212575b600080fd5b6101dc6103ad565b6040516101e99190611a65565b60405180910390f35b61020561020036600461190f565b610443565b6040516101e991906119ff565b61021a610460565b6040516101e99190611a0a565b61020561023536600461185a565b610466565b61021a6104f3565b61024a610517565b6040516101e99190611e56565b61021a610520565b61020561026d36600461190f565b610526565b61027a61057a565b005b61027a61028a36600461190f565b6106b9565b61027a61029d366004611976565b6107d8565b610205610820565b61021a61082e565b61021a6102c0366004611806565b6108b8565b61027a6102d336600461190f565b6108d3565b61021a6102e6366004611806565b6109e6565b61027a6102f9366004611806565b6109f8565b61027a610aed565b6101dc610c21565b610316610c82565b6040516101e991906119c1565b61020561033136600461190f565b610d0a565b61020561034436600461190f565b610d78565b61021a610d8c565b61027a61035f366004611822565b610d96565b610316610e8e565b61031661037a366004611806565b610ede565b61027a61038d36600461189a565b610ef9565b61021a6103a0366004611822565b611068565b610316611093565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104395780601f1061040e57610100808354040283529160200191610439565b820191906000526020600020905b81548152906001019060200180831161041c57829003601f168201915b5050505050905090565b60006104576104506110a8565b84846110ac565b50600192915050565b60025490565b6000610473848484611160565b6104e98461047f6110a8565b6104e485604051806060016040528060288152602001611ec2602891396001600160a01b038a166000908152600160205260408120906104bd6110a8565b6001600160a01b03168152602081019190915260400160002054919063ffffffff61117b16565b6110ac565b5060019392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b60075481565b60006104576105336110a8565b846104e485600160006105446110a8565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6111a716565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b8906105af9033906004016119c1565b60206040518083038186803b1580156105c757600080fd5b505afa1580156105db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ff919061193a565b8061068a5750600554604051630c68ba2160e01b8152620100009091046001600160a01b031690630c68ba219061063a9033906004016119c1565b60206040518083038186803b15801561065257600080fd5b505afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a919061193a565b6106af5760405162461bcd60e51b81526004016106a690611ba2565b60405180910390fd5b6106b76111d3565b565b6005546040516355138f0d60e11b8152620100009091046001600160a01b03169063aa271e1a906106ee9033906004016119c1565b60206040518083038186803b15801561070657600080fd5b505afa15801561071a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073e919061193a565b61075a5760405162461bcd60e51b81526004016106a690611b29565b610762610820565b1561077f5760405162461bcd60e51b81526004016106a690611cba565b6107898282611242565b336001600160a01b0316826001600160a01b03167fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca836040516107cc9190611a0a565b60405180910390a35050565b6107e181611302565b604051339081907f227fb4b3aae8331f21af5167739c291fefe3afd3c2e08cea44f499e564f486ef90610815908590611a0a565b60405180910390a350565b600554610100900460ff1690565b6000610838610e8e565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161086391906119c1565b60206040518083038186803b15801561087b57600080fd5b505afa15801561088f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061198e565b905090565b6001600160a01b031660009081526020819052604090205490565b60055460405163219a30a560e11b8152620100009091046001600160a01b031690634334614a906109089033906004016119c1565b60206040518083038186803b15801561092057600080fd5b505afa158015610934573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610958919061193a565b6109745760405162461bcd60e51b81526004016106a690611c26565b61097c610820565b156109995760405162461bcd60e51b81526004016106a690611cba565b6109a38282611316565b336001600160a01b0316826001600160a01b03167f227fb4b3aae8331f21af5167739c291fefe3afd3c2e08cea44f499e564f486ef836040516107cc9190611a0a565b60086020526000908152604090205481565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610a2d9033906004016119c1565b60206040518083038186803b158015610a4557600080fd5b505afa158015610a59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7d919061193a565b610a995760405162461bcd60e51b81526004016106a690611dde565b6005805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517fad9400e618eb1344fde53db22397a1b82c765527ecbba3a5c86bcac15090828b90600090a250565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610b229033906004016119c1565b60206040518083038186803b158015610b3a57600080fd5b505afa158015610b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b72919061193a565b80610bfd5750600554604051630c68ba2160e01b8152620100009091046001600160a01b031690630c68ba2190610bad9033906004016119c1565b60206040518083038186803b158015610bc557600080fd5b505afa158015610bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfd919061193a565b610c195760405162461bcd60e51b81526004016106a690611ba2565b6106b76113f8565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104395780601f1061040e57610100808354040283529160200191610439565b6000600560029054906101000a90046001600160a01b03166001600160a01b0316639a9ba4da6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cd257600080fd5b505afa158015610ce6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061195a565b6000610457610d176110a8565b846104e485604051806060016040528060258152602001611eea6025913960016000610d416110a8565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61117b16565b6000610457610d856110a8565b8484611160565b6000610838610c82565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610dcb9033906004016119c1565b60206040518083038186803b158015610de357600080fd5b505afa158015610df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1b919061193a565b610e375760405162461bcd60e51b81526004016106a690611dde565b6001600160a01b0382811660008181526006602052604080822080546001600160a01b0319169486169485179055517f88bb9e877881758e827c849b8a0e38421bd5ff916f4ef79ed65aec74cc04a5da9190a35050565b6000600560029054906101000a90046001600160a01b03166001600160a01b031663b86677fe6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cd257600080fd5b6006602052600090815260409020546001600160a01b031681565b42841015610f195760405162461bcd60e51b81526004016106a690611c5d565b6007546001600160a01b03881660009081526008602090815260408083208054600181019091559051929392610f7a927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d92918d9101611a13565b60405160208183030381529060405280519060200120604051602001610fa19291906119a6565b604051602081830303815290604052805190602001209050600060018286868660405160008152602001604052604051610fde9493929190611a47565b6020604051602081039080840390855afa158015611000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906110365750886001600160a01b0316816001600160a01b0316145b6110525760405162461bcd60e51b81526004016106a690611ce4565b61105d8989896110ac565b505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6005546201000090046001600160a01b031690565b3390565b6001600160a01b0383166110d25760405162461bcd60e51b81526004016106a690611d9a565b6001600160a01b0382166110f85760405162461bcd60e51b81526004016106a690611b60565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590611153908590611a0a565b60405180910390a3505050565b61116b838383611455565b611176838383611576565b505050565b6000818484111561119f5760405162461bcd60e51b81526004016106a69190611a65565b505050900390565b6000828201838110156111cc5760405162461bcd60e51b81526004016106a690611bef565b9392505050565b6111db610820565b6111f75760405162461bcd60e51b81526004016106a690611afb565b6005805461ff00191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61122b6110a8565b60405161123891906119c1565b60405180910390a1565b6001600160a01b0382166112685760405162461bcd60e51b81526004016106a690611e1f565b61127460008383611176565b600254611287908263ffffffff6111a716565b6002556001600160a01b0382166000908152602081905260409020546112b3908263ffffffff6111a716565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107cc908590611a0a565b61131361130d6110a8565b82611316565b50565b6001600160a01b03821661133c5760405162461bcd60e51b81526004016106a690611d14565b61134882600083611176565b61138b81604051806060016040528060228152602001611e7a602291396001600160a01b038516600090815260208190526040902054919063ffffffff61117b16565b6001600160a01b0383166000908152602081905260409020556002546113b7908263ffffffff6117de16565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107cc908590611a0a565b611400610820565b1561141d5760405162461bcd60e51b81526004016106a690611cba565b6005805461ff0019166101001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861122b6110a8565b6001600160a01b03831661147b5760405162461bcd60e51b81526004016106a690611d55565b6001600160a01b0382166114a15760405162461bcd60e51b81526004016106a690611ab8565b6114ac838383611176565b6114ef81604051806060016040528060268152602001611e9c602691396001600160a01b038616600090815260208190526040902054919063ffffffff61117b16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611524908263ffffffff6111a716565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611153908590611a0a565b6001600160a01b038084166000908152600660205260409020541680156115fc57604051636e22230d60e01b81526001600160a01b03821690636e22230d906115c99087908790339088906004016119d5565b600060405180830381600087803b1580156115e357600080fd5b505af11580156115f7573d6000803e3d6000fd5b505050505b6001600160a01b0380841660009081526006602052604090205416801561168257604051636e22230d60e01b81526001600160a01b03821690636e22230d9061164f9088908890339089906004016119d5565b600060405180830381600087803b15801561166957600080fd5b505af115801561167d573d6000803e3d6000fd5b505050505b336000818152600660205260409020546001600160a01b0390811691908716148015906116b85750336001600160a01b03861614155b80156116cc57506001600160a01b03811615155b1561173657604051636e22230d60e01b81526001600160a01b03821690636e22230d90611703908990899033908a906004016119d5565b600060405180830381600087803b15801561171d57600080fd5b505af1158015611731573d6000803e3d6000fd5b505050505b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8546001600160a01b031680156117d557604051636e22230d60e01b81526001600160a01b03821690636e22230d906117a2908a908a9033908b906004016119d5565b600060405180830381600087803b1580156117bc57600080fd5b505af11580156117d0573d6000803e3d6000fd5b505050505b50505050505050565b6000828211156118005760405162461bcd60e51b81526004016106a690611c83565b50900390565b600060208284031215611817578081fd5b81356111cc81611e64565b60008060408385031215611834578081fd5b823561183f81611e64565b9150602083013561184f81611e64565b809150509250929050565b60008060006060848603121561186e578081fd5b833561187981611e64565b9250602084013561188981611e64565b929592945050506040919091013590565b600080600080600080600060e0888a0312156118b4578283fd5b87356118bf81611e64565b965060208801356118cf81611e64565b95506040880135945060608801359350608088013560ff811681146118f2578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611921578182fd5b823561192c81611e64565b946020939093013593505050565b60006020828403121561194b578081fd5b815180151581146111cc578182fd5b60006020828403121561196b578081fd5b81516111cc81611e64565b600060208284031215611987578081fd5b5035919050565b60006020828403121561199f578081fd5b5051919050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611a9157858101830151858201604001528201611a75565b81811115611aa25783604083870101525b50601f01601f1916929092016040019392505050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601f908201527f436f72655265663a2043616c6c6572206973206e6f742061206d696e74657200604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602d908201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160408201526c371037b91033b7bb32b93737b960991b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601f908201527f436f72655265663a2043616c6c6572206973206e6f742061206275726e657200604082015260600190565b6020808252600c908201526b11995a4e881156141254915160a21b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601690820152754665693a20494e56414c49445f5349474e415455524560501b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526021908201527f436f72655265663a2043616c6c6572206973206e6f74206120676f7665726e6f6040820152603960f91b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b60ff91909116815260200190565b6001600160a01b038116811461131357600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122050e890c3b2545b3935ee59eb10f843e1ae9421c4c123c2534bea07e27e8ff0f164736f6c6343000606003360806040526b033b2e3c9fd0803ce80000006000553480156200002157600080fd5b506040516200210938038062002109833981016040819052620000449162000121565b600080546001600160a01b0384168083526003602052604080842080546001600160601b0319166001600160601b0390941693909317909255825491519092917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91620000b2919062000179565b60405180910390a3600180546001600160a01b0319166001600160a01b0383811691909117918290556040517f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f69262000111926000929116906200015f565b60405180910390a150506200019b565b6000806040838503121562000134578182fd5b8251620001418162000182565b6020840151909250620001548162000182565b809150509250929050565b6001600160a01b0392831681529116602082015260400190565b90815260200190565b6001600160a01b03811681146200019857600080fd5b50565b611f5e80620001ab6000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c806370a08231116100c3578063c3cda5201161007c578063c3cda520146102cc578063d505accf146102df578063dd62ed3e146102f2578063e7a324dc14610305578063f1127ed81461030d578063fca3b5aa1461032e57610158565b806370a0823114610258578063782d6fe11461026b5780637ecebe001461028b57806395d89b411461029e578063a9059cbb146102a6578063b4b5ea57146102b957610158565b806330adf81f1161011557806330adf81f146101e0578063313ce567146101e857806340c10f19146101fd578063587cde1e146102125780635c19a95c146102255780636fcfff451461023857610158565b806306fdde031461015d578063075461721461017b578063095ea7b31461019057806318160ddd146101b057806320606b70146101c557806323b872dd146101cd575b600080fd5b610165610341565b6040516101729190611b78565b60405180910390f35b610183610362565b6040516101729190611a9c565b6101a361019e3660046118ab565b610371565b6040516101729190611aca565b6101b861043b565b6040516101729190611ad5565b6101b8610441565b6101a36101db3660046117ff565b610458565b6101b86105a7565b6101f06105b3565b6040516101729190611e1c565b61021061020b3660046118ab565b6105b8565b005b6101836102203660046117b0565b610794565b6102106102333660046117b0565b6107af565b61024b6102463660046117b0565b6107bc565b6040516101729190611dec565b6101b86102663660046117b0565b6107d4565b61027e6102793660046118ab565b6107f8565b6040516101729190611e2a565b6101b86102993660046117b0565b610a06565b610165610a18565b6101a36102b43660046118ab565b610a39565b61027e6102c73660046117b0565b610a80565b6102106102da3660046118d5565b610af1565b6102106102ed36600461183f565b610cd8565b6101b86103003660046117cb565b610fcc565b6101b8611000565b61032061031b36600461192e565b61100c565b604051610172929190611dfd565b61021061033c3660046117b0565b611041565b60405180604001604052806005815260200164547269626560d81b81525081565b6001546001600160a01b031681565b60008060001983141561038757506000196103b7565b6103b4836040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90505b3360008181526002602090815260408083206001600160a01b03891680855292529182902080546001600160601b0319166001600160601b03861617905590519091907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610427908590611e2a565b60405180910390a360019150505b92915050565b60005481565b60405161044d906119f2565b604051809103902081565b6001600160a01b038316600090815260026020908152604080832033808552908352818420548251808401909352601d8352600080516020611f0983398151915293830193909352916001600160601b03169083906104b89086906110d4565b9050866001600160a01b0316836001600160a01b0316141580156104e557506001600160601b0382811614155b1561058f57600061050f8383604051806060016040528060308152602001611eb360309139611103565b6001600160a01b038981166000818152600260209081526040808320948a16808452949091529081902080546001600160601b0319166001600160601b0386161790555192935090917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610585908590611e2a565b60405180910390a3505b61059a878783611142565b5060019695505050505050565b60405161044d90611988565b601281565b6001546001600160a01b031633146105eb5760405162461bcd60e51b81526004016105e290611bcb565b60405180910390fd5b6001600160a01b0382166106115760405162461bcd60e51b81526004016105e290611c02565b6000610640826040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90506000610668600054604051806060016040528060228152602001611e91602291396110d4565b905061068d8183604051806060016040528060228152602001611e9160229139611305565b6001600160601b0390811660009081556001600160a01b0386168152600360209081526040918290205482518084019093528183527f54726962653a207472616e7366657220616d6f756e74206f766572666c6f7773918301919091526106f79216908490611305565b6001600160a01b03851660008181526003602052604080822080546001600160601b0319166001600160601b03959095169490941790935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610761908690611e2a565b60405180910390a36001600160a01b0380851660009081526004602052604081205461078e921684611341565b50505050565b6004602052600090815260409020546001600160a01b031681565b6107b9338261150d565b50565b60066020526000908152604090205463ffffffff1681565b6001600160a01b03166000908152600360205260409020546001600160601b031690565b60004382106108195760405162461bcd60e51b81526004016105e290611db5565b6001600160a01b03831660009081526006602052604090205463ffffffff1680610847576000915050610435565b6001600160a01b038416600090815260056020908152604080832063ffffffff6000198601811685529252909120541683106108c3576001600160a01b03841660009081526005602090815260408083206000199490940163ffffffff1683529290522054600160201b90046001600160601b03169050610435565b6001600160a01b038416600090815260056020908152604080832083805290915290205463ffffffff168310156108fe576000915050610435565b600060001982015b8163ffffffff168163ffffffff1611156109c157600282820363ffffffff16048103610930611771565b506001600160a01b038716600090815260056020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b0316918101919091529087141561099c576020015194506104359350505050565b805163ffffffff168711156109b3578193506109ba565b6001820392505b5050610906565b506001600160a01b038516600090815260056020908152604080832063ffffffff909416835292905220546001600160601b03600160201b9091041691505092915050565b60076020526000908152604090205481565b60405180604001604052806005815260200164545249424560d81b81525081565b600080610a69836040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b9050610a76338583611142565b5060019392505050565b6001600160a01b03811660009081526006602052604081205463ffffffff1680610aab576000610aea565b6001600160a01b0383166000908152600560209081526040808320600019850163ffffffff168452909152902054600160201b90046001600160601b03165b9392505050565b6000604051610aff906119f2565b604080519182900382208282019091526005825264547269626560d81b6020909201919091527febed0dee75115424b4c6084a9ab165e0c99bcf5a44403d7510e1ad1caeaea506610b4e611591565b30604051602001610b629493929190611b36565b6040516020818303038152906040528051906020012090506000604051610b8890611a4d565b604051908190038120610ba3918a908a908a90602001611b12565b60405160208183030381529060405280519060200120905060008282604051602001610bd092919061196d565b604051602081830303815290604052805190602001209050600060018288888860405160008152602001604052604051610c0d9493929190611b5a565b6020604051602081039080840390855afa158015610c2f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610c625760405162461bcd60e51b81526004016105e290611cfc565b6001600160a01b03811660009081526007602052604090208054600181019091558914610ca15760405162461bcd60e51b81526004016105e290611d33565b87421115610cc15760405162461bcd60e51b81526004016105e290611c4c565b610ccb818b61150d565b505050505b505050505050565b6000600019861415610ced5750600019610d1d565b610d1a866040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90505b6000604051610d2b906119f2565b604080519182900382208282019091526005825264547269626560d81b6020909201919091527febed0dee75115424b4c6084a9ab165e0c99bcf5a44403d7510e1ad1caeaea506610d7a611591565b30604051602001610d8e9493929190611b36565b6040516020818303038152906040528051906020012090506000604051610db490611988565b604080519182900382206001600160a01b038d16600090815260076020908152929020805460018101909155610df69391928e928e928e9290918e9101611ade565b60405160208183030381529060405280519060200120905060008282604051602001610e2392919061196d565b604051602081830303815290604052805190602001209050600060018289898960405160008152602001604052604051610e609493929190611b5a565b6020604051602081039080840390855afa158015610e82573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610eb55760405162461bcd60e51b81526004016105e290611cfc565b8b6001600160a01b0316816001600160a01b031614610ee65760405162461bcd60e51b81526004016105e290611ccf565b88421115610f065760405162461bcd60e51b81526004016105e290611c4c565b84600260008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160601b0302191690836001600160601b031602179055508a6001600160a01b03168c6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92587604051610fb69190611e2a565b60405180910390a3505050505050505050505050565b6001600160a01b0391821660009081526002602090815260408083209390941682529190915220546001600160601b031690565b60405161044d90611a4d565b600560209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6001546001600160a01b0316331461106b5760405162461bcd60e51b81526004016105e290611d61565b6001546040517f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f6916110aa916001600160a01b03909116908490611ab0565b60405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b600081600160601b84106110fb5760405162461bcd60e51b81526004016105e29190611b78565b509192915050565b6000836001600160601b0316836001600160601b03161115829061113a5760405162461bcd60e51b81526004016105e29190611b78565b505050900390565b6001600160a01b0383166111685760405162461bcd60e51b81526004016105e290611c83565b6001600160a01b03821661118e5760405162461bcd60e51b81526004016105e290611c02565b6001600160a01b0383166000908152600360209081526040918290205482516060810190935260268084526111d9936001600160601b039092169285929190611ee390830139611103565b6001600160a01b03848116600090815260036020908152604080832080546001600160601b0319166001600160601b039687161790559286168252908290205482518084019093528183527f54726962653a207472616e7366657220616d6f756e74206f766572666c6f7773918301919091526112599216908390611305565b6001600160a01b038381166000818152600360205260409081902080546001600160601b0319166001600160601b0395909516949094179093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906112c6908590611e2a565b60405180910390a36001600160a01b0380841660009081526004602052604080822054858416835291205461130092918216911683611341565b505050565b6000838301826001600160601b0380871690831610156113385760405162461bcd60e51b81526004016105e29190611b78565b50949350505050565b816001600160a01b0316836001600160a01b03161415801561136c57506000816001600160601b0316115b15611300576001600160a01b03831615611441576001600160a01b03831660009081526006602052604081205463ffffffff1690816113ac5760006113eb565b6001600160a01b0385166000908152600560209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b9050600061142f82856040518060400160405280601d81526020017f54726962653a20766f746520616d6f756e7420756e646572666c6f7773000000815250611103565b905061143d86848484611595565b5050505b6001600160a01b03821615611300576001600160a01b03821660009081526006602052604081205463ffffffff16908161147c5760006114bb565b6001600160a01b0384166000908152600560209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b905060006114ff82856040518060400160405280601c81526020017f54726962653a20766f746520616d6f756e74206f766572666c6f777300000000815250611305565b9050610cd085848484611595565b6001600160a01b03808316600081815260046020818152604080842080546003845282862054949093528787166001600160a01b031984168117909155905191909516946001600160601b039092169391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a461078e828483611341565b4690565b60006115b943604051806060016040528060238152602001611e6e6023913961174a565b905060008463ffffffff1611801561160257506001600160a01b038516600090815260056020908152604080832063ffffffff6000198901811685529252909120548282169116145b15611661576001600160a01b0385166000908152600560209081526040808320600019880163ffffffff168452909152902080546fffffffffffffffffffffffff000000001916600160201b6001600160601b03851602179055611700565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000818152600583528781208c871682528352878120965187549451909516600160201b026fffffffffffffffffffffffff000000001995871663ffffffff19958616179590951694909417909555938252600690935292909220805460018801909316929091169190911790555b846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724848460405161173b929190611e3e565b60405180910390a25050505050565b600081600160201b84106110fb5760405162461bcd60e51b81526004016105e29190611b78565b604080518082019091526000808252602082015290565b80356001600160a01b038116811461043557600080fd5b803560ff8116811461043557600080fd5b6000602082840312156117c1578081fd5b610aea8383611788565b600080604083850312156117dd578081fd5b6117e78484611788565b91506117f68460208501611788565b90509250929050565b600080600060608486031215611813578081fd5b833561181e81611e58565b9250602084013561182e81611e58565b929592945050506040919091013590565b600080600080600080600060e0888a031215611859578283fd5b6118638989611788565b96506118728960208a01611788565b9550604088013594506060880135935061188f8960808a0161179f565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156118bd578182fd5b6118c78484611788565b946020939093013593505050565b60008060008060008060c087890312156118ed578182fd5b6118f78888611788565b95506020870135945060408701359350611914886060890161179f565b92506080870135915060a087013590509295509295509295565b60008060408385031215611940578182fd5b61194a8484611788565b9150602083013563ffffffff81168114611962578182fd5b809150509250929050565b61190160f01b81526002810192909252602282015260420190565b7f5065726d69742861646472657373206f776e65722c616464726573732073706581527f6e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63656020820152712c75696e7432353620646561646c696e652960701b604082015260520190565b7f454950373132446f6d61696e28737472696e67206e616d652c75696e7432353681527f20636861696e49642c6164647265737320766572696679696e67436f6e74726160208201526263742960e81b604082015260430190565b7f44656c65676174696f6e28616464726573732064656c6567617465652c75696e81527f74323536206e6f6e63652c75696e7432353620657870697279290000000000006020820152603a0190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611ba457858101830151858201604001528201611b88565b81811115611bb55783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601f908201527f54726962653a206f6e6c7920746865206d696e7465722063616e206d696e7400604082015260600190565b6020808252602a908201527f54726962653a2063616e6e6f74207472616e7366657220746f20746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526018908201527f54726962653a207369676e617475726520657870697265640000000000000000604082015260600190565b6020808252602c908201527f54726962653a2063616e6e6f74207472616e736665722066726f6d207468652060408201526b7a65726f206164647265737360a01b606082015260800190565b602080825260139082015272151c9a58994e881d5b985d5d1a1bdc9a5e9959606a1b604082015260600190565b60208082526018908201527f54726962653a20696e76616c6964207369676e61747572650000000000000000604082015260600190565b60208082526014908201527354726962653a20696e76616c6964206e6f6e636560601b604082015260600190565b60208082526034908201527f54726962653a206f6e6c7920746865206d696e7465722063616e206368616e676040820152736520746865206d696e746572206164647265737360601b606082015260800190565b60208082526019908201527f54726962653a206e6f74207965742064657465726d696e656400000000000000604082015260600190565b63ffffffff91909116815260200190565b63ffffffff9290921682526001600160601b0316602082015260400190565b60ff91909116815260200190565b6001600160601b0391909116815260200190565b6001600160601b0392831681529116602082015260400190565b6001600160a01b03811681146107b957600080fdfe54726962653a20626c6f636b206e756d6265722065786365656473203332206269747354726962653a20746f74616c537570706c792065786365656473203936206269747354726962653a207472616e7366657220616d6f756e742065786365656473207370656e64657220616c6c6f77616e636554726962653a207472616e7366657220616d6f756e7420657863656564732062616c616e636554726962653a20616d6f756e7420657863656564732039362062697473000000a26469706673582212204b5ab84c8ee5befcd5fba2745834ef385b0d07beb1f852bc25562eb10a137ac064736f6c63430006060033a2646970667358221220062ff29caa9fb83e030acb922feb057204cd2a5c38816a82f996dd0f7178683c64736f6c63430006060033

Deployed Bytecode Sourcemap

385:2677:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;385:2677:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;4081:347:3;;;;;;;;;:::i;:::-;;3100:117;;;;;;;;;:::i;5781:130::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;1996:115;;;;;;;;;:::i;2387:441:0:-;;;:::i;4282:112:10:-;;;;;;;;;:::i;:::-;;;;;;;;561:66:3;;;:::i;1796:115::-;;;;;;;;;:::i;273:62::-;;;:::i;4644:223:10:-;;;;;;;;;:::i;5818:205::-;;;;;;;;;:::i;493:62:3:-;;;:::i;2474:121::-;;;;;;;;;:::i;4827:128::-;;;;;;;;;:::i;1552:159::-;;;;;;;;;:::i;1186:93:0:-;;;;;;;;;:::i;1577:200::-;;;;;;;;;:::i;5098:179:3:-;;;;;;;;;:::i;668:36:0:-;;;:::i;:::-;;;;;;;;3325:174:3;;;;;;;;;:::i;3965:136:10:-;;;;;;;;;:::i;2950:137::-;;;;;;;;;:::i;2686:123:3:-;;;;;;;;;:::i;770:45:0:-;;;:::i;491:24::-;;;:::i;1727:49:10:-;;;:::i;4564:128:3:-;;;;;;;;;:::i;3808:125::-;;;;;;;;;:::i;576:28:0:-;;;:::i;1376:97::-;;;;;;;;;:::i;2211:172:3:-;;;;;;;;;:::i;3255:125:10:-;;;;;;;;;:::i;2896:117:3:-;;;;;;;;;:::i;341:62::-;;;:::i;5101:226:10:-;;;;;;;;;:::i;409:78:3:-;;;:::i;822:271:0:-;;;:::i;5462:180:3:-;;;;;;;;;:::i;3592:123::-;;;;;;;;;:::i;1943:349:0:-;;;;;;;;;:::i;4081:347:3:-;1259:22;1270:10;1259;:22::i;:::-;1251:72;;;;-1:-1:-1;;;1251:72:3;;;;;;;;;;;;;;;;;531:24:::1;;;;;;;;;;;;;;4213:4;:19;;4205:76;;;;-1:-1:-1::0;;;4205:76:3::1;;;;;;;;;4391:30;::::0;-1:-1:-1;;;4391:30:3;;:4:::1;::::0;:15:::1;::::0;:30:::1;::::0;4407:4;;4413:7;;4391:30:::1;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;4391:30:3;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;4391:30:3;;;;4081:347:::0;;:::o;3100:117::-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;3179:31:::1;311:24;;;;;;;;;;;;;;3203:6;3179:10;:31::i;:::-;3100:117:::0;:::o;5781:130::-;5849:4;5872:32;601:26;;;;;;;;;;;;;;5895:8;5872:7;:32::i;:::-;5865:39;5781:130;-1:-1:-1;;5781:130:3:o;1996:115::-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2074:30:::1;311:24;;;;;;;;;;;;;;2097:6;2074:9;:30::i;2387:441:0:-:0;2469:24;;-1:-1:-1;;;2469:24:0;;;;2468:25;2447:108;;;;-1:-1:-1;;;2447:108:0;;;;;;;;;2600:12;;-1:-1:-1;;;;;2600:12:0;2586:10;:26;2565:106;;;;-1:-1:-1;;;2565:106:0;;;;;;;;;2682:24;:31;;-1:-1:-1;;;;2682:31:0;-1:-1:-1;;;2682:31:0;;;2783:38;;;;;;2805:15;;2783:38;;;;;;;;;;2387:441::o;4282:112:10:-;4339:7;4365:12;;;;;;;;;;:22;;;;4282:112::o;561:66:3:-;601:26;;;;;;;;;;;;;;561:66;:::o;1796:115::-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1874:30:::1;379:24;;;;;;273:62:::0;311:24;;;;;;4644:223:10;4735:6;:12;;;;;;;;;;:22;;;4727:45;;4759:12;:10;:12::i;4727:45::-;4719:105;;;;-1:-1:-1;;;4719:105:10;;;;;;;;;4835:25;4846:4;4852:7;4835:10;:25::i;:::-;4644:223;;:::o;5818:205::-;5915:12;:10;:12::i;:::-;-1:-1:-1;;;;;5904:23:10;:7;-1:-1:-1;;;;;5904:23:10;;5896:83;;;;-1:-1:-1;;;5896:83:10;;;;;;;;;5990:26;6002:4;6008:7;5990:11;:26::i;493:62:3:-;531:24;;;;;;2474:121;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2556:32:::1;531:24;;;;;;4827:128:::0;4895:4;4918:30;311:24;;;;;;1552:159;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1674:30:::1;1688:4;1694:9;1674:13;:30::i;1186:93:0:-:0;1108:22:3;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1258:14:0::1;1266:5;1258:7;:14::i;1577:200::-:0;1108:22:3;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1694:12:0::1;:28:::0;;-1:-1:-1;;;;;;1694:28:0::1;-1:-1:-1::0;;;;;1694:28:0;::::1;::::0;;::::1;::::0;;;1737:33:::1;::::0;::::1;::::0;-1:-1:-1;;1737:33:0::1;1577:200:::0;:::o;5098:179:3:-;5205:4;5232:38;455:32;;;;;;668:36:0;;;-1:-1:-1;;;;;668:36:0;;:::o;3325:174:3:-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;3446:46:::1;455:32;;;;;;3965:136:10::0;4038:7;4064:12;;;;;;;;;;:30;;4088:5;4064:30;:23;:30;:::i;:::-;4057:37;3965:136;-1:-1:-1;;;3965:136:10:o;2950:137::-;3019:4;3042:12;;;;;;;;;;:38;;3072:7;3042:38;:29;:38;:::i;2686:123:3:-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2768:34:::1;601:26;;;;;;770:45:0::0;;;-1:-1:-1;;;770:45:0;;;;;:::o;491:24::-;;;;;;-1:-1:-1;;;;;491:24:0;;:::o;1727:49:10:-;1772:4;1727:49;:::o;4564:128:3:-;4632:4;4655:30;379:24;;;;;;3808:125;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;3891:35:::1;601:26;;;;;;576:28:0::0;;;-1:-1:-1;;;;;576:28:0;;:::o;1376:97::-;1108:22:3;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1450:16:0::1;1460:5;1450:9;:16::i;2211:172:3:-:0;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2331:45:::1;455:32;;;;;;3255:125:10::0;3318:7;3344:12;;;;;;;;;;:29;;:27;:29::i;2896:117:3:-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2975:31:::1;379:24;;;;;;341:62:::0;379:24;;;;;;5101:226:10;5193:6;:12;;;;;;;;;;:22;;;5185:45;;5217:12;:10;:12::i;5185:45::-;5177:106;;;;-1:-1:-1;;;5177:106:10;;;;;;;;409:78:3;455:32;;;;;;822:271:0;1501:13:12;;;;;;;;:33;;;1518:16;:14;:16::i;:::-;1501:50;;;-1:-1:-1;1539:12:12;;;;1538:13;1501:50;1493:109;;;;-1:-1:-1;;;1493:109:12;;;;;;;;;1636:13;;;;;;;1635:14;1659:98;;;;1709:4;1693:20;;-1:-1:-1;;;;1693:20:12;;;;;1727:19;;;;;1659:98;878:26:0::1;893:10;878:14;:26::i;:::-;923:8;950:4;934:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;934:22:0;923:33;;966:22;982:4;966:7;:22::i;:::-;999:12;1032:4;1039:10;1014:36;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;1014:36:0;999:51;;1060:26;1078:6;1060:9;:26::i;:::-;1767:1:12;;1783:14:::0;1779:66;;;1813:13;:21;;-1:-1:-1;;1813:21:12;;;822:271:0;:::o;5462:180:3:-;5578:4;5605:30;531:24;;;;;;3592:123;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;3675:33:::1;531:24;;;;;;1943:349:0::0;1108:22:3;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2079:5:0::1;::::0;2115:31:::1;::::0;-1:-1:-1;;;2115:31:0;;-1:-1:-1;;;;;2079:5:0;;::::1;::::0;2150:6;;2079:5;;2115:16:::1;::::0;:31:::1;::::0;2140:4:::1;::::0;2115:31:::1;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;2115:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;2115:31:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2115:31:0;;;;;;;;;:41;;2094:110;;;;-1:-1:-1::0;;;2094:110:0::1;;;;;;;;;2215:27;::::0;-1:-1:-1;;;2215:27:0;;-1:-1:-1;;;;;2215:15:0;::::1;::::0;::::1;::::0;:27:::1;::::0;2231:2;;2235:6;;2215:27:::1;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;2215:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;2215:27:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2215:27:0;;;;;;;;;;2274:2;-1:-1:-1::0;;;;;2258:27:0::1;;2278:6;2258:27;;;;;;;;;;;;;;;1203:1:3;1943:349:0::0;;:::o;598:104:17:-;685:10;598:104;:::o;7025:184:10:-;7098:6;:12;;;;;;;;;;:33;;7123:7;7098:33;:24;:33;:::i;:::-;7094:109;;;7179:12;:10;:12::i;:::-;-1:-1:-1;;;;;7152:40:10;7170:7;-1:-1:-1;;;;;7152:40:10;7164:4;7152:40;;;;;;;;;;7025:184;;:::o;7215:188::-;7289:6;:12;;;;;;;;;;:36;;7317:7;7289:36;:27;:36;:::i;:::-;7285:112;;;7373:12;:10;:12::i;:::-;-1:-1:-1;;;;;7346:40:10;7364:7;-1:-1:-1;;;;;7346:40:10;7358:4;7346:40;;;;;;;;;;7215:188;;:::o;6823:196::-;6934:6;:12;;;;;;;;;;;:22;;;6911:57;;6958:9;;6941:4;;6911:57;;6934:6;6911:57;6978:6;:12;;;;;;;;;;;:22;;:34;6823:196::o;2834:106:0:-;2885:3;:17;;-1:-1:-1;;;;;;2885:17:0;;-1:-1:-1;;;;;2885:17:0;;;;;;;;;;;;2917:16;;;;-1:-1:-1;;2917:16:0;2834:106;:::o;7677:156:18:-;7751:7;7801:22;7805:3;7817:5;7801:3;:22::i;6984:165::-;7064:4;7087:55;7097:3;-1:-1:-1;;;;;7117:23:18;;7087:9;:55::i;2946:114:0:-;2999:5;:21;;-1:-1:-1;;;;;;2999:21:0;-1:-1:-1;;;;;2999:21:0;;;;;;;;3035:18;;;;-1:-1:-1;;3035:18:0;2946:114;:::o;7230:115:18:-;7293:7;7319:19;7327:3;7319:7;:19::i;1941:112:12:-;1989:4;2013:33;2040:4;2013:18;:33::i;:::-;2012:34;2005:41;;1941:112;:::o;5917:101:3:-;5978:33;531:24;;;;;;;;;;;;;;6002:8;5978:10;:33::i;6429:150:18:-;6499:4;6522:50;6527:3;-1:-1:-1;;;;;6547:23:18;;6522:4;:50::i;6747:156::-;6820:4;6843:53;6851:3;-1:-1:-1;;;;;6871:23:18;;6843:7;:53::i;4452:201::-;4546:18;;4519:7;;4546:26;-1:-1:-1;4538:73:18;;;;-1:-1:-1;;;4538:73:18;;;;;;;;;4628:3;:11;;4640:5;4628:18;;;;;;;;;;;;;;;;4621:25;;4452:201;;;;:::o;3805:127::-;3878:4;3901:19;;;:12;;;;;:19;;;;;;:24;;;3805:127::o;4013:107::-;4095:18;;4013:107::o;726:413:16:-;1086:20;1124:8;;;726:413::o;1640:404:18:-;1703:4;1724:21;1734:3;1739:5;1724:9;:21::i;:::-;1719:319;;-1:-1:-1;27:10;;39:1;23:18;;;45:23;;1761:11:18;:23;;;;;;;;;;;;;1941:18;;1919:19;;;:12;;;:19;;;;;;:40;;;;1973:11;;1719:319;-1:-1:-1;2022:5:18;2015:12;;2212:1512;2278:4;2415:19;;;:12;;;:19;;;;;;2449:15;;2445:1273;;2878:18;;-1:-1:-1;;2830:14:18;;;;2878:22;;;;2806:21;;2878:3;;:22;;3160;;;;;;;;;;;;;;3140:42;;3303:9;3274:3;:11;;3286:13;3274:26;;;;;;;;;;;;;;;;;;;:38;;;;3378:23;;;3420:1;3378:12;;;:23;;;;;;3404:17;;;3378:43;;3527:17;;3378:3;;3527:17;;;;;;;;;;;;;;;;;;;;;;3619:3;:12;;:19;3632:5;3619:19;;;;;;;;;;;3612:26;;;3660:4;3653:11;;;;;;;;2445:1273;3702:5;3695:12;;;;;385:2677:0;;;;;;;;:::o;:::-;;;;;;;;:::o;5:130:-1:-;72:20;;-1:-1;;;;;19625:54;;20778:35;;20768:2;;20827:1;;20817:12;692:241;;796:2;784:9;775:7;771:23;767:32;764:2;;;-1:-1;;802:12;764:2;864:53;909:7;885:22;864:53;;940:366;;;1061:2;1049:9;1040:7;1036:23;1032:32;1029:2;;;-1:-1;;1067:12;1029:2;1129:53;1174:7;1150:22;1129:53;;;1119:63;1219:2;1258:22;;;;481:20;;-1:-1;;;1023:283;1313:257;;1425:2;1413:9;1404:7;1400:23;1396:32;1393:2;;;-1:-1;;1431:12;1393:2;223:6;217:13;20924:5;19458:13;19451:21;20902:5;20899:32;20889:2;;-1:-1;;20935:12;1577:241;;1681:2;1669:9;1660:7;1656:23;1652:32;1649:2;;;-1:-1;;1687:12;1649:2;-1:-1;344:20;;1643:175;-1:-1;1643:175;1825:366;;;1946:2;1934:9;1925:7;1921:23;1917:32;1914:2;;;-1:-1;;1952:12;1914:2;344:20;;;-1:-1;2104:2;2143:22;;72:20;-1:-1;;;;;19625:54;;20778:35;;20768:2;;-1:-1;;20817:12;20768:2;2112:63;;;;1908:283;;;;;;2198:366;;;2319:2;2307:9;2298:7;2294:23;2290:32;2287:2;;;-1:-1;;2325:12;2287:2;-1:-1;;344:20;;;2477:2;2516:22;;;344:20;;-1:-1;2281:283;2944:263;;3059:2;3047:9;3038:7;3034:23;3030:32;3027:2;;;-1:-1;;3065:12;3027:2;-1:-1;629:13;;3021:186;-1:-1;3021:186;10146:372;-1:-1;;;5076:42;;5060:2;5137:12;;10326:192;10525:372;-1:-1;;;6164:34;;6148:2;6217:12;;10705:192;10904:372;-1:-1;;;6520:36;;6504:2;6575:12;;11084:192;11283:372;-1:-1;;;8425:34;;8409:2;8478:12;;11463:192;11662:372;-1:-1;;;8781:34;;8765:2;8834:12;;11842:192;12041:213;-1:-1;;;;;19625:54;;;;3434:37;;12159:2;12144:18;;12130:124;12261:340;-1:-1;;;;;19625:54;;;3434:37;;19625:54;;12587:2;12572:18;;3293:58;12415:2;12400:18;;12386:215;12608:324;-1:-1;;;;;19625:54;;;;3434:37;;12918:2;12903:18;;3665:37;12754:2;12739:18;;12725:207;12939:201;19458:13;;19451:21;3548:34;;13051:2;13036:18;;13022:118;13147:213;3665:37;;;13265:2;13250:18;;13236:124;13367:324;3665:37;;;-1:-1;;;;;19625:54;13677:2;13662:18;;3434:37;13513:2;13498:18;;13484:207;14194:407;14385:2;14399:47;;;4261:2;14370:18;;;19072:19;4297:34;19112:14;;;4277:55;-1:-1;;;4352:12;;;4345:26;4390:12;;;14356:245;14608:407;14799:2;14813:47;;;4641:2;14784:18;;;19072:19;4677:34;19112:14;;;4657:55;-1:-1;;;4732:12;;;4725:29;4773:12;;;14770:245;15022:407;15213:2;15227:47;;;5388:2;15198:18;;;19072:19;5424:34;19112:14;;;5404:55;-1:-1;;;5479:12;;;5472:39;5530:12;;;15184:245;15436:407;15627:2;15641:47;;;5781:2;15612:18;;;19072:19;-1:-1;;;19112:14;;;5797:45;5861:12;;;15598:245;15850:407;16041:2;16055:47;;;6826:2;16026:18;;;19072:19;6862:34;19112:14;;;6842:55;-1:-1;;;6917:12;;;6910:25;6954:12;;;16012:245;16264:407;16455:2;16469:47;;;7205:2;16440:18;;;19072:19;7241:34;19112:14;;;7221:55;-1:-1;;;7296:12;;;7289:28;7336:12;;;16426:245;16678:407;16869:2;16883:47;;;7587:2;16854:18;;;19072:19;7623:34;19112:14;;;7603:55;-1:-1;;;7678:12;;;7671:40;7730:12;;;16840:245;17092:407;17283:2;17297:47;;;7981:2;17268:18;;;19072:19;8017:34;19112:14;;;7997:55;-1:-1;;;8072:12;;;8065:38;8122:12;;;17254:245;17506:407;17697:2;17711:47;;;9085:2;17682:18;;;19072:19;9121:34;19112:14;;;9101:55;-1:-1;;;9176:12;;;9169:29;9217:12;;;17668:245;17920:407;18111:2;18125:47;;;9468:2;18096:18;;;19072:19;9504:34;19112:14;;;9484:55;-1:-1;;;9559:12;;;9552:36;9607:12;;;18082:245;18334:407;18525:2;18539:47;;;9858:2;18510:18;;;19072:19;9894:34;19112:14;;;9874:55;-1:-1;;;9949:12;;;9942:39;10000:12;;;18496:245

Swarm Source

ipfs://062ff29caa9fb83e030acb922feb057204cd2a5c38816a82f996dd0f7178683c
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.