ETH Price: $3,033.43 (+0.32%)
Gas: 3 Gwei

Token

Wolf Game (WGAME)
 

Overview

Max Total Supply

13,809 WGAME

Holders

12

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
Null: 0x000...000
Balance
0 WGAME
0x0000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Thousands of Sheep and Wolves compete on a farm in the metaverse. A tempting prize of WOOL awaits, with deadly high stakes. All the metadata and images are generated and stored 100% on-chain. No IPFS. NO API. Just the Ethereum blockchain.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Woolf

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 23 of 23: Woolf.sol
// SPDX-License-Identifier: MIT LICENSE

pragma solidity ^0.8.0;
import "./Ownable.sol";
import "./Pausable.sol";
import "./ERC721Enumerable.sol";
import "./IWoolf.sol";
import "./IBarn.sol";
import "./ITraits.sol";
import "./WOOL.sol";


contract Woolf is IWoolf, ERC721Enumerable, Ownable, Pausable {

  // mint price
  uint256 public constant MINT_PRICE = .069420 ether;
  // max number of tokens that can be minted - 50000 in production
  uint256 public immutable MAX_TOKENS;
  // number of tokens that can be claimed for free - 20% of MAX_TOKENS
  uint256 public PAID_TOKENS;
  // number of tokens have been minted so far
  uint16 public minted;

  // mapping from tokenId to a struct containing the token's traits
  mapping(uint256 => SheepWolf) public tokenTraits;
  // mapping from hashed(tokenTrait) to the tokenId it's associated with
  // used to ensure there are no duplicates
  mapping(uint256 => uint256) public existingCombinations;

  // list of probabilities for each trait type
  // 0 - 9 are associated with Sheep, 10 - 18 are associated with Wolves
  uint8[][18] public rarities;
  // list of aliases for Walker's Alias algorithm
  // 0 - 9 are associated with Sheep, 10 - 18 are associated with Wolves
  uint8[][18] public aliases;

  // reference to the Barn for choosing random Wolf thieves
  IBarn public barn;
  // reference to $WOOL for burning on mint
  WOOL public wool;
  // reference to Traits
  ITraits public traits;

  /** 
   * instantiates contract and rarity tables
   */
  constructor(address _wool, address _traits, uint256 _maxTokens) ERC721("Wolf Game", 'WGAME') { 
    wool = WOOL(_wool);
    traits = ITraits(_traits);
    MAX_TOKENS = _maxTokens;
    PAID_TOKENS = _maxTokens / 5;

    // I know this looks weird but it saves users gas by making lookup O(1)
    // A.J. Walker's Alias Algorithm
    // sheep
    // fur
    rarities[0] = [15, 50, 200, 250, 255];
    aliases[0] = [4, 4, 4, 4, 4];
    // head
    rarities[1] = [190, 215, 240, 100, 110, 135, 160, 185, 80, 210, 235, 240, 80, 80, 100, 100, 100, 245, 250, 255];
    aliases[1] = [1, 2, 4, 0, 5, 6, 7, 9, 0, 10, 11, 17, 0, 0, 0, 0, 4, 18, 19, 19];
    // ears
    rarities[2] =  [255, 30, 60, 60, 150, 156];
    aliases[2] = [0, 0, 0, 0, 0, 0];
    // eyes
    rarities[3] = [221, 100, 181, 140, 224, 147, 84, 228, 140, 224, 250, 160, 241, 207, 173, 84, 254, 220, 196, 140, 168, 252, 140, 183, 236, 252, 224, 255];
    aliases[3] = [1, 2, 5, 0, 1, 7, 1, 10, 5, 10, 11, 12, 13, 14, 16, 11, 17, 23, 13, 14, 17, 23, 23, 24, 27, 27, 27, 27];
    // nose
    rarities[4] = [175, 100, 40, 250, 115, 100, 185, 175, 180, 255];
    aliases[4] = [3, 0, 4, 6, 6, 7, 8, 8, 9, 9];
    // mouth
    rarities[5] = [80, 225, 227, 228, 112, 240, 64, 160, 167, 217, 171, 64, 240, 126, 80, 255];
    aliases[5] = [1, 2, 3, 8, 2, 8, 8, 9, 9, 10, 13, 10, 13, 15, 13, 15];
    // neck
    rarities[6] = [255];
    aliases[6] = [0];
    // feet
    rarities[7] = [243, 189, 133, 133, 57, 95, 152, 135, 133, 57, 222, 168, 57, 57, 38, 114, 114, 114, 255];
    aliases[7] = [1, 7, 0, 0, 0, 0, 0, 10, 0, 0, 11, 18, 0, 0, 0, 1, 7, 11, 18];
    // alphaIndex
    rarities[8] = [255];
    aliases[8] = [0];

    // wolves
    // fur
    rarities[9] = [210, 90, 9, 9, 9, 150, 9, 255, 9];
    aliases[9] = [5, 0, 0, 5, 5, 7, 5, 7, 5];
    // head
    rarities[10] = [255];
    aliases[10] = [0];
    // ears
    rarities[11] = [255];
    aliases[11] = [0];
    // eyes
    rarities[12] = [135, 177, 219, 141, 183, 225, 147, 189, 231, 135, 135, 135, 135, 246, 150, 150, 156, 165, 171, 180, 186, 195, 201, 210, 243, 252, 255];
    aliases[12] = [1, 2, 3, 4, 5, 6, 7, 8, 13, 3, 6, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26];
    // nose
    rarities[13] = [255];
    aliases[13] = [0];
    // mouth
    rarities[14] = [239, 244, 249, 234, 234, 234, 234, 234, 234, 234, 130, 255, 247];
    aliases[14] = [1, 2, 11, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11];
    // neck
    rarities[15] = [75, 180, 165, 120, 60, 150, 105, 195, 45, 225, 75, 45, 195, 120, 255];
    aliases[15] = [1, 9, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 14, 12, 14];
    // feet 
    rarities[16] = [255];
    aliases[16] = [0];
    // alphaIndex
    rarities[17] = [8, 160, 73, 255]; 
    aliases[17] = [2, 3, 3, 3];
  }

  /** EXTERNAL */

  /** 
   * mint a token - 90% Sheep, 10% Wolves
   * The first 20% are free to claim, the remaining cost $WOOL
   */
  function mint(uint256 amount, bool stake) external payable whenNotPaused {
    require(tx.origin == _msgSender(), "Only EOA");
    require(minted + amount <= MAX_TOKENS, "All tokens minted");
    require(amount > 0 && amount <= 10, "Invalid mint amount");
    if (minted < PAID_TOKENS) {
      require(minted + amount <= PAID_TOKENS, "All tokens on-sale already sold");
      require(amount * MINT_PRICE == msg.value, "Invalid payment amount");
    } else {
      require(msg.value == 0);
    }

    uint256 totalWoolCost = 0;
    uint16[] memory tokenIds = stake ? new uint16[](amount) : new uint16[](0);
    uint256 seed;
    for (uint i = 0; i < amount; i++) {
      minted++;
      seed = random(minted);
      generate(minted, seed);
      address recipient = selectRecipient(seed);
      if (!stake || recipient != _msgSender()) {
        _safeMint(recipient, minted);
      } else {
        _safeMint(address(barn), minted);
        tokenIds[i] = minted;
      }
      totalWoolCost += mintCost(minted);
    }
    
    if (totalWoolCost > 0) wool.burn(_msgSender(), totalWoolCost);
    if (stake) barn.addManyToBarnAndPack(_msgSender(), tokenIds);
  }

  /** 
   * the first 20% are paid in ETH
   * the next 20% are 20000 $WOOL
   * the next 40% are 40000 $WOOL
   * the final 20% are 80000 $WOOL
   * @param tokenId the ID to check the cost of to mint
   * @return the cost of the given token ID
   */
  function mintCost(uint256 tokenId) public view returns (uint256) {
    if (tokenId <= PAID_TOKENS) return 0;
    if (tokenId <= MAX_TOKENS * 2 / 5) return 20000 ether;
    if (tokenId <= MAX_TOKENS * 4 / 5) return 40000 ether;
    return 80000 ether;
  }

  function transferFrom(
    address from,
    address to,
    uint256 tokenId
  ) public virtual override {
    // Hardcode the Barn's approval so that users don't have to waste gas approving
    if (_msgSender() != address(barn))
      require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
    _transfer(from, to, tokenId);
  }

  /** INTERNAL */

  /**
   * generates traits for a specific token, checking to make sure it's unique
   * @param tokenId the id of the token to generate traits for
   * @param seed a pseudorandom 256 bit number to derive traits from
   * @return t - a struct of traits for the given token ID
   */
  function generate(uint256 tokenId, uint256 seed) internal returns (SheepWolf memory t) {
    t = selectTraits(seed);
    if (existingCombinations[structToHash(t)] == 0) {
      tokenTraits[tokenId] = t;
      existingCombinations[structToHash(t)] = tokenId;
      return t;
    }
    return generate(tokenId, random(seed));
  }

  /**
   * uses A.J. Walker's Alias algorithm for O(1) rarity table lookup
   * ensuring O(1) instead of O(n) reduces mint cost by more than 50%
   * probability & alias tables are generated off-chain beforehand
   * @param seed portion of the 256 bit seed to remove trait correlation
   * @param traitType the trait type to select a trait for 
   * @return the ID of the randomly selected trait
   */
  function selectTrait(uint16 seed, uint8 traitType) internal view returns (uint8) {
    uint8 trait = uint8(seed) % uint8(rarities[traitType].length);
    if (seed >> 8 < rarities[traitType][trait]) return trait;
    return aliases[traitType][trait];
  }

  /**
   * the first 20% (ETH purchases) go to the minter
   * the remaining 80% have a 10% chance to be given to a random staked wolf
   * @param seed a random value to select a recipient from
   * @return the address of the recipient (either the minter or the Wolf thief's owner)
   */
  function selectRecipient(uint256 seed) internal view returns (address) {
    if (minted <= PAID_TOKENS || ((seed >> 245) % 10) != 0) return _msgSender(); // top 10 bits haven't been used
    address thief = barn.randomWolfOwner(seed >> 144); // 144 bits reserved for trait selection
    if (thief == address(0x0)) return _msgSender();
    return thief;
  }

  /**
   * selects the species and all of its traits based on the seed value
   * @param seed a pseudorandom 256 bit number to derive traits from
   * @return t -  a struct of randomly selected traits
   */
  function selectTraits(uint256 seed) internal view returns (SheepWolf memory t) {    
    t.isSheep = (seed & 0xFFFF) % 10 != 0;
    uint8 shift = t.isSheep ? 0 : 9;
    seed >>= 16;
    t.fur = selectTrait(uint16(seed & 0xFFFF), 0 + shift);
    seed >>= 16;
    t.head = selectTrait(uint16(seed & 0xFFFF), 1 + shift);
    seed >>= 16;
    t.ears = selectTrait(uint16(seed & 0xFFFF), 2 + shift);
    seed >>= 16;
    t.eyes = selectTrait(uint16(seed & 0xFFFF), 3 + shift);
    seed >>= 16;
    t.nose = selectTrait(uint16(seed & 0xFFFF), 4 + shift);
    seed >>= 16;
    t.mouth = selectTrait(uint16(seed & 0xFFFF), 5 + shift);
    seed >>= 16;
    t.neck = selectTrait(uint16(seed & 0xFFFF), 6 + shift);
    seed >>= 16;
    t.feet = selectTrait(uint16(seed & 0xFFFF), 7 + shift);
    seed >>= 16;
    t.alphaIndex = selectTrait(uint16(seed & 0xFFFF), 8 + shift);
  }

  /**
   * converts a struct to a 256 bit hash to check for uniqueness
   * @param s the struct to pack into a hash
   * @return the 256 bit hash of the struct
   */
  function structToHash(SheepWolf memory s) internal pure returns (uint256) {
    return uint256(bytes32(
      abi.encodePacked(
        s.isSheep,
        s.fur,
        s.head,
        s.eyes,
        s.mouth,
        s.neck,
        s.ears,
        s.feet,
        s.alphaIndex
      )
    ));
  }

  /**
   * generates a pseudorandom number
   * @param seed a value ensure different outcomes for different sources in the same block
   * @return a pseudorandom value
   */
  function random(uint256 seed) internal view returns (uint256) {
    return uint256(keccak256(abi.encodePacked(
      tx.origin,
      blockhash(block.number - 1),
      block.timestamp,
      seed
    )));
  }

  /** READ */

  function getTokenTraits(uint256 tokenId) external view override returns (SheepWolf memory) {
    return tokenTraits[tokenId];
  }

  function getPaidTokens() external view override returns (uint256) {
    return PAID_TOKENS;
  }

  /** ADMIN */

  /**
   * called after deployment so that the contract can get random wolf thieves
   * @param _barn the address of the Barn
   */
  function setBarn(address _barn) external onlyOwner {
    barn = IBarn(_barn);
  }

  /**
   * allows owner to withdraw funds from minting
   */
  function withdraw() external onlyOwner {
    payable(owner()).transfer(address(this).balance);
  }

  /**
   * updates the number of tokens for sale
   */
  function setPaidTokens(uint256 _paidTokens) external onlyOwner {
    PAID_TOKENS = _paidTokens;
  }

  /**
   * enables owner to pause / unpause minting
   */
  function setPaused(bool _paused) external onlyOwner {
    if (_paused) _pause();
    else _unpause();
  }

  /** RENDER */

  function tokenURI(uint256 tokenId) public view override returns (string memory) {
    require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
    return traits.tokenURI(tokenId);
  }
}

File 1 of 23: 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);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal 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 2 of 23: Barn.sol
// SPDX-License-Identifier: MIT LICENSE

pragma solidity ^0.8.0;

import "./IERC721Receiver.sol";
import "./Pausable.sol";
import "./Woolf.sol";
import "./WOOL.sol";

contract Barn is Ownable, IERC721Receiver, Pausable {
  
  // maximum alpha score for a Wolf
  uint8 public constant MAX_ALPHA = 8;

  // struct to store a stake's token, owner, and earning values
  struct Stake {
    uint16 tokenId;
    uint80 value;
    address owner;
  }

  event TokenStaked(address owner, uint256 tokenId, uint256 value);
  event SheepClaimed(uint256 tokenId, uint256 earned, bool unstaked);
  event WolfClaimed(uint256 tokenId, uint256 earned, bool unstaked);

  // reference to the Woolf NFT contract
  Woolf woolf;
  // reference to the $WOOL contract for minting $WOOL earnings
  WOOL wool;

  // maps tokenId to stake
  mapping(uint256 => Stake) public barn; 
  // maps alpha to all Wolf stakes with that alpha
  mapping(uint256 => Stake[]) public pack; 
  // tracks location of each Wolf in Pack
  mapping(uint256 => uint256) public packIndices; 
  // total alpha scores staked
  uint256 public totalAlphaStaked = 0; 
  // any rewards distributed when no wolves are staked
  uint256 public unaccountedRewards = 0; 
  // amount of $WOOL due for each alpha point staked
  uint256 public woolPerAlpha = 0; 

  // sheep earn 10000 $WOOL per day
  uint256 public constant DAILY_WOOL_RATE = 10000 ether;
  // sheep must have 2 days worth of $WOOL to unstake or else it's too cold
  uint256 public constant MINIMUM_TO_EXIT = 2 days;
  // wolves take a 20% tax on all $WOOL claimed
  uint256 public constant WOOL_CLAIM_TAX_PERCENTAGE = 20;
  // there will only ever be (roughly) 2.4 billion $WOOL earned through staking
  uint256 public constant MAXIMUM_GLOBAL_WOOL = 2400000000 ether;

  // amount of $WOOL earned so far
  uint256 public totalWoolEarned;
  // number of Sheep staked in the Barn
  uint256 public totalSheepStaked;
  // the last time $WOOL was claimed
  uint256 public lastClaimTimestamp;

  // emergency rescue to allow unstaking without any checks but without $WOOL
  bool public rescueEnabled = false;

  /**
   * @param _woolf reference to the Woolf NFT contract
   * @param _wool reference to the $WOOL token
   */
  constructor(address _woolf, address _wool) { 
    woolf = Woolf(_woolf);
    wool = WOOL(_wool);
  }

  /** STAKING */

  /**
   * adds Sheep and Wolves to the Barn and Pack
   * @param account the address of the staker
   * @param tokenIds the IDs of the Sheep and Wolves to stake
   */
  function addManyToBarnAndPack(address account, uint16[] calldata tokenIds) external {
    require(account == _msgSender() || _msgSender() == address(woolf), "DONT GIVE YOUR TOKENS AWAY");
    for (uint i = 0; i < tokenIds.length; i++) {
      if (_msgSender() != address(woolf)) { // dont do this step if its a mint + stake
        require(woolf.ownerOf(tokenIds[i]) == _msgSender(), "AINT YO TOKEN");
        woolf.transferFrom(_msgSender(), address(this), tokenIds[i]);
      } else if (tokenIds[i] == 0) {
        continue; // there may be gaps in the array for stolen tokens
      }

      if (isSheep(tokenIds[i])) 
        _addSheepToBarn(account, tokenIds[i]);
      else 
        _addWolfToPack(account, tokenIds[i]);
    }
  }

  /**
   * adds a single Sheep to the Barn
   * @param account the address of the staker
   * @param tokenId the ID of the Sheep to add to the Barn
   */
  function _addSheepToBarn(address account, uint256 tokenId) internal whenNotPaused _updateEarnings {
    barn[tokenId] = Stake({
      owner: account,
      tokenId: uint16(tokenId),
      value: uint80(block.timestamp)
    });
    totalSheepStaked += 1;
    emit TokenStaked(account, tokenId, block.timestamp);
  }

  /**
   * adds a single Wolf to the Pack
   * @param account the address of the staker
   * @param tokenId the ID of the Wolf to add to the Pack
   */
  function _addWolfToPack(address account, uint256 tokenId) internal {
    uint256 alpha = _alphaForWolf(tokenId);
    totalAlphaStaked += alpha; // Portion of earnings ranges from 8 to 5
    packIndices[tokenId] = pack[alpha].length; // Store the location of the wolf in the Pack
    pack[alpha].push(Stake({
      owner: account,
      tokenId: uint16(tokenId),
      value: uint80(woolPerAlpha)
    })); // Add the wolf to the Pack
    emit TokenStaked(account, tokenId, woolPerAlpha);
  }

  /** CLAIMING / UNSTAKING */

  /**
   * realize $WOOL earnings and optionally unstake tokens from the Barn / Pack
   * to unstake a Sheep it will require it has 2 days worth of $WOOL unclaimed
   * @param tokenIds the IDs of the tokens to claim earnings from
   * @param unstake whether or not to unstake ALL of the tokens listed in tokenIds
   */
  function claimManyFromBarnAndPack(uint16[] calldata tokenIds, bool unstake) external whenNotPaused _updateEarnings {
    uint256 owed = 0;
    for (uint i = 0; i < tokenIds.length; i++) {
      if (isSheep(tokenIds[i]))
        owed += _claimSheepFromBarn(tokenIds[i], unstake);
      else
        owed += _claimWolfFromPack(tokenIds[i], unstake);
    }
    if (owed == 0) return;
    wool.mint(_msgSender(), owed);
  }

  /**
   * realize $WOOL earnings for a single Sheep and optionally unstake it
   * if not unstaking, pay a 20% tax to the staked Wolves
   * if unstaking, there is a 50% chance all $WOOL is stolen
   * @param tokenId the ID of the Sheep to claim earnings from
   * @param unstake whether or not to unstake the Sheep
   * @return owed - the amount of $WOOL earned
   */
  function _claimSheepFromBarn(uint256 tokenId, bool unstake) internal returns (uint256 owed) {
    Stake memory stake = barn[tokenId];
    require(stake.owner == _msgSender(), "SWIPER, NO SWIPING");
    require(!(unstake && block.timestamp - stake.value < MINIMUM_TO_EXIT), "GONNA BE COLD WITHOUT TWO DAY'S WOOL");
    if (totalWoolEarned < MAXIMUM_GLOBAL_WOOL) {
      owed = (block.timestamp - stake.value) * DAILY_WOOL_RATE / 1 days;
    } else if (stake.value > lastClaimTimestamp) {
      owed = 0; // $WOOL production stopped already
    } else {
      owed = (lastClaimTimestamp - stake.value) * DAILY_WOOL_RATE / 1 days; // stop earning additional $WOOL if it's all been earned
    }
    if (unstake) {
      if (random(tokenId) & 1 == 1) { // 50% chance of all $WOOL stolen
        _payWolfTax(owed);
        owed = 0;
      }
      woolf.safeTransferFrom(address(this), _msgSender(), tokenId, ""); // send back Sheep
      delete barn[tokenId];
      totalSheepStaked -= 1;
    } else {
      _payWolfTax(owed * WOOL_CLAIM_TAX_PERCENTAGE / 100); // percentage tax to staked wolves
      owed = owed * (100 - WOOL_CLAIM_TAX_PERCENTAGE) / 100; // remainder goes to Sheep owner
      barn[tokenId] = Stake({
        owner: _msgSender(),
        tokenId: uint16(tokenId),
        value: uint80(block.timestamp)
      }); // reset stake
    }
    emit SheepClaimed(tokenId, owed, unstake);
  }

  /**
   * realize $WOOL earnings for a single Wolf and optionally unstake it
   * Wolves earn $WOOL proportional to their Alpha rank
   * @param tokenId the ID of the Wolf to claim earnings from
   * @param unstake whether or not to unstake the Wolf
   * @return owed - the amount of $WOOL earned
   */
  function _claimWolfFromPack(uint256 tokenId, bool unstake) internal returns (uint256 owed) {
    require(woolf.ownerOf(tokenId) == address(this), "AINT A PART OF THE PACK");
    uint256 alpha = _alphaForWolf(tokenId);
    Stake memory stake = pack[alpha][packIndices[tokenId]];
    require(stake.owner == _msgSender(), "SWIPER, NO SWIPING");
    owed = (alpha) * (woolPerAlpha - stake.value); // Calculate portion of tokens based on Alpha
    if (unstake) {
      totalAlphaStaked -= alpha; // Remove Alpha from total staked
      woolf.safeTransferFrom(address(this), _msgSender(), tokenId, ""); // Send back Wolf
      Stake memory lastStake = pack[alpha][pack[alpha].length - 1];
      pack[alpha][packIndices[tokenId]] = lastStake; // Shuffle last Wolf to current position
      packIndices[lastStake.tokenId] = packIndices[tokenId];
      pack[alpha].pop(); // Remove duplicate
      delete packIndices[tokenId]; // Delete old mapping
    } else {
      pack[alpha][packIndices[tokenId]] = Stake({
        owner: _msgSender(),
        tokenId: uint16(tokenId),
        value: uint80(woolPerAlpha)
      }); // reset stake
    }
    emit WolfClaimed(tokenId, owed, unstake);
  }

  /**
   * emergency unstake tokens
   * @param tokenIds the IDs of the tokens to claim earnings from
   */
  function rescue(uint256[] calldata tokenIds) external {
    require(rescueEnabled, "RESCUE DISABLED");
    uint256 tokenId;
    Stake memory stake;
    Stake memory lastStake;
    uint256 alpha;
    for (uint i = 0; i < tokenIds.length; i++) {
      tokenId = tokenIds[i];
      if (isSheep(tokenId)) {
        stake = barn[tokenId];
        require(stake.owner == _msgSender(), "SWIPER, NO SWIPING");
        woolf.safeTransferFrom(address(this), _msgSender(), tokenId, ""); // send back Sheep
        delete barn[tokenId];
        totalSheepStaked -= 1;
        emit SheepClaimed(tokenId, 0, true);
      } else {
        alpha = _alphaForWolf(tokenId);
        stake = pack[alpha][packIndices[tokenId]];
        require(stake.owner == _msgSender(), "SWIPER, NO SWIPING");
        totalAlphaStaked -= alpha; // Remove Alpha from total staked
        woolf.safeTransferFrom(address(this), _msgSender(), tokenId, ""); // Send back Wolf
        lastStake = pack[alpha][pack[alpha].length - 1];
        pack[alpha][packIndices[tokenId]] = lastStake; // Shuffle last Wolf to current position
        packIndices[lastStake.tokenId] = packIndices[tokenId];
        pack[alpha].pop(); // Remove duplicate
        delete packIndices[tokenId]; // Delete old mapping
        emit WolfClaimed(tokenId, 0, true);
      }
    }
  }

  /** ACCOUNTING */

  /** 
   * add $WOOL to claimable pot for the Pack
   * @param amount $WOOL to add to the pot
   */
  function _payWolfTax(uint256 amount) internal {
    if (totalAlphaStaked == 0) { // if there's no staked wolves
      unaccountedRewards += amount; // keep track of $WOOL due to wolves
      return;
    }
    // makes sure to include any unaccounted $WOOL 
    woolPerAlpha += (amount + unaccountedRewards) / totalAlphaStaked;
    unaccountedRewards = 0;
  }

  /**
   * tracks $WOOL earnings to ensure it stops once 2.4 billion is eclipsed
   */
  modifier _updateEarnings() {
    if (totalWoolEarned < MAXIMUM_GLOBAL_WOOL) {
      totalWoolEarned += 
        (block.timestamp - lastClaimTimestamp)
        * totalSheepStaked
        * DAILY_WOOL_RATE / 1 days; 
      lastClaimTimestamp = block.timestamp;
    }
    _;
  }

  /** ADMIN */

  /**
   * allows owner to enable "rescue mode"
   * simplifies accounting, prioritizes tokens out in emergency
   */
  function setRescueEnabled(bool _enabled) external onlyOwner {
    rescueEnabled = _enabled;
  }

  /**
   * enables owner to pause / unpause minting
   */
  function setPaused(bool _paused) external onlyOwner {
    if (_paused) _pause();
    else _unpause();
  }

  /** READ ONLY */

  /**
   * checks if a token is a Sheep
   * @param tokenId the ID of the token to check
   * @return sheep - whether or not a token is a Sheep
   */
  function isSheep(uint256 tokenId) public view returns (bool sheep) {
    (sheep, , , , , , , , , ) = woolf.tokenTraits(tokenId);
  }

  /**
   * gets the alpha score for a Wolf
   * @param tokenId the ID of the Wolf to get the alpha score for
   * @return the alpha score of the Wolf (5-8)
   */
  function _alphaForWolf(uint256 tokenId) internal view returns (uint8) {
    ( , , , , , , , , , uint8 alphaIndex) = woolf.tokenTraits(tokenId);
    return MAX_ALPHA - alphaIndex; // alpha index is 0-3
  }

  /**
   * chooses a random Wolf thief when a newly minted token is stolen
   * @param seed a random value to choose a Wolf from
   * @return the owner of the randomly selected Wolf thief
   */
  function randomWolfOwner(uint256 seed) external view returns (address) {
    if (totalAlphaStaked == 0) return address(0x0);
    uint256 bucket = (seed & 0xFFFFFFFF) % totalAlphaStaked; // choose a value from 0 to total alpha staked
    uint256 cumulative;
    seed >>= 32;
    // loop through each bucket of Wolves with the same alpha score
    for (uint i = MAX_ALPHA - 3; i <= MAX_ALPHA; i++) {
      cumulative += pack[i].length * i;
      // if the value is not inside of that bucket, keep going
      if (bucket >= cumulative) continue;
      // get the address of a random Wolf with that alpha score
      return pack[i][seed % pack[i].length].owner;
    }
    return address(0x0);
  }

  /**
   * generates a pseudorandom number
   * @param seed a value ensure different outcomes for different sources in the same block
   * @return a pseudorandom value
   */
  function random(uint256 seed) internal view returns (uint256) {
    return uint256(keccak256(abi.encodePacked(
      tx.origin,
      blockhash(block.number - 1),
      block.timestamp,
      seed
    )));
  }

  function onERC721Received(
        address,
        address from,
        uint256,
        bytes calldata
    ) external pure override returns (bytes4) {
      require(from == address(0x0), "Cannot send tokens to Barn directly");
      return IERC721Receiver.onERC721Received.selector;
    }

  
}

File 3 of 23: 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 4 of 23: 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;
    }
}

File 5 of 23: ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./IERC20Metadata.sol";
import "./Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens 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 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been 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 _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 6 of 23: ERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./IERC721Metadata.sol";
import "./Address.sol";
import "./Context.sol";
import "./Strings.sol";
import "./ERC165.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.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 7 of 23: 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 8 of 23: IBarn.sol
// SPDX-License-Identifier: MIT LICENSE 

pragma solidity ^0.8.0;

interface IBarn {
  function addManyToBarnAndPack(address account, uint16[] calldata tokenIds) external;
  function randomWolfOwner(uint256 seed) external view returns (address);
}

File 9 of 23: 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 10 of 23: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 11 of 23: IERC20Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 12 of 23: 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 13 of 23: 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 14 of 23: 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 15 of 23: 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 16 of 23: ITraits.sol
// SPDX-License-Identifier: MIT LICENSE 

pragma solidity ^0.8.0;

interface ITraits {
  function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 17 of 23: IWoolf.sol
// SPDX-License-Identifier: MIT LICENSE

pragma solidity ^0.8.0;

interface IWoolf {

  // struct to store each token's traits
  struct SheepWolf {
    bool isSheep;
    uint8 fur;
    uint8 head;
    uint8 ears;
    uint8 eyes;
    uint8 nose;
    uint8 mouth;
    uint8 neck;
    uint8 feet;
    uint8 alphaIndex;
  }


  function getPaidTokens() external view returns (uint256);
  function getTokenTraits(uint256 tokenId) external view returns (SheepWolf memory);
}

File 18 of 23: 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 19 of 23: Pausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 20 of 23: 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 21 of 23: Traits.sol
// SPDX-License-Identifier: MIT LICENSE

pragma solidity ^0.8.0;
import "./Ownable.sol";
import "./Strings.sol";
import "./ITraits.sol";
import "./IWoolf.sol";

contract Traits is Ownable, ITraits {

  using Strings for uint256;

  // struct to store each trait's data for metadata and rendering
  struct Trait {
    string name;
    string png;
  }

  // mapping from trait type (index) to its name
  string[9] _traitTypes = [
    "Fur",
    "Head",
    "Ears",
    "Eyes",
    "Nose",
    "Mouth",
    "Neck",
    "Feet",
    "Alpha"
  ];
  // storage of each traits name and base64 PNG data
  mapping(uint8 => mapping(uint8 => Trait)) public traitData;
  // mapping from alphaIndex to its score
  string[4] _alphas = [
    "8",
    "7",
    "6",
    "5"
  ];

  IWoolf public woolf;

  constructor() {}

  /** ADMIN */

  function setWoolf(address _woolf) external onlyOwner {
    woolf = IWoolf(_woolf);
  }

  /**
   * administrative to upload the names and images associated with each trait
   * @param traitType the trait type to upload the traits for (see traitTypes for a mapping)
   * @param traits the names and base64 encoded PNGs for each trait
   */
  function uploadTraits(uint8 traitType, uint8[] calldata traitIds, Trait[] calldata traits) external onlyOwner {
    require(traitIds.length == traits.length, "Mismatched inputs");
    for (uint i = 0; i < traits.length; i++) {
      traitData[traitType][traitIds[i]] = Trait(
        traits[i].name,
        traits[i].png
      );
    }
  }

  /** RENDER */

  /**
   * generates an <image> element using base64 encoded PNGs
   * @param trait the trait storing the PNG data
   * @return the <image> element
   */
  function drawTrait(Trait memory trait) internal pure returns (string memory) {
    return string(abi.encodePacked(
      '<image x="4" y="4" width="32" height="32" image-rendering="pixelated" preserveAspectRatio="xMidYMid" xlink:href="data:image/png;base64,',
      trait.png,
      '"/>'
    ));
  }

  /**
   * generates an entire SVG by composing multiple <image> elements of PNGs
   * @param tokenId the ID of the token to generate an SVG for
   * @return a valid SVG of the Sheep / Wolf
   */
  function drawSVG(uint256 tokenId) public view returns (string memory) {
    IWoolf.SheepWolf memory s = woolf.getTokenTraits(tokenId);
    uint8 shift = s.isSheep ? 0 : 9;

    string memory svgString = string(abi.encodePacked(
      drawTrait(traitData[0 + shift][s.fur]),
      s.isSheep ? drawTrait(traitData[1 + shift][s.head]) : drawTrait(traitData[1 + shift][s.alphaIndex]),
      s.isSheep ? drawTrait(traitData[2 + shift][s.ears]) : '',
      drawTrait(traitData[3 + shift][s.eyes]),
      s.isSheep ? drawTrait(traitData[4 + shift][s.nose]) : '',
      drawTrait(traitData[5 + shift][s.mouth]),
      s.isSheep ? '' : drawTrait(traitData[6 + shift][s.neck]),
      s.isSheep ? drawTrait(traitData[7 + shift][s.feet]) : ''
    ));

    return string(abi.encodePacked(
      '<svg id="woolf" width="100%" height="100%" version="1.1" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">',
      svgString,
      "</svg>"
    ));
  }

  /**
   * generates an attribute for the attributes array in the ERC721 metadata standard
   * @param traitType the trait type to reference as the metadata key
   * @param value the token's trait associated with the key
   * @return a JSON dictionary for the single attribute
   */
  function attributeForTypeAndValue(string memory traitType, string memory value) internal pure returns (string memory) {
    return string(abi.encodePacked(
      '{"trait_type":"',
      traitType,
      '","value":"',
      value,
      '"}'
    ));
  }

  /**
   * generates an array composed of all the individual traits and values
   * @param tokenId the ID of the token to compose the metadata for
   * @return a JSON array of all of the attributes for given token ID
   */
  function compileAttributes(uint256 tokenId) public view returns (string memory) {
    IWoolf.SheepWolf memory s = woolf.getTokenTraits(tokenId);
    string memory traits;
    if (s.isSheep) {
      traits = string(abi.encodePacked(
        attributeForTypeAndValue(_traitTypes[0], traitData[0][s.fur].name),',',
        attributeForTypeAndValue(_traitTypes[1], traitData[1][s.head].name),',',
        attributeForTypeAndValue(_traitTypes[2], traitData[2][s.ears].name),',',
        attributeForTypeAndValue(_traitTypes[3], traitData[3][s.eyes].name),',',
        attributeForTypeAndValue(_traitTypes[4], traitData[4][s.nose].name),',',
        attributeForTypeAndValue(_traitTypes[5], traitData[5][s.mouth].name),',',
        attributeForTypeAndValue(_traitTypes[7], traitData[7][s.feet].name),','
      ));
    } else {
      traits = string(abi.encodePacked(
        attributeForTypeAndValue(_traitTypes[0], traitData[9][s.fur].name),',',
        attributeForTypeAndValue(_traitTypes[1], traitData[10][s.alphaIndex].name),',',
        attributeForTypeAndValue(_traitTypes[3], traitData[12][s.eyes].name),',',
        attributeForTypeAndValue(_traitTypes[5], traitData[14][s.mouth].name),',',
        attributeForTypeAndValue(_traitTypes[6], traitData[15][s.neck].name),',',
        attributeForTypeAndValue("Alpha Score", _alphas[s.alphaIndex]),','
      ));
    }
    return string(abi.encodePacked(
      '[',
      traits,
      '{"trait_type":"Generation","value":',
      tokenId <= woolf.getPaidTokens() ? '"Gen 0"' : '"Gen 1"',
      '},{"trait_type":"Type","value":',
      s.isSheep ? '"Sheep"' : '"Wolf"',
      '}]'
    ));
  }

  /**
   * generates a base64 encoded metadata response without referencing off-chain content
   * @param tokenId the ID of the token to generate the metadata for
   * @return a base64 encoded JSON dictionary of the token's metadata and SVG
   */
  function tokenURI(uint256 tokenId) public view override returns (string memory) {
    IWoolf.SheepWolf memory s = woolf.getTokenTraits(tokenId);

    string memory metadata = string(abi.encodePacked(
      '{"name": "',
      s.isSheep ? 'Sheep #' : 'Wolf #',
      tokenId.toString(),
      '", "description": "Thousands of Sheep and Wolves compete on a farm in the metaverse. A tempting prize of $WOOL awaits, with deadly high stakes. All the metadata and images are generated and stored 100% on-chain. No IPFS. NO API. Just the Ethereum blockchain.", "image": "data:image/svg+xml;base64,',
      base64(bytes(drawSVG(tokenId))),
      '", "attributes":',
      compileAttributes(tokenId),
      "}"
    ));

    return string(abi.encodePacked(
      "data:application/json;base64,",
      base64(bytes(metadata))
    ));
  }

  /** BASE 64 - Written by Brech Devos */
  
  string internal constant TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

  function base64(bytes memory data) internal pure returns (string memory) {
    if (data.length == 0) return '';
    
    // load the table into memory
    string memory table = TABLE;

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

    // add some extra buffer at the end required for the writing
    string memory result = new string(encodedLen + 32);

    assembly {
      // set the actual output length
      mstore(result, encodedLen)
      
      // prepare the lookup table
      let tablePtr := add(table, 1)
      
      // input ptr
      let dataPtr := data
      let endPtr := add(dataPtr, mload(data))
      
      // result ptr, jump over length
      let resultPtr := add(result, 32)
      
      // run over the input, 3 bytes at a time
      for {} lt(dataPtr, endPtr) {}
      {
          dataPtr := add(dataPtr, 3)
          
          // read 3 bytes
          let input := mload(dataPtr)
          
          // write 4 characters
          mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
          resultPtr := add(resultPtr, 1)
          mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
          resultPtr := add(resultPtr, 1)
          mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F)))))
          resultPtr := add(resultPtr, 1)
          mstore(resultPtr, shl(248, mload(add(tablePtr, and(        input,  0x3F)))))
          resultPtr := add(resultPtr, 1)
      }
      
      // padding with '='
      switch mod(mload(data), 3)
      case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
      case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
    }
    
    return result;
  }
}

File 22 of 23: WOOL.sol
// SPDX-License-Identifier: MIT LICENSE

pragma solidity ^0.8.0;
import "./ERC20.sol";
import "./Ownable.sol";

contract WOOL is ERC20, Ownable {

  // a mapping from an address to whether or not it can mint / burn
  mapping(address => bool) controllers;
  
  constructor() ERC20("WOOL", "WOOL") { }

  /**
   * mints $WOOL to a recipient
   * @param to the recipient of the $WOOL
   * @param amount the amount of $WOOL to mint
   */
  function mint(address to, uint256 amount) external {
    require(controllers[msg.sender], "Only controllers can mint");
    _mint(to, amount);
  }

  /**
   * burns $WOOL from a holder
   * @param from the holder of the $WOOL
   * @param amount the amount of $WOOL to burn
   */
  function burn(address from, uint256 amount) external {
    require(controllers[msg.sender], "Only controllers can burn");
    _burn(from, amount);
  }

  /**
   * enables an address to mint / burn
   * @param controller the address to enable
   */
  function addController(address controller) external onlyOwner {
    controllers[controller] = true;
  }

  /**
   * disables an address from minting / burning
   * @param controller the address to disbale
   */
  function removeController(address controller) external onlyOwner {
    controllers[controller] = false;
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_wool","type":"address"},{"internalType":"address","name":"_traits","type":"address"},{"internalType":"uint256","name":"_maxTokens","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"MAX_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAID_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"aliases","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"barn","outputs":[{"internalType":"contract IBarn","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"existingCombinations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPaidTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTokenTraits","outputs":[{"components":[{"internalType":"bool","name":"isSheep","type":"bool"},{"internalType":"uint8","name":"fur","type":"uint8"},{"internalType":"uint8","name":"head","type":"uint8"},{"internalType":"uint8","name":"ears","type":"uint8"},{"internalType":"uint8","name":"eyes","type":"uint8"},{"internalType":"uint8","name":"nose","type":"uint8"},{"internalType":"uint8","name":"mouth","type":"uint8"},{"internalType":"uint8","name":"neck","type":"uint8"},{"internalType":"uint8","name":"feet","type":"uint8"},{"internalType":"uint8","name":"alphaIndex","type":"uint8"}],"internalType":"struct IWoolf.SheepWolf","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":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"stake","type":"bool"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minted","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","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":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"rarities","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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":"_barn","type":"address"}],"name":"setBarn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_paidTokens","type":"uint256"}],"name":"setPaidTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","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":"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":"","type":"uint256"}],"name":"tokenTraits","outputs":[{"internalType":"bool","name":"isSheep","type":"bool"},{"internalType":"uint8","name":"fur","type":"uint8"},{"internalType":"uint8","name":"head","type":"uint8"},{"internalType":"uint8","name":"ears","type":"uint8"},{"internalType":"uint8","name":"eyes","type":"uint8"},{"internalType":"uint8","name":"nose","type":"uint8"},{"internalType":"uint8","name":"mouth","type":"uint8"},{"internalType":"uint8","name":"neck","type":"uint8"},{"internalType":"uint8","name":"feet","type":"uint8"},{"internalType":"uint8","name":"alphaIndex","type":"uint8"}],"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":[],"name":"traits","outputs":[{"internalType":"contract ITraits","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wool","outputs":[{"internalType":"contract WOOL","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60a06040523480156200001157600080fd5b50604051620041cd380380620041cd833981016040819052620000349162001131565b6040805180820182526009815268576f6c662047616d6560b81b6020808301918252835180850190945260058452645747414d4560d81b908401528151919291620000829160009162000fcb565b5080516200009890600190602084019062000fcb565b505050620000b5620000af62000f7560201b60201c565b62000f79565b600a805460ff60a01b19169055603480546001600160a01b038086166001600160a01b031992831617909255603580549285169290911691909117905560808190526200010460058262001172565b600b556040805160a081018252600f8082526032602083015260c89282019290925260fa606082015260ff608082015262000142919060056200105a565b506040805160a0810182526004808252602082018190529181018290526060810182905260808101919091526200017e9060219060056200105a565b50604080516102808101825260be815260d7602082015260f0918101829052606460608201819052606e6080830152608760a08084019190915260c083015260b960e08301526050610100830181905260d261012084015260eb61014084015261016083019390935261018082018390526101a08201929092526101c081018290526101e0810182905261020081019190915260f561022082015260fa61024082015260ff610260820152620002399060109060146200105a565b5060408051610280810182526001815260026020820152600491810182905260006060820181905260056080830152600660a0830152600760c0830152600960e08301526101008201819052600a610120830152600b610140830152601161016083015261018082018190526101a082018190526101c082018190526101e0820152610200810191909152601261022082015260136102408201819052610260820152620002ec9060229060146200105a565b506040805160c08101825260ff8152601e6020820152603c918101829052606081019190915260966080820152609c60a0820152620003309060119060066200105a565b506040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152620003739060239060066200105a565b50604080516103808101825260dd81526064602082015260b591810191909152608c6060820181905260e060808301819052609360a080850191909152605460c0850181905260e4838601526101008501849052610120850183905260fa61014086015261016085019190915260f161018085015260cf6101a085015260ad6101c08501526101e084015260fe61020084015260dc61022084015260c4610240840152610260830182905260a861028084015260fc6102a084018190526102c084019290925260b76102e084015260ec61030084015261032083019190915261034082015260ff6103608201526200047090601290601c6200105a565b50604080516103808101825260018082526002602083015260059282018390526000606083015260808201819052600760a083015260c0820152600a60e08201819052610100820192909252610120810191909152600b6101408201819052600c610160830152600d6101808301819052600e6101a0840181905260106101c08501526101e084019290925260116102008401819052601761022085018190526102408501929092526102608401929092526102808301919091526102a082018190526102c082015260186102e0820152601b6103008201819052610320820181905261034082018190526103608201526200057190602490601c6200105a565b50604080516101408101825260af80825260646020830181905260289383019390935260fa60608301526073608083015260a082019290925260b960c082015260e081019190915260b461010082015260ff610120820152620005d990601390600a6200105a565b50604080516101408101825260038152600060208201526004918101919091526006606082018190526080820152600760a0820152600860c0820181905260e0820152600961010082018190526101208201526200063c90602590600a6200105a565b506040805161020081018252605080825260e1602083015260e38284015260e460608301526070608083015260f060a080840182905260c0840185905260e084015260a761010084015260d961012084015260ab610140840152610160830193909352610180820192909252607e6101a08201526101c081019190915260ff6101e0820152620006d19060149060106200105a565b50604080516102008101825260018152600260208201819052600392820192909252600860608201819052608082019290925260a0810182905260c0810191909152600960e08201819052610100820152600a6101208201819052600d61014083018190526101608301919091526101808201819052600f6101a083018190526101c08301919091526101e0820152620007709060269060106200105a565b50604080516020810190915260ff8152620007909060159060016200105a565b50604080516020810190915260008152620007b09060279060016200105a565b50604080516102608101825260f3815260bd6020820152608591810182905260608101829052603960808201819052605f60a0830152609860c0830152608760e0830152610100820192909252610120810182905260de61014082015260a861016082015261018081018290526101a081019190915260266101c082015260726101e08201819052610200820181905261022082015260ff6102408201526200085e9060169060136200105a565b50604080516102608101825260018082526007602083018190526000938301849052606083018490526080830184905260a0830184905260c08301849052600a60e084015261010083018490526101208301849052600b61014084018190526012610160850181905261018085018690526101a085018690526101c08501959095526101e08401929092526102008301526102208201526102408101919091526200090e9060289060136200105a565b50604080516020810190915260ff81526200092e9060179060016200105a565b506040805160208101909152600081526200094e9060299060016200105a565b50604080516101208101825260d28152605a602082015260099181018290526060810182905260808101829052609660a082015260c0810182905260ff60e08201526101008101829052620009a791601891906200105a565b5060408051610120810182526005808252600060208301819052928201929092526060810182905260808101829052600760a0820181905260c0820183905260e082015261010081019190915262000a0490602a9060096200105a565b50604080516020810190915260ff815262000a249060199060016200105a565b5060408051602081019091526000815262000a4490602b9060016200105a565b50604080516020810190915260ff815262000a6490601a9060016200105a565b5060408051602081019091526000815262000a8490602c9060016200105a565b506040805161036081018252608780825260b1602083015260db92820192909252608d606082015260b7608082015260e160a0820152609360c082015260bd60e082015260e761010082015261012081018290526101408101829052610160810182905261018081019190915260f66101a082015260966101c082018190526101e0820152609c61020082015260a561022082015260ab61024082015260b461026082015260ba61028082015260c36102a082015260c96102c082015260d26102e082015260f361030082015260fc61032082015260ff61034082015262000b7090601b90816200105a565b506040805161036081018252600181526002602082015260039181018290526004606082015260056080820152600660a08201819052600760c0830152600860e0830152600d610100830152610120820192909252610140810191909152600e610160820152600f61018082015260106101a082018190526101c082015260116101e08201526012610200820152601361022082015260146102408201526015610260820152601661028082015260176102a082015260186102c082015260196102e0820152601a6103008201819052610320820181905261034082015262000c5e90602d90601b6200105a565b50604080516020810190915260ff815262000c7e90601c9060016200105a565b5060408051602081019091526000815262000c9e90602e9060016200105a565b50604080516101a08101825260ef815260f4602082015260f99181019190915260ea606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820152608261014082015260ff61016082015260f761018082015262000d1990601d90600d6200105a565b50604080516101a0810182526001815260026020820152600b918101829052600060608201526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915262000d9490602f90600d6200105a565b50604080516101e081018252604b80825260b4602083015260a592820192909252607860608201819052603c6080830152609660a0830152606960c083015260c360e08301819052602d610100840181905260e16101208501526101408401949094526101608301939093526101808201929092526101a081019190915260ff6101c082015262000e2a90601e90600f6200105a565b50604080516101e08101825260018152600960208201526000918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052600c61012082018190526101408201839052610160820192909252600e61018082018190526101a08201929092526101c081019190915262000ebb90603090600f6200105a565b50604080516020810190915260ff815262000edb90601f9060016200105a565b5060408051602081019091526000815262000efb9060319060016200105a565b50604080516080810182526008815260a0602082015260499181019190915260ff6060820152600f601162000f359291019060046200105a565b506040805160808101825260028152600360208201819052918101829052606081019190915262000f6b9060329060046200105a565b50505050620011d2565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b82805462000fd99062001195565b90600052602060002090601f01602090048101928262000ffd576000855562001048565b82601f106200101857805160ff191683800117855562001048565b8280016001018555821562001048579182015b82811115620010485782518255916020019190600101906200102b565b5062001056929150620010fd565b5090565b82805482825590600052602060002090601f01602090048101928215620010485791602002820160005b83821115620010c457835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262001084565b8015620010f35782816101000a81549060ff0219169055600101602081600001049283019260010302620010c4565b5050620010569291505b5b80821115620010565760008155600101620010fe565b80516001600160a01b03811681146200112c57600080fd5b919050565b6000806000606084860312156200114757600080fd5b620011528462001114565b9250620011626020850162001114565b9150604084015190509250925092565b6000826200119057634e487b7160e01b600052601260045260246000fd5b500490565b600181811c90821680620011aa57607f821691505b60208210811415620011cc57634e487b7160e01b600052602260045260246000fd5b50919050565b608051612fca620012036000396000818161081501528181610b4d01528181610b9b0152610f6e0152612fca6000f3fe6080604052600436106102305760003560e01c80635c975abb1161012e578063a22cb465116100ab578063e05c57bf1161006f578063e05c57bf14610694578063e1fc334f1461077a578063e985e9c51461079a578063f2fde38b146107e3578063f47c84c51461080357600080fd5b8063a22cb46514610603578063b88d4fde14610623578063c002d23d14610643578063c084f5401461065e578063c87b56dd1461067457600080fd5b80638da5cb5b116100f25780638da5cb5b146105565780638fbb5fa71461057457806394e568471461059457806395d89b41146105c1578063a1b8f374146105d657600080fd5b80635c975abb146104cf5780636352211e146104ee57806367f68fac1461050e57806370a0823114610521578063715018a61461054157600080fd5b80632f745c59116101bc5780633ccfd60b116101805780633ccfd60b146104375780634018b1f81461044c57806342842e0e146104615780634f02c420146104815780634f6ccce7146104af57600080fd5b80632f745c591461038557806333df4b2c146103a55780633431a753146103d757806336838391146103f75780633b342a851461041757600080fd5b806316c38b3c1161020357806316c38b3c146102e657806318160ddd14610306578063194f480e1461032557806323b872dd1461034557806327de8f271461036557600080fd5b806301ffc9a71461023557806306fdde031461026a578063081812fc1461028c578063095ea7b3146102c4575b600080fd5b34801561024157600080fd5b5061025561025036600461299f565b610837565b60405190151581526020015b60405180910390f35b34801561027657600080fd5b5061027f610862565b6040516102619190612b71565b34801561029857600080fd5b506102ac6102a7366004612a50565b6108f4565b6040516001600160a01b039091168152602001610261565b3480156102d057600080fd5b506102e46102df366004612958565b61098e565b005b3480156102f257600080fd5b506102e4610301366004612984565b610aa4565b34801561031257600080fd5b506008545b604051908152602001610261565b34801561033157600080fd5b506033546102ac906001600160a01b031681565b34801561035157600080fd5b506102e4610360366004612833565b610ae7565b34801561037157600080fd5b50610317610380366004612a50565b610b33565b34801561039157600080fd5b506103176103a0366004612958565b610bf3565b3480156103b157600080fd5b506103c56103c0366004612a8c565b610c89565b60405160ff9091168152602001610261565b3480156103e357600080fd5b506102e46103f2366004612a50565b610ccf565b34801561040357600080fd5b506103c5610412366004612a8c565b610cfe565b34801561042357600080fd5b506102e46104323660046127c0565b610d0e565b34801561044357600080fd5b506102e4610d5a565b34801561045857600080fd5b50600b54610317565b34801561046d57600080fd5b506102e461047c366004612833565b610dbd565b34801561048d57600080fd5b50600c5461049c9061ffff1681565b60405161ffff9091168152602001610261565b3480156104bb57600080fd5b506103176104ca366004612a50565b610dd8565b3480156104db57600080fd5b50600a54600160a01b900460ff16610255565b3480156104fa57600080fd5b506102ac610509366004612a50565b610e6b565b6102e461051c366004612a69565b610ee2565b34801561052d57600080fd5b5061031761053c3660046127c0565b611378565b34801561054d57600080fd5b506102e46113ff565b34801561056257600080fd5b50600a546001600160a01b03166102ac565b34801561058057600080fd5b506034546102ac906001600160a01b031681565b3480156105a057600080fd5b506105b46105af366004612a50565b611435565b6040516102619190612c5c565b3480156105cd57600080fd5b5061027f6114ef565b3480156105e257600080fd5b506103176105f1366004612a50565b600e6020526000908152604090205481565b34801561060f57600080fd5b506102e461061e366004612923565b6114fe565b34801561062f57600080fd5b506102e461063e366004612874565b6115c3565b34801561064f57600080fd5b5061031766f6a11f484ec00081565b34801561066a57600080fd5b50610317600b5481565b34801561068057600080fd5b5061027f61068f366004612a50565b6115fb565b3480156106a057600080fd5b5061071f6106af366004612a50565b600d6020526000908152604090205460ff808216916101008104821691620100008204811691630100000081048216916401000000008204811691650100000000008104821691600160301b8204811691600160381b8104821691600160401b8204811691600160481b9004168a565b604080519a15158b5260ff998a1660208c0152978916978a01979097529487166060890152928616608088015290851660a0870152841660c0860152831660e085015282166101008401521661012082015261014001610261565b34801561078657600080fd5b506035546102ac906001600160a01b031681565b3480156107a657600080fd5b506102556107b53660046127fa565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b3480156107ef57600080fd5b506102e46107fe3660046127c0565b6116fa565b34801561080f57600080fd5b506103177f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b0319821663780e9d6360e01b148061085c575061085c82611792565b92915050565b60606000805461087190612e53565b80601f016020809104026020016040519081016040528092919081815260200182805461089d90612e53565b80156108ea5780601f106108bf576101008083540402835291602001916108ea565b820191906000526020600020905b8154815290600101906020018083116108cd57829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166109725760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061099982610e6b565b9050806001600160a01b0316836001600160a01b03161415610a075760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610969565b336001600160a01b0382161480610a235750610a2381336107b5565b610a955760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610969565b610a9f83836117e2565b505050565b600a546001600160a01b03163314610ace5760405162461bcd60e51b815260040161096990612bd6565b8015610adf57610adc611850565b50565b610adc6118f5565b6033546001600160a01b0316336001600160a01b031614610b2857610b0c3382611979565b610b285760405162461bcd60e51b815260040161096990612c0b565b610a9f838383611a70565b6000600b548211610b4657506000919050565b6005610b737f00000000000000000000000000000000000000000000000000000000000000006002612dca565b610b7d9190612db6565b8211610b94575069043c33c1937564800000919050565b6005610bc17f00000000000000000000000000000000000000000000000000000000000000006004612dca565b610bcb9190612db6565b8211610be25750690878678326eac9000000919050565b506910f0cf064dd592000000919050565b6000610bfe83611378565b8210610c605760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610969565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600f8260128110610c9957600080fd5b018181548110610ca857600080fd5b9060005260206000209060209182820401919006915091509054906101000a900460ff1681565b600a546001600160a01b03163314610cf95760405162461bcd60e51b815260040161096990612bd6565b600b55565b60218260128110610c9957600080fd5b600a546001600160a01b03163314610d385760405162461bcd60e51b815260040161096990612bd6565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b600a546001600160a01b03163314610d845760405162461bcd60e51b815260040161096990612bd6565b600a546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610adc573d6000803e3d6000fd5b610a9f838383604051806020016040528060008152506115c3565b6000610de360085490565b8210610e465760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610969565b60088281548110610e5957610e59612f3d565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b03168061085c5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610969565b600a54600160a01b900460ff1615610f2f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610969565b323314610f695760405162461bcd60e51b81526020600482015260086024820152674f6e6c7920454f4160c01b6044820152606401610969565b600c547f000000000000000000000000000000000000000000000000000000000000000090610f9d90849061ffff16612d79565b1115610fdf5760405162461bcd60e51b8152602060048201526011602482015270105b1b081d1bdad95b9cc81b5a5b9d1959607a1b6044820152606401610969565b600082118015610ff05750600a8211155b6110325760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152606401610969565b600b54600c5461ffff16101561110257600b54600c5461105790849061ffff16612d79565b11156110a55760405162461bcd60e51b815260206004820152601f60248201527f416c6c20746f6b656e73206f6e2d73616c6520616c726561647920736f6c64006044820152606401610969565b346110b766f6a11f484ec00084612dca565b146110fd5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081c185e5b595b9d08185b5bdd5b9d60521b6044820152606401610969565b61110d565b341561110d57600080fd5b600080826111295760408051600081526020810190915261116d565b8367ffffffffffffffff81111561114257611142612f53565b60405190808252806020026020018201604052801561116b578160200160208202803683370190505b505b90506000805b8581101561128e57600c805461ffff1690600061118f83612e88565b82546101009290920a61ffff818102199093169183160217909155600c546111b8925016611c1b565b600c549092506111cc9061ffff1683611c7a565b5060006111d883611e16565b90508515806111f057506001600160a01b0381163314155b1561120c57600c5461120790829061ffff16611ee2565b61125e565b603354600c54611229916001600160a01b03169061ffff16611ee2565b600c54845161ffff9091169085908490811061124757611247612f3d565b602002602001019061ffff16908161ffff16815250505b600c5461126e9061ffff16610b33565b6112789086612d79565b945050808061128690612eaa565b915050611173565b508215611308576034546001600160a01b0316639dc29fac336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101869052604401600060405180830381600087803b1580156112ef57600080fd5b505af1158015611303573d6000803e3d6000fd5b505050505b8315611371576033546001600160a01b03166381d449c133846040518363ffffffff1660e01b815260040161133e929190612b17565b600060405180830381600087803b15801561135857600080fd5b505af115801561136c573d6000803e3d6000fd5b505050505b5050505050565b60006001600160a01b0382166113e35760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610969565b506001600160a01b031660009081526003602052604090205490565b600a546001600160a01b031633146114295760405162461bcd60e51b815260040161096990612bd6565b6114336000611f00565b565b61143d612757565b506000908152600d6020908152604091829020825161014081018452905460ff808216151583526101008083048216948401949094526201000082048116948301949094526301000000810484166060830152640100000000810484166080830152650100000000008104841660a0830152600160301b8104841660c0830152600160381b8104841660e0830152600160401b8104841692820192909252600160481b90910490911661012082015290565b60606001805461087190612e53565b6001600160a01b0382163314156115575760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610969565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6115cd3383611979565b6115e95760405162461bcd60e51b815260040161096990612c0b565b6115f584848484611f52565b50505050565b6000818152600260205260409020546060906001600160a01b031661167a5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610969565b60355460405163c87b56dd60e01b8152600481018490526001600160a01b039091169063c87b56dd9060240160006040518083038186803b1580156116be57600080fd5b505afa1580156116d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261085c91908101906129d9565b600a546001600160a01b031633146117245760405162461bcd60e51b815260040161096990612bd6565b6001600160a01b0381166117895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610969565b610adc81611f00565b60006001600160e01b031982166380ac58cd60e01b14806117c357506001600160e01b03198216635b5e139f60e01b145b8061085c57506301ffc9a760e01b6001600160e01b031983161461085c565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061181782610e6b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600a54600160a01b900460ff161561189d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610969565b600a805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586118d83390565b6040516001600160a01b03909116815260200160405180910390a1565b600a54600160a01b900460ff166119455760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610969565b600a805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336118d8565b6000818152600260205260408120546001600160a01b03166119f25760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610969565b60006119fd83610e6b565b9050806001600160a01b0316846001600160a01b03161480611a385750836001600160a01b0316611a2d846108f4565b6001600160a01b0316145b80611a6857506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316611a8382610e6b565b6001600160a01b031614611aeb5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610969565b6001600160a01b038216611b4d5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610969565b611b58838383611f85565b611b636000826117e2565b6001600160a01b0383166000908152600360205260408120805460019290611b8c908490612de9565b90915550506001600160a01b0382166000908152600360205260408120805460019290611bba908490612d79565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600032611c29600143612de9565b60405160609290921b6bffffffffffffffffffffffff191660208301524060348201524260548201526074810183905260940160408051601f19818403018152919052805160209091012092915050565b611c82612757565b611c8b8261203d565b9050600e6000611c9a836121ab565b81526020019081526020016000205460001415611dfd576000838152600d602090815260408083208451815493860151928601516060870151608088015160a089015160c08a015160e08b0151610100808d01516101208e015161ffff19909c1698151561ff0019169890981760ff9a8b169091021763ffff0000191662010000968a169690960263ff0000001916959095176301000000948916949094029390931765ffff0000000019166401000000009288169290920265ff000000000019169190911765010000000000918716919091021767ffff0000000000001916600160301b9186169190910267ff00000000000000191617600160381b918516919091021769ffff00000000000000001916600160401b9184169190910269ff000000000000000000191617600160481b92909316919091029190911790558390600e90611de7846121ab565b815260208101919091526040016000205561085c565b611e0f83611e0a84611c1b565b611c7a565b9392505050565b600b54600c5460009161ffff909116111580611e3f5750611e3c600a60f584901c612ec5565b15155b15611e4a573361085c565b603354604051631e4c4f3560e11b8152609084901c60048201526000916001600160a01b031690633c989e6a9060240160206040518083038186803b158015611e9257600080fd5b505afa158015611ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eca91906127dd565b90506001600160a01b03811661085c57339392505050565b611efc82826040518060200160405280600081525061225d565b5050565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611f5d848484611a70565b611f6984848484612290565b6115f55760405162461bcd60e51b815260040161096990612b84565b6001600160a01b038316611fe057611fdb81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b612003565b816001600160a01b0316836001600160a01b03161461200357612003838261239d565b6001600160a01b03821661201a57610a9f8161243a565b826001600160a01b0316826001600160a01b031614610a9f57610a9f82826124e9565b612045612757565b612054600a61ffff8416612ec5565b151580825260009061206757600961206a565b60005b60109390931c92905061208b61ffff8416612086836000612d91565b61252d565b60ff16602083015260109290921c916120ad61ffff8416612086836001612d91565b60ff16604083015260109290921c916120cf61ffff8416612086836002612d91565b60ff16606083015260109290921c916120f161ffff8416612086836003612d91565b60ff16608083015260109290921c9161211361ffff8416612086836004612d91565b60ff1660a083015260109290921c9161213561ffff8416612086836005612d91565b60ff1660c083015260109290921c9161215761ffff8416612086836006612d91565b60ff1660e083015260109290921c9161217961ffff8416612086836007612d91565b60ff1661010083015260109290921c9161219c61ffff8416612086836008612d91565b60ff1661012083015250919050565b8051602080830151604080850151608086015160c087015160e088015160608901516101008a01516101208b0151965199151560f890811b998b01999099526001600160f81b031997891b881660218b015294881b871660228a015292871b8616602389015290861b85166024880152851b84166025870152841b83166026860152831b8216602785015290911b16602882015260009060290160405160208183030381529060405261085c90612e00565b6122678383612609565b6122746000848484612290565b610a9f5760405162461bcd60e51b815260040161096990612b84565b60006001600160a01b0384163b1561239257604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906122d4903390899088908890600401612ada565b602060405180830381600087803b1580156122ee57600080fd5b505af192505050801561231e575060408051601f3d908101601f1916820190925261231b918101906129bc565b60015b612378573d80801561234c576040519150601f19603f3d011682016040523d82523d6000602084013e612351565b606091505b5080516123705760405162461bcd60e51b815260040161096990612b84565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611a68565b506001949350505050565b600060016123aa84611378565b6123b49190612de9565b600083815260076020526040902054909150808214612407576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009061244c90600190612de9565b6000838152600960205260408120546008805493945090928490811061247457612474612f3d565b90600052602060002001549050806008838154811061249557612495612f3d565b60009182526020808320909101929092558281526009909152604080822084905585825281205560088054806124cd576124cd612f27565b6001900381819060005260206000200160009055905550505050565b60006124f483611378565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b600080600f8360ff166012811061254657612546612f3d565b01546125529085612ed9565b9050600f8360ff166012811061256a5761256a612f3d565b018160ff168154811061257f5761257f612f3d565b60009182526020918290209181049091015460ff601f9092166101000a90048116600886901c90911610156125b557905061085c565b60218360ff16601281106125cb576125cb612f3d565b018160ff16815481106125e0576125e0612f3d565b90600052602060002090602091828204019190069054906101000a900460ff1691505092915050565b6001600160a01b03821661265f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610969565b6000818152600260205260409020546001600160a01b0316156126c45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610969565b6126d060008383611f85565b6001600160a01b03821660009081526003602052604081208054600192906126f9908490612d79565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b803580151581146127bb57600080fd5b919050565b6000602082840312156127d257600080fd5b8135611e0f81612f69565b6000602082840312156127ef57600080fd5b8151611e0f81612f69565b6000806040838503121561280d57600080fd5b823561281881612f69565b9150602083013561282881612f69565b809150509250929050565b60008060006060848603121561284857600080fd5b833561285381612f69565b9250602084013561286381612f69565b929592945050506040919091013590565b6000806000806080858703121561288a57600080fd5b843561289581612f69565b935060208501356128a581612f69565b925060408501359150606085013567ffffffffffffffff8111156128c857600080fd5b8501601f810187136128d957600080fd5b80356128ec6128e782612d51565b612d20565b81815288602083850101111561290157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561293657600080fd5b823561294181612f69565b915061294f602084016127ab565b90509250929050565b6000806040838503121561296b57600080fd5b823561297681612f69565b946020939093013593505050565b60006020828403121561299657600080fd5b611e0f826127ab565b6000602082840312156129b157600080fd5b8135611e0f81612f7e565b6000602082840312156129ce57600080fd5b8151611e0f81612f7e565b6000602082840312156129eb57600080fd5b815167ffffffffffffffff811115612a0257600080fd5b8201601f81018413612a1357600080fd5b8051612a216128e782612d51565b818152856020838501011115612a3657600080fd5b612a47826020830160208601612e27565b95945050505050565b600060208284031215612a6257600080fd5b5035919050565b60008060408385031215612a7c57600080fd5b8235915061294f602084016127ab565b60008060408385031215612a9f57600080fd5b50508035926020909101359150565b60008151808452612ac6816020860160208601612e27565b601f01601f19169290920160200192915050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612b0d90830184612aae565b9695505050505050565b6001600160a01b038316815260406020808301829052835191830182905260009184820191906060850190845b81811015612b6457845161ffff1683529383019391830191600101612b44565b5090979650505050505050565b602081526000611e0f6020830184612aae565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b81511515815261014081016020830151612c7b602084018260ff169052565b506040830151612c90604084018260ff169052565b506060830151612ca5606084018260ff169052565b506080830151612cba608084018260ff169052565b5060a0830151612ccf60a084018260ff169052565b5060c0830151612ce460c084018260ff169052565b5060e0830151612cf960e084018260ff169052565b506101008381015160ff908116918401919091526101209384015116929091019190915290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4957612d49612f53565b604052919050565b600067ffffffffffffffff821115612d6b57612d6b612f53565b50601f01601f191660200190565b60008219821115612d8c57612d8c612efb565b500190565b600060ff821660ff84168060ff03821115612dae57612dae612efb565b019392505050565b600082612dc557612dc5612f11565b500490565b6000816000190483118215151615612de457612de4612efb565b500290565b600082821015612dfb57612dfb612efb565b500390565b80516020808301519190811015612e21576000198160200360031b1b821691505b50919050565b60005b83811015612e42578181015183820152602001612e2a565b838111156115f55750506000910152565b600181811c90821680612e6757607f821691505b60208210811415612e2157634e487b7160e01b600052602260045260246000fd5b600061ffff80831681811415612ea057612ea0612efb565b6001019392505050565b6000600019821415612ebe57612ebe612efb565b5060010190565b600082612ed457612ed4612f11565b500690565b600060ff831680612eec57612eec612f11565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610adc57600080fd5b6001600160e01b031981168114610adc57600080fdfea2646970667358221220b3ce39ee22297b56605e3c0e70deea10e6ad821b85ac6034a47b9b10f040ac0464736f6c634300080700330000000000000000000000008355dbe8b0e275abad27eb843f3eaf3fc855e525000000000000000000000000ae05b31e679a3b352d8493c09dcce739da5b2070000000000000000000000000000000000000000000000000000000000000c350

Deployed Bytecode

0x6080604052600436106102305760003560e01c80635c975abb1161012e578063a22cb465116100ab578063e05c57bf1161006f578063e05c57bf14610694578063e1fc334f1461077a578063e985e9c51461079a578063f2fde38b146107e3578063f47c84c51461080357600080fd5b8063a22cb46514610603578063b88d4fde14610623578063c002d23d14610643578063c084f5401461065e578063c87b56dd1461067457600080fd5b80638da5cb5b116100f25780638da5cb5b146105565780638fbb5fa71461057457806394e568471461059457806395d89b41146105c1578063a1b8f374146105d657600080fd5b80635c975abb146104cf5780636352211e146104ee57806367f68fac1461050e57806370a0823114610521578063715018a61461054157600080fd5b80632f745c59116101bc5780633ccfd60b116101805780633ccfd60b146104375780634018b1f81461044c57806342842e0e146104615780634f02c420146104815780634f6ccce7146104af57600080fd5b80632f745c591461038557806333df4b2c146103a55780633431a753146103d757806336838391146103f75780633b342a851461041757600080fd5b806316c38b3c1161020357806316c38b3c146102e657806318160ddd14610306578063194f480e1461032557806323b872dd1461034557806327de8f271461036557600080fd5b806301ffc9a71461023557806306fdde031461026a578063081812fc1461028c578063095ea7b3146102c4575b600080fd5b34801561024157600080fd5b5061025561025036600461299f565b610837565b60405190151581526020015b60405180910390f35b34801561027657600080fd5b5061027f610862565b6040516102619190612b71565b34801561029857600080fd5b506102ac6102a7366004612a50565b6108f4565b6040516001600160a01b039091168152602001610261565b3480156102d057600080fd5b506102e46102df366004612958565b61098e565b005b3480156102f257600080fd5b506102e4610301366004612984565b610aa4565b34801561031257600080fd5b506008545b604051908152602001610261565b34801561033157600080fd5b506033546102ac906001600160a01b031681565b34801561035157600080fd5b506102e4610360366004612833565b610ae7565b34801561037157600080fd5b50610317610380366004612a50565b610b33565b34801561039157600080fd5b506103176103a0366004612958565b610bf3565b3480156103b157600080fd5b506103c56103c0366004612a8c565b610c89565b60405160ff9091168152602001610261565b3480156103e357600080fd5b506102e46103f2366004612a50565b610ccf565b34801561040357600080fd5b506103c5610412366004612a8c565b610cfe565b34801561042357600080fd5b506102e46104323660046127c0565b610d0e565b34801561044357600080fd5b506102e4610d5a565b34801561045857600080fd5b50600b54610317565b34801561046d57600080fd5b506102e461047c366004612833565b610dbd565b34801561048d57600080fd5b50600c5461049c9061ffff1681565b60405161ffff9091168152602001610261565b3480156104bb57600080fd5b506103176104ca366004612a50565b610dd8565b3480156104db57600080fd5b50600a54600160a01b900460ff16610255565b3480156104fa57600080fd5b506102ac610509366004612a50565b610e6b565b6102e461051c366004612a69565b610ee2565b34801561052d57600080fd5b5061031761053c3660046127c0565b611378565b34801561054d57600080fd5b506102e46113ff565b34801561056257600080fd5b50600a546001600160a01b03166102ac565b34801561058057600080fd5b506034546102ac906001600160a01b031681565b3480156105a057600080fd5b506105b46105af366004612a50565b611435565b6040516102619190612c5c565b3480156105cd57600080fd5b5061027f6114ef565b3480156105e257600080fd5b506103176105f1366004612a50565b600e6020526000908152604090205481565b34801561060f57600080fd5b506102e461061e366004612923565b6114fe565b34801561062f57600080fd5b506102e461063e366004612874565b6115c3565b34801561064f57600080fd5b5061031766f6a11f484ec00081565b34801561066a57600080fd5b50610317600b5481565b34801561068057600080fd5b5061027f61068f366004612a50565b6115fb565b3480156106a057600080fd5b5061071f6106af366004612a50565b600d6020526000908152604090205460ff808216916101008104821691620100008204811691630100000081048216916401000000008204811691650100000000008104821691600160301b8204811691600160381b8104821691600160401b8204811691600160481b9004168a565b604080519a15158b5260ff998a1660208c0152978916978a01979097529487166060890152928616608088015290851660a0870152841660c0860152831660e085015282166101008401521661012082015261014001610261565b34801561078657600080fd5b506035546102ac906001600160a01b031681565b3480156107a657600080fd5b506102556107b53660046127fa565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b3480156107ef57600080fd5b506102e46107fe3660046127c0565b6116fa565b34801561080f57600080fd5b506103177f000000000000000000000000000000000000000000000000000000000000c35081565b60006001600160e01b0319821663780e9d6360e01b148061085c575061085c82611792565b92915050565b60606000805461087190612e53565b80601f016020809104026020016040519081016040528092919081815260200182805461089d90612e53565b80156108ea5780601f106108bf576101008083540402835291602001916108ea565b820191906000526020600020905b8154815290600101906020018083116108cd57829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166109725760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061099982610e6b565b9050806001600160a01b0316836001600160a01b03161415610a075760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610969565b336001600160a01b0382161480610a235750610a2381336107b5565b610a955760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610969565b610a9f83836117e2565b505050565b600a546001600160a01b03163314610ace5760405162461bcd60e51b815260040161096990612bd6565b8015610adf57610adc611850565b50565b610adc6118f5565b6033546001600160a01b0316336001600160a01b031614610b2857610b0c3382611979565b610b285760405162461bcd60e51b815260040161096990612c0b565b610a9f838383611a70565b6000600b548211610b4657506000919050565b6005610b737f000000000000000000000000000000000000000000000000000000000000c3506002612dca565b610b7d9190612db6565b8211610b94575069043c33c1937564800000919050565b6005610bc17f000000000000000000000000000000000000000000000000000000000000c3506004612dca565b610bcb9190612db6565b8211610be25750690878678326eac9000000919050565b506910f0cf064dd592000000919050565b6000610bfe83611378565b8210610c605760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610969565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600f8260128110610c9957600080fd5b018181548110610ca857600080fd5b9060005260206000209060209182820401919006915091509054906101000a900460ff1681565b600a546001600160a01b03163314610cf95760405162461bcd60e51b815260040161096990612bd6565b600b55565b60218260128110610c9957600080fd5b600a546001600160a01b03163314610d385760405162461bcd60e51b815260040161096990612bd6565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b600a546001600160a01b03163314610d845760405162461bcd60e51b815260040161096990612bd6565b600a546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610adc573d6000803e3d6000fd5b610a9f838383604051806020016040528060008152506115c3565b6000610de360085490565b8210610e465760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610969565b60088281548110610e5957610e59612f3d565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b03168061085c5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610969565b600a54600160a01b900460ff1615610f2f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610969565b323314610f695760405162461bcd60e51b81526020600482015260086024820152674f6e6c7920454f4160c01b6044820152606401610969565b600c547f000000000000000000000000000000000000000000000000000000000000c35090610f9d90849061ffff16612d79565b1115610fdf5760405162461bcd60e51b8152602060048201526011602482015270105b1b081d1bdad95b9cc81b5a5b9d1959607a1b6044820152606401610969565b600082118015610ff05750600a8211155b6110325760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152606401610969565b600b54600c5461ffff16101561110257600b54600c5461105790849061ffff16612d79565b11156110a55760405162461bcd60e51b815260206004820152601f60248201527f416c6c20746f6b656e73206f6e2d73616c6520616c726561647920736f6c64006044820152606401610969565b346110b766f6a11f484ec00084612dca565b146110fd5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081c185e5b595b9d08185b5bdd5b9d60521b6044820152606401610969565b61110d565b341561110d57600080fd5b600080826111295760408051600081526020810190915261116d565b8367ffffffffffffffff81111561114257611142612f53565b60405190808252806020026020018201604052801561116b578160200160208202803683370190505b505b90506000805b8581101561128e57600c805461ffff1690600061118f83612e88565b82546101009290920a61ffff818102199093169183160217909155600c546111b8925016611c1b565b600c549092506111cc9061ffff1683611c7a565b5060006111d883611e16565b90508515806111f057506001600160a01b0381163314155b1561120c57600c5461120790829061ffff16611ee2565b61125e565b603354600c54611229916001600160a01b03169061ffff16611ee2565b600c54845161ffff9091169085908490811061124757611247612f3d565b602002602001019061ffff16908161ffff16815250505b600c5461126e9061ffff16610b33565b6112789086612d79565b945050808061128690612eaa565b915050611173565b508215611308576034546001600160a01b0316639dc29fac336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101869052604401600060405180830381600087803b1580156112ef57600080fd5b505af1158015611303573d6000803e3d6000fd5b505050505b8315611371576033546001600160a01b03166381d449c133846040518363ffffffff1660e01b815260040161133e929190612b17565b600060405180830381600087803b15801561135857600080fd5b505af115801561136c573d6000803e3d6000fd5b505050505b5050505050565b60006001600160a01b0382166113e35760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610969565b506001600160a01b031660009081526003602052604090205490565b600a546001600160a01b031633146114295760405162461bcd60e51b815260040161096990612bd6565b6114336000611f00565b565b61143d612757565b506000908152600d6020908152604091829020825161014081018452905460ff808216151583526101008083048216948401949094526201000082048116948301949094526301000000810484166060830152640100000000810484166080830152650100000000008104841660a0830152600160301b8104841660c0830152600160381b8104841660e0830152600160401b8104841692820192909252600160481b90910490911661012082015290565b60606001805461087190612e53565b6001600160a01b0382163314156115575760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610969565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6115cd3383611979565b6115e95760405162461bcd60e51b815260040161096990612c0b565b6115f584848484611f52565b50505050565b6000818152600260205260409020546060906001600160a01b031661167a5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610969565b60355460405163c87b56dd60e01b8152600481018490526001600160a01b039091169063c87b56dd9060240160006040518083038186803b1580156116be57600080fd5b505afa1580156116d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261085c91908101906129d9565b600a546001600160a01b031633146117245760405162461bcd60e51b815260040161096990612bd6565b6001600160a01b0381166117895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610969565b610adc81611f00565b60006001600160e01b031982166380ac58cd60e01b14806117c357506001600160e01b03198216635b5e139f60e01b145b8061085c57506301ffc9a760e01b6001600160e01b031983161461085c565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061181782610e6b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600a54600160a01b900460ff161561189d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610969565b600a805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586118d83390565b6040516001600160a01b03909116815260200160405180910390a1565b600a54600160a01b900460ff166119455760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610969565b600a805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336118d8565b6000818152600260205260408120546001600160a01b03166119f25760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610969565b60006119fd83610e6b565b9050806001600160a01b0316846001600160a01b03161480611a385750836001600160a01b0316611a2d846108f4565b6001600160a01b0316145b80611a6857506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316611a8382610e6b565b6001600160a01b031614611aeb5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610969565b6001600160a01b038216611b4d5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610969565b611b58838383611f85565b611b636000826117e2565b6001600160a01b0383166000908152600360205260408120805460019290611b8c908490612de9565b90915550506001600160a01b0382166000908152600360205260408120805460019290611bba908490612d79565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600032611c29600143612de9565b60405160609290921b6bffffffffffffffffffffffff191660208301524060348201524260548201526074810183905260940160408051601f19818403018152919052805160209091012092915050565b611c82612757565b611c8b8261203d565b9050600e6000611c9a836121ab565b81526020019081526020016000205460001415611dfd576000838152600d602090815260408083208451815493860151928601516060870151608088015160a089015160c08a015160e08b0151610100808d01516101208e015161ffff19909c1698151561ff0019169890981760ff9a8b169091021763ffff0000191662010000968a169690960263ff0000001916959095176301000000948916949094029390931765ffff0000000019166401000000009288169290920265ff000000000019169190911765010000000000918716919091021767ffff0000000000001916600160301b9186169190910267ff00000000000000191617600160381b918516919091021769ffff00000000000000001916600160401b9184169190910269ff000000000000000000191617600160481b92909316919091029190911790558390600e90611de7846121ab565b815260208101919091526040016000205561085c565b611e0f83611e0a84611c1b565b611c7a565b9392505050565b600b54600c5460009161ffff909116111580611e3f5750611e3c600a60f584901c612ec5565b15155b15611e4a573361085c565b603354604051631e4c4f3560e11b8152609084901c60048201526000916001600160a01b031690633c989e6a9060240160206040518083038186803b158015611e9257600080fd5b505afa158015611ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eca91906127dd565b90506001600160a01b03811661085c57339392505050565b611efc82826040518060200160405280600081525061225d565b5050565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611f5d848484611a70565b611f6984848484612290565b6115f55760405162461bcd60e51b815260040161096990612b84565b6001600160a01b038316611fe057611fdb81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b612003565b816001600160a01b0316836001600160a01b03161461200357612003838261239d565b6001600160a01b03821661201a57610a9f8161243a565b826001600160a01b0316826001600160a01b031614610a9f57610a9f82826124e9565b612045612757565b612054600a61ffff8416612ec5565b151580825260009061206757600961206a565b60005b60109390931c92905061208b61ffff8416612086836000612d91565b61252d565b60ff16602083015260109290921c916120ad61ffff8416612086836001612d91565b60ff16604083015260109290921c916120cf61ffff8416612086836002612d91565b60ff16606083015260109290921c916120f161ffff8416612086836003612d91565b60ff16608083015260109290921c9161211361ffff8416612086836004612d91565b60ff1660a083015260109290921c9161213561ffff8416612086836005612d91565b60ff1660c083015260109290921c9161215761ffff8416612086836006612d91565b60ff1660e083015260109290921c9161217961ffff8416612086836007612d91565b60ff1661010083015260109290921c9161219c61ffff8416612086836008612d91565b60ff1661012083015250919050565b8051602080830151604080850151608086015160c087015160e088015160608901516101008a01516101208b0151965199151560f890811b998b01999099526001600160f81b031997891b881660218b015294881b871660228a015292871b8616602389015290861b85166024880152851b84166025870152841b83166026860152831b8216602785015290911b16602882015260009060290160405160208183030381529060405261085c90612e00565b6122678383612609565b6122746000848484612290565b610a9f5760405162461bcd60e51b815260040161096990612b84565b60006001600160a01b0384163b1561239257604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906122d4903390899088908890600401612ada565b602060405180830381600087803b1580156122ee57600080fd5b505af192505050801561231e575060408051601f3d908101601f1916820190925261231b918101906129bc565b60015b612378573d80801561234c576040519150601f19603f3d011682016040523d82523d6000602084013e612351565b606091505b5080516123705760405162461bcd60e51b815260040161096990612b84565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611a68565b506001949350505050565b600060016123aa84611378565b6123b49190612de9565b600083815260076020526040902054909150808214612407576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009061244c90600190612de9565b6000838152600960205260408120546008805493945090928490811061247457612474612f3d565b90600052602060002001549050806008838154811061249557612495612f3d565b60009182526020808320909101929092558281526009909152604080822084905585825281205560088054806124cd576124cd612f27565b6001900381819060005260206000200160009055905550505050565b60006124f483611378565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b600080600f8360ff166012811061254657612546612f3d565b01546125529085612ed9565b9050600f8360ff166012811061256a5761256a612f3d565b018160ff168154811061257f5761257f612f3d565b60009182526020918290209181049091015460ff601f9092166101000a90048116600886901c90911610156125b557905061085c565b60218360ff16601281106125cb576125cb612f3d565b018160ff16815481106125e0576125e0612f3d565b90600052602060002090602091828204019190069054906101000a900460ff1691505092915050565b6001600160a01b03821661265f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610969565b6000818152600260205260409020546001600160a01b0316156126c45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610969565b6126d060008383611f85565b6001600160a01b03821660009081526003602052604081208054600192906126f9908490612d79565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b803580151581146127bb57600080fd5b919050565b6000602082840312156127d257600080fd5b8135611e0f81612f69565b6000602082840312156127ef57600080fd5b8151611e0f81612f69565b6000806040838503121561280d57600080fd5b823561281881612f69565b9150602083013561282881612f69565b809150509250929050565b60008060006060848603121561284857600080fd5b833561285381612f69565b9250602084013561286381612f69565b929592945050506040919091013590565b6000806000806080858703121561288a57600080fd5b843561289581612f69565b935060208501356128a581612f69565b925060408501359150606085013567ffffffffffffffff8111156128c857600080fd5b8501601f810187136128d957600080fd5b80356128ec6128e782612d51565b612d20565b81815288602083850101111561290157600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561293657600080fd5b823561294181612f69565b915061294f602084016127ab565b90509250929050565b6000806040838503121561296b57600080fd5b823561297681612f69565b946020939093013593505050565b60006020828403121561299657600080fd5b611e0f826127ab565b6000602082840312156129b157600080fd5b8135611e0f81612f7e565b6000602082840312156129ce57600080fd5b8151611e0f81612f7e565b6000602082840312156129eb57600080fd5b815167ffffffffffffffff811115612a0257600080fd5b8201601f81018413612a1357600080fd5b8051612a216128e782612d51565b818152856020838501011115612a3657600080fd5b612a47826020830160208601612e27565b95945050505050565b600060208284031215612a6257600080fd5b5035919050565b60008060408385031215612a7c57600080fd5b8235915061294f602084016127ab565b60008060408385031215612a9f57600080fd5b50508035926020909101359150565b60008151808452612ac6816020860160208601612e27565b601f01601f19169290920160200192915050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612b0d90830184612aae565b9695505050505050565b6001600160a01b038316815260406020808301829052835191830182905260009184820191906060850190845b81811015612b6457845161ffff1683529383019391830191600101612b44565b5090979650505050505050565b602081526000611e0f6020830184612aae565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b81511515815261014081016020830151612c7b602084018260ff169052565b506040830151612c90604084018260ff169052565b506060830151612ca5606084018260ff169052565b506080830151612cba608084018260ff169052565b5060a0830151612ccf60a084018260ff169052565b5060c0830151612ce460c084018260ff169052565b5060e0830151612cf960e084018260ff169052565b506101008381015160ff908116918401919091526101209384015116929091019190915290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612d4957612d49612f53565b604052919050565b600067ffffffffffffffff821115612d6b57612d6b612f53565b50601f01601f191660200190565b60008219821115612d8c57612d8c612efb565b500190565b600060ff821660ff84168060ff03821115612dae57612dae612efb565b019392505050565b600082612dc557612dc5612f11565b500490565b6000816000190483118215151615612de457612de4612efb565b500290565b600082821015612dfb57612dfb612efb565b500390565b80516020808301519190811015612e21576000198160200360031b1b821691505b50919050565b60005b83811015612e42578181015183820152602001612e2a565b838111156115f55750506000910152565b600181811c90821680612e6757607f821691505b60208210811415612e2157634e487b7160e01b600052602260045260246000fd5b600061ffff80831681811415612ea057612ea0612efb565b6001019392505050565b6000600019821415612ebe57612ebe612efb565b5060010190565b600082612ed457612ed4612f11565b500690565b600060ff831680612eec57612eec612f11565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610adc57600080fd5b6001600160e01b031981168114610adc57600080fdfea2646970667358221220b3ce39ee22297b56605e3c0e70deea10e6ad821b85ac6034a47b9b10f040ac0464736f6c63430008070033

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

0000000000000000000000008355dbe8b0e275abad27eb843f3eaf3fc855e525000000000000000000000000ae05b31e679a3b352d8493c09dcce739da5b2070000000000000000000000000000000000000000000000000000000000000c350

-----Decoded View---------------
Arg [0] : _wool (address): 0x8355DBE8B0e275ABAd27eB843F3eaF3FC855e525
Arg [1] : _traits (address): 0xae05B31E679a3b352d8493C09DCcE739DA5B2070
Arg [2] : _maxTokens (uint256): 50000

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000008355dbe8b0e275abad27eb843f3eaf3fc855e525
Arg [1] : 000000000000000000000000ae05b31e679a3b352d8493c09dcce739da5b2070
Arg [2] : 000000000000000000000000000000000000000000000000000000000000c350


Deployed Bytecode Sourcemap

239:11289:22:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;909:222:6;;;;;;;;;;-1:-1:-1;909:222:6;;;;;:::i;:::-;;:::i;:::-;;;8975:14:23;;8968:22;8950:41;;8938:2;8923:18;909:222:6;;;;;;;;2349:98:5;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;3860:217::-;;;;;;;;;;-1:-1:-1;3860:217:5;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;7249:32:23;;;7231:51;;7219:2;7204:18;3860:217:5;7085:203:23;3398:401:5;;;;;;;;;;-1:-1:-1;3398:401:5;;;;;:::i;:::-;;:::i;:::-;;11196:105:22;;;;;;;;;;-1:-1:-1;11196:105:22;;;;;:::i;:::-;;:::i;1534:111:6:-;;;;;;;;;;-1:-1:-1;1621:10:6;:17;1534:111;;;22214:25:23;;;22202:2;22187:18;1534:111:6;22068:177:23;1316:17:22;;;;;;;;;;-1:-1:-1;1316:17:22;;;;-1:-1:-1;;;;;1316:17:22;;;6083:378;;;;;;;;;;-1:-1:-1;6083:378:22;;;;;:::i;:::-;;:::i;5825:254::-;;;;;;;;;;-1:-1:-1;5825:254:22;;;;;:::i;:::-;;:::i;1210:253:6:-;;;;;;;;;;-1:-1:-1;1210:253:6;;;;;:::i;:::-;;:::i;1071:27:22:-;;;;;;;;;;-1:-1:-1;1071:27:22;;;;;:::i;:::-;;:::i;:::-;;;22422:4:23;22410:17;;;22392:36;;22380:2;22365:18;1071:27:22;22250:184:23;11035:99:22;;;;;;;;;;-1:-1:-1;11035:99:22;;;;;:::i;:::-;;:::i;1225:26::-;;;;;;;;;;-1:-1:-1;1225:26:22;;;;;:::i;:::-;;:::i;10732:81::-;;;;;;;;;;-1:-1:-1;10732:81:22;;;;;:::i;:::-;;:::i;10878:98::-;;;;;;;;;;;;;:::i;10485:95::-;;;;;;;;;;-1:-1:-1;10564:11:22;;10485:95;;5120:179:5;;;;;;;;;;-1:-1:-1;5120:179:5;;;;;:::i;:::-;;:::i;629:20:22:-;;;;;;;;;;-1:-1:-1;629:20:22;;;;;;;;;;;22049:6:23;22037:19;;;22019:38;;22007:2;21992:18;629:20:22;21875:188:23;1717:230:6;;;;;;;;;;-1:-1:-1;1717:230:6;;;;;:::i;:::-;;:::i;1034:84:18:-;;;;;;;;;;-1:-1:-1;1104:7:18;;-1:-1:-1;;;1104:7:18;;;;1034:84;;2052:235:5;;;;;;;;;;-1:-1:-1;2052:235:5;;;;;:::i;:::-;;:::i;4412:1158:22:-;;;;;;:::i;:::-;;:::i;1790:205:5:-;;;;;;;;;;-1:-1:-1;1790:205:5;;;;;:::i;:::-;;:::i;1598:92:17:-;;;;;;;;;;;;;:::i;966:85::-;;;;;;;;;;-1:-1:-1;1038:6:17;;-1:-1:-1;;;;;1038:6:17;966:85;;1381:16:22;;;;;;;;;;-1:-1:-1;1381:16:22;;;;-1:-1:-1;;;;;1381:16:22;;;10352:129;;;;;;;;;;-1:-1:-1;10352:129:22;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2511:102:5:-;;;;;;;;;;;;;:::i;891:55:22:-;;;;;;;;;;-1:-1:-1;891:55:22;;;;;:::i;:::-;;;;;;;;;;;;;;4144:290:5;;;;;;;;;;-1:-1:-1;4144:290:5;;;;;:::i;:::-;;:::i;5365:320::-;;;;;;;;;;-1:-1:-1;5365:320:5;;;;;:::i;:::-;;:::i;322:50:22:-;;;;;;;;;;;;359:13;322:50;;553:26;;;;;;;;;;;;;;;;11322:204;;;;;;;;;;-1:-1:-1;11322:204:22;;;;;:::i;:::-;;:::i;722:48::-;;;;;;;;;;-1:-1:-1;722:48:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;722:48:22;;;;;-1:-1:-1;;;722:48:22;;;;;-1:-1:-1;;;722:48:22;;;;;-1:-1:-1;;;722:48:22;;;;;;;;;9384:14:23;;9377:22;9359:41;;9419:4;9459:15;;;9454:2;9439:18;;9432:43;9511:15;;;9491:18;;;9484:43;;;;9563:15;;;9558:2;9543:18;;9536:43;9616:15;;;9610:3;9595:19;;9588:44;9669:15;;;9663:3;9648:19;;9641:44;9722:15;;9716:3;9701:19;;9694:44;9775:15;;9769:3;9754:19;;9747:44;9828:15;;9822:3;9807:19;;9800:44;9881:15;9875:3;9860:19;;9853:44;9346:3;9331:19;722:48:22;9002:901:23;1426:21:22;;;;;;;;;;-1:-1:-1;1426:21:22;;;;-1:-1:-1;;;;;1426:21:22;;;4500:162:5;;;;;;;;;;-1:-1:-1;4500:162:5;;;;;:::i;:::-;-1:-1:-1;;;;;4620:25:5;;;4597:4;4620:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;4500:162;1839:189:17;;;;;;;;;;-1:-1:-1;1839:189:17;;;;;:::i;:::-;;:::i;443:35:22:-;;;;;;;;;;;;;;;909:222:6;1011:4;-1:-1:-1;;;;;;1034:50:6;;-1:-1:-1;;;1034:50:6;;:90;;;1088:36;1112:11;1088:23;:36::i;:::-;1027:97;909:222;-1:-1:-1;;909:222:6:o;2349:98:5:-;2403:13;2435:5;2428:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2349:98;:::o;3860:217::-;3936:7;7245:16;;;:7;:16;;;;;;-1:-1:-1;;;;;7245:16:5;3955:73;;;;-1:-1:-1;;;3955:73:5;;17462:2:23;3955:73:5;;;17444:21:23;17501:2;17481:18;;;17474:30;17540:34;17520:18;;;17513:62;-1:-1:-1;;;17591:18:23;;;17584:42;17643:19;;3955:73:5;;;;;;;;;-1:-1:-1;4046:24:5;;;;:15;:24;;;;;;-1:-1:-1;;;;;4046:24:5;;3860:217::o;3398:401::-;3478:13;3494:23;3509:7;3494:14;:23::i;:::-;3478:39;;3541:5;-1:-1:-1;;;;;3535:11:5;:2;-1:-1:-1;;;;;3535:11:5;;;3527:57;;;;-1:-1:-1;;;3527:57:5;;19062:2:23;3527:57:5;;;19044:21:23;19101:2;19081:18;;;19074:30;19140:34;19120:18;;;19113:62;-1:-1:-1;;;19191:18:23;;;19184:31;19232:19;;3527:57:5;18860:397:23;3527:57:5;666:10:2;-1:-1:-1;;;;;3616:21:5;;;;:62;;-1:-1:-1;3641:37:5;3658:5;666:10:2;4500:162:5;:::i;3641:37::-;3595:165;;;;-1:-1:-1;;;3595:165:5;;15855:2:23;3595:165:5;;;15837:21:23;15894:2;15874:18;;;15867:30;15933:34;15913:18;;;15906:62;16004:26;15984:18;;;15977:54;16048:19;;3595:165:5;15653:420:23;3595:165:5;3771:21;3780:2;3784:7;3771:8;:21::i;:::-;3468:331;3398:401;;:::o;11196:105:22:-;1038:6:17;;-1:-1:-1;;;;;1038:6:17;666:10:2;1178:23:17;1170:68;;;;-1:-1:-1;;;1170:68:17;;;;;;;:::i;:::-;11258:7:22::1;11254:42;;;11267:8;:6;:8::i;:::-;11196:105:::0;:::o;11254:42::-:1;11286:10;:8;:10::i;6083:378::-:0;6306:4;;-1:-1:-1;;;;;6306:4:22;666:10:2;-1:-1:-1;;;;;6282:29:22;;6278:144;;6327:41;666:10:2;6360:7:22;6327:18;:41::i;:::-;6319:103;;;;-1:-1:-1;;;6319:103:22;;;;;;;:::i;:::-;6428:28;6438:4;6444:2;6448:7;6428:9;:28::i;5825:254::-;5881:7;5911:11;;5900:7;:22;5896:36;;-1:-1:-1;5931:1:22;;5825:254;-1:-1:-1;5825:254:22:o;5896:36::-;5970:1;5953:14;:10;5966:1;5953:14;:::i;:::-;:18;;;;:::i;:::-;5942:7;:29;5938:53;;-1:-1:-1;5980:11:22;;5825:254;-1:-1:-1;5825:254:22:o;5938:53::-;6029:1;6012:14;:10;6025:1;6012:14;:::i;:::-;:18;;;;:::i;:::-;6001:7;:29;5997:53;;-1:-1:-1;6039:11:22;;5825:254;-1:-1:-1;5825:254:22:o;5997:53::-;-1:-1:-1;6063:11:22;;5825:254;-1:-1:-1;5825:254:22:o;1210:253:6:-;1307:7;1342:23;1359:5;1342:16;:23::i;:::-;1334:5;:31;1326:87;;;;-1:-1:-1;;;1326:87:6;;11350:2:23;1326:87:6;;;11332:21:23;11389:2;11369:18;;;11362:30;11428:34;11408:18;;;11401:62;-1:-1:-1;;;11479:18:23;;;11472:41;11530:19;;1326:87:6;11148:407:23;1326:87:6;-1:-1:-1;;;;;;1430:19:6;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;1210:253::o;1071:27:22:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;11035:99::-;1038:6:17;;-1:-1:-1;;;;;1038:6:17;666:10:2;1178:23:17;1170:68;;;;-1:-1:-1;;;1170:68:17;;;;;;;:::i;:::-;11104:11:22::1;:25:::0;11035:99::o;1225:26::-;;;;;;;;;;;10732:81;1038:6:17;;-1:-1:-1;;;;;1038:6:17;666:10:2;1178:23:17;1170:68;;;;-1:-1:-1;;;1170:68:17;;;;;;;:::i;:::-;10789:4:22::1;:19:::0;;-1:-1:-1;;;;;;10789:19:22::1;-1:-1:-1::0;;;;;10789:19:22;;;::::1;::::0;;;::::1;::::0;;10732:81::o;10878:98::-;1038:6:17;;-1:-1:-1;;;;;1038:6:17;666:10:2;1178:23:17;1170:68;;;;-1:-1:-1;;;1170:68:17;;;;;;;:::i;:::-;1038:6;;10923:48:22::1;::::0;-1:-1:-1;;;;;1038:6:17;;;;10949:21:22::1;10923:48:::0;::::1;;;::::0;::::1;::::0;;;10949:21;1038:6:17;10923:48:22;::::1;;;;;;;;;;;;;::::0;::::1;;;;5120:179:5::0;5253:39;5270:4;5276:2;5280:7;5253:39;;;;;;;;;;;;:16;:39::i;1717:230:6:-;1792:7;1827:30;1621:10;:17;;1534:111;1827:30;1819:5;:38;1811:95;;;;-1:-1:-1;;;1811:95:6;;20230:2:23;1811:95:6;;;20212:21:23;20269:2;20249:18;;;20242:30;20308:34;20288:18;;;20281:62;-1:-1:-1;;;20359:18:23;;;20352:42;20411:19;;1811:95:6;20028:408:23;1811:95:6;1923:10;1934:5;1923:17;;;;;;;;:::i;:::-;;;;;;;;;1916:24;;1717:230;;;:::o;2052:235:5:-;2124:7;2159:16;;;:7;:16;;;;;;-1:-1:-1;;;;;2159:16:5;2193:19;2185:73;;;;-1:-1:-1;;;2185:73:5;;16691:2:23;2185:73:5;;;16673:21:23;16730:2;16710:18;;;16703:30;16769:34;16749:18;;;16742:62;-1:-1:-1;;;16820:18:23;;;16813:39;16869:19;;2185:73:5;16489:405:23;4412:1158:22;1104:7:18;;-1:-1:-1;;;1104:7:18;;;;1347:9;1339:38;;;;-1:-1:-1;;;1339:38:18;;15510:2:23;1339:38:18;;;15492:21:23;15549:2;15529:18;;;15522:30;-1:-1:-1;;;15568:18:23;;;15561:46;15624:18;;1339:38:18;15308:340:23;1339:38:18;4499:9:22::1;666:10:2::0;4499:25:22::1;4491:46;;;::::0;-1:-1:-1;;;4491:46:22;;13642:2:23;4491:46:22::1;::::0;::::1;13624:21:23::0;13681:1;13661:18;;;13654:29;-1:-1:-1;;;13699:18:23;;;13692:38;13747:18;;4491:46:22::1;13440:331:23::0;4491:46:22::1;4551:6;::::0;4570:10:::1;::::0;4551:15:::1;::::0;4560:6;;4551::::1;;:15;:::i;:::-;:29;;4543:59;;;::::0;-1:-1:-1;;;4543:59:22;;12588:2:23;4543:59:22::1;::::0;::::1;12570:21:23::0;12627:2;12607:18;;;12600:30;-1:-1:-1;;;12646:18:23;;;12639:47;12703:18;;4543:59:22::1;12386:341:23::0;4543:59:22::1;4625:1;4616:6;:10;:26;;;;;4640:2;4630:6;:12;;4616:26;4608:58;;;::::0;-1:-1:-1;;;4608:58:22;;19882:2:23;4608:58:22::1;::::0;::::1;19864:21:23::0;19921:2;19901:18;;;19894:30;-1:-1:-1;;;19940:18:23;;;19933:49;19999:18;;4608:58:22::1;19680:343:23::0;4608:58:22::1;4685:11;::::0;4676:6:::1;::::0;::::1;;:20;4672:234;;;4733:11;::::0;4714:6:::1;::::0;:15:::1;::::0;4723:6;;4714::::1;;:15;:::i;:::-;:30;;4706:74;;;::::0;-1:-1:-1;;;4706:74:22;;15150:2:23;4706:74:22::1;::::0;::::1;15132:21:23::0;15189:2;15169:18;;;15162:30;15228:33;15208:18;;;15201:61;15279:18;;4706:74:22::1;14948:355:23::0;4706:74:22::1;4819:9;4796:19;359:13;4796:6:::0;:19:::1;:::i;:::-;:32;4788:67;;;::::0;-1:-1:-1;;;4788:67:22;;13291:2:23;4788:67:22::1;::::0;::::1;13273:21:23::0;13330:2;13310:18;;;13303:30;-1:-1:-1;;;13349:18:23;;;13342:52;13411:18;;4788:67:22::1;13089:346:23::0;4788:67:22::1;4672:234;;;4884:9;:14:::0;4876:23:::1;;;::::0;::::1;;4912:21;4943:24:::0;4970:5:::1;:46;;5001:15;::::0;;5014:1:::1;5001:15:::0;;::::1;::::0;::::1;::::0;;;4970:46:::1;;;4991:6;4978:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;4978:20:22::1;;4970:46;4943:73:::0;-1:-1:-1;5022:12:22::1;::::0;5040:388:::1;5061:6;5057:1;:10;5040:388;;;5082:6;:8:::0;;::::1;;::::0;:6:::1;:8;::::0;::::1;:::i;:::-;::::0;;::::1;::::0;;;::::1;;::::0;;::::1;;::::0;;::::1;::::0;;::::1;;;::::0;;;5112:6:::1;::::0;5105:14:::1;::::0;-1:-1:-1;5112:6:22::1;5105;:14::i;:::-;5136:6;::::0;5098:21;;-1:-1:-1;5127:22:22::1;::::0;5136:6:::1;;5098:21:::0;5127:8:::1;:22::i;:::-;;5157:17;5177:21;5193:4;5177:15;:21::i;:::-;5157:41;;5211:5;5210:6;:35;;;-1:-1:-1::0;;;;;;5220:25:22;::::1;666:10:2::0;5220:25:22::1;;5210:35;5206:175;;;5278:6;::::0;5257:28:::1;::::0;5267:9;;5278:6:::1;;5257:9;:28::i;:::-;5206:175;;;5328:4;::::0;5335:6:::1;::::0;5310:32:::1;::::0;-1:-1:-1;;;;;5328:4:22::1;::::0;5335:6:::1;;5310:9;:32::i;:::-;5366:6;::::0;5352:11;;5366:6:::1;::::0;;::::1;::::0;5352:8;;5361:1;;5352:11;::::1;;;;;:::i;:::-;;;;;;:20;;;;;;;;;::::0;::::1;5206:175;5414:6;::::0;5405:16:::1;::::0;5414:6:::1;;5405:8;:16::i;:::-;5388:33;::::0;;::::1;:::i;:::-;;;5074:354;5069:3;;;;;:::i;:::-;;;;5040:388;;;-1:-1:-1::0;5442:17:22;;5438:61:::1;;5461:4;::::0;-1:-1:-1;;;;;5461:4:22::1;:9;666:10:2::0;5461:38:22::1;::::0;-1:-1:-1;;;;;;5461:38:22::1;::::0;;;;;;-1:-1:-1;;;;;8723:32:23;;;5461:38:22::1;::::0;::::1;8705:51:23::0;8772:18;;;8765:34;;;8678:18;;5461:38:22::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;5438:61;5509:5;5505:60;;;5516:4;::::0;-1:-1:-1;;;;;5516:4:22::1;:25;666:10:2::0;5556:8:22::1;5516:49;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;5505:60;4485:1085;;;4412:1158:::0;;:::o;1790:205:5:-;1862:7;-1:-1:-1;;;;;1889:19:5;;1881:74;;;;-1:-1:-1;;;1881:74:5;;16280:2:23;1881:74:5;;;16262:21:23;16319:2;16299:18;;;16292:30;16358:34;16338:18;;;16331:62;-1:-1:-1;;;16409:18:23;;;16402:40;16459:19;;1881:74:5;16078:406:23;1881:74:5;-1:-1:-1;;;;;;1972:16:5;;;;;:9;:16;;;;;;;1790:205::o;1598:92:17:-;1038:6;;-1:-1:-1;;;;;1038:6:17;666:10:2;1178:23:17;1170:68;;;;-1:-1:-1;;;1170:68:17;;;;;;;:::i;:::-;1662:21:::1;1680:1;1662:9;:21::i;:::-;1598:92::o:0;10352:129:22:-;10425:16;;:::i;:::-;-1:-1:-1;10456:20:22;;;;:11;:20;;;;;;;;;10449:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;10449:27:22;;;;;;;;-1:-1:-1;;;10449:27:22;;;;;;;;-1:-1:-1;;;10449:27:22;;;;;;;;;;;-1:-1:-1;;;10449:27:22;;;;;;;;;;;10352:129::o;2511:102:5:-;2567:13;2599:7;2592:14;;;;;:::i;4144:290::-;-1:-1:-1;;;;;4246:24:5;;666:10:2;4246:24:5;;4238:62;;;;-1:-1:-1;;;4238:62:5;;14383:2:23;4238:62:5;;;14365:21:23;14422:2;14402:18;;;14395:30;14461:27;14441:18;;;14434:55;14506:18;;4238:62:5;14181:349:23;4238:62:5;666:10:2;4311:32:5;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;4311:42:5;;;;;;;;;;;;:53;;-1:-1:-1;;4311:53:5;;;;;;;;;;4379:48;;8950:41:23;;;4311:42:5;;666:10:2;4379:48:5;;8923:18:23;4379:48:5;;;;;;;4144:290;;:::o;5365:320::-;5534:41;666:10:2;5567:7:5;5534:18;:41::i;:::-;5526:103;;;;-1:-1:-1;;;5526:103:5;;;;;;;:::i;:::-;5639:39;5653:4;5659:2;5663:7;5672:5;5639:13;:39::i;:::-;5365:320;;;;:::o;11322:204:22:-;7222:4:5;7245:16;;;:7;:16;;;;;;11387:13:22;;-1:-1:-1;;;;;7245:16:5;11408:76:22;;;;-1:-1:-1;;;11408:76:22;;18646:2:23;11408:76:22;;;18628:21:23;18685:2;18665:18;;;18658:30;18724:34;18704:18;;;18697:62;-1:-1:-1;;;18775:18:23;;;18768:45;18830:19;;11408:76:22;18444:411:23;11408:76:22;11497:6;;:24;;-1:-1:-1;;;11497:24:22;;;;;22214:25:23;;;-1:-1:-1;;;;;11497:6:22;;;;:15;;22187:18:23;;11497:24:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11497:24:22;;;;;;;;;;;;:::i;1839:189:17:-;1038:6;;-1:-1:-1;;;;;1038:6:17;666:10:2;1178:23:17;1170:68;;;;-1:-1:-1;;;1170:68:17;;;;;;;:::i;:::-;-1:-1:-1;;;;;1927:22:17;::::1;1919:73;;;::::0;-1:-1:-1;;;1919:73:17;;12181:2:23;1919:73:17::1;::::0;::::1;12163:21:23::0;12220:2;12200:18;;;12193:30;12259:34;12239:18;;;12232:62;-1:-1:-1;;;12310:18:23;;;12303:36;12356:19;;1919:73:17::1;11979:402:23::0;1919:73:17::1;2002:19;2012:8;2002:9;:19::i;1431:300:5:-:0;1533:4;-1:-1:-1;;;;;;1568:40:5;;-1:-1:-1;;;1568:40:5;;:104;;-1:-1:-1;;;;;;;1624:48:5;;-1:-1:-1;;;1624:48:5;1568:104;:156;;;-1:-1:-1;;;;;;;;;;871:40:3;;;1688:36:5;763:155:3;11008:171:5;11082:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;11082:29:5;-1:-1:-1;;;;;11082:29:5;;;;;;;;:24;;11135:23;11082:24;11135:14;:23::i;:::-;-1:-1:-1;;;;;11126:46:5;;;;;;;;;;;11008:171;;:::o;1799:115:18:-;1104:7;;-1:-1:-1;;;1104:7:18;;;;1347:9;1339:38;;;;-1:-1:-1;;;1339:38:18;;15510:2:23;1339:38:18;;;15492:21:23;15549:2;15529:18;;;15522:30;-1:-1:-1;;;15568:18:23;;;15561:46;15624:18;;1339:38:18;15308:340:23;1339:38:18;1858:7:::1;:14:::0;;-1:-1:-1;;;;1858:14:18::1;-1:-1:-1::0;;;1858:14:18::1;::::0;;1887:20:::1;1894:12;666:10:2::0;;587:96;1894:12:18::1;1887:20;::::0;-1:-1:-1;;;;;7249:32:23;;;7231:51;;7219:2;7204:18;1887:20:18::1;;;;;;;1799:115::o:0;2046:117::-;1104:7;;-1:-1:-1;;;1104:7:18;;;;1605:41;;;;-1:-1:-1;;;1605:41:18;;11001:2:23;1605:41:18;;;10983:21:23;11040:2;11020:18;;;11013:30;-1:-1:-1;;;11059:18:23;;;11052:50;11119:18;;1605:41:18;10799:344:23;1605:41:18;2104:7:::1;:15:::0;;-1:-1:-1;;;;2104:15:18::1;::::0;;2134:22:::1;666:10:2::0;2143:12:18::1;587:96:2::0;7440:344:5;7533:4;7245:16;;;:7;:16;;;;;;-1:-1:-1;;;;;7245:16:5;7549:73;;;;-1:-1:-1;;;7549:73:5;;14737:2:23;7549:73:5;;;14719:21:23;14776:2;14756:18;;;14749:30;14815:34;14795:18;;;14788:62;-1:-1:-1;;;14866:18:23;;;14859:42;14918:19;;7549:73:5;14535:408:23;7549:73:5;7632:13;7648:23;7663:7;7648:14;:23::i;:::-;7632:39;;7700:5;-1:-1:-1;;;;;7689:16:5;:7;-1:-1:-1;;;;;7689:16:5;;:51;;;;7733:7;-1:-1:-1;;;;;7709:31:5;:20;7721:7;7709:11;:20::i;:::-;-1:-1:-1;;;;;7709:31:5;;7689:51;:87;;;-1:-1:-1;;;;;;4620:25:5;;;4597:4;4620:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;7744:32;7681:96;7440:344;-1:-1:-1;;;;7440:344:5:o;10337:560::-;10491:4;-1:-1:-1;;;;;10464:31:5;:23;10479:7;10464:14;:23::i;:::-;-1:-1:-1;;;;;10464:31:5;;10456:85;;;;-1:-1:-1;;;10456:85:5;;18236:2:23;10456:85:5;;;18218:21:23;18275:2;18255:18;;;18248:30;18314:34;18294:18;;;18287:62;-1:-1:-1;;;18365:18:23;;;18358:39;18414:19;;10456:85:5;18034:405:23;10456:85:5;-1:-1:-1;;;;;10559:16:5;;10551:65;;;;-1:-1:-1;;;10551:65:5;;13978:2:23;10551:65:5;;;13960:21:23;14017:2;13997:18;;;13990:30;14056:34;14036:18;;;14029:62;-1:-1:-1;;;14107:18:23;;;14100:34;14151:19;;10551:65:5;13776:400:23;10551:65:5;10627:39;10648:4;10654:2;10658:7;10627:20;:39::i;:::-;10728:29;10745:1;10749:7;10728:8;:29::i;:::-;-1:-1:-1;;;;;10768:15:5;;;;;;:9;:15;;;;;:20;;10787:1;;10768:15;:20;;10787:1;;10768:20;:::i;:::-;;;;-1:-1:-1;;;;;;;10798:13:5;;;;;;:9;:13;;;;;:18;;10815:1;;10798:13;:18;;10815:1;;10798:18;:::i;:::-;;;;-1:-1:-1;;10826:16:5;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;10826:21:5;-1:-1:-1;;;;;10826:21:5;;;;;;;;;10863:27;;10826:16;;10863:27;;;;;;;10337:560;;;:::o;10124:209:22:-;10177:7;10241:9;10268:16;10283:1;10268:12;:16;:::i;:::-;10217:109;;6013:2:23;6009:15;;;;-1:-1:-1;;6005:53:23;10217:109:22;;;5993:66:23;10258:27:22;6075:12:23;;;6068:28;10293:15:22;6112:12:23;;;6105:28;6149:12;;;6142:28;;;6186:13;;10217:109:22;;;-1:-1:-1;;10217:109:22;;;;;;;;;10207:120;;10217:109;10207:120;;;;;10124:209;-1:-1:-1;;10124:209:22:o;6765:327::-;6832:18;;:::i;:::-;6862;6875:4;6862:12;:18::i;:::-;6858:22;;6890:20;:37;6911:15;6924:1;6911:12;:15::i;:::-;6890:37;;;;;;;;;;;;6931:1;6890:42;6886:158;;;6942:20;;;;:11;:20;;;;;;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6942:24:22;;;;;;-1:-1:-1;;6942:24:22;;;;;;;;;;;;;-1:-1:-1;;6942:24:22;;;;;;;;;-1:-1:-1;;6942:24:22;;;;;;;;;;;;;;;;;-1:-1:-1;;6942:24:22;;;;;;;;;-1:-1:-1;;6942:24:22;;;;;;;;;;;;;;-1:-1:-1;;6942:24:22;-1:-1:-1;;;6942:24:22;;;;;;;-1:-1:-1;;6942:24:22;;-1:-1:-1;;;6942:24:22;;;;;;;;-1:-1:-1;;6942:24:22;-1:-1:-1;;;6942:24:22;;;;;;;-1:-1:-1;;6942:24:22;;-1:-1:-1;;;6942:24:22;;;;;;;;;;;;;;:20;;6974;;6995:15;6942:24;6995:12;:15::i;:::-;6974:37;;;;;;;;;;;-1:-1:-1;6974:37:22;:47;7029:8;;6886:158;7056:31;7065:7;7074:12;7081:4;7074:6;:12::i;:::-;7056:8;:31::i;:::-;7049:38;6765:327;-1:-1:-1;;;6765:327:22:o;8043:356::-;8134:11;;8124:6;;8105:7;;8124:6;;;;:21;;;:50;;-1:-1:-1;8150:18:22;8166:2;8159:3;8151:11;;;8150:18;:::i;:::-;8149:25;;8124:50;8120:75;;;666:10:2;8183:12:22;587:96:2;8120:75:22;8250:4;;:33;;-1:-1:-1;;;8250:33:22;;8279:3;8271:11;;;8250:33;;;22214:25:23;8234:13:22;;-1:-1:-1;;;;;8250:4:22;;:20;;22187:18:23;;8250:33:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8234:49;-1:-1:-1;;;;;;8334:21:22;;8330:46;;666:10:2;8357:19:22;8043:356;-1:-1:-1;;;8043:356:22:o;8114:108:5:-;8189:26;8199:2;8203:7;8189:26;;;;;;;;;;;;:9;:26::i;:::-;8114:108;;:::o;2034:169:17:-;2108:6;;;-1:-1:-1;;;;;2124:17:17;;;-1:-1:-1;;;;;;2124:17:17;;;;;;;2156:40;;2108:6;;;2124:17;2108:6;;2156:40;;2089:16;;2156:40;2079:124;2034:169;:::o;6547:307:5:-;6698:28;6708:4;6714:2;6718:7;6698:9;:28::i;:::-;6744:48;6767:4;6773:2;6777:7;6786:5;6744:22;:48::i;:::-;6736:111;;;;-1:-1:-1;;;6736:111:5;;;;;;;:::i;2543:572:6:-;-1:-1:-1;;;;;2742:18:6;;2738:183;;2776:40;2808:7;3924:10;:17;;3897:24;;;;:15;:24;;;;;:44;;;3951:24;;;;;;;;;;;;3821:161;2776:40;2738:183;;;2845:2;-1:-1:-1;;;;;2837:10:6;:4;-1:-1:-1;;;;;2837:10:6;;2833:88;;2863:47;2896:4;2902:7;2863:32;:47::i;:::-;-1:-1:-1;;;;;2934:16:6;;2930:179;;2966:45;3003:7;2966:36;:45::i;2930:179::-;3038:4;-1:-1:-1;;;;;3032:10:6;:2;-1:-1:-1;;;;;3032:10:6;;3028:81;;3058:40;3086:2;3090:7;3058:27;:40::i;8610:867:22:-;8669:18;;:::i;:::-;8711:20;8729:2;8719:6;8712:13;;8711:20;:::i;:::-;:25;;8699:37;;;8735:1;;8756:17;;8772:1;8756:17;;;8768:1;8756:17;8788:2;8779:11;;;;;8742:31;-1:-1:-1;8804:45:22;8830:6;8823:13;;8839:9;8742:31;8839:1;:9;:::i;:::-;8804:11;:45::i;:::-;8796:53;;:5;;;:53;8864:2;8855:11;;;;;8881:45;8907:6;8900:13;;8916:9;8920:5;8916:1;:9;:::i;8881:45::-;8872:54;;:6;;;:54;8941:2;8932:11;;;;;8958:45;8984:6;8977:13;;8993:9;8997:5;8993:1;:9;:::i;8958:45::-;8949:54;;:6;;;:54;9018:2;9009:11;;;;;9035:45;9061:6;9054:13;;9070:9;9074:5;9070:1;:9;:::i;9035:45::-;9026:54;;:6;;;:54;9095:2;9086:11;;;;;9112:45;9138:6;9131:13;;9147:9;9151:5;9147:1;:9;:::i;9112:45::-;9103:54;;:6;;;:54;9172:2;9163:11;;;;;9190:45;9216:6;9209:13;;9225:9;9229:5;9225:1;:9;:::i;9190:45::-;9180:55;;:7;;;:55;9250:2;9241:11;;;;;9267:45;9293:6;9286:13;;9302:9;9306:5;9302:1;:9;:::i;9267:45::-;9258:54;;:6;;;:54;9327:2;9318:11;;;;;9344:45;9370:6;9363:13;;9379:9;9383:5;9379:1;:9;:::i;9344:45::-;9335:54;;:6;;;:54;9404:2;9395:11;;;;;9427:45;9453:6;9446:13;;9462:9;9466:5;9462:1;:9;:::i;9427:45::-;9412:60;;:12;;;:60;-1:-1:-1;9412:1:22;8610:867;-1:-1:-1;8610:867:22:o;9647:299::-;9783:9;;9802:5;;;;;9817:6;;;;;9833;;;;9849:7;;;;9866:6;;;;9882;;;;9898;;;;9914:12;;;;9757:177;;6574:14:23;;6567:22;6535:3;6559:31;;;9757:177:22;;;6547:44:23;;;;-1:-1:-1;;;;;;6656:15:23;;;6652:24;;6639:11;;;6632:45;6710:15;;;6706:24;;6693:11;;;6686:45;6764:15;;;6760:24;;6747:11;;;6740:45;6818:15;;;6814:24;;6801:11;;;6794:45;6872:15;;6868:24;;6855:11;;;6848:45;6926:15;;6922:24;;6909:11;;;6902:45;6980:15;;6976:24;;6963:11;;;6956:45;5737:15;;;5733:35;7035:11;;;5721:48;9712:7:22;;7063:11:23;;9757:177:22;;;;;;;;;;;;9742:198;;;:::i;8443:311:5:-;8568:18;8574:2;8578:7;8568:5;:18::i;:::-;8617:54;8648:1;8652:2;8656:7;8665:5;8617:22;:54::i;:::-;8596:151;;;;-1:-1:-1;;;8596:151:5;;;;;;;:::i;11732:778::-;11882:4;-1:-1:-1;;;;;11902:13:5;;1034:20:0;1080:8;11898:606:5;;11937:72;;-1:-1:-1;;;11937:72:5;;-1:-1:-1;;;;;11937:36:5;;;;;:72;;666:10:2;;11988:4:5;;11994:7;;12003:5;;11937:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11937:72:5;;;;;;;;-1:-1:-1;;11937:72:5;;;;;;;;;;;;:::i;:::-;;;11933:519;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12176:13:5;;12172:266;;12218:60;;-1:-1:-1;;;12218:60:5;;;;;;;:::i;12172:266::-;12390:6;12384:13;12375:6;12371:2;12367:15;12360:38;11933:519;-1:-1:-1;;;;;;12059:51:5;-1:-1:-1;;;12059:51:5;;-1:-1:-1;12052:58:5;;11898:606;-1:-1:-1;12489:4:5;11732:778;;;;;;:::o;4599:970:6:-;4861:22;4911:1;4886:22;4903:4;4886:16;:22::i;:::-;:26;;;;:::i;:::-;4922:18;4943:26;;;:17;:26;;;;;;4861:51;;-1:-1:-1;5073:28:6;;;5069:323;;-1:-1:-1;;;;;5139:18:6;;5117:19;5139:18;;;:12;:18;;;;;;;;:34;;;;;;;;;5188:30;;;;;;:44;;;5304:30;;:17;:30;;;;;:43;;;5069:323;-1:-1:-1;5485:26:6;;;;:17;:26;;;;;;;;5478:33;;;-1:-1:-1;;;;;5528:18:6;;;;;:12;:18;;;;;:34;;;;;;;5521:41;4599:970::o;5857:1061::-;6131:10;:17;6106:22;;6131:21;;6151:1;;6131:21;:::i;:::-;6162:18;6183:24;;;:15;:24;;;;;;6551:10;:26;;6106:46;;-1:-1:-1;6183:24:6;;6106:46;;6551:26;;;;;;:::i;:::-;;;;;;;;;6529:48;;6613:11;6588:10;6599;6588:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;6692:28;;;:15;:28;;;;;;;:41;;;6861:24;;;;;6854:31;6895:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;5928:990;;;5857:1061;:::o;3409:217::-;3493:14;3510:20;3527:2;3510:16;:20::i;:::-;-1:-1:-1;;;;;3540:16:6;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;3584:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;3409:217:6:o;7498:253:22:-;7572:5;7585:11;7619:8;7628:9;7619:19;;;;;;;;;:::i;:::-;;:26;7599:47;;7605:4;7599:47;:::i;:::-;7585:61;;7668:8;7677:9;7668:19;;;;;;;;;:::i;:::-;;7688:5;7668:26;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;7664:1;7656:9;;;;;;:38;7652:56;;;7703:5;-1:-1:-1;7696:12:22;;7652:56;7721:7;7729:9;7721:18;;;;;;;;;:::i;:::-;;7740:5;7721:25;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;7714:32;;;7498:253;;;;:::o;9076:372:5:-;-1:-1:-1;;;;;9155:16:5;;9147:61;;;;-1:-1:-1;;;9147:61:5;;17101:2:23;9147:61:5;;;17083:21:23;;;17120:18;;;17113:30;17179:34;17159:18;;;17152:62;17231:18;;9147:61:5;16899:356:23;9147:61:5;7222:4;7245:16;;;:7;:16;;;;;;-1:-1:-1;;;;;7245:16:5;:30;9218:58;;;;-1:-1:-1;;;9218:58:5;;12934:2:23;9218:58:5;;;12916:21:23;12973:2;12953:18;;;12946:30;13012;12992:18;;;12985:58;13060:18;;9218:58:5;12732:352:23;9218:58:5;9287:45;9316:1;9320:2;9324:7;9287:20;:45::i;:::-;-1:-1:-1;;;;;9343:13:5;;;;;;:9;:13;;;;;:18;;9360:1;;9343:13;:18;;9360:1;;9343:18;:::i;:::-;;;;-1:-1:-1;;9371:16:5;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;9371:21:5;-1:-1:-1;;;;;9371:21:5;;;;;;;;9408:33;;9371:16;;;9408:33;;9371:16;;9408:33;9076:372;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:160:23:-;79:20;;135:13;;128:21;118:32;;108:60;;164:1;161;154:12;108:60;14:160;;;:::o;179:247::-;238:6;291:2;279:9;270:7;266:23;262:32;259:52;;;307:1;304;297:12;259:52;346:9;333:23;365:31;390:5;365:31;:::i;431:251::-;501:6;554:2;542:9;533:7;529:23;525:32;522:52;;;570:1;567;560:12;522:52;602:9;596:16;621:31;646:5;621:31;:::i;687:388::-;755:6;763;816:2;804:9;795:7;791:23;787:32;784:52;;;832:1;829;822:12;784:52;871:9;858:23;890:31;915:5;890:31;:::i;:::-;940:5;-1:-1:-1;997:2:23;982:18;;969:32;1010:33;969:32;1010:33;:::i;:::-;1062:7;1052:17;;;687:388;;;;;:::o;1080:456::-;1157:6;1165;1173;1226:2;1214:9;1205:7;1201:23;1197:32;1194:52;;;1242:1;1239;1232:12;1194:52;1281:9;1268:23;1300:31;1325:5;1300:31;:::i;:::-;1350:5;-1:-1:-1;1407:2:23;1392:18;;1379:32;1420:33;1379:32;1420:33;:::i;:::-;1080:456;;1472:7;;-1:-1:-1;;;1526:2:23;1511:18;;;;1498:32;;1080:456::o;1541:1016::-;1636:6;1644;1652;1660;1713:3;1701:9;1692:7;1688:23;1684:33;1681:53;;;1730:1;1727;1720:12;1681:53;1769:9;1756:23;1788:31;1813:5;1788:31;:::i;:::-;1838:5;-1:-1:-1;1895:2:23;1880:18;;1867:32;1908:33;1867:32;1908:33;:::i;:::-;1960:7;-1:-1:-1;2014:2:23;1999:18;;1986:32;;-1:-1:-1;2069:2:23;2054:18;;2041:32;2096:18;2085:30;;2082:50;;;2128:1;2125;2118:12;2082:50;2151:22;;2204:4;2196:13;;2192:27;-1:-1:-1;2182:55:23;;2233:1;2230;2223:12;2182:55;2269:2;2256:16;2294:48;2310:31;2338:2;2310:31;:::i;:::-;2294:48;:::i;:::-;2365:2;2358:5;2351:17;2405:7;2400:2;2395;2391;2387:11;2383:20;2380:33;2377:53;;;2426:1;2423;2416:12;2377:53;2481:2;2476;2472;2468:11;2463:2;2456:5;2452:14;2439:45;2525:1;2520:2;2515;2508:5;2504:14;2500:23;2493:34;2546:5;2536:15;;;;;1541:1016;;;;;;;:::o;2562:315::-;2627:6;2635;2688:2;2676:9;2667:7;2663:23;2659:32;2656:52;;;2704:1;2701;2694:12;2656:52;2743:9;2730:23;2762:31;2787:5;2762:31;:::i;:::-;2812:5;-1:-1:-1;2836:35:23;2867:2;2852:18;;2836:35;:::i;:::-;2826:45;;2562:315;;;;;:::o;2882:::-;2950:6;2958;3011:2;2999:9;2990:7;2986:23;2982:32;2979:52;;;3027:1;3024;3017:12;2979:52;3066:9;3053:23;3085:31;3110:5;3085:31;:::i;:::-;3135:5;3187:2;3172:18;;;;3159:32;;-1:-1:-1;;;2882:315:23:o;3202:180::-;3258:6;3311:2;3299:9;3290:7;3286:23;3282:32;3279:52;;;3327:1;3324;3317:12;3279:52;3350:26;3366:9;3350:26;:::i;3387:245::-;3445:6;3498:2;3486:9;3477:7;3473:23;3469:32;3466:52;;;3514:1;3511;3504:12;3466:52;3553:9;3540:23;3572:30;3596:5;3572:30;:::i;3637:249::-;3706:6;3759:2;3747:9;3738:7;3734:23;3730:32;3727:52;;;3775:1;3772;3765:12;3727:52;3807:9;3801:16;3826:30;3850:5;3826:30;:::i;3891:635::-;3971:6;4024:2;4012:9;4003:7;3999:23;3995:32;3992:52;;;4040:1;4037;4030:12;3992:52;4073:9;4067:16;4106:18;4098:6;4095:30;4092:50;;;4138:1;4135;4128:12;4092:50;4161:22;;4214:4;4206:13;;4202:27;-1:-1:-1;4192:55:23;;4243:1;4240;4233:12;4192:55;4272:2;4266:9;4297:48;4313:31;4341:2;4313:31;:::i;4297:48::-;4368:2;4361:5;4354:17;4408:7;4403:2;4398;4394;4390:11;4386:20;4383:33;4380:53;;;4429:1;4426;4419:12;4380:53;4442:54;4493:2;4488;4481:5;4477:14;4472:2;4468;4464:11;4442:54;:::i;:::-;4515:5;3891:635;-1:-1:-1;;;;;3891:635:23:o;4531:180::-;4590:6;4643:2;4631:9;4622:7;4618:23;4614:32;4611:52;;;4659:1;4656;4649:12;4611:52;-1:-1:-1;4682:23:23;;4531:180;-1:-1:-1;4531:180:23:o;4716:248::-;4781:6;4789;4842:2;4830:9;4821:7;4817:23;4813:32;4810:52;;;4858:1;4855;4848:12;4810:52;4894:9;4881:23;4871:33;;4923:35;4954:2;4943:9;4939:18;4923:35;:::i;4969:248::-;5037:6;5045;5098:2;5086:9;5077:7;5073:23;5069:32;5066:52;;;5114:1;5111;5104:12;5066:52;-1:-1:-1;;5137:23:23;;;5207:2;5192:18;;;5179:32;;-1:-1:-1;4969:248:23:o;5318:257::-;5359:3;5397:5;5391:12;5424:6;5419:3;5412:19;5440:63;5496:6;5489:4;5484:3;5480:14;5473:4;5466:5;5462:16;5440:63;:::i;:::-;5557:2;5536:15;-1:-1:-1;;5532:29:23;5523:39;;;;5564:4;5519:50;;5318:257;-1:-1:-1;;5318:257:23:o;7293:488::-;-1:-1:-1;;;;;7562:15:23;;;7544:34;;7614:15;;7609:2;7594:18;;7587:43;7661:2;7646:18;;7639:34;;;7709:3;7704:2;7689:18;;7682:31;;;7487:4;;7730:45;;7755:19;;7747:6;7730:45;:::i;:::-;7722:53;7293:488;-1:-1:-1;;;;;;7293:488:23:o;7786:740::-;-1:-1:-1;;;;;8032:32:23;;8014:51;;8002:2;8084;8102:18;;;8095:30;;;8174:13;;7987:18;;;8196:22;;;7954:4;;8275:15;;;;8084:2;8249;8234:18;;;7954:4;8318:182;8332:6;8329:1;8326:13;8318:182;;;8397:13;;8412:6;8393:26;8381:39;;8475:15;;;;8440:12;;;;8354:1;8347:9;8318:182;;;-1:-1:-1;8517:3:23;;7786:740;-1:-1:-1;;;;;;;7786:740:23:o;10575:219::-;10724:2;10713:9;10706:21;10687:4;10744:44;10784:2;10773:9;10769:18;10761:6;10744:44;:::i;11560:414::-;11762:2;11744:21;;;11801:2;11781:18;;;11774:30;11840:34;11835:2;11820:18;;11813:62;-1:-1:-1;;;11906:2:23;11891:18;;11884:48;11964:3;11949:19;;11560:414::o;17673:356::-;17875:2;17857:21;;;17894:18;;;17887:30;17953:34;17948:2;17933:18;;17926:62;18020:2;18005:18;;17673:356::o;19262:413::-;19464:2;19446:21;;;19503:2;19483:18;;;19476:30;19542:34;19537:2;19522:18;;19515:62;-1:-1:-1;;;19608:2:23;19593:18;;19586:47;19665:3;19650:19;;19262:413::o;20441:1429::-;20658:13;;5292;5285:21;5273:34;;20629:3;20614:19;;20730:4;20722:6;20718:17;20712:24;20745:61;20800:4;20789:9;20785:20;20771:12;5656:4;5645:16;5633:29;;5580:84;20745:61;;20855:4;20847:6;20843:17;20837:24;20870:63;20927:4;20916:9;20912:20;20896:14;5656:4;5645:16;5633:29;;5580:84;20870:63;;20982:4;20974:6;20970:17;20964:24;20997:63;21054:4;21043:9;21039:20;21023:14;5656:4;5645:16;5633:29;;5580:84;20997:63;;21109:4;21101:6;21097:17;21091:24;21124:63;21181:4;21170:9;21166:20;21150:14;5656:4;5645:16;5633:29;;5580:84;21124:63;;21236:4;21228:6;21224:17;21218:24;21251:63;21308:4;21297:9;21293:20;21277:14;5656:4;5645:16;5633:29;;5580:84;21251:63;;21363:4;21355:6;21351:17;21345:24;21378:63;21435:4;21424:9;21420:20;21404:14;5656:4;5645:16;5633:29;;5580:84;21378:63;;21490:4;21482:6;21478:17;21472:24;21505:63;21562:4;21551:9;21547:20;21531:14;5656:4;5645:16;5633:29;;5580:84;21505:63;-1:-1:-1;21587:6:23;21630:15;;;21624:22;5656:4;5645:16;;;21697:18;;;5633:29;;;;21735:6;21778:15;;;21772:22;5645:16;21845:18;;;;5633:29;;;;20441:1429;:::o;22439:275::-;22510:2;22504:9;22575:2;22556:13;;-1:-1:-1;;22552:27:23;22540:40;;22610:18;22595:34;;22631:22;;;22592:62;22589:88;;;22657:18;;:::i;:::-;22693:2;22686:22;22439:275;;-1:-1:-1;22439:275:23:o;22719:186::-;22767:4;22800:18;22792:6;22789:30;22786:56;;;22822:18;;:::i;:::-;-1:-1:-1;22888:2:23;22867:15;-1:-1:-1;;22863:29:23;22894:4;22859:40;;22719:186::o;22910:128::-;22950:3;22981:1;22977:6;22974:1;22971:13;22968:39;;;22987:18;;:::i;:::-;-1:-1:-1;23023:9:23;;22910:128::o;23043:204::-;23081:3;23117:4;23114:1;23110:12;23149:4;23146:1;23142:12;23184:3;23178:4;23174:14;23169:3;23166:23;23163:49;;;23192:18;;:::i;:::-;23228:13;;23043:204;-1:-1:-1;;;23043:204:23:o;23252:120::-;23292:1;23318;23308:35;;23323:18;;:::i;:::-;-1:-1:-1;23357:9:23;;23252:120::o;23377:168::-;23417:7;23483:1;23479;23475:6;23471:14;23468:1;23465:21;23460:1;23453:9;23446:17;23442:45;23439:71;;;23490:18;;:::i;:::-;-1:-1:-1;23530:9:23;;23377:168::o;23550:125::-;23590:4;23618:1;23615;23612:8;23609:34;;;23623:18;;:::i;:::-;-1:-1:-1;23660:9:23;;23550:125::o;23680:297::-;23798:12;;23845:4;23834:16;;;23828:23;;23798:12;23863:16;;23860:111;;;23957:1;23953:6;23943;23937:4;23933:17;23930:1;23926:25;23922:38;23915:5;23911:50;23902:59;;23860:111;;23680:297;;;:::o;23982:258::-;24054:1;24064:113;24078:6;24075:1;24072:13;24064:113;;;24154:11;;;24148:18;24135:11;;;24128:39;24100:2;24093:10;24064:113;;;24195:6;24192:1;24189:13;24186:48;;;-1:-1:-1;;24230:1:23;24212:16;;24205:27;23982:258::o;24245:380::-;24324:1;24320:12;;;;24367;;;24388:61;;24442:4;24434:6;24430:17;24420:27;;24388:61;24495:2;24487:6;24484:14;24464:18;24461:38;24458:161;;;24541:10;24536:3;24532:20;24529:1;24522:31;24576:4;24573:1;24566:15;24604:4;24601:1;24594:15;24630:197;24668:3;24696:6;24737:2;24730:5;24726:14;24764:2;24755:7;24752:15;24749:41;;;24770:18;;:::i;:::-;24819:1;24806:15;;24630:197;-1:-1:-1;;;24630:197:23:o;24832:135::-;24871:3;-1:-1:-1;;24892:17:23;;24889:43;;;24912:18;;:::i;:::-;-1:-1:-1;24959:1:23;24948:13;;24832:135::o;24972:112::-;25004:1;25030;25020:35;;25035:18;;:::i;:::-;-1:-1:-1;25069:9:23;;24972:112::o;25089:157::-;25119:1;25153:4;25150:1;25146:12;25177:3;25167:37;;25184:18;;:::i;:::-;25236:3;25229:4;25226:1;25222:12;25218:22;25213:27;;;25089:157;;;;:::o;25251:127::-;25312:10;25307:3;25303:20;25300:1;25293:31;25343:4;25340:1;25333:15;25367:4;25364:1;25357:15;25383:127;25444:10;25439:3;25435:20;25432:1;25425:31;25475:4;25472:1;25465:15;25499:4;25496:1;25489:15;25515:127;25576:10;25571:3;25567:20;25564:1;25557:31;25607:4;25604:1;25597:15;25631:4;25628:1;25621:15;25647:127;25708:10;25703:3;25699:20;25696:1;25689:31;25739:4;25736:1;25729:15;25763:4;25760:1;25753:15;25779:127;25840:10;25835:3;25831:20;25828:1;25821:31;25871:4;25868:1;25861:15;25895:4;25892:1;25885:15;25911:131;-1:-1:-1;;;;;25986:31:23;;25976:42;;25966:70;;26032:1;26029;26022:12;26047:131;-1:-1:-1;;;;;;26121:32:23;;26111:43;;26101:71;;26168:1;26165;26158:12

Swarm Source

ipfs://b3ce39ee22297b56605e3c0e70deea10e6ad821b85ac6034a47b9b10f040ac04
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.