ETH Price: $3,123.45 (+0.86%)

Contract

0x4fA884153Cd40CC36b92ACAbe8314BB2c632C89c
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60806040142495652022-02-21 12:59:49998 days ago1645448389IN
 Create: EthernalElvesV4
0 ETH0.2510498460.63714335

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

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

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.