ETH Price: $2,101.32 (-10.74%)

Token

MFiends (MFIENDS)
 

Overview

Max Total Supply

3 MFIENDS

Holders

2

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 MFIENDS
0x3b1fc0dde8acc6e67328eecf8e65fa9e20879616
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
MFiends

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 19 : MFiends.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.0 <0.9.0;

import "./IMGear.sol";
import "./Ownable.sol";
import "./BattleStats.sol";
import "./ERC721Enumerable.sol";
import "./IOnChainPixelArtv2.sol";
import "./MFiendsAssets.sol";
import "./MFiendCharacteristics.sol";

contract MFiends is Ownable, ERC721Enumerable, BattleStats, MFiendsAssets, MFiendCharacteristics {
  IMGear private mineableGear;
  IOnChainPixelArtv2 private onChainPixelArt;

  uint256 private DIFFICULTY;

  struct Stats {
    uint64 ruin;
    uint64 guard;
    uint64 vigor;
    uint64 celerity;
  }

  uint8 private constant RUIN = 0;
  uint8 private constant GUARD = 1;
  uint8 private constant VIGOR = 2;
  uint8 private constant CELERITY = 3;

  //7 bits for 128: 0111 1111
  uint8 private constant ROLL_MASK = 0x7f;
  //16/128

  uint8 private constant CRIT_SHIFT = 7;
  uint8 private constant MISS_SHIFT = 14;
  uint8 private constant BLOCK_SHIFT = 21;
  uint8 private constant ATTACK_SHIFT = 23;
  uint8 private constant BASE_ROLL = 16;

  uint8 private constant TURN_SHIFT = 25;

  uint8 private constant TRAIT_MASK = 0xF;
  uint32 private constant TRAITS_MASK = 0xFFFFFFFF;

  mapping(uint256 => bool) public traits;
  uint256[] tokenIdToData;

  mapping(address => uint256)[4] public equipped;
  mapping(address => Stats) public stats;
  mapping(uint256 => address) public equippedBy;

  // stat buffs are stored [ruin][guard][vigor][celerity][ruin][guard][vigor][celerity]

  // 0, 0, 0, 0,   0, 0, 0, 0,   3, 0, 0, 1,   0, 1, 0, 3,   0, 2, 2, 0,   3, 3, 0, 0,   0, 0, 3, 4,   3, 2, 2, 2
  uint8[32] affinityToStatBuff = [
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    3,
    0,
    0,
    1,
    0,
    1,
    0,
    3,
    0,
    2,
    2,
    0,
    3,
    3,
    0,
    0,
    0,
    0,
    3,
    4,
    3,
    2,
    2,
    2
  ];

  constructor(
    IMGear _mineableGear,
    IOnChainPixelArtv2 _onChainPixelArt,
    uint256 _difficulty
  ) ERC721("MFiends", "MFIENDS") MFiendsAssets(_onChainPixelArt) Ownable() {
    mineableGear = _mineableGear;
    onChainPixelArt = _onChainPixelArt;
    DIFFICULTY = _difficulty;
  }

  function addOrSubtract(
    uint256 initial,
    uint256 amount,
    bool add
  ) internal pure returns (uint64) {
    if (add) {
      return uint64(initial + amount);
    }
    return uint64(initial - amount);
  }

  function updateStat(
    uint256 statType,
    bool equip,
    uint256 amount,
    address player
  ) internal {
    if (statType == RUIN) {
      stats[player].ruin = addOrSubtract(stats[player].ruin, amount, equip);
    }
    if (statType == GUARD) {
      stats[player].guard = addOrSubtract(stats[player].guard, amount, equip);
    }
    if (statType == VIGOR) {
      stats[player].vigor = addOrSubtract(stats[player].vigor, amount, equip);
    }
    if (statType == CELERITY) {
      stats[player].celerity = addOrSubtract(stats[player].celerity, amount, equip);
    }
  }

  function manageItem(
    uint256 mgear,
    address equippee,
    bool equip
  ) internal {
    uint8 itemMajorType = BattleStats.getMajorType(mgear);
    uint8 itemMinor1Type = BattleStats.getMinorType1(mgear);
    uint8 itemMinor2Type = BattleStats.getMinorType2(mgear);

    if (equip) {
      // there's always a major stat
      updateStat(itemMajorType, true, BattleStats.getMajorValue(mgear), equippee);
      // 5 means no stat
      if (itemMinor1Type < 5) {
        updateStat(itemMinor1Type, true, BattleStats.getMinorValue1(mgear), equippee);
      }

      if (itemMinor2Type < 5) {
        updateStat(itemMinor2Type, true, BattleStats.getMinorValue2(mgear), equippee);
      }
    } else {
      updateStat(itemMajorType, false, BattleStats.getMajorValue(mgear), equippee);

      if (itemMinor1Type < 5) {
        updateStat(itemMinor1Type, false, BattleStats.getMinorValue1(mgear), equippee);
      }

      if (itemMinor2Type < 5) {
        updateStat(itemMinor2Type, false, BattleStats.getMinorValue2(mgear), equippee);
      }
    }
  }

  function unequipItem(
    uint256 itemSlot,
    uint256 mgearId,
    address equippee
  ) internal {
    uint256 equippedItem = equipped[itemSlot][equippee];
    // only unequip if we have one equipped already
    if (equippedItem > 0) {
      uint256 mgearToUnequip = mineableGear.tokenIdToMGear(equippedItem);
      manageItem(mgearToUnequip, equippee, false);
      equipped[itemSlot][equippee] = 0;
      equippedBy[mgearId] = address(0);
    }
  }

  function equipItem(
    uint256 mgearId,
    address equippee,
    uint256 itemSlot
  ) internal {
    uint256 mgear = mineableGear.tokenIdToMGear(mgearId);

    // if mgearId is the same as equipped, no op
    if (mgearId > 0) {
      // only transact if it's a different mgearId from equipped
      if (mgearId != equipped[itemSlot][equippee]) {
        uint8 itemMajorType = BattleStats.getMajorType(mgear);
        // make sure the item is actually the specified type
        require(itemMajorType == itemSlot, "slot");
        // make sure they own the mgear
        require(mineableGear.ownerOf(mgearId) == equippee, "own");
        // unequip current slot
        unequipItem(itemMajorType, mgearId, equippee);

        // apply new stats
        manageItem(mgear, equippee, true);
        // track who has it equipped
        equipped[itemMajorType][equippee] = mgearId;
        equippedBy[mgearId] = equippee;
      }
    } else {
      unequipItem(itemSlot, mgearId, equippee);
    }
  }

  function equipItems(
    uint256 ruinItemId,
    uint256 guardItemId,
    uint256 vigorItemId,
    uint256 celerityItemId
  ) external {
    // initialize if not yet
    if (stats[msg.sender].vigor == 0) {
      stats[msg.sender] = Stats(1, 0, 10, 0);
    }
    equipItem(ruinItemId, msg.sender, RUIN);
    equipItem(guardItemId, msg.sender, GUARD);
    equipItem(vigorItemId, msg.sender, VIGOR);
    equipItem(celerityItemId, msg.sender, CELERITY);
  }

  function subtractWithLimit(uint256 n1, uint256 n2) internal pure returns (uint256) {
    if (n2 > n1) {
      return 0;
    } else {
      return n1 - n2;
    }
  }

  function getEquippedItems(address owner) public view returns (uint256[4] memory gear) {
    return [equipped[0][owner], equipped[1][owner], equipped[2][owner], equipped[3][owner]];
  }

  function assertValidGear(address player) public view returns (bool) {
    require(stats[player].vigor > 0, "init");
    uint256[4] memory equippedItems = getEquippedItems(player);
    if (equippedItems[RUIN] != 0) {
      require(mineableGear.ownerOf(equipped[RUIN][player]) == player, "e0");
    }
    if (equippedItems[GUARD] != 0) {
      require(mineableGear.ownerOf(equipped[GUARD][player]) == player, "e1");
    }
    if (equippedItems[VIGOR] != 0) {
      require(mineableGear.ownerOf(equipped[VIGOR][player]) == player, "e2");
    }
    if (equippedItems[CELERITY] != 0) {
      require(mineableGear.ownerOf(equipped[CELERITY][player]) == player, "e3");
    }
    return true;
  }

  //21 bits is a turn
  function getDamageFromTurn(
    uint256 game,
    uint256 turn,
    Stats memory damageDealer,
    Stats memory damageTaker
  ) private pure returns (uint256) {
    uint256 turnShift = TURN_SHIFT * turn;
    uint256 damageTakerDodgeRoll = (game >> (turnShift)) & ROLL_MASK;

    damageTakerDodgeRoll = subtractWithLimit(damageTakerDodgeRoll, damageTaker.celerity << 1);

    uint256 missRoll = ((game >> (turnShift + MISS_SHIFT)) & ROLL_MASK) +
      (damageDealer.celerity << 1);

    if (missRoll < BASE_ROLL || damageTakerDodgeRoll < BASE_ROLL) {
      return 0;
    }

    uint256 critRoll = (game >> (turnShift + CRIT_SHIFT)) & ROLL_MASK;

    critRoll = subtractWithLimit(critRoll, damageTaker.celerity * 3);

    // if ruin is bigger than opponent, crit roll is reduced to reduce the chance of annihilation
    if (damageDealer.ruin > damageTaker.ruin) {
      critRoll = critRoll + ((damageDealer.ruin - damageTaker.ruin) * 5);
    }

    uint256 blockRoll = (game >> (turnShift + BLOCK_SHIFT)) & 0x3;
    uint256 blockAmount = damageTaker.guard >> blockRoll;

    uint256 damage = subtractWithLimit(damageDealer.ruin, 2) +
      ((game >> (turnShift + ATTACK_SHIFT)) & 0x3);

    // if miss roll is between base roll and 2x base roll, we do half damage
    if (missRoll < (BASE_ROLL << 1)) {
      damage = damage >> 1;
    }

    if (critRoll < BASE_ROLL) {
      damage = damage + damage;
    }

    //default to 1 damage if defense exceeds
    if (blockAmount > damage) {
      return 1;
    } else {
      return damage - blockAmount;
    }
  }

  function generateEnemy(
    uint256 seed,
    Stats memory challenger,
    uint256 affinity
  ) public view returns (Stats memory enemy) {
    // fiends get harder as more are minted
    uint256 fiendDifficulty = (ERC721Enumerable.totalSupply() / 256) + 1;

    // ruin is at least 5 to avoid intentional tie-breaking
    uint256 ruin = 5;
    if (challenger.ruin > 5) {
      ruin = challenger.ruin;
    }

    return
      Stats(
        uint64(ruin + (((seed >> 32) & 0xF) % fiendDifficulty)) + affinityToStatBuff[affinity * 4],
        uint64(challenger.guard + (((seed >> 36) & 0xF) % fiendDifficulty)) +
          affinityToStatBuff[affinity * 4 + 1],
        // add a little vigor to make it slightly harder
        uint64(challenger.vigor + (((seed >> 40) & 0xF) % fiendDifficulty)) +
          1 +
          affinityToStatBuff[affinity * 4 + 2],
        uint64(challenger.celerity + (((seed >> 44) & 0xF) % fiendDifficulty)) +
          affinityToStatBuff[affinity * 4 + 3]
      );
  }

  function getTieBreak(uint256 game, Stats memory c) internal pure returns (bool result) {
    // -11 for base stats of 1 ruin and 10 vigor
    // roll can add up to 64. Having a stat total of 32 gives a 50% to win. 64 is guaranteed
    if ((((game >> 250) & 0x3F) + (c.ruin + c.guard + c.vigor + c.celerity - 11)) > 64) {
      return true;
    } else {
      return false;
    }
  }

  //game returns winning address, or 0 if tie
  function executeGame(
    uint256 game,
    Stats memory challenger,
    Stats memory enemy
  ) public pure returns (bool result) {
    uint256 challengerHealth = challenger.vigor;
    uint256 enemyHealth = enemy.vigor;

    for (uint256 turn = 0; turn < 5; turn++) {
      //defender attacks first
      uint256 challengerDamageDealt = getDamageFromTurn(game, turn * 2, challenger, enemy);

      //opposer attacks next
      uint256 enemyDamageDealt = getDamageFromTurn(game, turn * 2 + 1, enemy, challenger);

      if (enemyDamageDealt >= challengerHealth && challengerDamageDealt >= enemyHealth) {
        return getTieBreak(game, challenger);
      }
      if (challengerDamageDealt >= enemyHealth) {
        return true;
      }
      if (enemyDamageDealt >= challengerHealth) {
        return false;
      }

      //proceed with damage if no win conditions are met
      enemyHealth = enemyHealth - challengerDamageDealt;
      challengerHealth = challengerHealth - enemyDamageDealt;
    }
    return getTieBreak(game, challenger);
  }

  function encodeNonce(address sender, uint96 nonce) internal pure returns (uint256) {
    return uint256(keccak256(abi.encodePacked(uint160(sender), nonce)));
  }

  function encodeTokenData(uint256 traitData, Stats memory enemy) internal pure returns (uint256) {
    return
      traitData +
      (enemy.ruin << 32) +
      (enemy.guard << 40) +
      (enemy.vigor << 48) +
      (enemy.celerity << 56);
  }

  function getCharacteristicsData(uint256 tokenId) public view returns (uint256) {
    return encodeNonce(address(this), uint96(tokenIdToData[tokenId - 1] & TRAITS_MASK));
  }

  // 11-25 26-40 41-55 56-70 71-85 85+
  function getPowerLevel(Stats memory charStats) public pure returns (string memory) {
    uint256 total = charStats.ruin + charStats.guard + charStats.vigor + charStats.celerity;

    if (total <= 25) {
      return "Feeble";
    }
    if (total <= 40) {
      return "Sturdy";
    }
    if (total <= 55) {
      return "Formidable";
    }
    if (total <= 70) {
      return "Powerful";
    }
    if (total <= 85) {
      return "Triumphant";
    }
    return "Godlike";
  }

  function getStatsFromToken(uint256 tokenId) public view returns (Stats memory) {
    uint256 tokenData = tokenIdToData[tokenId - 1];
    return
      Stats(
        uint64((tokenData >> 32) & 0xFF),
        uint64((tokenData >> 40) & 0xFF),
        uint64((tokenData >> 48) & 0xFF),
        uint64((tokenData >> 56) & 0xFF)
      );
  }

  struct RenderTracker {
    uint256 armIndex;
    uint256 backIndex;
    uint256 bodyIndex;
    uint256 headIndex;
    uint256 legsIndex;
    uint256 runeIndex;
    bool hasBack;
    bool hasRune;
    uint256 size;
  }

  function renderData(
    uint256 tokenData,
    uint256[] memory palette,
    string memory backgroundColor
  ) public view returns (string memory svg) {
    RenderTracker memory tracker = RenderTracker(
      tokenData & TRAIT_MASK,
      (tokenData >> 4) & TRAIT_MASK,
      (tokenData >> 8) & TRAIT_MASK,
      (tokenData >> 12) & TRAIT_MASK,
      (tokenData >> 16) & TRAIT_MASK,
      (tokenData >> 20) & TRAIT_MASK,
      ((tokenData >> 24) & 0xF) < 2,
      ((tokenData >> 28) & 0xF) < 2,
      4
    );

    if (tracker.hasBack) {
      tracker.size += 1;
    }
    if (tracker.hasRune) {
      tracker.size += 1;
    }

    uint256[] memory layers = new uint256[](tracker.size);

    if (tracker.hasBack) {
      layers[0] = tracker.backIndex + 16;
      layers[1] = tracker.bodyIndex + 32;
      if (tracker.hasRune) {
        layers[2] = tracker.runeIndex + 80;
        layers[3] = tracker.headIndex + 48;
        layers[4] = tracker.legsIndex + 64;
        layers[5] = tracker.armIndex;
      } else {
        layers[2] = tracker.headIndex + 48;
        layers[3] = tracker.legsIndex + 64;
        layers[4] = tracker.armIndex;
      }
    } else {
      layers[0] = tracker.bodyIndex + 32;
      if (tracker.hasRune) {
        layers[1] = tracker.runeIndex + 80;
        layers[2] = tracker.headIndex + 48;
        layers[3] = tracker.legsIndex + 64;
        layers[4] = tracker.armIndex;
      } else {
        layers[1] = tracker.headIndex + 48;
        layers[2] = tracker.legsIndex + 64;
        layers[3] = tracker.armIndex;
      }
    }

    return
      onChainPixelArt.render(
        MFiendsAssets.composeLayers(layers),
        palette,
        21,
        21,
        string(abi.encodePacked('style="background-color: #', backgroundColor, '"')),
        3,
        3
      );
  }

  function renderStat(uint256 value, bytes memory name) internal view returns (bytes memory) {
    return
      abi.encodePacked(
        '{ "display_type": "number", "trait_type": "',
        name,
        '", "value": ',
        onChainPixelArt.toString(value),
        "}"
      );
  }

  function renderFiend(
    uint256 tokenTraits,
    uint256 paletteData,
    uint256 affinity
  ) public view returns (string memory svg) {
    uint256[] memory palette = new uint256[](3);
    uint256 paletteColor = getPalette(paletteData, affinity);
    // overfill palette just to make sure we don't OOB
    palette[0] = paletteColor;
    palette[1] = getPalette(encodeNonce(address(this), uint96(palette[0])), affinity);
    palette[2] = getPalette(encodeNonce(address(this), uint96(palette[1])), affinity);
    return renderData(tokenTraits, palette, onChainPixelArt.toHexString(affinityToColor[affinity]));
  }

  function render(uint256 tokenId) internal view returns (string memory svg) {
    uint256 hashedTraits = encodeNonce(
      address(this),
      uint96(tokenIdToData[tokenId - 1] & TRAITS_MASK)
    );
    return
      renderFiend(
        tokenIdToData[tokenId - 1] & TRAITS_MASK,
        hashedTraits,
        getAffinity(hashedTraits)
      );
  }

  function withdraw(uint256 amount) external onlyOwner {
    payable(Ownable.owner()).transfer(amount);
  }

  function mint(uint96 nonce, bool callForHelp) external payable {
    assertValidGear(msg.sender);
    uint256 result = encodeNonce(msg.sender, nonce);
    require(result < DIFFICULTY, "dif");
    uint256 tokenData = result & TRAITS_MASK;
    require(!traits[tokenData], "alr");

    if (callForHelp) {
      // mfiends can always be beat, but limited can be purchased
      require(tokenIdToData.length < 4096, "lim");
      require(msg.value >= 50000000000000000, "fee");
    }

    // game result comes from the hash of mineable gear address with nonce
    uint256 gameResult = encodeNonce(address(mineableGear), nonce);
    // use the hash result because we only use the first 32 bits for traits
    Stats memory enemy = generateEnemy(
      result,
      stats[msg.sender],
      getAffinity(encodeNonce(address(this), uint96(tokenData)))
    );

    bool win = executeGame(gameResult, stats[msg.sender], enemy);
    require(win || callForHelp, "lost");
    uint256 tokenId = tokenIdToData.length + 1;
    tokenIdToData.push(encodeTokenData(tokenData, enemy));
    traits[tokenData] = true;
    ERC721._safeMint(msg.sender, tokenId);
  }

  function getAttributes(uint256 tokenId) public view returns (string memory) {
    uint256 tokenData = tokenIdToData[tokenId - 1];
    Stats memory tokenStats = getStatsFromToken(tokenId);

    bytes memory attributes = abi.encodePacked(
      '"attributes": [{ "trait_type": "Affinity", "value": "',
      affinityToName[getAffinity(encodeNonce(address(this), uint96(tokenData & TRAITS_MASK)))],
      '" }, { "trait_type": "Power Level", "value": "',
      getPowerLevel(tokenStats),
      '" }'
    );

    bool hasBack = ((tokenData >> 24) & 0xF) < 2;
    bool hasRune = ((tokenData >> 28) & 0xF) < 2;

    string memory rareForm;
    if (hasBack || hasRune) {
      if (hasBack && hasRune) {
        rareForm = "Runed & Winged";
      } else if (hasBack) {
        rareForm = "Winged";
      } else if (hasRune) {
        rareForm = "Runed";
      }

      attributes = abi.encodePacked(
        attributes,
        ', { "trait_type": "Rare Form", "value": "',
        rareForm,
        '" }'
      );
    }

    attributes = abi.encodePacked(
      attributes,
      ", ",
      renderStat(tokenStats.ruin, "Ruin"),
      ", ",
      renderStat(tokenStats.guard, "Guard"),
      ", ",
      renderStat(tokenStats.vigor, "Vigor"),
      ", ",
      renderStat(tokenStats.celerity, "Celerity")
    );

    return string(abi.encodePacked(attributes, "]"));
  }

  function renderTokenURI(uint256 tokenId) public view returns (string memory) {
    return
      onChainPixelArt.uri(
        string(
          abi.encodePacked(
            '{"name": "mfiend #',
            onChainPixelArt.toString(tokenId),
            '", "description": "A fiend captured by proof-of-combat.", "image": "',
            onChainPixelArt.uriSvg(render(tokenId)),
            '", ',
            getAttributes(tokenId),
            " }"
          )
        )
      );
  }

  function tokenURI(uint256 tokenId) public view override returns (string memory) {
    require(ERC721._exists(tokenId), "404");
    return renderTokenURI(tokenId);
  }
}

File 2 of 19 : IMGear.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./IERC721Enumerable.sol";

interface IMGear is IERC721Enumerable {
  function tokenIdToMGear(uint256 mgearId) external view returns (uint256 mgearData);

  function renderData(uint256 mgear) external view returns (string memory svg);
}

File 3 of 19 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./Context.sol";

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _setOwner(_msgSender());
    }

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

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

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

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

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 4 of 19 : BattleStats.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.0 <0.9.0;
import "hardhat/console.sol";

contract BattleStats {
  uint8 NO_STAT = 5;
  uint8[4] public tierToStatBase;
  uint8[3][6] public rarityToTiers;

  constructor() {
    tierToStatBase[0] = 0;
    tierToStatBase[1] = 0;
    tierToStatBase[2] = 3;
    tierToStatBase[3] = 6;

    rarityToTiers[0] = [1, 0, 0];
    rarityToTiers[1] = [2, 0, 0];
    rarityToTiers[2] = [2, 1, 0];
    rarityToTiers[3] = [2, 2, 0];
    rarityToTiers[4] = [3, 2, 1];
    rarityToTiers[5] = [3, 2, 2];
  }

  function getMajorType(uint256 mgear) public pure returns (uint8) {
    return uint8((mgear >> 19) & 0x3);
  }

  function getMinorType1(uint256 mgear) public view returns (uint8) {
    if (rarityToTiers[uint8(mgear & 0x7)][1] == 0) {
      return NO_STAT;
    }
    return uint8((mgear >> 21) & 0x3);
  }

  function getMinorType2(uint256 mgear) public view returns (uint8) {
    if (rarityToTiers[uint8(mgear & 0x7)][2] == 0) {
      return NO_STAT;
    }
    return uint8((mgear >> 23) & 0x3);
  }

  function getMajorValue(uint256 mgear) public view returns (uint8) {
    return tierToStatBase[rarityToTiers[uint8(mgear & 0x7)][0]] + uint8((mgear >> 25) & 0x3);
  }

  function getMinorValue1(uint256 mgear) public view returns (uint8) {
    if (rarityToTiers[uint8(mgear & 0x7)][1] == 0) {
      return 0;
    }
    return tierToStatBase[rarityToTiers[uint8(mgear & 0x7)][1]] + uint8((mgear >> 27) & 0x3);
  }

  function getMinorValue2(uint256 mgear) public view returns (uint8) {
    if (rarityToTiers[uint8(mgear & 0x7)][2] == 0) {
      return 0;
    }
    return tierToStatBase[rarityToTiers[uint8(mgear & 0x7)][2]] + uint8((mgear >> 29) & 0x3);
  }
}

File 5 of 19 : ERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ERC721.sol";
import "./IERC721Enumerable.sol";

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
  // Mapping from owner to list of owned token IDs
  mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

  // Mapping from token ID to index of the owner tokens list
  mapping(uint256 => uint256) private _ownedTokensIndex;

  // Array with all token ids, used for enumeration
  uint256[] private _allTokens;

  // Mapping from token id to position in the allTokens array
  mapping(uint256 => uint256) private _allTokensIndex;

  /**
   * @dev See {IERC165-supportsInterface}.
   */
  function supportsInterface(bytes4 interfaceId)
    public
    view
    virtual
    override(IERC165, ERC721)
    returns (bool)
  {
    return
      interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
  }

  /**
   * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
   */
  function tokenOfOwnerByIndex(address owner, uint256 index)
    public
    view
    virtual
    override
    returns (uint256)
  {
    require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
    return _ownedTokens[owner][index];
  }

  /**
   * @dev See {IERC721Enumerable-totalSupply}.
   */
  function totalSupply() public view virtual override returns (uint256) {
    return _allTokens.length;
  }

  /**
   * @dev See {IERC721Enumerable-tokenByIndex}.
   */
  function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
    require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
    return _allTokens[index];
  }

  /**
   * @dev Hook that is called before any token transfer. This includes minting
   * and burning.
   *
   * Calling conditions:
   *
   * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
   * transferred to `to`.
   * - When `from` is zero, `tokenId` will be minted for `to`.
   * - When `to` is zero, ``from``'s `tokenId` will be burned.
   * - `from` cannot be the zero address.
   * - `to` cannot be the zero address.
   *
   * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
   */
  function _beforeTokenTransfer(
    address from,
    address to,
    uint256 tokenId
  ) internal virtual override {
    super._beforeTokenTransfer(from, to, tokenId);

    if (from == address(0)) {
      _addTokenToAllTokensEnumeration(tokenId);
    } else if (from != to) {
      _removeTokenFromOwnerEnumeration(from, tokenId);
    }
    if (to == address(0)) {
      _removeTokenFromAllTokensEnumeration(tokenId);
    } else if (to != from) {
      _addTokenToOwnerEnumeration(to, tokenId);
    }
  }

  /**
   * @dev Private function to add a token to this extension's ownership-tracking data structures.
   * @param to address representing the new owner of the given token ID
   * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
   */
  function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
    uint256 length = ERC721.balanceOf(to);
    _ownedTokens[to][length] = tokenId;
    _ownedTokensIndex[tokenId] = length;
  }

  /**
   * @dev Private function to add a token to this extension's token tracking data structures.
   * @param tokenId uint256 ID of the token to be added to the tokens list
   */
  function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
    _allTokensIndex[tokenId] = _allTokens.length;
    _allTokens.push(tokenId);
  }

  /**
   * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
   * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
   * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
   * This has O(1) time complexity, but alters the order of the _ownedTokens array.
   * @param from address representing the previous owner of the given token ID
   * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
   */
  function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
    // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
    // then delete the last slot (swap and pop).

    uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
    uint256 tokenIndex = _ownedTokensIndex[tokenId];

    // When the token to delete is the last token, the swap operation is unnecessary
    if (tokenIndex != lastTokenIndex) {
      uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

      _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
      _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
    }

    // This also deletes the contents at the last position of the array
    delete _ownedTokensIndex[tokenId];
    delete _ownedTokens[from][lastTokenIndex];
  }

  /**
   * @dev Private function to remove a token from this extension's token tracking data structures.
   * This has O(1) time complexity, but alters the order of the _allTokens array.
   * @param tokenId uint256 ID of the token to be removed from the tokens list
   */
  function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
    // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
    // then delete the last slot (swap and pop).

    uint256 lastTokenIndex = _allTokens.length - 1;
    uint256 tokenIndex = _allTokensIndex[tokenId];

    // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
    // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
    // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
    uint256 lastTokenId = _allTokens[lastTokenIndex];

    _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
    _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

    // This also deletes the contents at the last position of the array
    delete _allTokensIndex[tokenId];
    _allTokens.pop();
  }
}

File 6 of 19 : IOnChainPixelArtv2.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IOnChainPixelArtv2 {
  /**
   * @dev Takes an encoded canvas, encoded palette, dimensions, and a background color and returns an svg.
   * Background color must end in 1 - so green would be 0x00FF001.
   * This is so 0 (which would otherwise be black) can be passed for no color.
   * Dimensions must match what the canvas was encoded with.
   */
  function render(
    uint256[] memory canvas,
    uint256[] memory palette,
    uint256 xDim,
    uint256 yDim,
    string memory svgExtension,
    uint256 paddingX,
    uint256 paddingY
  ) external pure returns (string memory svg);

  /**
   * @dev Compresses and encodes an array of pixels into an canvas of uint256s that can be rendered.
   * For example, a 3x3 image with a plus sign would be: [0, 1, 0, 1, 1, 1, 0, 1, 0]
   * Numbers are indexes into a palette, so say each pixel was a different color: [0, 1, 0, 2, 3, 4, 0, 5, 0]
   * Supplied palette would then match the indexes.
   * For example, each of these hex grey colors would correspond to the respective number 0x555555444444333333222222111111
   * So 5 would be 0x555555, 4 0x444444, etc.
   *
   * pixelCompression indicates the max number of pixels in a block. So pixelCompression 4 means you can have 2^4 (16) pixels in a block.
   * Use higher pixelCompressions for lots of repeated horizontal pixels, and lower if there aren't many sequential pixels.
   */
  function encodeColorArray(
    uint256[] memory colors,
    uint256 pixelCompression,
    uint256 colorCount
  ) external pure returns (uint256[] memory encoded);

  /**
   * @dev Composes 2 palettes together into one palette.
   * Since 0x000000 is black, we need to supply how many colors are in each palette.
   * The number of colors for a canvas are encoded within the canvas data, which is why they need to be passed explicitly.
   */

  function composePalettes(
    uint256[] memory palette1,
    uint256[] memory palette2,
    uint256 colorCount1,
    uint256 colorCount2
  ) external view returns (uint256[] memory composedPalette);

  /**
   * @dev Composes 2 encoded canvases together into one canvas.
   */

  function composeLayers(
    uint256[] memory layer1,
    uint256[] memory layer2,
    uint256 totalPixels
  ) external pure returns (uint256[] memory comp);

  /**
   * @dev Get number of colors.
   */
  function getColorCount(uint256[] memory layer) external view returns (uint256 colorCount);

  function toString(uint256 value) external pure returns (string memory);

  function toHexString(uint256 value) external pure returns (string memory);

  function base64Encode(bytes memory data) external pure returns (string memory);

  function uri(string memory data) external pure returns (string memory);

  function uriSvg(string memory data) external pure returns (string memory);
}

File 7 of 19 : MFiendsAssets.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

import "./IOnChainPixelArtv2.sol";

pragma solidity ^0.8.0;

contract MFiendsAssets {
  IOnChainPixelArtv2 private renderer;

  uint256[][96] public assets;
  uint256 public constant X = 21;
  uint256 public constant Y = 21;

  constructor(IOnChainPixelArtv2 _renderer) {
    renderer = _renderer;

    // Arms1
    assets[0] = [0x4611210510511d10510611d10520d20512510521520512521d22912510830024, 0x232e312144d];

    // Arms10
    assets[1] = [0x118d13d28d23530d33121523121522b14874b12314874b12331f306d0034];

    // Arms11
    assets[2] = [0x446f90df223e447d534254f623e447c86f90df10430014];

    // Arms12
    assets[3] = [0x8513d18424cd4c344344744344684148548184e3d22522512510830024];

    // Arms13
    assets[4] = [
      0x112c4341c8510c4b10c4520c4b22c8b12c8f2545315453144d332c9b202c0014,
      0x24792622896228ae258a681
    ];

    // Arms14
    assets[5] = [
      0x4611913221d13511513d11513511d31d32118521528512131d32512510830024,
      0x8520cf8520cf8c9
    ];

    // Arms15
    assets[6] = [0x111cd73244315c431251342c4314c4313587644531544312c431548f20830014, 0x444f];

    // Arms16
    assets[7] = [0x8853e104f9413e10510cf8424423e20913e11521d48864874828833e10810024];

    // Arms2
    assets[8] = [0x045f11cdb31c5f13493244cf34ccb35c4f10990014];

    // Arms3
    assets[9] = [0x1f12f31732b18711718712e11e12928511518521d306116105311525507f0034, 0x31];

    // Arms4
    assets[10] = [0x044cf895f10be41905f43ccb30c8d33c8f44c4f21be447c88f899f10270014];

    // Arms5
    assets[11] = [
      0x044443920484222628490526090834c1c883421510d42107a162107b10570044,
      0x1ec50841e8428f42147a10e885a10e885a1621520b22150b144288b142110b1,
      0x1884
    ];

    // Arms6
    assets[12] = [0x3210fc893cf9038d21d28c39131551d28858921720918478511b20900034];

    // Arms7
    assets[13] = [0x113511513d11113d11123521532532518458512d18478512a12610830024];

    // Arms8
    assets[14] = [0xc443f228f3e210f8813d221225221220f3e210f88a3cfc843f10270034];

    // Arms9
    assets[15] = [0x4464cb44644244944b485488843447447871841449446c610921d21a10670034];

    // Back1
    assets[16] = [0x112c5f11c4ef7bdef7c4511c4514c4512c4513c4513c451445314c5710190014, 0x89e2d];

    // Back10
    assets[17] = [0x044b1748726c4f14cd334453134c314c433245b1345b10030014];

    // Back11
    assets[18] = [0x45714c4312c4313d4f5349323c972345b1345b10180014];

    // Back12
    assets[19] = [0x04473d10d13d18511912918d11118512918510511112110d10020024];

    // Back13
    assets[20] = [0x45b12c4523c851251342c5b1244515c451144515c4511c9b20020014];

    // Back14
    assets[21] = [0x44f15c8f24ccf344cf344932445710040014];

    // Back15
    assets[22] = [0x123c9722c9b12c4af7c4b16c8b25c8f2545310590014];

    // Back16
    assets[23] = [0x0241905f20c8af7cc7364c7364c734513425134251342513402c0014];

    // Back2
    assets[24] = [0x120d22e14c54e11e14c74e11614c94e112148b4a11513510180024];

    // Back3
    assets[25] = [0x089225892239866598661b9ee97c5d102c0014];

    // Back4
    assets[26] = [0x44323c8313c9323c8313c432344314c4314c4d101c0014];

    // Back5
    assets[27] = [0x048f25c4f1549323c9722c5f10170014];

    // Back6
    assets[28] = [0x0214874a12224474621e14621e246119184b8511613e10170024];

    // Back7
    assets[29] = [0x1d12510518511518510511530511d10530d28522528520d32d31513510030024, 0x11];

    // Back8
    assets[30] = [0x134cd6f9ae687d1b40150014];

    // Back9
    assets[31] = [0x088a4790a2388a4990a228864b90622889f11c5f10170014];

    // Body
    assets[32] = [0x448f98df31be637cc6f989f57ddb90840014];

    // Body10
    assets[33] = [0x000112be647c82fa85f50be447c88fa89f30870014];

    // Body11
    assets[34] = [0x0001123e627d44f98df31be637cc4fa89f30870014];

    // Body12
    assets[35] = [0x0001123e647c4af895f123e627d44f991f10880014];

    // Body13
    assets[36] = [0x4c23d10d104f4434423d308f4434413d106105104f4434423d30870024];

    // Body14
    assets[37] = [0x044af90df223e247cc8f906227ccaf891f20870014];

    // Body15
    assets[38] = [0x1123e6a7be2a7be627d42fa8df10880014];

    // Body16
    assets[39] = [0x4443d308f4414414423d308f5423d308f5413d53930d331215235115105b0024];

    // Body2
    assets[40] = [0x44af891f10c46f98df31be627d5f1144516c4f106f0014];

    // Body3
    assets[41] = [0x131be21891f123e637cc4fa8df10880014];

    // Body4
    assets[42] = [0x02247cc4fa8df123e637cc6f991f10880014];

    // Body5
    assets[43] = [0x002627c47113e647c48f98df323e247c4310870014];

    // Body6
    assets[44] = [0x04c4fa89f31be457c4af909f675db20cc320840014];

    // Body7
    assets[45] = [0x02817d02fa11f12be237d06fa0df40850014];

    // Body8
    assets[46] = [0x0001123e457c88f90df223e457c88f911f10880014];

    // Body9
    assets[47] = [0x0991f123e627d44f98df31be627d5f20c4327c4710710014];

    // Head1
    assets[48] = [0x224433e14610cf4620480024];

    // Head10
    assets[49] = [0x004c43d110f4614423d285204f4e14423d30090024];

    // Head11
    assets[50] = [0x0130cf8718433d1c463d101e0034];

    // Head12
    assets[51] = [0x8833e14a104f8434613d10710d101c0034];

    // Head13
    assets[52] = [0x04433d310f85204f8424823d301e0024];

    // Head14
    assets[53] = [0x08518423e14614613e14814a13911513d10d101d0024];

    // Head15
    assets[54] = [0x210510613e10530613d28523e10530613e105106101d0024];

    // Head16
    assets[55] = [0x01308f4a14833e14423d18443d20200024];

    // Head2
    assets[56] = [0x2105110f8510cf4614433d18443d10200024];

    // Head3
    assets[57] = [0x01114f4443d308f4a14813d205201d0024];

    // Head4
    assets[58] = [0x4414433d30cf4614423d53930d301b0024];

    // Head5
    assets[59] = [0x1508f4614433d18510cf4614433d301e0024];

    // Head6
    assets[60] = [0x4434423d310f8510cfc414433d301e0034];

    // Head7
    assets[61] = [0x230cf85304f85285104f5023d305101d0024];

    // Head8
    assets[62] = [0x110cf5413d106105104f4418414413d10d101d0024];

    // Head9
    assets[63] = [0x004614423d30cf4418443d40cf8414433d20090024];

    // Legs1
    assets[64] = [0x0886218862f88e217c4710bea27cc4f88e217c4711040014];

    // Legs10
    assets[65] = [0x094719172c54173045b14ec46a12a84791820609112e0044];

    // Legs11
    assets[66] = [
      0x3120910923528518523610510510510613511513210910d10a12d21520ed0024,
      0x8433e10e13e10a10a13620910a2
    ];

    // Legs12
    assets[67] = [0x2227c451145910c4511443154431144510c5510dc3155435648721180014];

    // Legs13
    assets[68] = [0x212cf3d110f4c23d504f5423d105112f0024];

    // Legs14
    assets[69] = [0x04c4f9064f9062193a219862f906417c47112e0014];

    // Legs15
    assets[70] = [0x111c42f88e217c8327cc3374c33748726c8b2648b2644f10d80014];

    // Legs16
    assets[71] = [0x0886227c4716c853744511c5bb744311c5b11c4321160014];

    // Legs2
    assets[72] = [0x0054f46154d4e14e144d56144f4e14423d312f0024];

    // Legs3
    assets[73] = [0x88e217c8320be23885f11c42f906417c83212e0014];

    // Legs4
    assets[74] = [0x4c63e108f4c144e4611113910518510513920d212d0024];

    // Legs5
    assets[75] = [0x2217c45114491544511443264c510c5f664871744340cccf915f11010014];

    // Legs6
    assets[76] = [0x5074550745cc736c8727487274872748727c4711190014];

    // Legs7
    assets[77] = [
      0x05104f8418413d1073051391c63c513b18510518713a14434613d10d11040034,
      0x210cf8433d10e1
    ];

    // Legs8
    assets[78] = [0x0220e23918438513911513930533a15613d205212e0024];

    // Legs9
    assets[79] = [0x08443d105108f8510518413e144146104f8510518413e10e11190024];

    // Rune1
    assets[80] = [0x44cf895f12be237c45109b0014];

    // Rune10
    assets[81] = [0x448f991f10b20014];

    // Rune11
    assets[82] = [0x44cf899f10b10014];

    // Rune12
    assets[83] = [0x221891f12be257c8af88df109e0014];

    // Rune13
    assets[84] = [0x2257c8af915f10b10014];

    // Rune14
    assets[85] = [0x44cf895f123e2188df109e0014];

    // Rune15
    assets[86] = [0x44af891f10c48f895f109d0014];

    // Rune16
    assets[87] = [0x02437c4cf8a9ef991f109d0014];

    // Rune2
    assets[88] = [0x899f133e237c43109c0014];

    // Rune3
    assets[89] = [0x0899f12be447c48f915f109d0014];

    // Rune4
    assets[90] = [0x02437c4311be2188df20b20014];

    // Rune5
    assets[91] = [0x0456f7c4af911f109d0014];

    // Rune6
    assets[92] = [0x0125bdf15bdf209c0014];

    // Rune7
    assets[93] = [0x2257c4af895f209c0014];

    // Rune8
    assets[94] = [0x0452f7c8af895f109d0014];

    // Rune9
    assets[95] = [0x02247c56f7c48f98df109e0014];
  }

  function composeLayers(uint256[] memory layerIds)
    public
    view
    returns (uint256[] memory composed)
  {
    uint256[] memory composedLayers = assets[layerIds[0]];
    uint256 nextLayer;

    for (uint256 i; i < layerIds.length - 1; i += 1) {
      nextLayer = layerIds[i + 1];
      composedLayers = renderer.composeLayers(composedLayers, assets[nextLayer], X * Y);
    }

    return composedLayers;
  }
}

File 8 of 19 : MFiendCharacteristics.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.0 <0.9.0;

contract MFiendCharacteristics {
  //Basic types
  uint8 private constant PROTOTYPICAL = 0;
  uint8 private constant VIBRANT = 1;

  //Elemental types
  uint8 private constant PLASMIC = 2;
  uint8 private constant FLUID = 3;
  uint8 private constant ORGANIC = 4;

  //Elemental types
  uint8 private constant UMBRAL = 5;
  uint8 private constant LUMINOUS = 6;
  uint8 private constant ABYSSAL = 7;

  uint256 private constant MASK = 0xFF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000;

  string[] public affinityToName = [
    "Prototypical",
    "Vibrant",
    "Plasmic",
    "Fluid",
    "Organic",
    "Umbral",
    "Luminous",
    "Abyssal"
  ];

  uint24[8] public affinityToColor = [
    0xc7c5c5,
    0xfbc9ff,
    0xffc9c9,
    0xc9e0ff,
    0xdffade,
    0x796791,
    0xfffef0,
    0x171717
  ];

  function getAffinity(uint256 tokenData) public pure returns (uint256) {
    // roll is out of 32
    uint256 roll = (tokenData >> 251);

    if (roll == 0) {
      return ABYSSAL;
    }
    if (roll <= 2) {
      return UMBRAL;
    }
    if (roll <= 4) {
      return LUMINOUS;
    }
    if (roll <= 8) {
      return PLASMIC;
    }
    if (roll <= 12) {
      return FLUID;
    }
    if (roll <= 16) {
      return ORGANIC;
    }
    if (roll <= 24) {
      return VIBRANT;
    }
    return PROTOTYPICAL;
  }

  function getUmbralColor(uint256 color) internal pure returns (uint256) {
    return color % 64;
  }

  function getLuminousColor(uint256 color) internal pure returns (uint256) {
    return 192 + (color % 64);
  }

  function getPrototypicalColor(uint256 color) internal pure returns (uint256) {
    return 112 + (color % 32);
  }

  function getAdjustedColors(uint256 tokenData, function(uint256) pure returns (uint256) adjuster)
    internal
    pure
    returns (uint256)
  {
    uint256 palette;
    for (uint256 i = 0; i < 10; i += 1) {
      uint256 shifted = tokenData >> (i * 24);
      uint256 r = shifted & 0xFF;
      uint256 g = (shifted & 0xFF00) >> 8;
      uint256 b = (shifted & 0xFF0000) >> 16;

      uint256 rAdjusted = adjuster(r);
      uint256 gAdjusted = adjuster(g);
      uint256 bAdjusted = adjuster(b);

      uint256 packedColor = bAdjusted + (gAdjusted << 8) + (rAdjusted << 16);

      palette = palette + (packedColor << (i * 24));
    }
    return palette;
  }

  function protoypicalPalette(uint256 tokenData) internal pure returns (uint256) {
    return getAdjustedColors(tokenData, getPrototypicalColor);
  }

  function umbralPalette(uint256 tokenData) internal pure returns (uint256) {
    return getAdjustedColors(tokenData, getUmbralColor);
  }

  function luminousPalette(uint256 tokenData) internal pure returns (uint256) {
    return getAdjustedColors(tokenData, getLuminousColor);
  }

  function plasmicPalette(uint256 tokenData) internal pure returns (uint256) {
    uint256 masked = (tokenData & (MASK >> 8)) + (tokenData & (MASK >> 16));
    return masked + MASK;
  }

  function fluidPalette(uint256 tokenData) internal pure returns (uint256) {
    uint256 masked = (tokenData & (MASK >> 8)) + (tokenData & (MASK));
    return masked + (MASK >> 16);
  }

  function organicPalette(uint256 tokenData) internal pure returns (uint256) {
    uint256 masked = (tokenData & (MASK)) + (tokenData & (MASK >> 16));
    return masked + (MASK >> 8);
  }

  function abyssalPalette(uint256 tokenData) internal pure returns (uint256) {
    uint256 masked = tokenData & MASK;
    return masked + (masked >> 8) + (masked >> 16);
  }

  function getPalette(uint256 tokenData, uint256 affinity) public pure returns (uint256) {
    if (affinity == PROTOTYPICAL) {
      return protoypicalPalette(tokenData);
    }

    if (affinity == VIBRANT) {
      return tokenData;
    }

    if (affinity == PLASMIC) {
      return plasmicPalette(tokenData);
    }

    if (affinity == FLUID) {
      return fluidPalette(tokenData);
    }

    if (affinity == ORGANIC) {
      return organicPalette(tokenData);
    }

    if (affinity == UMBRAL) {
      return umbralPalette(tokenData);
    }

    if (affinity == LUMINOUS) {
      return luminousPalette(tokenData);
    }

    return abyssalPalette(tokenData);
  }
}

File 9 of 19 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
  /**
   * @dev Returns the total amount of tokens stored by the contract.
   */
  function totalSupply() external view returns (uint256);

  /**
   * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
   * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
   */
  function tokenOfOwnerByIndex(address owner, uint256 index)
    external
    view
    returns (uint256 tokenId);

  /**
   * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
   * Use along with {totalSupply} to enumerate all tokens.
   */
  function tokenByIndex(uint256 index) external view returns (uint256);
}

File 10 of 19 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId)
        external
        view
        returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator)
        external
        view
        returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

File 11 of 19 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 12 of 19 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 13 of 19 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;

library console {
	address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

	function _sendLogPayload(bytes memory payload) private view {
		uint256 payloadLength = payload.length;
		address consoleAddress = CONSOLE_ADDRESS;
		assembly {
			let payloadStart := add(payload, 32)
			let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
		}
	}

	function log() internal view {
		_sendLogPayload(abi.encodeWithSignature("log()"));
	}

	function logInt(int p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
	}

	function logUint(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function logString(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function logBool(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function logAddress(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function logBytes(bytes memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
	}

	function logBytes1(bytes1 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
	}

	function logBytes2(bytes2 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
	}

	function logBytes3(bytes3 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
	}

	function logBytes4(bytes4 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
	}

	function logBytes5(bytes5 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
	}

	function logBytes6(bytes6 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
	}

	function logBytes7(bytes7 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
	}

	function logBytes8(bytes8 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
	}

	function logBytes9(bytes9 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
	}

	function logBytes10(bytes10 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
	}

	function logBytes11(bytes11 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
	}

	function logBytes12(bytes12 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
	}

	function logBytes13(bytes13 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
	}

	function logBytes14(bytes14 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
	}

	function logBytes15(bytes15 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
	}

	function logBytes16(bytes16 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
	}

	function logBytes17(bytes17 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
	}

	function logBytes18(bytes18 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
	}

	function logBytes19(bytes19 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
	}

	function logBytes20(bytes20 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
	}

	function logBytes21(bytes21 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
	}

	function logBytes22(bytes22 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
	}

	function logBytes23(bytes23 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
	}

	function logBytes24(bytes24 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
	}

	function logBytes25(bytes25 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
	}

	function logBytes26(bytes26 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
	}

	function logBytes27(bytes27 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
	}

	function logBytes28(bytes28 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
	}

	function logBytes29(bytes29 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
	}

	function logBytes30(bytes30 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
	}

	function logBytes31(bytes31 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
	}

	function logBytes32(bytes32 p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
	}

	function log(uint p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
	}

	function log(string memory p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
	}

	function log(bool p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
	}

	function log(address p0) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
	}

	function log(uint p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
	}

	function log(uint p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
	}

	function log(uint p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
	}

	function log(uint p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
	}

	function log(string memory p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
	}

	function log(string memory p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
	}

	function log(string memory p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
	}

	function log(string memory p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
	}

	function log(bool p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
	}

	function log(bool p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
	}

	function log(bool p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
	}

	function log(bool p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
	}

	function log(address p0, uint p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
	}

	function log(address p0, string memory p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
	}

	function log(address p0, bool p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
	}

	function log(address p0, address p1) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
	}

	function log(uint p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
	}

	function log(uint p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
	}

	function log(uint p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
	}

	function log(uint p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
	}

	function log(uint p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
	}

	function log(uint p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
	}

	function log(uint p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
	}

	function log(uint p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
	}

	function log(uint p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
	}

	function log(uint p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
	}

	function log(uint p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
	}

	function log(uint p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
	}

	function log(uint p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
	}

	function log(string memory p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
	}

	function log(string memory p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
	}

	function log(string memory p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
	}

	function log(string memory p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
	}

	function log(string memory p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
	}

	function log(string memory p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
	}

	function log(string memory p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
	}

	function log(bool p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
	}

	function log(bool p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
	}

	function log(bool p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
	}

	function log(bool p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
	}

	function log(bool p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
	}

	function log(bool p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
	}

	function log(bool p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
	}

	function log(bool p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
	}

	function log(bool p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
	}

	function log(bool p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
	}

	function log(bool p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
	}

	function log(bool p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
	}

	function log(bool p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
	}

	function log(address p0, uint p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
	}

	function log(address p0, uint p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
	}

	function log(address p0, uint p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
	}

	function log(address p0, uint p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
	}

	function log(address p0, string memory p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
	}

	function log(address p0, string memory p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
	}

	function log(address p0, string memory p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
	}

	function log(address p0, string memory p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
	}

	function log(address p0, bool p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
	}

	function log(address p0, bool p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
	}

	function log(address p0, bool p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
	}

	function log(address p0, bool p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
	}

	function log(address p0, address p1, uint p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
	}

	function log(address p0, address p1, string memory p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
	}

	function log(address p0, address p1, bool p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
	}

	function log(address p0, address p1, address p2) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
	}

	function log(uint p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
	}

	function log(uint p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
	}

	function log(string memory p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
	}

	function log(bool p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, uint p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, string memory p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, bool p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, uint p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, string memory p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, bool p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, uint p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, string memory p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, bool p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
	}

	function log(address p0, address p1, address p2, address p3) internal view {
		_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
	}

}

File 14 of 19 : ERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Metadata.sol";
import "./IERC721Receiver.sol";
import "./Address.sol";
import "./Strings.sol";
import "./Context.sol";
import "./ERC165.sol";
import "hardhat/console.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
  using Address for address;
  using Strings for uint256;

  // Token name
  string private _name;

  // Token symbol
  string private _symbol;

  // Mapping from token ID to owner address
  mapping(uint256 => address) private _owners;

  // Mapping owner address to token count
  mapping(address => uint256) private _balances;

  // Mapping from token ID to approved address
  mapping(uint256 => address) private _tokenApprovals;

  // Mapping from owner to operator approvals
  mapping(address => mapping(address => bool)) private _operatorApprovals;

  /**
   * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
   */
  constructor(string memory name_, string memory symbol_) {
    _name = name_;
    _symbol = symbol_;
  }

  /**
   * @dev See {IERC165-supportsInterface}.
   */
  function supportsInterface(bytes4 interfaceId)
    public
    view
    virtual
    override(ERC165, IERC165)
    returns (bool)
  {
    return
      interfaceId == type(IERC721).interfaceId ||
      interfaceId == type(IERC721Metadata).interfaceId ||
      super.supportsInterface(interfaceId);
  }

  /**
   * @dev See {IERC721-balanceOf}.
   */
  function balanceOf(address owner)
    public
    view
    virtual
    override
    returns (uint256)
  {
    require(owner != address(0), "ERC721: balance query for the zero address");
    return _balances[owner];
  }

  /**
   * @dev See {IERC721-ownerOf}.
   */
  function ownerOf(uint256 tokenId)
    public
    view
    virtual
    override
    returns (address)
  {
    address owner = _owners[tokenId];
    require(owner != address(0), "ERC721: owner query for nonexistent token");
    return owner;
  }

  /**
   * @dev See {IERC721Metadata-name}.
   */
  function name() public view virtual override returns (string memory) {
    return _name;
  }

  /**
   * @dev See {IERC721Metadata-symbol}.
   */
  function symbol() public view virtual override returns (string memory) {
    return _symbol;
  }

  /**
   * @dev See {IERC721Metadata-tokenURI}.
   */
  function tokenURI(uint256 tokenId)
    public
    view
    virtual
    override
    returns (string memory)
  {
    require(
      _exists(tokenId),
      "ERC721Metadata: URI query for nonexistent token"
    );

    string memory baseURI = _baseURI();
    return
      bytes(baseURI).length > 0
        ? string(abi.encodePacked(baseURI, tokenId.toString()))
        : "";
  }

  /**
   * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
   * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
   * by default, can be overriden in child contracts.
   */
  function _baseURI() internal view virtual returns (string memory) {
    return "";
  }

  /**
   * @dev See {IERC721-approve}.
   */
  function approve(address to, uint256 tokenId) public virtual override {
    address owner = ERC721.ownerOf(tokenId);
    require(to != owner, "ERC721: approval to current owner");

    require(
      _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
      "ERC721: approve caller is not owner nor approved for all"
    );

    _approve(to, tokenId);
  }

  /**
   * @dev See {IERC721-getApproved}.
   */
  function getApproved(uint256 tokenId)
    public
    view
    virtual
    override
    returns (address)
  {
    require(_exists(tokenId), "ERC721: approved query for nonexistent token");

    return _tokenApprovals[tokenId];
  }

  /**
   * @dev See {IERC721-setApprovalForAll}.
   */
  function setApprovalForAll(address operator, bool approved)
    public
    virtual
    override
  {
    require(operator != _msgSender(), "ERC721: approve to caller");

    _operatorApprovals[_msgSender()][operator] = approved;
    emit ApprovalForAll(_msgSender(), operator, approved);
  }

  /**
   * @dev See {IERC721-isApprovedForAll}.
   */
  function isApprovedForAll(address owner, address operator)
    public
    view
    virtual
    override
    returns (bool)
  {
    return _operatorApprovals[owner][operator];
  }

  /**
   * @dev See {IERC721-transferFrom}.
   */
  function transferFrom(
    address from,
    address to,
    uint256 tokenId
  ) public virtual override {
    //solhint-disable-next-line max-line-length
    require(
      _isApprovedOrOwner(_msgSender(), tokenId),
      "ERC721: transfer caller is not owner nor approved"
    );

    _transfer(from, to, tokenId);
  }

  /**
   * @dev See {IERC721-safeTransferFrom}.
   */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId
  ) public virtual override {
    safeTransferFrom(from, to, tokenId, "");
  }

  /**
   * @dev See {IERC721-safeTransferFrom}.
   */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes memory _data
  ) public virtual override {
    require(
      _isApprovedOrOwner(_msgSender(), tokenId),
      "ERC721: transfer caller is not owner nor approved"
    );
    _safeTransfer(from, to, tokenId, _data);
  }

  /**
   * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
   * are aware of the ERC721 protocol to prevent tokens from being forever locked.
   *
   * `_data` is additional data, it has no specified format and it is sent in call to `to`.
   *
   * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
   * implement alternative mechanisms to perform token transfer, such as signature-based.
   *
   * Requirements:
   *
   * - `from` cannot be the zero address.
   * - `to` cannot be the zero address.
   * - `tokenId` token must exist and be owned by `from`.
   * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
   *
   * Emits a {Transfer} event.
   */
  function _safeTransfer(
    address from,
    address to,
    uint256 tokenId,
    bytes memory _data
  ) internal virtual {
    _transfer(from, to, tokenId);
    require(
      _checkOnERC721Received(from, to, tokenId, _data),
      "ERC721: transfer to non ERC721Receiver implementer"
    );
  }

  /**
   * @dev Returns whether `tokenId` exists.
   *
   * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
   *
   * Tokens start existing when they are minted (`_mint`),
   * and stop existing when they are burned (`_burn`).
   */
  function _exists(uint256 tokenId) internal view virtual returns (bool) {
    return _owners[tokenId] != address(0);
  }

  /**
   * @dev Returns whether `spender` is allowed to manage `tokenId`.
   *
   * Requirements:
   *
   * - `tokenId` must exist.
   */
  function _isApprovedOrOwner(address spender, uint256 tokenId)
    internal
    view
    virtual
    returns (bool)
  {
    require(_exists(tokenId), "ERC721: operator query for nonexistent token");
    address owner = ERC721.ownerOf(tokenId);
    return (spender == owner ||
      getApproved(tokenId) == spender ||
      isApprovedForAll(owner, spender));
  }

  /**
   * @dev Safely mints `tokenId` and transfers it to `to`.
   *
   * Requirements:
   *
   * - `tokenId` must not exist.
   * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
   *
   * Emits a {Transfer} event.
   */
  function _safeMint(address to, uint256 tokenId) internal virtual {
    _safeMint(to, tokenId, "");
  }

  /**
   * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
   * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
   */
  function _safeMint(
    address to,
    uint256 tokenId,
    bytes memory _data
  ) internal virtual {
    _mint(to, tokenId);
    require(
      _checkOnERC721Received(address(0), to, tokenId, _data),
      "ERC721: transfer to non ERC721Receiver implementer"
    );
  }

  /**
   * @dev Mints `tokenId` and transfers it to `to`.
   *
   * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
   *
   * Requirements:
   *
   * - `tokenId` must not exist.
   * - `to` cannot be the zero address.
   *
   * Emits a {Transfer} event.
   */
  function _mint(address to, uint256 tokenId) internal virtual {
    require(to != address(0), "ERC721: mint to the zero address");
    require(!_exists(tokenId), "ERC721: token already minted");

    _beforeTokenTransfer(address(0), to, tokenId);

    _balances[to] += 1;
    _owners[tokenId] = to;

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

  /**
   * @dev Destroys `tokenId`.
   * The approval is cleared when the token is burned.
   *
   * Requirements:
   *
   * - `tokenId` must exist.
   *
   * Emits a {Transfer} event.
   */
  function _burn(uint256 tokenId) internal virtual {
    address owner = ERC721.ownerOf(tokenId);

    _beforeTokenTransfer(owner, address(0), tokenId);

    // Clear approvals
    _approve(address(0), tokenId);

    _balances[owner] -= 1;
    delete _owners[tokenId];

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

  /**
   * @dev Transfers `tokenId` from `from` to `to`.
   *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
   *
   * Requirements:
   *
   * - `to` cannot be the zero address.
   * - `tokenId` token must be owned by `from`.
   *
   * Emits a {Transfer} event.
   */
  function _transfer(
    address from,
    address to,
    uint256 tokenId
  ) internal virtual {
    require(
      ERC721.ownerOf(tokenId) == from,
      "ERC721: transfer of token that is not own"
    );
    require(to != address(0), "ERC721: transfer to the zero address");

    _beforeTokenTransfer(from, to, tokenId);

    // Clear approvals from the previous owner
    _approve(address(0), tokenId);

    _balances[from] -= 1;
    _balances[to] += 1;
    _owners[tokenId] = to;

    emit Transfer(from, to, tokenId);
  }

  /**
   * @dev Approve `to` to operate on `tokenId`
   *
   * Emits a {Approval} event.
   */
  function _approve(address to, uint256 tokenId) internal virtual {
    _tokenApprovals[tokenId] = to;
    emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
  }

  /**
   * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
   * The call is not executed if the target address is not a contract.
   *
   * @param from address representing the previous owner of the given token ID
   * @param to target address that will receive the tokens
   * @param tokenId uint256 ID of the token to be transferred
   * @param _data bytes optional data to send along with the call
   * @return bool whether the call correctly returned the expected magic value
   */
  function _checkOnERC721Received(
    address from,
    address to,
    uint256 tokenId,
    bytes memory _data
  ) private returns (bool) {
    if (to.isContract()) {
      try
        IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data)
      returns (bytes4 retval) {
        return retval == IERC721Receiver(to).onERC721Received.selector;
      } catch (bytes memory reason) {
        if (reason.length == 0) {
          revert("ERC721: transfer to non ERC721Receiver implementer");
        } else {
          assembly {
            revert(add(32, reason), mload(reason))
          }
        }
      }
    } else {
      return true;
    }
  }

  /**
   * @dev Hook that is called before any token transfer. This includes minting
   * and burning.
   *
   * Calling conditions:
   *
   * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
   * transferred to `to`.
   * - When `from` is zero, `tokenId` will be minted for `to`.
   * - When `to` is zero, ``from``'s `tokenId` will be burned.
   * - `from` and `to` are never both zero.
   *
   * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
   */
  function _beforeTokenTransfer(
    address from,
    address to,
    uint256 tokenId
  ) internal virtual {}
}

File 15 of 19 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 16 of 19 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 17 of 19 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) private pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 18 of 19 : Strings.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

File 19 of 19 : ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IMGear","name":"_mineableGear","type":"address"},{"internalType":"contract IOnChainPixelArtv2","name":"_onChainPixelArt","type":"address"},{"internalType":"uint256","name":"_difficulty","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":"X","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Y","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"affinityToColor","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"affinityToName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"assertValidGear","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"assets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"composeLayers","outputs":[{"internalType":"uint256[]","name":"composed","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ruinItemId","type":"uint256"},{"internalType":"uint256","name":"guardItemId","type":"uint256"},{"internalType":"uint256","name":"vigorItemId","type":"uint256"},{"internalType":"uint256","name":"celerityItemId","type":"uint256"}],"name":"equipItems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"equipped","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"equippedBy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"game","type":"uint256"},{"components":[{"internalType":"uint64","name":"ruin","type":"uint64"},{"internalType":"uint64","name":"guard","type":"uint64"},{"internalType":"uint64","name":"vigor","type":"uint64"},{"internalType":"uint64","name":"celerity","type":"uint64"}],"internalType":"struct MFiends.Stats","name":"challenger","type":"tuple"},{"components":[{"internalType":"uint64","name":"ruin","type":"uint64"},{"internalType":"uint64","name":"guard","type":"uint64"},{"internalType":"uint64","name":"vigor","type":"uint64"},{"internalType":"uint64","name":"celerity","type":"uint64"}],"internalType":"struct MFiends.Stats","name":"enemy","type":"tuple"}],"name":"executeGame","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"seed","type":"uint256"},{"components":[{"internalType":"uint64","name":"ruin","type":"uint64"},{"internalType":"uint64","name":"guard","type":"uint64"},{"internalType":"uint64","name":"vigor","type":"uint64"},{"internalType":"uint64","name":"celerity","type":"uint64"}],"internalType":"struct MFiends.Stats","name":"challenger","type":"tuple"},{"internalType":"uint256","name":"affinity","type":"uint256"}],"name":"generateEnemy","outputs":[{"components":[{"internalType":"uint64","name":"ruin","type":"uint64"},{"internalType":"uint64","name":"guard","type":"uint64"},{"internalType":"uint64","name":"vigor","type":"uint64"},{"internalType":"uint64","name":"celerity","type":"uint64"}],"internalType":"struct MFiends.Stats","name":"enemy","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenData","type":"uint256"}],"name":"getAffinity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","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":"tokenId","type":"uint256"}],"name":"getAttributes","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getCharacteristicsData","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getEquippedItems","outputs":[{"internalType":"uint256[4]","name":"gear","type":"uint256[4]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mgear","type":"uint256"}],"name":"getMajorType","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"mgear","type":"uint256"}],"name":"getMajorValue","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mgear","type":"uint256"}],"name":"getMinorType1","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mgear","type":"uint256"}],"name":"getMinorType2","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mgear","type":"uint256"}],"name":"getMinorValue1","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mgear","type":"uint256"}],"name":"getMinorValue2","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenData","type":"uint256"},{"internalType":"uint256","name":"affinity","type":"uint256"}],"name":"getPalette","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"ruin","type":"uint64"},{"internalType":"uint64","name":"guard","type":"uint64"},{"internalType":"uint64","name":"vigor","type":"uint64"},{"internalType":"uint64","name":"celerity","type":"uint64"}],"internalType":"struct MFiends.Stats","name":"charStats","type":"tuple"}],"name":"getPowerLevel","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getStatsFromToken","outputs":[{"components":[{"internalType":"uint64","name":"ruin","type":"uint64"},{"internalType":"uint64","name":"guard","type":"uint64"},{"internalType":"uint64","name":"vigor","type":"uint64"},{"internalType":"uint64","name":"celerity","type":"uint64"}],"internalType":"struct MFiends.Stats","name":"","type":"tuple"}],"stateMutability":"view","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":[{"internalType":"uint96","name":"nonce","type":"uint96"},{"internalType":"bool","name":"callForHelp","type":"bool"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","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":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"rarityToTiers","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenData","type":"uint256"},{"internalType":"uint256[]","name":"palette","type":"uint256[]"},{"internalType":"string","name":"backgroundColor","type":"string"}],"name":"renderData","outputs":[{"internalType":"string","name":"svg","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenTraits","type":"uint256"},{"internalType":"uint256","name":"paletteData","type":"uint256"},{"internalType":"uint256","name":"affinity","type":"uint256"}],"name":"renderFiend","outputs":[{"internalType":"string","name":"svg","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"renderTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stats","outputs":[{"internalType":"uint64","name":"ruin","type":"uint64"},{"internalType":"uint64","name":"guard","type":"uint64"},{"internalType":"uint64","name":"vigor","type":"uint64"},{"internalType":"uint64","name":"celerity","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","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":"","type":"uint256"}],"name":"tierToStatBase","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"traits","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

600b805460ff19166005908117909155600c6101809081526b141c9bdd1bdd1e5c1a58d85b60a21b6101a052608090815260076101c081815266159a589c985b9d60ca1b6101e05260a05261020081815266506c61736d696360c81b6102205260c05261024092835264119b1d5a5960da1b6102605260e092909252610280828152664f7267616e696360c81b6102a0526101005260066102c090815265155b589c985b60d21b6102e052610120526008610300818152674c756d696e6f757360c01b61032052610140526103806040526103409283526610589e5cdcd85b60ca1b6103605261016092909252620000fb916074919062001948565b50604080516101008101825262c7c5c5815262fbc9ff602082015262ffc9c99181019190915262c9e0ff606082015262dffade60808201526279679160a082015262fffef060c08201526217171760e08201526200015e906075906008620019ac565b50604080516104008101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905260036101008301819052610120830182905261014083018290526001610160840181905261018084018390526101a08401526101c083018290526101e083018190526102008301829052600261022084018190526102408401819052610260840183905261028084018290526102a084018290526102c084018390526102e084018390526103008401839052610320840192909252610340830181905260046103608401526103808301526103a082018190526103c082018190526103e082015262000270916081919062001a48565b503480156200027e57600080fd5b5060405162007b8538038062007b85833981016040819052620002a19162002248565b81604051806040016040528060078152602001664d4669656e647360c81b815250604051806040016040528060078152602001664d4649454e445360c81b815250620002fc620002f6620018f460201b60201c565b620018f8565b81516200031190600190602085019062001ace565b5080516200032790600290602084019062001ace565b5050600c805463ffffffff19166306030000179055506040805160608101825260018152600060208201819052918101919091526200036b90600d90600362001a48565b506040805160608101825260028152600060208201819052918101919091526200039a90600e90600362001a48565b50604080516060810182526002815260016020820152600091810191909152620003c990600f90600362001a48565b506040805160608101825260028082526020820152600091810191909152620003f790601090600362001a48565b506040805160608101825260038082526002602083015260019282019290925262000426916011919062001a48565b506040805160608101825260038082526002602083018190529282019290925262000455916012919062001a48565b50601380546001600160a01b0319166001600160a01b038316179055604080518082019091527f4611210510511d10510611d10520d20512510521520512521d229125108300248152650232e312144d6020820152620004ba90601490600262001b4b565b5060408051602081019091527d118d13d28d23530d33121523121522b14874b12314874b12331f306d00348152620004f790601590600162001b88565b50604080516020810190915276446f90df223e447d534254f623e447c86f90df1043001481526200052d90601690600162001bd1565b5060408051602081019091527c8513d18424cd4c344344744344684148548184e3d2252251251083002481526200056990601790600162001c1a565b50604080518082019091527f112c4341c8510c4b10c4520c4b22c8b12c8f2545315453144d332c9b202c001481526b024792622896228ae258a6816020820152620005b990601890600262001b4b565b50604080518082019091527f4611913221d13511513d11513511d31d32118521528512131d3251251083002481526708520cf8520cf8c960208201526200060590601990600262001b4b565b50604080518082019091527f111cd73244315c431251342c4314c4313587644531544312c431548f20830014815261444f60208201526200064b90601a90600262001b4b565b5060408051602081019091527f8853e104f9413e10510cf8424423e20913e11521d48864874828833e1081002481526200068a90601b90600162001b4b565b50604080516020810190915274045f11cdb31c5f13493244cf34ccb35c4f109900148152620006be90601c90600162001c63565b50604080518082019091527f1f12f31732b18711718712e11e12928511518521d306116105311525507f00348152603160208201526200070390601d90600262001b4b565b5060408051602081019091527e044cf895f10be41905f43ccb30c8d33c8f44c4f21be447c88f899f1027001481526200074190601e90600162001cac565b50604080516060810182527f044443920484222628490526090834c1c883421510d42107a162107b1057004481527f01ec50841e8428f42147a10e885a10e885a1621520b22150b144288b142110b1602082015261188491810191909152620007af90601f90600362001b4b565b506040805160208082019092527d3210fc893cf9038d21d28c39131551d28858921720918478511b209000348152620007eb9190600162001b88565b5060408051602081019091527d113511513d11113d11123521532532518458512d18478512a1261083002481526200082890602190600162001b88565b5060408051602081019091527cc443f228f3e210f8813d221225221220f3e210f88a3cfc843f1027003481526200086490602290600162001c1a565b5060408051602081019091527f4464cb44644244944b485488843447447871841449446c610921d21a106700348152620008a390602390600162001b4b565b50604080518082019091527f112c5f11c4ef7bdef7c4511c4514c4512c4513c4513c451445314c5710190014815262089e2d6020820152620008ea90602490600262001b4b565b50604080516020810190915279044b1748726c4f14cd334453134c314c433245b1345b1003001481526200092390602590600162001cf5565b5060408051602081019091527645714c4312c4313d4f5349323c972345b1345b1018001481526200095990602690600162001bd1565b5060408051602081019091527b04473d10d13d18511912918d11118512918510511112110d1002002481526200099490602790600162001d3e565b5060408051602081019091527b45b12c4523c851251342c5b1244515c451144515c4511c9b200200148152620009cf90602890600162001d3e565b5060408051602081019091527144f15c8f24ccf344cf344932445710040014815262000a0090602990600162001d87565b50604080516020810190915275123c9722c9b12c4af7c4b16c8b25c8f2545310590014815262000a3590602a90600162001dd0565b5060408051602081019091527b0241905f20c8af7cc7364c7364c734513425134251342513402c0014815262000a7090602b90600162001d3e565b5060408051602081019091527a120d22e14c54e11e14c74e11614c94e112148b4a11513510180024815262000aaa90602c90600162001e19565b50604080516020810190915272089225892239866598661b9ee97c5d102c0014815262000adc90602d90600162001e62565b5060408051602081019091527644323c8313c9323c8313c432344314c4314c4d101c0014815262000b1290602e90600162001bd1565b5060408051602081019091526f048f25c4f1549323c9722c5f10170014815262000b4190602f90600162001eab565b506040805160208101909152790214874a12224474621e14621e246119184b8511613e10170024815262000b7a90603090600162001cf5565b50604080518082019091527f1d12510518511518510511530511d10530d28522528520d32d3151351003002481526011602082015262000bbf90603190600262001b4b565b5060408051602081019091526b134cd6f9ae687d1b40150014815262000bea90603290600162001ef4565b50604080516020810190915277088a4790a2388a4990a228864b90622889f11c5f10170014815262000c2190603390600162001f3d565b50604080516020810190915271448f98df31be637cc6f989f57ddb90840014815262000c5290603490600162001d87565b506040805160208101909152730112be647c82fa85f50be447c88fa89f30870014815262000c8590603590600162001f86565b5060408051602081019091527301123e627d44f98df31be637cc4fa89f30870014815262000cb890603690600162001f86565b5060408051602081019091527301123e647c4af895f123e627d44f991f10880014815262000ceb90603790600162001f86565b5060408051602081019091527c4c23d10d104f4434423d308f4434413d106105104f4434423d30870024815262000d2790603890600162001c1a565b50604080516020810190915274044af90df223e247cc8f906227ccaf891f20870014815262000d5b90603990600162001c63565b506040805160208101909152701123e6a7be2a7be627d42fa8df10880014815262000d8b90603a90600162001fcf565b5060408051602081019091527f4443d308f4414414423d308f5423d308f5413d53930d331215235115105b0024815262000dca90603b90600162001b4b565b5060408051602081019091527644af891f10c46f98df31be627d5f1144516c4f106f0014815262000e0090603c90600162001bd1565b50604080516020810190915270131be21891f123e637cc4fa8df10880014815262000e3090603d90600162001fcf565b5060408051602081019091527102247cc4fa8df123e637cc6f991f10880014815262000e6190603e90600162001d87565b506040805160208101909152732627c47113e647c48f98df323e247c4310870014815262000e9490603f90600162001f86565b50604080516020810182527404c4fa89f31be457c4af909f675db20cc320840014815262000ec59190600162001c63565b5060408051602081019091527102817d02fa11f12be237d06fa0df40850014815262000ef690604190600162001d87565b5060408051602081019091527301123e457c88f90df223e457c88f911f10880014815262000f2990604290600162001f86565b506040805160208101909152770991f123e627d44f98df31be627d5f20c4327c4710710014815262000f6090604390600162001f3d565b5060408051602081019091526b224433e14610cf4620480024815262000f8b90604490600162001ef4565b506040805160208101909152734c43d110f4614423d285204f4e14423d30090024815262000fbe90604590600162001f86565b5060408051602081019091526d0130cf8718433d1c463d101e0034815262000feb90604690600162002018565b506040805160208101909152708833e14a104f8434613d10710d101c003481526200101b90604790600162001fcf565b5060408051602081019091526f04433d310f85204f8424823d301e002481526200104a90604890600162001eab565b5060408051602081019091527508518423e14614613e14814a13911513d10d101d002481526200107f90604990600162001dd0565b50604080516020810190915277210510613e10530613d28523e10530613e105106101d00248152620010b690604a90600162001f3d565b5060408051602081019091527001308f4a14833e14423d18443d202000248152620010e690604b90600162001fcf565b506040805160208101909152712105110f8510cf4614433d18443d1020002481526200111790604c90600162001d87565b5060408051602081019091527001114f4443d308f4a14813d205201d002481526200114790604d90600162001fcf565b506040805160208101909152704414433d30cf4614423d53930d301b002481526200117790604e90600162001fcf565b506040805160208101909152711508f4614433d18510cf4614433d301e00248152620011a890604f90600162001d87565b506040805160208101909152704434423d310f8510cfc414433d301e00348152620011d890605090600162001fcf565b50604080516020810190915271230cf85304f85285104f5023d305101d002481526200120990605190600162001d87565b50604080516020810190915274110cf5413d106105104f4418414413d10d101d002481526200123d90605290600162001c63565b506040805160208101909152734614423d30cf4418443d40cf8414433d2009002481526200127090605390600162001f86565b506040805160208101909152770886218862f88e217c4710bea27cc4f88e217c47110400148152620012a790605490600162001f3d565b50604080516020810190915277094719172c54173045b14ec46a12a84791820609112e00448152620012de90605590600162001f3d565b50604080518082019091527f3120910923528518523610510510510613511513210910d10a12d21520ed002481526d08433e10e13e10a10a13620910a260208201526200133090605690600262001b4b565b5060408051602081019091527d2227c451145910c4511443154431144510c5510dc315543564872118001481526200136d90605790600162001b88565b50604080516020810190915271212cf3d110f4c23d504f5423d105112f002481526200139e90605890600162001d87565b5060408051602081019091527404c4f9064f9062193a219862f906417c47112e00148152620013d290605990600162001c63565b5060408051602081019091527a111c42f88e217c8327cc3374c33748726c8b2648b2644f10d8001481526200140c90605a90600162001e19565b506040805160208101909152770886227c4716c853744511c5bb744311c5b11c432116001481526200144390605b90600162001f3d565b5060408051602081019091527354f46154d4e14e144d56144f4e14423d312f002481526200147690605c90600162001f86565b5060408051602081019091527488e217c8320be23885f11c42f906417c83212e00148152620014aa90605d90600162001c63565b506040805160208101909152764c63e108f4c144e4611113910518510513920d212d00248152620014e090605e90600162001bd1565b5060408051602081019091527d2217c45114491544511443264c510c5f664871744340cccf915f1101001481526200151d90605f90600162001b88565b506040805160208101909152765074550745cc736c8727487274872748727c471119001481526200155390606090600162001bd1565b50604080518082019091527f05104f8418413d1073051391c63c513b18510518713a14434613d10d11040034815266210cf8433d10e160208201526200159e90606190600262001b4b565b506040805160208101909152760220e23918438513911513930533a15613d205212e00248152620015d490606290600162001bd1565b5060408051602081019091527b08443d105108f8510518413e144146104f8510518413e10e1119002481526200160f90606390600162001d3e565b5060408051602081019091526c44cf895f12be237c45109b001481526200163b90606490600162002061565b50604080516020810190915267448f991f10b20014815262001662906065906001620020aa565b5060408051602081019091526744cf899f10b10014815262001689906066906001620020aa565b5060408051602081019091526e221891f12be257c8af88df109e00148152620016b7906067906001620020f3565b506040805160208101909152692257c8af915f10b100148152620016e09060689060016200213c565b5060408051602081019091526c44cf895f123e2188df109e001481526200170c90606990600162002061565b5060408051602081019091526c44af891f10c48f895f109d001481526200173890606a90600162002061565b5060408051602081019091526c02437c4cf8a9ef991f109d001481526200176490606b90600162002061565b5060408051602081019091526a899f133e237c43109c001481526200178e90606c90600162002185565b5060408051602081019091526d0899f12be447c48f915f109d00148152620017bb90606d90600162002018565b5060408051602081019091526c02437c4311be2188df20b200148152620017e790606e90600162002061565b5060408051602081019091526a0456f7c4af911f109d001481526200181190606f90600162002185565b506040805160208101909152690125bdf15bdf209c001481526200183a9060709060016200213c565b506040805160208101909152692257c4af895f209c00148152620018639060719060016200213c565b5060408051602081019091526a0452f7c8af895f109d001481526200188d90607290600162002185565b5060408051602081019091526c02247c56f7c48f98df109e00148152620018b990607390600162002061565b5050607680546001600160a01b039485166001600160a01b0319918216179091556077805493909416921691909117909155607855620022e2565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156200199a579160200282015b828111156200199a57825180516200198991849160209091019062001ace565b509160200191906001019062001969565b50620019a8929150620021ce565b5090565b60018301918390821562001a3a5791602002820160005b8382111562001a0757835183826101000a81548162ffffff021916908362ffffff1602179055509260200192600301602081600201049283019260010302620019c3565b801562001a385782816101000a81549062ffffff021916905560030160208160020104928301926001030262001a07565b505b50620019a8929150620021ef565b60018301918390821562001a3a5791602002820160005b8382111562001a9f57835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262001a5f565b801562001a385782816101000a81549060ff021916905560010160208160000104928301926001030262001a9f565b82805462001adc906200228f565b90600052602060002090601f01602090048101928262001b00576000855562001a3a565b82601f1062001b1b57805160ff191683800117855562001a3a565b8280016001018555821562001a3a579182015b8281111562001a3a57825182559160200191906001019062001b2e565b82805482825590600052602060002090810192821562001a3a579160200282018281111562001a3a57825182559160200191906001019062001b2e565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160f01b031690559160200191906001019062001ba9565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160b81b031690559160200191906001019062001bf2565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160e81b031690559160200191906001019062001c3b565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160a81b031690559160200191906001019062001c84565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160f81b031690559160200191906001019062001ccd565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160d01b031690559160200191906001019062001d16565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160e01b031690559160200191906001019062001d5f565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160901b031690559160200191906001019062001da8565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160b01b031690559160200191906001019062001df1565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160d81b031690559160200191906001019062001e3a565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160981b031690559160200191906001019062001e83565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160801b031690559160200191906001019062001ecc565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160601b031690559160200191906001019062001f15565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160c01b031690559160200191906001019062001f5e565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160a01b031690559160200191906001019062001fa7565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160881b031690559160200191906001019062001ff0565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160701b031690559160200191906001019062002039565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160681b031690559160200191906001019062002082565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160401b0316905591602001919060010190620020cb565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160781b031690559160200191906001019062002114565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160501b03169055916020019190600101906200215d565b82805482825590600052602060002090810192821562001a3a579160200282015b8281111562001a3a57825182906001600160581b0316905591602001919060010190620021a6565b80821115620019a8576000620021e5828262002206565b50600101620021ce565b5b80821115620019a85760008155600101620021f0565b50805462002214906200228f565b6000825580601f1062002225575050565b601f016020900490600052602060002090810190620022459190620021ef565b50565b6000806000606084860312156200225d578283fd5b83516200226a81620022cc565b60208501519093506200227d81620022cc565b80925050604084015190509250925092565b600181811c90821680620022a457607f821691505b60208210811415620022c657634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b03811681146200224557600080fd5b61589380620022f26000396000f3fe60806040526004361061031a5760003560e01c806366945428116101ab578063ac9b4697116100f7578063d678b7b211610095578063ec7dae2b1161006f578063ec7dae2b14610a61578063eefe533b14610a81578063f2fde38b14610aa1578063f6edafef14610ac157600080fd5b8063d678b7b2146109d8578063e0aff049146109f8578063e985e9c514610a1857600080fd5b8063c1599bd9116100d1578063c1599bd914610638578063c87b56dd14610978578063cf16d17214610998578063d45eaa82146109b857600080fd5b8063ac9b469714610904578063af6bb41214610924578063b88d4fde1461095857600080fd5b806378cca8661161016457806395d89b411161013e57806395d89b411461086c578063971f71a0146108815780639cf71021146108b7578063a22cb465146108e457600080fd5b806378cca866146107a65780638bcdcbf3146107c65780638da5cb5b1461084e57600080fd5b806366945428146106f15780636d03f217146107115780636d04a653146107315780636f1347811461075157806370a0823114610771578063715018a61461079157600080fd5b80632f745c591161026a57806344e7aaec1161022357806356261b9f116101fd57806356261b9f1461066d5780635c6bb69a146106915780635f509bba146106b15780636352211e146106d157600080fd5b806344e7aaec1461061857806345b3fe42146106385780634f6ccce71461064d57600080fd5b80632f745c591461051557806336f76b731461053557806342842e0e146105985780634375fe2c146105b85780634378a6e3146105e55780634428d0a01461060557600080fd5b806311f301a9116102d75780631f22d2fe116102b15780631f22d2fe1461048557806323b872dd146104a55780632d72225b146104c55780632e1a7d4d146104f557600080fd5b806311f301a914610410578063165b5dcf1461043e57806318160ddd1461047057600080fd5b806301ffc9a71461031f5780630297497b1461035457806304093a0e1461037457806306fdde03146103a1578063081812fc146103b6578063095ea7b3146103ee575b600080fd5b34801561032b57600080fd5b5061033f61033a366004614c46565b610ae1565b60405190151581526020015b60405180910390f35b34801561036057600080fd5b5061033f61036f3660046149f7565b610b0c565b34801561038057600080fd5b5061039461038f366004614d0b565b610ee7565b60405161034b91906154ec565b3480156103ad57600080fd5b50610394610f93565b3480156103c257600080fd5b506103d66103d1366004614d0b565b611025565b6040516001600160a01b03909116815260200161034b565b3480156103fa57600080fd5b5061040e610409366004614b57565b6110ba565b005b34801561041c57600080fd5b5061043061042b366004614d3b565b6111d0565b60405190815260200161034b565b34801561044a57600080fd5b5061045e610459366004614d0b565b6111f3565b60405160ff909116815260200161034b565b34801561047c57600080fd5b50600954610430565b34801561049157600080fd5b506103946104a0366004614d0b565b61127b565b3480156104b157600080fd5b5061040e6104c0366004614a67565b611428565b3480156104d157600080fd5b5061033f6104e0366004614d0b565b60796020526000908152604090205460ff1681565b34801561050157600080fd5b5061040e610510366004614d0b565b611459565b34801561052157600080fd5b50610430610530366004614b57565b6114c0565b34801561054157600080fd5b50610555610550366004614e19565b611556565b60405161034b919081516001600160401b039081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b3480156105a457600080fd5b5061040e6105b3366004614a67565b611801565b3480156105c457600080fd5b506105d86105d3366004614b82565b61181c565b60405161034b919061541b565b3480156105f157600080fd5b50610394610600366004614d0b565b6119d9565b61040e610613366004614ecb565b611c85565b34801561062457600080fd5b50610430610633366004614e4e565b611f32565b34801561064457600080fd5b50610430601581565b34801561065957600080fd5b50610430610668366004614d0b565b611fbc565b34801561067957600080fd5b5061045e610688366004614d0b565b60131c60031690565b34801561069d57600080fd5b506104306106ac366004614e4e565b61205d565b3480156106bd57600080fd5b506104306106cc366004614d0b565b612091565b3480156106dd57600080fd5b506103d66106ec366004614d0b565b6120d8565b3480156106fd57600080fd5b5061045e61070c366004614e4e565b61214f565b34801561071d57600080fd5b5061043061072c366004614d0b565b61218b565b34801561073d57600080fd5b5061045e61074c366004614d0b565b61220f565b34801561075d57600080fd5b5061045e61076c366004614d0b565b612258565b34801561077d57600080fd5b5061043061078c3660046149f7565b6122cb565b34801561079d57600080fd5b5061040e612352565b3480156107b257600080fd5b506105556107c1366004614d0b565b612388565b3480156107d257600080fd5b5061081b6107e13660046149f7565b607f602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b039586168152938516602085015291841691830191909152909116606082015260800161034b565b34801561085a57600080fd5b506000546001600160a01b03166103d6565b34801561087857600080fd5b50610394612428565b34801561088d57600080fd5b506103d661089c366004614d0b565b6080602052600090815260409020546001600160a01b031681565b3480156108c357600080fd5b506108d76108d23660046149f7565b612437565b60405161034b91906153ea565b3480156108f057600080fd5b5061040e6108ff366004614b23565b612498565b34801561091057600080fd5b5061045e61091f366004614d0b565b61255d565b34801561093057600080fd5b5061094461093f366004614d0b565b6125a7565b60405162ffffff909116815260200161034b565b34801561096457600080fd5b5061040e610973366004614aa7565b6125d6565b34801561098457600080fd5b50610394610993366004614d0b565b61260e565b3480156109a457600080fd5b506103946109b3366004614e6f565b612664565b3480156109c457600080fd5b5061033f6109d3366004614ddb565b612852565b3480156109e457600080fd5b5061045e6109f3366004614d0b565b612943565b348015610a0457600080fd5b5061040e610a13366004614e9a565b61296d565b348015610a2457600080fd5b5061033f610a33366004614a2f565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b348015610a6d57600080fd5b50610394610a7c366004614cf0565b612a6b565b348015610a8d57600080fd5b5061045e610a9c366004614d0b565b612bb7565b348015610aad57600080fd5b5061040e610abc3660046149f7565b612c29565b348015610acd57600080fd5b50610394610adc366004614d5f565b612cc4565b60006001600160e01b0319821663780e9d6360e01b1480610b065750610b06826131e9565b92915050565b6001600160a01b0381166000908152607f6020526040812054600160801b90046001600160401b0316610b735760405162461bcd60e51b8152600401610b6a906020808252600490820152631a5b9a5d60e21b604082015260600190565b60405180910390fd5b6000610b7e83612437565b805190915015610c56576076546001600160a01b038481166000818152607b6020526040908190205490516331a9108f60e11b8152600481019190915290929190911690636352211e9060240160206040518083038186803b158015610be357600080fd5b505afa158015610bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1b9190614a13565b6001600160a01b031614610c565760405162461bcd60e51b8152602060048201526002602482015261065360f41b6044820152606401610b6a565b602081015115610d2e576076546001600160a01b038481166000818152607c6020526040908190205490516331a9108f60e11b8152600481019190915290929190911690636352211e9060240160206040518083038186803b158015610cbb57600080fd5b505afa158015610ccf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf39190614a13565b6001600160a01b031614610d2e5760405162461bcd60e51b8152602060048201526002602482015261653160f01b6044820152606401610b6a565b604081015115610e06576076546001600160a01b038481166000818152607d6020526040908190205490516331a9108f60e11b8152600481019190915290929190911690636352211e9060240160206040518083038186803b158015610d9357600080fd5b505afa158015610da7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcb9190614a13565b6001600160a01b031614610e065760405162461bcd60e51b8152602060048201526002602482015261329960f11b6044820152606401610b6a565b606081015115610ede576076546001600160a01b038481166000818152607e6020526040908190205490516331a9108f60e11b8152600481019190915290929190911690636352211e9060240160206040518083038186803b158015610e6b57600080fd5b505afa158015610e7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea39190614a13565b6001600160a01b031614610ede5760405162461bcd60e51b8152602060048201526002602482015261653360f01b6044820152606401610b6a565b50600192915050565b60748181548110610ef757600080fd5b906000526020600020016000915090508054610f1290615786565b80601f0160208091040260200160405190810160405280929190818152602001828054610f3e90615786565b8015610f8b5780601f10610f6057610100808354040283529160200191610f8b565b820191906000526020600020905b815481529060010190602001808311610f6e57829003601f168201915b505050505081565b606060018054610fa290615786565b80601f0160208091040260200160405190810160405280929190818152602001828054610fce90615786565b801561101b5780601f10610ff05761010080835404028352916020019161101b565b820191906000526020600020905b815481529060010190602001808311610ffe57829003601f168201915b5050505050905090565b6000818152600360205260408120546001600160a01b031661109e5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b6a565b506000908152600560205260409020546001600160a01b031690565b60006110c5826120d8565b9050806001600160a01b0316836001600160a01b031614156111335760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610b6a565b336001600160a01b038216148061114f575061114f8133610a33565b6111c15760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610b6a565b6111cb8383613239565b505050565b607b82600481106111e057600080fd5b0160205260009081526040902054905081565b60006003601983901c16600c600d600785166006811061122357634e487b7160e01b600052603260045260246000fd5b0160005b602081049091015460ff601f9092166101000a9004166004811061125b57634e487b7160e01b600052603260045260246000fd5b602091828204019190069054906101000a900460ff16610b069190615694565b60775460405163348051d760e11b8152600481018390526060916001600160a01b031690630de72b7e908290636900a3ae9060240160006040518083038186803b1580156112c857600080fd5b505afa1580156112dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113049190810190614c7e565b6077546001600160a01b031663e89cec8f61131e876132a7565b6040518263ffffffff1660e01b815260040161133a91906154ec565b60006040518083038186803b15801561135257600080fd5b505afa158015611366573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261138e9190810190614c7e565b611397866119d9565b6040516020016113a993929190615199565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016113d491906154ec565b60006040518083038186803b1580156113ec57600080fd5b505afa158015611400573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b069190810190614c7e565b611432338261330c565b61144e5760405162461bcd60e51b8152600401610b6a90615586565b6111cb838383613403565b6000546001600160a01b031633146114835760405162461bcd60e51b8152600401610b6a90615551565b600080546040516001600160a01b039091169183156108fc02918491818181858888f193505050501580156114bc573d6000803e3d6000fd5b5050565b60006114cb836122cb565b821061152d5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610b6a565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b604080516080810182526000808252602082018190529181018290526060810191909152600061010061158860095490565b61159291906156b9565b61159d906001615651565b84519091506005906001600160401b03168110156115c2575083516001600160401b03165b604051806080016040528060818660046115dc91906156cd565b602081106115fa57634e487b7160e01b600052603260045260246000fd5b60208082049092015460ff601f9092166101000a90041690611624908690600f908c901c166157dc565b61162e9085615651565b6116389190615669565b6001600160401b0316815260200160816116538760046156cd565b61165e906001615651565b6020811061167c57634e487b7160e01b600052603260045260246000fd5b602081049091015460ff601f9092166101000a9004166116a385600f60248c901c166157dc565b88602001516001600160401b03166116bb9190615651565b6116c59190615669565b6001600160401b0316815260200160816116e08760046156cd565b6116eb906002615651565b6020811061170957634e487b7160e01b600052603260045260246000fd5b602081049091015460ff601f9092166101000a90041661173085600f60288c901c166157dc565b88604001516001600160401b03166117489190615651565b611753906001615669565b61175d9190615669565b6001600160401b0316815260200160816117788760046156cd565b611783906003615651565b602081106117a157634e487b7160e01b600052603260045260246000fd5b602081049091015460ff601f9092166101000a9004166117c885600f602c8c901c166157dc565b88606001516001600160401b03166117e09190615651565b6117ea9190615669565b6001600160401b03169052925050505b9392505050565b6111cb838383604051806020016040528060008152506125d6565b6060600060148360008151811061184357634e487b7160e01b600052603260045260246000fd5b60200260200101516060811061186957634e487b7160e01b600052603260045260246000fd5b018054806020026020016040519081016040528092919081815260200182805480156118b457602002820191906000526020600020905b8154815260200190600101908083116118a0575b505050505090506000805b600185516118cd919061571b565b8110156119d057846118e0826001615651565b815181106118fe57634e487b7160e01b600052603260045260246000fd5b60209081029190910101516013549092506001600160a01b0316624aaa15846014856060811061193e57634e487b7160e01b600052603260045260246000fd5b0161194a6015806156cd565b6040518463ffffffff1660e01b81526004016119689392919061548a565b60006040518083038186803b15801561198057600080fd5b505afa158015611994573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119bc9190810190614bb4565b92506119c9600182615651565b90506118bf565b50909392505050565b60606000607a6119ea60018561571b565b81548110611a0857634e487b7160e01b600052603260045260246000fd5b906000526020600020015490506000611a2084612388565b905060006074611a3961072c3063ffffffff87166135ae565b81548110611a5757634e487b7160e01b600052603260045260246000fd5b90600052602060002001611a6a83612a6b565b604051602001611a7b929190615277565b60408051601f1981840301815291905290506002600f601885901c8116821191601c86901c9091161060608280611aaf5750815b15611b6057828015611abe5750815b15611aee575060408051808201909152600e81526d149d5b995908098815da5b99d95960921b6020820152611b3b565b8215611b17575060408051808201909152600681526515da5b99d95960d21b6020820152611b3b565b8115611b3b5750604080518082019091526005815264149d5b995960da1b60208201525b8381604051602001611b4e92919061503c565b60405160208183030381529060405293505b83611b9486600001516001600160401b031660405180604001604052806004815260200163293ab4b760e11b8152506135fb565b611bc887602001516001600160401b03166040518060400160405280600581526020016411dd585c9960da1b8152506135fb565b611bfc88604001516001600160401b0316604051806040016040528060058152602001642b34b3b7b960d91b8152506135fb565b611c3389606001516001600160401b03166040518060400160405280600881526020016743656c657269747960c01b8152506135fb565b604051602001611c47959493929190614f9f565b604051602081830303815290604052935083604051602001611c699190614f7a565b6040516020818303038152906040529650505050505050919050565b611c8e33610b0c565b506000611c9b33846135ae565b90506078548110611cd45760405162461bcd60e51b81526020600482015260036024820152623234b360e91b6044820152606401610b6a565b63ffffffff811660008181526079602052604090205460ff1615611d205760405162461bcd60e51b815260206004820152600360248201526230b63960e91b6044820152606401610b6a565b8215611d9c57607a5461100011611d5f5760405162461bcd60e51b81526020600482015260036024820152626c696d60e81b6044820152606401610b6a565b66b1a2bc2ec50000341015611d9c5760405162461bcd60e51b815260206004820152600360248201526266656560e81b6044820152606401610b6a565b607654600090611db5906001600160a01b0316866135ae565b336000908152607f60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811694830194909452600160801b8104841692820192909252600160c01b909104909116606082015291925090611e2590859061055061072c30886135ae565b336000908152607f60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811694830194909452600160801b8104841692820192909252600160c01b909104909116606082015291925090611e8e90849084612852565b90508080611e995750855b611ece5760405162461bcd60e51b8152600401610b6a906020808252600490820152631b1bdcdd60e21b604082015260600190565b607a54600090611edf906001615651565b9050607a611eed86856136a8565b8154600181810184556000938452602080852090920192909255878352607990526040909120805460ff19169091179055611f28338261373f565b5050505050505050565b600081611f4957611f4283613759565b9050610b06565b6001821415611f59575081610b06565b6002821415611f6b57611f4283613767565b6003821415611f7d57611f42836137db565b6004821415611f8f57611f428361384f565b6005821415611fa157611f42836138c3565b6006821415611fb357611f42836138d1565b6117fa836138df565b6000611fc760095490565b821061202a5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610b6a565b6009828154811061204b57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b6014826060811061206d57600080fd5b01818154811061207c57600080fd5b90600052602060002001600091509150505481565b6000610b063063ffffffff607a6120a960018761571b565b815481106120c757634e487b7160e01b600052603260045260246000fd5b9060005260206000200154166135ae565b6000818152600360205260408120546001600160a01b031680610b065760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610b6a565b600d826006811061215f57600080fd5b01816003811061216e57600080fd5b602081049091015460ff601f9092166101000a9004169150829050565b600060fb82901c806121a05750600792915050565b600281116121b15750600592915050565b600481116121c25750600692915050565b600881116121d35750600292915050565b600c81116121e45750600392915050565b601081116121f55750600492915050565b601881116122065750600192915050565b50600092915050565b6000600d600783166006811061223557634e487b7160e01b600052603260045260246000fd5b0154610100900460ff1661224e575050600b5460ff1690565b5060151c60031690565b6000600d600783166006811061227e57634e487b7160e01b600052603260045260246000fd5b015462010000900460ff1661229557506000919050565b6003601d83901c16600c600d60078516600681106122c357634e487b7160e01b600052603260045260246000fd5b016002611227565b60006001600160a01b0382166123365760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610b6a565b506001600160a01b031660009081526004602052604090205490565b6000546001600160a01b0316331461237c5760405162461bcd60e51b8152600401610b6a90615551565b6123866000613952565b565b604080516080810182526000808252602082018190529181018290526060810182905290607a6123b960018561571b565b815481106123d757634e487b7160e01b600052603260045260246000fd5b600091825260209182902001546040805160808101825260ff83851c81168252602884901c811694820194909452603083901c84169181019190915260389190911c90911660608201529392505050565b606060028054610fa290615786565b61243f614887565b50604080516080810182526001600160a01b03929092166000818152607b6020908152838220548552828252607c81528382205481860152828252607d81528382205485850152918152607e9091522054606082015290565b6001600160a01b0382163314156124f15760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b6a565b3360008181526006602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6000600d600783166006811061258357634e487b7160e01b600052603260045260246000fd5b015462010000900460ff1661259d575050600b5460ff1690565b5060171c60031690565b607581600881106125b757600080fd5b600a9182820401919006600302915054906101000a900462ffffff1681565b6125e0338361330c565b6125fc5760405162461bcd60e51b8152600401610b6a90615586565b612608848484846139a2565b50505050565b6000818152600360205260409020546060906001600160a01b031661265b5760405162461bcd60e51b81526020600482015260036024820152620d0c0d60ea1b6044820152606401610b6a565b610b068261127b565b604080516003808252608082019092526060916000919060208201848036833701905050905060006126968585611f32565b905080826000815181106126ba57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506127016126fb30846000815181106126ee57634e487b7160e01b600052603260045260246000fd5b60200260200101516135ae565b85611f32565b8260018151811061272257634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506127566126fb30846001815181106126ee57634e487b7160e01b600052603260045260246000fd5b8260028151811061277757634e487b7160e01b600052603260045260246000fd5b602090810291909101015260775461284890879084906001600160a01b0316638fba8d5c607589600881106127bc57634e487b7160e01b600052603260045260246000fd5b600a808204929092015460405160e085901b6001600160e01b0319168152929091066003026101000a900462ffffff16600482015260240160006040518083038186803b15801561280c57600080fd5b505afa158015612820573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610adc9190810190614c7e565b9695505050505050565b604080830151908201516000916001600160401b039081169116825b600581101561293857600061288f886128888460026156cd565b89896139d5565b905060006128b4896128a28560026156cd565b6128ad906001615651565b898b6139d5565b90508481101580156128c65750838210155b156128e1576128d58989613b95565b955050505050506117fa565b8382106128f6576001955050505050506117fa565b84811061290b576000955050505050506117fa565b612915828561571b565b9350612921818661571b565b945050508080612930906157c1565b91505061286e565b506128488686613b95565b600c816004811061295357600080fd5b60209182820401919006915054906101000a900460ff1681565b336000908152607f6020526040902054600160801b90046001600160401b0316612a3b57604080516080810182526001815260006020808301828152600a84860190815260608501848152338552607f90935294909220925183549251945191516001600160401b03908116600160c01b026001600160c01b03938216600160801b02939093166fffffffffffffffffffffffffffffffff968216600160401b026fffffffffffffffffffffffffffffffff1990951692909116919091179290921793909316179190911790555b612a4784336000613c04565b612a5383336001613c04565b612a5f82336002613c04565b61260881336003613c04565b606060008260600151836040015184602001518560000151612a8d9190615669565b612a979190615669565b612aa19190615669565b6001600160401b0316905060198111612ad8575050604080518082019091526006815265466565626c6560d01b6020820152919050565b60288111612b0457505060408051808201909152600681526553747572647960d01b6020820152919050565b60378111612b3457505060408051808201909152600a815269466f726d696461626c6560b01b6020820152919050565b60468111612b62575050604080518082019091526008815267141bddd95c999d5b60c21b6020820152919050565b60558111612b9257505060408051808201909152600a815269151c9a5d5b5c1a185b9d60b21b6020820152919050565b5050604080518082019091526007815266476f646c696b6560c81b6020820152919050565b6000600d6007831660068110612bdd57634e487b7160e01b600052603260045260246000fd5b0154610100900460ff16612bf357506000919050565b6003601b83901c16600c600d6007851660068110612c2157634e487b7160e01b600052603260045260246000fd5b016001611227565b6000546001600160a01b03163314612c535760405162461bcd60e51b8152600401610b6a90615551565b6001600160a01b038116612cb85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b6a565b612cc181613952565b50565b6040805161012081018252600f8581168252600486811c82166020840152600887901c821693830193909352600c86901c8116606083810191909152601087901c82166080840152601487901c821660a08401526002601888901c8316811160c08501819052601c89901c9093161060e084015261010083019390935215612d5e5760018161010001818151612d5a9190615651565b9052505b8060e0015115612d805760018161010001818151612d7c9190615651565b9052505b60008161010001516001600160401b03811115612dad57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612dd6578160200160208202803683370190505b5090508160c0015115612ff3576020820151612df3906010615651565b81600081518110612e1457634e487b7160e01b600052603260045260246000fd5b60200260200101818152505081604001516020612e319190615651565b81600181518110612e5257634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508160e0015115612f545760a0820151612e78906050615651565b81600281518110612e9957634e487b7160e01b600052603260045260246000fd5b60209081029190910101526060820151612eb4906030615651565b81600381518110612ed557634e487b7160e01b600052603260045260246000fd5b60209081029190910101526080820151612ef0906040615651565b81600481518110612f1157634e487b7160e01b600052603260045260246000fd5b602002602001018181525050816000015181600581518110612f4357634e487b7160e01b600052603260045260246000fd5b602002602001018181525050613132565b6060820151612f64906030615651565b81600281518110612f8557634e487b7160e01b600052603260045260246000fd5b60209081029190910101526080820151612fa0906040615651565b81600381518110612fc157634e487b7160e01b600052603260045260246000fd5b602002602001018181525050816000015181600481518110612f4357634e487b7160e01b600052603260045260246000fd5b6040820151613003906020615651565b8160008151811061302457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508160e00151156130865760a082015161304a906050615651565b8160018151811061306b57634e487b7160e01b600052603260045260246000fd5b60209081029190910101526060820151612f64906030615651565b6060820151613096906030615651565b816001815181106130b757634e487b7160e01b600052603260045260246000fd5b602090810291909101015260808201516130d2906040615651565b816002815181106130f357634e487b7160e01b600052603260045260246000fd5b60200260200101818152505081600001518160038151811061312557634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b6077546001600160a01b0316635ef8c13461314c8361181c565b87601580896040516020016131619190615149565b6040516020818303038152906040526003806040518863ffffffff1660e01b8152600401613195979695949392919061542e565b60006040518083038186803b1580156131ad57600080fd5b505afa1580156131c1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128489190810190614c7e565b60006001600160e01b031982166380ac58cd60e01b148061321a57506001600160e01b03198216635b5e139f60e01b145b80610b0657506301ffc9a760e01b6001600160e01b0319831614610b06565b600081815260056020526040902080546001600160a01b0319166001600160a01b038416908117909155819061326e826120d8565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b606060006132c13063ffffffff607a6120a960018861571b565b90506117fa63ffffffff607a6132d860018761571b565b815481106132f657634e487b7160e01b600052603260045260246000fd5b906000526020600020015416826109b38461218b565b6000818152600360205260408120546001600160a01b03166133855760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b6a565b6000613390836120d8565b9050806001600160a01b0316846001600160a01b031614806133cb5750836001600160a01b03166133c084611025565b6001600160a01b0316145b806133fb57506001600160a01b0380821660009081526006602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316613416826120d8565b6001600160a01b03161461347e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610b6a565b6001600160a01b0382166134e05760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610b6a565b6134eb838383613e50565b6134f6600082613239565b6001600160a01b038316600090815260046020526040812080546001929061351f90849061571b565b90915550506001600160a01b038216600090815260046020526040812080546001929061354d908490615651565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6040805160609390931b6bffffffffffffffffffffffff191660208085019190915260a09290921b6001600160a01b03191660348401528051808403830181529281019052815191012090565b60775460405163348051d760e11b81526004810184905260609183916001600160a01b0390911690636900a3ae9060240160006040518083038186803b15801561364457600080fd5b505afa158015613658573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526136809190810190614c7e565b6040516020016136919291906150b7565b604051602081830303815290604052905092915050565b6000603882606001516001600160401b0316901b6001600160401b0316603083604001516001600160401b0316901b6001600160401b0316602884602001516001600160401b0316901b6001600160401b0316602085600001516001600160401b0316901b6001600160401b0316866137219190615651565b61372b9190615651565b6137359190615651565b6117fa9190615651565b6114bc828260405180602001604052806000815250613f08565b6000610b0682613f3b613f53565b6000806137b17bff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff84167cff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff008516615651565b90506117fa7dff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff000082615651565b6000806138277dff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff000084167cff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff008516615651565b90506117fa7bff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff82615651565b60008061389a7bff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff84167dff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff00008516615651565b90506117fa7cff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0082615651565b6000610b068261401a613f53565b6000610b0682614027613f53565b60007dff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff000082167bff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff601084901c166137357cff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff00600886901c1683615651565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6139ad848484613403565b6139b98484848461403f565b6126085760405162461bcd60e51b8152600401610b6a906154ff565b6000806139e38560196156cd565b6060840151909150607f87831c1690613a0a90829060011b67fffffffffffffffe16614149565b606086015190915060009060011b67fffffffffffffffe16607f613a2f600e86615651565b8a901c16613a3d9190615651565b90506010811080613a4e5750601082105b15613a5f57600093505050506133fb565b6000607f613a6e600786615651565b8a901c169050613a978187606001516003613a8991906156ec565b6001600160401b0316614149565b865188519192506001600160401b0390811691161115613ae05785518751613abf9190615732565b613aca9060056156ec565b613add906001600160401b031682615651565b90505b6000613aed601586615651565b6020880151908b901c60031691506001600160401b03908116821c166000613b16601788615651565b8c901c600316613b348b600001516001600160401b03166002614149565b613b3e9190615651565b90506020851015613b4d5760011c5b6010841015613b6357613b608180615651565b90505b80821115613b7b5760019750505050505050506133fb565b613b85828261571b565b9c9b505050505050505050505050565b60006040600b8360600151846040015185602001518660000151613bb99190615669565b613bc39190615669565b613bcd9190615669565b613bd79190615732565b613bee906001600160401b031660fa86901c615651565b1115613bfc57506001610b06565b506000610b06565b60765460405163985c5cd960e01b8152600481018590526000916001600160a01b03169063985c5cd99060240160206040518083038186803b158015613c4957600080fd5b505afa158015613c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c819190614d23565b90508315613e4557607b8260048110613caa57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0385166000908152910160205260409020548414613e40576003601382901c16828114613d095760405162461bcd60e51b8152600401610b6a906020808252600490820152631cdb1bdd60e21b604082015260600190565b6076546040516331a9108f60e11b8152600481018790526001600160a01b03868116921690636352211e9060240160206040518083038186803b158015613d4f57600080fd5b505afa158015613d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d879190614a13565b6001600160a01b031614613dc35760405162461bcd60e51b815260206004820152600360248201526237bbb760e91b6044820152606401610b6a565b613dd18160ff168686614165565b613ddd82856001614293565b84607b8260ff1660048110613e0257634e487b7160e01b600052603260045260246000fd5b6001600160a01b03871660008181529290910160209081526040808420949094558883526080905291902080546001600160a01b0319169091179055505b612608565b612608828585614165565b6001600160a01b038316613eab57613ea681600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b613ece565b816001600160a01b0316836001600160a01b031614613ece57613ece838261436d565b6001600160a01b038216613ee5576111cb8161440a565b826001600160a01b0316826001600160a01b0316146111cb576111cb82826144e3565b613f128383614527565b613f1f600084848461403f565b6111cb5760405162461bcd60e51b8152600401610b6a906154ff565b6000613f486020836157dc565b610b06906070615651565b60008060005b600a811015614012576000613f6f8260186156cd565b86901c905060ff80821690600883901c811690601084901c166000613f978463ffffffff8b16565b90506000613fa8848b63ffffffff16565b90506000613fb9848c63ffffffff16565b90506000601084901b613fd0600885901b84615651565b613fda9190615651565b9050613fe78960186156cd565b613ff49082901b8b615651565b9950505050505050505060018161400b9190615651565b9050613f59565b509392505050565b6000610b066040836157dc565b60006140346040836157dc565b610b069060c0615651565b60006001600160a01b0384163b1561414157604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906140839033908990889088906004016153b7565b602060405180830381600087803b15801561409d57600080fd5b505af19250505080156140cd575060408051601f3d908101601f191682019092526140ca91810190614c62565b60015b614127573d8080156140fb576040519150601f19603f3d011682016040523d82523d6000602084013e614100565b606091505b50805161411f5760405162461bcd60e51b8152600401610b6a906154ff565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506133fb565b5060016133fb565b60008282111561415b57506000610b06565b611f42828461571b565b6000607b846004811061418857634e487b7160e01b600052603260045260246000fd5b6001600160a01b038416600090815291016020526040902054905080156126085760765460405163985c5cd960e01b8152600481018390526000916001600160a01b03169063985c5cd99060240160206040518083038186803b1580156141ee57600080fd5b505afa158015614202573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142269190614d23565b905061423481846000614293565b6000607b866004811061425757634e487b7160e01b600052603260045260246000fd5b6001600160a01b038616600090815291016020908152604080832093909355868252608090522080546001600160a01b03191690555050505050565b6003601384901c1660006142a68561220f565b905060006142b38661255d565b90508315614317576142d68360ff1660016142cd896111f3565b60ff1688614675565b60058260ff1610156142f4576142f48260ff1660016142cd89612bb7565b60058160ff161015614312576143128160ff1660016142cd89612258565b614365565b6143298360ff1660006142cd896111f3565b60058260ff161015614347576143478260ff1660006142cd89612bb7565b60058160ff161015614365576143658160ff1660006142cd89612258565b505050505050565b6000600161437a846122cb565b614384919061571b565b6000838152600860205260409020549091508082146143d7576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b60095460009061441c9060019061571b565b6000838152600a60205260408120546009805493945090928490811061445257634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050806009838154811061448157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255828152600a909152604080822084905585825281205560098054806144c757634e487b7160e01b600052603160045260246000fd5b6001900381819060005260206000200160009055905550505050565b60006144ee836122cb565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b6001600160a01b03821661457d5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b6a565b6000818152600360205260409020546001600160a01b0316156145e25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b6a565b6145ee60008383613e50565b6001600160a01b0382166000908152600460205260408120805460019290614617908490615651565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b836146df576001600160a01b0381166000908152607f60205260409020546146a7906001600160401b03168385614864565b6001600160a01b0382166000908152607f60205260409020805467ffffffffffffffff19166001600160401b03929092169190911790555b6001841415614764576001600160a01b0381166000908152607f602052604090205461471c90600160401b90046001600160401b03168385614864565b6001600160a01b0382166000908152607f6020526040902080546001600160401b0392909216600160401b026fffffffffffffffff0000000000000000199092169190911790555b60028414156147e4576001600160a01b0381166000908152607f60205260409020546147a190600160801b90046001600160401b03168385614864565b6001600160a01b0382166000908152607f6020526040902080546001600160401b0392909216600160801b0267ffffffffffffffff60801b199092169190911790555b6003841415612608576001600160a01b0381166000908152607f602052604090205461482190600160c01b90046001600160401b03168385614864565b6001600160a01b0382166000908152607f6020526040902080546001600160401b0392909216600160c01b026001600160c01b0390921691909117905550505050565b6000811561487d576148768385615651565b90506117fa565b6133fb838561571b565b60405180608001604052806004906020820280368337509192915050565b60006148b86148b38461562a565b6155d7565b90508281528383830111156148cc57600080fd5b828260208301376000602084830101529392505050565b600082601f8301126148f3578081fd5b813560206149036148b383615607565b80838252828201915082860187848660051b8901011115614922578586fd5b855b8581101561494057813584529284019290840190600101614924565b5090979650505050505050565b8035801515811461495d57600080fd5b919050565b600060808284031215614973578081fd5b604051608081018181106001600160401b03821117156149955761499561581c565b6040529050806149a4836149e0565b81526149b2602084016149e0565b60208201526149c3604084016149e0565b60408201526149d4606084016149e0565b60608201525092915050565b80356001600160401b038116811461495d57600080fd5b600060208284031215614a08578081fd5b81356117fa81615832565b600060208284031215614a24578081fd5b81516117fa81615832565b60008060408385031215614a41578081fd5b8235614a4c81615832565b91506020830135614a5c81615832565b809150509250929050565b600080600060608486031215614a7b578081fd5b8335614a8681615832565b92506020840135614a9681615832565b929592945050506040919091013590565b60008060008060808587031215614abc578081fd5b8435614ac781615832565b93506020850135614ad781615832565b92506040850135915060608501356001600160401b03811115614af8578182fd5b8501601f81018713614b08578182fd5b614b17878235602084016148a5565b91505092959194509250565b60008060408385031215614b35578182fd5b8235614b4081615832565b9150614b4e6020840161494d565b90509250929050565b60008060408385031215614b69578182fd5b8235614b7481615832565b946020939093013593505050565b600060208284031215614b93578081fd5b81356001600160401b03811115614ba8578182fd5b6133fb848285016148e3565b60006020808385031215614bc6578182fd5b82516001600160401b03811115614bdb578283fd5b8301601f81018513614beb578283fd5b8051614bf96148b382615607565b80828252848201915084840188868560051b8701011115614c18578687fd5b8694505b83851015614c3a578051835260019490940193918501918501614c1c565b50979650505050505050565b600060208284031215614c57578081fd5b81356117fa81615847565b600060208284031215614c73578081fd5b81516117fa81615847565b600060208284031215614c8f578081fd5b81516001600160401b03811115614ca4578182fd5b8201601f81018413614cb4578182fd5b8051614cc26148b38261562a565b818152856020838501011115614cd6578384fd5b614ce782602083016020860161575a565b95945050505050565b600060808284031215614d01578081fd5b6117fa8383614962565b600060208284031215614d1c578081fd5b5035919050565b600060208284031215614d34578081fd5b5051919050565b60008060408385031215614d4d578182fd5b823591506020830135614a5c81615832565b600080600060608486031215614d73578081fd5b8335925060208401356001600160401b0380821115614d90578283fd5b614d9c878388016148e3565b93506040860135915080821115614db1578283fd5b508401601f81018613614dc2578182fd5b614dd1868235602084016148a5565b9150509250925092565b60008060006101208486031215614df0578081fd5b83359250614e018560208601614962565b9150614e108560a08601614962565b90509250925092565b600080600060c08486031215614e2d578081fd5b83359250614e3e8560208601614962565b915060a084013590509250925092565b60008060408385031215614e60578182fd5b50508035926020909101359150565b600080600060608486031215614e83578081fd5b505081359360208301359350604090920135919050565b60008060008060808587031215614eaf578182fd5b5050823594602084013594506040840135936060013592509050565b60008060408385031215614edd578182fd5b82356bffffffffffffffffffffffff81168114614b40578283fd5b6000815180845260208085019450808401835b83811015614f2757815187529582019590820190600101614f0b565b509495945050505050565b60008151808452614f4a81602086016020860161575a565b601f01601f19169290920160200192915050565b60008151614f7081856020860161575a565b9290920192915050565b60008251614f8c81846020870161575a565b605d60f81b920191825250600101919050565b60008651614fb1818460208b0161575a565b808301905061016160f51b8082528751614fd2816002850160208c0161575a565b600292019182018190528651614fef816004850160208b0161575a565b60049201918201819052855161500c816006850160208a0161575a565b60069201918201528351600282019161502d9082906008016020880161575a565b01600601979650505050505050565b6000835161504e81846020880161575a565b80830190507f2c207b202274726169745f74797065223a20225261726520466f726d222c20228152683b30b63ab2911d101160b91b6020820152835161509b81602984016020880161575a565b6222207d60e81b60299290910191820152602c01949350505050565b7f7b2022646973706c61795f74797065223a20226e756d626572222c202274726181526a34ba2fba3cb832911d101160a91b60208201526000835161510381602b85016020880161575a565b6b0111610113b30b63ab2911d160a51b602b91840191820152835161512f81603784016020880161575a565b607d60f81b60379290910191820152603801949350505050565b7f7374796c653d226261636b67726f756e642d636f6c6f723a202300000000000081526000825161518181601a85016020870161575a565b601160f91b601a939091019283015250601b01919050565b717b226e616d65223a20226d6669656e64202360701b815283516000906151c781601285016020890161575a565b7f222c20226465736372697074696f6e223a202241206669656e642063617074756012918401918201527f7265642062792070726f6f662d6f662d636f6d6261742e222c2022696d616765603282015263111d101160e11b6052820152845161523781605684016020890161575a565b6201116160ed1b60569290910191820152835161525b81605984016020880161575a565b61207d60f01b60599290910191820152605b0195945050505050565b7f2261747472696275746573223a205b7b202274726169745f74797065223a20228152600060207420b33334b734ba3c911610113b30b63ab2911d101160591b81840152603582865484600182811c9150808316806152d757607f831692505b8683108114156152f557634e487b7160e01b88526022600452602488fd5b808015615309576001811461531e5761534e565b60ff1985168a880152838a018701955061534e565b60008c815260209020895b858110156153445781548c82018a0152908401908901615329565b505086848b010195505b50507f22207d2c207b202274726169745f74797065223a2022506f776572204c657665845250506d36111610113b30b63ab2911d101160911b6020830152506153ac61539d602e830188614f5e565b6222207d60e81b815260030190565b979650505050505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061284890830184614f32565b60808101818360005b60048110156154125781518352602092830192909101906001016153f3565b50505092915050565b6020815260006117fa6020830184614ef8565b60e08152600061544160e083018a614ef8565b8281036020840152615453818a614ef8565b905087604084015286606084015282810360808401526154738187614f32565b60a0840195909552505060c0015295945050505050565b60608152600061549d6060830186614ef8565b828103602084810191909152855480835286845281842092820190845b818110156154d6578454835260019485019492840192016154ba565b5050809350505050826040830152949350505050565b6020815260006117fa6020830184614f32565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b604051601f8201601f191681016001600160401b03811182821017156155ff576155ff61581c565b604052919050565b60006001600160401b038211156156205761562061581c565b5060051b60200190565b60006001600160401b038211156156435761564361581c565b50601f01601f191660200190565b60008219821115615664576156646157f0565b500190565b60006001600160401b0380831681851680830382111561568b5761568b6157f0565b01949350505050565b600060ff821660ff84168060ff038211156156b1576156b16157f0565b019392505050565b6000826156c8576156c8615806565b500490565b60008160001904831182151516156156e7576156e76157f0565b500290565b60006001600160401b0380831681851681830481118215151615615712576157126157f0565b02949350505050565b60008282101561572d5761572d6157f0565b500390565b60006001600160401b0383811690831681811015615752576157526157f0565b039392505050565b60005b8381101561577557818101518382015260200161575d565b838111156126085750506000910152565b600181811c9082168061579a57607f821691505b602082108114156157bb57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156157d5576157d56157f0565b5060010190565b6000826157eb576157eb615806565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114612cc157600080fd5b6001600160e01b031981168114612cc157600080fdfea264697066735822122013c8f7abd840b8734cf4115b85c0e26a07e5647ee2399a2943b2265dd8b4b0a964736f6c634300080400330000000000000000000000005d070a1c9acdc38d853d8501f2740fab9e9b4821000000000000000000000000fcbad2f45676397792381612913491321e2aad75000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Deployed Bytecode

0x60806040526004361061031a5760003560e01c806366945428116101ab578063ac9b4697116100f7578063d678b7b211610095578063ec7dae2b1161006f578063ec7dae2b14610a61578063eefe533b14610a81578063f2fde38b14610aa1578063f6edafef14610ac157600080fd5b8063d678b7b2146109d8578063e0aff049146109f8578063e985e9c514610a1857600080fd5b8063c1599bd9116100d1578063c1599bd914610638578063c87b56dd14610978578063cf16d17214610998578063d45eaa82146109b857600080fd5b8063ac9b469714610904578063af6bb41214610924578063b88d4fde1461095857600080fd5b806378cca8661161016457806395d89b411161013e57806395d89b411461086c578063971f71a0146108815780639cf71021146108b7578063a22cb465146108e457600080fd5b806378cca866146107a65780638bcdcbf3146107c65780638da5cb5b1461084e57600080fd5b806366945428146106f15780636d03f217146107115780636d04a653146107315780636f1347811461075157806370a0823114610771578063715018a61461079157600080fd5b80632f745c591161026a57806344e7aaec1161022357806356261b9f116101fd57806356261b9f1461066d5780635c6bb69a146106915780635f509bba146106b15780636352211e146106d157600080fd5b806344e7aaec1461061857806345b3fe42146106385780634f6ccce71461064d57600080fd5b80632f745c591461051557806336f76b731461053557806342842e0e146105985780634375fe2c146105b85780634378a6e3146105e55780634428d0a01461060557600080fd5b806311f301a9116102d75780631f22d2fe116102b15780631f22d2fe1461048557806323b872dd146104a55780632d72225b146104c55780632e1a7d4d146104f557600080fd5b806311f301a914610410578063165b5dcf1461043e57806318160ddd1461047057600080fd5b806301ffc9a71461031f5780630297497b1461035457806304093a0e1461037457806306fdde03146103a1578063081812fc146103b6578063095ea7b3146103ee575b600080fd5b34801561032b57600080fd5b5061033f61033a366004614c46565b610ae1565b60405190151581526020015b60405180910390f35b34801561036057600080fd5b5061033f61036f3660046149f7565b610b0c565b34801561038057600080fd5b5061039461038f366004614d0b565b610ee7565b60405161034b91906154ec565b3480156103ad57600080fd5b50610394610f93565b3480156103c257600080fd5b506103d66103d1366004614d0b565b611025565b6040516001600160a01b03909116815260200161034b565b3480156103fa57600080fd5b5061040e610409366004614b57565b6110ba565b005b34801561041c57600080fd5b5061043061042b366004614d3b565b6111d0565b60405190815260200161034b565b34801561044a57600080fd5b5061045e610459366004614d0b565b6111f3565b60405160ff909116815260200161034b565b34801561047c57600080fd5b50600954610430565b34801561049157600080fd5b506103946104a0366004614d0b565b61127b565b3480156104b157600080fd5b5061040e6104c0366004614a67565b611428565b3480156104d157600080fd5b5061033f6104e0366004614d0b565b60796020526000908152604090205460ff1681565b34801561050157600080fd5b5061040e610510366004614d0b565b611459565b34801561052157600080fd5b50610430610530366004614b57565b6114c0565b34801561054157600080fd5b50610555610550366004614e19565b611556565b60405161034b919081516001600160401b039081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b3480156105a457600080fd5b5061040e6105b3366004614a67565b611801565b3480156105c457600080fd5b506105d86105d3366004614b82565b61181c565b60405161034b919061541b565b3480156105f157600080fd5b50610394610600366004614d0b565b6119d9565b61040e610613366004614ecb565b611c85565b34801561062457600080fd5b50610430610633366004614e4e565b611f32565b34801561064457600080fd5b50610430601581565b34801561065957600080fd5b50610430610668366004614d0b565b611fbc565b34801561067957600080fd5b5061045e610688366004614d0b565b60131c60031690565b34801561069d57600080fd5b506104306106ac366004614e4e565b61205d565b3480156106bd57600080fd5b506104306106cc366004614d0b565b612091565b3480156106dd57600080fd5b506103d66106ec366004614d0b565b6120d8565b3480156106fd57600080fd5b5061045e61070c366004614e4e565b61214f565b34801561071d57600080fd5b5061043061072c366004614d0b565b61218b565b34801561073d57600080fd5b5061045e61074c366004614d0b565b61220f565b34801561075d57600080fd5b5061045e61076c366004614d0b565b612258565b34801561077d57600080fd5b5061043061078c3660046149f7565b6122cb565b34801561079d57600080fd5b5061040e612352565b3480156107b257600080fd5b506105556107c1366004614d0b565b612388565b3480156107d257600080fd5b5061081b6107e13660046149f7565b607f602052600090815260409020546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b039586168152938516602085015291841691830191909152909116606082015260800161034b565b34801561085a57600080fd5b506000546001600160a01b03166103d6565b34801561087857600080fd5b50610394612428565b34801561088d57600080fd5b506103d661089c366004614d0b565b6080602052600090815260409020546001600160a01b031681565b3480156108c357600080fd5b506108d76108d23660046149f7565b612437565b60405161034b91906153ea565b3480156108f057600080fd5b5061040e6108ff366004614b23565b612498565b34801561091057600080fd5b5061045e61091f366004614d0b565b61255d565b34801561093057600080fd5b5061094461093f366004614d0b565b6125a7565b60405162ffffff909116815260200161034b565b34801561096457600080fd5b5061040e610973366004614aa7565b6125d6565b34801561098457600080fd5b50610394610993366004614d0b565b61260e565b3480156109a457600080fd5b506103946109b3366004614e6f565b612664565b3480156109c457600080fd5b5061033f6109d3366004614ddb565b612852565b3480156109e457600080fd5b5061045e6109f3366004614d0b565b612943565b348015610a0457600080fd5b5061040e610a13366004614e9a565b61296d565b348015610a2457600080fd5b5061033f610a33366004614a2f565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b348015610a6d57600080fd5b50610394610a7c366004614cf0565b612a6b565b348015610a8d57600080fd5b5061045e610a9c366004614d0b565b612bb7565b348015610aad57600080fd5b5061040e610abc3660046149f7565b612c29565b348015610acd57600080fd5b50610394610adc366004614d5f565b612cc4565b60006001600160e01b0319821663780e9d6360e01b1480610b065750610b06826131e9565b92915050565b6001600160a01b0381166000908152607f6020526040812054600160801b90046001600160401b0316610b735760405162461bcd60e51b8152600401610b6a906020808252600490820152631a5b9a5d60e21b604082015260600190565b60405180910390fd5b6000610b7e83612437565b805190915015610c56576076546001600160a01b038481166000818152607b6020526040908190205490516331a9108f60e11b8152600481019190915290929190911690636352211e9060240160206040518083038186803b158015610be357600080fd5b505afa158015610bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1b9190614a13565b6001600160a01b031614610c565760405162461bcd60e51b8152602060048201526002602482015261065360f41b6044820152606401610b6a565b602081015115610d2e576076546001600160a01b038481166000818152607c6020526040908190205490516331a9108f60e11b8152600481019190915290929190911690636352211e9060240160206040518083038186803b158015610cbb57600080fd5b505afa158015610ccf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf39190614a13565b6001600160a01b031614610d2e5760405162461bcd60e51b8152602060048201526002602482015261653160f01b6044820152606401610b6a565b604081015115610e06576076546001600160a01b038481166000818152607d6020526040908190205490516331a9108f60e11b8152600481019190915290929190911690636352211e9060240160206040518083038186803b158015610d9357600080fd5b505afa158015610da7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcb9190614a13565b6001600160a01b031614610e065760405162461bcd60e51b8152602060048201526002602482015261329960f11b6044820152606401610b6a565b606081015115610ede576076546001600160a01b038481166000818152607e6020526040908190205490516331a9108f60e11b8152600481019190915290929190911690636352211e9060240160206040518083038186803b158015610e6b57600080fd5b505afa158015610e7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea39190614a13565b6001600160a01b031614610ede5760405162461bcd60e51b8152602060048201526002602482015261653360f01b6044820152606401610b6a565b50600192915050565b60748181548110610ef757600080fd5b906000526020600020016000915090508054610f1290615786565b80601f0160208091040260200160405190810160405280929190818152602001828054610f3e90615786565b8015610f8b5780601f10610f6057610100808354040283529160200191610f8b565b820191906000526020600020905b815481529060010190602001808311610f6e57829003601f168201915b505050505081565b606060018054610fa290615786565b80601f0160208091040260200160405190810160405280929190818152602001828054610fce90615786565b801561101b5780601f10610ff05761010080835404028352916020019161101b565b820191906000526020600020905b815481529060010190602001808311610ffe57829003601f168201915b5050505050905090565b6000818152600360205260408120546001600160a01b031661109e5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b6a565b506000908152600560205260409020546001600160a01b031690565b60006110c5826120d8565b9050806001600160a01b0316836001600160a01b031614156111335760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610b6a565b336001600160a01b038216148061114f575061114f8133610a33565b6111c15760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610b6a565b6111cb8383613239565b505050565b607b82600481106111e057600080fd5b0160205260009081526040902054905081565b60006003601983901c16600c600d600785166006811061122357634e487b7160e01b600052603260045260246000fd5b0160005b602081049091015460ff601f9092166101000a9004166004811061125b57634e487b7160e01b600052603260045260246000fd5b602091828204019190069054906101000a900460ff16610b069190615694565b60775460405163348051d760e11b8152600481018390526060916001600160a01b031690630de72b7e908290636900a3ae9060240160006040518083038186803b1580156112c857600080fd5b505afa1580156112dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113049190810190614c7e565b6077546001600160a01b031663e89cec8f61131e876132a7565b6040518263ffffffff1660e01b815260040161133a91906154ec565b60006040518083038186803b15801561135257600080fd5b505afa158015611366573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261138e9190810190614c7e565b611397866119d9565b6040516020016113a993929190615199565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016113d491906154ec565b60006040518083038186803b1580156113ec57600080fd5b505afa158015611400573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b069190810190614c7e565b611432338261330c565b61144e5760405162461bcd60e51b8152600401610b6a90615586565b6111cb838383613403565b6000546001600160a01b031633146114835760405162461bcd60e51b8152600401610b6a90615551565b600080546040516001600160a01b039091169183156108fc02918491818181858888f193505050501580156114bc573d6000803e3d6000fd5b5050565b60006114cb836122cb565b821061152d5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610b6a565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b604080516080810182526000808252602082018190529181018290526060810191909152600061010061158860095490565b61159291906156b9565b61159d906001615651565b84519091506005906001600160401b03168110156115c2575083516001600160401b03165b604051806080016040528060818660046115dc91906156cd565b602081106115fa57634e487b7160e01b600052603260045260246000fd5b60208082049092015460ff601f9092166101000a90041690611624908690600f908c901c166157dc565b61162e9085615651565b6116389190615669565b6001600160401b0316815260200160816116538760046156cd565b61165e906001615651565b6020811061167c57634e487b7160e01b600052603260045260246000fd5b602081049091015460ff601f9092166101000a9004166116a385600f60248c901c166157dc565b88602001516001600160401b03166116bb9190615651565b6116c59190615669565b6001600160401b0316815260200160816116e08760046156cd565b6116eb906002615651565b6020811061170957634e487b7160e01b600052603260045260246000fd5b602081049091015460ff601f9092166101000a90041661173085600f60288c901c166157dc565b88604001516001600160401b03166117489190615651565b611753906001615669565b61175d9190615669565b6001600160401b0316815260200160816117788760046156cd565b611783906003615651565b602081106117a157634e487b7160e01b600052603260045260246000fd5b602081049091015460ff601f9092166101000a9004166117c885600f602c8c901c166157dc565b88606001516001600160401b03166117e09190615651565b6117ea9190615669565b6001600160401b03169052925050505b9392505050565b6111cb838383604051806020016040528060008152506125d6565b6060600060148360008151811061184357634e487b7160e01b600052603260045260246000fd5b60200260200101516060811061186957634e487b7160e01b600052603260045260246000fd5b018054806020026020016040519081016040528092919081815260200182805480156118b457602002820191906000526020600020905b8154815260200190600101908083116118a0575b505050505090506000805b600185516118cd919061571b565b8110156119d057846118e0826001615651565b815181106118fe57634e487b7160e01b600052603260045260246000fd5b60209081029190910101516013549092506001600160a01b0316624aaa15846014856060811061193e57634e487b7160e01b600052603260045260246000fd5b0161194a6015806156cd565b6040518463ffffffff1660e01b81526004016119689392919061548a565b60006040518083038186803b15801561198057600080fd5b505afa158015611994573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119bc9190810190614bb4565b92506119c9600182615651565b90506118bf565b50909392505050565b60606000607a6119ea60018561571b565b81548110611a0857634e487b7160e01b600052603260045260246000fd5b906000526020600020015490506000611a2084612388565b905060006074611a3961072c3063ffffffff87166135ae565b81548110611a5757634e487b7160e01b600052603260045260246000fd5b90600052602060002001611a6a83612a6b565b604051602001611a7b929190615277565b60408051601f1981840301815291905290506002600f601885901c8116821191601c86901c9091161060608280611aaf5750815b15611b6057828015611abe5750815b15611aee575060408051808201909152600e81526d149d5b995908098815da5b99d95960921b6020820152611b3b565b8215611b17575060408051808201909152600681526515da5b99d95960d21b6020820152611b3b565b8115611b3b5750604080518082019091526005815264149d5b995960da1b60208201525b8381604051602001611b4e92919061503c565b60405160208183030381529060405293505b83611b9486600001516001600160401b031660405180604001604052806004815260200163293ab4b760e11b8152506135fb565b611bc887602001516001600160401b03166040518060400160405280600581526020016411dd585c9960da1b8152506135fb565b611bfc88604001516001600160401b0316604051806040016040528060058152602001642b34b3b7b960d91b8152506135fb565b611c3389606001516001600160401b03166040518060400160405280600881526020016743656c657269747960c01b8152506135fb565b604051602001611c47959493929190614f9f565b604051602081830303815290604052935083604051602001611c699190614f7a565b6040516020818303038152906040529650505050505050919050565b611c8e33610b0c565b506000611c9b33846135ae565b90506078548110611cd45760405162461bcd60e51b81526020600482015260036024820152623234b360e91b6044820152606401610b6a565b63ffffffff811660008181526079602052604090205460ff1615611d205760405162461bcd60e51b815260206004820152600360248201526230b63960e91b6044820152606401610b6a565b8215611d9c57607a5461100011611d5f5760405162461bcd60e51b81526020600482015260036024820152626c696d60e81b6044820152606401610b6a565b66b1a2bc2ec50000341015611d9c5760405162461bcd60e51b815260206004820152600360248201526266656560e81b6044820152606401610b6a565b607654600090611db5906001600160a01b0316866135ae565b336000908152607f60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811694830194909452600160801b8104841692820192909252600160c01b909104909116606082015291925090611e2590859061055061072c30886135ae565b336000908152607f60209081526040808320815160808101835290546001600160401b038082168352600160401b8204811694830194909452600160801b8104841692820192909252600160c01b909104909116606082015291925090611e8e90849084612852565b90508080611e995750855b611ece5760405162461bcd60e51b8152600401610b6a906020808252600490820152631b1bdcdd60e21b604082015260600190565b607a54600090611edf906001615651565b9050607a611eed86856136a8565b8154600181810184556000938452602080852090920192909255878352607990526040909120805460ff19169091179055611f28338261373f565b5050505050505050565b600081611f4957611f4283613759565b9050610b06565b6001821415611f59575081610b06565b6002821415611f6b57611f4283613767565b6003821415611f7d57611f42836137db565b6004821415611f8f57611f428361384f565b6005821415611fa157611f42836138c3565b6006821415611fb357611f42836138d1565b6117fa836138df565b6000611fc760095490565b821061202a5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610b6a565b6009828154811061204b57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b6014826060811061206d57600080fd5b01818154811061207c57600080fd5b90600052602060002001600091509150505481565b6000610b063063ffffffff607a6120a960018761571b565b815481106120c757634e487b7160e01b600052603260045260246000fd5b9060005260206000200154166135ae565b6000818152600360205260408120546001600160a01b031680610b065760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610b6a565b600d826006811061215f57600080fd5b01816003811061216e57600080fd5b602081049091015460ff601f9092166101000a9004169150829050565b600060fb82901c806121a05750600792915050565b600281116121b15750600592915050565b600481116121c25750600692915050565b600881116121d35750600292915050565b600c81116121e45750600392915050565b601081116121f55750600492915050565b601881116122065750600192915050565b50600092915050565b6000600d600783166006811061223557634e487b7160e01b600052603260045260246000fd5b0154610100900460ff1661224e575050600b5460ff1690565b5060151c60031690565b6000600d600783166006811061227e57634e487b7160e01b600052603260045260246000fd5b015462010000900460ff1661229557506000919050565b6003601d83901c16600c600d60078516600681106122c357634e487b7160e01b600052603260045260246000fd5b016002611227565b60006001600160a01b0382166123365760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610b6a565b506001600160a01b031660009081526004602052604090205490565b6000546001600160a01b0316331461237c5760405162461bcd60e51b8152600401610b6a90615551565b6123866000613952565b565b604080516080810182526000808252602082018190529181018290526060810182905290607a6123b960018561571b565b815481106123d757634e487b7160e01b600052603260045260246000fd5b600091825260209182902001546040805160808101825260ff83851c81168252602884901c811694820194909452603083901c84169181019190915260389190911c90911660608201529392505050565b606060028054610fa290615786565b61243f614887565b50604080516080810182526001600160a01b03929092166000818152607b6020908152838220548552828252607c81528382205481860152828252607d81528382205485850152918152607e9091522054606082015290565b6001600160a01b0382163314156124f15760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b6a565b3360008181526006602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6000600d600783166006811061258357634e487b7160e01b600052603260045260246000fd5b015462010000900460ff1661259d575050600b5460ff1690565b5060171c60031690565b607581600881106125b757600080fd5b600a9182820401919006600302915054906101000a900462ffffff1681565b6125e0338361330c565b6125fc5760405162461bcd60e51b8152600401610b6a90615586565b612608848484846139a2565b50505050565b6000818152600360205260409020546060906001600160a01b031661265b5760405162461bcd60e51b81526020600482015260036024820152620d0c0d60ea1b6044820152606401610b6a565b610b068261127b565b604080516003808252608082019092526060916000919060208201848036833701905050905060006126968585611f32565b905080826000815181106126ba57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506127016126fb30846000815181106126ee57634e487b7160e01b600052603260045260246000fd5b60200260200101516135ae565b85611f32565b8260018151811061272257634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506127566126fb30846001815181106126ee57634e487b7160e01b600052603260045260246000fd5b8260028151811061277757634e487b7160e01b600052603260045260246000fd5b602090810291909101015260775461284890879084906001600160a01b0316638fba8d5c607589600881106127bc57634e487b7160e01b600052603260045260246000fd5b600a808204929092015460405160e085901b6001600160e01b0319168152929091066003026101000a900462ffffff16600482015260240160006040518083038186803b15801561280c57600080fd5b505afa158015612820573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610adc9190810190614c7e565b9695505050505050565b604080830151908201516000916001600160401b039081169116825b600581101561293857600061288f886128888460026156cd565b89896139d5565b905060006128b4896128a28560026156cd565b6128ad906001615651565b898b6139d5565b90508481101580156128c65750838210155b156128e1576128d58989613b95565b955050505050506117fa565b8382106128f6576001955050505050506117fa565b84811061290b576000955050505050506117fa565b612915828561571b565b9350612921818661571b565b945050508080612930906157c1565b91505061286e565b506128488686613b95565b600c816004811061295357600080fd5b60209182820401919006915054906101000a900460ff1681565b336000908152607f6020526040902054600160801b90046001600160401b0316612a3b57604080516080810182526001815260006020808301828152600a84860190815260608501848152338552607f90935294909220925183549251945191516001600160401b03908116600160c01b026001600160c01b03938216600160801b02939093166fffffffffffffffffffffffffffffffff968216600160401b026fffffffffffffffffffffffffffffffff1990951692909116919091179290921793909316179190911790555b612a4784336000613c04565b612a5383336001613c04565b612a5f82336002613c04565b61260881336003613c04565b606060008260600151836040015184602001518560000151612a8d9190615669565b612a979190615669565b612aa19190615669565b6001600160401b0316905060198111612ad8575050604080518082019091526006815265466565626c6560d01b6020820152919050565b60288111612b0457505060408051808201909152600681526553747572647960d01b6020820152919050565b60378111612b3457505060408051808201909152600a815269466f726d696461626c6560b01b6020820152919050565b60468111612b62575050604080518082019091526008815267141bddd95c999d5b60c21b6020820152919050565b60558111612b9257505060408051808201909152600a815269151c9a5d5b5c1a185b9d60b21b6020820152919050565b5050604080518082019091526007815266476f646c696b6560c81b6020820152919050565b6000600d6007831660068110612bdd57634e487b7160e01b600052603260045260246000fd5b0154610100900460ff16612bf357506000919050565b6003601b83901c16600c600d6007851660068110612c2157634e487b7160e01b600052603260045260246000fd5b016001611227565b6000546001600160a01b03163314612c535760405162461bcd60e51b8152600401610b6a90615551565b6001600160a01b038116612cb85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b6a565b612cc181613952565b50565b6040805161012081018252600f8581168252600486811c82166020840152600887901c821693830193909352600c86901c8116606083810191909152601087901c82166080840152601487901c821660a08401526002601888901c8316811160c08501819052601c89901c9093161060e084015261010083019390935215612d5e5760018161010001818151612d5a9190615651565b9052505b8060e0015115612d805760018161010001818151612d7c9190615651565b9052505b60008161010001516001600160401b03811115612dad57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612dd6578160200160208202803683370190505b5090508160c0015115612ff3576020820151612df3906010615651565b81600081518110612e1457634e487b7160e01b600052603260045260246000fd5b60200260200101818152505081604001516020612e319190615651565b81600181518110612e5257634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508160e0015115612f545760a0820151612e78906050615651565b81600281518110612e9957634e487b7160e01b600052603260045260246000fd5b60209081029190910101526060820151612eb4906030615651565b81600381518110612ed557634e487b7160e01b600052603260045260246000fd5b60209081029190910101526080820151612ef0906040615651565b81600481518110612f1157634e487b7160e01b600052603260045260246000fd5b602002602001018181525050816000015181600581518110612f4357634e487b7160e01b600052603260045260246000fd5b602002602001018181525050613132565b6060820151612f64906030615651565b81600281518110612f8557634e487b7160e01b600052603260045260246000fd5b60209081029190910101526080820151612fa0906040615651565b81600381518110612fc157634e487b7160e01b600052603260045260246000fd5b602002602001018181525050816000015181600481518110612f4357634e487b7160e01b600052603260045260246000fd5b6040820151613003906020615651565b8160008151811061302457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508160e00151156130865760a082015161304a906050615651565b8160018151811061306b57634e487b7160e01b600052603260045260246000fd5b60209081029190910101526060820151612f64906030615651565b6060820151613096906030615651565b816001815181106130b757634e487b7160e01b600052603260045260246000fd5b602090810291909101015260808201516130d2906040615651565b816002815181106130f357634e487b7160e01b600052603260045260246000fd5b60200260200101818152505081600001518160038151811061312557634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b6077546001600160a01b0316635ef8c13461314c8361181c565b87601580896040516020016131619190615149565b6040516020818303038152906040526003806040518863ffffffff1660e01b8152600401613195979695949392919061542e565b60006040518083038186803b1580156131ad57600080fd5b505afa1580156131c1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128489190810190614c7e565b60006001600160e01b031982166380ac58cd60e01b148061321a57506001600160e01b03198216635b5e139f60e01b145b80610b0657506301ffc9a760e01b6001600160e01b0319831614610b06565b600081815260056020526040902080546001600160a01b0319166001600160a01b038416908117909155819061326e826120d8565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b606060006132c13063ffffffff607a6120a960018861571b565b90506117fa63ffffffff607a6132d860018761571b565b815481106132f657634e487b7160e01b600052603260045260246000fd5b906000526020600020015416826109b38461218b565b6000818152600360205260408120546001600160a01b03166133855760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b6a565b6000613390836120d8565b9050806001600160a01b0316846001600160a01b031614806133cb5750836001600160a01b03166133c084611025565b6001600160a01b0316145b806133fb57506001600160a01b0380821660009081526006602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316613416826120d8565b6001600160a01b03161461347e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610b6a565b6001600160a01b0382166134e05760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610b6a565b6134eb838383613e50565b6134f6600082613239565b6001600160a01b038316600090815260046020526040812080546001929061351f90849061571b565b90915550506001600160a01b038216600090815260046020526040812080546001929061354d908490615651565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6040805160609390931b6bffffffffffffffffffffffff191660208085019190915260a09290921b6001600160a01b03191660348401528051808403830181529281019052815191012090565b60775460405163348051d760e11b81526004810184905260609183916001600160a01b0390911690636900a3ae9060240160006040518083038186803b15801561364457600080fd5b505afa158015613658573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526136809190810190614c7e565b6040516020016136919291906150b7565b604051602081830303815290604052905092915050565b6000603882606001516001600160401b0316901b6001600160401b0316603083604001516001600160401b0316901b6001600160401b0316602884602001516001600160401b0316901b6001600160401b0316602085600001516001600160401b0316901b6001600160401b0316866137219190615651565b61372b9190615651565b6137359190615651565b6117fa9190615651565b6114bc828260405180602001604052806000815250613f08565b6000610b0682613f3b613f53565b6000806137b17bff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff84167cff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff008516615651565b90506117fa7dff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff000082615651565b6000806138277dff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff000084167cff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff008516615651565b90506117fa7bff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff82615651565b60008061389a7bff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff84167dff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff00008516615651565b90506117fa7cff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0082615651565b6000610b068261401a613f53565b6000610b0682614027613f53565b60007dff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff000082167bff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff601084901c166137357cff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff00600886901c1683615651565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6139ad848484613403565b6139b98484848461403f565b6126085760405162461bcd60e51b8152600401610b6a906154ff565b6000806139e38560196156cd565b6060840151909150607f87831c1690613a0a90829060011b67fffffffffffffffe16614149565b606086015190915060009060011b67fffffffffffffffe16607f613a2f600e86615651565b8a901c16613a3d9190615651565b90506010811080613a4e5750601082105b15613a5f57600093505050506133fb565b6000607f613a6e600786615651565b8a901c169050613a978187606001516003613a8991906156ec565b6001600160401b0316614149565b865188519192506001600160401b0390811691161115613ae05785518751613abf9190615732565b613aca9060056156ec565b613add906001600160401b031682615651565b90505b6000613aed601586615651565b6020880151908b901c60031691506001600160401b03908116821c166000613b16601788615651565b8c901c600316613b348b600001516001600160401b03166002614149565b613b3e9190615651565b90506020851015613b4d5760011c5b6010841015613b6357613b608180615651565b90505b80821115613b7b5760019750505050505050506133fb565b613b85828261571b565b9c9b505050505050505050505050565b60006040600b8360600151846040015185602001518660000151613bb99190615669565b613bc39190615669565b613bcd9190615669565b613bd79190615732565b613bee906001600160401b031660fa86901c615651565b1115613bfc57506001610b06565b506000610b06565b60765460405163985c5cd960e01b8152600481018590526000916001600160a01b03169063985c5cd99060240160206040518083038186803b158015613c4957600080fd5b505afa158015613c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c819190614d23565b90508315613e4557607b8260048110613caa57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0385166000908152910160205260409020548414613e40576003601382901c16828114613d095760405162461bcd60e51b8152600401610b6a906020808252600490820152631cdb1bdd60e21b604082015260600190565b6076546040516331a9108f60e11b8152600481018790526001600160a01b03868116921690636352211e9060240160206040518083038186803b158015613d4f57600080fd5b505afa158015613d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d879190614a13565b6001600160a01b031614613dc35760405162461bcd60e51b815260206004820152600360248201526237bbb760e91b6044820152606401610b6a565b613dd18160ff168686614165565b613ddd82856001614293565b84607b8260ff1660048110613e0257634e487b7160e01b600052603260045260246000fd5b6001600160a01b03871660008181529290910160209081526040808420949094558883526080905291902080546001600160a01b0319169091179055505b612608565b612608828585614165565b6001600160a01b038316613eab57613ea681600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b613ece565b816001600160a01b0316836001600160a01b031614613ece57613ece838261436d565b6001600160a01b038216613ee5576111cb8161440a565b826001600160a01b0316826001600160a01b0316146111cb576111cb82826144e3565b613f128383614527565b613f1f600084848461403f565b6111cb5760405162461bcd60e51b8152600401610b6a906154ff565b6000613f486020836157dc565b610b06906070615651565b60008060005b600a811015614012576000613f6f8260186156cd565b86901c905060ff80821690600883901c811690601084901c166000613f978463ffffffff8b16565b90506000613fa8848b63ffffffff16565b90506000613fb9848c63ffffffff16565b90506000601084901b613fd0600885901b84615651565b613fda9190615651565b9050613fe78960186156cd565b613ff49082901b8b615651565b9950505050505050505060018161400b9190615651565b9050613f59565b509392505050565b6000610b066040836157dc565b60006140346040836157dc565b610b069060c0615651565b60006001600160a01b0384163b1561414157604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906140839033908990889088906004016153b7565b602060405180830381600087803b15801561409d57600080fd5b505af19250505080156140cd575060408051601f3d908101601f191682019092526140ca91810190614c62565b60015b614127573d8080156140fb576040519150601f19603f3d011682016040523d82523d6000602084013e614100565b606091505b50805161411f5760405162461bcd60e51b8152600401610b6a906154ff565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506133fb565b5060016133fb565b60008282111561415b57506000610b06565b611f42828461571b565b6000607b846004811061418857634e487b7160e01b600052603260045260246000fd5b6001600160a01b038416600090815291016020526040902054905080156126085760765460405163985c5cd960e01b8152600481018390526000916001600160a01b03169063985c5cd99060240160206040518083038186803b1580156141ee57600080fd5b505afa158015614202573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142269190614d23565b905061423481846000614293565b6000607b866004811061425757634e487b7160e01b600052603260045260246000fd5b6001600160a01b038616600090815291016020908152604080832093909355868252608090522080546001600160a01b03191690555050505050565b6003601384901c1660006142a68561220f565b905060006142b38661255d565b90508315614317576142d68360ff1660016142cd896111f3565b60ff1688614675565b60058260ff1610156142f4576142f48260ff1660016142cd89612bb7565b60058160ff161015614312576143128160ff1660016142cd89612258565b614365565b6143298360ff1660006142cd896111f3565b60058260ff161015614347576143478260ff1660006142cd89612bb7565b60058160ff161015614365576143658160ff1660006142cd89612258565b505050505050565b6000600161437a846122cb565b614384919061571b565b6000838152600860205260409020549091508082146143d7576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b60095460009061441c9060019061571b565b6000838152600a60205260408120546009805493945090928490811061445257634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050806009838154811061448157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255828152600a909152604080822084905585825281205560098054806144c757634e487b7160e01b600052603160045260246000fd5b6001900381819060005260206000200160009055905550505050565b60006144ee836122cb565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b6001600160a01b03821661457d5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b6a565b6000818152600360205260409020546001600160a01b0316156145e25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b6a565b6145ee60008383613e50565b6001600160a01b0382166000908152600460205260408120805460019290614617908490615651565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b836146df576001600160a01b0381166000908152607f60205260409020546146a7906001600160401b03168385614864565b6001600160a01b0382166000908152607f60205260409020805467ffffffffffffffff19166001600160401b03929092169190911790555b6001841415614764576001600160a01b0381166000908152607f602052604090205461471c90600160401b90046001600160401b03168385614864565b6001600160a01b0382166000908152607f6020526040902080546001600160401b0392909216600160401b026fffffffffffffffff0000000000000000199092169190911790555b60028414156147e4576001600160a01b0381166000908152607f60205260409020546147a190600160801b90046001600160401b03168385614864565b6001600160a01b0382166000908152607f6020526040902080546001600160401b0392909216600160801b0267ffffffffffffffff60801b199092169190911790555b6003841415612608576001600160a01b0381166000908152607f602052604090205461482190600160c01b90046001600160401b03168385614864565b6001600160a01b0382166000908152607f6020526040902080546001600160401b0392909216600160c01b026001600160c01b0390921691909117905550505050565b6000811561487d576148768385615651565b90506117fa565b6133fb838561571b565b60405180608001604052806004906020820280368337509192915050565b60006148b86148b38461562a565b6155d7565b90508281528383830111156148cc57600080fd5b828260208301376000602084830101529392505050565b600082601f8301126148f3578081fd5b813560206149036148b383615607565b80838252828201915082860187848660051b8901011115614922578586fd5b855b8581101561494057813584529284019290840190600101614924565b5090979650505050505050565b8035801515811461495d57600080fd5b919050565b600060808284031215614973578081fd5b604051608081018181106001600160401b03821117156149955761499561581c565b6040529050806149a4836149e0565b81526149b2602084016149e0565b60208201526149c3604084016149e0565b60408201526149d4606084016149e0565b60608201525092915050565b80356001600160401b038116811461495d57600080fd5b600060208284031215614a08578081fd5b81356117fa81615832565b600060208284031215614a24578081fd5b81516117fa81615832565b60008060408385031215614a41578081fd5b8235614a4c81615832565b91506020830135614a5c81615832565b809150509250929050565b600080600060608486031215614a7b578081fd5b8335614a8681615832565b92506020840135614a9681615832565b929592945050506040919091013590565b60008060008060808587031215614abc578081fd5b8435614ac781615832565b93506020850135614ad781615832565b92506040850135915060608501356001600160401b03811115614af8578182fd5b8501601f81018713614b08578182fd5b614b17878235602084016148a5565b91505092959194509250565b60008060408385031215614b35578182fd5b8235614b4081615832565b9150614b4e6020840161494d565b90509250929050565b60008060408385031215614b69578182fd5b8235614b7481615832565b946020939093013593505050565b600060208284031215614b93578081fd5b81356001600160401b03811115614ba8578182fd5b6133fb848285016148e3565b60006020808385031215614bc6578182fd5b82516001600160401b03811115614bdb578283fd5b8301601f81018513614beb578283fd5b8051614bf96148b382615607565b80828252848201915084840188868560051b8701011115614c18578687fd5b8694505b83851015614c3a578051835260019490940193918501918501614c1c565b50979650505050505050565b600060208284031215614c57578081fd5b81356117fa81615847565b600060208284031215614c73578081fd5b81516117fa81615847565b600060208284031215614c8f578081fd5b81516001600160401b03811115614ca4578182fd5b8201601f81018413614cb4578182fd5b8051614cc26148b38261562a565b818152856020838501011115614cd6578384fd5b614ce782602083016020860161575a565b95945050505050565b600060808284031215614d01578081fd5b6117fa8383614962565b600060208284031215614d1c578081fd5b5035919050565b600060208284031215614d34578081fd5b5051919050565b60008060408385031215614d4d578182fd5b823591506020830135614a5c81615832565b600080600060608486031215614d73578081fd5b8335925060208401356001600160401b0380821115614d90578283fd5b614d9c878388016148e3565b93506040860135915080821115614db1578283fd5b508401601f81018613614dc2578182fd5b614dd1868235602084016148a5565b9150509250925092565b60008060006101208486031215614df0578081fd5b83359250614e018560208601614962565b9150614e108560a08601614962565b90509250925092565b600080600060c08486031215614e2d578081fd5b83359250614e3e8560208601614962565b915060a084013590509250925092565b60008060408385031215614e60578182fd5b50508035926020909101359150565b600080600060608486031215614e83578081fd5b505081359360208301359350604090920135919050565b60008060008060808587031215614eaf578182fd5b5050823594602084013594506040840135936060013592509050565b60008060408385031215614edd578182fd5b82356bffffffffffffffffffffffff81168114614b40578283fd5b6000815180845260208085019450808401835b83811015614f2757815187529582019590820190600101614f0b565b509495945050505050565b60008151808452614f4a81602086016020860161575a565b601f01601f19169290920160200192915050565b60008151614f7081856020860161575a565b9290920192915050565b60008251614f8c81846020870161575a565b605d60f81b920191825250600101919050565b60008651614fb1818460208b0161575a565b808301905061016160f51b8082528751614fd2816002850160208c0161575a565b600292019182018190528651614fef816004850160208b0161575a565b60049201918201819052855161500c816006850160208a0161575a565b60069201918201528351600282019161502d9082906008016020880161575a565b01600601979650505050505050565b6000835161504e81846020880161575a565b80830190507f2c207b202274726169745f74797065223a20225261726520466f726d222c20228152683b30b63ab2911d101160b91b6020820152835161509b81602984016020880161575a565b6222207d60e81b60299290910191820152602c01949350505050565b7f7b2022646973706c61795f74797065223a20226e756d626572222c202274726181526a34ba2fba3cb832911d101160a91b60208201526000835161510381602b85016020880161575a565b6b0111610113b30b63ab2911d160a51b602b91840191820152835161512f81603784016020880161575a565b607d60f81b60379290910191820152603801949350505050565b7f7374796c653d226261636b67726f756e642d636f6c6f723a202300000000000081526000825161518181601a85016020870161575a565b601160f91b601a939091019283015250601b01919050565b717b226e616d65223a20226d6669656e64202360701b815283516000906151c781601285016020890161575a565b7f222c20226465736372697074696f6e223a202241206669656e642063617074756012918401918201527f7265642062792070726f6f662d6f662d636f6d6261742e222c2022696d616765603282015263111d101160e11b6052820152845161523781605684016020890161575a565b6201116160ed1b60569290910191820152835161525b81605984016020880161575a565b61207d60f01b60599290910191820152605b0195945050505050565b7f2261747472696275746573223a205b7b202274726169745f74797065223a20228152600060207420b33334b734ba3c911610113b30b63ab2911d101160591b81840152603582865484600182811c9150808316806152d757607f831692505b8683108114156152f557634e487b7160e01b88526022600452602488fd5b808015615309576001811461531e5761534e565b60ff1985168a880152838a018701955061534e565b60008c815260209020895b858110156153445781548c82018a0152908401908901615329565b505086848b010195505b50507f22207d2c207b202274726169745f74797065223a2022506f776572204c657665845250506d36111610113b30b63ab2911d101160911b6020830152506153ac61539d602e830188614f5e565b6222207d60e81b815260030190565b979650505050505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061284890830184614f32565b60808101818360005b60048110156154125781518352602092830192909101906001016153f3565b50505092915050565b6020815260006117fa6020830184614ef8565b60e08152600061544160e083018a614ef8565b8281036020840152615453818a614ef8565b905087604084015286606084015282810360808401526154738187614f32565b60a0840195909552505060c0015295945050505050565b60608152600061549d6060830186614ef8565b828103602084810191909152855480835286845281842092820190845b818110156154d6578454835260019485019492840192016154ba565b5050809350505050826040830152949350505050565b6020815260006117fa6020830184614f32565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b604051601f8201601f191681016001600160401b03811182821017156155ff576155ff61581c565b604052919050565b60006001600160401b038211156156205761562061581c565b5060051b60200190565b60006001600160401b038211156156435761564361581c565b50601f01601f191660200190565b60008219821115615664576156646157f0565b500190565b60006001600160401b0380831681851680830382111561568b5761568b6157f0565b01949350505050565b600060ff821660ff84168060ff038211156156b1576156b16157f0565b019392505050565b6000826156c8576156c8615806565b500490565b60008160001904831182151516156156e7576156e76157f0565b500290565b60006001600160401b0380831681851681830481118215151615615712576157126157f0565b02949350505050565b60008282101561572d5761572d6157f0565b500390565b60006001600160401b0383811690831681811015615752576157526157f0565b039392505050565b60005b8381101561577557818101518382015260200161575d565b838111156126085750506000910152565b600181811c9082168061579a57607f821691505b602082108114156157bb57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156157d5576157d56157f0565b5060010190565b6000826157eb576157eb615806565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114612cc157600080fd5b6001600160e01b031981168114612cc157600080fdfea264697066735822122013c8f7abd840b8734cf4115b85c0e26a07e5647ee2399a2943b2265dd8b4b0a964736f6c63430008040033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000005d070a1c9acdc38d853d8501f2740fab9e9b4821000000000000000000000000fcbad2f45676397792381612913491321e2aad75000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

-----Decoded View---------------
Arg [0] : _mineableGear (address): 0x5d070A1c9Acdc38d853D8501F2740FaB9e9B4821
Arg [1] : _onChainPixelArt (address): 0xfCBaD2f45676397792381612913491321E2aad75
Arg [2] : _difficulty (uint256): 6901746346790563787434755862277025452451108972170386555162524223799295

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000005d070a1c9acdc38d853d8501f2740fab9e9b4821
Arg [1] : 000000000000000000000000fcbad2f45676397792381612913491321e2aad75
Arg [2] : 000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff


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

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