Contract 0xcd2539dfb06d3bf708d875c045094c89f60a60f6

Contract Overview

Balance:
0 BNB

Token:
Txn Hash
Block
From
To
Value [Txn Fee]
0x586370ef1c7268a89f535c53a64e0d3b2fc0e9a0b335f8222d838f22855b0324108524162021-07-23 20:57:2913 days 16 mins ago0xaadd94e2b39e39b13828d51784e79ad1afc8e9e9 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00186903
0x981ae0691a998a4fa206361be415d7d3d0146b41890a9fd5d6feba9f7844a836108277402021-07-23 0:09:4513 days 21 hrs ago0xaadd94e2b39e39b13828d51784e79ad1afc8e9e9 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00181325
0x52291bfb180cb449c4299eabe49a75323822be4452f43a911642b82384bb3035108277042021-07-23 0:07:5713 days 21 hrs ago0xaadd94e2b39e39b13828d51784e79ad1afc8e9e9 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0020638
0x9de771634c4d54d5a3446a5ef585dc37d00ef48e15544f262c1894fa6ece520d108275602021-07-23 0:00:4513 days 21 hrs ago0x14d30436dd1a318493381f878eae7edc02c3b202 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00186903
0x3767befc0c60c5cca68a9a8288dbecc6cd667f9a210bf25a481dff0ed19176f7108213442021-07-22 18:48:3814 days 2 hrs ago0x14d30436dd1a318493381f878eae7edc02c3b202 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0017568
0xa0b3521d935307b7a15aea43269ed9446e8b38b620383e659733147ab621281f108212962021-07-22 18:46:1414 days 2 hrs ago0x14d30436dd1a318493381f878eae7edc02c3b202 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0020638
0xcd5b5ad31e8f8c2545c7acdc5c9dc3a127c57f98d2639b497ceb0d9b67788db8108200502021-07-22 17:43:5614 days 3 hrs ago0xf0ac3431af8e2ac38678cfb0b6cc887700039fbb IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00129204
0x3ee957f1f78cafe611634fd2ddac460bff3e5b6ce6671e74aab001c910b1567e108199742021-07-22 17:40:0814 days 3 hrs ago0xf0ac3431af8e2ac38678cfb0b6cc887700039fbb IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00186903
0x72dc3d2dcd94d91f77803c5623feb39a9fad477ce201619ed6f43589182b9c9e108121462021-07-22 11:08:2614 days 10 hrs ago0xf0ac3431af8e2ac38678cfb0b6cc887700039fbb IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0016068
0x3df22b33b9c0d54a9f11ec0044a1ed185a659473d6e9866aa80bb6780f0571a1108121222021-07-22 11:07:1414 days 10 hrs ago0xf0ac3431af8e2ac38678cfb0b6cc887700039fbb IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00186903
0x6acf8e0452ac56532f23814f77b8adc59d9ff26bf631b360a88a17c87ebb895e108121162021-07-22 11:06:5614 days 10 hrs ago0xf0ac3431af8e2ac38678cfb0b6cc887700039fbb IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00224913
0x8f1fb62267d85a8b874c029b1c5a7e465316a318525b3f8af0a1288b83a61d7d108121022021-07-22 11:06:1414 days 10 hrs ago0x0734e898d0b14471da232303037a330189e66c1a IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00186903
0x691749f2db1cf99e60bc4b1c6567944727001bd318722d46f845415e71cd0d79108120912021-07-22 11:05:4114 days 10 hrs ago0xb36a5ee119072296711b8ace01b31686e2a7ed63 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00186903
0x9f6f76af0d413d892dce648553569f3b466105151b10599694c4537b7ab7bef8108118422021-07-22 10:53:1414 days 10 hrs ago0xb36a5ee119072296711b8ace01b31686e2a7ed63 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00125004
0xd50cba526eaf55ad264b6ad83f67472be4b13f8dea89e7d7619e898b2bbcfddd108073072021-07-22 7:05:4414 days 14 hrs ago0x14d30436dd1a318493381f878eae7edc02c3b202 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0020638
0x4441f547173c738addac961652f2dc8458dcf02ea29d95ce82c8fb24714e608c108071722021-07-22 6:58:5914 days 14 hrs ago0xb36a5ee119072296711b8ace01b31686e2a7ed63 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0020638
0xb87c9ab79c3cf67e1310c0370ec72d43aef7eab5bfec4a04bcb5654a7da77316108067982021-07-22 6:40:1714 days 14 hrs ago0xac11304308621059f6622a6f7d090e1c573c79a8 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0020638
0xde97d560bd2e4ef310b2e561f8ed545eb18f2b976fe47e1bb559beb346959d3a108067882021-07-22 6:39:4714 days 14 hrs ago0x64a6e6fc0817ad1940b92ed2d6d2ffb6f0a59557 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00129204
0x4e8010e9c4cd6de1a460113eaf6142e5947b299bd45eaa09cda2c1930e205e24108057802021-07-22 5:49:2314 days 15 hrs ago0x64a6e6fc0817ad1940b92ed2d6d2ffb6f0a59557 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0020638
0xdcfeea0ca1a2ddd34908740108529215fbdeb05502fc6a8407fd32c92ba6d649108057142021-07-22 5:46:0514 days 15 hrs ago0xf0ac3431af8e2ac38678cfb0b6cc887700039fbb IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00202273
0x1c4fceabed438ea80e5ef3f4e9e36d9fdd1c38d31f1ed6c54283fbd2492646b3108057042021-07-22 5:45:3514 days 15 hrs ago0x0734e898d0b14471da232303037a330189e66c1a IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00134948
0x2f2695a4bddc60afb907051e194bbcd17cfca373180095e9fff534441a33ec1d108056772021-07-22 5:44:1414 days 15 hrs ago0x0734e898d0b14471da232303037a330189e66c1a IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.0020638
0x8fd556dcc863f579dbc439798fc791dedd0f87a46edcf51460ad853773aaed87108056602021-07-22 5:43:2314 days 15 hrs ago0xaadd94e2b39e39b13828d51784e79ad1afc8e9e9 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00146005
0x77fcf61351412b3e17c94b956dab920fdf9edf07cf902468b876e02918616b0e108055442021-07-22 5:37:3514 days 15 hrs ago0xaadd94e2b39e39b13828d51784e79ad1afc8e9e9 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00186903
0x3e6dbba5c6b0fce21842b7d4840477f8226dd7fea1788bdb09cf51a0a7affefc108055342021-07-22 5:37:0514 days 15 hrs ago0xaadd94e2b39e39b13828d51784e79ad1afc8e9e9 IN  0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB0.00129204
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x42eea9eeace7221c776af3d2e3dd2f932683e78ae6482b95864e114f97508e3d108524322021-07-23 20:58:1713 days 15 mins ago 0xa555fc018435bef5a13c6c6870a9d4c11dec329c 0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB
0x586370ef1c7268a89f535c53a64e0d3b2fc0e9a0b335f8222d838f22855b0324108524162021-07-23 20:57:2913 days 16 mins ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x84b9b910527ad5c03a9ca831909e21e236ea7b060 BNB
0x586370ef1c7268a89f535c53a64e0d3b2fc0e9a0b335f8222d838f22855b0324108524162021-07-23 20:57:2913 days 16 mins ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x84b9b910527ad5c03a9ca831909e21e236ea7b060 BNB
0x981ae0691a998a4fa206361be415d7d3d0146b41890a9fd5d6feba9f7844a836108277402021-07-23 0:09:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x981ae0691a998a4fa206361be415d7d3d0146b41890a9fd5d6feba9f7844a836108277402021-07-23 0:09:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x981ae0691a998a4fa206361be415d7d3d0146b41890a9fd5d6feba9f7844a836108277402021-07-23 0:09:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x981ae0691a998a4fa206361be415d7d3d0146b41890a9fd5d6feba9f7844a836108277402021-07-23 0:09:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x981ae0691a998a4fa206361be415d7d3d0146b41890a9fd5d6feba9f7844a836108277402021-07-23 0:09:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x981ae0691a998a4fa206361be415d7d3d0146b41890a9fd5d6feba9f7844a836108277402021-07-23 0:09:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x4adac260c5a33874545c98c1f70c23c9169290490 BNB
0x981ae0691a998a4fa206361be415d7d3d0146b41890a9fd5d6feba9f7844a836108277402021-07-23 0:09:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x8e0f86d82bd1c13957bcb8d7b357653f74a6d1ce8bdd1fd8c500f99a41b18251108277202021-07-23 0:08:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x4adac260c5a33874545c98c1f70c23c9169290490 BNB
0x8e0f86d82bd1c13957bcb8d7b357653f74a6d1ce8bdd1fd8c500f99a41b18251108277202021-07-23 0:08:4513 days 21 hrs ago 0xa555fc018435bef5a13c6c6870a9d4c11dec329c 0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB
0x52291bfb180cb449c4299eabe49a75323822be4452f43a911642b82384bb3035108277042021-07-23 0:07:5713 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x84b9b910527ad5c03a9ca831909e21e236ea7b060 BNB
0x52291bfb180cb449c4299eabe49a75323822be4452f43a911642b82384bb3035108277042021-07-23 0:07:5713 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x52291bfb180cb449c4299eabe49a75323822be4452f43a911642b82384bb3035108277042021-07-23 0:07:5713 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x52291bfb180cb449c4299eabe49a75323822be4452f43a911642b82384bb3035108277042021-07-23 0:07:5713 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x84b9b910527ad5c03a9ca831909e21e236ea7b060 BNB
0x57e3e00d78161f034a2c09ebfa273e5c1317fe8bd9069f542260eefaee4c47ed108275762021-07-23 0:01:3313 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x4adac260c5a33874545c98c1f70c23c9169290490 BNB
0x57e3e00d78161f034a2c09ebfa273e5c1317fe8bd9069f542260eefaee4c47ed108275762021-07-23 0:01:3313 days 21 hrs ago 0xa555fc018435bef5a13c6c6870a9d4c11dec329c 0xcd2539dfb06d3bf708d875c045094c89f60a60f60 BNB
0x9de771634c4d54d5a3446a5ef585dc37d00ef48e15544f262c1894fa6ece520d108275602021-07-23 0:00:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x84b9b910527ad5c03a9ca831909e21e236ea7b060 BNB
0x9de771634c4d54d5a3446a5ef585dc37d00ef48e15544f262c1894fa6ece520d108275602021-07-23 0:00:4513 days 21 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x84b9b910527ad5c03a9ca831909e21e236ea7b060 BNB
0x3767befc0c60c5cca68a9a8288dbecc6cd667f9a210bf25a481dff0ed19176f7108213442021-07-22 18:48:3814 days 2 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x3767befc0c60c5cca68a9a8288dbecc6cd667f9a210bf25a481dff0ed19176f7108213442021-07-22 18:48:3814 days 2 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x3767befc0c60c5cca68a9a8288dbecc6cd667f9a210bf25a481dff0ed19176f7108213442021-07-22 18:48:3814 days 2 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x3767befc0c60c5cca68a9a8288dbecc6cd667f9a210bf25a481dff0ed19176f7108213442021-07-22 18:48:3814 days 2 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
0x3767befc0c60c5cca68a9a8288dbecc6cd667f9a210bf25a481dff0ed19176f7108213442021-07-22 18:48:3814 days 2 hrs ago 0xcd2539dfb06d3bf708d875c045094c89f60a60f6 0x7866169591ac93957d25acbd9dd0ee6cfd8bd3990 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xf4339196B5f558b4b323935c2452f4cA18594FeF

Contract Name:
Memenopoly

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 30 : MNOPToken.sol
pragma solidity 0.6.12;

import "./libs/BEP20.sol";
import "./libs/MinterRole.sol";
import "./libs/CanTransferRole.sol";


// MNOP Token with Governance.
contract MNOPToken is MinterRole, CanTransferRole, BEP20('Memenopoly Money', 'MNOP') {
    /// @notice Creates `_amount` token to `_to`. Must only be called by the a minter.
    function mint(address _to, uint256 _amount) public onlyMinter {
        _mint(_to, _amount);
        _moveDelegates(address(0), _delegates[_to], _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) public onlyMinter {
        _burn(_account, _amount);
        _moveDelegates( _delegates[_account],address(0), _amount);
    }

    //Coppied and modified from EggToken Code

    // which is copied and modified from YAM code:
    // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol
    // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol
    // Which is copied and modified from COMPOUND:
    // https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol


    mapping (address => address) internal _delegates;

    uint256 private _totalClaimed;

    /// @notice A checkpoint for marking number of votes from a given block
    struct Checkpoint {
        uint32 fromBlock;
        uint256 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 A record of states for signing / validating signatures
    mapping (address => uint) public nonces;

      /// @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);


    /// returns the total claimed mnop
    // this is just purely used to display the total mnop claimed by users on the frontend
    function totalClaimed() public view returns (uint256) {
        return _totalClaimed;
    }

    // add mnop claimed
    function addClaimed(uint256 _amount) public onlyCanTransfer {
        _totalClaimed = _totalClaimed.add(_amount);
    }

    // set mnop claimed to a custom value, for if we wanna reset the counter anytime
    function setClaimed(uint256 _amount) public onlyCanTransfer {
        require(_amount >= 0, "nonono cant be negative");
        _totalClaimed = _amount;
    }

    /**
     * @notice Delegate votes from `msg.sender` to `delegatee`
     * @param delegator The address to get delegatee for
     */
    function delegates(address delegator)
        external
        view
        returns (address)
    {
        return _delegates[delegator];
    }

   /**
    * @notice Delegate votes from `msg.sender` to `delegatee`
    * @param delegatee The address to delegate votes to
    */
    function delegate(address delegatee) external {
        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
    )
        external
    {
        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), "MNOP::delegateBySig: invalid signature");
        require(nonce == nonces[signatory]++, "MNOP::delegateBySig: invalid nonce");
        require(now <= expiry, "MNOP::delegateBySig: 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 (uint256)
    {
        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)
        external
        view
        returns (uint256)
    {
        require(blockNumber < block.number, "MNOP::getPriorVotes: 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];
        uint256 delegatorBalance = balanceOf(delegator); // balance of underlying MNOP (not scaled);
        _delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);

        _moveDelegates(currentDelegate, delegatee, delegatorBalance);
    }

    function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
        if (srcRep != dstRep && amount > 0) {
            if (srcRep != address(0)) {
                // decrease old representative
                uint32 srcRepNum = numCheckpoints[srcRep];
                uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
                uint256 srcRepNew = srcRepOld.sub(amount);
                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
            }

            if (dstRep != address(0)) {
                // increase new representative
                uint32 dstRepNum = numCheckpoints[dstRep];
                uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
                uint256 dstRepNew = dstRepOld.add(amount);
                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
            }
        }
    }

    function _writeCheckpoint(
        address delegatee,
        uint32 nCheckpoints,
        uint256 oldVotes,
        uint256 newVotes
    )
        internal
    {
        uint32 blockNumber = safe32(block.number, "MNOP::_writeCheckpoint: 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 getChainId() internal pure returns (uint) {
        uint256 chainId;
        assembly { chainId := chainid() }
        return chainId;
    }
}

File 2 of 30 : Memenopoly.sol
pragma solidity 0.6.12;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "./libs/IBEP20.sol";
import "./libs/SafeBEP20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";

import "./MNOPToken.sol";
import "./MnopCard.sol";
import "./TheBroker.sol";


// This is the main game contrat, all logic for Memenopoly game mechanics can be found within.

contract Memenopoly is Ownable, ReentrancyGuard, VRFConsumerBase {
    // using SafeMath for uint256;
    using SafeMathChainlink for uint256;
    
    using SafeBEP20 for IBEP20;


    // Chainlink VRF
    bytes32 internal keyHash;
    uint256 internal linkFee;
    address internal vrfCoordinator;

    // The MNOP TOKEN!
    MNOPToken public mnop;

    // TheBroker Contract
    TheBroker public theBroker;

    // Dev address.
    address public devaddr;

    // The amount to seed the parking jackpot with
    uint256 public defaultParking;

    // The burn address
    address public burnAddress;   
    
    //Game active
    bool public gameActive;

    // Max level a play can achive
    uint256 public maxLevel;

    // The amount you collect landing on go/sppt 0
    uint256 public payDayReward;

    // The amount you collect landing on chest spots
    uint256 public chestReward;

    // time in second between rolls
    uint256 public rollTimeLimit;

    // time in second before a player is no longer considered active for payout
    uint256 public activeTimeLimit;

    uint256 nonce; //for chainlink seed
    uint256 totalSpaces; // Total board spots
    uint256 public parkingBalance; // current jackpot balance
    uint256 public totalRentPaid; // total rent ever paid
    uint256 public totalRentPaidOut; // total rewards paid out
    uint256 public totalPlayers; //players that rolled at least 1 time
    uint256 public totalRolls; //all time total rolls
    uint256 public jackpotWins; //Total times the jackpot was won
    uint256 public jailCount; //Total times someone was sent to jail


    //player data structure
    struct PlayerInfo {
      uint256 rewards; //rewards this player has gained during the game
      uint256 spotId;   // the index of the spot they are currently on.
      uint256 rentDue;      // the current rent due for this player.
      uint256 lastRoll; // the lsast number rolled
      uint256 lastRollTime; // timestamp of the last roll
      uint256 level; //the current level for this player
      bool inJail; //if this player is in jail
      uint256 totalClaimed; //lifetime mnop claimed from the game
      uint256 totalRentPaid; //lifetime rent and taxes paid
      uint256 totalRolls; //total rolls for this player
      uint256 jackpotWins; //Total times the jackpot was won
      uint256 jailCount; //Total times someone was sent to jail
      bool isRolling; //if this player is in jail

    }

    
    struct BoardInfo {
        uint256 spotType; //what type of space this is
        uint256 rent;      // the rent for this space.
        uint256 balance;  // the balance currently paid to this spot
        uint256 nftId; // Nft id's that relate to this spot
        uint256 totalPaid;  // total rent paid to this spot
        uint256 totalLanded;  // total times someone landed on this spot
    }

    mapping(address => PlayerInfo) public playerInfo;
    mapping(bytes32 => address) private rollQueue;
    mapping(uint256 => BoardInfo) public boardInfo;

    event Roll(address indexed user, uint256 rollNum, uint256 spodId, uint256 rent, bool isPropOwner, uint256 timeStart);
    event LandedParking(address indexed user, uint256 amount);
    event RewardsClaimed(address indexed user, uint256 amount);
    event GotoJail(address indexed user, uint256 amountBurned);

    event SetGameActive(bool isActive);
    event SetDefaultParking(uint256 amount);
    event SetChestReward(uint256 amount);
    event SetPayDayReward(uint256 amount);
    event SpotUpdated(uint256 spotId, uint256 spotType, uint256 rent, uint256 nftId, bool clearBalance);

    event SetFeeAddress(address indexed user, address indexed newAddress);
    event SetDevAddress(address indexed user, address indexed newAddress);
    event UpdateBrokerAddress(address indexed user, TheBroker indexed theBroker);
    event UpdateRollTimeLimit(address indexed user, uint256 rollTimeLimit);
    event UpdateActiveTimeLimit(address indexed user, uint256 activeTimeLimit);
    event UpdateMaxLevel(address indexed user, uint256 level);
    event SpotPaid(uint256 spotId, uint256 totalBal, uint256 share, uint256 extraBurnt, uint256 toParking, uint256 toBurn, uint256 toDev, address[] stakers);
    event SetLinkFee(address indexed user, uint256 fee);

    //-----------------------------

    constructor(
        MNOPToken _mnop, //mnop token address
        TheBroker _theBroker, //the broker token address
        address _devaddr, //dev address
        uint256 _maxLevel, //the level cap for players
        uint256 _defaultParking, //the value of a fresh parking jackpot
        uint256 _payDayReward, //the value of landing on go, (payDayReward/10) for passing it
        uint256 _chestReward, //value to mint on a chest spot
        uint256 _rollTimeLimit, //seconds between rolls
        uint256 _activeTimeLimit, //seconds since last roll before a player is ineligible for payouts
        uint256[] memory _boardTypes, //an array of each board piece by type
        uint256[] memory _boardRent, //a corresponding array of each board piece by rent
        uint256[] memory _nftIds, //a corresponding array of each board piece by nftId
        address _vrfCoordinator,
        bytes32 _vrfKeyHash, 
        address _linkToken,
        uint256 _linkFee
    )  VRFConsumerBase (
        _vrfCoordinator, 
        _linkToken
    ) public {
        mnop = _mnop;
        theBroker = _theBroker;
        devaddr = _devaddr;
        maxLevel = _maxLevel;
        defaultParking = _defaultParking;
        payDayReward = _payDayReward;
        chestReward = _chestReward;
        rollTimeLimit = _rollTimeLimit;
        activeTimeLimit = _activeTimeLimit;

        burnAddress = 0x000000000000000000000000000000000000dEaD;
        //set the default board
        _setBoard(_boardTypes, _boardRent, _nftIds); 

        
        vrfCoordinator = _vrfCoordinator;
        keyHash = _vrfKeyHash;
        linkFee = _linkFee;

        // testnet settings
        // vrfCoordinator = 0xa555fC018435bef5A13C6c6870a9d4C11DEC329C;
        // linkToken = LinkTokenInterface(0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06);
        // keyHash = 0xcaf3c3727e033261d383b315559476f48034c13b18f8cafed4d871abe5049186;
        // linkFee = 0.1 * 10 ** 18; // 0.1 LINK (Varies by network)
    }



    /** 
     * @notice Modifier to only allow updates by the VRFCoordinator contract
     */
    modifier onlyVRFCoordinator {
        require(msg.sender == vrfCoordinator, 'Fulfillment only allowed by VRFCoordinator');
        _;
    }


    /**
    * @dev Roll and take a players turn
    * - must not owe rent
    * - must have waited long enough between rolls
    * - sends request to chainlink VRF
    */
    function roll() public returns (bytes32 requestId) {
        //roll and move

        PlayerInfo storage player = playerInfo[msg.sender];

        require(gameActive, "Memenopoly: Game not active");
        require(player.rentDue == 0, "Memenopoly: Rent is due pal!");
        require( block.timestamp >= player.lastRollTime.add(rollTimeLimit), "Memenopoly: Roll time not reached");
        require(LINK.balanceOf(address(this)) > linkFee, "Not enough LINK - fill contract with faucet");
       

        //Virgin player
        if( player.totalRolls < 1){
            totalPlayers = totalPlayers.add(1);
        }

        //inc some counters
        player.totalRolls = player.totalRolls.add(1);
        totalRolls = totalRolls.add(1);

        //check for players in jail
        if(player.inJail){
            //set them free
            player.inJail = false;
            //transport them to the jail spot 
            player.spotId = 10;
        }

        //check free parking to make sure there is always something to pay out
        //this shouldnt need to happen
        if(parkingBalance <= 0){
            seedParking();
        }

        //harvest any pending game rewards
        if(player.rewards > 0){
            _claimGameRewards();
        }

        //time lock the roll
        player.lastRollTime = block.timestamp;
        player.isRolling = true;
        bytes32 _requestId = requestRandomness(keyHash, linkFee, randomizeSeed());
        rollQueue[_requestId] = msg.sender;
        return _requestId;
    }

     /**
     * @notice Callback function used by VRF Coordinator
     * @dev Important! Add a modifier to only allow this function to be called by the VRFCoordinator
     * @dev The VRF Coordinator will only send this function verified responses.
     * @dev The VRF Coordinator will not pass randomness that could not be verified.
     * @dev Get a number between 2 and 12, and run the roll logic
     */
    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override onlyVRFCoordinator {
        uint256 _roll = randomness.mod(11).add(2);
        address _player = rollQueue[requestId];
        doRoll(_roll,_player);
    }


    /*
    types: [
        0: 'start',
        1: 'prop',
        2: 'rr',
        3: 'util',
        4: 'chest',
        5: 'chance',
        6: 'tax',
        7: 'jail',
        8: 'gojail',
        9: 'parking'
    ]
    */
    /**
     * @dev called by fulfillRandomness, process the roll and mvoe the player
     */
    function doRoll(uint256 _roll,address _player) internal onlyVRFCoordinator {

        bool isPropOwner =  false;
        bool doSeedParking = false;

        PlayerInfo storage player = playerInfo[_player];

        //move the player
        player.spotId = player.spotId.add(_roll);

        //log last roll
        player.lastRoll = _roll;

        //check if we passed go
        if(player.spotId >= totalSpaces){
          player.level = player.level.add(1);
          
          //make sure they are capped at the max level
          if(player.level > maxLevel){
            player.level = maxLevel;
          }

          player.spotId = player.spotId.sub(totalSpaces);
          
          //don't pay them twice
          if(player.spotId != 0){
            //multiply by the level
            totalRentPaidOut = totalRentPaidOut.add(payDayReward.mul(player.level));
            player.rewards = player.rewards.add(payDayReward.mul(player.level));
            mnop.mint(address(this), payDayReward.mul(player.level));
          }
        }

        BoardInfo storage bSpot = boardInfo[player.spotId];

        //some stats
        bSpot.totalLanded = bSpot.totalLanded.add(1);

        //set the rent
        uint256 rent = bSpot.rent;
        
        //check the spot type
        if(bSpot.spotType == 0){
            //landed on go mint 4x the pay day x the level
            totalRentPaidOut =  totalRentPaidOut.add(payDayReward.mul(4).mul(player.level));
            player.rewards = player.rewards.add(payDayReward.mul(4).mul(player.level));
            mnop.mint(address(this), payDayReward.mul(4).mul(player.level));
        }

        if(bSpot.spotType == 1 || bSpot.spotType == 2){
            //property and rocket
            //don't pay rent for our own property
            isPropOwner = _isStaked(_player, player.spotId);
            if(isPropOwner){
                rent = 0;
            }
        }


        if(bSpot.spotType == 3){
            /*
            @dev Utility
            rent is base rent X the roll so we can have varying util rents
            ie: 
            - first util spot rent is 4 so (4x the roll)
            - second util spot rent is 8 so (8x the roll)
            */

            rent = rent.mul(_roll);
        }

        if(bSpot.spotType == 4){
            //community chest
            totalRentPaidOut =  totalRentPaidOut.add(chestReward);
            player.rewards = player.rewards.add(chestReward);
            mnop.mint(address(this), chestReward);
        }

        if(bSpot.spotType == 5){
            //roll again
            //get a free roll, set the timesamp back 
            player.lastRollTime = block.timestamp.sub(rollTimeLimit);
        }

        if(bSpot.spotType == 8){
            //go to jail
            //take away a level
            if(player.level > 0){
                player.level = player.level.sub(1);
            }

            //flag player in jail
            player.inJail = true;
            player.jailCount = player.jailCount.add(1);
            jailCount = jailCount.add(1);

            //Clear the jackpot
            uint256 _pbal = parkingBalance;
            parkingBalance = 0;

            //lock them for 2 rolls time
            player.lastRollTime = block.timestamp.add(rollTimeLimit.mul(2));

            emit GotoJail(_player, _pbal);

           /*  )
              ) \  
             / ) (  
             \(_)/ */
            //Burn the jackpot!!! 
            safeMnopTransfer(address(burnAddress), _pbal);

            //re-seed the jackpot
            doSeedParking = true;

        }

        if(bSpot.spotType == 9){
            //Moon Jackpot
            //WINNER WINNER CHICKEN DINNER!!!
            if(parkingBalance > 0){
                //send the winner the prize
                uint256 _pbal = parkingBalance;
                emit LandedParking(_player, _pbal);
                parkingBalance = 0;
                player.rewards = player.rewards.add(_pbal);
                player.jackpotWins = player.jackpotWins.add(1);
                jackpotWins = jackpotWins.add(1);
                totalRentPaidOut =  totalRentPaidOut.add(_pbal);
                //reset the parking balance
                doSeedParking = true;
            }
        }

        if(doSeedParking){
            seedParking();
        }

        player.isRolling = false;
        player.rentDue = rent;

        emit Roll(_player, player.lastRoll, player.spotId , rent, isPropOwner, block.timestamp);
    }


    /**
    * @dev See if a player has a valid card staked and has recently rolled
    */
    function _isStaked(address _account, uint256 _spotId) private view returns(bool){

        //see if they have rolled lately 
        // do we need this since it is onlycalled on doRoll? 
        if(!_playerActive(_account)){
            return false;
        }

        BoardInfo storage bSpot = boardInfo[_spotId];

        if(bSpot.nftId == 0){
            return false;
        }

        uint256[] memory stakedCards = theBroker.getCardsStakedOfAddress(_account);
        uint256 len = stakedCards.length;
        
        
        if(len <= 0){
            return false;
        }

        

        for (uint i=0; i<len; i++) {
            if(stakedCards[i] > 0 && i == bSpot.nftId){
                //check if they have rolled/active
                return true;
            } 
        }

        return false;

    }

    /* @dev set the bord spots from the constructor */ 
    function _setBoard(uint256[] memory _boardTypes, uint256[] memory _boardRent, uint256[] memory _nftIds) private {
        totalSpaces = _boardTypes.length;
        for (uint i=0; i<totalSpaces; i++) {
            BoardInfo storage bSpot = boardInfo[i];
            bSpot.spotType = _boardTypes[i];
            bSpot.rent = _boardRent[i];
            bSpot.nftId = _nftIds[i];
            //bSpot.balance = 0;
        }

        //seedParking();
    }

    /**
     * @dev Claim/harvest the pending rewards won while playing, not related to yield farming
    */
    function claimGameRewards() public nonReentrant {
           _claimGameRewards();
    }

    function _claimGameRewards() internal {

         PlayerInfo storage player = playerInfo[msg.sender];
            uint256 pending = player.rewards;
            require(pending > 0, "Memenopoly: No rewards to claim");
            if(pending > 0){

                emit RewardsClaimed(msg.sender, pending);
                player.rewards = 0;
                player.totalClaimed = player.totalClaimed.add(pending);
                safeMnopTransfer(msg.sender, pending);

            }
    }

    /**
    * @dev Handle paying a players rent/tax 
    */
    function payRent() public nonReentrant {

            
        bool transferSuccess = false;
         // BoardInfo storage bSpot = boardInfo[_spotId];
        PlayerInfo storage player = playerInfo[msg.sender];

        uint256 _rentDue = player.rentDue;
        uint256 mnopBal = mnop.balanceOf(msg.sender);

        require(gameActive, "Memenopoly: Game not active");
        require(_rentDue > 0, "Memenopoly: No rent is due!");
        require(mnopBal > 0, "Memenopoly: Insufficient Balance");

         //if we don't have full rent take what we can get
        if(mnopBal < _rentDue){
            _rentDue = mnopBal;
        }

        //pay the rent internally 
        player.rentDue = player.rentDue.sub(_rentDue);

        if(boardInfo[player.spotId].spotType == 3){
            //utils are community add to the moon jackpot
            parkingBalance = parkingBalance.add(_rentDue);
        } else if(boardInfo[player.spotId].spotType == 6){

           /*  )
              ) \  
             / ) (  
             \(_)/ */
            //Burn all taxes 
            safeMnopTransfer(address(burnAddress), _rentDue);
        } else {
            //pay the spot and run payouts for all the stakers
            boardInfo[player.spotId].balance = boardInfo[player.spotId].balance.add(_rentDue);
            _payOutSpot(player.spotId);
            
        }

        //keep track of the total paid stats
        totalRentPaid = totalRentPaid.add(_rentDue);
        player.totalRentPaid = player.totalRentPaid.add(_rentDue);
        boardInfo[player.spotId].totalPaid = boardInfo[player.spotId].totalPaid.add(_rentDue);

        transferSuccess = mnop.transferFrom(address(msg.sender),address(this),_rentDue);
        require(transferSuccess, "Memenopoly: pay rent transfer failed");

            
    }


    /**
     * @dev Pays out all the stakers of this spot and resets its balance.
     *
     * Emits a {SpotPaid} 
     *
     * Payouts are distributed like so:
     * 10% - burned forever
     * 10% - sent to the parking jackpot
     * 5% - sent to dev address
     * 75% - split evenly between all stakers (active or not)
     * - To be eligible to receive the payout the player must have the card staked and rolled in the last day
     * - Any staked share that is not eligible will be burned
     * 
     *
     * Requirements
     *
     * - `_spotId` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
    */
    function _payOutSpot(uint256 _spotId) internal {
    //get all the addresses that have this card staked
    //total up the stakers
        require(_spotId.add(1) <= totalSpaces, "Memenopoly: Invalid Spot");
        require(boardInfo[_spotId].balance > 0, "Memenopoly: No balance to pay out");

        address[] memory stakers = theBroker.getStakersOfCard(boardInfo[_spotId].nftId);
        uint256 amtStaking = stakers.length;
        uint256 totalToDistribute = boardInfo[_spotId].balance;
        uint256 origBal = totalToDistribute;

        //10% to burn
        uint256 toBurn = totalToDistribute.mul(10).div(100);

        //10% to parking
        uint256 toParking = totalToDistribute.mul(10).div(100);

        //5% to dev
        uint256 toDev = totalToDistribute.mul(5).div(100);

        totalToDistribute = totalToDistribute.sub(toBurn).sub(toParking).sub(toDev);
        
        //clear the spot balance
        boardInfo[_spotId].balance = 0;
        uint256 share = totalToDistribute;

        if(amtStaking > 0){
            share = totalToDistribute.div(amtStaking);
            
            for (uint i=0; i<amtStaking; i++) {

               if(_playerActive(stakers[i])){
                   totalRentPaidOut = totalRentPaidOut.add(share);
                   playerInfo[stakers[i]].rewards = playerInfo[stakers[i]].rewards.add(share);
                   totalToDistribute = totalToDistribute.sub(share);
               }
            }
        }

        //if there is anything left over 
        if(totalToDistribute > 0){

           /*  )
              ) \  
             / ) (  
             \(_)/ */
            //burn m-fer... burn
            toBurn = toBurn.add(totalToDistribute);
            // safeMnopTransfer(address(burnAddress), totalToDistribute);
        }

        parkingBalance = parkingBalance.add(toParking);
       /*  )
          ) \  
         / ) (  
         \(_)/ */
        //burn it!
        safeMnopTransfer(address(burnAddress), toBurn);
        safeMnopTransfer(devaddr,toDev);

        emit SpotPaid(_spotId, origBal, share, totalToDistribute, toParking, toBurn, toDev, stakers);
    }
     
    /**
    * @dev reset the parking jackpot
    */
    function seedParking() private {
         //seed the parking
        parkingBalance = defaultParking;
        mnop.mint(address(this), defaultParking);
    }

    /**
    * @dev Add to the parking jackpot used for promos or for any generous soul to give back
    */
    function addParking(uint256 _amount) public nonReentrant {
             // manually add to the parking jackpot
            require(_amount > 0, "Memenopoly: Amount must not be Zero");

            bool transferSuccess = false;

            uint256 mnopBal = mnop.balanceOf(msg.sender);

            require(mnopBal >= _amount, "Memenopoly: Insufficient Balance");

            parkingBalance = parkingBalance.add(_amount);

            transferSuccess = mnop.transferFrom(address(msg.sender),address(this),_amount);
            require(transferSuccess, "Memenopoly: pay rent transfer failed");

    }

    /**
    * @dev Update the details on a space
    */
    function updateSpot(
        uint256 _spotId, 
        uint256 _spotType, 
        uint256 _rent,
        uint256 _nftId,
        bool _clearBalance) public onlyOwner {

            boardInfo[_spotId].spotType = _spotType;
            boardInfo[_spotId].rent = _rent;
            boardInfo[_spotId].nftId = _nftId;

            /* in case we need to reset the game */
            if(_clearBalance){
                boardInfo[_spotId].balance = 0;
            }
            emit SpotUpdated(_spotId, _spotType, _rent, _nftId, _clearBalance);
    }

    function randomizeSeed() private returns (uint) {
        uint randomnumber = uint(keccak256(abi.encodePacked(now, msg.sender, nonce))) % 11111;
        randomnumber = randomnumber + 2;
        nonce++;        
        return randomnumber;
    }

    function canRoll(address _account) external view returns(bool){

        if(!gameActive){
            return false;
        }
        
        //see if they are already rolling
        if(playerInfo[_account].isRolling ){
            return false;
        }

        //check if they have rent
        if(playerInfo[_account].rentDue > 0){
            return false;
        }

        //check the timer
        if(block.timestamp >= playerInfo[_account].lastRollTime.add(rollTimeLimit)){
            return true;
        }
        return false;
    }

    function playerActive(address _account) external view returns(bool){
        return _playerActive(_account);
    }

    function _playerActive(address _account) internal view returns(bool){
        if(block.timestamp <= playerInfo[_account].lastRollTime.add(activeTimeLimit)){
            return true;
        }
        return false;
    }

    // Safe mnop transfer function, just in case if rounding error causes pool to not have enough MNOPs.
    function safeMnopTransfer(address _to, uint256 _amount) internal {
        uint256 mnopBal = mnop.balanceOf(address(this));
        bool transferSuccess = false;
        if (_amount > mnopBal) {
            transferSuccess = mnop.transfer(_to, mnopBal);
        } else {
            transferSuccess = mnop.transfer(_to, _amount);
        }
        require(transferSuccess, "safeMnopTransfer: transfer failed");
    }

    /**
    * @dev Set the game active 
    */
    function setGameActive(bool _isActive) public onlyOwner {
        gameActive = _isActive;
        emit SetGameActive(_isActive);
    }

     /**
    * @dev Update the amount to seed the parking jackpot
    */
    function setDefaultParking(uint256 _amount) public onlyOwner {
        defaultParking = _amount;
        emit SetDefaultParking(_amount);
    }

    /**
     * @dev Update the amount paid out on chest spots
     */
    function setChestReward(uint256 _amount) public onlyOwner {
      chestReward = _amount;
      emit SetChestReward(_amount);
    }

   /**
    * @dev Update the amount paid out when landing on go
    */
    function setPayDayReward(uint256 _amount) public onlyOwner {
      payDayReward = _amount;
      emit SetPayDayReward(_amount);
    }

    // Update dev address by the previous dev.
    function dev(address _devaddr) public {
        require(msg.sender == devaddr, "dev: wut?");
        devaddr = _devaddr;
        emit SetDevAddress(msg.sender, _devaddr);
    }

     /**
     * @dev Update TheBroker address.
     */
    function updateTheBrokerAddress(TheBroker _theBrokerAddress) public onlyOwner{
        theBroker = _theBrokerAddress;
        emit UpdateBrokerAddress(msg.sender, _theBrokerAddress);
    }

     /**
     * @dev Set the roll timer (seconds between rolls)
     */
    function updateRollTimeLimit(uint256 _rollTimeLimit) public onlyOwner{
        rollTimeLimit = _rollTimeLimit;
        emit UpdateRollTimeLimit(msg.sender, _rollTimeLimit);
    }

     /**
     * @dev Set the time limit a player is no longer active (seconds since last roll)
     */
    function updateActiveTimeLimit(uint256 _activeTimeLimit) public onlyOwner{
        activeTimeLimit = _activeTimeLimit;
        emit UpdateActiveTimeLimit(msg.sender, _activeTimeLimit);
    }

    /**
     * @dev Set the max level
     */
    function updateMaxLevel(uint256 _maxLevel) public onlyOwner{
        maxLevel = _maxLevel;
        emit UpdateMaxLevel(msg.sender, _maxLevel);
    }

    /**
     * @dev transfer LINK out of the contract
     */
    function withdrawLink(uint256 _amount) public onlyOwner {
        require(LINK.transfer(msg.sender, _amount), "Unable to transfer");
    }

    /**
     * @dev update the link fee amount
     */
    function setLinkFee(uint256 _linkFee) public onlyOwner {
        linkFee = _linkFee;
        emit SetLinkFee(msg.sender, _linkFee);
    }

}

File 3 of 30 : MnopCard.sol
pragma solidity >=0.5.0 <0.6.13;
//pragma solidity ^0.5.11;

import "./libs/ERC1155/ERC1155Tradable.sol";

/**
 * @title Memenopoly Card NFT 
 */
contract MnopCard is ERC1155Tradable {
    string private _contractURI;

    constructor(address _proxyRegistryAddress) public ERC1155Tradable("Memenopoly Cards", "MnopCard", _proxyRegistryAddress) {
        _setBaseMetadataURI("https://api.mnop.finance/cards/");
        _contractURI = "https://api.mnop.finance/contract/cards-erc1155";
    }

    function setBaseMetadataURI(string memory newURI) public override onlyWhitelistAdmin {
        _setBaseMetadataURI(newURI);
    }

    function setContractURI(string memory newURI) public onlyWhitelistAdmin {
        _contractURI = newURI;
    }

    function contractURI() public view returns (string memory) {
        return _contractURI;
    }

    /**
         * @dev Ends minting of token
         * @param _id          Token ID for which minting will end
         */
    function endMinting(uint256 _id) external onlyWhitelistAdmin {
        tokenMaxSupply[_id] = tokenSupply[_id];
    }

    function burn(address _account, uint256 _id, uint256 _amount) public onlyMinter {
        require(balanceOf(_account, _id) >= _amount, "cannot burn more than address has");
        _burn(_account, _id, _amount);
    }

    /**
    * Mint NFT and send those to the list of given addresses
    */
    function airdrop(uint256 _id, address[] memory _addresses) public onlyMinter {
        require(tokenMaxSupply[_id] - tokenSupply[_id] >= _addresses.length, "cannot mint above max supply");
        for (uint256 i = 0; i < _addresses.length; i++) {
            mint(_addresses[i], _id, 1, "");
        }
    }
}

/*
Constructor Argument To Add During Deployment
OpenSea Registry Address
000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1

0xa5409ec958c83c3f309868babaca7c86dcb077c1
*/

File 4 of 30 : TheBroker.sol
pragma solidity >=0.5.0 <0.6.13;
// pragma solidity  >=0.5.0 <0.6.0;

// import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
// import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./MnopCard.sol";
import "./MNOPToken.sol";
// import "./MnopBooster.sol";

/**
 * @dev Contract for handling the NFT staking and set creation.
 */
contract TheBroker is Ownable {
    using SafeMath for uint256;

    struct CardSet {
        uint256[] cardIds;
        uint256 mnopPerDayPerCard;      //reward per day per card
        uint256 bonusMnopMultiplier;    // bonus for a full set 100% bonus = 1e5
        bool isRemoved;
    }

    ERC1155Tradable public mnopCard;
    MNOPToken public mnop;

    //def address 
    address public treasuryAddr;

    uint256[] public cardSetList;

	//Highest CardId added to the museum
    uint256 public highestCardId;

	//SetId mapped to all card IDs in the set.
    mapping (uint256 => CardSet) public cardSets;

	//CardId to SetId mapping
    mapping (uint256 => uint256) public cardToSetMap;

    //toal staked for each cardId
    mapping (uint256 => uint256) public totalStaked;

	//user's cards staked mapped to the cardID with the value of the idx of stakedCards
    mapping (address => mapping(uint256 => uint256)) public userCards;

    //Status of cards staked mapped to the user addresses
    mapping (uint256 => mapping(uint256 => address)) public stakedCards;

	//Last update time for a user's MNOP rewards calculation
    mapping (address => uint256) public userLastUpdate;

    event Stake(address indexed user, uint256[] cardIds);
    event Unstake(address indexed user, uint256[] cardIds);
    event Harvest(address indexed user, uint256 amount);
//    event SetCardContract(address indexed user, ERC1155Tradable mnopCard);
//    event SetMnopTokenContract(address indexed user, MNOPToken mnopToken);


    constructor(ERC1155Tradable _mnopCardAddr, MNOPToken _mnopAddr, address _treasuryAddr) public { //, MnopBooster _mnopBoosterAddr
        mnopCard = _mnopCardAddr;
        mnop = _mnopAddr;
        treasuryAddr = _treasuryAddr;
    }

	/**
     * @dev Utility function to check if a value is inside an array
     */
    function _isInArray(uint256 _value, uint256[] memory _array) internal pure returns(bool) {
        uint256 length = _array.length;
        for (uint256 i = 0; i < length; ++i) {
            if (_array[i] == _value) {
                return true;
            }
        }
        return false;
    }

	/**
     * @dev Indexed boolean for whether a card is staked or not. Index represents the cardId.
     */
    function getCardsStakedOfAddress(address _user) public view returns(uint256[] memory) {
        uint256[] memory cardsStaked = new uint256[](highestCardId + 1);
        for (uint256 i = 0; i < highestCardId + 1; ++i) {			
            cardsStaked[i] = userCards[_user][i];
        }
        return cardsStaked;
    }
    
	/**
     * @dev Returns the list of cardIds which are part of a set
     */
    function getCardIdListOfSet(uint256 _setId) external view returns(uint256[] memory) {
        return cardSets[_setId].cardIds;
    }
    

    /**
     * @dev returns all the addresses that have a cardId staked
     */
    function getStakersOfCard(uint256 _cardId) external view returns(address[] memory) {
        address[] memory cardStakers = new address[](totalStaked[_cardId]);
        for (uint256 i = 0; i < totalStaked[_cardId]; ++i) {
            if(stakedCards[_cardId][i] != address(0)){
                cardStakers[i] = stakedCards[_cardId][i];
            }
        }
        return cardStakers;
    }
   
	
	/**
     * @dev Indexed  boolean of each setId for which a user has a full set or not.
     */
    function getFullSetsOfAddress(address _user) public view returns(bool[] memory) {
        uint256 length = cardSetList.length;
        bool[] memory isFullSet = new bool[](length);
        for (uint256 i = 0; i < length; ++i) {
            uint256 setId = cardSetList[i];
            if (cardSets[setId].isRemoved) {
                isFullSet[i] = false;
                continue;
            }
            bool _fullSet = true;
            uint256[] memory _cardIds = cardSets[setId].cardIds;
			
            for (uint256 j = 0; j < _cardIds.length; ++j) {
                if (userCards[_user][_cardIds[j]] == 0) {
                    _fullSet = false;
                    break;
                }
            }
            isFullSet[i] = _fullSet;
        }
        return isFullSet;
    }

	/**
     * @dev Returns the amount of NFTs staked by an address for a given set
     */
    function getNumOfNftsStakedForSet(address _user, uint256 _setId) public view returns(uint256) {
        uint256 nbStaked = 0;
        if (cardSets[_setId].isRemoved) return 0;
        uint256 length = cardSets[_setId].cardIds.length;
        for (uint256 j = 0; j < length; ++j) {
            uint256 cardId = cardSets[_setId].cardIds[j];
            if (userCards[_user][cardId] > 0) {
                nbStaked = nbStaked.add(1);
            }
        }
        return nbStaked;
    }

	/**
     * @dev Returns the total amount of NFTs staked by an address across all sets
     */
    function getNumOfNftsStakedByAddress(address _user) public view returns(uint256) {
        uint256 nbStaked = 0;
        for (uint256 i = 0; i < cardSetList.length; ++i) {
            nbStaked = nbStaked.add(getNumOfNftsStakedForSet(_user, cardSetList[i]));
        }
        return nbStaked;
    }
    
	/**
     * @dev Returns the total mnop pending for a given address. Can include the bonus from MnopBooster,
	 * if second param is set to true.
     */
    function totalPendingMnopOfAddress(address _user) public view returns (uint256) {
        uint256 totalMnopPerDay = 0;
        uint256 length = cardSetList.length;
        for (uint256 i = 0; i < length; ++i) {
            uint256 setId = cardSetList[i];
            CardSet storage set = cardSets[setId];
            if (set.isRemoved) continue;
            uint256 cardLength = set.cardIds.length;
            bool isFullSet = true;
            uint256 setMnopPerDay = 0;
            for (uint256 j = 0; j < cardLength; ++j) {
                if (userCards[_user][set.cardIds[j]] == 0) {
                    isFullSet = false;
                    continue;
                }
                setMnopPerDay = setMnopPerDay.add(set.mnopPerDayPerCard);
            }
            if (isFullSet) {
                setMnopPerDay = setMnopPerDay.mul(set.bonusMnopMultiplier).div(1e5);
            }
            totalMnopPerDay = totalMnopPerDay.add(setMnopPerDay);
        }

        uint256 lastUpdate = userLastUpdate[_user];
        uint256 blockTime = block.timestamp;
        return blockTime.sub(lastUpdate).mul(totalMnopPerDay.div(86400));
    }

	/**
     * @dev Manually sets the highestCardId, if it goes out of sync.
	 * Required calculate the range for iterating the list of staked cards for an address.
     */
    function setHighestCardId(uint256 _highestId) public onlyOwner {
        require(_highestId > 0, "Set if minimum 1 card is staked.");
        highestCardId = _highestId;
    }

	/**
     * @dev Adds a card set with the input param configs. Removes an existing set if the id exists.
     */
     // bool _isBooster,
     // uint256 _bonusFullSetBoost
     // uint256[] memory _poolBoosts, 
    function addCardSet(
        uint256 _setId, 
        uint256[] memory _cardIds, 
        uint256 _bonusMnopMultiplier, 
        uint256 _mnopPerDayPerCard
        
        ) public onlyOwner {
            removeCardSet(_setId);
            uint256 length = _cardIds.length;
            for (uint256 i = 0; i < length; ++i) {
                uint256 cardId = _cardIds[i];
                if (cardId > highestCardId) {
                    highestCardId = cardId;
                }
                // Check all cards to assign arent already part of another set
                require(cardToSetMap[cardId] == 0, "Card already assigned to a set");
                // Assign to set
                cardToSetMap[cardId] = _setId;
            }
            if (_isInArray(_setId, cardSetList) == false) {
                cardSetList.push(_setId);
            }
            cardSets[_setId] = CardSet({
                cardIds: _cardIds,
                bonusMnopMultiplier: _bonusMnopMultiplier,
                mnopPerDayPerCard: _mnopPerDayPerCard,
                isRemoved: false
            });
    }

	/**
     * @dev Updates the mnopPerDayPerCard for a card set.
     */
    function setMnopRateOfSets(uint256[] memory _setIds, uint256[] memory _mnopPerDayPerCard) public onlyOwner {
        require(_setIds.length == _mnopPerDayPerCard.length, "_setId and _mnopPerDayPerCard have different length");
        for (uint256 i = 0; i < _setIds.length; ++i) {
            require(cardSets[_setIds[i]].cardIds.length > 0, "Set is empty");
            cardSets[_setIds[i]].mnopPerDayPerCard = _mnopPerDayPerCard[i];
        }
    }

	/**
     * @dev Set the bonusMnopMultiplier value for a list of Card sets
     */
    function setBonusMnopMultiplierOfSets(uint256[] memory _setIds, uint256[] memory _bonusMnopMultiplier) public onlyOwner {
        require(_setIds.length == _bonusMnopMultiplier.length, "_setId and _mnopPerDayPerCard have different length");
        for (uint256 i = 0; i < _setIds.length; ++i) {
            require(cardSets[_setIds[i]].cardIds.length > 0, "Set is empty");
            cardSets[_setIds[i]].bonusMnopMultiplier = _bonusMnopMultiplier[i];
        }
    }

	/**
     * @dev Remove a cardSet that has been added.
     */
    function removeCardSet(uint256 _setId) public onlyOwner {
        uint256 length = cardSets[_setId].cardIds.length;
        for (uint256 i = 0; i < length; ++i) {
            uint256 cardId = cardSets[_setId].cardIds[i];
            cardToSetMap[cardId] = 0;
        }
        delete cardSets[_setId].cardIds;
        cardSets[_setId].isRemoved = true;
    }

	/**
     * @dev Harvests the accumulated MNOP in the contract, for the caller.
     */
    function harvest() public {
        uint256 pendingMnop = totalPendingMnopOfAddress(msg.sender);
        userLastUpdate[msg.sender] = block.timestamp;
        if (pendingMnop > 0) {
            mnop.mint(treasuryAddr, pendingMnop.div(40)); // 2.5% MNOP for the dev 
            mnop.mint(msg.sender, pendingMnop);
            mnop.addClaimed(pendingMnop);
        }
        emit Harvest(msg.sender, pendingMnop);
    }

	/**
     * @dev Stakes the cards on providing the card IDs. 
     */
    function stake(uint256[] memory _cardIds) public {
        require(_cardIds.length > 0, "you need to stake something");

        // Check no card will end up above max stake and if it is needed to update the user NFT pool
        uint256 length = _cardIds.length;
        bool onlyBoosters = true;
        bool onlyNoBoosters = true;
        for (uint256 i = 0; i < length; ++i) {
            uint256 cardId = _cardIds[i];
            require(userCards[msg.sender][cardId] == 0, "item already staked");
            require(cardToSetMap[cardId] != 0, "you can't stake that");
            if (cardSets[cardToSetMap[cardId]].mnopPerDayPerCard > 0) onlyBoosters = false;
        }

        // Harvest NFT pool if the Mnop/day will be modified
        if (onlyBoosters == false) harvest();
        
        //Stake 1 unit of each cardId
        uint256[] memory amounts = new uint256[](_cardIds.length);
        for (uint256 i = 0; i < _cardIds.length; ++i) {
            amounts[i] = 1;
        }
        mnopCard.safeBatchTransferFrom(msg.sender, address(this), _cardIds, amounts, "");
		//Update the staked status for the card ID.
        for (uint256 i = 0; i < length; ++i) {
            uint256 cardId = _cardIds[i];
            userCards[msg.sender][cardId] = totalStaked[cardId].add(1); 
            stakedCards[cardId][totalStaked[cardId]] = msg.sender;
            totalStaked[cardId] = totalStaked[cardId].add(1);
        }
        emit Stake(msg.sender, _cardIds);
    }

	/**
     * @dev Unstakes the cards on providing the card IDs. 
     */
    function unstake(uint256[] memory _cardIds) public {
 
         require(_cardIds.length > 0, "input at least 1 card id");

        // Check if all cards are staked and if it is needed to update the user NFT pool
        uint256 length = _cardIds.length;
        bool onlyBoosters = true;
        bool onlyNoBoosters = true;
        for (uint256 i = 0; i < length; ++i) {
            uint256 cardId = _cardIds[i];
            require(userCards[msg.sender][cardId] > 0, "Card not staked");
            delete stakedCards[cardId][userCards[msg.sender][cardId]];
            userCards[msg.sender][cardId] = 0;
            
            totalStaked[cardId] = totalStaked[cardId].sub(1);
            if (cardSets[cardToSetMap[cardId]].mnopPerDayPerCard > 0) onlyBoosters = false;
        }
        
        if (onlyBoosters == false) harvest();


        //UnStake 1 unit of each cardId
        uint256[] memory amounts = new uint256[](_cardIds.length);
        for (uint256 i = 0; i < _cardIds.length; ++i) {
            amounts[i] = 1;
        }
        mnopCard.safeBatchTransferFrom(address(this), msg.sender, _cardIds, amounts, "");
        emit Unstake(msg.sender, _cardIds);
    }

	/**
     * @dev Emergency unstake the cards on providing the card IDs, forfeiting the MNOP rewards 
     */
    function emergencyUnstake(uint256[] memory _cardIds) public {
        userLastUpdate[msg.sender] = block.timestamp;
        uint256 length = _cardIds.length;
        for (uint256 i = 0; i < length; ++i) {
            uint256 cardId = _cardIds[i];
            require(userCards[msg.sender][cardId] > 0, "Card not staked");
            delete stakedCards[cardId][userCards[msg.sender][cardId]];
            userCards[msg.sender][cardId] = 0;
        }

        //UnStake 1 unit of each cardId
        uint256[] memory amounts = new uint256[](_cardIds.length);
        for (uint256 i = 0; i < _cardIds.length; ++i) {
            amounts[i] = 1;
        }
        mnopCard.safeBatchTransferFrom(address(this), msg.sender, _cardIds, amounts, "");
    }
    
	
    /**
     * @dev Update the Mnop token address only callable by the owner
     */
//	function setMnopTokenContract(MNOPToken _mnopAddr) public onlyOwner {
//        mnop = _mnopAddr;
//        emit SetMnopTokenContract(msg.sender, _mnopAddr);
//    }

    /**
     * @dev Update the card NFT contract address only callable by the owner
     */
//    function setCardContract(ERC1155Tradable _mnopCard) public onlyOwner {
//        mnopCard = _mnopCard;
//        emit SetCardContract(msg.sender, _mnopCard);
//    }

    /**
     * @dev Update treasury address by the previous treasury.
     */
    function treasury(address _treasuryAddr) public {
        require(msg.sender == treasuryAddr, "Only current treasury address can update.");
        treasuryAddr = _treasuryAddr;
    }

    /**
     * @notice Handle the receipt of a single ERC1155 token type
     * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated
     * This function MAY throw to revert and reject the transfer
     * Return of other amount than the magic value MUST result in the transaction being reverted
     * Note: The token contract address is always the message sender
     * @param _operator  The address which called the `safeTransferFrom` function
     * @param _from      The address which previously owned the token
     * @param _id        The id of the token being transferred
     * @param _amount    The amount of tokens being transferred
     * @param _data      Additional data with no specified format
     * @return           `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     */
    function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _amount, bytes calldata _data) external returns(bytes4) {
        return 0xf23a6e61;
    }

    /**
     * @notice Handle the receipt of multiple ERC1155 token types
     * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated
     * This function MAY throw to revert and reject the transfer
     * Return of other amount than the magic value WILL result in the transaction being reverted
     * Note: The token contract address is always the message sender
     * @param _operator  The address which called the `safeBatchTransferFrom` function
     * @param _from      The address which previously owned the token
     * @param _ids       An array containing ids of each token being transferred
     * @param _amounts   An array containing amounts of each token being transferred
     * @param _data      Additional data with no specified format
     * @return           `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     */
    function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data) external returns(bytes4) {
        return 0xbc197c81;
    }

    /**
     * @notice Indicates whether a contract implements the `ERC1155TokenReceiver` functions and so can accept ERC1155 token types.
     * @param  interfaceID The ERC-165 interface ID that is queried for support.s
     * @dev This function MUST return true if it implements the ERC1155TokenReceiver interface and ERC-165 interface.
     *      This function MUST NOT consume more than 5,000 gas.
     * @return Wheter ERC-165 or ERC1155TokenReceiver interfaces are supported.
     */
    function supportsInterface(bytes4 interfaceID) external view returns (bool) {
        return  interfaceID == 0x01ffc9a7 ||    // ERC-165 support (i.e. `bytes4(keccak256('supportsInterface(bytes4)'))`).
        interfaceID == 0x4e2312e0;      // ERC-1155 `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) ^ bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`).
    }
}

File 5 of 30 : BEP20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.4.0;

import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/GSN/Context.sol';
import './IBEP20.sol';
import '@openzeppelin/contracts/math/SafeMath.sol';

/**
 * @dev Implementation of the {IBEP20} 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 {BEP20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-BEP20-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 BEP20 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 {IBEP20-approve}.
 */
contract BEP20 is Context, IBEP20, Ownable {
    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 bep token owner.
     */
    function getOwner() external override view returns (address) {
        return owner();
    }

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

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

    /**
    * @dev Returns the number of decimals used to get its user representation.
    */
    function decimals() public override view returns (uint8) {
        return _decimals;
    }

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

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

    /**
     * @dev See {BEP20-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 override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

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

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

    /**
     * @dev See {BEP20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {BEP20};
     *
     * 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 override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(
            sender,
            _msgSender(),
            _allowances[sender][_msgSender()].sub(amount, 'BEP20: 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 {BEP20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public 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 {BEP20-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 returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, 'BEP20: decreased allowance below zero'));
        return true;
    }

    /**
     * @dev Creates `amount` tokens and assigns them to `msg.sender`, increasing
     * the total supply.
     *
     * Requirements
     *
     * - `msg.sender` must be the token owner
     */
    // function mint(uint256 amount) public onlyOwner returns (bool) {
    //    _mint(_msgSender(), amount);
    //    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 {
        require(sender != address(0), 'BEP20: transfer from the zero address');
        require(recipient != address(0), 'BEP20: transfer to the zero address');

        _balances[sender] = _balances[sender].sub(amount, 'BEP20: 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 {
        require(account != address(0), 'BEP20: mint to the zero address');

        _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 {
        require(account != address(0), 'BEP20: burn from the zero address');

        _balances[account] = _balances[account].sub(amount, 'BEP20: 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 is 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 {
        require(owner != address(0), 'BEP20: approve from the zero address');
        require(spender != address(0), 'BEP20: approve to the zero address');

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

    /**
     * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, 'BEP20: burn amount exceeds allowance'));
    }
}

File 6 of 30 : CanTransferRole.sol
pragma solidity >=0.5.0 <0.6.13;

import "@openzeppelin/contracts/GSN/Context.sol";
import "./Roles.sol";

contract CanTransferRole is Context {
    using Roles for Roles.Role;

    event CanTransferAdded(address indexed account);
    event CanTransferRemoved(address indexed account);

    Roles.Role private _canTransfer;

    constructor () internal {
        _addCanTransfer(_msgSender());
    }

    modifier onlyCanTransfer() {
        require(canTransfer(_msgSender()), "cant: smol caller is not beeg");
        _;
    }

    function canTransfer(address account) public view returns (bool) {
        return _canTransfer.has(account);
    }

    function addCanTransfer(address account) public onlyCanTransfer {
        _addCanTransfer(account);
    }

    function renounceCanTransfer() public {
        _removeCanTransfer(_msgSender());
    }

    function _addCanTransfer(address account) internal {
        _canTransfer.add(account);
        emit CanTransferAdded(account);
    }

    function _removeCanTransfer(address account) internal {
        _canTransfer.remove(account);
        emit CanTransferRemoved(account);
    }
}

File 7 of 30 : ERC1155.sol
pragma solidity >=0.5.0 <0.6.13;

import "../interfaces/IERC165.sol";
import "../interfaces/IERC1155TokenReceiver.sol";
import "../interfaces/IERC1155.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";



/**
 * @dev Implementation of Multi-Token Standard contract
 */
contract ERC1155 is IERC165 {
  using SafeMath for uint256;
  using Address for address;


  /***********************************|
  |        Variables and Events       |
  |__________________________________*/

  // onReceive function signatures
  bytes4 constant internal ERC1155_RECEIVED_VALUE = 0xf23a6e61;
  bytes4 constant internal ERC1155_BATCH_RECEIVED_VALUE = 0xbc197c81;

  // Objects balances
  mapping (address => mapping(uint256 => uint256)) internal balances;

  // Operator Functions
  mapping (address => mapping(address => bool)) internal operators;

  // Events
  event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _amount);
  event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _amounts);
  event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
  event URI(string _uri, uint256 indexed _id);


  /***********************************|
  |     Public Transfer Functions     |
  |__________________________________*/


  function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data)
    public
  {
    require((msg.sender == _from) || isApprovedForAll(_from, msg.sender), "ERC1155#safeTransferFrom: INVALID_OPERATOR");
    require(_to != address(0),"ERC1155#safeTransferFrom: INVALID_RECIPIENT");
    // require(_amount >= balances[_from][_id]) is not necessary since checked with safemath operations

    _safeTransferFrom(_from, _to, _id, _amount);
    _callonERC1155Received(_from, _to, _id, _amount, _data);
  }


  function safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data)
    public
  {
    // Requirements
    require((msg.sender == _from) || isApprovedForAll(_from, msg.sender), "ERC1155#safeBatchTransferFrom: INVALID_OPERATOR");
    require(_to != address(0), "ERC1155#safeBatchTransferFrom: INVALID_RECIPIENT");

    _safeBatchTransferFrom(_from, _to, _ids, _amounts);
    _callonERC1155BatchReceived(_from, _to, _ids, _amounts, _data);
  }


  /***********************************|
  |    Internal Transfer Functions    |
  |__________________________________*/


  function _safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount)
    internal
  {
    // Update balances
    balances[_from][_id] = balances[_from][_id].sub(_amount); // Subtract amount
    balances[_to][_id] = balances[_to][_id].add(_amount);     // Add amount

    // Emit event
    emit TransferSingle(msg.sender, _from, _to, _id, _amount);
  }

  /**
   * @dev Verifies if receiver is contract and if so, calls (_to).onERC1155Received(...)
   */
  function _callonERC1155Received(address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data)
    internal
  {
    // Check if recipient is contract
    if (_to.isContract()) {
      bytes4 retval = IERC1155TokenReceiver(_to).onERC1155Received(msg.sender, _from, _id, _amount, _data);
      require(retval == ERC1155_RECEIVED_VALUE, "ERC1155#_callonERC1155Received: INVALID_ON_RECEIVE_MESSAGE");
    }
  }

  /**
   * @dev Send multiple types of Tokens from the _from address to the _to address (with safety call)
   * @dev _from     Source addresses
   * @dev _to       Target addresses
   * @dev _ids      IDs of each token type
   * @dev _amounts  Transfer amounts per token type
   */
  function _safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts)
    internal
  {
    require(_ids.length == _amounts.length, "ERC1155#_safeBatchTransferFrom: INVALID_ARRAYS_LENGTH");

    // Number of transfer to execute
    uint256 nTransfer = _ids.length;

    // Executing all transfers
    for (uint256 i = 0; i < nTransfer; i++) {
      // Update storage balance of previous bin
      balances[_from][_ids[i]] = balances[_from][_ids[i]].sub(_amounts[i]);
      balances[_to][_ids[i]] = balances[_to][_ids[i]].add(_amounts[i]);
    }

    // Emit event
    emit TransferBatch(msg.sender, _from, _to, _ids, _amounts);
  }

  /**
   * @dev Verifies if receiver is contract and if so, calls (_to).onERC1155BatchReceived(...)
   */
  function _callonERC1155BatchReceived(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data)
    internal
  {
    // Pass data if recipient is contract
    if (_to.isContract()) {
      bytes4 retval = IERC1155TokenReceiver(_to).onERC1155BatchReceived(msg.sender, _from, _ids, _amounts, _data);
      require(retval == ERC1155_BATCH_RECEIVED_VALUE, "ERC1155#_callonERC1155BatchReceived: INVALID_ON_RECEIVE_MESSAGE");
    }
  }


  /***********************************|
  |         Operator Functions        |
  |__________________________________*/

  function setApprovalForAll(address _operator, bool _approved)
    external
  {
    // Update operator status
    operators[msg.sender][_operator] = _approved;
    emit ApprovalForAll(msg.sender, _operator, _approved);
  }


  function isApprovedForAll(address _owner, address _operator)
    public virtual view returns (bool isOperator)
  {
    return operators[_owner][_operator];
  }


  /***********************************|
  |         Balance Functions         |
  |__________________________________*/


  function balanceOf(address _owner, uint256 _id)
    public view returns (uint256)
  {
    return balances[_owner][_id];
  }


  function balanceOfBatch(address[] memory _owners, uint256[] memory _ids)
    public view returns (uint256[] memory)
  {
    require(_owners.length == _ids.length, "ERC1155#balanceOfBatch: INVALID_ARRAY_LENGTH");

    // Variables
    uint256[] memory batchBalances = new uint256[](_owners.length);

    // Iterate over each owner and token ID
    for (uint256 i = 0; i < _owners.length; i++) {
      batchBalances[i] = balances[_owners[i]][_ids[i]];
    }

    return batchBalances;
  }


  /***********************************|
  |          ERC165 Functions         |
  |__________________________________*/

  /**
   * INTERFACE_SIGNATURE_ERC165 = bytes4(keccak256("supportsInterface(bytes4)"));
   */
  bytes4 constant private INTERFACE_SIGNATURE_ERC165 = 0x01ffc9a7;

  /**
   * INTERFACE_SIGNATURE_ERC1155 =
   * bytes4(keccak256("safeTransferFrom(address,address,uint256,uint256,bytes)")) ^
   * bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)")) ^
   * bytes4(keccak256("balanceOf(address,uint256)")) ^
   * bytes4(keccak256("balanceOfBatch(address[],uint256[])")) ^
   * bytes4(keccak256("setApprovalForAll(address,bool)")) ^
   * bytes4(keccak256("isApprovedForAll(address,address)"));
   */
  bytes4 constant private INTERFACE_SIGNATURE_ERC1155 = 0xd9b67a26;


  function supportsInterface(bytes4 _interfaceID) external override view returns (bool) {
    if (_interfaceID == INTERFACE_SIGNATURE_ERC165 ||
        _interfaceID == INTERFACE_SIGNATURE_ERC1155) {
      return true;
    }
    return false;
  }

}

File 8 of 30 : ERC1155Metadata.sol
pragma solidity >=0.5.0 <0.6.13;
import "../interfaces/IERC1155.sol";


/**
 * @notice Contract that handles metadata related methods.
 * @dev Methods assume a deterministic generation of URI based on token IDs.
 *      Methods also assume that URI uses hex representation of token IDs.
 */
contract ERC1155Metadata {

  // URI's default URI prefix
  string internal baseMetadataURI;
  event URI(string _uri, uint256 indexed _id);


  /***********************************|
  |     Metadata Public Function s    |
  |__________________________________*/

  /**
   * @notice A distinct Uniform Resource Identifier (URI) for a given token.
   * @dev URIs are defined in RFC 3986.
   *      URIs are assumed to be deterministically generated based on token ID
   *      Token IDs are assumed to be represented in their hex format in URIs
   * @return URI string
   */
  function uri(uint256 _id) public virtual view returns (string memory) {
    return string(abi.encodePacked(baseMetadataURI, _uint2str(_id), ".json"));
  }


  /***********************************|
  |    Metadata Internal Functions    |
  |__________________________________*/

  /**
   * @notice Will emit default URI log event for corresponding token _id
   * @param _tokenIDs Array of IDs of tokens to log default URI
   */
  function _logURIs(uint256[] memory _tokenIDs) internal {
    string memory baseURL = baseMetadataURI;
    string memory tokenURI;

    for (uint256 i = 0; i < _tokenIDs.length; i++) {
      tokenURI = string(abi.encodePacked(baseURL, _uint2str(_tokenIDs[i]), ".json"));
      emit URI(tokenURI, _tokenIDs[i]);
    }
  }

  /**
   * @notice Will emit a specific URI log event for corresponding token
   * @param _tokenIDs IDs of the token corresponding to the _uris logged
   * @param _URIs    The URIs of the specified _tokenIDs
   */
  function _logURIs(uint256[] memory _tokenIDs, string[] memory _URIs) internal {
    require(_tokenIDs.length == _URIs.length, "ERC1155Metadata#_logURIs: INVALID_ARRAYS_LENGTH");
    for (uint256 i = 0; i < _tokenIDs.length; i++) {
      emit URI(_URIs[i], _tokenIDs[i]);
    }
  }

  /**
   * @notice Will update the base URL of token's URI
   * @param _newBaseMetadataURI New base URL of token's URI
   */
  function _setBaseMetadataURI(string memory _newBaseMetadataURI) internal {
    baseMetadataURI = _newBaseMetadataURI;
  }


  /***********************************|
  |    Utility Internal Functions     |
  |__________________________________*/

  /**
   * @notice Convert uint256 to string
   * @param _i Unsigned integer to convert to string
   */
  function _uint2str(uint256 _i) internal pure returns (string memory _uintAsString) {
    if (_i == 0) {
      return "0";
    }

    uint256 j = _i;
    uint256 ii = _i;
    uint256 len;

    // Get number of bytes
    while (j != 0) {
      len++;
      j /= 10;
    }

    bytes memory bstr = new bytes(len);
    uint256 k = len - 1;

    // Get each individual ASCII
    while (ii != 0) {
      bstr[k--] = byte(uint8(48 + ii % 10));
      ii /= 10;
    }

    // Convert to string
    return string(bstr);
  }

}

File 9 of 30 : ERC1155MintBurn.sol
pragma solidity >=0.5.0 <0.6.13;

import "./ERC1155.sol";


/**
 * @dev Multi-Fungible Tokens with minting and burning methods. These methods assume
 *      a parent contract to be executed as they are `internal` functions
 */
contract ERC1155MintBurn is ERC1155 {


  /****************************************|
  |            Minting Functions           |
  |_______________________________________*/


  function _mint(address _to, uint256 _id, uint256 _amount, bytes memory _data)
    internal
  {
    // Add _amount
    balances[_to][_id] = balances[_to][_id].add(_amount);

    // Emit event
    emit TransferSingle(msg.sender, address(0x0), _to, _id, _amount);

    // Calling onReceive method if recipient is contract
    _callonERC1155Received(address(0x0), _to, _id, _amount, _data);
  }


  function _batchMint(address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data)
    internal
  {
    require(_ids.length == _amounts.length, "ERC1155MintBurn#batchMint: INVALID_ARRAYS_LENGTH");

    // Number of mints to execute
    uint256 nMint = _ids.length;

     // Executing all minting
    for (uint256 i = 0; i < nMint; i++) {
      // Update storage balance
      balances[_to][_ids[i]] = balances[_to][_ids[i]].add(_amounts[i]);
    }

    // Emit batch mint event
    emit TransferBatch(msg.sender, address(0x0), _to, _ids, _amounts);

    // Calling onReceive method if recipient is contract
    _callonERC1155BatchReceived(address(0x0), _to, _ids, _amounts, _data);
  }


  /****************************************|
  |            Burning Functions           |
  |_______________________________________*/


  function _burn(address _from, uint256 _id, uint256 _amount)
    internal
  {
    //Substract _amount
    balances[_from][_id] = balances[_from][_id].sub(_amount);

    // Emit event
    emit TransferSingle(msg.sender, _from, address(0x0), _id, _amount);
  }


  function _batchBurn(address _from, uint256[] memory _ids, uint256[] memory _amounts)
    internal
  {
    require(_ids.length == _amounts.length, "ERC1155MintBurn#batchBurn: INVALID_ARRAYS_LENGTH");

    // Number of mints to execute
    uint256 nBurn = _ids.length;

     // Executing all minting
    for (uint256 i = 0; i < nBurn; i++) {
      // Update storage balance
      balances[_from][_ids[i]] = balances[_from][_ids[i]].sub(_amounts[i]);
    }

    // Emit batch mint event
    emit TransferBatch(msg.sender, _from, address(0x0), _ids, _amounts);
  }

}

File 10 of 30 : ERC1155Tradable.sol
pragma solidity >=0.5.0 <0.6.13; 
// pragma solidity >=0.5.0 <0.6.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "../Strings.sol";
import './ERC1155.sol';
import './ERC1155Metadata.sol';
import './ERC1155MintBurn.sol';
import "../MinterRole.sol";
import "../WhitelistAdminRole.sol";

import '../ProxyRegistry.sol';


/**
 * @title ERC1155Tradable
 * ERC1155Tradable - ERC1155 contract that whitelists an operator address,
 * has create and mint functionality, and supports useful standards from OpenZeppelin,
  like _exists(), name(), symbol(), and totalSupply()
 */
contract ERC1155Tradable is ERC1155, ERC1155MintBurn, ERC1155Metadata, Ownable, MinterRole, WhitelistAdminRole {
    using Strings for string;

    address proxyRegistryAddress;
    uint256 private _currentTokenID = 0;
    mapping(uint256 => address) public creators;
    mapping(uint256 => uint256) public tokenSupply;
    mapping(uint256 => uint256) public tokenMaxSupply;
    // Contract name
    string public name;
    // Contract symbol
    string public symbol;

    constructor(
        string memory _name,
        string memory _symbol,
        address _proxyRegistryAddress
    ) public {
        name = _name;
        symbol = _symbol;
        proxyRegistryAddress = _proxyRegistryAddress;
    }

    function removeWhitelistAdmin(address account) public onlyOwner {
        _removeWhitelistAdmin(account);
    }

    function removeMinter(address account) public onlyOwner {
        _removeMinter(account);
    }

    function uri(uint256 _id) public override view returns (string memory) {
        require(_exists(_id), "erc721tradable#uri: NONEXISTENT_TOKEN");
        return Strings.strConcat(baseMetadataURI, Strings.uint2str(_id));
    }


    function totalSupply(uint256 _id) public view returns (uint256) {
        return tokenSupply[_id];
    }

    function maxSupply(uint256 _id) public view returns (uint256) {
        return tokenMaxSupply[_id];
    }


    function setBaseMetadataURI(string memory _newBaseMetadataURI) public virtual onlyWhitelistAdmin {
        _setBaseMetadataURI(_newBaseMetadataURI);
    }

    function create(
        uint256 _maxSupply,
        uint256 _initialSupply,
        string calldata _uri,
        bytes calldata _data
    ) external onlyWhitelistAdmin returns (uint256 tokenId) {
        require(_initialSupply <= _maxSupply, "initial supply cannot be more than max supply");
        uint256 _id = _getNextTokenID();
        _incrementTokenTypeId();
        creators[_id] = msg.sender;

        if (bytes(_uri).length > 0) {
            emit URI(_uri, _id);
        }

        if (_initialSupply != 0) _mint(msg.sender, _id, _initialSupply, _data);
        tokenSupply[_id] = _initialSupply;
        tokenMaxSupply[_id] = _maxSupply;
        return _id;
    }


    function mint(
        address _to,
        uint256 _id,
        uint256 _quantity,
        bytes memory _data
    ) public onlyMinter {
        uint256 tokenId = _id;
        uint256 newSupply = tokenSupply[tokenId].add(_quantity);
        require(newSupply <= tokenMaxSupply[tokenId], "max NFT supply reached");
        _mint(_to, _id, _quantity, _data);
        tokenSupply[_id] = tokenSupply[_id].add(_quantity);
    }

    /**
     * Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-free listings - The Beano of NFTs
     */
    function isApprovedForAll(address _owner, address _operator) public override view returns (bool isOperator) {
        // Whitelist OpenSea proxy contract for easy trading.
        ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
        if (address(proxyRegistry.proxies(_owner)) == _operator) {
            return true;
        }

        return ERC1155.isApprovedForAll(_owner, _operator);
    }

    function _exists(uint256 _id) internal view returns (bool) {
        return creators[_id] != address(0);
    }

    function _getNextTokenID() private view returns (uint256) {
        return _currentTokenID.add(1);
    }

    function _incrementTokenTypeId() private {
        _currentTokenID++;
    }
}

File 11 of 30 : IBEP20.sol
pragma solidity >=0.6.4;

interface IBEP20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

    /**
     * @dev Returns the bep token owner.
     */
    function getOwner() external view returns (address);

    /**
     * @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 12 of 30 : MinterRole.sol
pragma solidity >=0.5.0 <0.6.13;

import "@openzeppelin/contracts/GSN/Context.sol";
import "./Roles.sol";

contract MinterRole is Context {
    using Roles for Roles.Role;

    event MinterAdded(address indexed account);
    event MinterRemoved(address indexed account);

    Roles.Role private _minters;

    constructor () internal {
        _addMinter(_msgSender());
    }

    modifier onlyMinter() {
        require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
        _;
    }

    function isMinter(address account) public view returns (bool) {
        return _minters.has(account);
    }

    function addMinter(address account) public onlyMinter {
        _addMinter(account);
    }

    function renounceMinter() public {
        _removeMinter(_msgSender());
    }

    function _addMinter(address account) internal {
        _minters.add(account);
        emit MinterAdded(account);
    }

    function _removeMinter(address account) internal {
        _minters.remove(account);
        emit MinterRemoved(account);
    }
}

File 13 of 30 : ProxyRegistry.sol
pragma solidity >=0.5.0 <0.6.13;

contract OwnableDelegateProxy {}

contract ProxyRegistry {
    mapping(address => OwnableDelegateProxy) public proxies;
}

File 14 of 30 : Roles.sol
pragma solidity >=0.5.0 <0.6.13;

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    /**
     * @dev Give an account access to this role.
     */
    function add(Role storage role, address account) internal {
        require(!has(role, account), "Roles: account already has role");
        role.bearer[account] = true;
    }

    /**
     * @dev Remove an account's access to this role.
     */
    function remove(Role storage role, address account) internal {
        require(has(role, account), "Roles: account does not have role");
        role.bearer[account] = false;
    }

    /**
     * @dev Check if an account has this role.
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

File 15 of 30 : SafeBEP20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IBEP20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";

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

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

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

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

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

    function safeDecreaseAllowance(IBEP20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeBEP20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

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

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

File 16 of 30 : Strings.sol
pragma solidity >=0.6.4;

library Strings {
  // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol
  function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory) {
      bytes memory _ba = bytes(_a);
      bytes memory _bb = bytes(_b);
      bytes memory _bc = bytes(_c);
      bytes memory _bd = bytes(_d);
      bytes memory _be = bytes(_e);
      string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length);
      bytes memory babcde = bytes(abcde);
      uint k = 0;
      for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i];
      for (uint i = 0; i < _bb.length; i++) babcde[k++] = _bb[i];
      for (uint i = 0; i < _bc.length; i++) babcde[k++] = _bc[i];
      for (uint i = 0; i < _bd.length; i++) babcde[k++] = _bd[i];
      for (uint i = 0; i < _be.length; i++) babcde[k++] = _be[i];
      return string(babcde);
    }

    function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory) {
        return strConcat(_a, _b, _c, _d, "");
    }

    function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory) {
        return strConcat(_a, _b, _c, "", "");
    }

    function strConcat(string memory _a, string memory _b) internal pure returns (string memory) {
        return strConcat(_a, _b, "", "", "");
    }

    function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
        if (_i == 0) {
            return "0";
        }
        uint j = _i;
        uint len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len - 1;
        while (_i != 0) {
            bstr[k--] = byte(uint8(48 + _i % 10));
            _i /= 10;
        }
        return string(bstr);
    }
}

File 17 of 30 : WhitelistAdminRole.sol
pragma solidity >=0.5.0 <0.6.13;

import "@openzeppelin/contracts/GSN/Context.sol";
import "./Roles.sol";

/**
 * @title WhitelistAdminRole
 * @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts.
 */
contract WhitelistAdminRole is Context {
    using Roles for Roles.Role;

    event WhitelistAdminAdded(address indexed account);
    event WhitelistAdminRemoved(address indexed account);

    Roles.Role private _whitelistAdmins;

    constructor () internal {
        _addWhitelistAdmin(_msgSender());
    }

    modifier onlyWhitelistAdmin() {
        require(isWhitelistAdmin(_msgSender()), "WhitelistAdminRole: caller does not have the WhitelistAdmin role");
        _;
    }

    function isWhitelistAdmin(address account) public view returns (bool) {
        return _whitelistAdmins.has(account);
    }

    function addWhitelistAdmin(address account) public onlyWhitelistAdmin {
        _addWhitelistAdmin(account);
    }

    function renounceWhitelistAdmin() public {
        _removeWhitelistAdmin(_msgSender());
    }

    function _addWhitelistAdmin(address account) internal {
        _whitelistAdmins.add(account);
        emit WhitelistAdminAdded(account);
    }

    function _removeWhitelistAdmin(address account) internal {
        _whitelistAdmins.remove(account);
        emit WhitelistAdminRemoved(account);
    }
}

File 18 of 30 : IERC1155.sol
pragma solidity >=0.5.0 <0.6.13; 


interface IERC1155 {
  // Events

  /**
   * @dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, including zero amount transfers as well as minting or burning
   *   Operator MUST be msg.sender
   *   When minting/creating tokens, the `_from` field MUST be set to `0x0`
   *   When burning/destroying tokens, the `_to` field MUST be set to `0x0`
   *   The total amount transferred from address 0x0 minus the total amount transferred to 0x0 may be used by clients and exchanges to be added to the "circulating supply" for a given token ID
   *   To broadcast the existence of a token ID with no initial balance, the contract SHOULD emit the TransferSingle event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_amount` of 0
   */
  event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _amount);

  /**
   * @dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, including zero amount transfers as well as minting or burning
   *   Operator MUST be msg.sender
   *   When minting/creating tokens, the `_from` field MUST be set to `0x0`
   *   When burning/destroying tokens, the `_to` field MUST be set to `0x0`
   *   The total amount transferred from address 0x0 minus the total amount transferred to 0x0 may be used by clients and exchanges to be added to the "circulating supply" for a given token ID
   *   To broadcast the existence of multiple token IDs with no initial balance, this SHOULD emit the TransferBatch event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_amount` of 0
   */
  event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _amounts);

  /**
   * @dev MUST emit when an approval is updated
   */
  event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

  /**
   * @dev MUST emit when the URI is updated for a token ID
   *   URIs are defined in RFC 3986
   *   The URI MUST point a JSON file that conforms to the "ERC-1155 Metadata JSON Schema"
   */
  event URI(string _amount, uint256 indexed _id);


  function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount, bytes calldata _data) external;

  function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data) external;
  

  function balanceOf(address _owner, uint256 _id) external view returns (uint256);

  function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);


  function setApprovalForAll(address _operator, bool _approved) external;


  function isApprovedForAll(address _owner, address _operator) external view returns (bool isOperator);

}

File 19 of 30 : IERC1155TokenReceiver.sol
pragma solidity >=0.5.0 <0.6.13; 

/**
 * @dev ERC-1155 interface for accepting safe transfers.
 */
interface IERC1155TokenReceiver {


  function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _amount, bytes calldata _data) external returns(bytes4);

  function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data) external returns(bytes4);

  function supportsInterface(bytes4 interfaceID) external view returns (bool);

}

File 20 of 30 : IERC165.sol
pragma solidity >=0.5.0 <0.6.13; 

/**
 * @title ERC165
 * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
 */
interface IERC165 {


    function supportsInterface(bytes4 _interfaceId)
    external
    view
    returns (bool);
}

File 21 of 30 : VRFConsumerBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import "./vendor/SafeMathChainlink.sol";

import "./interfaces/LinkTokenInterface.sol";

import "./VRFRequestIDBase.sol";

/** ****************************************************************************
 * @notice Interface for contracts using VRF randomness
 * *****************************************************************************
 * @dev PURPOSE
 *
 * @dev Reggie the Random Oracle (not his real job) wants to provide randomness
 * @dev to Vera the verifier in such a way that Vera can be sure he's not
 * @dev making his output up to suit himself. Reggie provides Vera a public key
 * @dev to which he knows the secret key. Each time Vera provides a seed to
 * @dev Reggie, he gives back a value which is computed completely
 * @dev deterministically from the seed and the secret key.
 *
 * @dev Reggie provides a proof by which Vera can verify that the output was
 * @dev correctly computed once Reggie tells it to her, but without that proof,
 * @dev the output is indistinguishable to her from a uniform random sample
 * @dev from the output space.
 *
 * @dev The purpose of this contract is to make it easy for unrelated contracts
 * @dev to talk to Vera the verifier about the work Reggie is doing, to provide
 * @dev simple access to a verifiable source of randomness.
 * *****************************************************************************
 * @dev USAGE
 *
 * @dev Calling contracts must inherit from VRFConsumerBase, and can
 * @dev initialize VRFConsumerBase's attributes in their constructor as
 * @dev shown:
 *
 * @dev   contract VRFConsumer {
 * @dev     constuctor(<other arguments>, address _vrfCoordinator, address _link)
 * @dev       VRFConsumerBase(_vrfCoordinator, _link) public {
 * @dev         <initialization with other arguments goes here>
 * @dev       }
 * @dev   }
 *
 * @dev The oracle will have given you an ID for the VRF keypair they have
 * @dev committed to (let's call it keyHash), and have told you the minimum LINK
 * @dev price for VRF service. Make sure your contract has sufficient LINK, and
 * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you
 * @dev want to generate randomness from.
 *
 * @dev Once the VRFCoordinator has received and validated the oracle's response
 * @dev to your request, it will call your contract's fulfillRandomness method.
 *
 * @dev The randomness argument to fulfillRandomness is the actual random value
 * @dev generated from your seed.
 *
 * @dev The requestId argument is generated from the keyHash and the seed by
 * @dev makeRequestId(keyHash, seed). If your contract could have concurrent
 * @dev requests open, you can use the requestId to track which seed is
 * @dev associated with which randomness. See VRFRequestIDBase.sol for more
 * @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind,
 * @dev if your contract could have multiple requests in flight simultaneously.)
 *
 * @dev Colliding `requestId`s are cryptographically impossible as long as seeds
 * @dev differ. (Which is critical to making unpredictable randomness! See the
 * @dev next section.)
 *
 * *****************************************************************************
 * @dev SECURITY CONSIDERATIONS
 *
 * @dev A method with the ability to call your fulfillRandomness method directly
 * @dev could spoof a VRF response with any random value, so it's critical that
 * @dev it cannot be directly called by anything other than this base contract
 * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
 *
 * @dev For your users to trust that your contract's random behavior is free
 * @dev from malicious interference, it's best if you can write it so that all
 * @dev behaviors implied by a VRF response are executed *during* your
 * @dev fulfillRandomness method. If your contract must store the response (or
 * @dev anything derived from it) and use it later, you must ensure that any
 * @dev user-significant behavior which depends on that stored value cannot be
 * @dev manipulated by a subsequent VRF request.
 *
 * @dev Similarly, both miners and the VRF oracle itself have some influence
 * @dev over the order in which VRF responses appear on the blockchain, so if
 * @dev your contract could have multiple VRF requests in flight simultaneously,
 * @dev you must ensure that the order in which the VRF responses arrive cannot
 * @dev be used to manipulate your contract's user-significant behavior.
 *
 * @dev Since the ultimate input to the VRF is mixed with the block hash of the
 * @dev block in which the request is made, user-provided seeds have no impact
 * @dev on its economic security properties. They are only included for API
 * @dev compatability with previous versions of this contract.
 *
 * @dev Since the block hash of the block which contains the requestRandomness
 * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
 * @dev miner could, in principle, fork the blockchain to evict the block
 * @dev containing the request, forcing the request to be included in a
 * @dev different block with a different hash, and therefore a different input
 * @dev to the VRF. However, such an attack would incur a substantial economic
 * @dev cost. This cost scales with the number of blocks the VRF oracle waits
 * @dev until it calls responds to a request.
 */
abstract contract VRFConsumerBase is VRFRequestIDBase {

  using SafeMathChainlink for uint256;

  /**
   * @notice fulfillRandomness handles the VRF response. Your contract must
   * @notice implement it. See "SECURITY CONSIDERATIONS" above for important
   * @notice principles to keep in mind when implementing your fulfillRandomness
   * @notice method.
   *
   * @dev VRFConsumerBase expects its subcontracts to have a method with this
   * @dev signature, and will call it once it has verified the proof
   * @dev associated with the randomness. (It is triggered via a call to
   * @dev rawFulfillRandomness, below.)
   *
   * @param requestId The Id initially returned by requestRandomness
   * @param randomness the VRF output
   */
  function fulfillRandomness(bytes32 requestId, uint256 randomness)
    internal virtual;

  /**
   * @notice requestRandomness initiates a request for VRF output given _seed
   *
   * @dev The fulfillRandomness method receives the output, once it's provided
   * @dev by the Oracle, and verified by the vrfCoordinator.
   *
   * @dev The _keyHash must already be registered with the VRFCoordinator, and
   * @dev the _fee must exceed the fee specified during registration of the
   * @dev _keyHash.
   *
   * @dev The _seed parameter is vestigial, and is kept only for API
   * @dev compatibility with older versions. It can't *hurt* to mix in some of
   * @dev your own randomness, here, but it's not necessary because the VRF
   * @dev oracle will mix the hash of the block containing your request into the
   * @dev VRF seed it ultimately uses.
   *
   * @param _keyHash ID of public key against which randomness is generated
   * @param _fee The amount of LINK to send with the request
   * @param _seed seed mixed into the input of the VRF.
   *
   * @return requestId unique ID for this request
   *
   * @dev The returned requestId can be used to distinguish responses to
   * @dev concurrent requests. It is passed as the first argument to
   * @dev fulfillRandomness.
   */
  function requestRandomness(bytes32 _keyHash, uint256 _fee, uint256 _seed)
    internal returns (bytes32 requestId)
  {
    LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, _seed));
    // This is the seed passed to VRFCoordinator. The oracle will mix this with
    // the hash of the block containing this request to obtain the seed/input
    // which is finally passed to the VRF cryptographic machinery.
    uint256 vRFSeed  = makeVRFInputSeed(_keyHash, _seed, address(this), nonces[_keyHash]);
    // nonces[_keyHash] must stay in sync with
    // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above
    // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest).
    // This provides protection against the user repeating their input seed,
    // which would result in a predictable/duplicate output, if multiple such
    // requests appeared in the same block.
    nonces[_keyHash] = nonces[_keyHash].add(1);
    return makeRequestId(_keyHash, vRFSeed);
  }

  LinkTokenInterface immutable internal LINK;
  address immutable private vrfCoordinator;

  // Nonces for each VRF key from which randomness has been requested.
  //
  // Must stay in sync with VRFCoordinator[_keyHash][this]
  mapping(bytes32 /* keyHash */ => uint256 /* nonce */) private nonces;

  /**
   * @param _vrfCoordinator address of VRFCoordinator contract
   * @param _link address of LINK token contract
   *
   * @dev https://docs.chain.link/docs/link-token-contracts
   */
  constructor(address _vrfCoordinator, address _link) public {
    vrfCoordinator = _vrfCoordinator;
    LINK = LinkTokenInterface(_link);
  }

  // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
  // proof. rawFulfillRandomness then calls fulfillRandomness, after validating
  // the origin of the call
  function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external {
    require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill");
    fulfillRandomness(requestId, randomness);
  }
}

File 22 of 30 : VRFRequestIDBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract VRFRequestIDBase {

  /**
   * @notice returns the seed which is actually input to the VRF coordinator
   *
   * @dev To prevent repetition of VRF output due to repetition of the
   * @dev user-supplied seed, that seed is combined in a hash with the
   * @dev user-specific nonce, and the address of the consuming contract. The
   * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in
   * @dev the final seed, but the nonce does protect against repetition in
   * @dev requests which are included in a single block.
   *
   * @param _userSeed VRF seed input provided by user
   * @param _requester Address of the requesting contract
   * @param _nonce User-specific nonce at the time of the request
   */
  function makeVRFInputSeed(bytes32 _keyHash, uint256 _userSeed,
    address _requester, uint256 _nonce)
    internal pure returns (uint256)
  {
    return  uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce)));
  }

  /**
   * @notice Returns the id for this request
   * @param _keyHash The serviceAgreement ID to be used for this request
   * @param _vRFInputSeed The seed to be passed directly to the VRF
   * @return The id for this request
   *
   * @dev Note that _vRFInputSeed is not the seed passed by the consuming
   * @dev contract, but the one generated by makeVRFInputSeed
   */
  function makeRequestId(
    bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed));
  }
}

File 23 of 30 : LinkTokenInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);
  function approve(address spender, uint256 value) external returns (bool success);
  function balanceOf(address owner) external view returns (uint256 balance);
  function decimals() external view returns (uint8 decimalPlaces);
  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
  function increaseApproval(address spender, uint256 subtractedValue) external;
  function name() external view returns (string memory tokenName);
  function symbol() external view returns (string memory tokenSymbol);
  function totalSupply() external view returns (uint256 totalTokensIssued);
  function transfer(address to, uint256 value) external returns (bool success);
  function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
  function transferFrom(address from, address to, uint256 value) external returns (bool success);
}

File 24 of 30 : SafeMathChainlink.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.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 SafeMathChainlink {
  /**
    * @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");
    uint256 c = a - b;

    return c;
  }

  /**
    * @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) {
    // 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-solidity/pull/522
    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. Reverts 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) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, "SafeMath: division by zero");
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
    * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
    * Reverts 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;
  }
}

File 25 of 30 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

File 26 of 30 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

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

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

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

File 27 of 30 : 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 28 of 30 : 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 29 of 30 : 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 30 of 30 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

    uint256 private _status;

    constructor () internal {
        _status = _NOT_ENTERED;
    }

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

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

        _;

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

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

Contract ABI

[{"inputs":[{"internalType":"contract MNOPToken","name":"_mnop","type":"address"},{"internalType":"contract TheBroker","name":"_theBroker","type":"address"},{"internalType":"address","name":"_devaddr","type":"address"},{"internalType":"uint256","name":"_maxLevel","type":"uint256"},{"internalType":"uint256","name":"_defaultParking","type":"uint256"},{"internalType":"uint256","name":"_payDayReward","type":"uint256"},{"internalType":"uint256","name":"_chestReward","type":"uint256"},{"internalType":"uint256","name":"_rollTimeLimit","type":"uint256"},{"internalType":"uint256","name":"_activeTimeLimit","type":"uint256"},{"internalType":"uint256[]","name":"_boardTypes","type":"uint256[]"},{"internalType":"uint256[]","name":"_boardRent","type":"uint256[]"},{"internalType":"uint256[]","name":"_nftIds","type":"uint256[]"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"bytes32","name":"_vrfKeyHash","type":"bytes32"},{"internalType":"address","name":"_linkToken","type":"address"},{"internalType":"uint256","name":"_linkFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountBurned","type":"uint256"}],"name":"GotoJail","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LandedParking","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rollNum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"spodId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rent","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isPropOwner","type":"bool"},{"indexed":false,"internalType":"uint256","name":"timeStart","type":"uint256"}],"name":"Roll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetChestReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetDefaultParking","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"SetDevAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"SetFeeAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"SetGameActive","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"SetLinkFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetPayDayReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"spotId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"share","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"extraBurnt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toParking","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toBurn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toDev","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"stakers","type":"address[]"}],"name":"SpotPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"spotId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"spotType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"clearBalance","type":"bool"}],"name":"SpotUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"activeTimeLimit","type":"uint256"}],"name":"UpdateActiveTimeLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract TheBroker","name":"theBroker","type":"address"}],"name":"UpdateBrokerAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"level","type":"uint256"}],"name":"UpdateMaxLevel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rollTimeLimit","type":"uint256"}],"name":"UpdateRollTimeLimit","type":"event"},{"inputs":[],"name":"activeTimeLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addParking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"boardInfo","outputs":[{"internalType":"uint256","name":"spotType","type":"uint256"},{"internalType":"uint256","name":"rent","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"totalPaid","type":"uint256"},{"internalType":"uint256","name":"totalLanded","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"canRoll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chestReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimGameRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultParking","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_devaddr","type":"address"}],"name":"dev","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devaddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"jackpotWins","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"jailCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mnop","outputs":[{"internalType":"contract MNOPToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"parkingBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payDayReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payRent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"playerActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerInfo","outputs":[{"internalType":"uint256","name":"rewards","type":"uint256"},{"internalType":"uint256","name":"spotId","type":"uint256"},{"internalType":"uint256","name":"rentDue","type":"uint256"},{"internalType":"uint256","name":"lastRoll","type":"uint256"},{"internalType":"uint256","name":"lastRollTime","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"bool","name":"inJail","type":"bool"},{"internalType":"uint256","name":"totalClaimed","type":"uint256"},{"internalType":"uint256","name":"totalRentPaid","type":"uint256"},{"internalType":"uint256","name":"totalRolls","type":"uint256"},{"internalType":"uint256","name":"jackpotWins","type":"uint256"},{"internalType":"uint256","name":"jailCount","type":"uint256"},{"internalType":"bool","name":"isRolling","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"roll","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rollTimeLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setChestReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setDefaultParking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isActive","type":"bool"}],"name":"setGameActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_linkFee","type":"uint256"}],"name":"setLinkFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setPayDayReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"theBroker","outputs":[{"internalType":"contract TheBroker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPlayers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRentPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRentPaidOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRolls","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_activeTimeLimit","type":"uint256"}],"name":"updateActiveTimeLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLevel","type":"uint256"}],"name":"updateMaxLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rollTimeLimit","type":"uint256"}],"name":"updateRollTimeLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_spotId","type":"uint256"},{"internalType":"uint256","name":"_spotType","type":"uint256"},{"internalType":"uint256","name":"_rent","type":"uint256"},{"internalType":"uint256","name":"_nftId","type":"uint256"},{"internalType":"bool","name":"_clearBalance","type":"bool"}],"name":"updateSpot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract TheBroker","name":"_theBrokerAddress","type":"address"}],"name":"updateTheBrokerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b50604051620052d5380380620052d583398181016040526102008110156200003857600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080516040519392919084640100000000821115620000b357600080fd5b83820191506020820185811115620000ca57600080fd5b8251866020820283011164010000000082111715620000e857600080fd5b8083526020830192505050908051906020019060200280838360005b838110156200012157808201518184015260208101905062000104565b50505050905001604052602001805160405193929190846401000000008211156200014b57600080fd5b838201915060208201858111156200016257600080fd5b82518660208202830111640100000000821117156200018057600080fd5b8083526020830192505050908051906020019060200280838360005b83811015620001b95780820151818401526020810190506200019c565b5050505090500160405260200180516040519392919084640100000000821115620001e357600080fd5b83820191506020820185811115620001fa57600080fd5b82518660208202830111640100000000821117156200021857600080fd5b8083526020830192505050908051906020019060200280838360005b838110156200025157808201518184015260208101905062000234565b5050505090500160405260200180519060200190929190805190602001909291908051906020019092919080519060200190929190505050838260006200029d6200055a60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600180819055508173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250508073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505050508f600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508e600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508d600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508c600b819055508b6009819055508a600c8190555089600d8190555088600e8190555087600f8190555061dead600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620004f58787876200056260201b60201c565b83600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550826003819055508060048190555050505050505050505050505050505050620005fb565b600033905090565b825160118190555060005b601154811015620005f5576000601b600083815260200190815260200160002090508482815181106200059c57fe5b60200260200101518160000181905550838281518110620005b957fe5b60200260200101518160010181905550828281518110620005d657fe5b602002602001015181600301819055505080806001019150506200056d565b50505050565b60805160601c60a05160601c614ca1620006346000398061189c5280613c275250806115cb52806126b45280613beb5250614ca16000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c80639d8d28f811610146578063cc06c359116100c3578063d19895df11610087578063d19895df1461090e578063d49e77cd14610968578063ee0850e41461099c578063f020044f146109ba578063f2fde38b146109da578063f60cdcf614610a1e5761025e565b8063cc06c3591461080f578063ccc089741461082d578063cd5e3c5d1461085d578063cd8ff6571461087b578063ce4aa18f146108a95761025e565b8063c617d4741161010a578063c617d474146106f3578063c711c42f1461074b578063c9e3f421146107a5578063ca30c5fd146107d3578063cb98df73146107f15761025e565b80639d8d28f814610651578063a11f94331461067f578063a57c97b0146106ad578063a709c4fe146106cb578063a9224b64146106d55761025e565b80635918931b116101df57806379b5a47c116101a357806379b5a47c1461054b5780637a8042bd146105555780637f8aa692146105835780638d88a90e146105a15780638da5cb5b146105e557806394985ddd146106195761025e565b80635918931b146104a3578063605b9f42146104d15780636398de50146104ef57806370d5ae051461050d578063715018a6146105415761025e565b80633b9af158116102265780633b9af1581461032f578063442dee44146103735780634613da2e146103915780634a5af23c146103c55780634b114691146103f35761025e565b80631839a4bf1461026357806322d4c99a146102975780632c57d123146102b5578063342b158f146102e357806337cef55414610311575b600080fd5b61026b610a3c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61029f610a62565b6040518082815260200191505060405180910390f35b6102e1600480360360208110156102cb57600080fd5b8101908080359060200190929190505050610a68565b005b61030f600480360360208110156102f957600080fd5b8101908080359060200190929190505050610b6f565b005b610319610ef3565b6040518082815260200191505060405180910390f35b6103716004803603602081101561034557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ef9565b005b61037b611046565b6040518082815260200191505060405180910390f35b61039961104c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103f1600480360360208110156103db57600080fd5b8101908080359060200190929190505050611072565b005b6104356004803603602081101561040957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611179565b604051808e81526020018d81526020018c81526020018b81526020018a8152602001898152602001881515815260200187815260200186815260200185815260200184815260200183815260200182151581526020019d505050505050505050505050505060405180910390f35b6104cf600480360360208110156104b957600080fd5b81019080803590602001909291905050506111f9565b005b6104d96112e9565b6040518082815260200191505060405180910390f35b6104f76112ef565b6040518082815260200191505060405180910390f35b6105156112f5565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61054961131b565b005b610553611488565b005b6105816004803603602081101561056b57600080fd5b810190808035906020019092919050505061151a565b005b61058b61170a565b6040518082815260200191505060405180910390f35b6105e3600480360360208110156105b757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611710565b005b6105ed611871565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61064f6004803603604081101561062f57600080fd5b81019080803590602001909291908035906020019092919050505061189a565b005b61067d6004803603602081101561066757600080fd5b8101908080359060200190929190505050611969565b005b6106ab6004803603602081101561069557600080fd5b8101908080359060200190929190505050611a59565b005b6106b5611b60565b6040518082815260200191505060405180910390f35b6106d3611b66565b005b6106dd61215c565b6040518082815260200191505060405180910390f35b610749600480360360a081101561070957600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190803515159060200190929190505050612162565b005b61078d6004803603602081101561076157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506122e5565b60405180821515815260200191505060405180910390f35b6107d1600480360360208110156107bb57600080fd5b81019080803590602001909291905050506122f7565b005b6107db6123e7565b6040518082815260200191505060405180910390f35b6107f96123ed565b6040518082815260200191505060405180910390f35b6108176123f3565b6040518082815260200191505060405180910390f35b61085b6004803603602081101561084357600080fd5b810190808035151590602001909291905050506123f9565b005b6108656124fe565b6040518082815260200191505060405180910390f35b6108a76004803603602081101561089157600080fd5b8101908080359060200190929190505050612932565b005b6108d5600480360360208110156108bf57600080fd5b8101908080359060200190929190505050612a39565b60405180878152602001868152602001858152602001848152602001838152602001828152602001965050505050505060405180910390f35b6109506004803603602081101561092457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a75565b60405180821515815260200191505060405180910390f35b610970612bb6565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109a4612bdc565b6040518082815260200191505060405180910390f35b6109c2612be2565b60405180821515815260200191505060405180910390f35b610a1c600480360360208110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612bf5565b005b610a26612de7565b6040518082815260200191505060405180910390f35b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f5481565b610a70612ded565b73ffffffffffffffffffffffffffffffffffffffff16610a8e611871565b73ffffffffffffffffffffffffffffffffffffffff1614610b17576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600b819055503373ffffffffffffffffffffffffffffffffffffffff167fe2113f3a81a0d318da4c32309f2e2537eb0f99047de52d02ffcdfb685676a5e5826040518082815260200191505060405180910390a250565b60026001541415610be8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260018190555060008111610c49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180614b916023913960400191505060405180910390fd5b600080600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610cd557600080fd5b505afa158015610ce9573d6000803e3d6000fd5b505050506040513d6020811015610cff57600080fd5b8101908080519060200190929190505050905082811015610d88576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4d656d656e6f706f6c793a20496e73756666696369656e742042616c616e636581525060200191505060405180910390fd5b610d9d83601254612df590919063ffffffff16565b601281905550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330866040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b158015610e5457600080fd5b505af1158015610e68573d6000803e3d6000fd5b505050506040513d6020811015610e7e57600080fd5b8101908080519060200190929190505050915081610ee7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180614b476024913960400191505060405180910390fd5b50506001808190555050565b60145481565b610f01612ded565b73ffffffffffffffffffffffffffffffffffffffff16610f1f611871565b73ffffffffffffffffffffffffffffffffffffffff1614610fa8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ff6002eae0f95af49d5f2a8442e24081aa231784e87d69d11adda27a5ee41700d60405160405180910390a350565b600e5481565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61107a612ded565b73ffffffffffffffffffffffffffffffffffffffff16611098611871565b73ffffffffffffffffffffffffffffffffffffffff1614611121576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600e819055503373ffffffffffffffffffffffffffffffffffffffff167f30480cadb8b7ebec84d96cf365c0fb99f49ee3df78bf94c63afd203a9db3dfaa826040518082815260200191505060405180910390a250565b60196020528060005260406000206000915090508060000154908060010154908060020154908060030154908060040154908060050154908060060160009054906101000a900460ff169080600701549080600801549080600901549080600a01549080600b01549080600c0160009054906101000a900460ff1690508d565b611201612ded565b73ffffffffffffffffffffffffffffffffffffffff1661121f611871565b73ffffffffffffffffffffffffffffffffffffffff16146112a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b806009819055507f37f1d0f22488fc8874a4296124b68db0b3ff4532f88cca23df0afe5fcfeea048816040518082815260200191505060405180910390a150565b600c5481565b60095481565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611323612ded565b73ffffffffffffffffffffffffffffffffffffffff16611341611871565b73ffffffffffffffffffffffffffffffffffffffff16146113ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60026001541415611501576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600181905550611511612e7d565b60018081905550565b611522612ded565b73ffffffffffffffffffffffffffffffffffffffff16611540611871565b73ffffffffffffffffffffffffffffffffffffffff16146115c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561165a57600080fd5b505af115801561166e573d6000803e3d6000fd5b505050506040513d602081101561168457600080fd5b8101908080519060200190929190505050611707576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f556e61626c6520746f207472616e73666572000000000000000000000000000081525060200191505060405180910390fd5b50565b60125481565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146117d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260098152602001807f6465763a207775743f000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f618c54559e94f1499a808aad71ee8729f8e74e8c48e979616328ce493a1a52e760405160405180910390a350565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461195b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c0081525060200191505060405180910390fd5b6119658282612fce565b5050565b611971612ded565b73ffffffffffffffffffffffffffffffffffffffff1661198f611871565b73ffffffffffffffffffffffffffffffffffffffff1614611a18576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600d819055507f42f31f5974bce85d165cd67618def3c1884fe01269db6ec99862b7c57120217a816040518082815260200191505060405180910390a150565b611a61612ded565b73ffffffffffffffffffffffffffffffffffffffff16611a7f611871565b73ffffffffffffffffffffffffffffffffffffffff1614611b08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600f819055503373ffffffffffffffffffffffffffffffffffffffff167f170d540cb233a1295f1efbfccd6782cbb4d5126986d2f88574ff86d5f0e6cde1826040518082815260200191505060405180910390a250565b600d5481565b60026001541415611bdf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600181905550600080601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816002015490506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611cbf57600080fd5b505afa158015611cd3573d6000803e3d6000fd5b505050506040513d6020811015611ce957600080fd5b81019080805190602001909291905050509050600a60149054906101000a900460ff16611d7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f4d656d656e6f706f6c793a2047616d65206e6f7420616374697665000000000081525060200191505060405180910390fd5b60008211611df4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f4d656d656e6f706f6c793a204e6f2072656e742069732064756521000000000081525060200191505060405180910390fd5b60008111611e6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4d656d656e6f706f6c793a20496e73756666696369656e742042616c616e636581525060200191505060405180910390fd5b81811015611e76578091505b611e8d8284600201546130e790919063ffffffff16565b83600201819055506003601b600085600101548152602001908152602001600020600001541415611ed857611ecd82601254612df590919063ffffffff16565b601281905550611f86565b6006601b600085600101548152602001908152602001600020600001541415611f2c57611f27600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683613170565b611f85565b611f5982601b60008660010154815260200190815260200160002060020154612df590919063ffffffff16565b601b60008560010154815260200190815260200160002060020181905550611f848360010154613444565b5b5b611f9b82601354612df590919063ffffffff16565b601381905550611fb8828460080154612df590919063ffffffff16565b8360080181905550611fed82601b60008660010154815260200190815260200160002060040154612df590919063ffffffff16565b601b60008560010154815260200190815260200160002060040181905550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156120bc57600080fd5b505af11580156120d0573d6000803e3d6000fd5b505050506040513d60208110156120e657600080fd5b810190808051906020019092919050505093508361214f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180614b476024913960400191505060405180910390fd5b5050505060018081905550565b60165481565b61216a612ded565b73ffffffffffffffffffffffffffffffffffffffff16612188611871565b73ffffffffffffffffffffffffffffffffffffffff1614612211576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b83601b60008781526020019081526020016000206000018190555082601b60008781526020019081526020016000206001018190555081601b6000878152602001908152602001600020600301819055508015612285576000601b6000878152602001908152602001600020600201819055505b7f641dba802bf4c1b1582cb692b3dbe0c770da85f4c89bb55160917b54e8c0322485858585856040518086815260200185815260200184815260200183815260200182151581526020019550505050505060405180910390a15050505050565b60006122f082613a39565b9050919050565b6122ff612ded565b73ffffffffffffffffffffffffffffffffffffffff1661231d611871565b73ffffffffffffffffffffffffffffffffffffffff16146123a6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600c819055507f719e068c9a9d7666114d65cbc0d3d5446067874bc1ced4294164859416a57f5c816040518082815260200191505060405180910390a150565b60185481565b60175481565b600b5481565b612401612ded565b73ffffffffffffffffffffffffffffffffffffffff1661241f611871565b73ffffffffffffffffffffffffffffffffffffffff16146124a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600a60146101000a81548160ff0219169083151502179055507ff3e1b0f5223c1e42e79b47415c28b259f992b865b872b8a1dff336d5d0fd9c288160405180821515815260200191505060405180910390a150565b600080601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600a60149054906101000a900460ff166125c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f4d656d656e6f706f6c793a2047616d65206e6f7420616374697665000000000081525060200191505060405180910390fd5b600081600201541461263e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4d656d656e6f706f6c793a2052656e74206973206475652070616c210000000081525060200191505060405180910390fd5b612657600e548260040154612df590919063ffffffff16565b4210156126af576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614c216021913960400191505060405180910390fd5b6004547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561273957600080fd5b505afa15801561274d573d6000803e3d6000fd5b505050506040513d602081101561276357600080fd5b8101908080519060200190929190505050116127ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180614bb4602b913960400191505060405180910390fd5b6001816009015410156127f4576127ed6001601554612df590919063ffffffff16565b6015819055505b61280c60018260090154612df590919063ffffffff16565b816009018190555061282a6001601654612df590919063ffffffff16565b6016819055508060060160009054906101000a900460ff161561286f5760008160060160006101000a81548160ff021916908315150217905550600a81600101819055505b60006012541161288257612881613aab565b5b60008160000154111561289857612897612e7d565b5b428160040181905550600181600c0160006101000a81548160ff02191690831515021790555060006128d66003546004546128d1613b63565b613be7565b905033601a600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550809250505090565b61293a612ded565b73ffffffffffffffffffffffffffffffffffffffff16612958611871565b73ffffffffffffffffffffffffffffffffffffffff16146129e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b806004819055503373ffffffffffffffffffffffffffffffffffffffff167f765a98729fad585de4538fe0eb8e6e1adcd14c173136ceb635bf5841c8ec75a1826040518082815260200191505060405180910390a250565b601b6020528060005260406000206000915090508060000154908060010154908060020154908060030154908060040154908060050154905086565b6000600a60149054906101000a900460ff16612a945760009050612bb1565b601960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600c0160009054906101000a900460ff1615612af25760009050612bb1565b6000601960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201541115612b465760009050612bb1565b612b9d600e54601960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040154612df590919063ffffffff16565b4210612bac5760019050612bb1565b600090505b919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60135481565b600a60149054906101000a900460ff1681565b612bfd612ded565b73ffffffffffffffffffffffffffffffffffffffff16612c1b611871565b73ffffffffffffffffffffffffffffffffffffffff1614612ca4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612d2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614b6b6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60155481565b600033905090565b600080828401905083811015612e73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905060008111612f3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4d656d656e6f706f6c793a204e6f207265776172647320746f20636c61696d0081525060200191505060405180910390fd5b6000811115612fca573373ffffffffffffffffffffffffffffffffffffffff167ffc30cddea38e2bf4d6ea7d3f9ed3b6ad7f176419f4963bd81318067a4aee73fe826040518082815260200191505060405180910390a260008260000181905550612fb7818360070154612df590919063ffffffff16565b8260070181905550612fc93382613170565b5b5050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180614c42602a913960400191505060405180910390fd5b600061309d600261308f600b85613ddf90919063ffffffff16565b612df590919063ffffffff16565b90506000601a600085815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506130e18282613e69565b50505050565b60008282111561315f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b600082840390508091505092915050565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156131fb57600080fd5b505afa15801561320f573d6000803e3d6000fd5b505050506040513d602081101561322557600080fd5b8101908080519060200190929190505050905060008183111561331757600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156132d557600080fd5b505af11580156132e9573d6000803e3d6000fd5b505050506040513d60208110156132ff57600080fd5b810190808051906020019092919050505090506133e8565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156133aa57600080fd5b505af11580156133be573d6000803e3d6000fd5b505050506040513d60208110156133d457600080fd5b810190808051906020019092919050505090505b8061343e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614bdf6021913960400191505060405180910390fd5b50505050565b60115461345b600183612df590919063ffffffff16565b11156134cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f4d656d656e6f706f6c793a20496e76616c69642053706f74000000000000000081525060200191505060405180910390fd5b6000601b6000838152602001908152602001600020600201541161353e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614b266021913960400191505060405180910390fd5b6060600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d540dcc7601b6000858152602001908152602001600020600301546040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b1580156135c957600080fd5b505afa1580156135dd573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561360757600080fd5b810190808051604051939291908464010000000082111561362757600080fd5b8382019150602082018581111561363d57600080fd5b825186602082028301116401000000008211171561365a57600080fd5b8083526020830192505050908051906020019060200280838360005b83811015613691578082015181840152602081019050613676565b5050505090500160405250505090506000815190506000601b6000858152602001908152602001600020600201549050600081905060006136ef60646136e1600a8661475290919063ffffffff16565b6147d890919063ffffffff16565b9050600061371a606461370c600a8761475290919063ffffffff16565b6147d890919063ffffffff16565b90506000613745606461373760058861475290919063ffffffff16565b6147d890919063ffffffff16565b905061377e8161377084613762878a6130e790919063ffffffff16565b6130e790919063ffffffff16565b6130e790919063ffffffff16565b94506000601b60008a815260200190815260200160002060020181905550600085905060008711156138ec576137bd87876147d890919063ffffffff16565b905060005b878110156138ea576137e68982815181106137d957fe5b6020026020010151613a39565b156138dd5761380082601454612df590919063ffffffff16565b60148190555061386e82601960008c858151811061381a57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154612df590919063ffffffff16565b601960008b848151811061387e57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055506138da82886130e790919063ffffffff16565b96505b80806001019150506137c2565b505b600086111561390b576139088685612df590919063ffffffff16565b93505b61392083601254612df590919063ffffffff16565b601281905550613952600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685613170565b61397e600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683613170565b7fb03902cca8c7948e4aad54bd25e3f1f9bd51ff8ab534c931dfa0ba0831f904d2898683898789888f6040518089815260200188815260200187815260200186815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015613a145780820151818401526020810190506139f9565b50505050905001995050505050505050505060405180910390a1505050505050505050565b6000613a92600f54601960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040154612df590919063ffffffff16565b4211613aa15760019050613aa6565b600090505b919050565b600954601281905550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f19306009546040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015613b4957600080fd5b505af1158015613b5d573d6000803e3d6000fd5b50505050565b600080612b674233601054604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff1660601b815260140182815260200193505050506040516020818303038152906040528051906020012060001c81613bc557fe5b0690506002810190506010600081548092919060010191905055508091505090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea07f000000000000000000000000000000000000000000000000000000000000000085878660405160200180838152602001828152602001925050506040516020818303038152906040526040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613ce0578082015181840152602081019050613cc5565b50505050905090810190601f168015613d0d5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015613d2e57600080fd5b505af1158015613d42573d6000803e3d6000fd5b505050506040513d6020811015613d5857600080fd5b8101908080519060200190929190505050506000613d8b858430600260008a815260200190815260200160002054614867565b9050613db460016002600088815260200190815260200160002054612df590919063ffffffff16565b6002600087815260200190815260200160002081905550613dd585826148cb565b9150509392505050565b600080821415613e57576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f536166654d6174683a206d6f64756c6f206279207a65726f000000000000000081525060200191505060405180910390fd5b818381613e6057fe5b06905092915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613f0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180614c42602a913960400191505060405180910390fd5b6000806000601960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050613f6c858260010154612df590919063ffffffff16565b816001018190555084816003018190555060115481600101541061412057613fa260018260050154612df590919063ffffffff16565b8160050181905550600b5481600501541115613fc457600b5481600501819055505b613fdd60115482600101546130e790919063ffffffff16565b8160010181905550600081600101541461411f5761401e61400d8260050154600c5461475290919063ffffffff16565b601454612df590919063ffffffff16565b6014819055506140536140408260050154600c5461475290919063ffffffff16565b8260000154612df590919063ffffffff16565b8160000181905550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f19306140b38460050154600c5461475290919063ffffffff16565b6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561410657600080fd5b505af115801561411a573d6000803e3d6000fd5b505050505b5b6000601b600083600101548152602001908152602001600020905061415360018260050154612df590919063ffffffff16565b81600501819055506000816001015490506000826000015414156142d8576141b16141a084600501546141926004600c5461475290919063ffffffff16565b61475290919063ffffffff16565b601454612df590919063ffffffff16565b6014819055506141f96141e684600501546141d86004600c5461475290919063ffffffff16565b61475290919063ffffffff16565b8460000154612df590919063ffffffff16565b8360000181905550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f193061426c866005015461425e6004600c5461475290919063ffffffff16565b61475290919063ffffffff16565b6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b1580156142bf57600080fd5b505af11580156142d3573d6000803e3d6000fd5b505050505b6001826000015414806142ef575060028260000154145b1561431057614302868460010154614904565b9450841561430f57600090505b5b60038260000154141561433357614330878261475290919063ffffffff16565b90505b60048260000154141561442c57614357600d54601454612df590919063ffffffff16565b601481905550614376600d548460000154612df590919063ffffffff16565b8360000181905550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f1930600d546040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561441357600080fd5b505af1158015614427573d6000803e3d6000fd5b505050505b6005826000015414156144575761444e600e54426130e790919063ffffffff16565b83600401819055505b6008826000015414156145aa5760008360050154111561449257614489600184600501546130e790919063ffffffff16565b83600501819055505b60018360060160006101000a81548160ff0219169083151502179055506144c7600184600b0154612df590919063ffffffff16565b83600b01819055506144e56001601854612df590919063ffffffff16565b6018819055506000601254905060006012819055506145226145136002600e5461475290919063ffffffff16565b42612df590919063ffffffff16565b84600401819055508673ffffffffffffffffffffffffffffffffffffffff167f63937e06ea0532bc675f0d4d297e571adc90ac93a6a399a77b9836dadc453c6e826040518082815260200191505060405180910390a26145a4600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682613170565b60019450505b60098260000154141561469c576000601254111561469b57600060125490508673ffffffffffffffffffffffffffffffffffffffff167f76828a99c7914f33ddda2515fef83f1fc2967a274d2e37800021a6ab6021be2f826040518082815260200191505060405180910390a26000601281905550614636818560000154612df590919063ffffffff16565b8460000181905550614656600185600a0154612df590919063ffffffff16565b84600a01819055506146746001601754612df590919063ffffffff16565b60178190555061468f81601454612df590919063ffffffff16565b60148190555060019450505b5b83156146ab576146aa613aab565b5b600083600c0160006101000a81548160ff0219169083151502179055508083600201819055508573ffffffffffffffffffffffffffffffffffffffff167ffe3d557dbf64be2946e1265def60832b82914bee594134aeba66e1a820cf5d58846003015485600101548489426040518086815260200185815260200184815260200183151581526020018281526020019550505050505060405180910390a250505050505050565b60008083141561476557600090506147d2565b600082840290508284828161477657fe5b04146147cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614c006021913960400191505060405180910390fd5b809150505b92915050565b600080821161484f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b600082848161485a57fe5b0490508091505092915050565b600084848484604051602001808581526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019450505050506040516020818303038152906040528051906020012060001c9050949350505050565b60008282604051602001808381526020018281526020019250505060405160208183030381529060405280519060200120905092915050565b600061490f83613a39565b61491c5760009050614b1f565b6000601b6000848152602001908152602001600020905060008160030154141561494a576000915050614b1f565b6060600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166327a1cdab866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060006040518083038186803b1580156149d557600080fd5b505afa1580156149e9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506020811015614a1357600080fd5b8101908080516040519392919084640100000000821115614a3357600080fd5b83820191506020820185811115614a4957600080fd5b8251866020820283011164010000000082111715614a6657600080fd5b8083526020830192505050908051906020019060200280838360005b83811015614a9d578082015181840152602081019050614a82565b50505050905001604052505050905060008151905060008111614ac65760009350505050614b1f565b60005b81811015614b16576000838281518110614adf57fe5b6020026020010151118015614af75750836003015481145b15614b09576001945050505050614b1f565b8080600101915050614ac9565b50600093505050505b9291505056fe4d656d656e6f706f6c793a204e6f2062616c616e636520746f20706179206f75744d656d656e6f706f6c793a207061792072656e74207472616e73666572206661696c65644f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734d656d656e6f706f6c793a20416d6f756e74206d757374206e6f74206265205a65726f4e6f7420656e6f756768204c494e4b202d2066696c6c20636f6e7472616374207769746820666175636574736166654d6e6f705472616e736665723a207472616e73666572206661696c6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d656d656e6f706f6c793a20526f6c6c2074696d65206e6f74207265616368656446756c66696c6c6d656e74206f6e6c7920616c6c6f77656420627920565246436f6f7264696e61746f72a2646970667358221220a032145c60dd959c127a78299c99f4ad85f4261bb5a43b915ce22ef67a84409a64736f6c634300060c0033000000000000000000000000cb963463b018dc6a4a773b5dfd096002d0723d64000000000000000000000000cb963463b018dc6a4a773b5dfd096002d0723d64000000000000000000000000b36a5ee119072296711b8ace01b31686e2a7ed63000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000d8d726b7177a800000000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000000000000000000000000000410d586a20a4c000000000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000c40000000000000000000000000a555fc018435bef5a13c6c6870a9d4c11dec329ccaf3c3727e033261d383b315559476f48034c13b18f8cafed4d871abe504918600000000000000000000000084b9b910527ad5c03a9ca831909e21e236ea7b06000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000410d586a20a4c00000000000000000000000000000000000000000000000000015af1d78b58c4000000000000000000000000000000000000000000000000000053444835ec580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000053444835ec5800000000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000003782dace9d9000000000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000000000000000000000000000a688906bd8b000000000000000000000000000000000000000000000000000015af1d78b58c40000000000000000000000000000000000000000000000000000c249fdd3277800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c249fdd327780000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f9ccd8a1c50800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f9ccd8a1c5080000000000000000000000000000000000000000000000000001158e460913d000000000000000000000000000000000000000000000000000015af1d78b58c40000000000000000000000000000000000000000000000000001314fb37062980000000000000000000000000000000000000000000000000001314fb370629800000000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000014d1120d7b1600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000168d28e3f0028000000000000000000000000000000000000000000000000000168d28e3f0028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018493fba64ef000000000000000000000000000000000000000000000000000015af1d78b58c400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e5b8fa8fe2ac00000000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000000000000000000000000002b5e3af16b18800000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016

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