ETH Price: $3,174.23 (+2.26%)

Token

Ethernal Elves (ELV)
 

Overview

Max Total Supply

0 ELV

Holders

0

Total Transfers

-

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
EthernalElvesV4

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 6 : EthernalElvesV4.sol
// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.7;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./ERC721.sol"; 
import "./DataStructures.sol";
import "./Interfaces.sol";
//import "hardhat/console.sol"; 

// We are the Ethernal. The Ethernal Elves         
// Written by 0xHusky & Beff Jezos. Everything is on-chain for all time to come.
// Version 2.0.0
// Release notes: Export Sentinel / Polygon

contract EthernalElvesV4 is ERC721 {

    function name() external pure returns (string memory) { return "Ethernal Elves"; }
    function symbol() external pure returns (string memory) { return "ELV"; }
       
    using DataStructures for DataStructures.ActionVariables;
    using DataStructures for DataStructures.Elf;
    using DataStructures for DataStructures.Token; 

    IElfMetaDataHandler elfmetaDataHandler;
    ICampaigns campaigns;
    IERC20Lite public ren;
    
    using ECDSA for bytes32;
    
//STATE   

    bool public isGameActive;
    bool public isMintOpen;
    bool public isWlOpen;
    bool private initialized;

    address dev1Address;
    address dev2Address;
    address terminus;
    address public validator;
   
    uint256 public INIT_SUPPLY; 
    uint256 public price;
    bytes32 internal ketchup;
    
    uint256[] public _remaining; 
    mapping(uint256 => uint256) public sentinels; //memory slot for Elfs
    mapping(address => uint256) public bankBalances; //memory slot for bank balances
    mapping(address => bool)    public auth;
    mapping(address => uint16)  public whitelist; 

/////NEW STORAGE FROM THIS LINE V3///////////////////////////////////////////////////////
    bool public isTerminalOpen;
/////NEW STORAGE FROM THIS LINE V4///////////////////////////////////////////////////////
    mapping(bytes => uint16)  public usedRenSignatures; 

       function initialize(address _dev1Address, address _dev2Address) public {
    
       require(!initialized, "Already initialized");
       admin                = msg.sender;   
       dev1Address          = _dev1Address;
       dev2Address          = _dev2Address;
       maxSupply            = 6666; 
       INIT_SUPPLY          = 3300; 
       initialized          = true;
       price                = .088 ether;  
       _remaining           = [250,660,2500]; //[200, 600, 2500]; //this is the supply of each whitelist role
       validator            = 0x80861814a8775de20F9506CF41932E95f80f7035;
       
    }

    function setAddresses(address _ren, address _inventory, address _campaigns, address _validator)  public {
       onlyOwner();
       ren                  = IERC20Lite(_ren);
       elfmetaDataHandler   = IElfMetaDataHandler(_inventory);
       campaigns            = ICampaigns(_campaigns);
       validator            = _validator;
    }    
    
    function setAuth(address[] calldata adds_, bool status) public {
       onlyOwner();
       
        for (uint256 index = 0; index < adds_.length; index++) {
            auth[adds_[index]] = status;
        }
    }

//EVENTS

    event Action(address indexed from, uint256 indexed action, uint256 indexed tokenId);         
    event BalanceChanged(address indexed owner, uint256 indexed amount, bool indexed subtract);
    event Campaigns(address indexed owner, uint256 amount, uint256 indexed campaign, uint256 sector, uint256 indexed tokenId);
    event CheckIn(address indexed from, uint256 timestamp, uint256 indexed tokenId, uint256 indexed sentinel);      
    event CheckOut(address indexed to, uint256 timestamp, uint256 indexed tokenId);      
    event RenTransferOut(address indexed from, uint256 timestamp, uint256 indexed renAmount);   
   
        
//////////////EXPORT TO OTHER CHAINS/////////////////

function checkIn(uint256[] calldata ids, uint256 renAmount) public returns (bool) {
     
        isPlayer();
        require(isTerminalOpen, "Terminal is closed");         
         uint256 travelers = ids.length;
         if (travelers > 0) {

                    for (uint256 index = 0; index < ids.length; index++) {  
                        _actions(ids[index], 8, msg.sender, 0, 0, false, false, false, 0);
                        emit CheckIn(msg.sender, block.timestamp, ids[index], sentinels[ids[index]]);
                    }

                  
          }

            if (renAmount > 0) {
                        
                        bankBalances[msg.sender] >= renAmount ? _setAccountBalance(msg.sender, renAmount, true) :  ren.burn(msg.sender, renAmount);

                        emit RenTransferOut(msg.sender,block.timestamp,renAmount);
             }
    

}

 function checkOut(uint256[] calldata ids, uint256[] calldata sentinel, bytes[] memory signatures) public returns (bool) {
   
    isPlayer();
    require(isTerminalOpen, "Terminal is closed");
     
    
    //Add this to 
    ///All checks to happen in polygon
     uint256 travelers = ids.length;
         if (travelers > 0) {

                for (uint256 index = 0; index < ids.length; index++) {  
                    require(_isSignedByValidator(encodeSentinelForSignature(ids[index], msg.sender, sentinel[index]),signatures[index]), "incorrect signature");
                    sentinels[ids[index]] = sentinel[index];
                    _actions(ids[index], 0, msg.sender, 0, 0, false, false, false, 0);
                    emit CheckOut(msg.sender, block.timestamp, ids[index]);
                }
         }

 }

 function checkOutRen(uint256 renAmount, bytes memory renSignatures, uint256 timestamp) public returns (bool) {
   
    isPlayer();
    require(isTerminalOpen, "Terminal is closed"); 
    require(usedRenSignatures[renSignatures] == 0, "Signature already used");   

        if(renAmount > 0){
             require(_isSignedByValidator(encodeRenForSignature(renAmount, msg.sender, timestamp),renSignatures), "incorrect signature");
             usedRenSignatures[renSignatures] = 1;
             ren.mint(msg.sender, renAmount);
        }
    

 }

//CheckOut Permissions 
function encodeSentinelForSignature(uint256 id, address owner, uint256 sentinel) public pure returns (bytes32) {
     return keccak256(
            abi.encodePacked("\x19Ethereum Signed Message:\n32", 
                keccak256(
                        abi.encodePacked(id, owner, sentinel))
                        )
                    );
} 

function encodeRenForSignature(uint256 renAmount, address owner, uint256 timestamp) public pure returns (bytes32) {
     return keccak256(
            abi.encodePacked("\x19Ethereum Signed Message:\n32", 
                keccak256(
                        abi.encodePacked(renAmount, owner, timestamp))
                        )
                    );
}  
  
function _isSignedByValidator(bytes32 _hash, bytes memory _signature) private view returns (bool) {
    
    bytes32 r;
    bytes32 s;
    uint8 v;
           assembly {
                r := mload(add(_signature, 0x20))
                s := mload(add(_signature, 0x40))
                v := byte(0, mload(add(_signature, 0x60)))
            }
        
            address signer = ecrecover(_hash, v, r, s);
            return signer == validator;
  
}

/////////////////////////////////////////////////////////////////

    function mint() external payable  returns (uint256 id) {
        isPlayer();
        require(isMintOpen, "Minting is closed");
        uint256 cost;
        (cost,) = getMintPriceLevel();
        
        if (totalSupply <= INIT_SUPPLY) {            
             require(msg.value >= cost, "NotEnoughEther");
        }else{
            bankBalances[msg.sender] >= cost ? _setAccountBalance(msg.sender, cost, true) :  ren.burn(msg.sender, cost);
        }

        return _mintElf(msg.sender);

    }

//GAMEPLAY//

    function unStake(uint256[] calldata ids) external  {
          isPlayer();        

          for (uint256 index = 0; index < ids.length; index++) {  
            _actions(ids[index], 0, msg.sender, 0, 0, false, false, false, 0);
          }
    }

    function sendCampaign(uint256[] calldata ids, uint256 campaign_, uint256 sector_, bool rollWeapons_, bool rollItems_, bool useitem_) external {
          isPlayer();          

          for (uint256 index = 0; index < ids.length; index++) {  
            _actions(ids[index], 2, msg.sender, campaign_, sector_, rollWeapons_, rollItems_, useitem_, 1);
          }
    }

    function passive(uint256[] calldata ids) external {
          isPlayer();         

          for (uint256 index = 0; index < ids.length; index++) {  
            _actions(ids[index], 3, msg.sender, 0, 0, false, false, false, 0);
          }
    }

    function returnPassive(uint256[] calldata ids) external  {
          isPlayer();        

          for (uint256 index = 0; index < ids.length; index++) {  
            _actions(ids[index], 4, msg.sender, 0, 0, false, false, false, 0);
          }
    }

    function forging(uint256[] calldata ids) external payable {
          isPlayer();         
        
          for (uint256 index = 0; index < ids.length; index++) {  
            _actions(ids[index], 5, msg.sender, 0, 0, false, false, false, 0);
          }
    }

    function merchant(uint256[] calldata ids) external payable {
          isPlayer();   

          for (uint256 index = 0; index < ids.length; index++) {  
            _actions(ids[index], 6, msg.sender, 0, 0, false, false, false, 0);
          }

    }

    function heal(uint256 healer, uint256 target) external {
        isPlayer();
        _actions(healer, 7, msg.sender, target, 0, false, false, false, 0);
    }    


    function withdrawTokenBalance() external {
      
        require(bankBalances[msg.sender] > 0, "NoBalance");
        ren.mint(msg.sender, bankBalances[msg.sender]); 
        bankBalances[msg.sender] = 0;

    }


    function withdrawSomeTokenBalance(uint256 amount) external {
      
        require(bankBalances[msg.sender] > 0, "NoBalance");
        require(bankBalances[msg.sender] - amount >= 0,"Overdraft Not permitted");
        bankBalances[msg.sender] =  bankBalances[msg.sender] - amount; //update ledger first
        ren.mint(msg.sender, amount); 
      

    }

//INTERNALS
    
        function _mintElf(address _to) private returns (uint16 id) {
        
            uint256 rand = _rand();
          
            
            {        
                DataStructures.Elf memory elf;
                id = uint16(totalSupply + 1);   
                        
                elf.owner = address(0);
                elf.timestamp = block.timestamp;
                
                elf.action = elf.weaponTier = elf.inventory = 0;
                
                elf.primaryWeapon = 69; //69 is the default weapon - fists.

                (,elf.level) = getMintPriceLevel();

                elf.sentinelClass = uint16(_randomize(rand, "Class", id)) % 3;

                elf.race = rand % 100 > 97 ? 3 : uint16(_randomize(rand, "Race", id)) % 3;

                elf.hair = elf.race == 3 ? 0 : uint16(_randomize(rand, "Hair", id)) % 3;            

                elf.accessories = elf.sentinelClass == 0 ? (uint16(_randomize(rand, "Accessories", id)) % 2) + 3 : uint16(_randomize(rand, "Accessories", id)) % 2; //2 accessories MAX 7 

                uint256 _traits = DataStructures.packAttributes(elf.hair, elf.race, elf.accessories);
                uint256 _class =  DataStructures.packAttributes(elf.sentinelClass, elf.weaponTier, elf.inventory);
                
                elf.healthPoints = DataStructures.calcHealthPoints(elf.sentinelClass, elf.level);
                elf.attackPoints = DataStructures.calcAttackPoints(elf.sentinelClass, elf.weaponTier); 

            sentinels[id] = DataStructures._setElf(elf.owner, elf.timestamp, elf.action, elf.healthPoints, elf.attackPoints, elf.primaryWeapon, elf.level, _traits, _class);
            
            }
                
            _mint(_to, id);           

        }


        function _actions(
            uint256 id_, 
            uint action, 
            address elfOwner, 
            uint256 campaign_, 
            uint256 sector_, 
            bool rollWeapons, 
            bool rollItems, 
            bool useItem, 
            uint256 gameMode_) 
        
        private {

            DataStructures.Elf memory elf = DataStructures.getElf(sentinels[id_]);
            DataStructures.ActionVariables memory actions;
            require(isGameActive);
            require(ownerOf[id_] == msg.sender || elf.owner == msg.sender, "NotYourElf");
            require(elf.action != 8, "elf in Polygon");

            uint256 rand = _rand();
                
                if(action == 0){//Unstake if currently staked

                    require(ownerOf[id_] == address(this));
                    require(elf.timestamp < block.timestamp, "elf busy");
                     
                     if(elf.action == 3){
                     actions.timeDiff = (block.timestamp - elf.timestamp) / 1 days; //amount of time spent in camp CHANGE TO 1 DAYS!
                     elf.level = _exitPassive(actions.timeDiff, elf.level);
                    
                     }

                    _transfer(address(this), elfOwner, id_);      

                    elf.owner = address(0);                            

                }else if(action == 2){//campaign loop - bloodthirst and rampage mode loop.

                    require(elf.timestamp < block.timestamp, "elf busy");
                    require(elf.action != 3, "exit passive mode first");                 
            
                        if(ownerOf[id_] != address(this)){
                        _transfer(elfOwner, address(this), id_);
                        elf.owner = elfOwner;
                        }
 
                    (elf.level, actions.reward, elf.timestamp, elf.inventory) = campaigns.gameEngine(campaign_, sector_, elf.level, elf.attackPoints, elf.healthPoints, elf.inventory, useItem);
                    
                    uint256 options;
                    if(rollWeapons && rollItems){
                        options = 3;
                        }else if(rollWeapons){
                        options = 1;
                        }else if(rollItems){
                        options = 2;
                        }else{
                        options = 0;
                    }
                  
                    if(options > 0){
                       (elf.weaponTier, elf.primaryWeapon, elf.inventory) 

                                    = DataStructures.roll(id_, elf.level, _rand(), options, elf.weaponTier, elf.primaryWeapon, elf.inventory);                                    
                                    
                    }
                    
                    if(gameMode_ == 1 || gameMode_ == 2) _setAccountBalance(msg.sender, actions.reward, false);
                    if(gameMode_ == 3) elf.level = elf.level + 1;
                    
                    emit Campaigns(msg.sender, actions.reward, campaign_, sector_, id_);

                
                }else if(action == 3){//passive campaign

                    require(elf.timestamp < block.timestamp, "elf busy");
                    
                        if(ownerOf[id_] != address(this)){
                            _transfer(elfOwner, address(this), id_);
                            elf.owner = elfOwner;
                         
                        }

                    elf.timestamp = block.timestamp; //set timestamp to current block time

                }else if(action == 4){///return from passive mode
                    
                    require(elf.action == 3);                    

                    actions.timeDiff = (block.timestamp - elf.timestamp) / 1 days; //amount of time spent in camp CHANGE TO 1 DAYS!

                    elf.level = _exitPassive(actions.timeDiff, elf.level);
                   
                    
                  /*  if(actions.timeDiff >= 7){
                        actions.reward = 140 ether;
                    }
                    if(actions.timeDiff >= 14 && actions.timeDiff < 30){
                        actions.reward = 420 ether;
                    }
                    if(actions.timeDiff >= 30){
                        actions.reward = 1200 ether;
                    }
                    
                    elf.level = elf.level + (actions.timeDiff * 1); //one level per day
                    elf.level = elf.level > 100 ? 100 : elf.level;

 
                    _setAccountBalance(msg.sender, actions.reward, false);
                */

                }else if(action == 5){//forge loop for weapons
                   
                    require(msg.value >= .01 ether);  
                    require(elf.action != 3); //Cant roll in passve mode  
                   //                    
                   // (elf.weaponTier, elf.primaryWeapon, elf.inventory) = DataStructures.roll(id_, elf.level, rand, 1, elf.weaponTier, elf.primaryWeapon, elf.inventory);
                   (elf.primaryWeapon, elf.weaponTier) = _rollWeapon(elf.level, id_, rand);
   
                
                }else if(action == 6){//item or merchant loop
                   
                    require(msg.value >= .01 ether); 
                    require(elf.action != 3); //Cant roll in passve mode
                    (elf.weaponTier, elf.primaryWeapon, elf.inventory) = DataStructures.roll(id_, elf.level, rand, 2, elf.weaponTier, elf.primaryWeapon, elf.inventory);                      

                }else if(action == 7){//healing loop


                    require(elf.sentinelClass == 0, "not a healer"); 
                    require(elf.action != 3, "cant heal while passive"); //Cant heal in passve mode
                    require(elf.timestamp < block.timestamp, "elf busy");

                        if(ownerOf[id_] != address(this)){
                        _transfer(elfOwner, address(this), id_);
                        elf.owner = elfOwner;
                        }
                    
                    
                    elf.timestamp = block.timestamp + (12 hours);

                    elf.level = elf.level + 1;
                    
                    {   

                        DataStructures.Elf memory hElf = DataStructures.getElf(sentinels[campaign_]);//using the campaign varialbe for elfId here.
                        require(ownerOf[campaign_] == msg.sender || hElf.owner == msg.sender, "NotYourElf");
                               
                                if(block.timestamp < hElf.timestamp){

                                        actions.timeDiff = hElf.timestamp - block.timestamp;
                
                                        actions.timeDiff = actions.timeDiff > 0 ? 
                                            
                                            hElf.sentinelClass == 0 ? 0 : 
                                            hElf.sentinelClass == 1 ? actions.timeDiff * 1/4 : 
                                            actions.timeDiff * 1/2
                                        
                                        : actions.timeDiff;
                                        
                                        hElf.timestamp = hElf.timestamp - actions.timeDiff;                        
                                        
                                }
                            
                        actions.traits = DataStructures.packAttributes(hElf.hair, hElf.race, hElf.accessories);
                        actions.class =  DataStructures.packAttributes(hElf.sentinelClass, hElf.weaponTier, hElf.inventory);
                                
                        sentinels[campaign_] = DataStructures._setElf(hElf.owner, hElf.timestamp, hElf.action, hElf.healthPoints, hElf.attackPoints, hElf.primaryWeapon, hElf.level, actions.traits, actions.class);

                }
                }else if (action == 8){//checkIn loop Do not remove
                    
                        if(ownerOf[id_] != address(this)){
                             _transfer(elfOwner, address(this), id_);
                             elf.owner = elfOwner;                                
                        }
                    

                 
                }           
             
            actions.traits   = DataStructures.packAttributes(elf.hair, elf.race, elf.accessories);
            actions.class    = DataStructures.packAttributes(elf.sentinelClass, elf.weaponTier, elf.inventory);
            elf.healthPoints = DataStructures.calcHealthPoints(elf.sentinelClass, elf.level); 
            elf.attackPoints = DataStructures.calcAttackPoints(elf.sentinelClass, elf.weaponTier);  
            elf.level        = elf.level > 100 ? 100 : elf.level; 
            elf.action       = action;

            sentinels[id_] = DataStructures._setElf(elf.owner, elf.timestamp, elf.action, elf.healthPoints, elf.attackPoints, elf.primaryWeapon, elf.level, actions.traits, actions.class);
            emit Action(msg.sender, action, id_); 
    }



    function _exitPassive(uint256 timeDiff, uint256 _level) private returns (uint256 level) {
            
            uint256 rewards;

                    if(timeDiff >= 7){
                        rewards = 140 ether;
                    }
                    if(timeDiff >= 14 && timeDiff < 30){
                        rewards = 420 ether;
                    }
                    if(timeDiff >= 30){
                        rewards = 1200 ether;
                    }
                    
                    level = _level + (timeDiff * 1); //one level per day
                    
                    if(level >= 100){
                        level = 100;
                    }
                    
                   

                    _setAccountBalance(msg.sender, rewards, false);

    }


    function _rollWeapon(uint256 level, uint256 id, uint256 rand) internal pure returns (uint256 newWeapon, uint256 newWeaponTier) {
    
        uint256 levelTier = level == 100 ? 5 : uint256((level/20) + 1);
                
                uint256  chance = _randomize(rand, "Weapon", id) % 100;
      
                if(chance > 10 && chance < 80){
        
                             newWeaponTier = levelTier;
        
                        }else if (chance > 80 ){
        
                             newWeaponTier = levelTier + 1 > 4 ? 4 : levelTier + 1;
        
                        }else{

                                newWeaponTier = levelTier - 1 < 1 ? 1 : levelTier - 1;          
                        }
                         

                newWeapon = ((newWeaponTier - 1) * 3) + (rand % 3);  
            
        
    }
    

    function _setAccountBalance(address _owner, uint256 _amount, bool _subtract) private {
            
            _subtract ? bankBalances[_owner] -= _amount : bankBalances[_owner] += _amount;
            emit BalanceChanged(_owner, _amount, _subtract);
    }
    //NOTE BEFF WE NEED TO CHANGE THIS
    function getMintPriceLevel() public view returns (uint256 mintCost, uint256 mintLevel) {
            
            if (totalSupply <= INIT_SUPPLY) return  (price, 1);
            if (totalSupply < 4000) return  (  60 ether, 3);
            if (totalSupply < 4500) return  ( 180 ether, 5);
            if (totalSupply < 5000) return  ( 360 ether, 15);
            if (totalSupply < 5500) return  ( 600 ether, 25);
            if (totalSupply < 6000) return  ( 900 ether, 35);
            if (totalSupply < 6333) return  ( 1800 ether, 45);
            if (totalSupply < 6666) return  ( 2700  ether, 60);

    }

    function _randomize(uint256 ran, string memory dom, uint256 ness) internal pure returns (uint256) {
    return uint256(keccak256(abi.encode(ran,dom,ness)));}

    function _rand() internal view returns (uint256) {
    return uint256(keccak256(abi.encodePacked(msg.sender, block.difficulty, block.timestamp, block.basefee, ketchup)));}

//PUBLIC VIEWS
    function tokenURI(uint256 _id) external view returns(string memory) {
    return elfmetaDataHandler.getTokenURI(uint16(_id), sentinels[_id]);
    }

    function attributes(uint256 _id) external view returns(uint hair, uint race, uint accessories, uint sentinelClass, uint weaponTier, uint inventory){
    uint256 character = sentinels[_id];

    uint _traits =        uint256(uint8(character>>240));
    uint _class =         uint256(uint8(character>>248));

    hair           = (_traits / 100) % 10;
    race           = (_traits / 10) % 10;
    accessories    = (_traits) % 10;
    sentinelClass  = (_class / 100) % 10;
    weaponTier     = (_class / 10) % 10;
    inventory      = (_class) % 10; 

}

function getSentinel(uint256 _id) external view returns(uint256 sentinel){
    return sentinel = sentinels[_id];
}


function getToken(uint256 _id) external view returns(DataStructures.Token memory token){
   
    return DataStructures.getToken(sentinels[_id]);
}

function elves(uint256 _id) external view returns(address owner, uint timestamp, uint action, uint healthPoints, uint attackPoints, uint primaryWeapon, uint level) {

    uint256 character = sentinels[_id];

    owner =          address(uint160(uint256(character)));
    timestamp =      uint(uint40(character>>160));
    action =         uint(uint8(character>>200));
    healthPoints =   uint(uint8(character>>208));
    attackPoints =   uint(uint8(character>>216));
    primaryWeapon =  uint(uint8(character>>224));
    level =          uint(uint8(character>>232));   

}

//Modifiers but as functions. Less Gas
    function isPlayer() internal {    
        uint256 size = 0;
        address acc = msg.sender;
        assembly { size := extcodesize(acc)}
        require((msg.sender == tx.origin && size == 0));
        ketchup = keccak256(abi.encodePacked(acc, block.coinbase));
    }


    function onlyOwner() internal view {    
        require(admin == msg.sender || auth[msg.sender] == true || dev1Address == msg.sender || dev2Address == msg.sender);
    }

//Bridge and Tunnel Stuff

    function modifyElfDNA(uint256 id, uint256 sentinel) external {
        require (msg.sender == terminus || admin == msg.sender, "not terminus");
        sentinels[id] = sentinel;
    }

   /*   function pull(address owner_, uint256[] calldata ids) external {
        require (msg.sender == terminus, "not terminus"); 
        for (uint256 index = 0; index < ids.length; index++) {
              _transfer(owner_, msg.sender, ids[index]);
        }
        ITerminus(msg.sender).pullCallback(owner_, ids);
    }
  */

//ADMIN Only
    function withdrawAll() public {
        onlyOwner();
        uint256 balance = address(this).balance;
        
        uint256 devShare = balance/2;      

        require(balance > 0);
        _withdraw(dev1Address, devShare);
        _withdraw(dev2Address, devShare);
    }

    //Internal withdraw
    function _withdraw(address _address, uint256 _amount) private {

        (bool success, ) = _address.call{value: _amount}("");
        require(success);
    }

    function flipActiveStatus() external {
        onlyOwner();
        isGameActive = !isGameActive;
    }

    function flipMint() external {
        onlyOwner();
        isMintOpen = !isMintOpen;
    }

    /*function flipWhitelist() external {
        onlyOwner();
        isWlOpen = !isWlOpen;
    }*/

     function flipTerminal() external {
        onlyOwner();
        isTerminalOpen = !isTerminalOpen;
    }

    
    
   function setAccountBalance(address _owner, uint256 _amount) public {                
        onlyOwner();
        bankBalances[_owner] += _amount;
    }
 
    function reserve(uint256 _reserveAmount, address _to) public {    
        onlyOwner();        
        for (uint i = 0; i < _reserveAmount; i++) {
            _mintElf(_to);
        }

    }


    function setElfManually(uint id, uint8 _primaryWeapon, uint8 _weaponTier, uint8 _attackPoints, uint8 _healthPoints, uint8 _level, uint8 _inventory, uint8 _race, uint8 _class, uint8 _accessories) external {
        onlyOwner();
        DataStructures.Elf memory elf = DataStructures.getElf(sentinels[id]);
        DataStructures.ActionVariables memory actions;

        elf.owner           = elf.owner;
        elf.timestamp       = elf.timestamp;
        elf.action          = elf.action;
        elf.healthPoints    = _healthPoints;
        elf.attackPoints    = _attackPoints;
        elf.primaryWeapon   = _primaryWeapon;
        elf.level           = _level;
        elf.weaponTier      = _weaponTier;
        elf.inventory       = _inventory;
        elf.race            = _race;
        elf.sentinelClass   = _class;
        elf.accessories     = _accessories;

        actions.traits = DataStructures.packAttributes(elf.hair, elf.race, elf.accessories);
        actions.class =  DataStructures.packAttributes(elf.sentinelClass, elf.weaponTier, elf.inventory);
                       
        sentinels[id] = DataStructures._setElf(elf.owner, elf.timestamp, elf.action, elf.healthPoints, elf.attackPoints, elf.primaryWeapon, elf.level, actions.traits, actions.class);
        
    }
    
   /* function addManyToWhitelist(address[] calldata _addr, uint256 _whitelistRole) public {
        onlyOwner();
        
            for (uint256 index = 0; index < _addr.length; index++) {
                whitelist[_addr[index]] = uint16(_whitelistRole);
            }
    }    
    */

    /*
function whitelistMint(uint256 qty, address to, uint256 roleIndex, bytes memory signature) public payable  {
    
    isPlayer();
    require(_isSignedByValidator(encodeForSignature(to, roleIndex),signature), "incorrect signature");  /////Francesco Sullo Thanks for showing me how to do this. Follow @sullof
    require(isWlOpen, "Whitelist is closed");
    require(whitelist[to] != 1,"Wallet used already"); //not on whitelist
    require(_remaining[roleIndex] > 0, "noneLeft");
    require(qty > 0 && qty <= 2, "max 2"); //max 2
    
    //Role:0 SOG 2 free Role:1 OG 1 free 1 paid Role:2 2 WL paid

    //  bytes32 messageHash = encodeForSignature(to, roleIndex);
    //  bool isValid = _isSignedByValidator(messageHash, signature);
    
    //     if(isValid){
    //        console.log("valid");
    //   }
    

    uint256 amount = msg.value;
    
    _remaining[roleIndex] = _remaining[roleIndex] - qty;

    whitelist[to] = 1; //indicate that address is used

        if(roleIndex == 0){
            
           for (uint i = 0; i < qty; i++) {
                _mintElf(to);
            }

        }else if(roleIndex == 1){
           
            require(amount >= price * qty/2, "NotEnoughEther");
            for (uint i = 0; i < qty; i++) {
                _mintElf(to);
            }

        }else if(roleIndex == 2){
             require(amount >= price * qty, "NotEnoughEther");
             for (uint i = 0; i < qty; i++) {
                _mintElf(to);
             }

        }

    }
*/

    
  /*  function setTerminus(address _terminus)  public {
       onlyOwner();
       terminus             = _terminus;
    }
  
    
    function setInitialSupply(uint256 _initialSupply)  public {
       onlyOwner();
       INIT_SUPPLY             = _initialSupply;
    }

*/


}

File 2 of 6 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s;
        uint8 v;
        assembly {
            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
            v := add(shr(255, vs), 27)
        }
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 3 of 6 : ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.7;

/// @notice Modern and gas efficient ERC-721 + ERC-20/EIP-2612-like implementation,
/// including the MetaData, and partially, Enumerable extensions.
contract ERC721 {
    /*///////////////////////////////////////////////////////////////
                                  EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 indexed tokenId
    );
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    /*///////////////////////////////////////////////////////////////
                             METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    address implementation_;
    address public admin;

    /*///////////////////////////////////////////////////////////////
                             ERC-721 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;
    uint256 public maxSupply;

    mapping(address => uint256) public balanceOf;
    mapping(uint256 => address) public ownerOf;
    mapping(uint256 => address) public getApproved;
    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*///////////////////////////////////////////////////////////////
                             VIEW FUNCTION
    //////////////////////////////////////////////////////////////*/

    function owner() external view returns (address) {
        return admin;
    }

    /*///////////////////////////////////////////////////////////////
                              ERC-20-LIKE LOGIC
    //////////////////////////////////////////////////////////////*/

    function transfer(address to, uint256 tokenId) external {
        require(msg.sender == ownerOf[tokenId], "NOT_OWNER");

        _transfer(msg.sender, to, tokenId);
    }

    /*///////////////////////////////////////////////////////////////
                              ERC-721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId)
        external
        pure
        returns (bool supported)
    {
        supported = interfaceId == 0x80ac58cd || interfaceId == 0x5b5e139f;
    }

    function approve(address spender, uint256 tokenId) external {
        address owner_ = ownerOf[tokenId];

        require(
            msg.sender == owner_ || isApprovedForAll[owner_][msg.sender],
            "NOT_APPROVED"
        );

        getApproved[tokenId] = spender;

        emit Approval(owner_, spender, tokenId);
    }

    function setApprovalForAll(address operator, bool approved) external {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(address from, address to, uint256 tokenId) public {
        address owner_ = ownerOf[tokenId];

        require(
            msg.sender == owner_ ||
                msg.sender == getApproved[tokenId] ||
                isApprovedForAll[owner_][msg.sender],
            "NOT_APPROVED"
        );

        _transfer(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId) external {
        safeTransferFrom(from, to, tokenId, "");
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public {
        transferFrom(from, to, tokenId);

        if (to.code.length != 0) {
            // selector = `onERC721Received(address,address,uint,bytes)`
            (, bytes memory returned) = to.staticcall(
                abi.encodeWithSelector(
                    0x150b7a02,
                    msg.sender,
                    from, 
                    tokenId,
                    data
                )
            );

            bytes4 selector = abi.decode(returned, (bytes4));

            require(selector == 0x150b7a02, "NOT_ERC721_RECEIVER");
        }
    }

    /*///////////////////////////////////////////////////////////////
                          INTERNAL UTILS
    //////////////////////////////////////////////////////////////*/

    function _transfer(address from, address to, uint256 tokenId) internal {
        
        require(ownerOf[tokenId] == from);

        balanceOf[from]--;
        balanceOf[to]++;

        delete getApproved[tokenId];

        ownerOf[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    function _mint(address to, uint256 tokenId) internal {
        require(ownerOf[tokenId] == address(0), "ALREADY_MINTED");
        require(totalSupply++ <= maxSupply, "MAX SUPPLY REACHED");

        // This is safe because the sum of all user
        // balances can't exceed type(uint256).max!
        unchecked {
            balanceOf[to]++;
        }

        ownerOf[tokenId] = to;

        emit Transfer(address(0), to, tokenId);
    }

    function _burn(uint256 tokenId) internal {
        address owner_ = ownerOf[tokenId];

        require(ownerOf[tokenId] != address(0), "NOT_MINTED");

        totalSupply--;
        balanceOf[owner_]--;

        delete ownerOf[tokenId];

        emit Transfer(owner_, address(0), tokenId);
    }
}

File 4 of 6 : DataStructures.sol
// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.7;
//import "hardhat/console.sol"; ///REMOVE BEFORE DEPLOYMENT
//v 1.0.3

library DataStructures {

/////////////DATA STRUCTURES///////////////////////////////
    struct Elf {
            address owner;  
            uint256 timestamp; 
            uint256 action; 
            uint256 healthPoints;
            uint256 attackPoints; 
            uint256 primaryWeapon; 
            uint256 level;
            uint256 hair;
            uint256 race; 
            uint256 accessories; 
            uint256 sentinelClass; 
            uint256 weaponTier; 
            uint256 inventory; 
    }

    struct Token {
            address owner;  
            uint256 timestamp; 
            uint8 action; 
            uint8 healthPoints;
            uint8 attackPoints; 
            uint8 primaryWeapon; 
            uint8 level;
            uint8 hair;
            uint8 race; 
            uint8 accessories; 
            uint8 sentinelClass; 
            uint8 weaponTier; 
            uint8 inventory; 
    }

    struct ActionVariables {

            uint256 reward;
            uint256 timeDiff;
            uint256 traits; 
            uint256 class;  
    }

    struct Camps {
            uint32 baseRewards; 
            uint32 creatureCount; 
            uint32 creatureHealth; 
            uint32 expPoints; 
            uint32 minLevel;
            uint32 itemDrop;
            uint32 weaponDrop;
            uint32 spare;
    }

    /*Dont Delete, just keep it for reference

    struct Attributes { 
            uint256 hair; //MAX 3 3 hair traits
            uint256 race;  //MAX 6 Body 4 for body
            uint256 accessories; //MAX 7 4 
            uint256 sentinelClass; //MAX 3 3 in class
            uint256 weaponTier; //MAX 6 5 tiers
            uint256 inventory; //MAX 7 6 items
    }

    */

/////////////////////////////////////////////////////
function getElf(uint256 character) internal pure returns(Elf memory _elf) {
   
    _elf.owner =          address(uint160(uint256(character)));
    _elf.timestamp =      uint256(uint40(character>>160));
    _elf.action =         uint256(uint8(character>>200));
    _elf.healthPoints =       uint256(uint8(character>>208));
    _elf.attackPoints =   uint256(uint8(character>>216));
    _elf.primaryWeapon =  uint256(uint8(character>>224));
    _elf.level    =       uint256(uint8(character>>232));
    _elf.hair           = (uint256(uint8(character>>240)) / 100) % 10;
    _elf.race           = (uint256(uint8(character>>240)) / 10) % 10;
    _elf.accessories    = (uint256(uint8(character>>240))) % 10;
    _elf.sentinelClass  = (uint256(uint8(character>>248)) / 100) % 10;
    _elf.weaponTier     = (uint256(uint8(character>>248)) / 10) % 10;
    _elf.inventory      = (uint256(uint8(character>>248))) % 10; 

} 

function getToken(uint256 character) internal pure returns(Token memory token) {
   
    token.owner          = address(uint160(uint256(character)));
    token.timestamp      = uint256(uint40(character>>160));
    token.action         = (uint8(character>>200));
    token.healthPoints   = (uint8(character>>208));
    token.attackPoints   = (uint8(character>>216));
    token.primaryWeapon  = (uint8(character>>224));
    token.level          = (uint8(character>>232));
    token.hair           = ((uint8(character>>240)) / 100) % 10; //MAX 3
    token.race           = ((uint8(character>>240)) / 10) % 10; //Max6
    token.accessories    = ((uint8(character>>240))) % 10; //Max7
    token.sentinelClass  = ((uint8(character>>248)) / 100) % 10; //MAX 3
    token.weaponTier     = ((uint8(character>>248)) / 10) % 10; //MAX 6
    token.inventory      = ((uint8(character>>248))) % 10; //MAX 7

    token.hair = (token.sentinelClass * 3) + (token.hair + 1);
    token.race = (token.sentinelClass * 4) + (token.race + 1);
    token.primaryWeapon = token.primaryWeapon == 69 ? 69 : (token.sentinelClass * 15) + (token.primaryWeapon + 1);
    token.accessories = (token.sentinelClass * 7) + (token.accessories + 1);

}

function _setElf(
                address owner, uint256 timestamp, uint256 action, uint256 healthPoints, 
                uint256 attackPoints, uint256 primaryWeapon, 
                uint256 level, uint256 traits, uint256 class )

    internal pure returns (uint256 sentinel) {

    uint256 character = uint256(uint160(address(owner)));
    
    character |= timestamp<<160;
    character |= action<<200;
    character |= healthPoints<<208;
    character |= attackPoints<<216;
    character |= primaryWeapon<<224;
    character |= level<<232;
    character |= traits<<240;
    character |= class<<248;
    
    return character;
}

//////////////////////////////HELPERS/////////////////

function packAttributes(uint hundreds, uint tens, uint ones) internal pure returns (uint256 packedAttributes) {
    packedAttributes = uint256(hundreds*100 + tens*10 + ones);
    return packedAttributes;
}

function calcAttackPoints(uint256 sentinelClass, uint256 weaponTier) internal pure returns (uint256 attackPoints) {

        attackPoints = ((sentinelClass + 1) * 2) + (weaponTier * 2);
        
        return attackPoints;
}

function calcHealthPoints(uint256 sentinelClass, uint256 level) internal pure returns (uint256 healthPoints) {

        healthPoints = (level/(3) +2) + (20 - (sentinelClass * 4));
        
        return healthPoints;
}

function calcCreatureHealth(uint256 sector, uint256 baseCreatureHealth) internal pure returns (uint256 creatureHealth) {

        creatureHealth = ((sector - 1) * 12) + baseCreatureHealth; 
        
        return creatureHealth;
}

function roll(uint256 id_, uint256 level_, uint256 rand, uint256 rollOption_, uint256 weaponTier_, uint256 primaryWeapon_, uint256 inventory_) 
internal pure 
returns (uint256 newWeaponTier, uint256 newWeapon, uint256 newInventory) {

   uint256 levelTier = level_ == 100 ? 5 : uint256((level_/20) + 1);

   newWeaponTier = weaponTier_;
   newWeapon     = primaryWeapon_;
   newInventory  = inventory_;


   if(rollOption_ == 1 || rollOption_ == 3){
       //Weapons
      
        uint16  chance = uint16(_randomize(rand, "Weapon", id_)) % 100;
       // console.log("chance: ", chance);
                if(chance > 10 && chance < 80){
        
                              newWeaponTier = levelTier;
        
                        }else if (chance > 80 ){
        
                              newWeaponTier = levelTier + 1 > 5 ? 5 : levelTier + 1;
        
                        }else{

                                newWeaponTier = levelTier - 1 < 1 ? 1 : levelTier - 1;          
                        }

                                         
        

        newWeapon = newWeaponTier == 0 ? 0 : ((newWeaponTier - 1) * 3) + (rand % 3);  
        

   }
   
   if(rollOption_ == 2 || rollOption_ == 3){//Items Loop
      
       
        uint16 morerand = uint16(_randomize(rand, "Inventory", id_));
        uint16 diceRoll = uint16(_randomize(rand, "Dice", id_));
        
        diceRoll = (diceRoll % 100);
        
        if(diceRoll <= 20){

            newInventory = levelTier > 3 ? morerand % 3 + 3: morerand % 6 + 1;
            //console.log("Token#: ", id_);
            //console.log("newITEM: ", newInventory);
        } 

   }
                      
              
}


function _randomize(uint256 ran, string memory dom, uint256 ness) internal pure returns (uint256) {
    return uint256(keccak256(abi.encode(ran,dom,ness)));}



}

File 5 of 6 : Interfaces.sol
// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.7;

interface IERC20Lite {
    
    function transfer(address to, uint256 value) external returns (bool);
    function burn(address from, uint256 value) external;
    function mint(address to, uint256 value) external; 

}

interface IElfMetaDataHandler {    
function getTokenURI(uint16 id_, uint256 sentinel) external view returns (string memory);
}

interface ICampaigns {
function gameEngine(uint256 _campId, uint256 _sector, uint256 _level, uint256 _attackPoints, uint256 _healthPoints, uint256 _inventory, bool _useItem) external 
returns(uint256 level, uint256 rewards, uint256 timestamp, uint256 inventory);
}

interface ITunnel {
    function sendMessage(bytes calldata message_) external;
}

interface ITerminus {
    function pullCallback(address owner, uint256[] calldata ids) external;
    
}

interface IElves {
    function getSentinel(uint256 _id) external view returns(uint256 sentinel);
    function modifyElfDNA(uint256 id, uint256 sentinel) external;
    function pull(address owner_, uint256[] calldata ids) external;
    function transfer(address to, uint256 id) external;
}

interface IERC721Lite {
    function transferFrom(address from, address to, uint256 id) external;   
    function transfer(address to, uint256 id) external;
    function ownerOf(uint256 id) external returns (address owner);
    function mint(address to, uint256 tokenid) external;
}

interface IEthernalElves {
function presale(uint256 _reserveAmount, address _whitelister) external payable returns (uint256 id);
}

File 6 of 6 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

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

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"action","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Action","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"bool","name":"subtract","type":"bool"}],"name":"BalanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"campaign","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sector","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Campaigns","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"sentinel","type":"uint256"}],"name":"CheckIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"CheckOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"renAmount","type":"uint256"}],"name":"RenTransferOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"INIT_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_remaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"attributes","outputs":[{"internalType":"uint256","name":"hair","type":"uint256"},{"internalType":"uint256","name":"race","type":"uint256"},{"internalType":"uint256","name":"accessories","type":"uint256"},{"internalType":"uint256","name":"sentinelClass","type":"uint256"},{"internalType":"uint256","name":"weaponTier","type":"uint256"},{"internalType":"uint256","name":"inventory","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"auth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bankBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256","name":"renAmount","type":"uint256"}],"name":"checkIn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"sentinel","type":"uint256[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"checkOut","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"renAmount","type":"uint256"},{"internalType":"bytes","name":"renSignatures","type":"bytes"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"checkOutRen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"elves","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"action","type":"uint256"},{"internalType":"uint256","name":"healthPoints","type":"uint256"},{"internalType":"uint256","name":"attackPoints","type":"uint256"},{"internalType":"uint256","name":"primaryWeapon","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"renAmount","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"encodeRenForSignature","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"sentinel","type":"uint256"}],"name":"encodeSentinelForSignature","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"flipActiveStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipTerminal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"forging","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintPriceLevel","outputs":[{"internalType":"uint256","name":"mintCost","type":"uint256"},{"internalType":"uint256","name":"mintLevel","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getSentinel","outputs":[{"internalType":"uint256","name":"sentinel","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getToken","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"uint8","name":"healthPoints","type":"uint8"},{"internalType":"uint8","name":"attackPoints","type":"uint8"},{"internalType":"uint8","name":"primaryWeapon","type":"uint8"},{"internalType":"uint8","name":"level","type":"uint8"},{"internalType":"uint8","name":"hair","type":"uint8"},{"internalType":"uint8","name":"race","type":"uint8"},{"internalType":"uint8","name":"accessories","type":"uint8"},{"internalType":"uint8","name":"sentinelClass","type":"uint8"},{"internalType":"uint8","name":"weaponTier","type":"uint8"},{"internalType":"uint8","name":"inventory","type":"uint8"}],"internalType":"struct DataStructures.Token","name":"token","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"healer","type":"uint256"},{"internalType":"uint256","name":"target","type":"uint256"}],"name":"heal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_dev1Address","type":"address"},{"internalType":"address","name":"_dev2Address","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isGameActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMintOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTerminalOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWlOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"merchant","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mint","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"sentinel","type":"uint256"}],"name":"modifyElfDNA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"passive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ren","outputs":[{"internalType":"contract IERC20Lite","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reserveAmount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"reserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"returnPassive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256","name":"campaign_","type":"uint256"},{"internalType":"uint256","name":"sector_","type":"uint256"},{"internalType":"bool","name":"rollWeapons_","type":"bool"},{"internalType":"bool","name":"rollItems_","type":"bool"},{"internalType":"bool","name":"useitem_","type":"bool"}],"name":"sendCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"sentinels","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setAccountBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ren","type":"address"},{"internalType":"address","name":"_inventory","type":"address"},{"internalType":"address","name":"_campaigns","type":"address"},{"internalType":"address","name":"_validator","type":"address"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"adds_","type":"address[]"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setAuth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint8","name":"_primaryWeapon","type":"uint8"},{"internalType":"uint8","name":"_weaponTier","type":"uint8"},{"internalType":"uint8","name":"_attackPoints","type":"uint8"},{"internalType":"uint8","name":"_healthPoints","type":"uint8"},{"internalType":"uint8","name":"_level","type":"uint8"},{"internalType":"uint8","name":"_inventory","type":"uint8"},{"internalType":"uint8","name":"_race","type":"uint8"},{"internalType":"uint8","name":"_class","type":"uint8"},{"internalType":"uint8","name":"_accessories","type":"uint8"}],"name":"setElfManually","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"supported","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"unStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"usedRenSignatures","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawSomeTokenBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawTokenBalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b506149f1806100206000396000f3fe6080604052600436106103b85760003560e01c8063956cc859116101f2578063cdc2544d1161010d578063e985e9c5116100a0578063f851a4401161006f578063f851a44014610bf7578063f8d0fded14610c17578063f93c50ac14610c2c578063fb5dc25d14610cce57600080fd5b8063e985e9c514610b67578063ec03a77614610ba2578063f014a89714610bc2578063f2e708db14610bd757600080fd5b8063d5f18429116100dc578063d5f1842914610ade578063d8c8346714610751578063dc8c0c9914610b1a578063e4b50cb814610b3a57600080fd5b8063cdc2544d14610a46578063d05dcc6a14610a66578063d2ed5c5914610ab3578063d5abeb0114610ac857600080fd5b8063b10dcc9311610185578063c092b13e11610154578063c092b13e146109c1578063c861aba4146109d6578063c87b56dd146109f6578063cd5d211814610a1657600080fd5b8063b10dcc9314610947578063b4eada8814610967578063b88d4fde14610981578063bddb95c1146109a157600080fd5b8063a22cb465116101c1578063a22cb465146108ba578063a59d1686146108da578063a8792a7414610907578063a9059cbb1461092757600080fd5b8063956cc8591461081e57806395d89b41146108345780639b19251a14610860578063a035b1fe146108a457600080fd5b80633a5381b5116102e25780636352211e11610275578063853828b611610244578063853828b61461079e5780638a9b4067146107b35780638b1681a6146107d35780638da5cb5b1461080057600080fd5b80636352211e146106ee57806370a08231146107245780637655c823146107515780638299b1661461077157600080fd5b806346ddb7db116102b157806346ddb7db1461066e578063485cc9551461068e5780634a945f8d146106ae5780635ea1f2fa146106ce57600080fd5b80633a5381b5146105e457806342842e0e146106045780634576da471461062457806345c9fce21461064457600080fd5b80631249c58b1161035a5780631990801611610329578063199080161461056257806323b872dd1461058357806330923299146105a357806338b3ccc8146105c357600080fd5b80631249c58b146104f65780631637bbdf1461050c57806318160ddd1461052c578063181f4c3b1461054257600080fd5b8063081812fc11610396578063081812fc14610454578063095ea7b3146104a257806309f94443146104c25780630c0ef2b0146104d557600080fd5b806301ffc9a7146103bd57806303339bcb146103f257806306fdde0314610414575b600080fd5b3480156103c957600080fd5b506103dd6103d83660046142ac565b610ce1565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b5061041261040d3660046143ab565b610d18565b005b34801561042057600080fd5b5060408051808201909152600e81526d45746865726e616c20456c76657360901b60208201525b6040516103e991906145d3565b34801561046057600080fd5b5061048a61046f366004614392565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103e9565b3480156104ae57600080fd5b506104126104bd366004613ffe565b610d4c565b6104126104d036600461407c565b610e31565b3480156104e157600080fd5b50600a546103dd90600160a01b900460ff1681565b6104fe610e83565b6040519081526020016103e9565b34801561051857600080fd5b506104fe610527366004614392565b610fd9565b34801561053857600080fd5b506104fe60025481565b34801561054e57600080fd5b5061041261055d366004614443565b610ffa565b34801561056e57600080fd5b50600a546103dd90600160a81b900460ff1681565b34801561058f57600080fd5b5061041261059e366004613f30565b61106a565b3480156105af57600080fd5b506104126105be36600461449b565b611120565b3480156105cf57600080fd5b50600a546103dd90600160b01b900460ff1681565b3480156105f057600080fd5b50600e5461048a906001600160a01b031681565b34801561061057600080fd5b5061041261061f366004613f30565b61125d565b34801561063057600080fd5b5061041261063f366004614028565b611278565b34801561065057600080fd5b506106596112f1565b604080519283526020830191909152016103e9565b34801561067a57600080fd5b50610412610689366004613ffe565b6113e0565b34801561069a57600080fd5b506104126106a9366004613ea9565b611419565b3480156106ba57600080fd5b506104126106c9366004613edc565b61152a565b3480156106da57600080fd5b506104126106e9366004614224565b611582565b3480156106fa57600080fd5b5061048a610709366004614392565b6005602052600090815260409020546001600160a01b031681565b34801561073057600080fd5b506104fe61073f366004613e8e565b60046020526000908152604090205481565b34801561075d57600080fd5b506104fe61076c3660046143ce565b6115dc565b34801561077d57600080fd5b506104fe61078c366004614392565b60136020526000908152604090205481565b3480156107aa57600080fd5b50610412611667565b3480156107bf57600080fd5b50600a5461048a906001600160a01b031681565b3480156107df57600080fd5b506104fe6107ee366004613e8e565b60146020526000908152604090205481565b34801561080c57600080fd5b506001546001600160a01b031661048a565b34801561082a57600080fd5b506104fe600f5481565b34801561084057600080fd5b5060408051808201909152600381526222a62b60e91b6020820152610447565b34801561086c57600080fd5b5061089161087b366004613e8e565b60166020526000908152604090205461ffff1681565b60405161ffff90911681526020016103e9565b3480156108b057600080fd5b506104fe60105481565b3480156108c657600080fd5b506104126108d5366004613fd4565b6116bc565b3480156108e657600080fd5b506104fe6108f5366004614392565b60009081526013602052604090205490565b34801561091357600080fd5b506103dd6109223660046140be565b611728565b34801561093357600080fd5b50610412610942366004613ffe565b6118f3565b34801561095357600080fd5b5061041261096236600461407c565b611950565b34801561097357600080fd5b506017546103dd9060ff1681565b34801561098d57600080fd5b5061041261099c366004613f6c565b61198a565b3480156109ad57600080fd5b506104126109bc366004614443565b611ac0565b3480156109cd57600080fd5b50610412611add565b3480156109e257600080fd5b506103dd6109f13660046141d8565b611b06565b348015610a0257600080fd5b50610447610a11366004614392565b611cdf565b348015610a2257600080fd5b506103dd610a31366004613e8e565b60156020526000908152604090205460ff1681565b348015610a5257600080fd5b506103dd610a613660046143f3565b611d7b565b348015610a7257600080fd5b50610a86610a81366004614392565b611f0b565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0016103e9565b348015610abf57600080fd5b50610412611fb9565b348015610ad457600080fd5b506104fe60035481565b348015610aea57600080fd5b50610891610af93660046142e6565b805160208183018101805160188252928201919093012091525461ffff1681565b348015610b2657600080fd5b50610412610b35366004614392565b611fe2565b348015610b4657600080fd5b50610b5a610b55366004614392565b61212b565b6040516103e99190614634565b348015610b7357600080fd5b506103dd610b82366004613ea9565b600760209081526000928352604080842090915290825290205460ff1681565b348015610bae57600080fd5b50610412610bbd36600461407c565b61214b565b348015610bce57600080fd5b5061041261219d565b348015610be357600080fd5b50610412610bf236600461407c565b6121b9565b348015610c0357600080fd5b5060015461048a906001600160a01b031681565b348015610c2357600080fd5b5061041261220b565b348015610c3857600080fd5b50610c8f610c47366004614392565b6000908152601360205260409020549064ffffffffff60a083901c169060ff60c884901c81169160d085901c82169160d886901c81169160e087901c82169160e888901c1690565b604080516001600160a01b0390981688526020880196909652948601939093526060850191909152608084015260a083015260c082015260e0016103e9565b610412610cdc36600461407c565b6122da565b60006380ac58cd60e01b6001600160e01b031983161480610d125750635b5e139f60e01b6001600160e01b03198316145b92915050565b610d2061232c565b60005b82811015610d4757610d348261238e565b5080610d3f816148d8565b915050610d23565b505050565b6000818152600560205260409020546001600160a01b031633811480610d9557506001600160a01b038116600090815260076020908152604080832033845290915290205460ff165b610dd55760405162461bcd60e51b815260206004820152600c60248201526b1393d517d054141493d5915160a21b60448201526064015b60405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b610e3961263c565b60005b81811015610d4757610e71838383818110610e5957610e59614976565b90506020020135600633600080600080600080612699565b80610e7b816148d8565b915050610e3c565b6000610e8d61263c565b600a54600160a81b900460ff16610eda5760405162461bcd60e51b8152602060048201526011602482015270135a5b9d1a5b99c81a5cc818db1bdcd959607a1b6044820152606401610dcc565b6000610ee46112f1565b5080915050600f5460025411610f3a5780341015610f355760405162461bcd60e51b815260206004820152600e60248201526d2737ba22b737bab3b422ba3432b960911b6044820152606401610dcc565b610fc6565b33600090815260146020526040902054811115610fba57600a54604051632770a7eb60e21b8152336004820152602481018390526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b158015610f9d57600080fd5b505af1158015610fb1573d6000803e3d6000fd5b50505050610fc6565b610fc633826001613081565b610fcf3361238e565b61ffff1691505090565b60128181548110610fe957600080fd5b600091825260209091200154905081565b600d546001600160a01b031633148061101d57506001546001600160a01b031633145b6110585760405162461bcd60e51b815260206004820152600c60248201526b6e6f74207465726d696e757360a01b6044820152606401610dcc565b60009182526013602052604090912055565b6000818152600560205260409020546001600160a01b0316338114806110a657506000828152600660205260409020546001600160a01b031633145b806110d457506001600160a01b038116600090815260076020908152604080832033845290915290205460ff165b61110f5760405162461bcd60e51b815260206004820152600c60248201526b1393d517d054141493d5915160a21b6044820152606401610dcc565b61111a848484613128565b50505050565b61112861232c565b60008a81526013602052604081205461114090613211565b905061116d6040518060800160405280600081526020016000815260200160008152602001600081525090565b81516001600160a01b0316825260ff808916606084015289811660808401528b811660a084015287811660c08401528a81166101608401528681166101808401528581166101008401819052858216610140850152908416610120840181905260e08401516111dd929091613331565b60408201526101408201516101608301516101808401516111ff929190613331565b81606001818152505061123d826000015183602001518460400151856060015186608001518760a001518860c0015188604001518960600151613366565b60009c8d5260136020526040909c209b909b555050505050505050505050565b610d478383836040518060200160405280600081525061198a565b61128061232c565b60005b8281101561111a5781601560008686858181106112a2576112a2614976565b90506020020160208101906112b79190613e8e565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055806112e9816148d8565b915050611283565b600080600f546002541161130a57505060105490600190565b610fa060025410156113285750680340aad21b3b7000009160039150565b611194600254101561134657506809c2007651b25000009160059150565b6113886002541015611364575068138400eca364a0000091600f9150565b61157c60025410156113825750682086ac3510526000009160199150565b61177060025410156113a057506830ca024f987b9000009160239150565b6118bd60025410156113be5750686194049f30f720000091602d9150565b611a0a60025410156113dc575068925e06eec972b0000091603c9150565b9091565b6113e861232c565b6001600160a01b038216600090815260146020526040812080548392906114109084906147c3565b90915550505050565b600a54600160b81b900460ff16156114695760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610dcc565b600180546001600160a01b03199081163317909155600b80546001600160a01b0385811691841691909117909155600c805491841691909216179055611a0a6003908155610ce4600f55600a805460ff60b81b1916600160b81b179055670138a388a43c00006010556040805160608101825260fa815261029460208201526109c4918101919091526114ff9160129190613c6c565b5050600e80546001600160a01b0319167380861814a8775de20f9506cf41932e95f80f703517905550565b61153261232c565b600a80546001600160a01b039586166001600160a01b03199182161790915560088054948616948216949094179093556009805492851692841692909217909155600e8054919093169116179055565b61158a61263c565b60005b868110156115d2576115c08888838181106115aa576115aa614976565b9050602002013560023389898989896001612699565b806115ca816148d8565b91505061158d565b5050505050505050565b604080516020808201869052606085901b6001600160601b031916828401526054808301859052835180840390910181526074830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a333200000000609484015260b0808401919091528351808403909101815260d090920190925280519101205b9392505050565b61166f61232c565b47600061167d600283614800565b90506000821161168c57600080fd5b600b546116a2906001600160a01b0316826133b5565b600c546116b8906001600160a01b0316826133b5565b5050565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600061173261263c565b60175460ff166117545760405162461bcd60e51b8152600401610dcc90614608565b8480156118e95760005b868110156118e7576117c36117a489898481811061177e5761177e614976565b905060200201353389898681811061179857611798614976565b905060200201356115dc565b8583815181106117b6576117b6614976565b6020026020010151613415565b6118055760405162461bcd60e51b8152602060048201526013602482015272696e636f7272656374207369676e617475726560681b6044820152606401610dcc565b85858281811061181757611817614976565b90506020020135601360008a8a8581811061183457611834614976565b9050602002013581526020019081526020016000208190555061187a88888381811061186257611862614976565b90506020020135600033600080600080600080612699565b87878281811061188c5761188c614976565b90506020020135336001600160a01b03167e817f5e0c1c773a9e3b8d5e7d593eb7d6556749dcc48cfd5798d888a2190f9d426040516118cd91815260200190565b60405180910390a3806118df816148d8565b91505061175e565b505b5095945050505050565b6000818152600560205260409020546001600160a01b031633146119455760405162461bcd60e51b81526020600482015260096024820152682727aa2fa7aba722a960b91b6044820152606401610dcc565b6116b8338383613128565b61195861263c565b60005b81811015610d475761197883838381811061186257611862614976565b80611982816148d8565b91505061195b565b61199584848461106a565b6001600160a01b0383163b1561111a576000836001600160a01b031663150b7a02338786866040516024016119cd9493929190614596565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051611a06919061457a565b600060405180830381855afa9150503d8060008114611a41576040519150601f19603f3d011682016040523d82523d6000602084013e611a46565b606091505b50915050600081806020019051810190611a6091906142c9565b9050630a85bd0160e11b6001600160e01b0319821614611ab85760405162461bcd60e51b81526020600482015260136024820152722727aa2fa2a9219b9918afa922a1a2a4ab22a960691b6044820152606401610dcc565b505050505050565b611ac861263c565b6116b882600733846000806000806000612699565b611ae561232c565b600a805460ff60a01b198116600160a01b9182900460ff1615909102179055565b6000611b1061263c565b60175460ff16611b325760405162461bcd60e51b8152600401610dcc90614608565b828015611c0d5760005b84811015611c0b57611b71868683818110611b5957611b59614976565b90506020020135600833600080600080600080612699565b60136000878784818110611b8757611b87614976565b90506020020135815260200190815260200160002054868683818110611baf57611baf614976565b90506020020135336001600160a01b03167ff70c8ccfb49937cb9079ffa719be60366bdb8f901313f28dd3da4e482977a7fa42604051611bf191815260200190565b60405180910390a480611c03816148d8565b915050611b3c565b505b8215611cd75733600090815260146020526040902054831115611c9357600a54604051632770a7eb60e21b8152336004820152602481018590526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b158015611c7657600080fd5b505af1158015611c8a573d6000803e3d6000fd5b50505050611c9f565b611c9f33846001613081565b604051428152839033907f0ae95557dadbad8b7a6e8ea6e957363d7eb9cf9c56d1916d13a65e750fa57f619060200160405180910390a35b509392505050565b6008546000828152601360205260409081902054905163470ad4b560e11b815261ffff8416600482015260248101919091526060916001600160a01b031690638e15a96a9060440160006040518083038186803b158015611d3f57600080fd5b505afa158015611d53573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d12919081019061431b565b6000611d8561263c565b60175460ff16611da75760405162461bcd60e51b8152600401610dcc90614608565b601883604051611db7919061457a565b9081526040519081900360200190205461ffff1615611e115760405162461bcd60e51b815260206004820152601660248201527514da59db985d1d5c9948185b1c9958591e481d5cd95960521b6044820152606401610dcc565b831561166057611e2b611e258533856115dc565b84613415565b611e6d5760405162461bcd60e51b8152602060048201526013602482015272696e636f7272656374207369676e617475726560681b6044820152606401610dcc565b6001601884604051611e7f919061457a565b908152604051908190036020018120805461ffff9390931661ffff1990931692909217909155600a546340c10f1960e01b8252336004830152602482018690526001600160a01b0316906340c10f1990604401600060405180830381600087803b158015611eec57600080fd5b505af1158015611f00573d6000803e3d6000fd5b505050509392505050565b6000818152601360205260408120548190819081908190819060ff60f082901c1660f882901c600a611f3e606484614800565b611f489190614914565b9850600a611f568184614800565b611f609190614914565b9750611f6d600a83614914565b9650600a611f7c606483614800565b611f869190614914565b9550600a611f948183614800565b611f9e9190614914565b9450611fab600a82614914565b935050505091939550919395565b611fc161232c565b600a805460ff60a81b198116600160a81b9182900460ff1615909102179055565b3360009081526014602052604090205461202a5760405162461bcd60e51b81526020600482015260096024820152684e6f42616c616e636560b81b6044820152606401610dcc565b3360009081526014602052604081205461204590839061487e565b10156120935760405162461bcd60e51b815260206004820152601760248201527f4f7665726472616674204e6f74207065726d69747465640000000000000000006044820152606401610dcc565b336000908152601460205260409020546120ae90829061487e565b336000818152601460205260409081902092909255600a5491516340c10f1960e01b81526004810191909152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b15801561211057600080fd5b505af1158015612124573d6000803e3d6000fd5b5050505050565b612133613cbd565b600082815260136020526040902054610d12906134a1565b61215361263c565b60005b81811015610d475761218b83838381811061217357612173614976565b90506020020135600433600080600080600080612699565b80612195816148d8565b915050612156565b6121a561232c565b6017805460ff19811660ff90911615179055565b6121c161263c565b60005b81811015610d47576121f98383838181106121e1576121e1614976565b90506020020135600333600080600080600080612699565b80612203816148d8565b9150506121c4565b336000908152601460205260409020546122535760405162461bcd60e51b81526020600482015260096024820152684e6f42616c616e636560b81b6044820152606401610dcc565b600a5433600081815260146020526040908190205490516340c10f1960e01b8152600481019290925260248201526001600160a01b03909116906340c10f1990604401600060405180830381600087803b1580156122b057600080fd5b505af11580156122c4573d6000803e3d6000fd5b5050336000908152601460205260408120555050565b6122e261263c565b60005b81811015610d475761231a83838381811061230257612302614976565b90506020020135600533600080600080600080612699565b80612324816148d8565b9150506122e5565b6001546001600160a01b031633148061235957503360009081526015602052604090205460ff1615156001145b8061236e5750600b546001600160a01b031633145b806123835750600c546001600160a01b031633145b61238c57600080fd5b565b6000806123996136af565b90506123a3613d29565b6002546123b19060016147c3565b6000808352426020840152610180830181905261016083018190526040830152604560a083015292506123e26112f1565b60c083015250604080518082019091526005815264436c61737360d81b602082015260039061241790849061ffff8716613706565b61242191906148f3565b61ffff166101408201526061612438606484614914565b1161247957600361246a83604051806040016040528060048152602001635261636560e01b8152508661ffff16613706565b61247491906148f3565b61247c565b60035b61ffff1661010082018190526003146124cb5760036124bc83604051806040016040528060048152602001632430b4b960e11b8152508661ffff16613706565b6124c691906148f3565b6124ce565b60005b61ffff1660e082015261014081015115612525576002612516836040518060400160405280600b81526020016a4163636573736f7269657360a81b8152508661ffff16613706565b61252091906148f3565b61256e565b6002612559836040518060400160405280600b81526020016a4163636573736f7269657360a81b8152508661ffff16613706565b61256391906148f3565b61256e90600361479d565b61ffff16610120820181905260e0820151610100830151600092612593929190613331565b905060006125b1836101400151846101600151856101800151613331565b90506125c68361014001518460c0015161373d565b60608401526101408301516101608401516125e19190613775565b60808401819052835160208501516040860151606087015160a088015160c08901516126109691908989613366565b61ffff861660008181526013602052604090209190915561263693508692509050613798565b50919050565b33803b90328114801561264d575081155b61265657600080fd5b6040516001600160601b0319606083811b8216602084015241901b16603482015260480160408051601f1981840301815291905280516020909101206011555050565b6000898152601360205260408120546126b190613211565b90506126de6040518060800160405280600081526020016000815260200160008152602001600081525090565b600a54600160a01b900460ff166126f457600080fd5b60008b8152600560205260409020546001600160a01b0316331480612722575081516001600160a01b031633145b61275b5760405162461bcd60e51b815260206004820152600a6024820152692737ba2cb7bab922b63360b11b6044820152606401610dcc565b8160400151600814156127a15760405162461bcd60e51b815260206004820152600e60248201526d32b6331034b7102837b63cb3b7b760911b6044820152606401610dcc565b60006127ab6136af565b90508a6128535760008c8152600560205260409020546001600160a01b031630146127d557600080fd5b428360200151106127f85760405162461bcd60e51b8152600401610dcc906145e6565b82604001516003141561283f5762015180836020015142612819919061487e565b6128239190614800565b6020830181905260c084015161283991906138b3565b60c08401525b61284a308b8e613128565b60008352612f5f565b8a60021415612adb574283602001511061287f5760405162461bcd60e51b8152600401610dcc906145e6565b8260400151600314156128d45760405162461bcd60e51b815260206004820152601760248201527f657869742070617373697665206d6f64652066697273740000000000000000006044820152606401610dcc565b60008c8152600560205260409020546001600160a01b0316301461290a576128fd8a308e613128565b6001600160a01b038a1683525b60095460c084015160808501516060860151610180870151604051636b9921c960e11b8152600481018f9052602481018e905260448101949094526064840192909252608483015260a482015286151560c48201526001600160a01b039091169063d73243929060e401608060405180830381600087803b15801561298e57600080fd5b505af11580156129a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c69190614465565b6101808701526020860152835260c084015260008780156129e45750865b156129f157506003612a11565b87156129ff57506001612a11565b8615612a0d57506002612a11565b5060005b8015612a5157612a3f8d8560c00151612a286136af565b848861016001518960a001518a6101800151613937565b61018087015260a08601526101608501525b8460011480612a605750846002145b15612a7557612a753384600001516000613081565b8460031415612a945760c0840151612a8e9060016147c3565b60c08501525b825160408051918252602082018b90528e918c9133917fdba077684e888626139ef24141ba8d03b94328892d5e2d8a85d586ab74071c06910160405180910390a450612f5f565b8a60031415612b485742836020015110612b075760405162461bcd60e51b8152600401610dcc906145e6565b60008c8152600560205260409020546001600160a01b03163014612b3d57612b308a308e613128565b6001600160a01b038a1683525b426020840152612f5f565b8a60041415612ba0578260400151600314612b6257600080fd5b62015180836020015142612b76919061487e565b612b809190614800565b6020830181905260c0840151612b9691906138b3565b60c0840152612f5f565b8a60051415612bee57662386f26fc10000341015612bbd57600080fd5b826040015160031415612bcf57600080fd5b612bde8360c001518d83613b56565b61016085015260a0840152612f5f565b8a60061415612c5557662386f26fc10000341015612c0b57600080fd5b826040015160031415612c1d57600080fd5b612c3f8c8460c001518360028761016001518860a00151896101800151613937565b61018086015260a0850152610160840152612f5f565b8a60071415612f205761014083015115612ca05760405162461bcd60e51b815260206004820152600c60248201526b3737ba1030903432b0b632b960a11b6044820152606401610dcc565b826040015160031415612cf55760405162461bcd60e51b815260206004820152601760248201527f63616e74206865616c207768696c6520706173736976650000000000000000006044820152606401610dcc565b42836020015110612d185760405162461bcd60e51b8152600401610dcc906145e6565b60008c8152600560205260409020546001600160a01b03163014612d4e57612d418a308e613128565b6001600160a01b038a1683525b612d5a4261a8c06147c3565b602084015260c0830151612d6f9060016147c3565b60c0840152600089815260136020526040812054612d8c90613211565b60008b8152600560205260409020549091506001600160a01b0316331480612dbd575080516001600160a01b031633145b612df65760405162461bcd60e51b815260206004820152600a6024820152692737ba2cb7bab922b63360b11b6044820152606401610dcc565b8060200151421015612e9257428160200151612e12919061487e565b60208401819052612e27578260200151612e77565b61014081015115612e7457806101400151600114612e6157600283602001516001612e529190614836565b612e5c9190614800565b612e77565b600483602001516001612e529190614836565b60005b6020808501829052820151612e8c919061487e565b60208201525b612eab8160e00151826101000151836101200151613331565b6040840152610140810151610160820151610180830151612ecd929190613331565b836060018181525050612f0b816000015182602001518360400151846060015185608001518660a001518760c001518a604001518b60600151613366565b60008b81526013602052604090205550612f5f565b8a60081415612f5f5760008c8152600560205260409020546001600160a01b03163014612f5f57612f528a308e613128565b6001600160a01b038a1683525b612f788360e00151846101000151856101200151613331565b6040830152610140830151610160840151610180850151612f9a929190613331565b606083015261014083015160c0840151612fb4919061373d565b6060840152610140830151610160840151612fcf9190613775565b608084015260c0830151606410612fea578260c00151612fed565b60645b8360c00181815250508a836040018181525050613035836000015184602001518560400151866060015187608001518860a001518960c0015189604001518a60600151613366565b60008d8152601360205260408082209290925590518d918d9133917fc87dac464bd9964598d47d6e7f7cbe0b76cad55b33430228240e72c18da0edf691a4505050505050505050505050565b806130b9576001600160a01b038316600090815260146020526040812080548492906130ae9084906147c3565b9250508190556130e8565b6001600160a01b038316600090815260146020526040812080548492906130e190849061487e565b9250508190555b5080151582846001600160a01b03167f18796921817e8fa1f03eaae699eabc26977ec4f4b6ec25ede8f7d69b9be8221b60405160405180910390a4505050565b6000818152600560205260409020546001600160a01b0384811691161461314e57600080fd5b6001600160a01b0383166000908152600460205260408120805491613172836148c1565b90915550506001600160a01b038216600090815260046020526040812080549161319b836148d8565b9091555050600081815260066020908152604080832080546001600160a01b0319908116909155600590925280832080546001600160a01b038781169190941681179091559051849391928716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b613219613d29565b6001600160a01b038216815260a082811c64ffffffffff16602083015260c883901c60ff908116604084015260d084901c8116606084015260d884901c8116608084015260e084901c81169183019190915260e883901c811660c0830152600a9061328c9060649060f086901c16614800565b6132969190614914565b60e0820152600a6132ae8160ff60f086901c16614800565b6132b89190614914565b6101008201526132d0600a60ff60f085901c16614914565b610120820152600a6132e7606460f885901c614800565b6132f19190614914565b610140820152600a6133078160f885901c614800565b6133119190614914565b610160820152613326600a60f884901c614914565b610180820152919050565b60008161333f84600a614836565b61334a866064614836565b61335491906147c3565b61335e91906147c3565b949350505050565b60f81b60f09190911b60e89290921b60e09390931b60d89490941b60d09590951b60c89690961b60a09790971b6001600160a01b03909816979097179590951793909317919091171717171790565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613402576040519150601f19603f3d011682016040523d82523d6000602084013e613407565b606091505b5050905080610d4757600080fd5b6020818101516040808401516060808601518351600080825296810180865289905290861a93810184905290810184905260808101829052909190849060019060a0016020604051602081039080840390855afa15801561347a573d6000803e3d6000fd5b5050604051601f190151600e546001600160a01b0390811691161498975050505050505050565b6134a9613cbd565b6001600160a01b038216815260a082811c64ffffffffff16602083015260c883901c60ff908116604084015260d084901c8116606084015260d884901c8116608084015260e084901c81169183019190915260e883901c1660c0820152600a613517606460f085901c614814565b6135219190614928565b60ff1660e0820152600a6135398160f085901c614814565b6135439190614928565b60ff1661010082015261355b600a60f084901c614928565b60ff16610120820152600a613575606460f885901c614814565b61357f9190614928565b60ff16610140820152600a6135988160f885901c614814565b6135a29190614928565b60ff166101608201526135ba600a60f884901c614928565b60ff1661018082015260e08101516135d39060016147db565b6101408201516135e4906003614855565b6135ee91906147db565b60ff1660e08201526101008101516136079060016147db565b610140820151613618906004614855565b61362291906147db565b60ff90811661010083015260a08201511660451461366a5760a081015161364a9060016147db565b61014082015161365b90600f614855565b61366591906147db565b61366d565b60455b60ff1660a08201526101208101516136869060016147db565b610140820151613697906007614855565b6136a191906147db565b60ff16610120820152919050565b6011546040516001600160601b03193360601b166020820152446034820152426054820152486074820152609481019190915260009060b4016040516020818303038152906040528051906020012060001c905090565b600083838360405160200161371d9392919061471b565b60408051601f198184030181529190528051602090910120949350505050565b600061374a836004614836565b61375590601461487e565b613760600384614800565b61376b9060026147c3565b61166091906147c3565b6000613782826002614836565b61378d8460016147c3565b61376b906002614836565b6000818152600560205260409020546001600160a01b0316156137ee5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610dcc565b60035460028054906000613801836148d8565b9190505511156138485760405162461bcd60e51b81526020600482015260126024820152711350560814d5541413164814915050d2115160721b6044820152606401610dcc565b6001600160a01b038216600081815260046020908152604080832080546001019055848352600590915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600080600784106138ca5750680796e3ea3f8ab000005b600e84101580156138db5750601e84105b156138ec57506816c4abbebea01000005b601e8410613900575068410d586a20a4c000005b61390b846001614836565b61391590846147c3565b91506064821061392457606491505b61393033826000613081565b5092915050565b600080600080896064146139605761395060148b614800565b61395b9060016147c3565b613963565b60055b9050869350859250849150876001148061397d5750876003145b15613a7d57600060646139af8b604051806040016040528060068152602001652bb2b0b837b760d11b8152508f613706565b6139b991906148f3565b9050600a8161ffff161180156139d3575060508161ffff16105b156139e057819450613a40565b60508161ffff161115613a195760056139fa8360016147c3565b11613a0f57613a0a8260016147c3565b613a12565b60055b9450613a40565b6001613a25818461487e565b10613a3a57613a3560018361487e565b613a3d565b60015b94505b8415613a7657613a5160038b614914565b613a5c60018761487e565b613a67906003614836565b613a7191906147c3565b613a79565b60005b9350505b8760021480613a8c5750876003145b15613b48576000613abf8a60405180604001604052806009815260200168496e76656e746f727960b81b8152508e613706565b90506000613aea8b604051806040016040528060048152602001634469636560e01b8152508f613706565b9050613af76064826148f3565b905060148161ffff1611613b455760038311613b2857613b186006836148f3565b613b2390600161479d565b613b3e565b613b336003836148f3565b613b3e90600361479d565b61ffff1693505b50505b509750975097945050505050565b600080600085606414613b7e57613b6e601487614800565b613b799060016147c3565b613b81565b60055b905060006064613bb086604051806040016040528060068152602001652bb2b0b837b760d11b81525089613706565b613bba9190614914565b9050600a81118015613bcc5750605081105b15613bd957819250613c35565b6050811115613c0e576004613bef8360016147c3565b11613c0457613bff8260016147c3565b613c07565b60045b9250613c35565b6001613c1a818461487e565b10613c2f57613c2a60018361487e565b613c32565b60015b92505b613c40600386614914565b613c4b60018561487e565b613c56906003614836565b613c6091906147c3565b93505050935093915050565b828054828255906000526020600020908101928215613cad579160200282015b82811115613cad578251829061ffff16905591602001919060010190613c8c565b50613cb9929150613d9a565b5090565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915290565b604051806101a0016040528060006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b80821115613cb95760008155600101613d9b565b80356001600160a01b0381168114613dc657600080fd5b919050565b60008083601f840112613ddd57600080fd5b50813567ffffffffffffffff811115613df557600080fd5b6020830191508360208260051b8501011115613e1057600080fd5b9250929050565b80358015158114613dc657600080fd5b600082601f830112613e3857600080fd5b8135613e4b613e4682614775565b614744565b818152846020838601011115613e6057600080fd5b816020850160208301376000918101602001919091529392505050565b803560ff81168114613dc657600080fd5b600060208284031215613ea057600080fd5b61166082613daf565b60008060408385031215613ebc57600080fd5b613ec583613daf565b9150613ed360208401613daf565b90509250929050565b60008060008060808587031215613ef257600080fd5b613efb85613daf565b9350613f0960208601613daf565b9250613f1760408601613daf565b9150613f2560608601613daf565b905092959194509250565b600080600060608486031215613f4557600080fd5b613f4e84613daf565b9250613f5c60208501613daf565b9150604084013590509250925092565b60008060008060808587031215613f8257600080fd5b613f8b85613daf565b9350613f9960208601613daf565b925060408501359150606085013567ffffffffffffffff811115613fbc57600080fd5b613fc887828801613e27565b91505092959194509250565b60008060408385031215613fe757600080fd5b613ff083613daf565b9150613ed360208401613e17565b6000806040838503121561401157600080fd5b61401a83613daf565b946020939093013593505050565b60008060006040848603121561403d57600080fd5b833567ffffffffffffffff81111561405457600080fd5b61406086828701613dcb565b9094509250614073905060208501613e17565b90509250925092565b6000806020838503121561408f57600080fd5b823567ffffffffffffffff8111156140a657600080fd5b6140b285828601613dcb565b90969095509350505050565b6000806000806000606086880312156140d657600080fd5b853567ffffffffffffffff808211156140ee57600080fd5b6140fa89838a01613dcb565b909750955060209150878201358181111561411457600080fd5b6141208a828b01613dcb565b90965094505060408801358181111561413857600080fd5b8801601f81018a1361414957600080fd5b80358281111561415b5761415b61498c565b8060051b61416a858201614744565b8281528581019084870183860188018f101561418557600080fd5b600093505b848410156141c35786813511156141a057600080fd5b6141af8f898335890101613e27565b83526001939093019291870191870161418a565b50809750505050505050509295509295909350565b6000806000604084860312156141ed57600080fd5b833567ffffffffffffffff81111561420457600080fd5b61421086828701613dcb565b909790965060209590950135949350505050565b600080600080600080600060c0888a03121561423f57600080fd5b873567ffffffffffffffff81111561425657600080fd5b6142628a828b01613dcb565b909850965050602088013594506040880135935061428260608901613e17565b925061429060808901613e17565b915061429e60a08901613e17565b905092959891949750929550565b6000602082840312156142be57600080fd5b8135611660816149a2565b6000602082840312156142db57600080fd5b8151611660816149a2565b6000602082840312156142f857600080fd5b813567ffffffffffffffff81111561430f57600080fd5b61335e84828501613e27565b60006020828403121561432d57600080fd5b815167ffffffffffffffff81111561434457600080fd5b8201601f8101841361435557600080fd5b8051614363613e4682614775565b81815285602083850101111561437857600080fd5b614389826020830160208601614895565b95945050505050565b6000602082840312156143a457600080fd5b5035919050565b600080604083850312156143be57600080fd5b82359150613ed360208401613daf565b6000806000606084860312156143e357600080fd5b83359250613f5c60208501613daf565b60008060006060848603121561440857600080fd5b83359250602084013567ffffffffffffffff81111561442657600080fd5b61443286828701613e27565b925050604084013590509250925092565b6000806040838503121561445657600080fd5b50508035926020909101359150565b6000806000806080858703121561447b57600080fd5b505082516020840151604085015160609095015191969095509092509050565b6000806000806000806000806000806101408b8d0312156144bb57600080fd5b8a3599506144cb60208c01613e7d565b98506144d960408c01613e7d565b97506144e760608c01613e7d565b96506144f560808c01613e7d565b955061450360a08c01613e7d565b945061451160c08c01613e7d565b935061451f60e08c01613e7d565b925061452e6101008c01613e7d565b915061453d6101208c01613e7d565b90509295989b9194979a5092959850565b60008151808452614566816020860160208601614895565b601f01601f19169290920160200192915050565b6000825161458c818460208701614895565b9190910192915050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906145c99083018461454e565b9695505050505050565b602081526000611660602083018461454e565b602080825260089082015267656c66206275737960c01b604082015260600190565b60208082526012908201527115195c9b5a5b985b081a5cc818db1bdcd95960721b604082015260600190565b81516001600160a01b031681526101a08101602083015160208301526040830151614664604084018260ff169052565b506060830151614679606084018260ff169052565b50608083015161468e608084018260ff169052565b5060a08301516146a360a084018260ff169052565b5060c08301516146b860c084018260ff169052565b5060e08301516146cd60e084018260ff169052565b506101008381015160ff908116918401919091526101208085015182169084015261014080850151821690840152610160808501518216908401526101809384015116929091019190915290565b838152606060208201526000614734606083018561454e565b9050826040830152949350505050565b604051601f8201601f1916810167ffffffffffffffff8111828210171561476d5761476d61498c565b604052919050565b600067ffffffffffffffff82111561478f5761478f61498c565b50601f01601f191660200190565b600061ffff8083168185168083038211156147ba576147ba61494a565b01949350505050565b600082198211156147d6576147d661494a565b500190565b600060ff821660ff84168060ff038211156147f8576147f861494a565b019392505050565b60008261480f5761480f614960565b500490565b600060ff83168061482757614827614960565b8060ff84160491505092915050565b60008160001904831182151516156148505761485061494a565b500290565b600060ff821660ff84168160ff04811182151516156148765761487661494a565b029392505050565b6000828210156148905761489061494a565b500390565b60005b838110156148b0578181015183820152602001614898565b8381111561111a5750506000910152565b6000816148d0576148d061494a565b506000190190565b60006000198214156148ec576148ec61494a565b5060010190565b600061ffff8084168061490857614908614960565b92169190910692915050565b60008261492357614923614960565b500690565b600060ff83168061493b5761493b614960565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b0319811681146149b857600080fd5b5056fea264697066735822122097843a83f4c5423362c16f907f19b162fd1ce6b15f06e3c4886774c5c57403f664736f6c63430008070033

Deployed Bytecode

0x6080604052600436106103b85760003560e01c8063956cc859116101f2578063cdc2544d1161010d578063e985e9c5116100a0578063f851a4401161006f578063f851a44014610bf7578063f8d0fded14610c17578063f93c50ac14610c2c578063fb5dc25d14610cce57600080fd5b8063e985e9c514610b67578063ec03a77614610ba2578063f014a89714610bc2578063f2e708db14610bd757600080fd5b8063d5f18429116100dc578063d5f1842914610ade578063d8c8346714610751578063dc8c0c9914610b1a578063e4b50cb814610b3a57600080fd5b8063cdc2544d14610a46578063d05dcc6a14610a66578063d2ed5c5914610ab3578063d5abeb0114610ac857600080fd5b8063b10dcc9311610185578063c092b13e11610154578063c092b13e146109c1578063c861aba4146109d6578063c87b56dd146109f6578063cd5d211814610a1657600080fd5b8063b10dcc9314610947578063b4eada8814610967578063b88d4fde14610981578063bddb95c1146109a157600080fd5b8063a22cb465116101c1578063a22cb465146108ba578063a59d1686146108da578063a8792a7414610907578063a9059cbb1461092757600080fd5b8063956cc8591461081e57806395d89b41146108345780639b19251a14610860578063a035b1fe146108a457600080fd5b80633a5381b5116102e25780636352211e11610275578063853828b611610244578063853828b61461079e5780638a9b4067146107b35780638b1681a6146107d35780638da5cb5b1461080057600080fd5b80636352211e146106ee57806370a08231146107245780637655c823146107515780638299b1661461077157600080fd5b806346ddb7db116102b157806346ddb7db1461066e578063485cc9551461068e5780634a945f8d146106ae5780635ea1f2fa146106ce57600080fd5b80633a5381b5146105e457806342842e0e146106045780634576da471461062457806345c9fce21461064457600080fd5b80631249c58b1161035a5780631990801611610329578063199080161461056257806323b872dd1461058357806330923299146105a357806338b3ccc8146105c357600080fd5b80631249c58b146104f65780631637bbdf1461050c57806318160ddd1461052c578063181f4c3b1461054257600080fd5b8063081812fc11610396578063081812fc14610454578063095ea7b3146104a257806309f94443146104c25780630c0ef2b0146104d557600080fd5b806301ffc9a7146103bd57806303339bcb146103f257806306fdde0314610414575b600080fd5b3480156103c957600080fd5b506103dd6103d83660046142ac565b610ce1565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b5061041261040d3660046143ab565b610d18565b005b34801561042057600080fd5b5060408051808201909152600e81526d45746865726e616c20456c76657360901b60208201525b6040516103e991906145d3565b34801561046057600080fd5b5061048a61046f366004614392565b6006602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103e9565b3480156104ae57600080fd5b506104126104bd366004613ffe565b610d4c565b6104126104d036600461407c565b610e31565b3480156104e157600080fd5b50600a546103dd90600160a01b900460ff1681565b6104fe610e83565b6040519081526020016103e9565b34801561051857600080fd5b506104fe610527366004614392565b610fd9565b34801561053857600080fd5b506104fe60025481565b34801561054e57600080fd5b5061041261055d366004614443565b610ffa565b34801561056e57600080fd5b50600a546103dd90600160a81b900460ff1681565b34801561058f57600080fd5b5061041261059e366004613f30565b61106a565b3480156105af57600080fd5b506104126105be36600461449b565b611120565b3480156105cf57600080fd5b50600a546103dd90600160b01b900460ff1681565b3480156105f057600080fd5b50600e5461048a906001600160a01b031681565b34801561061057600080fd5b5061041261061f366004613f30565b61125d565b34801561063057600080fd5b5061041261063f366004614028565b611278565b34801561065057600080fd5b506106596112f1565b604080519283526020830191909152016103e9565b34801561067a57600080fd5b50610412610689366004613ffe565b6113e0565b34801561069a57600080fd5b506104126106a9366004613ea9565b611419565b3480156106ba57600080fd5b506104126106c9366004613edc565b61152a565b3480156106da57600080fd5b506104126106e9366004614224565b611582565b3480156106fa57600080fd5b5061048a610709366004614392565b6005602052600090815260409020546001600160a01b031681565b34801561073057600080fd5b506104fe61073f366004613e8e565b60046020526000908152604090205481565b34801561075d57600080fd5b506104fe61076c3660046143ce565b6115dc565b34801561077d57600080fd5b506104fe61078c366004614392565b60136020526000908152604090205481565b3480156107aa57600080fd5b50610412611667565b3480156107bf57600080fd5b50600a5461048a906001600160a01b031681565b3480156107df57600080fd5b506104fe6107ee366004613e8e565b60146020526000908152604090205481565b34801561080c57600080fd5b506001546001600160a01b031661048a565b34801561082a57600080fd5b506104fe600f5481565b34801561084057600080fd5b5060408051808201909152600381526222a62b60e91b6020820152610447565b34801561086c57600080fd5b5061089161087b366004613e8e565b60166020526000908152604090205461ffff1681565b60405161ffff90911681526020016103e9565b3480156108b057600080fd5b506104fe60105481565b3480156108c657600080fd5b506104126108d5366004613fd4565b6116bc565b3480156108e657600080fd5b506104fe6108f5366004614392565b60009081526013602052604090205490565b34801561091357600080fd5b506103dd6109223660046140be565b611728565b34801561093357600080fd5b50610412610942366004613ffe565b6118f3565b34801561095357600080fd5b5061041261096236600461407c565b611950565b34801561097357600080fd5b506017546103dd9060ff1681565b34801561098d57600080fd5b5061041261099c366004613f6c565b61198a565b3480156109ad57600080fd5b506104126109bc366004614443565b611ac0565b3480156109cd57600080fd5b50610412611add565b3480156109e257600080fd5b506103dd6109f13660046141d8565b611b06565b348015610a0257600080fd5b50610447610a11366004614392565b611cdf565b348015610a2257600080fd5b506103dd610a31366004613e8e565b60156020526000908152604090205460ff1681565b348015610a5257600080fd5b506103dd610a613660046143f3565b611d7b565b348015610a7257600080fd5b50610a86610a81366004614392565b611f0b565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0016103e9565b348015610abf57600080fd5b50610412611fb9565b348015610ad457600080fd5b506104fe60035481565b348015610aea57600080fd5b50610891610af93660046142e6565b805160208183018101805160188252928201919093012091525461ffff1681565b348015610b2657600080fd5b50610412610b35366004614392565b611fe2565b348015610b4657600080fd5b50610b5a610b55366004614392565b61212b565b6040516103e99190614634565b348015610b7357600080fd5b506103dd610b82366004613ea9565b600760209081526000928352604080842090915290825290205460ff1681565b348015610bae57600080fd5b50610412610bbd36600461407c565b61214b565b348015610bce57600080fd5b5061041261219d565b348015610be357600080fd5b50610412610bf236600461407c565b6121b9565b348015610c0357600080fd5b5060015461048a906001600160a01b031681565b348015610c2357600080fd5b5061041261220b565b348015610c3857600080fd5b50610c8f610c47366004614392565b6000908152601360205260409020549064ffffffffff60a083901c169060ff60c884901c81169160d085901c82169160d886901c81169160e087901c82169160e888901c1690565b604080516001600160a01b0390981688526020880196909652948601939093526060850191909152608084015260a083015260c082015260e0016103e9565b610412610cdc36600461407c565b6122da565b60006380ac58cd60e01b6001600160e01b031983161480610d125750635b5e139f60e01b6001600160e01b03198316145b92915050565b610d2061232c565b60005b82811015610d4757610d348261238e565b5080610d3f816148d8565b915050610d23565b505050565b6000818152600560205260409020546001600160a01b031633811480610d9557506001600160a01b038116600090815260076020908152604080832033845290915290205460ff165b610dd55760405162461bcd60e51b815260206004820152600c60248201526b1393d517d054141493d5915160a21b60448201526064015b60405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b610e3961263c565b60005b81811015610d4757610e71838383818110610e5957610e59614976565b90506020020135600633600080600080600080612699565b80610e7b816148d8565b915050610e3c565b6000610e8d61263c565b600a54600160a81b900460ff16610eda5760405162461bcd60e51b8152602060048201526011602482015270135a5b9d1a5b99c81a5cc818db1bdcd959607a1b6044820152606401610dcc565b6000610ee46112f1565b5080915050600f5460025411610f3a5780341015610f355760405162461bcd60e51b815260206004820152600e60248201526d2737ba22b737bab3b422ba3432b960911b6044820152606401610dcc565b610fc6565b33600090815260146020526040902054811115610fba57600a54604051632770a7eb60e21b8152336004820152602481018390526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b158015610f9d57600080fd5b505af1158015610fb1573d6000803e3d6000fd5b50505050610fc6565b610fc633826001613081565b610fcf3361238e565b61ffff1691505090565b60128181548110610fe957600080fd5b600091825260209091200154905081565b600d546001600160a01b031633148061101d57506001546001600160a01b031633145b6110585760405162461bcd60e51b815260206004820152600c60248201526b6e6f74207465726d696e757360a01b6044820152606401610dcc565b60009182526013602052604090912055565b6000818152600560205260409020546001600160a01b0316338114806110a657506000828152600660205260409020546001600160a01b031633145b806110d457506001600160a01b038116600090815260076020908152604080832033845290915290205460ff165b61110f5760405162461bcd60e51b815260206004820152600c60248201526b1393d517d054141493d5915160a21b6044820152606401610dcc565b61111a848484613128565b50505050565b61112861232c565b60008a81526013602052604081205461114090613211565b905061116d6040518060800160405280600081526020016000815260200160008152602001600081525090565b81516001600160a01b0316825260ff808916606084015289811660808401528b811660a084015287811660c08401528a81166101608401528681166101808401528581166101008401819052858216610140850152908416610120840181905260e08401516111dd929091613331565b60408201526101408201516101608301516101808401516111ff929190613331565b81606001818152505061123d826000015183602001518460400151856060015186608001518760a001518860c0015188604001518960600151613366565b60009c8d5260136020526040909c209b909b555050505050505050505050565b610d478383836040518060200160405280600081525061198a565b61128061232c565b60005b8281101561111a5781601560008686858181106112a2576112a2614976565b90506020020160208101906112b79190613e8e565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055806112e9816148d8565b915050611283565b600080600f546002541161130a57505060105490600190565b610fa060025410156113285750680340aad21b3b7000009160039150565b611194600254101561134657506809c2007651b25000009160059150565b6113886002541015611364575068138400eca364a0000091600f9150565b61157c60025410156113825750682086ac3510526000009160199150565b61177060025410156113a057506830ca024f987b9000009160239150565b6118bd60025410156113be5750686194049f30f720000091602d9150565b611a0a60025410156113dc575068925e06eec972b0000091603c9150565b9091565b6113e861232c565b6001600160a01b038216600090815260146020526040812080548392906114109084906147c3565b90915550505050565b600a54600160b81b900460ff16156114695760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610dcc565b600180546001600160a01b03199081163317909155600b80546001600160a01b0385811691841691909117909155600c805491841691909216179055611a0a6003908155610ce4600f55600a805460ff60b81b1916600160b81b179055670138a388a43c00006010556040805160608101825260fa815261029460208201526109c4918101919091526114ff9160129190613c6c565b5050600e80546001600160a01b0319167380861814a8775de20f9506cf41932e95f80f703517905550565b61153261232c565b600a80546001600160a01b039586166001600160a01b03199182161790915560088054948616948216949094179093556009805492851692841692909217909155600e8054919093169116179055565b61158a61263c565b60005b868110156115d2576115c08888838181106115aa576115aa614976565b9050602002013560023389898989896001612699565b806115ca816148d8565b91505061158d565b5050505050505050565b604080516020808201869052606085901b6001600160601b031916828401526054808301859052835180840390910181526074830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a333200000000609484015260b0808401919091528351808403909101815260d090920190925280519101205b9392505050565b61166f61232c565b47600061167d600283614800565b90506000821161168c57600080fd5b600b546116a2906001600160a01b0316826133b5565b600c546116b8906001600160a01b0316826133b5565b5050565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600061173261263c565b60175460ff166117545760405162461bcd60e51b8152600401610dcc90614608565b8480156118e95760005b868110156118e7576117c36117a489898481811061177e5761177e614976565b905060200201353389898681811061179857611798614976565b905060200201356115dc565b8583815181106117b6576117b6614976565b6020026020010151613415565b6118055760405162461bcd60e51b8152602060048201526013602482015272696e636f7272656374207369676e617475726560681b6044820152606401610dcc565b85858281811061181757611817614976565b90506020020135601360008a8a8581811061183457611834614976565b9050602002013581526020019081526020016000208190555061187a88888381811061186257611862614976565b90506020020135600033600080600080600080612699565b87878281811061188c5761188c614976565b90506020020135336001600160a01b03167e817f5e0c1c773a9e3b8d5e7d593eb7d6556749dcc48cfd5798d888a2190f9d426040516118cd91815260200190565b60405180910390a3806118df816148d8565b91505061175e565b505b5095945050505050565b6000818152600560205260409020546001600160a01b031633146119455760405162461bcd60e51b81526020600482015260096024820152682727aa2fa7aba722a960b91b6044820152606401610dcc565b6116b8338383613128565b61195861263c565b60005b81811015610d475761197883838381811061186257611862614976565b80611982816148d8565b91505061195b565b61199584848461106a565b6001600160a01b0383163b1561111a576000836001600160a01b031663150b7a02338786866040516024016119cd9493929190614596565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051611a06919061457a565b600060405180830381855afa9150503d8060008114611a41576040519150601f19603f3d011682016040523d82523d6000602084013e611a46565b606091505b50915050600081806020019051810190611a6091906142c9565b9050630a85bd0160e11b6001600160e01b0319821614611ab85760405162461bcd60e51b81526020600482015260136024820152722727aa2fa2a9219b9918afa922a1a2a4ab22a960691b6044820152606401610dcc565b505050505050565b611ac861263c565b6116b882600733846000806000806000612699565b611ae561232c565b600a805460ff60a01b198116600160a01b9182900460ff1615909102179055565b6000611b1061263c565b60175460ff16611b325760405162461bcd60e51b8152600401610dcc90614608565b828015611c0d5760005b84811015611c0b57611b71868683818110611b5957611b59614976565b90506020020135600833600080600080600080612699565b60136000878784818110611b8757611b87614976565b90506020020135815260200190815260200160002054868683818110611baf57611baf614976565b90506020020135336001600160a01b03167ff70c8ccfb49937cb9079ffa719be60366bdb8f901313f28dd3da4e482977a7fa42604051611bf191815260200190565b60405180910390a480611c03816148d8565b915050611b3c565b505b8215611cd75733600090815260146020526040902054831115611c9357600a54604051632770a7eb60e21b8152336004820152602481018590526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b158015611c7657600080fd5b505af1158015611c8a573d6000803e3d6000fd5b50505050611c9f565b611c9f33846001613081565b604051428152839033907f0ae95557dadbad8b7a6e8ea6e957363d7eb9cf9c56d1916d13a65e750fa57f619060200160405180910390a35b509392505050565b6008546000828152601360205260409081902054905163470ad4b560e11b815261ffff8416600482015260248101919091526060916001600160a01b031690638e15a96a9060440160006040518083038186803b158015611d3f57600080fd5b505afa158015611d53573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d12919081019061431b565b6000611d8561263c565b60175460ff16611da75760405162461bcd60e51b8152600401610dcc90614608565b601883604051611db7919061457a565b9081526040519081900360200190205461ffff1615611e115760405162461bcd60e51b815260206004820152601660248201527514da59db985d1d5c9948185b1c9958591e481d5cd95960521b6044820152606401610dcc565b831561166057611e2b611e258533856115dc565b84613415565b611e6d5760405162461bcd60e51b8152602060048201526013602482015272696e636f7272656374207369676e617475726560681b6044820152606401610dcc565b6001601884604051611e7f919061457a565b908152604051908190036020018120805461ffff9390931661ffff1990931692909217909155600a546340c10f1960e01b8252336004830152602482018690526001600160a01b0316906340c10f1990604401600060405180830381600087803b158015611eec57600080fd5b505af1158015611f00573d6000803e3d6000fd5b505050509392505050565b6000818152601360205260408120548190819081908190819060ff60f082901c1660f882901c600a611f3e606484614800565b611f489190614914565b9850600a611f568184614800565b611f609190614914565b9750611f6d600a83614914565b9650600a611f7c606483614800565b611f869190614914565b9550600a611f948183614800565b611f9e9190614914565b9450611fab600a82614914565b935050505091939550919395565b611fc161232c565b600a805460ff60a81b198116600160a81b9182900460ff1615909102179055565b3360009081526014602052604090205461202a5760405162461bcd60e51b81526020600482015260096024820152684e6f42616c616e636560b81b6044820152606401610dcc565b3360009081526014602052604081205461204590839061487e565b10156120935760405162461bcd60e51b815260206004820152601760248201527f4f7665726472616674204e6f74207065726d69747465640000000000000000006044820152606401610dcc565b336000908152601460205260409020546120ae90829061487e565b336000818152601460205260409081902092909255600a5491516340c10f1960e01b81526004810191909152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b15801561211057600080fd5b505af1158015612124573d6000803e3d6000fd5b5050505050565b612133613cbd565b600082815260136020526040902054610d12906134a1565b61215361263c565b60005b81811015610d475761218b83838381811061217357612173614976565b90506020020135600433600080600080600080612699565b80612195816148d8565b915050612156565b6121a561232c565b6017805460ff19811660ff90911615179055565b6121c161263c565b60005b81811015610d47576121f98383838181106121e1576121e1614976565b90506020020135600333600080600080600080612699565b80612203816148d8565b9150506121c4565b336000908152601460205260409020546122535760405162461bcd60e51b81526020600482015260096024820152684e6f42616c616e636560b81b6044820152606401610dcc565b600a5433600081815260146020526040908190205490516340c10f1960e01b8152600481019290925260248201526001600160a01b03909116906340c10f1990604401600060405180830381600087803b1580156122b057600080fd5b505af11580156122c4573d6000803e3d6000fd5b5050336000908152601460205260408120555050565b6122e261263c565b60005b81811015610d475761231a83838381811061230257612302614976565b90506020020135600533600080600080600080612699565b80612324816148d8565b9150506122e5565b6001546001600160a01b031633148061235957503360009081526015602052604090205460ff1615156001145b8061236e5750600b546001600160a01b031633145b806123835750600c546001600160a01b031633145b61238c57600080fd5b565b6000806123996136af565b90506123a3613d29565b6002546123b19060016147c3565b6000808352426020840152610180830181905261016083018190526040830152604560a083015292506123e26112f1565b60c083015250604080518082019091526005815264436c61737360d81b602082015260039061241790849061ffff8716613706565b61242191906148f3565b61ffff166101408201526061612438606484614914565b1161247957600361246a83604051806040016040528060048152602001635261636560e01b8152508661ffff16613706565b61247491906148f3565b61247c565b60035b61ffff1661010082018190526003146124cb5760036124bc83604051806040016040528060048152602001632430b4b960e11b8152508661ffff16613706565b6124c691906148f3565b6124ce565b60005b61ffff1660e082015261014081015115612525576002612516836040518060400160405280600b81526020016a4163636573736f7269657360a81b8152508661ffff16613706565b61252091906148f3565b61256e565b6002612559836040518060400160405280600b81526020016a4163636573736f7269657360a81b8152508661ffff16613706565b61256391906148f3565b61256e90600361479d565b61ffff16610120820181905260e0820151610100830151600092612593929190613331565b905060006125b1836101400151846101600151856101800151613331565b90506125c68361014001518460c0015161373d565b60608401526101408301516101608401516125e19190613775565b60808401819052835160208501516040860151606087015160a088015160c08901516126109691908989613366565b61ffff861660008181526013602052604090209190915561263693508692509050613798565b50919050565b33803b90328114801561264d575081155b61265657600080fd5b6040516001600160601b0319606083811b8216602084015241901b16603482015260480160408051601f1981840301815291905280516020909101206011555050565b6000898152601360205260408120546126b190613211565b90506126de6040518060800160405280600081526020016000815260200160008152602001600081525090565b600a54600160a01b900460ff166126f457600080fd5b60008b8152600560205260409020546001600160a01b0316331480612722575081516001600160a01b031633145b61275b5760405162461bcd60e51b815260206004820152600a6024820152692737ba2cb7bab922b63360b11b6044820152606401610dcc565b8160400151600814156127a15760405162461bcd60e51b815260206004820152600e60248201526d32b6331034b7102837b63cb3b7b760911b6044820152606401610dcc565b60006127ab6136af565b90508a6128535760008c8152600560205260409020546001600160a01b031630146127d557600080fd5b428360200151106127f85760405162461bcd60e51b8152600401610dcc906145e6565b82604001516003141561283f5762015180836020015142612819919061487e565b6128239190614800565b6020830181905260c084015161283991906138b3565b60c08401525b61284a308b8e613128565b60008352612f5f565b8a60021415612adb574283602001511061287f5760405162461bcd60e51b8152600401610dcc906145e6565b8260400151600314156128d45760405162461bcd60e51b815260206004820152601760248201527f657869742070617373697665206d6f64652066697273740000000000000000006044820152606401610dcc565b60008c8152600560205260409020546001600160a01b0316301461290a576128fd8a308e613128565b6001600160a01b038a1683525b60095460c084015160808501516060860151610180870151604051636b9921c960e11b8152600481018f9052602481018e905260448101949094526064840192909252608483015260a482015286151560c48201526001600160a01b039091169063d73243929060e401608060405180830381600087803b15801561298e57600080fd5b505af11580156129a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c69190614465565b6101808701526020860152835260c084015260008780156129e45750865b156129f157506003612a11565b87156129ff57506001612a11565b8615612a0d57506002612a11565b5060005b8015612a5157612a3f8d8560c00151612a286136af565b848861016001518960a001518a6101800151613937565b61018087015260a08601526101608501525b8460011480612a605750846002145b15612a7557612a753384600001516000613081565b8460031415612a945760c0840151612a8e9060016147c3565b60c08501525b825160408051918252602082018b90528e918c9133917fdba077684e888626139ef24141ba8d03b94328892d5e2d8a85d586ab74071c06910160405180910390a450612f5f565b8a60031415612b485742836020015110612b075760405162461bcd60e51b8152600401610dcc906145e6565b60008c8152600560205260409020546001600160a01b03163014612b3d57612b308a308e613128565b6001600160a01b038a1683525b426020840152612f5f565b8a60041415612ba0578260400151600314612b6257600080fd5b62015180836020015142612b76919061487e565b612b809190614800565b6020830181905260c0840151612b9691906138b3565b60c0840152612f5f565b8a60051415612bee57662386f26fc10000341015612bbd57600080fd5b826040015160031415612bcf57600080fd5b612bde8360c001518d83613b56565b61016085015260a0840152612f5f565b8a60061415612c5557662386f26fc10000341015612c0b57600080fd5b826040015160031415612c1d57600080fd5b612c3f8c8460c001518360028761016001518860a00151896101800151613937565b61018086015260a0850152610160840152612f5f565b8a60071415612f205761014083015115612ca05760405162461bcd60e51b815260206004820152600c60248201526b3737ba1030903432b0b632b960a11b6044820152606401610dcc565b826040015160031415612cf55760405162461bcd60e51b815260206004820152601760248201527f63616e74206865616c207768696c6520706173736976650000000000000000006044820152606401610dcc565b42836020015110612d185760405162461bcd60e51b8152600401610dcc906145e6565b60008c8152600560205260409020546001600160a01b03163014612d4e57612d418a308e613128565b6001600160a01b038a1683525b612d5a4261a8c06147c3565b602084015260c0830151612d6f9060016147c3565b60c0840152600089815260136020526040812054612d8c90613211565b60008b8152600560205260409020549091506001600160a01b0316331480612dbd575080516001600160a01b031633145b612df65760405162461bcd60e51b815260206004820152600a6024820152692737ba2cb7bab922b63360b11b6044820152606401610dcc565b8060200151421015612e9257428160200151612e12919061487e565b60208401819052612e27578260200151612e77565b61014081015115612e7457806101400151600114612e6157600283602001516001612e529190614836565b612e5c9190614800565b612e77565b600483602001516001612e529190614836565b60005b6020808501829052820151612e8c919061487e565b60208201525b612eab8160e00151826101000151836101200151613331565b6040840152610140810151610160820151610180830151612ecd929190613331565b836060018181525050612f0b816000015182602001518360400151846060015185608001518660a001518760c001518a604001518b60600151613366565b60008b81526013602052604090205550612f5f565b8a60081415612f5f5760008c8152600560205260409020546001600160a01b03163014612f5f57612f528a308e613128565b6001600160a01b038a1683525b612f788360e00151846101000151856101200151613331565b6040830152610140830151610160840151610180850151612f9a929190613331565b606083015261014083015160c0840151612fb4919061373d565b6060840152610140830151610160840151612fcf9190613775565b608084015260c0830151606410612fea578260c00151612fed565b60645b8360c00181815250508a836040018181525050613035836000015184602001518560400151866060015187608001518860a001518960c0015189604001518a60600151613366565b60008d8152601360205260408082209290925590518d918d9133917fc87dac464bd9964598d47d6e7f7cbe0b76cad55b33430228240e72c18da0edf691a4505050505050505050505050565b806130b9576001600160a01b038316600090815260146020526040812080548492906130ae9084906147c3565b9250508190556130e8565b6001600160a01b038316600090815260146020526040812080548492906130e190849061487e565b9250508190555b5080151582846001600160a01b03167f18796921817e8fa1f03eaae699eabc26977ec4f4b6ec25ede8f7d69b9be8221b60405160405180910390a4505050565b6000818152600560205260409020546001600160a01b0384811691161461314e57600080fd5b6001600160a01b0383166000908152600460205260408120805491613172836148c1565b90915550506001600160a01b038216600090815260046020526040812080549161319b836148d8565b9091555050600081815260066020908152604080832080546001600160a01b0319908116909155600590925280832080546001600160a01b038781169190941681179091559051849391928716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b613219613d29565b6001600160a01b038216815260a082811c64ffffffffff16602083015260c883901c60ff908116604084015260d084901c8116606084015260d884901c8116608084015260e084901c81169183019190915260e883901c811660c0830152600a9061328c9060649060f086901c16614800565b6132969190614914565b60e0820152600a6132ae8160ff60f086901c16614800565b6132b89190614914565b6101008201526132d0600a60ff60f085901c16614914565b610120820152600a6132e7606460f885901c614800565b6132f19190614914565b610140820152600a6133078160f885901c614800565b6133119190614914565b610160820152613326600a60f884901c614914565b610180820152919050565b60008161333f84600a614836565b61334a866064614836565b61335491906147c3565b61335e91906147c3565b949350505050565b60f81b60f09190911b60e89290921b60e09390931b60d89490941b60d09590951b60c89690961b60a09790971b6001600160a01b03909816979097179590951793909317919091171717171790565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613402576040519150601f19603f3d011682016040523d82523d6000602084013e613407565b606091505b5050905080610d4757600080fd5b6020818101516040808401516060808601518351600080825296810180865289905290861a93810184905290810184905260808101829052909190849060019060a0016020604051602081039080840390855afa15801561347a573d6000803e3d6000fd5b5050604051601f190151600e546001600160a01b0390811691161498975050505050505050565b6134a9613cbd565b6001600160a01b038216815260a082811c64ffffffffff16602083015260c883901c60ff908116604084015260d084901c8116606084015260d884901c8116608084015260e084901c81169183019190915260e883901c1660c0820152600a613517606460f085901c614814565b6135219190614928565b60ff1660e0820152600a6135398160f085901c614814565b6135439190614928565b60ff1661010082015261355b600a60f084901c614928565b60ff16610120820152600a613575606460f885901c614814565b61357f9190614928565b60ff16610140820152600a6135988160f885901c614814565b6135a29190614928565b60ff166101608201526135ba600a60f884901c614928565b60ff1661018082015260e08101516135d39060016147db565b6101408201516135e4906003614855565b6135ee91906147db565b60ff1660e08201526101008101516136079060016147db565b610140820151613618906004614855565b61362291906147db565b60ff90811661010083015260a08201511660451461366a5760a081015161364a9060016147db565b61014082015161365b90600f614855565b61366591906147db565b61366d565b60455b60ff1660a08201526101208101516136869060016147db565b610140820151613697906007614855565b6136a191906147db565b60ff16610120820152919050565b6011546040516001600160601b03193360601b166020820152446034820152426054820152486074820152609481019190915260009060b4016040516020818303038152906040528051906020012060001c905090565b600083838360405160200161371d9392919061471b565b60408051601f198184030181529190528051602090910120949350505050565b600061374a836004614836565b61375590601461487e565b613760600384614800565b61376b9060026147c3565b61166091906147c3565b6000613782826002614836565b61378d8460016147c3565b61376b906002614836565b6000818152600560205260409020546001600160a01b0316156137ee5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606401610dcc565b60035460028054906000613801836148d8565b9190505511156138485760405162461bcd60e51b81526020600482015260126024820152711350560814d5541413164814915050d2115160721b6044820152606401610dcc565b6001600160a01b038216600081815260046020908152604080832080546001019055848352600590915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600080600784106138ca5750680796e3ea3f8ab000005b600e84101580156138db5750601e84105b156138ec57506816c4abbebea01000005b601e8410613900575068410d586a20a4c000005b61390b846001614836565b61391590846147c3565b91506064821061392457606491505b61393033826000613081565b5092915050565b600080600080896064146139605761395060148b614800565b61395b9060016147c3565b613963565b60055b9050869350859250849150876001148061397d5750876003145b15613a7d57600060646139af8b604051806040016040528060068152602001652bb2b0b837b760d11b8152508f613706565b6139b991906148f3565b9050600a8161ffff161180156139d3575060508161ffff16105b156139e057819450613a40565b60508161ffff161115613a195760056139fa8360016147c3565b11613a0f57613a0a8260016147c3565b613a12565b60055b9450613a40565b6001613a25818461487e565b10613a3a57613a3560018361487e565b613a3d565b60015b94505b8415613a7657613a5160038b614914565b613a5c60018761487e565b613a67906003614836565b613a7191906147c3565b613a79565b60005b9350505b8760021480613a8c5750876003145b15613b48576000613abf8a60405180604001604052806009815260200168496e76656e746f727960b81b8152508e613706565b90506000613aea8b604051806040016040528060048152602001634469636560e01b8152508f613706565b9050613af76064826148f3565b905060148161ffff1611613b455760038311613b2857613b186006836148f3565b613b2390600161479d565b613b3e565b613b336003836148f3565b613b3e90600361479d565b61ffff1693505b50505b509750975097945050505050565b600080600085606414613b7e57613b6e601487614800565b613b799060016147c3565b613b81565b60055b905060006064613bb086604051806040016040528060068152602001652bb2b0b837b760d11b81525089613706565b613bba9190614914565b9050600a81118015613bcc5750605081105b15613bd957819250613c35565b6050811115613c0e576004613bef8360016147c3565b11613c0457613bff8260016147c3565b613c07565b60045b9250613c35565b6001613c1a818461487e565b10613c2f57613c2a60018361487e565b613c32565b60015b92505b613c40600386614914565b613c4b60018561487e565b613c56906003614836565b613c6091906147c3565b93505050935093915050565b828054828255906000526020600020908101928215613cad579160200282015b82811115613cad578251829061ffff16905591602001919060010190613c8c565b50613cb9929150613d9a565b5090565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915290565b604051806101a0016040528060006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b80821115613cb95760008155600101613d9b565b80356001600160a01b0381168114613dc657600080fd5b919050565b60008083601f840112613ddd57600080fd5b50813567ffffffffffffffff811115613df557600080fd5b6020830191508360208260051b8501011115613e1057600080fd5b9250929050565b80358015158114613dc657600080fd5b600082601f830112613e3857600080fd5b8135613e4b613e4682614775565b614744565b818152846020838601011115613e6057600080fd5b816020850160208301376000918101602001919091529392505050565b803560ff81168114613dc657600080fd5b600060208284031215613ea057600080fd5b61166082613daf565b60008060408385031215613ebc57600080fd5b613ec583613daf565b9150613ed360208401613daf565b90509250929050565b60008060008060808587031215613ef257600080fd5b613efb85613daf565b9350613f0960208601613daf565b9250613f1760408601613daf565b9150613f2560608601613daf565b905092959194509250565b600080600060608486031215613f4557600080fd5b613f4e84613daf565b9250613f5c60208501613daf565b9150604084013590509250925092565b60008060008060808587031215613f8257600080fd5b613f8b85613daf565b9350613f9960208601613daf565b925060408501359150606085013567ffffffffffffffff811115613fbc57600080fd5b613fc887828801613e27565b91505092959194509250565b60008060408385031215613fe757600080fd5b613ff083613daf565b9150613ed360208401613e17565b6000806040838503121561401157600080fd5b61401a83613daf565b946020939093013593505050565b60008060006040848603121561403d57600080fd5b833567ffffffffffffffff81111561405457600080fd5b61406086828701613dcb565b9094509250614073905060208501613e17565b90509250925092565b6000806020838503121561408f57600080fd5b823567ffffffffffffffff8111156140a657600080fd5b6140b285828601613dcb565b90969095509350505050565b6000806000806000606086880312156140d657600080fd5b853567ffffffffffffffff808211156140ee57600080fd5b6140fa89838a01613dcb565b909750955060209150878201358181111561411457600080fd5b6141208a828b01613dcb565b90965094505060408801358181111561413857600080fd5b8801601f81018a1361414957600080fd5b80358281111561415b5761415b61498c565b8060051b61416a858201614744565b8281528581019084870183860188018f101561418557600080fd5b600093505b848410156141c35786813511156141a057600080fd5b6141af8f898335890101613e27565b83526001939093019291870191870161418a565b50809750505050505050509295509295909350565b6000806000604084860312156141ed57600080fd5b833567ffffffffffffffff81111561420457600080fd5b61421086828701613dcb565b909790965060209590950135949350505050565b600080600080600080600060c0888a03121561423f57600080fd5b873567ffffffffffffffff81111561425657600080fd5b6142628a828b01613dcb565b909850965050602088013594506040880135935061428260608901613e17565b925061429060808901613e17565b915061429e60a08901613e17565b905092959891949750929550565b6000602082840312156142be57600080fd5b8135611660816149a2565b6000602082840312156142db57600080fd5b8151611660816149a2565b6000602082840312156142f857600080fd5b813567ffffffffffffffff81111561430f57600080fd5b61335e84828501613e27565b60006020828403121561432d57600080fd5b815167ffffffffffffffff81111561434457600080fd5b8201601f8101841361435557600080fd5b8051614363613e4682614775565b81815285602083850101111561437857600080fd5b614389826020830160208601614895565b95945050505050565b6000602082840312156143a457600080fd5b5035919050565b600080604083850312156143be57600080fd5b82359150613ed360208401613daf565b6000806000606084860312156143e357600080fd5b83359250613f5c60208501613daf565b60008060006060848603121561440857600080fd5b83359250602084013567ffffffffffffffff81111561442657600080fd5b61443286828701613e27565b925050604084013590509250925092565b6000806040838503121561445657600080fd5b50508035926020909101359150565b6000806000806080858703121561447b57600080fd5b505082516020840151604085015160609095015191969095509092509050565b6000806000806000806000806000806101408b8d0312156144bb57600080fd5b8a3599506144cb60208c01613e7d565b98506144d960408c01613e7d565b97506144e760608c01613e7d565b96506144f560808c01613e7d565b955061450360a08c01613e7d565b945061451160c08c01613e7d565b935061451f60e08c01613e7d565b925061452e6101008c01613e7d565b915061453d6101208c01613e7d565b90509295989b9194979a5092959850565b60008151808452614566816020860160208601614895565b601f01601f19169290920160200192915050565b6000825161458c818460208701614895565b9190910192915050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906145c99083018461454e565b9695505050505050565b602081526000611660602083018461454e565b602080825260089082015267656c66206275737960c01b604082015260600190565b60208082526012908201527115195c9b5a5b985b081a5cc818db1bdcd95960721b604082015260600190565b81516001600160a01b031681526101a08101602083015160208301526040830151614664604084018260ff169052565b506060830151614679606084018260ff169052565b50608083015161468e608084018260ff169052565b5060a08301516146a360a084018260ff169052565b5060c08301516146b860c084018260ff169052565b5060e08301516146cd60e084018260ff169052565b506101008381015160ff908116918401919091526101208085015182169084015261014080850151821690840152610160808501518216908401526101809384015116929091019190915290565b838152606060208201526000614734606083018561454e565b9050826040830152949350505050565b604051601f8201601f1916810167ffffffffffffffff8111828210171561476d5761476d61498c565b604052919050565b600067ffffffffffffffff82111561478f5761478f61498c565b50601f01601f191660200190565b600061ffff8083168185168083038211156147ba576147ba61494a565b01949350505050565b600082198211156147d6576147d661494a565b500190565b600060ff821660ff84168060ff038211156147f8576147f861494a565b019392505050565b60008261480f5761480f614960565b500490565b600060ff83168061482757614827614960565b8060ff84160491505092915050565b60008160001904831182151516156148505761485061494a565b500290565b600060ff821660ff84168160ff04811182151516156148765761487661494a565b029392505050565b6000828210156148905761489061494a565b500390565b60005b838110156148b0578181015183820152602001614898565b8381111561111a5750506000910152565b6000816148d0576148d061494a565b506000190190565b60006000198214156148ec576148ec61494a565b5060010190565b600061ffff8084168061490857614908614960565b92169190910692915050565b60008261492357614923614960565b500690565b600060ff83168061493b5761493b614960565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b0319811681146149b857600080fd5b5056fea264697066735822122097843a83f4c5423362c16f907f19b162fd1ce6b15f06e3c4886774c5c57403f664736f6c63430008070033

Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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