Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
NFT
Overview
Max Total Supply
13,809 WGAME
Holders
12
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
0 WGAMELoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Woolf
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity Multiple files format)
// 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); } }
// 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); } } } }
// 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; } }
// 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; } }
// 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; } }
// 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 {} }
// 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 {} }
// 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(); } }
// 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); }
// 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); }
// 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); }
// 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); }
// 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; }
// 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); }
// 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); }
// 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); }
// SPDX-License-Identifier: MIT LICENSE pragma solidity ^0.8.0; interface ITraits { function tokenURI(uint256 tokenId) external view returns (string memory); }
// 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); }
// 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); } }
// 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()); } }
// 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); } }
// 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; } }
// 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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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.