ETH Price: $2,522.29 (+2.78%)

Contract

0x898d1DDe196C410c4AE3d3819d68efdd5cE22851
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer198539772024-05-12 12:35:35113 days ago1715517335IN
0x898d1DDe...d5cE22851
0 ETH0.00069643.90174635
Approve194256942024-03-13 10:56:23173 days ago1710327383IN
0x898d1DDe...d5cE22851
0 ETH0.0030321564.78822043
Approve192530722024-02-18 7:00:47197 days ago1708239647IN
0x898d1DDe...d5cE22851
0 ETH0.0008517418.19926967
Approve192416802024-02-16 16:36:35199 days ago1708101395IN
0x898d1DDe...d5cE22851
0 ETH0.0015206532.49190229
Approve192392602024-02-16 8:24:59199 days ago1708071899IN
0x898d1DDe...d5cE22851
0 ETH0.0010685222.83132843
Approve192388452024-02-16 7:00:59199 days ago1708066859IN
0x898d1DDe...d5cE22851
0 ETH0.0011607124.80112981
Approve192365952024-02-15 23:27:11200 days ago1708039631IN
0x898d1DDe...d5cE22851
0 ETH0.0013155128.10874069
Approve192364272024-02-15 22:52:59200 days ago1708037579IN
0x898d1DDe...d5cE22851
0 ETH0.0015020732.09489336
Approve192364192024-02-15 22:51:11200 days ago1708037471IN
0x898d1DDe...d5cE22851
0 ETH0.0015663633.56330485
Approve192364032024-02-15 22:47:59200 days ago1708037279IN
0x898d1DDe...d5cE22851
0 ETH0.0017484837.35990113
Approve192363962024-02-15 22:46:23200 days ago1708037183IN
0x898d1DDe...d5cE22851
0 ETH0.0016538735.33837947
Approve192363922024-02-15 22:45:35200 days ago1708037135IN
0x898d1DDe...d5cE22851
0 ETH0.0017216436.78658518
Approve192363692024-02-15 22:40:47200 days ago1708036847IN
0x898d1DDe...d5cE22851
0 ETH0.0015830433.78166729
Approve192363452024-02-15 22:35:59200 days ago1708036559IN
0x898d1DDe...d5cE22851
0 ETH0.0016957936.23425328
Approve192363302024-02-15 22:32:59200 days ago1708036379IN
0x898d1DDe...d5cE22851
0 ETH0.0015045432.1477025
Approve192362922024-02-15 22:25:23200 days ago1708035923IN
0x898d1DDe...d5cE22851
0 ETH0.0017372237.11936833
Get Multiple Rew...192362832024-02-15 22:23:35200 days ago1708035815IN
0x898d1DDe...d5cE22851
0 ETH0.0162793436.87280187
Approve192362002024-02-15 22:06:23200 days ago1708034783IN
0x898d1DDe...d5cE22851
0 ETH0.0018219838.93042537
Approve192361872024-02-15 22:03:47200 days ago1708034627IN
0x898d1DDe...d5cE22851
0 ETH0.0017973438.35474049
Approve192361682024-02-15 21:59:47200 days ago1708034387IN
0x898d1DDe...d5cE22851
0 ETH0.0018944540.42713263
Approve192361682024-02-15 21:59:47200 days ago1708034387IN
0x898d1DDe...d5cE22851
0 ETH0.0019856342.42713263
Get Multiple Rew...192361572024-02-15 21:57:35200 days ago1708034255IN
0x898d1DDe...d5cE22851
0 ETH0.0141726430.86472537
Approve192361522024-02-15 21:56:35200 days ago1708034195IN
0x898d1DDe...d5cE22851
0 ETH0.0011865425.35297431
Transfer From192361482024-02-15 21:55:47200 days ago1708034147IN
0x898d1DDe...d5cE22851
0 ETH0.0051815128.92343018
Transfer From192361442024-02-15 21:54:59200 days ago1708034099IN
0x898d1DDe...d5cE22851
0 ETH0.0029334734.40014703
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
192359222024-02-15 21:10:23200 days ago1708031423
0x898d1DDe...d5cE22851
0.15 ETH
192359202024-02-15 21:09:59200 days ago1708031399
0x898d1DDe...d5cE22851
0.15 ETH
192359192024-02-15 21:09:47200 days ago1708031387
0x898d1DDe...d5cE22851
0.15 ETH
192359192024-02-15 21:09:47200 days ago1708031387
0x898d1DDe...d5cE22851
0.15 ETH
192359192024-02-15 21:09:47200 days ago1708031387
0x898d1DDe...d5cE22851
0.15 ETH
192359192024-02-15 21:09:47200 days ago1708031387
0x898d1DDe...d5cE22851
0.15 ETH
192359182024-02-15 21:09:35200 days ago1708031375
0x898d1DDe...d5cE22851
0.15 ETH
192359162024-02-15 21:09:11200 days ago1708031351
0x898d1DDe...d5cE22851
0.15 ETH
192359162024-02-15 21:09:11200 days ago1708031351
0x898d1DDe...d5cE22851
0.15 ETH
192359162024-02-15 21:09:11200 days ago1708031351
0x898d1DDe...d5cE22851
0.15 ETH
192359142024-02-15 21:08:47200 days ago1708031327
0x898d1DDe...d5cE22851
0.15 ETH
192359142024-02-15 21:08:47200 days ago1708031327
0x898d1DDe...d5cE22851
0.15 ETH
192359142024-02-15 21:08:47200 days ago1708031327
0x898d1DDe...d5cE22851
0.15 ETH
192359142024-02-15 21:08:47200 days ago1708031327
0x898d1DDe...d5cE22851
0.15 ETH
192359132024-02-15 21:08:35200 days ago1708031315
0x898d1DDe...d5cE22851
0.15 ETH
192359132024-02-15 21:08:35200 days ago1708031315
0x898d1DDe...d5cE22851
0.15 ETH
192359132024-02-15 21:08:35200 days ago1708031315
0x898d1DDe...d5cE22851
0.15 ETH
192359122024-02-15 21:08:23200 days ago1708031303
0x898d1DDe...d5cE22851
0.15 ETH
192359122024-02-15 21:08:23200 days ago1708031303
0x898d1DDe...d5cE22851
0.15 ETH
192359122024-02-15 21:08:23200 days ago1708031303
0x898d1DDe...d5cE22851
0.15 ETH
192359122024-02-15 21:08:23200 days ago1708031303
0x898d1DDe...d5cE22851
0.15 ETH
192359122024-02-15 21:08:23200 days ago1708031303
0x898d1DDe...d5cE22851
0.15 ETH
192359122024-02-15 21:08:23200 days ago1708031303
0x898d1DDe...d5cE22851
0.15 ETH
192359122024-02-15 21:08:23200 days ago1708031303
0x898d1DDe...d5cE22851
0.15 ETH
192359112024-02-15 21:08:11200 days ago1708031291
0x898d1DDe...d5cE22851
0.15 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Land

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
shanghai EvmVersion
File 1 of 7 : Land.sol
// https://farmland.build/
// https://twitter.com/landERC20721
// https://t.me/Land_Erc20721

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "./Metadata.sol";

import { WrappedLand } from "./WrappedLand.sol";

import {Emissions} from "./Emissions.sol";

interface Receiver {
  function onERC721Received(
    address _operator,
    address _from,
    uint256 _tokenId,
    bytes calldata _data
  ) external returns (bytes4);
}

interface Router {
  function WETH() external pure returns (address);
  function factory() external pure returns (address);
  function addLiquidityETH(
    address,
    uint256,
    uint256,
    uint256,
    address,
    uint256
  ) external payable returns (uint256, uint256, uint256);
}

interface Factory {
  function createPair(address, address) external returns (address);
}

contract Land is Emissions {
  uint256 private constant UINT_MAX = type(uint256).max;
  uint256 private constant TOTAL_SUPPLY = 256;
  uint256 private constant LIQUIDITY_TOKENS = 32;
  Router private constant ROUTER =
    Router(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);

  uint256 private constant M1 =
    0x5555555555555555555555555555555555555555555555555555555555555555;
  uint256 private constant M2 =
    0x3333333333333333333333333333333333333333333333333333333333333333;
  uint256 private constant M4 =
    0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;
  uint256 private constant H01 =
    0x0101010101010101010101010101010101010101010101010101010101010101;
  bytes32 private constant TRANSFER_TOPIC =
    keccak256(bytes("Transfer(address,address,uint256)"));
  bytes32 private constant APPROVAL_TOPIC =
    keccak256(bytes("Approval(address,address,uint256)"));

  uint256 public constant MINT_COST = 0.15 ether;
  uint256 public constant HOUSE_COST = 0.05 ether;

  uint8 public constant decimals = 0;

  struct User {
    bytes32 mask;
    mapping(address => uint256) allowance;
    mapping(address => bool) approved;
  }

  struct Info {
    bytes32 salt;
    address pair;
    address owner;
    Metadata metadata;
    mapping(address => User) users;
    mapping(uint256 => address) approved;
    address[] holders;
  }
  Info private info;

  mapping(bytes4 => bool) public supportsInterface;

  event Transfer(
    address indexed from,
    address indexed to,
    uint256 indexed tokenId
  );
  event ERC20Transfer(
    bytes32 indexed topic0,
    address indexed from,
    address indexed to,
    uint256 tokens
  ) anonymous;
  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 indexed tokenId
  );
  event ERC20Approval(
    bytes32 indexed topic0,
    address indexed owner,
    address indexed spender,
    uint256 tokens
  ) anonymous;
  event ApprovalForAll(
    address indexed owner,
    address indexed operator,
    bool approved
  );

  modifier _onlyOwner() {
    require(msg.sender == owner());
    _;
  }

  constructor() {
    info.owner = tx.origin;
    info.metadata = new Metadata();
    supportsInterface[0x01ffc9a7] = true; // ERC-165
    supportsInterface[0x80ac58cd] = true; // ERC-721
    supportsInterface[0x5b5e139f] = true; // Metadata
    info.salt = keccak256(
      abi.encodePacked("Salt:", blockhash(block.number - 1))
    );
  }

  function setOwner(address _owner) external _onlyOwner {
    info.owner = _owner;
  }

  function setMetadata(Metadata _metadata) external _onlyOwner {
    info.metadata = _metadata;
  }

  function initialize() external {
    require(pair() == address(0x0));

    address _this = address(this);
    info.users[_this].mask = bytes32(UINT_MAX);
    info.holders.push(_this);
    emit ERC20Transfer(TRANSFER_TOPIC, address(0x0), _this, TOTAL_SUPPLY);
    for (uint256 i = 0; i < TOTAL_SUPPLY; i++) {
      emit Transfer(address(0x0), _this, TOTAL_SUPPLY + i + 1);
    }
    _approveERC20(_this, address(ROUTER), LIQUIDITY_TOKENS);
    _transferERC20(_this, tx.origin, 32); // for wLAND LP
    _transferERC20(_this, msg.sender, 60); // for emissions
    _transferERC20(_this, owner(), 4); // developer tokens
  }

  function initLP() payable external {
    require(msg.value > 0);
    address _weth = ROUTER.WETH();
    address _this = address(this);
    info.pair = Factory(ROUTER.factory()).createPair(_weth, _this);
    ROUTER.addLiquidityETH{ value: _this.balance }(
      _this,
      LIQUIDITY_TOKENS,
      0,
      0,
      owner(),
      block.timestamp
    );
  }

  function mint() external payable {
    address _this = address(this);
    uint256 _available = balanceOf(_this);
    require(1 <= _available);
    uint256 _cost = 1 * MINT_COST;
    require(msg.value >= _cost);
    _transferERC20(_this, msg.sender, 1);
    payable(owner()).transfer(_cost);
    if (msg.value > _cost) {
      payable(msg.sender).transfer(msg.value - _cost);
    }
  }

  function addHouse(uint256 tokenId) external payable {
    uint256 currentCount = houseCount[tokenId];

    require(currentCount < 4, "MAX houses"); // max 4 houses
    require(msg.value >= HOUSE_COST);

    payable(owner()).transfer(HOUSE_COST);

    houseCount[tokenId]++;
    totalSupplyScaled++;

    if (msg.value > HOUSE_COST) {
      payable(msg.sender).transfer(msg.value - HOUSE_COST);
    }


  }

  function approve(address _spender, uint256 _tokens) external returns (bool) {
    if (_tokens > TOTAL_SUPPLY && _tokens <= 2 * TOTAL_SUPPLY) {
      _approveNFT(_spender, _tokens);
    } else {
      _approveERC20(msg.sender, _spender, _tokens);
    }
    return true;
  }

  function setApprovalForAll(address _operator, bool _approved) external {
    info.users[msg.sender].approved[_operator] = _approved;
    emit ApprovalForAll(msg.sender, _operator, _approved);
  }

  function transfer(address _to, uint256 _tokens) external returns (bool) {
    _transferERC20(msg.sender, _to, _tokens);
    return true;
  }

  function transferFrom(
    address _from,
    address _to,
    uint256 _tokens
  ) external returns (bool) {
    if (_tokens > TOTAL_SUPPLY && _tokens <= 2 * TOTAL_SUPPLY) {
      _transferNFT(_from, _to, _tokens);
    } else {
      uint256 _allowance = allowance(_from, msg.sender);
      require(_allowance >= _tokens);
      if (_allowance != UINT_MAX) {
        info.users[_from].allowance[msg.sender] -= _tokens;
      }
      _transferERC20(_from, _to, _tokens);
    }
    return true;
  }

  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 {
    _transferNFT(_from, _to, _tokenId);
    uint32 _size;
    assembly {
      _size := extcodesize(_to)
    }
    if (_size > 0) {
      require(
        Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) ==
          0x150b7a02
      );
    }
  }

  function bulkTransfer(address _to, uint256[] memory _tokenIds) external {
    _transferNFTs(_to, _tokenIds);
  }

  function owner() public view returns (address) {
    return info.owner;
  }

  function pair() public view returns (address) {
    return info.pair;
  }

  function holders() public view returns (address[] memory) {
    return info.holders;
  }

  function salt() external view returns (bytes32) {
    return info.salt;
  }

  function metadata() external view returns (address) {
    return address(info.metadata);
  }

  function name() external view returns (string memory) {
    return info.metadata.name();
  }

  function symbol() external view returns (string memory) {
    return info.metadata.symbol();
  }

  function tokenURI(uint256 _tokenId) public view returns (string memory) {
    return info.metadata.tokenURI(_tokenId, houseCount[_tokenId]);
  }

  function totalSupply() public pure returns (uint256) {
    return TOTAL_SUPPLY;
  }

  function maskOf(address _user) public view returns (bytes32) {
    return info.users[_user].mask;
  }

  function balanceOf(address _user) public view returns (uint256) {
    return _popcount(maskOf(_user));
  }

  function allowance(
    address _user,
    address _spender
  ) public view returns (uint256) {
    return info.users[_user].allowance[_spender];
  }

  function ownerOf(uint256 _tokenId) public view returns (address) {
    unchecked {
      require(_tokenId > TOTAL_SUPPLY && _tokenId <= 2 * TOTAL_SUPPLY);
      bytes32 _mask = bytes32(1 << (_tokenId - TOTAL_SUPPLY - 1));
      address[] memory _holders = holders();
      for (uint256 i = 0; i < _holders.length; i++) {
        if (maskOf(_holders[i]) & _mask == _mask) {
          return _holders[i];
        }
      }
      return address(0x0);
    }
  }

  function getApproved(uint256 _tokenId) public view returns (address) {
    require(_tokenId > TOTAL_SUPPLY && _tokenId <= 2 * TOTAL_SUPPLY);
    return info.approved[_tokenId];
  }

  function isApprovedForAll(
    address _owner,
    address _operator
  ) public view returns (bool) {
    return info.users[_owner].approved[_operator];
  }

  function getToken(
    uint256 _tokenId
  )
    public
    view
    returns (address tokenOwner, address approved, string memory uri, uint256 xCoord, uint256 yCoord)
  {
    return (ownerOf(_tokenId), getApproved(_tokenId), tokenURI(_tokenId), info.metadata.getX(_tokenId), info.metadata.getY(_tokenId));
  }

  function getTokens(
    uint256[] memory _tokenIds
  )
    public
    view
    returns (
      address[] memory owners,
      address[] memory approveds,
      string[] memory uris,
      uint256[] memory xCoords,
      uint256[] memory yCoords
    )
  {
    uint256 _length = _tokenIds.length;
    owners = new address[](_length);
    approveds = new address[](_length);
    uris = new string[](_length);
    xCoords = new uint256[](_length);
    yCoords = new uint256[](_length);
    for (uint256 i = 0; i < _length; i++) {
      (owners[i], approveds[i], uris[i], xCoords[i], yCoords[i]) = getToken(_tokenIds[i]);
    }
  }

  function _approveERC20(
    address _owner,
    address _spender,
    uint256 _tokens
  ) internal {
    info.users[_owner].allowance[_spender] = _tokens;
    emit ERC20Approval(APPROVAL_TOPIC, _owner, _spender, _tokens);
  }

  function _approveNFT(address _spender, uint256 _tokenId) internal {
    bytes32 _mask = bytes32(1 << (_tokenId - TOTAL_SUPPLY - 1));
    require(maskOf(msg.sender) & _mask == _mask);
    info.approved[_tokenId] = _spender;
    emit Approval(msg.sender, _spender, _tokenId);
  }

  function _transferERC20(
    address _from,
    address _to,
    uint256 _tokens
  ) internal {
    unchecked {
      bytes32 _mask;
      uint256 _pos = 0;
      uint256 _count = 0;
      uint256 _n = uint256(maskOf(_from));
      uint256[] memory _tokenIds = new uint256[](_tokens);
      while (_n > 0 && _count < _tokens) {
        if (_n & 1 == 1) {
          _mask |= bytes32(1 << _pos);
          _tokenIds[_count++] = TOTAL_SUPPLY + _pos + 1;
        }
        _pos++;
        _n >>= 1;
      }
      require(_count == _tokens);
      require(maskOf(_from) & _mask == _mask);
      _transfer(_from, _to, _mask, _tokenIds);
    }
  }

  function _transferNFT(address _from, address _to, uint256 _tokenId) internal {
    unchecked {
      require(_tokenId > TOTAL_SUPPLY && _tokenId <= 2 * TOTAL_SUPPLY);
      bytes32 _mask = bytes32(1 << (_tokenId - TOTAL_SUPPLY - 1));
      require(maskOf(_from) & _mask == _mask);
      require(
        msg.sender == _from ||
          msg.sender == getApproved(_tokenId) ||
          isApprovedForAll(_from, msg.sender)
      );
      uint256[] memory _tokenIds = new uint256[](1);
      _tokenIds[0] = _tokenId;
      _transfer(_from, _to, _mask, _tokenIds);
    }
  }

  function _transferNFTs(address _to, uint256[] memory _tokenIds) internal {
    unchecked {
      bytes32 _mask;
      for (uint256 i = 0; i < _tokenIds.length; i++) {
        _mask |= bytes32(1 << (_tokenIds[i] - TOTAL_SUPPLY - 1));
      }
      require(_popcount(_mask) == _tokenIds.length);
      require(maskOf(msg.sender) & _mask == _mask);
      _transfer(msg.sender, _to, _mask, _tokenIds);
    }
  }

  function _transfer(
    address _from,
    address _to,
    bytes32 _mask,
    uint256[] memory _tokenIds
  ) internal {
    unchecked {
      require(_tokenIds.length > 0);
      for (uint256 i = 0; i < _tokenIds.length; i++) {
        if (getApproved(_tokenIds[i]) != address(0x0)) {
          info.approved[_tokenIds[i]] = address(0x0);
          emit Approval(address(0x0), address(0x0), _tokenIds[i]);
        }
        emit Transfer(_from, _to, _tokenIds[i]);
      }
      info.users[_from].mask ^= _mask;
      bool _from0 = maskOf(_from) == 0x0;
      bool _to0 = maskOf(_to) == 0x0;
      info.users[_to].mask |= _mask;
      if (_from0) {
        uint256 _index;
        address[] memory _holders = holders();
        for (uint256 i = 0; i < _holders.length; i++) {
          if (_holders[i] == _from) {
            _index = i;
            break;
          }
        }
        if (_to0) {
          info.holders[_index] = _to;
        } else {
          info.holders[_index] = _holders[_holders.length - 1];
          info.holders.pop();
        }
      } else if (_to0) {
        info.holders.push(_to);
      }
      require(maskOf(_from) & maskOf(_to) == 0x0);
      emit ERC20Transfer(TRANSFER_TOPIC, _from, _to, _tokenIds.length);
    }
  }

  function _popcount(bytes32 _b) internal pure returns (uint256) {
    uint256 _n = uint256(_b);
    if (_n == UINT_MAX) {
      return 256;
    }
    unchecked {
      _n -= (_n >> 1) & M1;
      _n = (_n & M2) + ((_n >> 2) & M2);
      _n = (_n + (_n >> 4)) & M4;
      _n = (_n * H01) >> 248;
    }
    return _n;
  }

  function getAllData() public view returns (
      address[] memory owners,
      string[] memory uris,
      uint256[] memory xCoords,
      uint256[] memory yCoords,
      uint256[] memory tokenIdList
    ) {
    tokenIdList = new uint256[](256);
    for (uint256 i = 257; i < 513; i++) {
        tokenIdList[i - 257] = i;
    }

    (owners, , uris, xCoords, yCoords) = getTokens(tokenIdList);
    return (owners, uris, xCoords, yCoords, tokenIdList);
  }

  function getReward(uint256 _tokenId) public updateReward(_tokenId) {
      require(ownerOf(_tokenId) == msg.sender, "Not Owner");

      uint reward = rewards[_tokenId];

      if (reward > 0) {
          rewards[_tokenId] = 0;
          rewardsToken.transfer(msg.sender, reward);
      }
  }

  function getMultipleRewards(uint256[] calldata tokenIds) external {
      for (uint i = 0; i < tokenIds.length; i++) {
          getReward(tokenIds[i]);
      }
  }
}

contract Deploy {
  Land public immutable land;
  WrappedLand public immutable wLand;
  constructor() {
    // deploy Land
    land = new Land();
    land.initialize();

    // deploy Wrapped Land (wLAND)
    wLand = new WrappedLand(address(land));
    uint256 landBal = land.balanceOf(address(this));
    land.approve(address(wLand), type(uint256).max);
    wLand.wrap(landBal);
    uint256 wLandBal = wLand.balanceOf(address(this));

    // set reward token
    land.setRewardToken(address(wLand));
    land.setRewardsDuration(7 days);

    // add rewards
    wLand.transfer(address(land), wLandBal);
    land.notifyRewardAmount(wLandBal);
  }
}

File 2 of 7 : Metadata.sol
// https://farmland.build/
// https://twitter.com/landERC20721
// https://t.me/Land_Erc20721

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";

library Base64 {
  bytes internal constant TABLE =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

  /// @notice Encodes some bytes to the base64 representation
  function encode(bytes memory data) internal pure returns (string memory) {
    uint256 len = data.length;
    if (len == 0) return "";

    // multiply by 4/3 rounded up
    uint256 encodedLen = 4 * ((len + 2) / 3);

    // Add some extra buffer at the end
    bytes memory result = new bytes(encodedLen + 32);

    bytes memory table = TABLE;

    assembly {
      let tablePtr := add(table, 1)
      let resultPtr := add(result, 32)

      for {
        let i := 0
      } lt(i, len) {

      } {
        i := add(i, 3)
        let input := and(mload(add(data, i)), 0xffffff)

        let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
        out := shl(8, out)
        out := add(
          out,
          and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF)
        )
        out := shl(8, out)
        out := add(
          out,
          and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF)
        )
        out := shl(8, out)
        out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
        out := shl(224, out)

        mstore(resultPtr, out)

        resultPtr := add(resultPtr, 4)
      }

      switch mod(len, 3)
      case 1 {
        mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
      }
      case 2 {
        mstore(sub(resultPtr, 1), shl(248, 0x3d))
      }

      mstore(result, encodedLen)
    }

    return string(result);
  }
}

interface LAND {
  function salt() external view returns (bytes32);
}

contract Metadata {
  string public name = "Land";
  string public symbol = "LAND";

  LAND public immutable land;

  uint256 constant WIDTH = 16;
  uint256 constant HEIGHT = 16;


  constructor() {
    land = LAND(msg.sender);
  }

  function tokenURI(uint256 tokenId, uint256 _houseCount) external view returns (string memory) {
    tokenId = tokenId - 256;

    string memory fillColor;

    if (_houseCount == 0) {
      fillColor = "13fc03";
    } else if (_houseCount == 1) {
      fillColor = "f8fc03";
    } else if (_houseCount == 2) {
      fillColor = "fcad03";
    } else if (_houseCount == 3) {
      fillColor = "fc0303";
    } else if (_houseCount == 4) {
      fillColor = "d203fc";
    }

    string[17] memory parts;
    parts[
      0
    ] = string(abi.encodePacked('<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"><style>.base { font-family: monospace; font-size: 28px; }</style><rect width="100%" height="100%" fill="#', fillColor,'" /><text x="50%" y="50%" text-anchor="middle" fill="#648efa" class="base">('));

    parts[1] = Strings.toString(getX(tokenId));

    parts[2] = ",";

    parts[3] = Strings.toString(getY(tokenId));

    parts[4] = ")</text></svg>";

    string memory output = string(
      abi.encodePacked(parts[0], parts[1], parts[2], parts[3], parts[4])
    );

    string memory json = Base64.encode(
      bytes(
        string(
          abi.encodePacked(
            '{"name": "Land (',
            Strings.toString(getX(tokenId)),
            ",",
            Strings.toString(getY(tokenId)),
            ')", "description": "Land is stored on chain and represents a ',
            Strings.toString(WIDTH),
            "x",
            Strings.toString(HEIGHT),
            ' grid of land. Earn emissions by buying houses!", "image": "data:image/svg+xml;base64,',
            Base64.encode(bytes(output)),
            '"}'
          )
        )
      )
    );
    output = string(abi.encodePacked("data:application/json;base64,", json));

    return output;
  }

  function getX(uint256 tokenId) public pure returns (uint256) {
    return (tokenId - 1) % WIDTH;
  }

  function getY(uint256 tokenId) public pure returns (uint256) {
    return ((tokenId - 1) / HEIGHT) % HEIGHT;
  }
}

File 3 of 7 : WrappedLand.sol
// https://farmland.build/
// https://twitter.com/landERC20721
// https://t.me/Land_Erc20721

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

interface Callable {
  function tokenCallback(
    address _from,
    uint256 _tokens,
    bytes calldata _data
  ) external returns (bool);
}

interface ILand {
  function balanceOf(address) external view returns (uint256);
  function allowance(address, address) external view returns (uint256);
  function isApprovedForAll(address, address) external view returns (bool);
  function transfer(address _to, uint256 _tokens) external returns (bool);
  function transferFrom(
    address _from,
    address _to,
    uint256 _tokens
  ) external returns (bool);
}

contract WrappedLand {
  uint256 private constant UINT_MAX = type(uint256).max;

  ILand public immutable land;

  string public constant name = "Wrapped Land";
  string public constant symbol = "wLAND";
  uint8 public constant decimals = 18;

  struct User {
    uint256 balance;
    mapping(address => uint256) allowance;
  }

  struct Info {
    mapping(address => User) users;
  }
  Info private info;

  event Transfer(address indexed from, address indexed to, uint256 tokens);
  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 tokens
  );
  event Wrap(address indexed owner, uint256 tokens);
  event Unwrap(address indexed owner, uint256 tokens);

  constructor(address _land) {
    land = ILand(_land);
  }

  function wrap(uint256 _tokensOrTokenId) external {
    uint256 _balanceBefore = land.balanceOf(address(this));
    land.transferFrom(msg.sender, address(this), _tokensOrTokenId);
    uint256 _wrapped = land.balanceOf(address(this)) - _balanceBefore;
    require(_wrapped > 0);
    info.users[msg.sender].balance += _wrapped * 1e18;
    emit Transfer(address(0x0), msg.sender, _wrapped * 1e18);
    emit Wrap(msg.sender, _wrapped);
  }

  function unwrap(uint256 _tokens) external {
    require(_tokens > 0);
    require(balanceOf(msg.sender) >= _tokens * 1e18);
    info.users[msg.sender].balance -= _tokens * 1e18;
    land.transfer(msg.sender, _tokens);
    emit Transfer(msg.sender, address(0x0), _tokens * 1e18);
    emit Unwrap(msg.sender, _tokens);
  }

  function transfer(address _to, uint256 _tokens) external returns (bool) {
    return _transfer(msg.sender, _to, _tokens);
  }

  function approve(address _spender, uint256 _tokens) external returns (bool) {
    info.users[msg.sender].allowance[_spender] = _tokens;
    emit Approval(msg.sender, _spender, _tokens);
    return true;
  }

  function transferFrom(
    address _from,
    address _to,
    uint256 _tokens
  ) external returns (bool) {
    uint256 _allowance = allowance(_from, msg.sender);
    require(_allowance >= _tokens);
    if (_allowance != UINT_MAX) {
      info.users[_from].allowance[msg.sender] -= _tokens;
    }
    return _transfer(_from, _to, _tokens);
  }

  function transferAndCall(
    address _to,
    uint256 _tokens,
    bytes calldata _data
  ) external returns (bool) {
    _transfer(msg.sender, _to, _tokens);
    uint32 _size;
    assembly {
      _size := extcodesize(_to)
    }
    if (_size > 0) {
      require(Callable(_to).tokenCallback(msg.sender, _tokens, _data));
    }
    return true;
  }

  function totalSupply() public view returns (uint256) {
    return land.balanceOf(address(this)) * 1e18;
  }

  function balanceOf(address _user) public view returns (uint256) {
    return info.users[_user].balance;
  }

  function allowance(
    address _user,
    address _spender
  ) public view returns (uint256) {
    return info.users[_user].allowance[_spender];
  }

  function allInfoFor(
    address _user
  )
    external
    view
    returns (
      uint256 totalTokens,
      uint256 userLANDs,
      uint256 userAllowance,
      bool userApprovedForAll,
      uint256 userBalance
    )
  {
    totalTokens = totalSupply();
    userLANDs = land.balanceOf(_user);
    userAllowance = land.allowance(_user, address(this));
    userApprovedForAll = land.isApprovedForAll(_user, address(this));
    userBalance = balanceOf(_user);
  }

  function _transfer(
    address _from,
    address _to,
    uint256 _tokens
  ) internal returns (bool) {
    unchecked {
      require(balanceOf(_from) >= _tokens);
      info.users[_from].balance -= _tokens;
      info.users[_to].balance += _tokens;
      emit Transfer(_from, _to, _tokens);
      return true;
    }
  }
}

File 4 of 7 : Emissions.sol
// https://farmland.build/
// https://twitter.com/landERC20721
// https://t.me/Land_Erc20721

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Emissions {
    IERC20 public rewardsToken;

    address public ownerEmissions;

    // Duration of rewards to be paid out (in seconds)
    uint public duration;
    // Timestamp of when the rewards finish
    uint public finishAt;
    // Minimum of last updated time and reward finish time
    uint public updatedAt;
    // Reward to be paid out per second
    uint public rewardRate;
    // Sum of (reward rate * dt * 1e18 / total supply)
    uint public rewardPerTokenStored;
    // User address => rewardPerTokenStored
    mapping(uint256 => uint) public userRewardPerTokenPaid;
    // User address => rewards to be claimed
    mapping(uint256 => uint) public rewards;

    // Total staked
    uint public totalSupplyScaled = 256; // all LAND
    // User address => staked amount
    mapping(uint256 => uint) public balanceOfTokenId;

    // house
    mapping(uint256 tokenId => uint256) public houseCount;

    constructor() {
        ownerEmissions = msg.sender;
    }

    function setRewardToken(address _rewardToken) external onlyOwner {
        rewardsToken = IERC20(_rewardToken);
    }

    modifier onlyOwner() {
        require(msg.sender == ownerEmissions, "not authorized");
        _;
    }

    modifier updateReward(uint256 _tokenId) {
        rewardPerTokenStored = rewardPerToken();
        updatedAt = lastTimeRewardApplicable();

        if (_tokenId != 0) {
            rewards[_tokenId] = earned(_tokenId);
            userRewardPerTokenPaid[_tokenId] = rewardPerTokenStored;
        }

        _;
    }

    function lastTimeRewardApplicable() public view returns (uint) {
        return _min(finishAt, block.timestamp);
    }

    function rewardPerToken() public view returns (uint) {
        if (totalSupplyScaled == 0) {
            return rewardPerTokenStored;
        }

        return
            rewardPerTokenStored +
            (rewardRate * (lastTimeRewardApplicable() - updatedAt) * 1e18) /
            totalSupplyScaled;
    }

    function earned(uint256 _tokenId) public view returns (uint) {
        return
            (((1 + houseCount[_tokenId]) *
                (rewardPerToken() - userRewardPerTokenPaid[_tokenId])) / 1e18) +
            rewards[_tokenId];
    }

    function setRewardsDuration(uint _duration) external onlyOwner {
        require(finishAt < block.timestamp, "reward duration not finished");
        duration = _duration;
    }

    function notifyRewardAmount(
        uint _amount
    ) external onlyOwner updateReward(0) {
        if (block.timestamp >= finishAt) {
            rewardRate = _amount / duration;
        } else {
            uint remainingRewards = (finishAt - block.timestamp) * rewardRate;
            rewardRate = (_amount + remainingRewards) / duration;
        }

        require(rewardRate > 0, "reward rate = 0");
        require(
            rewardRate * duration <= rewardsToken.balanceOf(address(this)),
            "reward amount > balance"
        );

        finishAt = block.timestamp + duration;
        updatedAt = block.timestamp;
    }

    function _min(uint x, uint y) private pure returns (uint) {
        return x <= y ? x : y;
    }
}

interface IERC20 {
    function totalSupply() external view returns (uint);

    function balanceOf(address account) external view returns (uint);

    function transfer(address recipient, uint amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}

File 5 of 7 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        uint256 localValue = value;
        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_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
     * representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 6 of 7 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

File 7 of 7 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"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":true,"inputs":[{"indexed":true,"internalType":"bytes32","name":"topic0","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"ERC20Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes32","name":"topic0","type":"bytes32"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"ERC20Transfer","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":"HOUSE_COST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_COST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"addHouse","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOfTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"bulkTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finishAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllData","outputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"string[]","name":"uris","type":"string[]"},{"internalType":"uint256[]","name":"xCoords","type":"uint256[]"},{"internalType":"uint256[]","name":"yCoords","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIdList","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"getMultipleRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getToken","outputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"address","name":"approved","type":"address"},{"internalType":"string","name":"uri","type":"string"},{"internalType":"uint256","name":"xCoord","type":"uint256"},{"internalType":"uint256","name":"yCoord","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"getTokens","outputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"address[]","name":"approveds","type":"address[]"},{"internalType":"string[]","name":"uris","type":"string[]"},{"internalType":"uint256[]","name":"xCoords","type":"uint256[]"},{"internalType":"uint256[]","name":"yCoords","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holders","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"houseCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initLP","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"maskOf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadata","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerEmissions","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","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":[],"name":"salt","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Metadata","name":"_metadata","type":"address"}],"name":"setMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"}],"name":"setRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"setRewardsDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupplyScaled","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updatedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405261010060095534801562000016575f80fd5b50600180546001600160a01b03199081163317909155600e80549091163217905560405162000045906200015b565b604051809103905ff0801580156200005f573d5f803e3d5ffd5b50600f80546001600160a01b0319166001600160a01b039290921691909117905560136020527f317681100331673b27c2499894e78912f138ae85f2dd790e454ff96a89cf2d77805460ff1990811660019081179092557f5829b1f18259a9cdcd4268c3b072804d2f8e3dedbb1b883db1fa2055bb26d84f8054821683179055635b5e139f60e01b5f527f65cb089fa41783e5af12e88573d882f263c09532a373334f0b809825d5a904ab8054909116821790556200011f904362000169565b6040516429b0b63a1d60d91b60208201529040602582015260450160408051601f198184030181529190528051602090910120600c556200018f565b610e888062002feb83390190565b818103818111156200018957634e487b7160e01b5f52601160045260245ffd5b92915050565b612e4e806200019d5f395ff3fe608060405260043610610341575f3560e01c80638129fc1c116101bd578063c87b56dd116100f2578063de85b4fe11610092578063e985e9c51161006d578063e985e9c514610981578063f301af42146109cc578063f3cb8385146109f7578063f732ece314610a16575f80fd5b8063de85b4fe14610911578063df136d651461093c578063e4b50cb814610951575f80fd5b8063d1af0c7d116100cd578063d1af0c7d14610877578063d28a476114610895578063d7629fcc146108b4578063dd62ed3e146108c9575f80fd5b8063c87b56dd14610825578063cc1a378f14610844578063cd3daf9d14610863575f80fd5b8063a86ba1021161015d578063ab80627811610138578063ab806278146107b8578063b88d4fde146107d7578063bfa0b133146107f6578063c662e4811461080a575f80fd5b8063a86ba1021461075d578063a8aa1b311461077c578063a9059cbb14610799575f80fd5b80638da5cb5b116101985780638da5cb5b146106e257806395d89b41146106ff5780639839caa714610713578063a22cb4651461073e575f80fd5b80638129fc1c1461068e5780638188f71c146106a25780638aee8127146106c3575f80fd5b806332ba0a1e1161029357806367d3b4881161023357806370a082311161020e57806370a08231146106315780637519ab50146106505780637b0a47ee1461066557806380faa57d1461067a575f80fd5b806367d3b488146105e95780636c6f858b146105fe5780636e34e91d14610629575f80fd5b80633debce301161026e5780633debce301461057257806342842e0e1461058c5780634d6ed8c4146105ab5780636352211e146105ca575f80fd5b806332ba0a1e14610506578063392f37e9146105365780633c6b16ab14610553575f80fd5b806313af4035116102fe57806323b872dd116102d957806323b872dd1461047e5780632497ab151461049d5780632d10fa28146104bc578063313ce567146104e1575f80fd5b806313af40351461042c57806318160ddd1461044b5780631c4b774b1461045f575f80fd5b806301ffc9a71461034557806306fdde0314610388578063081812fc146103a9578063095ea7b3146103e05780630fb5a6b4146103ff5780631249c58b14610422575b5f80fd5b348015610350575f80fd5b5061037361035f3660046125ee565b60136020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b348015610393575f80fd5b5061039c610a29565b60405161037f9190612656565b3480156103b4575f80fd5b506103c86103c3366004612668565b610a9c565b6040516001600160a01b03909116815260200161037f565b3480156103eb575f80fd5b506103736103fa366004612693565b610add565b34801561040a575f80fd5b5061041460025481565b60405190815260200161037f565b61042a610b24565b005b348015610437575f80fd5b5061042a6104463660046126bd565b610be6565b348015610456575f80fd5b50610100610414565b34801561046a575f80fd5b5061042a610479366004612668565b610c1e565b348015610489575f80fd5b506103736104983660046126d8565b610d4b565b3480156104a8575f80fd5b506104146104b73660046126bd565b610e0a565b3480156104c7575f80fd5b506104d0610e24565b60405161037f9594939291906127d9565b3480156104ec575f80fd5b506104f45f81565b60405160ff909116815260200161037f565b348015610511575f80fd5b50610525610520366004612905565b610eb6565b60405161037f95949392919061293e565b348015610541575f80fd5b50600f546001600160a01b03166103c8565b34801561055e575f80fd5b5061042a61056d366004612668565b611107565b34801561057d575f80fd5b5061041466b1a2bc2ec5000081565b348015610597575f80fd5b5061042a6105a63660046126d8565b6112f3565b3480156105b6575f80fd5b506104146105c5366004612668565b61130d565b3480156105d5575f80fd5b506103c86105e4366004612668565b611379565b3480156105f4575f80fd5b5061041460035481565b348015610609575f80fd5b50610414610618366004612668565b60076020525f908152604090205481565b61042a611414565b34801561063c575f80fd5b5061041461064b3660046126bd565b611667565b34801561065b575f80fd5b5061041460045481565b348015610670575f80fd5b5061041460055481565b348015610685575f80fd5b50610414611679565b348015610699575f80fd5b5061042a611686565b3480156106ad575f80fd5b506106b66117fb565b60405161037f9190612976565b3480156106ce575f80fd5b5061042a6106dd3660046126bd565b61185e565b3480156106ed575f80fd5b50600e546001600160a01b03166103c8565b34801561070a575f80fd5b5061039c6118a9565b34801561071e575f80fd5b5061041461072d366004612668565b600a6020525f908152604090205481565b348015610749575f80fd5b5061042a610758366004612995565b6118f0565b348015610768575f80fd5b5061042a6107773660046129cc565b61195f565b348015610787575f80fd5b50600d546001600160a01b03166103c8565b3480156107a4575f80fd5b506103736107b3366004612693565b61199c565b3480156107c3575f80fd5b506001546103c8906001600160a01b031681565b3480156107e2575f80fd5b5061042a6107f1366004612a60565b6119a8565b348015610801575f80fd5b50600c54610414565b348015610815575f80fd5b50610414670214e8348c4f000081565b348015610830575f80fd5b5061039c61083f366004612668565b611a4e565b34801561084f575f80fd5b5061042a61085e366004612668565b611ad8565b34801561086e575f80fd5b50610414611b58565b348015610882575f80fd5b505f546103c8906001600160a01b031681565b3480156108a0575f80fd5b5061042a6108af366004612b07565b611bb7565b3480156108bf575f80fd5b5061041460095481565b3480156108d4575f80fd5b506104146108e3366004612b53565b6001600160a01b039182165f9081526010602090815260408083209390941682526001909201909152205490565b34801561091c575f80fd5b5061041461092b366004612668565b600b6020525f908152604090205481565b348015610947575f80fd5b5061041460065481565b34801561095c575f80fd5b5061097061096b366004612668565b611bc5565b60405161037f959493929190612b7f565b34801561098c575f80fd5b5061037361099b366004612b53565b6001600160a01b039182165f9081526010602090815260408083209390941682526002909201909152205460ff1690565b3480156109d7575f80fd5b506104146109e6366004612668565b60086020525f908152604090205481565b348015610a02575f80fd5b5061042a610a113660046126bd565b611cce565b61042a610a24366004612668565b611d06565b600f54604080516306fdde0360e01b815290516060926001600160a01b0316916306fdde03916004808301925f9291908290030181865afa158015610a70573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a979190810190612bbe565b905090565b5f61010082118015610aba5750610ab66101006002612c43565b8211155b610ac2575f80fd5b505f908152601160205260409020546001600160a01b031690565b5f61010082118015610afb5750610af76101006002612c43565b8211155b15610b0f57610b0a8383611e19565b610b1a565b610b1a338484611ea6565b5060015b92915050565b305f610b2f82611667565b90508060011115610b3e575f80fd5b5f610b52670214e8348c4f00006001612c43565b905080341015610b60575f80fd5b610b6c83336001611f0f565b600e546040516001600160a01b039091169082156108fc029083905f818181858888f19350505050158015610ba3573d5f803e3d5ffd5b5080341115610be157336108fc610bba8334612c5a565b6040518115909202915f818181858888f19350505050158015610bdf573d5f803e3d5ffd5b505b505050565b600e546001600160a01b03163314610bfc575f80fd5b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b80610c27611b58565b600655610c32611679565b6004558015610c6557610c448161130d565b5f828152600860209081526040808320939093556006546007909152919020555b33610c6f83611379565b6001600160a01b031614610cb65760405162461bcd60e51b81526020600482015260096024820152682737ba1027bbb732b960b91b60448201526064015b60405180910390fd5b5f828152600860205260409020548015610be1575f838152600860205260408082208290559054905163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015610d27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bdf9190612c6d565b5f61010082118015610d695750610d656101006002612c43565b8211155b15610d7e57610d79848484611ffb565b610e00565b6001600160a01b0384165f90815260106020908152604080832033845260010190915290205482811015610db0575f80fd5b5f198114610df3576001600160a01b0385165f90815260106020908152604080832033845260010190915281208054859290610ded908490612c5a565b90915550505b610dfe858585611f0f565b505b5060019392505050565b6001600160a01b03165f9081526010602052604090205490565b604080516101008082526120208201909252606091829182918291829160208201612000803683370190505090506101015b610201811015610e9b578082610e6e61010183612c5a565b81518110610e7e57610e7e612c88565b602090810291909101015280610e9381612c9c565b915050610e56565b50610ea581610eb6565b939991985096509194509192509050565b60608060608060605f86519050806001600160401b03811115610edb57610edb612845565b604051908082528060200260200182016040528015610f04578160200160208202803683370190505b509550806001600160401b03811115610f1f57610f1f612845565b604051908082528060200260200182016040528015610f48578160200160208202803683370190505b509450806001600160401b03811115610f6357610f63612845565b604051908082528060200260200182016040528015610f9657816020015b6060815260200190600190039081610f815790505b509350806001600160401b03811115610fb157610fb1612845565b604051908082528060200260200182016040528015610fda578160200160208202803683370190505b509250806001600160401b03811115610ff557610ff5612845565b60405190808252806020026020018201604052801561101e578160200160208202803683370190505b5091505f5b818110156110fc5761104d88828151811061104057611040612c88565b6020026020010151611bc5565b8b868151811061105f5761105f612c88565b602002602001018b878151811061107857611078612c88565b602002602001018b888151811061109157611091612c88565b602002602001018b89815181106110aa576110aa612c88565b602002602001018b8a815181106110c3576110c3612c88565b602090810291909101019490945293909252929091526001600160a01b03928316905291169052806110f481612c9c565b915050611023565b505091939590929450565b6001546001600160a01b031633146111315760405162461bcd60e51b8152600401610cad90612cb4565b5f61113a611b58565b600655611145611679565b6004558015611178576111578161130d565b5f828152600860209081526040808320939093556006546007909152919020555b60035442106111965760025461118e9083612cdc565b6005556111d1565b5f600554426003546111a89190612c5a565b6111b29190612c43565b6002549091506111c28285612cfb565b6111cc9190612cdc565b600555505b5f600554116112145760405162461bcd60e51b815260206004820152600f60248201526e07265776172642072617465203d203608c1b6044820152606401610cad565b5f546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611259573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061127d9190612d0e565b60025460055461128d9190612c43565b11156112db5760405162461bcd60e51b815260206004820152601760248201527f72657761726420616d6f756e74203e2062616c616e63650000000000000000006044820152606401610cad565b6002546112e89042612cfb565b600355505042600455565b610be183838360405180602001604052805f8152506119a8565b5f818152600860209081526040808320546007909252822054670de0b6b3a764000090611338611b58565b6113429190612c5a565b5f858152600b602052604090205461135b906001612cfb565b6113659190612c43565b61136f9190612cdc565b610b1e9190612cfb565b5f6101008211801561138d57506102008211155b611395575f80fd5b60016101001983011b5f6113a76117fb565b90505f5b815181101561140a5782836113d88484815181106113cb576113cb612c88565b6020026020010151610e0a565b1603611402578181815181106113f0576113f0612c88565b60200260200101519350505050919050565b6001016113ab565b505f949350505050565b5f341161141f575f80fd5b5f737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611470573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114949190612d25565b90505f309050737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ea573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061150e9190612d25565b6040516364e329cb60e11b81526001600160a01b0384811660048301528381166024830152919091169063c9c65396906044016020604051808303815f875af115801561155d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115819190612d25565b600d80546001600160a01b039283166001600160a01b0319909116179055737a250d5630b4cf539739df2c5dacb4c659f2488d9063f305d719908316318360205f806115d5600e546001600160a01b031690565b60405160e088901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094526044840192909252606483015290911660848201524260a482015260c40160606040518083038185885af115801561163b573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906116609190612d40565b5050505050565b5f610b1e61167483610e0a565b6120e8565b5f610a97600354426121a5565b5f611699600d546001600160a01b031690565b6001600160a01b0316146116ab575f80fd5b305f8181526010602090815260408083205f199055601280546001810182559084527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b031916851790558051606081019091526021808252849392612df8908301398051906020012061010060405161173091815260200190565b60405180910390a35f5b6101008110156117a25761175081610100612cfb565b61175b906001612cfb565b6040516001600160a01b038416905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a48061179a81612c9c565b91505061173a565b506117c381737a250d5630b4cf539739df2c5dacb4c659f2488d6020611ea6565b6117cf81326020611f0f565b6117db8133603c611f0f565b6117f8816117f1600e546001600160a01b031690565b6004611f0f565b50565b6060600c60060180548060200260200160405190810160405280929190818152602001828054801561185457602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611836575b5050505050905090565b6001546001600160a01b031633146118885760405162461bcd60e51b8152600401610cad90612cb4565b5f80546001600160a01b0319166001600160a01b0392909216919091179055565b600f54604080516395d89b4160e01b815290516060926001600160a01b0316916395d89b41916004808301925f9291908290030181865afa158015610a70573d5f803e3d5ffd5b335f8181526010602090815260408083206001600160a01b0387168085526002909101835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b5f5b81811015610be15761198a83838381811061197e5761197e612c88565b90506020020135610c1e565b8061199481612c9c565b915050611961565b5f610b1a338484611f0f565b6119b3848484611ffb565b823b63ffffffff81161561166057604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906119f3903390899088908890600401612d6b565b6020604051808303815f875af1158015611a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a339190612da7565b6001600160e01b03191663150b7a0260e01b14611660575f80fd5b600f545f828152600b6020526040908190205490516392cb829d60e01b81526060926001600160a01b0316916392cb829d91611a97918691600401918252602082015260400190565b5f60405180830381865afa158015611ab1573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b1e9190810190612bbe565b6001546001600160a01b03163314611b025760405162461bcd60e51b8152600401610cad90612cb4565b4260035410611b535760405162461bcd60e51b815260206004820152601c60248201527f726577617264206475726174696f6e206e6f742066696e6973686564000000006044820152606401610cad565b600255565b5f6009545f03611b69575060065490565b600954600454611b77611679565b611b819190612c5a565b600554611b8e9190612c43565b611ba090670de0b6b3a7640000612c43565b611baa9190612cdc565b600654610a979190612cfb565b611bc182826121bd565b5050565b5f8060605f80611bd486611379565b611bdd87610a9c565b611be688611a4e565b600f5460405163472e5afb60e11b8152600481018b90526001600160a01b0390911690638e5cb5f690602401602060405180830381865afa158015611c2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c519190612d0e565b600f5460405163845a469760e01b8152600481018c90526001600160a01b039091169063845a469790602401602060405180830381865afa158015611c98573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cbc9190612d0e565b939a9299509097509550909350915050565b600e546001600160a01b03163314611ce4575f80fd5b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b5f818152600b602052604090205460048110611d515760405162461bcd60e51b815260206004820152600a6024820152694d415820686f7573657360b01b6044820152606401610cad565b66b1a2bc2ec50000341015611d64575f80fd5b600e546040516001600160a01b03909116905f9066b1a2bc2ec500009082818181858883f19350505050158015611d9d573d5f803e3d5ffd5b505f828152600b60205260408120805491611db783612c9c565b909155505060098054905f611dcb83612c9c565b919050555066b1a2bc2ec50000341115611bc157336108fc611df466b1a2bc2ec5000034612c5a565b6040518115909202915f818181858888f19350505050158015610be1573d5f803e3d5ffd5b5f6001611e2861010084612c5a565b611e329190612c5a565b6001901b90508080611e4333610e0a565b1614611e4d575f80fd5b5f8281526011602052604080822080546001600160a01b0319166001600160a01b0387169081179091559051849233917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a4505050565b6001600160a01b038084165f8181526010602090815260408083209487168084526001909501825291829020859055815160608101909252602180835290612dd7908301398051906020012083604051611f0291815260200190565b60405180910390a3505050565b5f808080611f1c87610e0a565b90505f856001600160401b03811115611f3757611f37612845565b604051908082528060200260200182016040528015611f60578160200160208202803683370190505b5090505b5f82118015611f7257508583105b15611fc55781600116600103611fb5578051600180861b96909617958401936101018601918391908110611fa857611fa8612c88565b6020026020010181815250505b6001938401939190911c90611f64565b858314611fd0575f80fd5b8485611fdb8a610e0a565b1614611fe5575f80fd5b611ff188888784612233565b5050505050505050565b6101008111801561200e57506102008111155b612016575f80fd5b60016101001982011b808061202a86610e0a565b1614612034575f80fd5b336001600160a01b0385161480612064575061204f82610a9c565b6001600160a01b0316336001600160a01b0316145b8061209457506001600160a01b0384165f90815260106020908152604080832033845260020190915290205460ff165b61209c575f80fd5b6040805160018082528183019092525f916020808301908036833701905050905082815f815181106120d0576120d0612c88565b60200260200101818152505061166085858484612233565b5f81600181016120fc575061010092915050565b7f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f5555555555555555555555555555555555555555555555555555555555555555600183901c16909103600281901c7f3333333333333333333333333333333333333333333333333333333333333333908116911601600481901c01167f01010101010101010101010101010101010101010101010101010101010101010260f81c92915050565b5f818311156121b457816121b6565b825b9392505050565b5f805b82518110156122015760016101008483815181106121e0576121e0612c88565b602002602001015103036001901b5f1b8217915080806001019150506121c0565b50815161220d826120e8565b14612216575f80fd5b808161222133610e0a565b161461222b575f80fd5b610be1338483855b5f81511161223f575f80fd5b5f5b8151811015612381575f6001600160a01b031661227683838151811061226957612269612c88565b6020026020010151610a9c565b6001600160a01b03161461231f575f600c6005015f84848151811061229d5761229d612c88565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508181815181106122e7576122e7612c88565b60209081029190910101516040515f9081907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908290a45b81818151811061233157612331612c88565b6020026020010151846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4600101612241565b506001600160a01b0384165f9081526010602052604081208054841890556123a885610e0a565b1590505f6123b585610e0a565b6001600160a01b0386165f9081526010602052604090208054861790551590508115612517575f806123e56117fb565b90505f5b815181101561243457886001600160a01b031682828151811061240e5761240e612c88565b60200260200101516001600160a01b03160361242c57809250612434565b6001016123e9565b5082156124825786600c600601838154811061245257612452612c88565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550612510565b8060018251038151811061249857612498612c88565b6020026020010151600c60060183815481106124b6576124b6612c88565b5f91825260209091200180546001600160a01b0319166001600160a01b039290921691909117905560128054806124ef576124ef612dc2565b5f8281526020902081015f1990810180546001600160a01b03191690550190555b5050612568565b801561256857601280546001810182555f919091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b0319166001600160a01b0387161790555b61257185610e0a565b61257a87610e0a565b1615612584575f80fd5b846001600160a01b0316866001600160a01b0316604051806060016040528060218152602001612df8602191398051906020012085516040516125c991815260200190565b60405180910390a3505050505050565b6001600160e01b0319811681146117f8575f80fd5b5f602082840312156125fe575f80fd5b81356121b6816125d9565b5f5b8381101561262357818101518382015260200161260b565b50505f910152565b5f8151808452612642816020860160208601612609565b601f01601f19169290920160200192915050565b602081525f6121b6602083018461262b565b5f60208284031215612678575f80fd5b5035919050565b6001600160a01b03811681146117f8575f80fd5b5f80604083850312156126a4575f80fd5b82356126af8161267f565b946020939093013593505050565b5f602082840312156126cd575f80fd5b81356121b68161267f565b5f805f606084860312156126ea575f80fd5b83356126f58161267f565b925060208401356127058161267f565b929592945050506040919091013590565b5f8151808452602080850194508084015f5b8381101561274d5781516001600160a01b031687529582019590820190600101612728565b509495945050505050565b5f81518084526020808501808196508360051b810191508286015f5b8581101561279e57828403895261278c84835161262b565b98850198935090840190600101612774565b5091979650505050505050565b5f8151808452602080850194508084015f5b8381101561274d578151875295820195908201906001016127bd565b60a081525f6127eb60a0830188612716565b82810360208401526127fd8188612758565b9050828103604084015261281181876127ab565b9050828103606084015261282581866127ab565b9050828103608084015261283981856127ab565b98975050505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561288157612881612845565b604052919050565b5f82601f830112612898575f80fd5b813560206001600160401b038211156128b3576128b3612845565b8160051b6128c2828201612859565b92835284810182019282810190878511156128db575f80fd5b83870192505b848310156128fa578235825291830191908301906128e1565b979650505050505050565b5f60208284031215612915575f80fd5b81356001600160401b0381111561292a575f80fd5b61293684828501612889565b949350505050565b60a081525f61295060a0830188612716565b82810360208401526129628188612716565b905082810360408401526128118187612758565b602081525f6121b66020830184612716565b80151581146117f8575f80fd5b5f80604083850312156129a6575f80fd5b82356129b18161267f565b915060208301356129c181612988565b809150509250929050565b5f80602083850312156129dd575f80fd5b82356001600160401b03808211156129f3575f80fd5b818501915085601f830112612a06575f80fd5b813581811115612a14575f80fd5b8660208260051b8501011115612a28575f80fd5b60209290920196919550909350505050565b5f6001600160401b03821115612a5257612a52612845565b50601f01601f191660200190565b5f805f8060808587031215612a73575f80fd5b8435612a7e8161267f565b93506020850135612a8e8161267f565b92506040850135915060608501356001600160401b03811115612aaf575f80fd5b8501601f81018713612abf575f80fd5b8035612ad2612acd82612a3a565b612859565b818152886020838501011115612ae6575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f8060408385031215612b18575f80fd5b8235612b238161267f565b915060208301356001600160401b03811115612b3d575f80fd5b612b4985828601612889565b9150509250929050565b5f8060408385031215612b64575f80fd5b8235612b6f8161267f565b915060208301356129c18161267f565b6001600160a01b0386811682528516602082015260a0604082018190525f90612baa9083018661262b565b606083019490945250608001529392505050565b5f60208284031215612bce575f80fd5b81516001600160401b03811115612be3575f80fd5b8201601f81018413612bf3575f80fd5b8051612c01612acd82612a3a565b818152856020838501011115612c15575f80fd5b612c26826020830160208601612609565b95945050505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610b1e57610b1e612c2f565b81810381811115610b1e57610b1e612c2f565b5f60208284031215612c7d575f80fd5b81516121b681612988565b634e487b7160e01b5f52603260045260245ffd5b5f60018201612cad57612cad612c2f565b5060010190565b6020808252600e908201526d1b9bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b5f82612cf657634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610b1e57610b1e612c2f565b5f60208284031215612d1e575f80fd5b5051919050565b5f60208284031215612d35575f80fd5b81516121b68161267f565b5f805f60608486031215612d52575f80fd5b8351925060208401519150604084015190509250925092565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90612d9d9083018461262b565b9695505050505050565b5f60208284031215612db7575f80fd5b81516121b6816125d9565b634e487b7160e01b5f52603160045260245ffdfe417070726f76616c28616464726573732c616464726573732c75696e74323536295472616e7366657228616464726573732c616464726573732c75696e7432353629a2646970667358221220996a5d12f0068519972669cafd3c9e9deb459dd2e2385f309056875232d05e4a64736f6c6343000814003360e0604052600460a09081526313185b9960e21b60c0525f9062000024908262000107565b506040805180820190915260048152631310539160e21b60208201526001906200004f908262000107565b503480156200005c575f80fd5b5033608052620001cf565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200009057607f821691505b602082108103620000af57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000102575f81815260208120601f850160051c81016020861015620000dd5750805b601f850160051c820191505b81811015620000fe57828155600101620000e9565b5050505b505050565b81516001600160401b0381111562000123576200012362000067565b6200013b816200013484546200007b565b84620000b5565b602080601f83116001811462000171575f8415620001595750858301515b5f19600386901b1c1916600185901b178555620000fe565b5f85815260208120601f198616915b82811015620001a15788860151825594840194600190910190840162000180565b5085821015620001bf57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b608051610ca1620001e75f395f60a80152610ca15ff3fe608060405234801561000f575f80fd5b5060043610610060575f3560e01c806306fdde0314610064578063845a4697146100825780638c980129146100a35780638e5cb5f6146100e257806392cb829d146100f557806395d89b4114610108575b5f80fd5b61006c610110565b604051610079919061073c565b60405180910390f35b61009561009036600461076e565b61019b565b604051908152602001610079565b6100ca7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610079565b6100956100f036600461076e565b6101c4565b61006c610103366004610785565b6101d2565b61006c61041b565b5f805461011c906107a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610148906107a5565b80156101935780601f1061016a57610100808354040283529160200191610193565b820191905f5260205f20905b81548152906001019060200180831161017657829003601f168201915b505050505081565b5f6010806101aa6001856107f1565b6101b49190610818565b6101be919061082b565b92915050565b5f60106101b46001846107f1565b60606101e0610100846107f1565b92506060825f0361020e575060408051808201909152600681526531336663303360d01b60208201526102b6565b82600103610239575060408051808201909152600681526566386663303360d01b60208201526102b6565b82600203610264575060408051808201909152600681526566636164303360d01b60208201526102b6565b8260030361028f575060408051808201909152600681526566633033303360d01b60208201526102b6565b826004036102b6575060408051808201909152600681526564323033666360d01b60208201525b6102be6106f2565b816040516020016102cf9190610859565b60408051808303601f1901815291905281526102f26102ed866101c4565b610428565b60208281019190915260408051808201825260018152600b60fa1b928101929092528201526103236102ed8661019b565b60608201908152604080518082018252600e81526d149e17ba32bc3a1f1e17b9bb339f60911b6020808301919091526080850182905284518186015184870151955194515f9661037b969395929490939291016109d3565b60405160208183030381529060405290505f6103ed61039c6102ed896101c4565b6103a86102ed8a61019b565b6103b26010610428565b6103bc6010610428565b6103c5876104b8565b6040516020016103d9959493929190610a3d565b6040516020818303038152906040526104b8565b9050806040516020016104009190610ba9565b60408051808303601f19018152919052979650505050505050565b6001805461011c906107a5565b60605f6104348361061b565b60010190505f8167ffffffffffffffff81111561045357610453610bed565b6040519080825280601f01601f19166020018201604052801561047d576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461048757509392505050565b80516060905f8190036104da57505060408051602081019091525f8152919050565b5f60036104e8836002610c01565b6104f29190610818565b6104fd906004610c14565b90505f61050b826020610c01565b67ffffffffffffffff81111561052357610523610bed565b6040519080825280601f01601f19166020018201604052801561054d576020820181803683370190505b5090505f604051806060016040528060408152602001610c2c60409139905060018101602083015f5b868110156105d7576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b835260049092019101610576565b5060038606600181146105f157600281146106025761060d565b613d3d60f01b60011983015261060d565b603d60f81b5f198301525b505050918152949350505050565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106106595772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610685576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106106a357662386f26fc10000830492506010015b6305f5e10083106106bb576305f5e100830492506008015b61271083106106cf57612710830492506004015b606483106106e1576064830492506002015b600a83106101be5760010192915050565b6040518061022001604052806011905b60608152602001906001900390816107025790505090565b5f5b8381101561073457818101518382015260200161071c565b50505f910152565b602081525f825180602084015261075a81604085016020870161071a565b601f01601f19169190910160400192915050565b5f6020828403121561077e575f80fd5b5035919050565b5f8060408385031215610796575f80fd5b50508035926020909101359150565b600181811c908216806107b957607f821691505b6020821081036107d757634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156101be576101be6107dd565b634e487b7160e01b5f52601260045260245ffd5b5f8261082657610826610804565b500490565b5f8261083957610839610804565b500690565b5f815161084f81856020860161071a565b9290920192915050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081527f30302f73766722207072657365727665417370656374526174696f3d22784d6960208201527f6e594d696e206d656574222076696577426f783d22302030203335302033353060408201527f223e3c7374796c653e2e62617365207b20666f6e742d66616d696c793a206d6f60608201527f6e6f73706163653b20666f6e742d73697a653a20323870783b207d3c2f73747960808201527f6c653e3c726563742077696474683d223130302522206865696768743d22313060a08201526a3025222066696c6c3d222360a81b60c08201525f82516109628160cb85016020870161071a565b7f22202f3e3c7465787420783d223530252220793d223530252220746578742d6160cb9390910192830152507f6e63686f723d226d6964646c65222066696c6c3d22233634386566612220636c60eb8201526b0c2e6e67a44c4c2e6ca447c560a31b61010b82015261011701919050565b5f86516109e4818460208b0161071a565b8651908301906109f8818360208b0161071a565b8651910190610a0b818360208a0161071a565b8551910190610a1e81836020890161071a565b8451910190610a3181836020880161071a565b01979650505050505050565b6f0f644dcc2daca4474404498c2dcc840560831b815285515f90610a68816010850160208b0161071a565b600b60fa1b6010918401918201528651610a89816011840160208b0161071a565b7f29222c20226465736372697074696f6e223a20224c616e642069732073746f72601192909101918201527f6564206f6e20636861696e20616e6420726570726573656e747320612000000060318201528551610aed81604e840160208a0161071a565b600f60fb1b604e92909101918201528451610b0f81604f84016020890161071a565b7f2067726964206f66206c616e642e204561726e20656d697373696f6e73206279604f92909101918201527f20627579696e6720686f7573657321222c2022696d616765223a202264617461606f820152750e9a5b5859d94bdcdd99cade1b5b0ed8985cd94d8d0b60521b608f820152610b9d610b8f60a583018661083e565b61227d60f01b815260020190565b98975050505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081525f8251610be081601d85016020870161071a565b91909101601d0192915050565b634e487b7160e01b5f52604160045260245ffd5b808201808211156101be576101be6107dd565b80820281158282048414176101be576101be6107dd56fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220af6aa0ca9cce28cd2c7441fb0aa1c48ffaee36d14bf4f25334889d8454ef1bbc64736f6c63430008140033

Deployed Bytecode

0x608060405260043610610341575f3560e01c80638129fc1c116101bd578063c87b56dd116100f2578063de85b4fe11610092578063e985e9c51161006d578063e985e9c514610981578063f301af42146109cc578063f3cb8385146109f7578063f732ece314610a16575f80fd5b8063de85b4fe14610911578063df136d651461093c578063e4b50cb814610951575f80fd5b8063d1af0c7d116100cd578063d1af0c7d14610877578063d28a476114610895578063d7629fcc146108b4578063dd62ed3e146108c9575f80fd5b8063c87b56dd14610825578063cc1a378f14610844578063cd3daf9d14610863575f80fd5b8063a86ba1021161015d578063ab80627811610138578063ab806278146107b8578063b88d4fde146107d7578063bfa0b133146107f6578063c662e4811461080a575f80fd5b8063a86ba1021461075d578063a8aa1b311461077c578063a9059cbb14610799575f80fd5b80638da5cb5b116101985780638da5cb5b146106e257806395d89b41146106ff5780639839caa714610713578063a22cb4651461073e575f80fd5b80638129fc1c1461068e5780638188f71c146106a25780638aee8127146106c3575f80fd5b806332ba0a1e1161029357806367d3b4881161023357806370a082311161020e57806370a08231146106315780637519ab50146106505780637b0a47ee1461066557806380faa57d1461067a575f80fd5b806367d3b488146105e95780636c6f858b146105fe5780636e34e91d14610629575f80fd5b80633debce301161026e5780633debce301461057257806342842e0e1461058c5780634d6ed8c4146105ab5780636352211e146105ca575f80fd5b806332ba0a1e14610506578063392f37e9146105365780633c6b16ab14610553575f80fd5b806313af4035116102fe57806323b872dd116102d957806323b872dd1461047e5780632497ab151461049d5780632d10fa28146104bc578063313ce567146104e1575f80fd5b806313af40351461042c57806318160ddd1461044b5780631c4b774b1461045f575f80fd5b806301ffc9a71461034557806306fdde0314610388578063081812fc146103a9578063095ea7b3146103e05780630fb5a6b4146103ff5780631249c58b14610422575b5f80fd5b348015610350575f80fd5b5061037361035f3660046125ee565b60136020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b348015610393575f80fd5b5061039c610a29565b60405161037f9190612656565b3480156103b4575f80fd5b506103c86103c3366004612668565b610a9c565b6040516001600160a01b03909116815260200161037f565b3480156103eb575f80fd5b506103736103fa366004612693565b610add565b34801561040a575f80fd5b5061041460025481565b60405190815260200161037f565b61042a610b24565b005b348015610437575f80fd5b5061042a6104463660046126bd565b610be6565b348015610456575f80fd5b50610100610414565b34801561046a575f80fd5b5061042a610479366004612668565b610c1e565b348015610489575f80fd5b506103736104983660046126d8565b610d4b565b3480156104a8575f80fd5b506104146104b73660046126bd565b610e0a565b3480156104c7575f80fd5b506104d0610e24565b60405161037f9594939291906127d9565b3480156104ec575f80fd5b506104f45f81565b60405160ff909116815260200161037f565b348015610511575f80fd5b50610525610520366004612905565b610eb6565b60405161037f95949392919061293e565b348015610541575f80fd5b50600f546001600160a01b03166103c8565b34801561055e575f80fd5b5061042a61056d366004612668565b611107565b34801561057d575f80fd5b5061041466b1a2bc2ec5000081565b348015610597575f80fd5b5061042a6105a63660046126d8565b6112f3565b3480156105b6575f80fd5b506104146105c5366004612668565b61130d565b3480156105d5575f80fd5b506103c86105e4366004612668565b611379565b3480156105f4575f80fd5b5061041460035481565b348015610609575f80fd5b50610414610618366004612668565b60076020525f908152604090205481565b61042a611414565b34801561063c575f80fd5b5061041461064b3660046126bd565b611667565b34801561065b575f80fd5b5061041460045481565b348015610670575f80fd5b5061041460055481565b348015610685575f80fd5b50610414611679565b348015610699575f80fd5b5061042a611686565b3480156106ad575f80fd5b506106b66117fb565b60405161037f9190612976565b3480156106ce575f80fd5b5061042a6106dd3660046126bd565b61185e565b3480156106ed575f80fd5b50600e546001600160a01b03166103c8565b34801561070a575f80fd5b5061039c6118a9565b34801561071e575f80fd5b5061041461072d366004612668565b600a6020525f908152604090205481565b348015610749575f80fd5b5061042a610758366004612995565b6118f0565b348015610768575f80fd5b5061042a6107773660046129cc565b61195f565b348015610787575f80fd5b50600d546001600160a01b03166103c8565b3480156107a4575f80fd5b506103736107b3366004612693565b61199c565b3480156107c3575f80fd5b506001546103c8906001600160a01b031681565b3480156107e2575f80fd5b5061042a6107f1366004612a60565b6119a8565b348015610801575f80fd5b50600c54610414565b348015610815575f80fd5b50610414670214e8348c4f000081565b348015610830575f80fd5b5061039c61083f366004612668565b611a4e565b34801561084f575f80fd5b5061042a61085e366004612668565b611ad8565b34801561086e575f80fd5b50610414611b58565b348015610882575f80fd5b505f546103c8906001600160a01b031681565b3480156108a0575f80fd5b5061042a6108af366004612b07565b611bb7565b3480156108bf575f80fd5b5061041460095481565b3480156108d4575f80fd5b506104146108e3366004612b53565b6001600160a01b039182165f9081526010602090815260408083209390941682526001909201909152205490565b34801561091c575f80fd5b5061041461092b366004612668565b600b6020525f908152604090205481565b348015610947575f80fd5b5061041460065481565b34801561095c575f80fd5b5061097061096b366004612668565b611bc5565b60405161037f959493929190612b7f565b34801561098c575f80fd5b5061037361099b366004612b53565b6001600160a01b039182165f9081526010602090815260408083209390941682526002909201909152205460ff1690565b3480156109d7575f80fd5b506104146109e6366004612668565b60086020525f908152604090205481565b348015610a02575f80fd5b5061042a610a113660046126bd565b611cce565b61042a610a24366004612668565b611d06565b600f54604080516306fdde0360e01b815290516060926001600160a01b0316916306fdde03916004808301925f9291908290030181865afa158015610a70573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a979190810190612bbe565b905090565b5f61010082118015610aba5750610ab66101006002612c43565b8211155b610ac2575f80fd5b505f908152601160205260409020546001600160a01b031690565b5f61010082118015610afb5750610af76101006002612c43565b8211155b15610b0f57610b0a8383611e19565b610b1a565b610b1a338484611ea6565b5060015b92915050565b305f610b2f82611667565b90508060011115610b3e575f80fd5b5f610b52670214e8348c4f00006001612c43565b905080341015610b60575f80fd5b610b6c83336001611f0f565b600e546040516001600160a01b039091169082156108fc029083905f818181858888f19350505050158015610ba3573d5f803e3d5ffd5b5080341115610be157336108fc610bba8334612c5a565b6040518115909202915f818181858888f19350505050158015610bdf573d5f803e3d5ffd5b505b505050565b600e546001600160a01b03163314610bfc575f80fd5b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b80610c27611b58565b600655610c32611679565b6004558015610c6557610c448161130d565b5f828152600860209081526040808320939093556006546007909152919020555b33610c6f83611379565b6001600160a01b031614610cb65760405162461bcd60e51b81526020600482015260096024820152682737ba1027bbb732b960b91b60448201526064015b60405180910390fd5b5f828152600860205260409020548015610be1575f838152600860205260408082208290559054905163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015610d27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bdf9190612c6d565b5f61010082118015610d695750610d656101006002612c43565b8211155b15610d7e57610d79848484611ffb565b610e00565b6001600160a01b0384165f90815260106020908152604080832033845260010190915290205482811015610db0575f80fd5b5f198114610df3576001600160a01b0385165f90815260106020908152604080832033845260010190915281208054859290610ded908490612c5a565b90915550505b610dfe858585611f0f565b505b5060019392505050565b6001600160a01b03165f9081526010602052604090205490565b604080516101008082526120208201909252606091829182918291829160208201612000803683370190505090506101015b610201811015610e9b578082610e6e61010183612c5a565b81518110610e7e57610e7e612c88565b602090810291909101015280610e9381612c9c565b915050610e56565b50610ea581610eb6565b939991985096509194509192509050565b60608060608060605f86519050806001600160401b03811115610edb57610edb612845565b604051908082528060200260200182016040528015610f04578160200160208202803683370190505b509550806001600160401b03811115610f1f57610f1f612845565b604051908082528060200260200182016040528015610f48578160200160208202803683370190505b509450806001600160401b03811115610f6357610f63612845565b604051908082528060200260200182016040528015610f9657816020015b6060815260200190600190039081610f815790505b509350806001600160401b03811115610fb157610fb1612845565b604051908082528060200260200182016040528015610fda578160200160208202803683370190505b509250806001600160401b03811115610ff557610ff5612845565b60405190808252806020026020018201604052801561101e578160200160208202803683370190505b5091505f5b818110156110fc5761104d88828151811061104057611040612c88565b6020026020010151611bc5565b8b868151811061105f5761105f612c88565b602002602001018b878151811061107857611078612c88565b602002602001018b888151811061109157611091612c88565b602002602001018b89815181106110aa576110aa612c88565b602002602001018b8a815181106110c3576110c3612c88565b602090810291909101019490945293909252929091526001600160a01b03928316905291169052806110f481612c9c565b915050611023565b505091939590929450565b6001546001600160a01b031633146111315760405162461bcd60e51b8152600401610cad90612cb4565b5f61113a611b58565b600655611145611679565b6004558015611178576111578161130d565b5f828152600860209081526040808320939093556006546007909152919020555b60035442106111965760025461118e9083612cdc565b6005556111d1565b5f600554426003546111a89190612c5a565b6111b29190612c43565b6002549091506111c28285612cfb565b6111cc9190612cdc565b600555505b5f600554116112145760405162461bcd60e51b815260206004820152600f60248201526e07265776172642072617465203d203608c1b6044820152606401610cad565b5f546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611259573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061127d9190612d0e565b60025460055461128d9190612c43565b11156112db5760405162461bcd60e51b815260206004820152601760248201527f72657761726420616d6f756e74203e2062616c616e63650000000000000000006044820152606401610cad565b6002546112e89042612cfb565b600355505042600455565b610be183838360405180602001604052805f8152506119a8565b5f818152600860209081526040808320546007909252822054670de0b6b3a764000090611338611b58565b6113429190612c5a565b5f858152600b602052604090205461135b906001612cfb565b6113659190612c43565b61136f9190612cdc565b610b1e9190612cfb565b5f6101008211801561138d57506102008211155b611395575f80fd5b60016101001983011b5f6113a76117fb565b90505f5b815181101561140a5782836113d88484815181106113cb576113cb612c88565b6020026020010151610e0a565b1603611402578181815181106113f0576113f0612c88565b60200260200101519350505050919050565b6001016113ab565b505f949350505050565b5f341161141f575f80fd5b5f737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611470573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114949190612d25565b90505f309050737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ea573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061150e9190612d25565b6040516364e329cb60e11b81526001600160a01b0384811660048301528381166024830152919091169063c9c65396906044016020604051808303815f875af115801561155d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115819190612d25565b600d80546001600160a01b039283166001600160a01b0319909116179055737a250d5630b4cf539739df2c5dacb4c659f2488d9063f305d719908316318360205f806115d5600e546001600160a01b031690565b60405160e088901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094526044840192909252606483015290911660848201524260a482015260c40160606040518083038185885af115801561163b573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906116609190612d40565b5050505050565b5f610b1e61167483610e0a565b6120e8565b5f610a97600354426121a5565b5f611699600d546001600160a01b031690565b6001600160a01b0316146116ab575f80fd5b305f8181526010602090815260408083205f199055601280546001810182559084527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b031916851790558051606081019091526021808252849392612df8908301398051906020012061010060405161173091815260200190565b60405180910390a35f5b6101008110156117a25761175081610100612cfb565b61175b906001612cfb565b6040516001600160a01b038416905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a48061179a81612c9c565b91505061173a565b506117c381737a250d5630b4cf539739df2c5dacb4c659f2488d6020611ea6565b6117cf81326020611f0f565b6117db8133603c611f0f565b6117f8816117f1600e546001600160a01b031690565b6004611f0f565b50565b6060600c60060180548060200260200160405190810160405280929190818152602001828054801561185457602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611836575b5050505050905090565b6001546001600160a01b031633146118885760405162461bcd60e51b8152600401610cad90612cb4565b5f80546001600160a01b0319166001600160a01b0392909216919091179055565b600f54604080516395d89b4160e01b815290516060926001600160a01b0316916395d89b41916004808301925f9291908290030181865afa158015610a70573d5f803e3d5ffd5b335f8181526010602090815260408083206001600160a01b0387168085526002909101835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b5f5b81811015610be15761198a83838381811061197e5761197e612c88565b90506020020135610c1e565b8061199481612c9c565b915050611961565b5f610b1a338484611f0f565b6119b3848484611ffb565b823b63ffffffff81161561166057604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906119f3903390899088908890600401612d6b565b6020604051808303815f875af1158015611a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a339190612da7565b6001600160e01b03191663150b7a0260e01b14611660575f80fd5b600f545f828152600b6020526040908190205490516392cb829d60e01b81526060926001600160a01b0316916392cb829d91611a97918691600401918252602082015260400190565b5f60405180830381865afa158015611ab1573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b1e9190810190612bbe565b6001546001600160a01b03163314611b025760405162461bcd60e51b8152600401610cad90612cb4565b4260035410611b535760405162461bcd60e51b815260206004820152601c60248201527f726577617264206475726174696f6e206e6f742066696e6973686564000000006044820152606401610cad565b600255565b5f6009545f03611b69575060065490565b600954600454611b77611679565b611b819190612c5a565b600554611b8e9190612c43565b611ba090670de0b6b3a7640000612c43565b611baa9190612cdc565b600654610a979190612cfb565b611bc182826121bd565b5050565b5f8060605f80611bd486611379565b611bdd87610a9c565b611be688611a4e565b600f5460405163472e5afb60e11b8152600481018b90526001600160a01b0390911690638e5cb5f690602401602060405180830381865afa158015611c2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c519190612d0e565b600f5460405163845a469760e01b8152600481018c90526001600160a01b039091169063845a469790602401602060405180830381865afa158015611c98573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cbc9190612d0e565b939a9299509097509550909350915050565b600e546001600160a01b03163314611ce4575f80fd5b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b5f818152600b602052604090205460048110611d515760405162461bcd60e51b815260206004820152600a6024820152694d415820686f7573657360b01b6044820152606401610cad565b66b1a2bc2ec50000341015611d64575f80fd5b600e546040516001600160a01b03909116905f9066b1a2bc2ec500009082818181858883f19350505050158015611d9d573d5f803e3d5ffd5b505f828152600b60205260408120805491611db783612c9c565b909155505060098054905f611dcb83612c9c565b919050555066b1a2bc2ec50000341115611bc157336108fc611df466b1a2bc2ec5000034612c5a565b6040518115909202915f818181858888f19350505050158015610be1573d5f803e3d5ffd5b5f6001611e2861010084612c5a565b611e329190612c5a565b6001901b90508080611e4333610e0a565b1614611e4d575f80fd5b5f8281526011602052604080822080546001600160a01b0319166001600160a01b0387169081179091559051849233917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a4505050565b6001600160a01b038084165f8181526010602090815260408083209487168084526001909501825291829020859055815160608101909252602180835290612dd7908301398051906020012083604051611f0291815260200190565b60405180910390a3505050565b5f808080611f1c87610e0a565b90505f856001600160401b03811115611f3757611f37612845565b604051908082528060200260200182016040528015611f60578160200160208202803683370190505b5090505b5f82118015611f7257508583105b15611fc55781600116600103611fb5578051600180861b96909617958401936101018601918391908110611fa857611fa8612c88565b6020026020010181815250505b6001938401939190911c90611f64565b858314611fd0575f80fd5b8485611fdb8a610e0a565b1614611fe5575f80fd5b611ff188888784612233565b5050505050505050565b6101008111801561200e57506102008111155b612016575f80fd5b60016101001982011b808061202a86610e0a565b1614612034575f80fd5b336001600160a01b0385161480612064575061204f82610a9c565b6001600160a01b0316336001600160a01b0316145b8061209457506001600160a01b0384165f90815260106020908152604080832033845260020190915290205460ff165b61209c575f80fd5b6040805160018082528183019092525f916020808301908036833701905050905082815f815181106120d0576120d0612c88565b60200260200101818152505061166085858484612233565b5f81600181016120fc575061010092915050565b7f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f5555555555555555555555555555555555555555555555555555555555555555600183901c16909103600281901c7f3333333333333333333333333333333333333333333333333333333333333333908116911601600481901c01167f01010101010101010101010101010101010101010101010101010101010101010260f81c92915050565b5f818311156121b457816121b6565b825b9392505050565b5f805b82518110156122015760016101008483815181106121e0576121e0612c88565b602002602001015103036001901b5f1b8217915080806001019150506121c0565b50815161220d826120e8565b14612216575f80fd5b808161222133610e0a565b161461222b575f80fd5b610be1338483855b5f81511161223f575f80fd5b5f5b8151811015612381575f6001600160a01b031661227683838151811061226957612269612c88565b6020026020010151610a9c565b6001600160a01b03161461231f575f600c6005015f84848151811061229d5761229d612c88565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508181815181106122e7576122e7612c88565b60209081029190910101516040515f9081907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908290a45b81818151811061233157612331612c88565b6020026020010151846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4600101612241565b506001600160a01b0384165f9081526010602052604081208054841890556123a885610e0a565b1590505f6123b585610e0a565b6001600160a01b0386165f9081526010602052604090208054861790551590508115612517575f806123e56117fb565b90505f5b815181101561243457886001600160a01b031682828151811061240e5761240e612c88565b60200260200101516001600160a01b03160361242c57809250612434565b6001016123e9565b5082156124825786600c600601838154811061245257612452612c88565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550612510565b8060018251038151811061249857612498612c88565b6020026020010151600c60060183815481106124b6576124b6612c88565b5f91825260209091200180546001600160a01b0319166001600160a01b039290921691909117905560128054806124ef576124ef612dc2565b5f8281526020902081015f1990810180546001600160a01b03191690550190555b5050612568565b801561256857601280546001810182555f919091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b0319166001600160a01b0387161790555b61257185610e0a565b61257a87610e0a565b1615612584575f80fd5b846001600160a01b0316866001600160a01b0316604051806060016040528060218152602001612df8602191398051906020012085516040516125c991815260200190565b60405180910390a3505050505050565b6001600160e01b0319811681146117f8575f80fd5b5f602082840312156125fe575f80fd5b81356121b6816125d9565b5f5b8381101561262357818101518382015260200161260b565b50505f910152565b5f8151808452612642816020860160208601612609565b601f01601f19169290920160200192915050565b602081525f6121b6602083018461262b565b5f60208284031215612678575f80fd5b5035919050565b6001600160a01b03811681146117f8575f80fd5b5f80604083850312156126a4575f80fd5b82356126af8161267f565b946020939093013593505050565b5f602082840312156126cd575f80fd5b81356121b68161267f565b5f805f606084860312156126ea575f80fd5b83356126f58161267f565b925060208401356127058161267f565b929592945050506040919091013590565b5f8151808452602080850194508084015f5b8381101561274d5781516001600160a01b031687529582019590820190600101612728565b509495945050505050565b5f81518084526020808501808196508360051b810191508286015f5b8581101561279e57828403895261278c84835161262b565b98850198935090840190600101612774565b5091979650505050505050565b5f8151808452602080850194508084015f5b8381101561274d578151875295820195908201906001016127bd565b60a081525f6127eb60a0830188612716565b82810360208401526127fd8188612758565b9050828103604084015261281181876127ab565b9050828103606084015261282581866127ab565b9050828103608084015261283981856127ab565b98975050505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561288157612881612845565b604052919050565b5f82601f830112612898575f80fd5b813560206001600160401b038211156128b3576128b3612845565b8160051b6128c2828201612859565b92835284810182019282810190878511156128db575f80fd5b83870192505b848310156128fa578235825291830191908301906128e1565b979650505050505050565b5f60208284031215612915575f80fd5b81356001600160401b0381111561292a575f80fd5b61293684828501612889565b949350505050565b60a081525f61295060a0830188612716565b82810360208401526129628188612716565b905082810360408401526128118187612758565b602081525f6121b66020830184612716565b80151581146117f8575f80fd5b5f80604083850312156129a6575f80fd5b82356129b18161267f565b915060208301356129c181612988565b809150509250929050565b5f80602083850312156129dd575f80fd5b82356001600160401b03808211156129f3575f80fd5b818501915085601f830112612a06575f80fd5b813581811115612a14575f80fd5b8660208260051b8501011115612a28575f80fd5b60209290920196919550909350505050565b5f6001600160401b03821115612a5257612a52612845565b50601f01601f191660200190565b5f805f8060808587031215612a73575f80fd5b8435612a7e8161267f565b93506020850135612a8e8161267f565b92506040850135915060608501356001600160401b03811115612aaf575f80fd5b8501601f81018713612abf575f80fd5b8035612ad2612acd82612a3a565b612859565b818152886020838501011115612ae6575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f8060408385031215612b18575f80fd5b8235612b238161267f565b915060208301356001600160401b03811115612b3d575f80fd5b612b4985828601612889565b9150509250929050565b5f8060408385031215612b64575f80fd5b8235612b6f8161267f565b915060208301356129c18161267f565b6001600160a01b0386811682528516602082015260a0604082018190525f90612baa9083018661262b565b606083019490945250608001529392505050565b5f60208284031215612bce575f80fd5b81516001600160401b03811115612be3575f80fd5b8201601f81018413612bf3575f80fd5b8051612c01612acd82612a3a565b818152856020838501011115612c15575f80fd5b612c26826020830160208601612609565b95945050505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610b1e57610b1e612c2f565b81810381811115610b1e57610b1e612c2f565b5f60208284031215612c7d575f80fd5b81516121b681612988565b634e487b7160e01b5f52603260045260245ffd5b5f60018201612cad57612cad612c2f565b5060010190565b6020808252600e908201526d1b9bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b5f82612cf657634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610b1e57610b1e612c2f565b5f60208284031215612d1e575f80fd5b5051919050565b5f60208284031215612d35575f80fd5b81516121b68161267f565b5f805f60608486031215612d52575f80fd5b8351925060208401519150604084015190509250925092565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90612d9d9083018461262b565b9695505050505050565b5f60208284031215612db7575f80fd5b81516121b6816125d9565b634e487b7160e01b5f52603160045260245ffdfe417070726f76616c28616464726573732c616464726573732c75696e74323536295472616e7366657228616464726573732c616464726573732c75696e7432353629a2646970667358221220996a5d12f0068519972669cafd3c9e9deb459dd2e2385f309056875232d05e4a64736f6c63430008140033

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  ]
[ 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.