ETH Price: $2,481.59 (+1.84%)

Transaction Decoder

Block:
10916714 at Sep-23-2020 04:44:35 AM +UTC
Transaction Fee:
0.00719328 ETH $17.85
Gas Used:
74,930 Gas / 96 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
(xnpool)
356.191131568876985471 Eth356.198324848876985471 Eth0.00719328
0x99588e87...5Be71A92F 31.989253 Eth32.024253 Eth0.035
0xB987700d...248c174C4
4.857235049764582952 Eth
Nonce: 1195
4.815041769764582952 Eth
Nonce: 1196
0.04219328
0xDe201dAe...28E270F06

Execution Trace

ETH 0.035 MEXPToken.mintToken( _tokenID=1558 ) => ( True )
  • Niftymoji.ownerOf( tokenId=1558 ) => ( 0xB987700d4152c27b9bBfbdd6041Ebdd248c174C4 )
  • Niftymoji.powerNLucks( 1558 ) => ( power=23, luck=97 )
  • ETH 0.035 0x99588e879b146cfc51628fef1e3715d5be71a92f.CALL( )
    File 1 of 2: MEXPToken
    pragma solidity 0.5.16; /*
    
    ___________________________________________________________________
      _      _                                        ______           
      |  |  /          /                                /              
    --|-/|-/-----__---/----__----__---_--_----__-------/-------__------
      |/ |/    /___) /   /   ' /   ) / /  ) /___)     /      /   )     
    __/__|____(___ _/___(___ _(___/_/_/__/_(___ _____/______(___/__o_o_
    
    
    
    
    
    ███╗   ███╗███████╗██╗  ██╗██████╗     ████████╗ ██████╗ ██╗  ██╗███████╗███╗   ██╗
    ████╗ ████║██╔════╝╚██╗██╔╝██╔══██╗    ╚══██╔══╝██╔═══██╗██║ ██╔╝██╔════╝████╗  ██║
    ██╔████╔██║█████╗   ╚███╔╝ ██████╔╝       ██║   ██║   ██║█████╔╝ █████╗  ██╔██╗ ██║
    ██║╚██╔╝██║██╔══╝   ██╔██╗ ██╔═══╝        ██║   ██║   ██║██╔═██╗ ██╔══╝  ██║╚██╗██║
    ██║ ╚═╝ ██║███████╗██╔╝ ██╗██║            ██║   ╚██████╔╝██║  ██╗███████╗██║ ╚████║
    ╚═╝     ╚═╝╚══════╝╚═╝  ╚═╝╚═╝            ╚═╝    ╚═════╝ ╚═╝  ╚═╝╚══════╝╚═╝  ╚═══╝
                                                                                       
    
    
                                                                                 
    
    
    === 'MEXP' Token contract with following features ===
        => TRC20 Compliance
        => Higher degree of control by owner - safeguard functionality
        => SafeMath implementation 
        => Burnable and minting ( For MOJI Players)
    
    
    ======================= Quick Stats ===================
        => Name        : "MOJI Experience Points"
        => Symbol      : MEXP
        => Total supply: 0 (Minted only by MOJI players only)
        => Decimals    : 18
    */
    
    
    //*******************************************************************//
    //------------------------ SafeMath Library -------------------------//
    //*******************************************************************//
    /**
        * @title SafeMath
        * @dev Math operations with safety checks that throw on error
        */
    library SafeMath {
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        require(c / a == b);
        return c;
        }
    
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
        }
    
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        return a - b;
        }
    
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);
        return c;
        }
    }
    
    
    //*******************************************************************//
    //------------------ Contract to Manage Ownership -------------------//
    //*******************************************************************//
        
    contract owned {
        address payable public owner;
        address payable private newOwner;
    
        /**
            Signer is deligated admin wallet, which can do sub-owner functions.
            Signer calls following four functions:
                => claimOwnerTokens
                => distributeMainDividend
                => distributeLeaders1
                => distributeLeaders2
        */
        address public signer;
    
        event OwnershipTransferred(address indexed _from, address indexed _to);
    
        constructor() public {
            owner = msg.sender;
            signer = msg.sender;
        }
    
        modifier onlyOwner {
            require(msg.sender == owner);
            _;
        }
    
        modifier onlySigner {
            require(msg.sender == signer);
            _;
        }
    
        function changeSigner(address _signer) public onlyOwner {
            signer = _signer;
        }
    
        function transferOwnership(address payable _newOwner) public onlyOwner {
            newOwner = _newOwner;
        }
    
        //this flow is to prevent transferring ownership to wrong wallet by mistake
        function acceptOwnership() public {
            require(msg.sender == newOwner);
            emit OwnershipTransferred(owner, newOwner);
            owner = newOwner;
            newOwner = address(0);
        }
    }
    
    
    //**************************************************************************//
    //-------------------    NIFTYMOJI CONTRACT INTERFACE    --------------------//
    //**************************************************************************//
    
    interface niftyMoji 
    {
        function ownerOf(uint256 tokenId) external view returns (address);
        function powerNLucks(uint256 tokenID) external view returns(uint256, uint256);
        function totalSupply() external view returns(uint256);
    } 
        
    
        
    //****************************************************************************//
    //---------------------    MEXP MAIN CODE STARTS HERE   ---------------------//
    //****************************************************************************//
        
    contract MEXPToken is owned {
    
        /*===============================
        =         DATA STORAGE          =
        ===============================*/
    
        // Public variables of the token
        using SafeMath for uint256;
        uint256 public withdrawnByAdmin; 
        string public constant name = "MOJI Experience Points";
        string public constant symbol = "MEXP";
        uint256 public constant decimals = 18; 
        uint256 public totalSupply;
        uint256 public burnTracker;     //mainly used in mintToken function..
        uint256 public mintingMultiplier=10000;  // 10000 = 1, 123 = 0.0123 admin can set it minting per day, will be factored as luck %
        address public niftyMojiContractAddress = 0xde544E54a330Abd1eA8a0E6693D46BFe95D9A684;  // admin can set / change this address 
        uint256 public battleFees=1;  // default is 0.000000000000000001 Ether for battle fees, which admin can change
        uint256 public mintTokenFee = 0.001 ether;
        uint256 public battleWinReward= 10**18; // = 1 token with 18 decimal places, admin can change
        uint256 public battleLooseReward = 10**17; // = 0.1 token with 10 decimal places, admin can change
        uint256 public maxBattlePerDay=10;  //daily 10 max battles
        bool public globalHalt; // Emergency Break
        uint256 public lastFinishedIndex;
    
        // This creates a mapping with all data storage
        mapping (address => uint256) public balanceOf;
        mapping(uint256 => uint256) public totalMintedForTokenId;
        mapping(uint256 => uint256) public totalMintedByOwnerForTokenID;
        mapping(uint256 => uint256) public totalMintedByUserForTokenID;
        mapping(uint256 => uint256) public totalMintedByBattleForTokenID;
        mapping(uint256 => uint256) public dayTracker;
        mapping (address => mapping (address => uint256)) public allowance;
        
        mapping(address => uint256) public BattleCountEndTime;
        mapping (address => uint256) public userBattleCount;
        mapping(address => bool) public blackListedUser;
        mapping(uint256 => bool) public blackListedToken;
        
    
    
        struct battleInfo
        {
            uint256 tokenID;
            uint256 userSeed;
            uint256 rewardAmount;
            uint256 blockNo;
            uint256 opponentTokenID;
        }
    
        battleInfo[] public battleInfos;
    
        /*===============================
        =         PUBLIC EVENTS         =
        ===============================*/
    
        // This generates a public event of token transfer
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        // This notifies clients about the amount burnt
        event Burn(address indexed indexed from, uint256 value);
    
        // This trackes approvals
        event Approval(address indexed owner, address indexed spender, uint256 value );
    
        /*======================================
        =       STANDARD TRC20 FUNCTIONS       =
        ======================================*/
    
        /* Internal transfer, only can be called by this contract */
        function _transfer(address _from, address _to, uint _value) internal {
            
            //checking conditions
            require(!globalHalt, "paused by admin");
            require (_to != address(0x0));                      // Prevent transfer to 0x0 address. Use burn() instead      
            // overflow and undeflow checked by SafeMath Library
            balanceOf[_from] = balanceOf[_from].sub(_value);    // Subtract from the sender
            balanceOf[_to] = balanceOf[_to].add(_value);        // Add the same to the recipient       
            // emit Transfer event
            emit Transfer(_from, _to, _value);
        }
    
        /**
            * Transfer tokens
            *
            * Send `_value` tokens to `_to` from your account
            *
            * @param _to The address of the recipient
            * @param _value the amount to send
            */
        function transfer(address _to, uint256 _value) public returns (bool success) {
            require(!blackListedUser[msg.sender], "you are not allowed");
            //no need to check for input validations, as that is ruled by SafeMath
            _transfer(msg.sender, _to, _value);
            
            return true;
        }
    
        /**
            * Transfer tokens from other address
            *
            * Send `_value` tokens to `_to` in behalf of `_from`
            *
            * @param _from The address of the sender
            * @param _to The address of the recipient
            * @param _value the amount to send
            */
        function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
            require(!blackListedUser[msg.sender], "you are not allowed");
            //require(_value <= allowance[_from][msg.sender]);     // no need for this condition as it is already checked by SafeMath below
            allowance[_from][msg.sender] = allowance[_from][msg.sender].sub(_value);
            _transfer(_from, _to, _value);
            
            return true;
        }
    
        /**
            * Set allowance for other address
            *
            * Allows `_spender` to spend no more than `_value` tokens in your behalf
            *
            * @param _spender The address authorized to spend
            * @param _value the max amount they can spend
            */
        function approve(address _spender, uint256 _value) public returns (bool success) {
            require(!blackListedUser[msg.sender], "you are not allowed");
            require(!globalHalt, "paused by admin");
            allowance[msg.sender][_spender] = _value;
            emit Approval(msg.sender, _spender, _value);
            return true;
        }
    
    
        /*=====================================
        =       CUSTOM PUBLIC FUNCTIONS       =
        ======================================*/
    
        /**
            Constructor function
        */
        constructor() public 
        {
            battleInfo memory temp;
            battleInfos.push(temp);
            
        }
    
        /**
            * Fallback function. It just accepts incoming Ether
        */
        function () payable external {}
        
    
        /**
            * Destroy tokens
            *
            * Remove `_value` tokens from the system irreversibly
            *
            * @param _value the amount of money to burn
            */
        function burn(uint256 _value) public returns (bool success) {
    
            require(!globalHalt, "paused by admin");
            require(!blackListedUser[msg.sender], "you are not allowed");
            //checking of enough token balance is done by SafeMath
            balanceOf[msg.sender] = balanceOf[msg.sender].sub(_value);  // Subtract from the sender
            totalSupply = totalSupply.sub(_value);                      // Updates totalSupply
            burnTracker = burnTracker.add(_value);
            
            emit Transfer(msg.sender, address(0), _value);
            //althogh we can track all the "burn" from the Transfer function, we just kept it as it is. As that is no much harm
            emit Burn(msg.sender, _value);
            return true;
        }
    
        /**
            * Destroy tokens from other account
            *
            * Remove `_value` tokens from the system irreversibly on behalf of `_from`.
            *
            * @param _from the address of the sender
            * @param _value the amount of money to burn
            */
        function burnFrom(address _from, uint256 _value) public returns (bool success) {
    
            require(!globalHalt, "paused by admin");
            require(!blackListedUser[msg.sender], "you are not allowed");
            //checking of allowance and token value is done by SafeMath
            balanceOf[_from] = balanceOf[_from].sub(_value);                         // Subtract from the targeted balance
            allowance[_from][msg.sender] = allowance[_from][msg.sender].sub(_value); // Subtract from the sender's allowance
            totalSupply = totalSupply.sub(_value);                                   // Update totalSupply
            burnTracker = burnTracker.add(_value);
            
            emit Transfer(_from, address(0), _value);
            emit  Burn(_from, _value);
            return true;
        }
    
        function mintTokenOwnerOnly(address user, uint256 _tokenID, uint256 tokenAmount) public onlyOwner returns(bool)
        {
            require(user != address(this) && user != address(0), "invalid address" );
            require(tokenAmount > 0 , "Invalid token to mint");
            require(!blackListedToken[_tokenID], "this token is blacklisted");
            if(_tokenID != 0)
            {
                require(niftyMoji(niftyMojiContractAddress).ownerOf(_tokenID) == user,"user is not the owner of this tokenID");
                totalMintedForTokenId[_tokenID] = totalMintedForTokenId[_tokenID].add(tokenAmount);
                totalMintedByOwnerForTokenID[_tokenID] = totalMintedByOwnerForTokenID[_tokenID].add(tokenAmount);
            }
            totalSupply = totalSupply.add(tokenAmount);
            balanceOf[user] = balanceOf[user].add(tokenAmount);
            //emitting Transfer event
            emit Transfer(address(0),user,tokenAmount);
            return true;
        }       
    
    
        function blackListUser(address user) public onlyOwner returns(bool)
        {
            blackListedUser[user] = true;
            return true;
        }
    
    
        function removeUserFromBlackList(address user) public onlyOwner returns(bool)
        {
            blackListedUser[user] = false;
            return true;
        }
    
    
    
    
        function blackListToken(uint256 _tokenID) public onlyOwner returns(bool)
        {
            blackListedToken[_tokenID] = true;
            return true;
        }
    
    
        function removeTokenFromBlackList(uint256 _tokenID) public onlyOwner returns(bool)
        {
            blackListedToken[_tokenID] = false;
            return true;
        }
    
        //Minting according to luck percent of the given token id 
        function mintToken(uint256 _tokenID)  public payable returns(bool) {
            require(!globalHalt, "paused by admin");
            address caller = niftyMoji(niftyMojiContractAddress).ownerOf(_tokenID);
            require(!blackListedUser[caller], "you are not allowed");
            require(!blackListedToken[_tokenID], "this token is blacklisted");
            require(caller == msg.sender,"caller is not the owner of this tokenID");
            require(msg.value >= mintTokenFee, 'Not enough token minting fee');
            uint256 dt = dayTracker[_tokenID];
            if (dt != 0)
            {
                uint256 secPassed  =  now - dt ;
                require(secPassed > 0 , "already minted for the day");
                (,uint256 luckPercent ) = niftyMoji(niftyMojiContractAddress).powerNLucks(_tokenID);
                uint256 mintAmount = (( (mintingMultiplier * (10 ** 18) * ((luckPercent + 9 ) / 10 ) ) / 100000 ) /  86400 ) * secPassed ;
                dayTracker[_tokenID] = now ;            
                totalMintedByUserForTokenID[_tokenID] = totalMintedByUserForTokenID[_tokenID].add(mintAmount);
                totalMintedForTokenId[_tokenID] = totalMintedForTokenId[_tokenID].add(mintAmount);
                totalSupply = totalSupply.add(mintAmount);
                balanceOf[caller] = balanceOf[caller].add(mintAmount);
                //emitting Transfer event
                emit Transfer(address(0),caller,mintAmount);
            }
            else
            {
               dayTracker[_tokenID] = now; 
            }
            owner.transfer(msg.value);
            return true;
        }
    
        function viewAmountIfIMintNow(uint256 _tokenID) public view returns(uint256 amount)
        {
            uint256 dt = dayTracker[_tokenID];
            if (dt != 0)
            {
                uint256 secPassed  =  now - dt ;
                (,uint256 luckPercent ) = niftyMoji(niftyMojiContractAddress).powerNLucks(_tokenID);
                amount = (( (mintingMultiplier * (10 ** 18) * ((luckPercent + 9 ) / 10 ) ) / 100000 ) /  86400 ) * secPassed ;
                return amount;
            }
            else
            {
               return (0);
            }        
        }
    
        function setMaxBattlePerDay(uint _maxBattlePerDay) public onlyOwner returns (bool)
        {
            maxBattlePerDay = _maxBattlePerDay;
            return true;
        }
    
    
        event initiateBattleEv(address caller,uint256 _tokenID,uint256 _userSeed,uint256 battleInfoIndex, uint256 blockNo);
        function initiateBattle(uint256 _tokenID, uint256 _userSeed) public payable returns (uint256 battleID)
        { 
            require(!globalHalt, "paused by admin");
            require(msg.value == battleFees, "Invalid fees amount");
            address caller = niftyMoji(niftyMojiContractAddress).ownerOf(_tokenID);
            require(!blackListedUser[caller], "you are not allowed");
            require(!blackListedToken[_tokenID], "this token is blacklisted");
            require(caller == msg.sender,"caller is not the owner of this tokenID");
            require( userBattleCount[caller] <= maxBattlePerDay, "enough for the day");
            if(BattleCountEndTime[caller] >= now )
            {
                userBattleCount[caller] += 1;
            }
            else
            {
                BattleCountEndTime[caller] = now + 86400;
                userBattleCount[caller] = 1;
            }        
            battleInfo memory temp;
            temp.tokenID = _tokenID;
            temp.userSeed = _userSeed;
            temp.blockNo = block.number;
            battleInfos.push(temp);
            //emitting Transfer event
            battleID = battleInfos.length - 1;
            address(owner).transfer(msg.value);
            emit initiateBattleEv(caller, _tokenID, _userSeed, battleID,block.number );   
            return battleID;
        }
    
    
        event finishBattleEv(address user, uint256 battleInfoIndex, uint256 _tokenID, uint256 randomToken, uint256 mintAmount);
        function finishBattle(uint256 _battleInfoIndex,bytes32 blockHashValue) public onlySigner returns (bool)  // returns winning amount minted
        { 
            require(_battleInfoIndex < battleInfos.length, "Invalid Battle Index");
            require(battleInfos[_battleInfoIndex].rewardAmount == 0, "Already finished");
            uint256 _tokenID = battleInfos[_battleInfoIndex].tokenID;
            uint256 _userSeed = battleInfos[_battleInfoIndex].userSeed;
            address caller = niftyMoji(niftyMojiContractAddress).ownerOf(_tokenID);
            bool success;
            uint256 randomToken;
            address randomTokenUser;
            for(uint256 i=0;i<50;i++)
            {
                randomToken = uint256(keccak256(abi.encodePacked(blockHashValue, _userSeed))) % niftyMoji(niftyMojiContractAddress).totalSupply() + 1;
                randomTokenUser = niftyMoji(niftyMojiContractAddress).ownerOf(_tokenID);
                if(blackListedToken[randomToken] || blackListedUser[randomTokenUser])
                {
                    _userSeed += block.number%8;
                }
                else
                {
                    success = true;
                    break;
                }
            }
            require(success, "try again");
            (uint256 powerPercent,uint256 luckPercent ) = niftyMoji(niftyMojiContractAddress).powerNLucks(_tokenID);
            (uint256 powerPercent2,uint256 luckPercent2 ) = niftyMoji(niftyMojiContractAddress).powerNLucks(randomToken); 
            uint256 mintAmount;
            if( powerPercent + luckPercent > powerPercent2 + luckPercent2) 
            {
                mintAmount = battleWinReward ;           
            } 
            else
            {
                mintAmount = battleLooseReward;
            }
            battleInfos[_battleInfoIndex].rewardAmount = mintAmount;
            battleInfos[_battleInfoIndex].opponentTokenID = randomToken;
    
            emit finishBattleEv(caller,_battleInfoIndex, _tokenID, randomToken, mintAmount);   
            balanceOf[caller] = balanceOf[caller].add(mintAmount);
            totalSupply = totalSupply.add(mintAmount);
            totalMintedForTokenId[_tokenID] = totalMintedForTokenId[_tokenID].add(mintAmount);
            totalMintedByBattleForTokenID[_tokenID] = totalMintedByBattleForTokenID[_tokenID].add(mintAmount);
            dayTracker[_tokenID] = now;
            lastFinishedIndex = _battleInfoIndex;                       
            emit Transfer(address(0),caller,mintAmount);
            return true;
        }
    
        function multipleFinishBattle (bytes32[] memory _blockHashValue) public onlySigner returns(bool)
        {
            uint i;
    
            for(i=0;i<_blockHashValue.length;i++)
            {
               require(finishBattle(lastFinishedIndex + i + 1,_blockHashValue[i]),"could not fihish battle");
            }
            return true;
        }
    
        function lastUnFinishedIndexNBlock() public view returns (uint256 lastUnFinishedIndex, uint256 blockNo)
        {
            uint len = battleInfos.length-1;
            if(len >  lastFinishedIndex)
            {
                return (lastFinishedIndex +1, battleInfos[lastFinishedIndex +1].blockNo);
            }
            else
            {
                return (0,0);
            }
        }
    
    
        function setNiftyMojiContractAddress(address _niftyMojiContractAddress) public onlyOwner returns(bool)
        {
            niftyMojiContractAddress = _niftyMojiContractAddress;
            return true;
        }
    
    
        function setMintingMultiplier(uint256 _mintingMultiplier) public onlyOwner returns (bool)
        {
            mintingMultiplier = _mintingMultiplier;
            return true;
        }
    
    
        function setbattleFees(uint256 _battleFees) public onlyOwner returns(bool)
        {
            battleFees = _battleFees;
            return true;
        }
        
        function setMintTokenFee(uint256 _mintTokenFee) public onlyOwner returns(bool)
        {
            mintTokenFee = _mintTokenFee;
            return true;
        }
        
        
        
    
        function setBattleReward(uint256 winReward, uint256 looseReward) public onlyOwner returns(bool)
        {
            battleWinReward = winReward;
            battleLooseReward = looseReward;
            return true;
        }
    
        /**
            * If global halt is off, then this funtion will on it. And vice versa
            * This also change safeguard for token movement status
        */
        function changeGlobalHalt() onlyOwner public returns(bool) {
            if (globalHalt == false){
                globalHalt = true;
            }
            else{
                globalHalt = false;  
            }
            return true;
        }
    
     
    
        /**
            * Function to check Ether balance in this contract
        */
        function totalEtherbalanceContract() public view returns(uint256){
            return address(this).balance;
        }
    
    
        /**
         * Just in rare case, owner wants to transfer Ether from contract to owner address
         */
        function manualWithdrawEtherAdmin(uint64 Amount) public onlyOwner returns (bool){
            require (address(this).balance >= Amount);
            address(owner).transfer(Amount);
            withdrawnByAdmin = withdrawnByAdmin.add(Amount);
            return true;
        }
    
    
    }

    File 2 of 2: Niftymoji
    pragma solidity ^0.5.16; /*
    
    ___________________________________________________________________
      _      _                                        ______           
      |  |  /          /                                /              
    --|-/|-/-----__---/----__----__---_--_----__-------/-------__------
      |/ |/    /___) /   /   ' /   ) / /  ) /___)     /      /   )     
    __/__|____(___ _/___(___ _(___/_/_/__/_(___ _____/______(___/__o_o_
    
    
    
    ███╗   ██╗██╗███████╗████████╗██╗   ██╗    ███╗   ███╗ ██████╗      ██╗██╗
    ████╗  ██║██║██╔════╝╚══██╔══╝╚██╗ ██╔╝    ████╗ ████║██╔═══██╗     ██║██║
    ██╔██╗ ██║██║█████╗     ██║    ╚████╔╝     ██╔████╔██║██║   ██║     ██║██║
    ██║╚██╗██║██║██╔══╝     ██║     ╚██╔╝      ██║╚██╔╝██║██║   ██║██   ██║██║
    ██║ ╚████║██║██║        ██║      ██║       ██║ ╚═╝ ██║╚██████╔╝╚█████╔╝██║
    ╚═╝  ╚═══╝╚═╝╚═╝        ╚═╝      ╚═╝       ╚═╝     ╚═╝ ╚═════╝  ╚════╝ ╚═╝
                                                                              
    
    === 'Niftymoji' NFT Management contract with following features ===
        => ERC721 Compliance
        => ERC165 Compliance
        => SafeMath implementation 
        => Generation of new digital assets
        => Destroyal of digital assets
    
    
    ============= Independant Audit of the code ============
        => Multiple Freelancers Auditors
    
    
    -------------------------------------------------------------------
     Copyright (c) 2019 onwards  Niftymoji Inc. ( https://niftymoji.com )
    -------------------------------------------------------------------
    */ 
    
    
    /**
     * @title Ownable
     * @dev The Ownable contract has an owner address, and provides basic authorization control
     * functions, this simplifies the implementation of "user permissions".
     */
    contract Ownable {
        address payable internal _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev The Ownable constructor sets the original `owner` of the contract to the sender
         * account.
         */
        constructor () internal {
            _owner = msg.sender;
            emit OwnershipTransferred(address(0), _owner);
        }
    
        /**
         * @return the address of the owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner());
            _;
        }
    
        /**
         * @return true if `msg.sender` is the owner of the contract.
         */
        function isOwner() public view returns (bool) {
            return msg.sender == _owner;
        }
    
        /**
         * @dev Allows the current owner to relinquish control of the contract.
         * It will not be possible to call the functions with the `onlyOwner`
         * modifier anymore.
         * @notice Renouncing ownership will leave the contract without an owner,
         * thereby removing any functionality that is only available to the owner.
         */
        function renounceOwnership() public onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        /**
         * @dev Allows the current owner to transfer control of the contract to a newOwner.
         * @param newOwner The address to transfer ownership to.
         */
        function transferOwnership(address payable newOwner) public onlyOwner {
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers control of the contract to a newOwner.
         * @param newOwner The address to transfer ownership to.
         */
        function _transferOwnership(address payable newOwner) internal {
            require(newOwner != address(0));
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    
    // File: contracts/Strings.sol
    
    pragma solidity ^0.5.2;
    
    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);
      }
    
      function fromAddress(address addr) internal pure returns(string memory) {
        bytes20 addrBytes = bytes20(addr);
        bytes16 hexAlphabet = "0123456789abcdef";
        bytes memory result = new bytes(42);
        result[0] = '0';
        result[1] = 'x';
        for (uint i = 0; i < 20; i++) {
          result[i * 2 + 2] = hexAlphabet[uint8(addrBytes[i] >> 4)];
          result[i * 2 + 3] = hexAlphabet[uint8(addrBytes[i] & 0x0f)];
        }
        return string(result);
      }
    }
    
    // File: openzeppelin-solidity/contracts/introspection/IERC165.sol
    
    pragma solidity ^0.5.2;
    
    /**
     * @title IERC165
     * @dev https://eips.ethereum.org/EIPS/eip-165
     */
    interface IERC165 {
        /**
         * @notice Query if a contract implements an interface
         * @param interfaceId The interface identifier, as specified in ERC-165
         * @dev Interface identification is specified in ERC-165. This function
         * uses less than 30,000 gas.
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool);
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/IERC721.sol
    
    pragma solidity ^0.5.2;
    
    
    /**
     * @title ERC721 Non-Fungible Token Standard basic interface
     * @dev see https://eips.ethereum.org/EIPS/eip-721
     */
    contract IERC721 is IERC165 {
        event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
        event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
        event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
    
        function balanceOf(address owner) public view returns (uint256 balance);
        function ownerOf(uint256 tokenId) public view returns (address owner);
    
        function approve(address to, uint256 tokenId) public;
        function getApproved(uint256 tokenId) public view returns (address operator);
    
        function setApprovalForAll(address operator, bool _approved) public;
        function isApprovedForAll(address owner, address operator) public view returns (bool);
    
        function transferFrom(address from, address to, uint256 tokenId) public;
        function safeTransferFrom(address from, address to, uint256 tokenId) public;
    
        function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol
    
    pragma solidity ^0.5.2;
    
    /**
     * @title ERC721 token receiver interface
     * @dev Interface for any contract that wants to support safeTransfers
     * from ERC721 asset contracts.
     */
    contract IERC721Receiver {
        /**
         * @notice Handle the receipt of an NFT
         * @dev The ERC721 smart contract calls this function on the recipient
         * after a `safeTransfer`. This function MUST return the function selector,
         * otherwise the caller will revert the transaction. The selector to be
         * returned can be obtained as `this.onERC721Received.selector`. This
         * function MAY throw to revert and reject the transfer.
         * Note: the ERC721 contract address is always the message sender.
         * @param operator The address which called `safeTransferFrom` function
         * @param from The address which previously owned the token
         * @param tokenId The NFT identifier which is being transferred
         * @param data Additional data with no specified format
         * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
         */
        function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
        public returns (bytes4);
    }
    
    // File: openzeppelin-solidity/contracts/math/SafeMath.sol
    
    pragma solidity ^0.5.2;
    
    /**
     * @title SafeMath
     * @dev Unsigned math operations with safety checks that revert on error
     */
    library SafeMath {
        /**
         * @dev Multiplies two unsigned integers, reverts on 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);
    
            return c;
        }
    
        /**
         * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0);
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    
            return c;
        }
    
        /**
         * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b <= a);
            uint256 c = a - b;
    
            return c;
        }
    
        /**
         * @dev Adds two unsigned integers, reverts on overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a);
    
            return c;
        }
    
        /**
         * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
         * reverts when dividing by zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b != 0);
            return a % b;
        }
    }
    
    // File: openzeppelin-solidity/contracts/utils/Address.sol
    
    pragma solidity ^0.5.2;
    
    /**
     * Utility library of inline functions on addresses
     */
    library Address {
        /**
         * Returns whether the target address is a contract
         * @dev This function will return false if invoked during the constructor of a contract,
         * as the code is not actually created until after the constructor finishes.
         * @param account address of the account to check
         * @return whether the target address is a contract
         */
        function isContract(address account) internal view returns (bool) {
            uint256 size;
            // XXX Currently there is no better way to check if there is a contract in an address
            // than to check the size of the code at that address.
            // See https://ethereum.stackexchange.com/a/14016/36603
            // for more details about how this works.
            // TODO Check this again before the Serenity release, because all addresses will be
            // contracts then.
            // solhint-disable-next-line no-inline-assembly
            assembly { size := extcodesize(account) }
            return size > 0;
        }
    }
    
    // File: openzeppelin-solidity/contracts/drafts/Counters.sol
    
    pragma solidity ^0.5.2;
    
    
    /**
     * @title Counters
     * @author Matt Condon (@shrugs)
     * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
     * of elements in a mapping, issuing ERC721 ids, or counting request ids
     *
     * Include with `using Counters for Counters.Counter;`
     * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath
     * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
     * directly accessed.
     */
    library Counters {
        using SafeMath for uint256;
    
        struct Counter {
            // This variable should never be directly accessed by users of the library: interactions must be restricted to
            // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
            // this feature: see https://github.com/ethereum/solidity/issues/4637
            uint256 _value; // default: 0
        }
    
        function current(Counter storage counter) internal view returns (uint256) {
            return counter._value;
        }
    
        function increment(Counter storage counter) internal {
            counter._value += 1;
        }
    
        function decrement(Counter storage counter) internal {
            counter._value = counter._value.sub(1);
        }
    }
    
    // File: openzeppelin-solidity/contracts/introspection/ERC165.sol
    
    pragma solidity ^0.5.2;
    
    
    /**
     * @title ERC165
     * @author Matt Condon (@shrugs)
     * @dev Implements ERC165 using a lookup table.
     */
    contract ERC165 is IERC165 {
        bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
        /*
         * 0x01ffc9a7 ===
         *     bytes4(keccak256('supportsInterface(bytes4)'))
         */
    
        /**
         * @dev a mapping of interface id to whether or not it's supported
         */
        mapping(bytes4 => bool) private _supportedInterfaces;
    
        /**
         * @dev A contract implementing SupportsInterfaceWithLookup
         * implement ERC165 itself
         */
        constructor () internal {
            _registerInterface(_INTERFACE_ID_ERC165);
        }
    
        /**
         * @dev implement supportsInterface(bytes4) using a lookup table
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool) {
            return _supportedInterfaces[interfaceId];
        }
    
        /**
         * @dev internal method for registering an interface
         */
        function _registerInterface(bytes4 interfaceId) internal {
            require(interfaceId != 0xffffffff);
            _supportedInterfaces[interfaceId] = true;
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/ERC721.sol
    
    pragma solidity ^0.5.2;
    
    
    
    
    interface OldNiftymoji{
        function powerNLucks(uint256 tokenID) external returns(uint256, uint256);
    }
    
    
    
    
    /**
     * @title ERC721 Non-Fungible Token Standard basic implementation
     * @dev see https://eips.ethereum.org/EIPS/eip-721
     */
    contract ERC721 is ERC165, IERC721 {
        using SafeMath for uint256;
        using Address for address;
        using Counters for Counters.Counter;
        
            struct powerNLuck
        {
            uint256 power;
            uint256 luck;        
        }
        
        uint256 public totalSupply;
        
        //uint256 is tokenNo and powerNLuck is associated details in uint256
        mapping (uint256 => powerNLuck) public powerNLucks;
    
        // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
        // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
        bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
    
        // Mapping from token ID to owner
        mapping (uint256 => address) private _tokenOwner;
    
        // Mapping from token ID to approved address
        mapping (uint256 => address) private _tokenApprovals;
    
        // Mapping from owner to number of owned token
        mapping (address => Counters.Counter) private _ownedTokensCount;
    
        // Mapping from owner to operator approvals
        mapping (address => mapping (address => bool)) private _operatorApprovals;
    
        bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
        /*
         * 0x80ac58cd ===
         *     bytes4(keccak256('balanceOf(address)')) ^
         *     bytes4(keccak256('ownerOf(uint256)')) ^
         *     bytes4(keccak256('approve(address,uint256)')) ^
         *     bytes4(keccak256('getApproved(uint256)')) ^
         *     bytes4(keccak256('setApprovalForAll(address,bool)')) ^
         *     bytes4(keccak256('isApprovedForAll(address,address)')) ^
         *     bytes4(keccak256('transferFrom(address,address,uint256)')) ^
         *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
         *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
         */
    
        constructor () public {
            // register the supported interfaces to conform to ERC721 via ERC165
            _registerInterface(_INTERFACE_ID_ERC721);
        }
    
        /**
         * @dev Gets the balance of the specified address
         * @param owner address to query the balance of
         * @return uint256 representing the amount owned by the passed address
         */
        function balanceOf(address owner) public view returns (uint256) {
            require(owner != address(0));
            return _ownedTokensCount[owner].current();
        }
    
        /**
         * @dev Gets the owner of the specified token ID
         * @param tokenId uint256 ID of the token to query the owner of
         * @return address currently marked as the owner of the given token ID
         */
        function ownerOf(uint256 tokenId) public view returns (address) {
            address owner = _tokenOwner[tokenId];
            require(owner != address(0));
            return owner;
        }
    
        /**
         * @dev Approves another address to transfer the given token ID
         * The zero address indicates there is no approved address.
         * There can only be one approved address per token at a given time.
         * Can only be called by the token owner or an approved operator.
         * @param to address to be approved for the given token ID
         * @param tokenId uint256 ID of the token to be approved
         */
        function approve(address to, uint256 tokenId) public {
            address owner = ownerOf(tokenId);
            require(to != owner);
            require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
    
            _tokenApprovals[tokenId] = to;
            emit Approval(owner, to, tokenId);
        }
    
        /**
         * @dev Gets the approved address for a token ID, or zero if no address set
         * Reverts if the token ID does not exist.
         * @param tokenId uint256 ID of the token to query the approval of
         * @return address currently approved for the given token ID
         */
        function getApproved(uint256 tokenId) public view returns (address) {
            require(_exists(tokenId));
            return _tokenApprovals[tokenId];
        }
    
        /**
         * @dev Sets or unsets the approval of a given operator
         * An operator is allowed to transfer all tokens of the sender on their behalf
         * @param to operator address to set the approval
         * @param approved representing the status of the approval to be set
         */
        function setApprovalForAll(address to, bool approved) public {
            require(to != msg.sender);
            _operatorApprovals[msg.sender][to] = approved;
            emit ApprovalForAll(msg.sender, to, approved);
        }
    
        /**
         * @dev Tells whether an operator is approved by a given owner
         * @param owner owner address which you want to query the approval of
         * @param operator operator address which you want to query the approval of
         * @return bool whether the given operator is approved by the given owner
         */
        function isApprovedForAll(address owner, address operator) public view returns (bool) {
            return _operatorApprovals[owner][operator];
        }
    
        /**
         * @dev Transfers the ownership of a given token ID to another address
         * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
         * Requires the msg.sender to be the owner, approved, or operator
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         */
        function transferFrom(address from, address to, uint256 tokenId) public {
            require(_isApprovedOrOwner(msg.sender, tokenId));
    
            _transferFrom(from, to, tokenId);
        }
    
        /**
         * @dev Safely transfers the ownership of a given token ID to another address
         * If the target address is a contract, it must implement `onERC721Received`,
         * which is called upon a safe transfer, and return the magic value
         * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
         * the transfer is reverted.
         * Requires the msg.sender to be the owner, approved, or operator
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         */
        function safeTransferFrom(address from, address to, uint256 tokenId) public {
            safeTransferFrom(from, to, tokenId, "");
        }
    
        /**
         * @dev Safely transfers the ownership of a given token ID to another address
         * If the target address is a contract, it must implement `onERC721Received`,
         * which is called upon a safe transfer, and return the magic value
         * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
         * the transfer is reverted.
         * Requires the msg.sender to be the owner, approved, or operator
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         * @param _data bytes data to send along with a safe transfer check
         */
        function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
            transferFrom(from, to, tokenId);
            require(_checkOnERC721Received(from, to, tokenId, _data));
        }
    
        /**
         * @dev Returns whether the specified token exists
         * @param tokenId uint256 ID of the token to query the existence of
         * @return bool whether the token exists
         */
        function _exists(uint256 tokenId) internal view returns (bool) {
            address owner = _tokenOwner[tokenId];
            return owner != address(0);
        }
    
        /**
         * @dev Returns whether the given spender can transfer a given token ID
         * @param spender address of the spender to query
         * @param tokenId uint256 ID of the token to be transferred
         * @return bool whether the msg.sender is approved for the given token ID,
         * is an operator of the owner, or is the owner of the token
         */
        function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
            address owner = ownerOf(tokenId);
            return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
        }
    
        /**
         * @dev Internal function to mint a new token
         * Reverts if the given token ID already exists
         * @param to The address that will own the minted token
         * @param tokenId uint256 ID of the token to be minted
         */
        function _mint(address to, uint256 tokenId, uint256 _userSeed) internal {
            require(to != address(0));
            require(!_exists(tokenId));
            require(totalSupply <= 3187, 'Excedend Max Token Supply');
    
            _tokenOwner[tokenId] = to;
            _ownedTokensCount[to].increment();
            totalSupply++;
            
            //generating random numbers for luck and power based on previous blockhash and user seed
            //this method of entropy is not very secure, but kept it as consent of client
            uint256 _luck = uint256(keccak256(abi.encodePacked(blockhash( block.number -1), _userSeed))) % 100; //0-99
            uint256 _power = uint256(keccak256(abi.encodePacked(blockhash( block.number -10), now, _userSeed))) % 100; //0-99
            //assigning lucky no and power to tokenId        
            powerNLucks[tokenId].luck = _luck+1;    //this will cause it will never be zero.
            powerNLucks[tokenId].power = _power+1;  //this will cause it will never be zero.
    
            emit Transfer(address(0), to, tokenId);
        }
        
        function _mintSyncedTokens(uint256 tokenID, address user) internal {
            
            _tokenOwner[tokenID] = user;
            _ownedTokensCount[user].increment();
            totalSupply++;
            
            //generating random numbers for luck and power based on previous blockhash and user seed
            //this method of entropy is not very secure, but kept it as consent of client
            (uint256 _power, uint256 _luck) = OldNiftymoji(0x40b16A1b6bEA856745FeDf7E0946494B895611a2).powerNLucks(tokenID);  //mainnet
            //(uint256 _power, uint256 _luck) = OldNiftymoji(0x03f701FB8EA5441A9Bf98B65461e795931B55298).powerNLucks(tokenID);    //testnet
            
            //assigning lucky no and power to tokenId        
            powerNLucks[tokenID].luck = _luck;    //this will cause it will never be zero.
            powerNLucks[tokenID].power = _power;  //this will cause it will never be zero.
    
            emit Transfer(address(0), user, tokenID);
        }
        
        
    
        /**
         * @dev Internal function to burn a specific token
         * Reverts if the token does not exist
         * Deprecated, use _burn(uint256) instead.
         * @param owner owner of the token to burn
         * @param tokenId uint256 ID of the token being burned
         */
        function _burn(address owner, uint256 tokenId) internal {
            require(ownerOf(tokenId) == owner);
    
            _clearApproval(tokenId);
    
            _ownedTokensCount[owner].decrement();
            _tokenOwner[tokenId] = address(0);
    
            emit Transfer(owner, address(0), tokenId);
        }
    
        /**
         * @dev Internal function to burn a specific token
         * Reverts if the token does not exist
         * @param tokenId uint256 ID of the token being burned
         */
        function _burn(uint256 tokenId) internal {
            _burn(ownerOf(tokenId), tokenId);
        }
    
        /**
         * @dev Internal function to transfer ownership of a given token ID to another address.
         * As opposed to transferFrom, this imposes no restrictions on msg.sender.
         * @param from current owner of the token
         * @param to address to receive the ownership of the given token ID
         * @param tokenId uint256 ID of the token to be transferred
         */
        function _transferFrom(address from, address to, uint256 tokenId) internal {
            require(ownerOf(tokenId) == from);
            require(to != address(0));
    
            _clearApproval(tokenId);
    
            _ownedTokensCount[from].decrement();
            _ownedTokensCount[to].increment();
    
            _tokenOwner[tokenId] = to;
    
            emit Transfer(from, to, tokenId);
        }
    
        /**
         * @dev Internal function to invoke `onERC721Received` on a target address
         * The call is not executed if the target address is not a contract
         * @param from address representing the previous owner of the given token ID
         * @param to target address that will receive the tokens
         * @param tokenId uint256 ID of the token to be transferred
         * @param _data bytes optional data to send along with the call
         * @return bool whether the call correctly returned the expected magic value
         */
        function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
            internal returns (bool)
        {
            if (!to.isContract()) {
                return true;
            }
    
            bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
            return (retval == _ERC721_RECEIVED);
        }
    
        /**
         * @dev Private function to clear current approval of a given token ID
         * @param tokenId uint256 ID of the token to be transferred
         */
        function _clearApproval(uint256 tokenId) private {
            if (_tokenApprovals[tokenId] != address(0)) {
                _tokenApprovals[tokenId] = address(0);
            }
        }
        
        
        
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Enumerable.sol
    
    pragma solidity ^0.5.2;
    
    
    /**
     * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
     * @dev See https://eips.ethereum.org/EIPS/eip-721
     */
    contract IERC721Enumerable is IERC721 {
        //function totalSupply() public view returns (uint256);
        function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId);
    
        function tokenByIndex(uint256 index) public view returns (uint256);
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/ERC721Enumerable.sol
    
    pragma solidity ^0.5.2;
    
    
    
    
    /**
     * @title ERC-721 Non-Fungible Token with optional enumeration extension logic
     * @dev See https://eips.ethereum.org/EIPS/eip-721
     */
    contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable {
        // Mapping from owner to list of owned token IDs
        mapping(address => uint256[]) private _ownedTokens;
    
        // Mapping from token ID to index of the owner tokens list
        mapping(uint256 => uint256) private _ownedTokensIndex;
    
        // Array with all token ids, used for enumeration
        uint256[] private _allTokens;
    
        // Mapping from token id to position in the allTokens array
        mapping(uint256 => uint256) private _allTokensIndex;
    
        bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
        /*
         * 0x780e9d63 ===
         *     bytes4(keccak256('totalSupply()')) ^
         *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
         *     bytes4(keccak256('tokenByIndex(uint256)'))
         */
    
        /**
         * @dev Constructor function
         */
        constructor () public {
            // register the supported interface to conform to ERC721Enumerable via ERC165
            _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
        }
    
        /**
         * @dev Gets the token ID at a given index of the tokens list of the requested owner
         * @param owner address owning the tokens list to be accessed
         * @param index uint256 representing the index to be accessed of the requested tokens list
         * @return uint256 token ID at the given index of the tokens list owned by the requested address
         */
        function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
            require(index < balanceOf(owner));
            return _ownedTokens[owner][index];
        }
    
        /**
         * @dev Gets the total amount of tokens stored by the contract
         * @return uint256 representing the total amount of tokens
         */
        function totalSupplyEnum() public view returns (uint256) {
            return _allTokens.length;
        }
    
        /**
         * @dev Gets the token ID at a given index of all the tokens in this contract
         * Reverts if the index is greater or equal to the total number of tokens
         * @param index uint256 representing the index to be accessed of the tokens list
         * @return uint256 token ID at the given index of the tokens list
         */
        function tokenByIndex(uint256 index) public view returns (uint256) {
            require(index < totalSupplyEnum());
            return _allTokens[index];
        }
    
        
    
        /**
         * @dev Gets the list of token IDs of the requested owner
         * @param owner address owning the tokens
         * @return uint256[] List of token IDs owned by the requested address
         */
        function _tokensOfOwner(address owner) internal view returns (uint256[] storage) {
            return _ownedTokens[owner];
        }
    
        /**
         * @dev Private function to add a token to this extension's ownership-tracking data structures.
         * @param to address representing the new owner of the given token ID
         * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
         */
        function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
            _ownedTokensIndex[tokenId] = _ownedTokens[to].length;
            _ownedTokens[to].push(tokenId);
        }
    
        /**
         * @dev Private function to add a token to this extension's token tracking data structures.
         * @param tokenId uint256 ID of the token to be added to the tokens list
         */
        function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
            _allTokensIndex[tokenId] = _allTokens.length;
            _allTokens.push(tokenId);
        }
        
        /**
         * @dev Internal function to mint a new token
         * Reverts if the given token ID already exists
         * @param to address the beneficiary that will own the minted token
         * @param tokenId uint256 ID of the token to be minted
         */
        function _mint(address to, uint256 tokenId) internal {
            super._mint(to, tokenId,0);
    
            _addTokenToOwnerEnumeration(to, tokenId);
    
            _addTokenToAllTokensEnumeration(tokenId);
        }
    
        /**
         * @dev Internal function to burn a specific token
         * Reverts if the token does not exist
         * Deprecated, use _burn(uint256) instead
         * @param owner owner of the token to burn
         * @param tokenId uint256 ID of the token being burned
         */
        function _burn(address owner, uint256 tokenId) internal {
            super._burn(owner, tokenId);
    
            _removeTokenFromOwnerEnumeration(owner, tokenId);
            // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund
            _ownedTokensIndex[tokenId] = 0;
    
            _removeTokenFromAllTokensEnumeration(tokenId);
        }
    
        /**
         * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
         * while the token is not assigned a new owner, the _ownedTokensIndex mapping is _not_ updated: this allows for
         * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
         * This has O(1) time complexity, but alters the order of the _ownedTokens array.
         * @param from address representing the previous owner of the given token ID
         * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
         */
        function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
            // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
            // then delete the last slot (swap and pop).
    
            uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
            uint256 tokenIndex = _ownedTokensIndex[tokenId];
    
            // When the token to delete is the last token, the swap operation is unnecessary
            if (tokenIndex != lastTokenIndex) {
                uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
    
                _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
                _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
            }
    
            // This also deletes the contents at the last position of the array
            _ownedTokens[from].length--;
    
            // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by
            // lastTokenId, or just over the end of the array if the token was the last one).
        }
    
        /**
         * @dev Private function to remove a token from this extension's token tracking data structures.
         * This has O(1) time complexity, but alters the order of the _allTokens array.
         * @param tokenId uint256 ID of the token to be removed from the tokens list
         */
        function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
            // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
            // then delete the last slot (swap and pop).
    
            uint256 lastTokenIndex = _allTokens.length.sub(1);
            uint256 tokenIndex = _allTokensIndex[tokenId];
    
            // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
            // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
            // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
            uint256 lastTokenId = _allTokens[lastTokenIndex];
    
            _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
    
            // This also deletes the contents at the last position of the array
            _allTokens.length--;
            _allTokensIndex[tokenId] = 0;
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Metadata.sol
    
    pragma solidity ^0.5.2;
    
    
    /**
     * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
     * @dev See https://eips.ethereum.org/EIPS/eip-721
     */
    contract IERC721Metadata is IERC721 {
        function name() external view returns (string memory);
        function symbol() external view returns (string memory);
        function tokenURI(uint256 tokenId) external view returns (string memory);
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/ERC721Metadata.sol
    
    pragma solidity ^0.5.2;
    
    
    
    
    contract ERC721Metadata is ERC165, IERC721Metadata, ERC721 {
        // Token name
        string private _name;
    
        // Token symbol
        string private _symbol;
    
        // Optional mapping for token URIs
        mapping(uint256 => string) private _tokenURIs;
    
        bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
        /*
         * 0x5b5e139f ===
         *     bytes4(keccak256('name()')) ^
         *     bytes4(keccak256('symbol()')) ^
         *     bytes4(keccak256('tokenURI(uint256)'))
         */
    
        /**
         * @dev Constructor function
         */
        constructor (string memory name, string memory symbol) public {
            _name = name;
            _symbol = symbol;
    
            // register the supported interfaces to conform to ERC721 via ERC165
            _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        }
    
        /**
         * @dev Gets the token name
         * @return string representing the token name
         */
        function name() external view returns (string memory) {
            return _name;
        }
    
        /**
         * @dev Gets the token symbol
         * @return string representing the token symbol
         */
        function symbol() external view returns (string memory) {
            return _symbol;
        }
    
        /**
         * @dev Returns an URI for a given token ID
         * Throws if the token ID does not exist. May return an empty string.
         * @param tokenId uint256 ID of the token to query
         */
        function tokenURI(uint256 tokenId) external view returns (string memory) {
            require(_exists(tokenId));
            return _tokenURIs[tokenId];
        }
    
        /**
         * @dev Internal function to set the token URI for a given token
         * Reverts if the token ID does not exist
         * @param tokenId uint256 ID of the token to set its URI
         * @param uri string URI to assign
         */
        function _setTokenURI(uint256 tokenId, string memory uri) internal {
            require(_exists(tokenId));
            _tokenURIs[tokenId] = uri;
        }
    
        /**
         * @dev Internal function to burn a specific token
         * Reverts if the token does not exist
         * Deprecated, use _burn(uint256) instead
         * @param owner owner of the token to burn
         * @param tokenId uint256 ID of the token being burned by the msg.sender
         */
        function _burn(address owner, uint256 tokenId) internal {
            super._burn(owner, tokenId);
    
            // Clear metadata (if any)
            if (bytes(_tokenURIs[tokenId]).length != 0) {
                delete _tokenURIs[tokenId];
            }
        }
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol
    
    pragma solidity ^0.5.2;
    
    
    
    
    /**
     * @title Full ERC721 Token
     * This implementation includes all the required and some optional functionality of the ERC721 standard
     * Moreover, it includes approve all functionality using operator terminology
     * @dev see https://eips.ethereum.org/EIPS/eip-721
     */
    contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata {
        constructor (string memory name, string memory symbol) public ERC721Metadata(name, symbol) {
            // solhint-disable-previous-line no-empty-blocks
        }
    }
    
    
    // File: contracts/TradeableERC721Token.sol
    
    pragma solidity ^0.5.2;
    
    
    
    
    contract OwnableDelegateProxy { }
    
    
    
    contract ProxyRegistry {
        mapping(address => OwnableDelegateProxy) public proxies;
    }
    
    /**
     * @title TradeableERC721Token
     * TradeableERC721Token - ERC721 contract that whitelists a trading address, and has minting functionality.
     */
    contract TradeableERC721Token is ERC721Full, Ownable {
      using Strings for string;
      
      uint256 public tokenPrice=5 * (10**16) ;  //price of token to buy
      address proxyRegistryAddress;
      uint256 private _currentTokenId = 0;
      
      
    
      constructor(string memory _name, string memory _symbol) ERC721Full(_name, _symbol) public {
      }
    
      /**
        * @dev Mints a token to an address with a tokenURI.
        * @param _to address of the future owner of the token
        */
      function mintTo(address _to) public onlyOwner {
        uint256 newTokenId = _getNextTokenId();
        _mint(_to, newTokenId,0);
        _incrementTokenId();
      }
    
    
      function setTokenPrice(uint256 _tokenPrice) public onlyOwner returns(bool)
      {
          tokenPrice = _tokenPrice;
          return true;
      }
      
    
      function buyToken(uint256 _userSeed) public payable returns(bool)
      {
        uint256 paidAmount = msg.value;
        require(paidAmount == tokenPrice, "Invalid amount paid");
        uint256 newTokenId = _getNextTokenId();
        _mint(msg.sender, newTokenId,_userSeed);
        _incrementTokenId(); 
        _owner.transfer(paidAmount);
         return true;
      }
      
      function batchMintToken(address[] memory _buyer) public onlyOwner returns(bool)
      {
          uint256 buyerLength = _buyer.length;
          require(buyerLength <= 100, "please try less then 101");
          for(uint256 i=0;i<buyerLength;i++)
          {
            uint256 newTokenId = _getNextTokenId();
            _mint(_buyer[i], newTokenId,0);
            _incrementTokenId();           
          }
          return true;
      }
      
    
      /**
        * @dev calculates the next token ID based on value of _currentTokenId 
        * @return uint256 for the next token ID
        */
      function _getNextTokenId() private view returns (uint256) {
        return _currentTokenId.add(1);
      }
    
      /**
        * @dev increments the value of _currentTokenId 
        */
      function _incrementTokenId() private  {
        _currentTokenId++;
      }
    
      function baseTokenURI() public view returns (string memory) {
        return "";
      }
    
      function tokenURI(uint256 _tokenId) external view returns (string memory) {
        return Strings.strConcat(baseTokenURI(),Strings.uint2str(_tokenId)
        );
      }
    
      /**
       * Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-less listings.
       */
      function isApprovedForAll(
        address owner,
        address operator
      )
        public
        view
        returns (bool)
      {
        // Whitelist OpenSea proxy contract for easy trading.
        ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
        if (address(proxyRegistry.proxies(owner)) == operator) {
            return true;
        }
    
        return super.isApprovedForAll(owner, operator);
      }
      
      function changeProxyURL(address newProxyAddress) public onlyOwner returns(bool){
          proxyRegistryAddress = newProxyAddress;
          return true;
      }
      
      
      function syncFromOldContract(uint256[] memory tokens, address[] memory users) public onlyOwner returns(bool) {
          uint256 arrayLength = tokens.length;
            require(arrayLength <= 150, 'Too many tokens IDs');
            
            //processing each entries
            for(uint8 i=0; i< arrayLength; i++ ){
                if(!_exists(tokens[i])){
                    _mintSyncedTokens(tokens[i], users[i]);
                    _incrementTokenId(); 
                }
            }
            return true;
        }
      
    }
    
    // File: contracts/OpenSeaAsset.sol
    
    pragma solidity ^0.5.2;
    
    
    
    /**
     * @title OpenSea Asset
     * OpenSea Asset - A contract for easily creating custom assets on OpenSea. 
     */
    contract Niftymoji is TradeableERC721Token {
      string private _baseTokenURI;
      uint256 public changePowerPrice = 20000000000000000; //0.02 ETH
      uint256 public changeLuckPrice =  20000000000000000; //0.02 ETH
    
      constructor(
        string memory _name,
        string memory _symbol,
        string memory baseURI
      ) TradeableERC721Token(_name, _symbol) public {
        _baseTokenURI = baseURI;
      }
    
      function openSeaVersion() public pure returns (string memory) {
        return "1.2.0";
      }
    
      function baseTokenURI() public view returns (string memory) {
        return _baseTokenURI;
      }
    
      function setBaseTokenURI(string memory uri) public onlyOwner {
        _baseTokenURI = uri;
      }
      
      function changePowerLuckPrice(uint256 powerPrice, uint256 luckPrice) public onlyOwner returns(bool){
          changePowerPrice = powerPrice;
          changeLuckPrice  = luckPrice;
          return true;
      }
      
      /**
       * Status: 0 = only power, 1 = only luck, 2 = both power and luck
       */
      function changePowerLuck(uint256 tokenID, uint8 status) public payable returns(bool){
          require(msg.sender == ownerOf(tokenID), 'This token is not owned by caller');
          if(status == 0){
              require(msg.value == changePowerPrice, 'Invalid ETH amount');
                //generating random numbers for luck and power based on previous blockhash and timestamp
                //this method of entropy is not very secure, but kept it as consent of client
                uint256 _power = uint256(keccak256(abi.encodePacked(blockhash( block.number -10), now))) % 100; //0-99 
                powerNLucks[tokenID].power = _power+1;  //this will cause it will never be zero.
          }
          else if(status == 1){
              require(msg.value == changeLuckPrice, 'Invalid ETH amount');
                uint256 _luck = uint256(keccak256(abi.encodePacked(blockhash( block.number -1)))) % 100;        //0-99
                powerNLucks[tokenID].luck = _luck+1;    //this will cause it will never be zero.
          }
          else if(status == 2){
              require(msg.value == (changePowerPrice + changeLuckPrice), 'Invalid ETH amount');
                uint256 _luck = uint256(keccak256(abi.encodePacked(blockhash( block.number -1)))) % 100;        //0-99
                uint256 _power = uint256(keccak256(abi.encodePacked(blockhash( block.number -10), now))) % 100; //0-99 
                //assigning lucky no and power to tokenId        
                powerNLucks[tokenID].luck = _luck+1;    //this will cause it will never be zero.
                powerNLucks[tokenID].power = _power+1;  //this will cause it will never be zero.
          }
          
            _owner.transfer(msg.value);
            return true;
          
      }
      
      
      
      
      
    }