ERC-721
NFT
Overview
Max Total Supply
26,969 ლ⚈෴⚈ლ
Holders
4,007
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 ლ⚈෴⚈ლLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
ChainFaces2
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPLv3 pragma solidity 0.8.7; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "./ChainFaces2Renderer.sol"; import "./ChainFaces2Errors.sol"; contract ChainFaces2 is ERC721, ERC721Enumerable, Ownable { /************************* COMMON *************************/ // Sale stage enum enum Stage { STAGE_COMPLETE, STAGE_PRESALE, STAGE_MAIN_SALE } bool balanceNotWithdrawn; constructor(uint256 _tokenLimit, uint256 _secretCommit, address _renderer, bytes32 _merkleRoot) ERC721("ChainFaces Arena", unicode"ლ⚈෴⚈ლ") { tokenLimit = _tokenLimit; secret = _secretCommit; merkleRoot = _merkleRoot; balanceNotWithdrawn = true; // Start in presale stage stage = Stage.STAGE_PRESALE; renderer = ChainFaces2Renderer(_renderer); // Mint ancients for (uint256 i = 0; i < 10; i++) { _createFace(); } } fallback() external payable {} /************************* TOKEN SALE *************************/ Stage public stage; uint256 public saleEnds; uint256 public immutable tokenLimit; // Merkle distributor values bytes32 immutable merkleRoot; mapping(uint256 => uint256) private claimedBitMap; uint256 public constant saleLength = 60 minutes; uint256 public constant salePrice = 0.069 ether; uint256 secret; // Entropy supplied by owner (commit/reveal style) uint256 userSecret; // Pseudorandom entropy provided by minters // -- MODIFIERS -- modifier onlyMainSaleOpen() { if (stage != Stage.STAGE_MAIN_SALE || mainSaleComplete()) { revert SaleNotOpen(); } _; } modifier onlyPreSale() { if (stage != Stage.STAGE_PRESALE) { revert NotPreSaleStage(); } _; } modifier onlyMainSale() { if (stage != Stage.STAGE_MAIN_SALE) { revert NotMainSaleStage(); } _; } modifier onlySaleComplete() { if (stage != Stage.STAGE_COMPLETE) { revert SaleNotComplete(); } _; } // -- VIEW METHODS -- function mainSaleComplete() public view returns (bool) { return block.timestamp >= saleEnds || totalSupply() == tokenLimit; } function isClaimed(uint256 index) public view returns (bool) { uint256 claimedWordIndex = index / 256; uint256 claimedBitIndex = index % 256; uint256 claimedWord = claimedBitMap[claimedWordIndex]; uint256 mask = (1 << claimedBitIndex); return claimedWord & mask == mask; } // -- OWNER METHODS -- // Reveal the faces function theGreatReveal(uint256 _secretReveal) external onlyOwner onlyMainSale { if (!mainSaleComplete()) { revert MainSaleNotComplete(); } if (uint256(keccak256(abi.encodePacked(_secretReveal))) != secret) { revert InvalidReveal(); } // Final secret is XOR between the pre-committed secret and the pseudo-random user contributed salt secret = _secretReveal ^ userSecret; // Won't be needing this anymore delete userSecret; stage = Stage.STAGE_COMPLETE; } // Start main sale function startMainSale() external onlyOwner onlyPreSale { stage = Stage.STAGE_MAIN_SALE; saleEnds = block.timestamp + saleLength; } // Withdraw sale proceeds function withdraw() external onlyOwner { // Owner can't reneg on bounty if (arenaActive()) { revert ArenaIsActive(); } balanceNotWithdrawn = false; owner().call{value : address(this).balance}(""); } // -- USER METHODS -- function claim(uint256 _index, uint256 _ogAmount, uint256 _wlAmount, bytes32[] calldata _merkleProof, uint256 _amount) external payable onlyPreSale { // Ensure not already claimed if (isClaimed(_index)) { revert AlreadyClaimed(); } // Prevent accidental claim of 0 if (_amount == 0) { revert InvalidClaimAmount(); } // Check claim amount uint256 total = _ogAmount + _wlAmount; if (_amount > total) { revert InvalidClaimAmount(); } // Check claim value uint256 paidClaims = 0; if (_amount > _ogAmount) { paidClaims = _amount - _ogAmount; } if (msg.value < paidClaims * salePrice) { revert InvalidClaimValue(); } // Verify the merkle proof bytes32 node = keccak256(abi.encodePacked(_index, msg.sender, _ogAmount, _wlAmount)); if (!MerkleProof.verify(_merkleProof, merkleRoot, node)) { revert InvalidProof(); } // Mark it claimed and mint _setClaimed(_index); for (uint256 i = 0; i < _amount; i++) { _createFace(); } _mix(); } // Mint faces function createFace() external payable onlyMainSaleOpen { uint256 count = msg.value / salePrice; if (count == 0) { revert InvalidMintValue(); } else if (count > 20) { count = 20; } // Don't mint more than supply if (count + totalSupply() > tokenLimit) { count = tokenLimit - totalSupply(); } // Mint 'em for (uint256 i = 0; i < count; i++) { _createFace(); } _mix(); // Send any excess ETH back to the caller uint256 excess = msg.value - (salePrice * count); if (excess > 0) { (bool success,) = msg.sender.call{value : excess}(""); require(success); } } // -- INTERNAL METHODS -- function _setClaimed(uint256 index) internal { uint256 claimedWordIndex = index / 256; uint256 claimedBitIndex = index % 256; claimedBitMap[claimedWordIndex] = claimedBitMap[claimedWordIndex] | (1 << claimedBitIndex); } function _createFace() internal { uint256 tokenId = totalSupply(); _mint(msg.sender, tokenId); } function _mix() internal { // Add some pseudorandom value which will be mixed with the pre-committed secret unchecked { userSecret += uint256(blockhash(block.number - 1)); } } /************************* NFT *************************/ modifier onlyTokenExists(uint256 _id) { if (!_exists(_id)) { revert NonExistentToken(); } _; } ChainFaces2Renderer public renderer; // -- VIEW METHODS -- function assembleFace(uint256 _id) external view onlyTokenExists(_id) returns (string memory) { return renderer.assembleFace(stage == Stage.STAGE_COMPLETE, _id, getFinalizedSeed(_id)); } function tokenURI(uint256 _id) public view override onlyTokenExists(_id) returns (string memory) { return renderer.renderMetadata(stage == Stage.STAGE_COMPLETE, _id, getFinalizedSeed(_id), roundsSurvived[_id], ownerOf(_id)); } function renderSvg(uint256 _id) external view onlyTokenExists(_id) returns (string memory) { uint256 rounds; // If face is still in the arena, show them with correct amount of scars if (ownerOf(_id) == address(this)) { rounds = currentRound; } else { rounds = roundsSurvived[_id]; } return renderer.renderSvg(stage == Stage.STAGE_COMPLETE, _id, getFinalizedSeed(_id), rounds, ownerOf(_id)); } // -- INTERNAL METHODS -- function getFinalizedSeed(uint256 _tokenId) internal view returns (uint256) { return uint256(keccak256(abi.encodePacked(secret, _tokenId))); } /************************* ARENA *************************/ uint256 arenaOpenedBlock; uint256 lionsLastFeeding; uint256 champion; uint256 public currentRound = 0; address constant happyFacePlace = 0x7039D65E346FDEEBbc72514D718C88699c74ba4b; uint256 public constant arenaWaitBlocks = 6969; uint256 public constant blocksPerRound = 69; mapping(uint256 => address) warriorDepositor; mapping(uint256 => uint256) public roundsSurvived; // -- MODIFIERS -- modifier onlyOpenArena() { if (!entryOpen()) { revert ArenaEntryClosed(); } _; } // -- VIEW METHODS -- struct ArenaInfo { uint256 fallen; uint256 alive; uint256 currentRound; uint256 bounty; uint256 hunger; uint256 nextFeed; uint256 champion; uint256 entryClosedBlock; bool hungry; bool open; bool active; bool gameOver; } function arenaInfo() external view returns (ArenaInfo memory info) { info.fallen = balanceOf(happyFacePlace); info.alive = balanceOf(address(this)); info.currentRound = currentRound; info.bounty = address(this).balance; info.hunger = howHungryAreTheLions(); info.champion = champion; info.entryClosedBlock = entryClosedBlock(); if (!theLionsAreHungry()) { info.nextFeed = lionsLastFeeding + blocksPerRound - block.number; } info.hungry = theLionsAreHungry(); info.open = entryOpen(); info.active = arenaActive(); info.gameOver = block.number > info.entryClosedBlock && info.alive <= 1; } // Return array of msg.senders warriors filtered by alive or fallen function myWarriors(bool _alive) external view returns (uint256[] memory) { return ownerWarriors(msg.sender, _alive); } // Return array of owner's warriors filtered by alive or fallen function ownerWarriors(address _owner, bool _alive) public view returns (uint256[] memory) { address holdingAddress; if (_alive) { holdingAddress = address(this); } else { holdingAddress = happyFacePlace; } uint256 total = balanceOf(holdingAddress); uint256[] memory warriors = new uint256[](total); uint256 index = 0; for (uint256 i = 0; i < total; i++) { uint256 id = tokenOfOwnerByIndex(holdingAddress, i); if (warriorDepositor[id] == _owner) { warriors[index++] = id; } } assembly { mstore(warriors, index) } return warriors; } function arenaActive() public view returns (bool) { return arenaOpenedBlock > 0; } function entryOpen() public view returns (bool) { return arenaActive() && block.number < entryClosedBlock(); } function entryClosedBlock() public view returns (uint256) { return arenaOpenedBlock + arenaWaitBlocks; } function totalSurvivingWarriors() public view returns (uint256) { return balanceOf(address(this)); } function howHungryAreTheLions() public view returns (uint256) { uint256 totalWarriors = totalSurvivingWarriors(); if (totalWarriors == 0) { return 0; } uint256 hunger = 1; // Calculate how many warriors got eaten (0.2% of warriors > 1000) if (totalWarriors >= 2000) { uint256 excess = totalWarriors - 1000; hunger = excess / 500; } // Never eat the last man standing if (hunger >= totalWarriors) { hunger = totalWarriors - 1; } // Generous upper bound to prevent gas overflow if (hunger > 50) { hunger = 50; } return hunger; } function theLionsAreHungry() public view returns (bool) { return block.number >= lionsLastFeeding + blocksPerRound; } // -- OWNER METHODS -- function openArena() external payable onlyOwner onlySaleComplete { if (arenaActive()) { revert ArenaIsActive(); } if (balanceNotWithdrawn) { revert BalanceNotWithdrawn(); } // Open the arena arenaOpenedBlock = block.number; lionsLastFeeding = block.number + arenaWaitBlocks; } // -- USER METHODS -- // Can be called every `blocksPerRound` blocks to kill off some eager warriors function timeToEat() external { if (!arenaActive()) { revert ArenaNotActive(); } if (!theLionsAreHungry()) { revert LionsNotHungry(); } uint256 totalWarriors = totalSurvivingWarriors(); if (totalWarriors == 1) { revert LastManStanding(); } if (totalWarriors == 0) { revert GameOver(); } // The blockhash of every `blocksPerRound` block is used to determine who gets eaten uint256 entropyBlock; if (block.number - (lionsLastFeeding + blocksPerRound) > 255) { // If this method isn't called within 255 blocks of the period end, this is a fallback so we can still progress entropyBlock = (block.number / blocksPerRound) * blocksPerRound - 1; } else { // Use blockhash of every 69th block entropyBlock = (lionsLastFeeding + blocksPerRound) - 1; } uint256 entropy = uint256(blockhash(entropyBlock)); assert(entropy != 0); // Update state lionsLastFeeding = block.number; currentRound++; // Kill off a percentage of warriors uint256 killCounter = howHungryAreTheLions(); bytes memory buffer = new bytes(32); for (uint256 i = 0; i < killCounter; i++) { uint256 tmp; unchecked { tmp = entropy + i; } // Gas saving trick to avoid abi.encodePacked assembly { mstore(add(buffer, 32), tmp) } uint256 whoDied = uint256(keccak256(buffer)) % totalWarriors; // Go to your happy place, loser uint256 faceToEat = tokenOfOwnerByIndex(address(this), whoDied); _transfer(address(this), happyFacePlace, faceToEat); // Take one down totalWarriors--; } // Record the champion if (totalWarriors == 1) { champion = tokenOfOwnerByIndex(address(this), 0); } } function joinArena(uint256 _tokenId) external onlyOpenArena { _joinArena(_tokenId); } function multiJoinArena(uint256[] memory _tokenIds) external onlyOpenArena { if (_tokenIds.length > 20) { revert InvalidJoinCount(); } for (uint256 i; i < _tokenIds.length; i++) { _joinArena(_tokenIds[i]); } } function leaveArena(uint256 _tokenId) external { if (warriorDepositor[_tokenId] != msg.sender) { revert NotYourWarrior(); } // Can't leave arena if lions are hungry (unless it's the champ and the game is over) uint256 survivors = totalSurvivingWarriors(); if (survivors != 1 && theLionsAreHungry()) { revert LionsAreHungry(); } // Can't leave before a single round has passed uint256 round = currentRound; if (currentRound == 0) { revert LeavingProhibited(); } // Record the warrior's achievement roundsSurvived[_tokenId] = round; // Clear state delete warriorDepositor[_tokenId]; // Return warrior and pay bounty uint256 battleBounty = address(this).balance / survivors; _transfer(address(this), msg.sender, _tokenId); payable(msg.sender).transfer(battleBounty); // If this was the second last warrior to leave, the last one left is the champ if (survivors == 2) { champion = tokenOfOwnerByIndex(address(this), 0); } } // -- INTERNAL METHODS -- function _joinArena(uint256 _tokenId) internal { // Send warrior to the arena transferFrom(msg.sender, address(this), _tokenId); warriorDepositor[_tokenId] = msg.sender; } /************************* MISC *************************/ function onERC721Received(address, address, uint256, bytes memory) external pure returns (bytes4) { return this.onERC721Received.selector; } function _beforeTokenTransfer(address _from, address _to, uint256 _tokenId) internal override(ERC721, ERC721Enumerable) { super._beforeTokenTransfer(_from, _to, _tokenId); } function supportsInterface(bytes4 _interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) { return super.supportsInterface(_interfaceId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/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 { _setApprovalForAll(_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 Approve `operator` to operate on all of `owner` tokens * * Emits a {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @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 // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) 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 // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/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() { _transferOwnership(_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 { _transferOwnership(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"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Trees proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { bytes32 proofElement = proof[i]; if (computedHash <= proofElement) { // Hash(current computed hash + current element of the proof) computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { // Hash(current element of the proof + current computed hash) computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } } return computedHash; } }
// SPDX-License-Identifier: GPLv3 pragma solidity 0.8.7; import "@openzeppelin/contracts/utils/Strings.sol"; contract ChainFaces2Renderer { using Strings for uint256; address public constant happyFacePlace = 0x7039D65E346FDEEBbc72514D718C88699c74ba4b; // Rendering constants string[18] public leftFaceArray = [unicode"ლ", unicode"ᕦ", unicode"(ง", unicode"𐐋", unicode"ᖳ", unicode"Ƹ", unicode"ᛩ", unicode"⦃", unicode"{", unicode"⦗", unicode"〈", unicode"⧼", unicode"|", unicode"〘", unicode"〚", unicode"【", unicode"[", unicode"❪"]; string[20] public leftEyeArray = [unicode"⚈", unicode"⚙", unicode"⊗", unicode"⋗", unicode" ͡°", unicode"◈", unicode"◬", unicode"≻", unicode"᛫", unicode"⨕", unicode"★", unicode"Ͼ", unicode"ᗒ", unicode"◠", unicode"⊡", unicode"⊙", unicode"▸", unicode"˘", unicode"⦿", unicode"●"]; string[22] public mouthArray = [unicode"෴", unicode"∪", unicode"ᨏ", unicode"᎔", unicode"᎑", unicode"⋏", unicode"⚇", unicode"_", unicode"۷", unicode"▾", unicode"ᨎ", unicode"ʖ", unicode"ܫ", unicode"໒", unicode"𐑒", unicode"⌴", unicode"‿", unicode"𐠑", unicode"⌒", unicode"◡", unicode"⥿", unicode"⩊"]; string[20] public rightEyeArray = [unicode"⚈", unicode"⚙", unicode"⊗", unicode"⋖", unicode" ͡°", unicode"◈", unicode"◬", unicode"≺", unicode"᛫", unicode"⨕", unicode"★", unicode"Ͽ", unicode"ᗕ", unicode"◠", unicode"⊡", unicode"⊙", unicode"◂", unicode"˘", unicode"⦿", unicode"●"]; string[18] public rightFaceArray = [unicode"ლ", unicode"ᕤ", unicode")ง", unicode"𐐙", unicode"ᖰ", unicode"Ʒ", unicode"ᚹ", unicode"⦄", unicode"}", unicode"⦘", unicode"〉", unicode"⧽", unicode"|", unicode"〙", unicode"〛", unicode"】", unicode"]", unicode"❫"]; uint256[22] rarityArray = [0, 2, 5, 9, 14, 20, 27, 35, 44, 54, 65, 77, 90, 104, 119, 135, 152, 170, 189, 209, 230, 252]; uint256[5][] ancients; constructor() { ancients.push([0, 0, 0, 0, 0]); ancients.push([1, 1, 1, 1, 1]); ancients.push([2, 2, 2, 2, 2]); ancients.push([3, 3, 3, 3, 3]); ancients.push([4, 4, 4, 4, 4]); ancients.push([5, 5, 5, 5, 5]); ancients.push([6, 6, 6, 6, 6]); ancients.push([7, 7, 7, 7, 7]); ancients.push([8, 8, 8, 8, 8]); ancients.push([9, 9, 9, 9, 9]); } function getLeftFace(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return leftFaceArray[ancients[id][0]]; } uint256 raritySelector = seed % 189; uint256 charSelector = 0; for (uint i = 0; i < 18; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return leftFaceArray[charSelector]; } function getLeftEye(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return leftEyeArray[ancients[id][1]]; } uint256 raritySelector = seed % 230; uint256 charSelector = 0; for (uint i = 0; i < 20; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return leftEyeArray[charSelector]; } function getMouth(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return mouthArray[ancients[id][2]]; } uint256 raritySelector = seed % 275; uint256 charSelector = 0; for (uint i = 0; i < 22; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return mouthArray[charSelector]; } function getRightEye(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return rightEyeArray[ancients[id][3]]; } uint256 raritySelector = uint256(keccak256(abi.encodePacked(seed))) % 230; uint256 charSelector = 0; for (uint i = 0; i < 20; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return rightEyeArray[charSelector]; } function getRightFace(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return rightFaceArray[ancients[id][4]]; } uint256 raritySelector = uint256(keccak256(abi.encodePacked(seed))) % 189; uint256 charSelector = 0; for (uint i = 0; i < 18; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return rightFaceArray[charSelector]; } function assembleFace(bool revealComplete, uint256 id, uint256 seed) public view returns (string memory face) { if (!revealComplete) { return '(._.)'; } return string(abi.encodePacked( getLeftFace(id, seed), getLeftEye(id, seed), getMouth(id, seed), getRightEye(id, seed), getRightFace(id, seed) )); } function calculateGolfScore(uint256 id, uint256 seed) public view returns (uint256) { if (id < ancients.length) { return 0; } uint256 leftFaceRarity = seed % 189; uint256 lefEyeRarity = seed % 230; uint256 mouthRarity = seed % 275; uint256 rightEyeRarity = uint256(keccak256(abi.encodePacked(seed))) % 230; uint256 rightFaceRarity = uint256(keccak256(abi.encodePacked(seed))) % 189; uint256 leftFaceGolf = 0; uint256 leftEyeGolf = 0; uint256 mouthGolf = 0; uint256 rightEyeGolf = 0; uint256 rightFaceGolf = 0; uint256 i = 0; for (i = 0; i < 18; i++) { if (leftFaceRarity >= rarityArray[i]) { leftFaceGolf = i; } } for (i = 0; i < 20; i++) { if (lefEyeRarity >= rarityArray[i]) { leftEyeGolf = i; } } for (i = 0; i < 22; i++) { if (mouthRarity >= rarityArray[i]) { mouthGolf = i; } } for (i = 0; i < 20; i++) { if (rightEyeRarity >= rarityArray[i]) { rightEyeGolf = i; } } for (i = 0; i < 18; i++) { if (rightFaceRarity >= rarityArray[i]) { rightFaceGolf = i; } } return leftFaceGolf + leftEyeGolf + mouthGolf + rightEyeGolf + rightFaceGolf; } function calculateSymmetry(uint256 id, uint256 seed) public view returns (string memory) { uint256 symCount = 0; if (id < ancients.length) { symCount = 2; } else { uint256 leftFaceRarity = seed % 189; uint256 lefEyeRarity = seed % 230; uint256 rightEyeRarity = uint256(keccak256(abi.encodePacked(seed))) % 230; uint256 rightFaceRarity = uint256(keccak256(abi.encodePacked(seed))) % 189; uint256 leftFaceIndex = 0; uint256 leftEyeIndex = 0; uint256 rightEyeIndex = 0; uint256 rightFaceIndex = 0; uint256 i = 0; for (i = 0; i < 18; i++) { if (leftFaceRarity >= rarityArray[i]) { leftFaceIndex = i; } } for (i = 0; i < 20; i++) { if (lefEyeRarity >= rarityArray[i]) { leftEyeIndex = i; } } for (i = 0; i < 20; i++) { if (rightEyeRarity >= rarityArray[i]) { rightEyeIndex = i; } } for (i = 0; i < 18; i++) { if (rightFaceRarity >= rarityArray[i]) { rightFaceIndex = i; } } if (leftFaceIndex == rightFaceIndex) { symCount = symCount + 1; } if (leftEyeIndex == rightEyeIndex) { symCount = symCount + 1; } } if (symCount == 2) { return "100% Symmetry"; } else if (symCount == 1) { return "Partial Symmetry"; } else { return "No Symmetry"; } } function getTextColor(uint256 id) public view returns (string memory) { if (id < ancients.length) { return 'RGB(148,256,209)'; } else { return 'RGB(0,0,0)'; } } function getBackgroundColor(uint256 id, uint256 seed, address owner) public view returns (string memory){ if (id < ancients.length) { return 'RGB(128,128,128)'; } uint256 golf = calculateGolfScore(id, seed); uint256 red; uint256 green; uint256 blue; if (owner == happyFacePlace) { red = 255; green = 128; blue = 128; } else if (golf >= 56) { red = 255; green = 255; blue = 255 - (golf - 56) * 4; } else { red = 255 - (56 - golf) * 4; green = 255 - (56 - golf) * 4; blue = 255; } return string(abi.encodePacked("RGB(", red.toString(), ",", green.toString(), ",", blue.toString(), ")")); } string constant headerText = 'data:application/json;ascii,{"description": "We are warrior ChainFaces. Here to watch over you forever, unless we get eaten by lions.","image":"data:image/svg+xml;base64,'; string constant attributesText = '","attributes":[{"trait_type":"Golf Score","value":'; string constant symmetryText = '},{"trait_type":"Symmetry","value":"'; string constant leftFaceText = '"},{"trait_type":"Left Face","value":"'; string constant leftEyeText = '"},{"trait_type":"Left Eye","value":"'; string constant mouthText = '"},{"trait_type":"Mouth","value":"'; string constant rightEyeText = '"},{"trait_type":"Right Eye","value":"'; string constant rightFaceText = '"},{"trait_type":"Right Face","value":"'; string constant arenaDurationText = '"},{"trait_type":"Arena Score","value":'; string constant ancientText = '},{"trait_type":"Ancient","value":"'; string constant footerText = '"}]}'; function renderMetadata(bool revealComplete, uint256 id, uint256 seed, uint256 arenaDuration, address owner) external view returns (string memory) { if (!revealComplete) { return preRevealMetadata(); } uint256 golfScore = calculateGolfScore(id, seed); string memory svg = b64Encode(bytes(renderSvg(true, id, seed, arenaDuration, owner))); string memory attributes = string(abi.encodePacked(attributesText, golfScore.toString())); attributes = string(abi.encodePacked(attributes, symmetryText, calculateSymmetry(id, seed))); attributes = string(abi.encodePacked(attributes, leftFaceText, getLeftFace(id, seed))); attributes = string(abi.encodePacked(attributes, leftEyeText, getLeftEye(id, seed))); attributes = string(abi.encodePacked(attributes, mouthText, getMouth(id, seed))); attributes = string(abi.encodePacked(attributes, rightEyeText, getRightEye(id, seed))); attributes = string(abi.encodePacked(attributes, rightFaceText, getRightFace(id, seed))); attributes = string(abi.encodePacked(attributes, arenaDurationText, arenaDuration.toString())); if (id < ancients.length) { attributes = string(abi.encodePacked(attributes, ancientText, 'Ancient')); } else { attributes = string(abi.encodePacked(attributes, ancientText, 'Not Ancient')); } attributes = string(abi.encodePacked(attributes, footerText)); return string(abi.encodePacked(headerText, svg, attributes)); } string constant svg1 = "<svg xmlns='http://www.w3.org/2000/svg' width='400' height='400' style='background-color:"; string constant svg2 = "'>"; string constant svg3 = "<text x='50%' y='50%' dominant-baseline='middle' text-anchor='middle' font-size='75px' fill='"; string constant svg4 = "'>"; string constant svg5 = "</text></svg>"; function renderSvg(bool revealComplete, uint256 id, uint256 seed, uint256 arenaDuration, address owner) public view returns (string memory) { if (!revealComplete) { return preRevealSvg(); } string memory face = assembleFace(true, id, seed); string memory scars; if (arenaDuration > 0) { scars = generateScars(arenaDuration, seed); } return string(abi.encodePacked(svg1, getBackgroundColor(id, seed, owner), svg2, scars, svg3, getTextColor(id), svg4, face, svg5)); } string constant scarSymbol = "<symbol id='scar'><g stroke='RGBA(200,40,40,.35)'><text x='40' y='40' dominant-baseline='middle' text-anchor='middle' font-weight='bold' font-size='22px' fill='RGBA(200,40,40,.45)'>++++++</text></g></symbol>"; string constant scarPlacement1 = "<g transform='translate("; string constant scarPlacement2 = ") scale("; string constant scarPlacement3 = ") rotate("; string constant scarPlacement4 = ")'><use href='#scar'/></g>"; function generateScars(uint256 arenaDuration, uint256 seed) internal pure returns (string memory) { string memory scars; string memory scarsTemp; uint256 count = arenaDuration / 10; if (count > 500) { count = 500; } for (uint256 i = 0; i < count; i++) { string memory scar; uint256 scarSeed = uint256(keccak256(abi.encodePacked(seed, i))); uint256 scale1 = scarSeed % 2; uint256 scale2 = scarSeed % 5; if (scale1 == 0) { scale2 += 5; } uint256 xShift = scarSeed % 332; uint256 yShift = scarSeed % 354; int256 rotate = int256(scarSeed % 91) - 45; scar = string(abi.encodePacked(scar, scarPlacement1, xShift.toString(), " ", yShift.toString(), scarPlacement2, scale1.toString(), ".", scale2.toString())); if (rotate >= 0) { scar = string(abi.encodePacked(scar, scarPlacement3, uint256(rotate).toString(), scarPlacement4)); } else { scar = string(abi.encodePacked(scar, scarPlacement3, "-", uint256(0 - rotate).toString(), scarPlacement4)); } scarsTemp = string(abi.encodePacked(scarsTemp, scar)); if (i % 10 == 0) { scars = string(abi.encodePacked(scars, scarsTemp)); scarsTemp = ""; } } return string(abi.encodePacked(scarSymbol, scars, scarsTemp)); } function preRevealMetadata() internal pure returns (string memory) { string memory JSON; string memory svg = preRevealSvg(); JSON = string(abi.encodePacked('data:application/json;ascii,{"description": "We are warrior ChainFaces. Here to watch over you forever, unless we get eaten by lions.","image":"data:image/svg+xml;base64,', b64Encode(bytes(svg)), '"}')); return JSON; } function preRevealSvg() internal pure returns (string memory) { return "<svg xmlns='http://www.w3.org/2000/svg' width='400' height='400' style='background-color:RGB(255,255,255);'><text x='50%' y='50%' dominant-baseline='middle' text-anchor='middle' font-size='75px'>?????</text></svg>"; } string constant private TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; function b64Encode(bytes memory _data) internal pure returns (string memory result) { if (_data.length == 0) return ''; string memory _table = TABLE; uint256 _encodedLen = 4 * ((_data.length + 2) / 3); result = new string(_encodedLen + 32); assembly { mstore(result, _encodedLen) let tablePtr := add(_table, 1) let dataPtr := _data let endPtr := add(dataPtr, mload(_data)) let resultPtr := add(result, 32) for {} lt(dataPtr, endPtr) {} { dataPtr := add(dataPtr, 3) let input := mload(dataPtr) 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) } 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; } }
pragma solidity 0.8.7; // Sale error SaleNotOpen(); error NotPreSaleStage(); error NotMainSaleStage(); error SaleNotComplete(); error MainSaleNotComplete(); error AlreadyClaimed(); error InvalidClaimValue(); error InvalidClaimAmount(); error InvalidProof(); error InvalidMintValue(); // NFT error NonExistentToken(); // Reveal error InvalidReveal(); error BalanceNotWithdrawn(); error BalanceAlreadyWithdrawn(); // Arena error LeavingProhibited(); error ArenaIsActive(); error ArenaNotActive(); error ArenaEntryClosed(); error LionsNotHungry(); error LionsAreHungry(); error LastManStanding(); error GameOver(); error InvalidJoinCount(); error NotYourWarrior();
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/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 // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol) 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 // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) 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 // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) 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 // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) 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 // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) 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 // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) 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 // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Enumerable.sol) 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); }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_tokenLimit","type":"uint256"},{"internalType":"uint256","name":"_secretCommit","type":"uint256"},{"internalType":"address","name":"_renderer","type":"address"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"ArenaEntryClosed","type":"error"},{"inputs":[],"name":"ArenaIsActive","type":"error"},{"inputs":[],"name":"ArenaNotActive","type":"error"},{"inputs":[],"name":"BalanceNotWithdrawn","type":"error"},{"inputs":[],"name":"GameOver","type":"error"},{"inputs":[],"name":"InvalidClaimAmount","type":"error"},{"inputs":[],"name":"InvalidClaimValue","type":"error"},{"inputs":[],"name":"InvalidJoinCount","type":"error"},{"inputs":[],"name":"InvalidMintValue","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidReveal","type":"error"},{"inputs":[],"name":"LastManStanding","type":"error"},{"inputs":[],"name":"LeavingProhibited","type":"error"},{"inputs":[],"name":"LionsAreHungry","type":"error"},{"inputs":[],"name":"LionsNotHungry","type":"error"},{"inputs":[],"name":"MainSaleNotComplete","type":"error"},{"inputs":[],"name":"NonExistentToken","type":"error"},{"inputs":[],"name":"NotMainSaleStage","type":"error"},{"inputs":[],"name":"NotPreSaleStage","type":"error"},{"inputs":[],"name":"NotYourWarrior","type":"error"},{"inputs":[],"name":"SaleNotComplete","type":"error"},{"inputs":[],"name":"SaleNotOpen","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"arenaActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"arenaInfo","outputs":[{"components":[{"internalType":"uint256","name":"fallen","type":"uint256"},{"internalType":"uint256","name":"alive","type":"uint256"},{"internalType":"uint256","name":"currentRound","type":"uint256"},{"internalType":"uint256","name":"bounty","type":"uint256"},{"internalType":"uint256","name":"hunger","type":"uint256"},{"internalType":"uint256","name":"nextFeed","type":"uint256"},{"internalType":"uint256","name":"champion","type":"uint256"},{"internalType":"uint256","name":"entryClosedBlock","type":"uint256"},{"internalType":"bool","name":"hungry","type":"bool"},{"internalType":"bool","name":"open","type":"bool"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bool","name":"gameOver","type":"bool"}],"internalType":"struct ChainFaces2.ArenaInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"arenaWaitBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"assembleFace","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksPerRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"uint256","name":"_ogAmount","type":"uint256"},{"internalType":"uint256","name":"_wlAmount","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"createFace","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"currentRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"entryClosedBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"entryOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"howHungryAreTheLions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"index","type":"uint256"}],"name":"isClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"joinArena","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"leaveArena","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mainSaleComplete","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"multiJoinArena","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_alive","type":"bool"}],"name":"myWarriors","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"openArena","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"bool","name":"_alive","type":"bool"}],"name":"ownerWarriors","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"renderSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renderer","outputs":[{"internalType":"contract ChainFaces2Renderer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roundsSurvived","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"saleLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"salePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stage","outputs":[{"internalType":"enum ChainFaces2.Stage","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startMainSale","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":"_secretReveal","type":"uint256"}],"name":"theGreatReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"theLionsAreHungry","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeToEat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenLimit","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":"_id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSurvivingWarriors","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"}]
Contract Creation Code
60c060405260006013553480156200001657600080fd5b5060405162006cb738038062006cb783398181016040528101906200003c919062000b78565b6040518060400160405280601081526020017f436861696e4661636573204172656e61000000000000000000000000000000008152506040518060400160405280600f81526020017fe1839ae29a88e0b7b4e29a88e1839a00000000000000000000000000000000008152508160009080519060200190620000c092919062000a83565b508060019080519060200190620000d992919062000a83565b505050620000fc620000f0620001db60201b60201c565b620001e360201b60201c565b836080818152505082600d819055508060a081815250506001600a60146101000a81548160ff0219169083151502179055506001600a60156101000a81548160ff0219169083600281111562000157576200015662000e69565b5b021790555081600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060005b600a811015620001d057620001ba620002a960201b60201c565b8080620001c79062000dec565b915050620001a0565b505050505062001019565b600033905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000620002bb620002d260201b60201c565b9050620002cf3382620002df60201b60201c565b50565b6000600880549050905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141562000352576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003499062000ca3565b60405180910390fd5b6200036381620004c560201b60201c565b15620003a6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200039d9062000c5f565b60405180910390fd5b620003ba600083836200053160201b60201c565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546200040c919062000cd6565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b620005498383836200054e60201b62002e491760201c565b505050565b620005668383836200069560201b62002f5d1760201c565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415620005b357620005ad816200069a60201b60201c565b620005fb565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614620005fa57620005f98382620006e360201b60201c565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620006485762000642816200086060201b60201c565b62000690565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146200068f576200068e82826200093c60201b60201c565b5b5b505050565b505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001620006fd84620009c860201b62001ef41760201c565b62000709919062000d33565b9050600060076000848152602001908152602001600020549050818114620007ef576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b6000600160088054905062000876919062000d33565b9050600060096000848152602001908152602001600020549050600060088381548110620008a957620008a862000ef6565b5b906000526020600020015490508060088381548110620008ce57620008cd62000ef6565b5b90600052602060002001819055508160096000838152602001908152602001600020819055506009600085815260200190815260200160002060009055600880548062000920576200091f62000ec7565b5b6001900381819060005260206000200160009055905550505050565b60006200095483620009c860201b62001ef41760201c565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141562000a3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000a339062000c81565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b82805462000a919062000db6565b90600052602060002090601f01602090048101928262000ab5576000855562000b01565b82601f1062000ad057805160ff191683800117855562000b01565b8280016001018555821562000b01579182015b8281111562000b0057825182559160200191906001019062000ae3565b5b50905062000b10919062000b14565b5090565b5b8082111562000b2f57600081600090555060010162000b15565b5090565b60008151905062000b448162000fcb565b92915050565b60008151905062000b5b8162000fe5565b92915050565b60008151905062000b728162000fff565b92915050565b6000806000806080858703121562000b955762000b9462000f25565b5b600062000ba58782880162000b61565b945050602062000bb88782880162000b61565b935050604062000bcb8782880162000b33565b925050606062000bde8782880162000b4a565b91505092959194509250565b600062000bf9601c8362000cc5565b915062000c068262000f2a565b602082019050919050565b600062000c20602a8362000cc5565b915062000c2d8262000f53565b604082019050919050565b600062000c4760208362000cc5565b915062000c548262000fa2565b602082019050919050565b6000602082019050818103600083015262000c7a8162000bea565b9050919050565b6000602082019050818103600083015262000c9c8162000c11565b9050919050565b6000602082019050818103600083015262000cbe8162000c38565b9050919050565b600082825260208201905092915050565b600062000ce38262000dac565b915062000cf08362000dac565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111562000d285762000d2762000e3a565b5b828201905092915050565b600062000d408262000dac565b915062000d4d8362000dac565b92508282101562000d635762000d6262000e3a565b5b828203905092915050565b600062000d7b8262000d8c565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000600282049050600182168062000dcf57607f821691505b6020821081141562000de65762000de562000e98565b5b50919050565b600062000df98262000dac565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141562000e2f5762000e2e62000e3a565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b62000fd68162000d6e565b811462000fe257600080fd5b50565b62000ff08162000d82565b811462000ffc57600080fd5b50565b6200100a8162000dac565b81146200101657600080fd5b50565b60805160a051615c636200105460003960006128dd015260008181610eb20152818161149c015281816114de0152611bb50152615c636000f3fe60806040526004361061031e5760003560e01c8063580e77d4116101ab578063acedb5b4116100f7578063e13cbe3811610095578063f2fde38b1161006f578063f2fde38b14610ba7578063f51f96dd14610bd0578063f6b3a00a14610bfb578063fd5ad31914610c245761031f565b8063e13cbe3814610b14578063e985e9c514610b3f578063f2e45a4f14610b7c5761031f565b8063c57540b9116100d1578063c57540b914610a53578063c87b56dd14610a7e578063cb0274d514610abb578063d0f9e2be14610ad75761031f565b8063acedb5b4146109d6578063b88d4fde146109ff578063c040e6b814610a285761031f565b806378aafea2116101645780638da5cb5b1161013e5780638da5cb5b1461091a57806395d89b41146109455780639e34070f14610970578063a22cb465146109ad5761031f565b806378aafea2146108ba5780638a19c8bc146108c45780638ada6b0f146108ef5761031f565b8063580e77d4146107aa5780636352211e146107c157806364d34c11146107fe5780636e4ed7961461083b57806370a0823114610866578063715018a6146108a35761031f565b80632f745c591161026a57806342842e0e11610223578063473e3ea4116101fd578063473e3ea4146106ec5780634f6ccce7146107175780635533f19a1461075457806356c7627e1461077f5761031f565b806342842e0e1461066f578063469fc9241461069857806346feb24a146106c35761031f565b80632f745c5914610580578063305f7dbb146105bd57806339af9afe146105e85780633ad3bfc4146106115780633ccfd60b1461061b5780633d8d47ee146106325761031f565b8063150b7a02116102d757806326a67c91116102b157806326a67c91146104d657806327f70b0f14610513578063291e5fe01461053e5780632ae07c33146105555761031f565b8063150b7a021461044557806318160ddd1461048257806323b872dd146104ad5761031f565b806301ffc9a71461032157806306fdde031461035e578063081812fc14610389578063095ea7b3146103c65780630a212469146103ef578063130eb2f61461041a5761031f565b5b005b34801561032d57600080fd5b5061034860048036038101906103439190614578565b610c61565b6040516103559190614d52565b60405180910390f35b34801561036a57600080fd5b50610373610c73565b6040516103809190614e48565b60405180910390f35b34801561039557600080fd5b506103b060048036038101906103ab919061461b565b610d05565b6040516103bd9190614cc9565b60405180910390f35b3480156103d257600080fd5b506103ed60048036038101906103e891906144c2565b610d8a565b005b3480156103fb57600080fd5b50610404610ea2565b6040516104119190614d52565b60405180910390f35b34801561042657600080fd5b5061042f610ee0565b60405161043c9190614d52565b60405180910390f35b34801561045157600080fd5b5061046c600480360381019061046791906143ff565b610eec565b6040516104799190614df7565b60405180910390f35b34801561048e57600080fd5b50610497610f00565b6040516104a491906150a6565b60405180910390f35b3480156104b957600080fd5b506104d460048036038101906104cf91906143ac565b610f0d565b005b3480156104e257600080fd5b506104fd60048036038101906104f8919061454b565b610f6d565b60405161050a9190614d30565b60405180910390f35b34801561051f57600080fd5b50610528610f80565b6040516105359190614d52565b60405180910390f35b34801561054a57600080fd5b50610553610f99565b005b34801561056157600080fd5b5061056a611242565b60405161057791906150a6565b60405180910390f35b34801561058c57600080fd5b506105a760048036038101906105a291906144c2565b611248565b6040516105b491906150a6565b60405180910390f35b3480156105c957600080fd5b506105d26112ed565b6040516105df91906150a6565b60405180910390f35b3480156105f457600080fd5b5061060f600480360381019061060a9190614502565b6112fd565b005b6106196113bd565b005b34801561062757600080fd5b506106306115e0565b005b34801561063e57600080fd5b5061065960048036038101906106549190614482565b611728565b6040516106669190614d30565b60405180910390f35b34801561067b57600080fd5b50610696600480360381019061069191906143ac565b61187f565b005b3480156106a457600080fd5b506106ad61189f565b6040516106ba91906150a6565b60405180910390f35b3480156106cf57600080fd5b506106ea60048036038101906106e5919061461b565b611920565b005b3480156106f857600080fd5b50610701611b25565b60405161070e91906150a6565b60405180910390f35b34801561072357600080fd5b5061073e6004803603810190610739919061461b565b611b3c565b60405161074b91906150a6565b60405180910390f35b34801561076057600080fd5b50610769611bad565b60405161077691906150a6565b60405180910390f35b34801561078b57600080fd5b50610794611bb3565b6040516107a191906150a6565b60405180910390f35b3480156107b657600080fd5b506107bf611bd7565b005b3480156107cd57600080fd5b506107e860048036038101906107e3919061461b565b611d01565b6040516107f59190614cc9565b60405180910390f35b34801561080a57600080fd5b506108256004803603810190610820919061461b565b611db3565b6040516108329190614e48565b60405180910390f35b34801561084757600080fd5b50610850611eef565b60405161085d91906150a6565b60405180910390f35b34801561087257600080fd5b5061088d6004803603810190610888919061433f565b611ef4565b60405161089a91906150a6565b60405180910390f35b3480156108af57600080fd5b506108b8611fac565b005b6108c2612034565b005b3480156108d057600080fd5b506108d96121c0565b6040516108e691906150a6565b60405180910390f35b3480156108fb57600080fd5b506109046121c6565b6040516109119190614e12565b60405180910390f35b34801561092657600080fd5b5061092f6121ec565b60405161093c9190614cc9565b60405180910390f35b34801561095157600080fd5b5061095a612216565b6040516109679190614e48565b60405180910390f35b34801561097c57600080fd5b506109976004803603810190610992919061461b565b6122a8565b6040516109a49190614d52565b60405180910390f35b3480156109b957600080fd5b506109d460048036038101906109cf9190614482565b6122fe565b005b3480156109e257600080fd5b506109fd60048036038101906109f8919061461b565b612314565b005b348015610a0b57600080fd5b50610a266004803603810190610a2191906143ff565b6124dd565b005b348015610a3457600080fd5b50610a3d61253f565b604051610a4a9190614e2d565b60405180910390f35b348015610a5f57600080fd5b50610a68612552565b604051610a759190614d52565b60405180910390f35b348015610a8a57600080fd5b50610aa56004803603810190610aa0919061461b565b612573565b604051610ab29190614e48565b60405180910390f35b610ad56004803603810190610ad09190614648565b6126ce565b005b348015610ae357600080fd5b50610afe6004803603810190610af9919061461b565b61297b565b604051610b0b91906150a6565b60405180910390f35b348015610b2057600080fd5b50610b29612993565b604051610b3691906150a6565b60405180910390f35b348015610b4b57600080fd5b50610b666004803603810190610b61919061436c565b612999565b604051610b739190614d52565b60405180910390f35b348015610b8857600080fd5b50610b91612a2d565b604051610b9e919061508a565b60405180910390f35b348015610bb357600080fd5b50610bce6004803603810190610bc9919061433f565b612b54565b005b348015610bdc57600080fd5b50610be5612c4c565b604051610bf291906150a6565b60405180910390f35b348015610c0757600080fd5b50610c226004803603810190610c1d919061461b565b612c57565b005b348015610c3057600080fd5b50610c4b6004803603810190610c46919061461b565b612ca1565b604051610c589190614e48565b60405180910390f35b6000610c6c82612f62565b9050919050565b606060008054610c829061544a565b80601f0160208091040260200160405190810160405280929190818152602001828054610cae9061544a565b8015610cfb5780601f10610cd057610100808354040283529160200191610cfb565b820191906000526020600020905b815481529060010190602001808311610cde57829003601f168201915b5050505050905090565b6000610d1082612fdc565b610d4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d4690614fca565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610d9582611d01565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd9061502a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610e25613048565b73ffffffffffffffffffffffffffffffffffffffff161480610e545750610e5381610e4e613048565b612999565b5b610e93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e8a90614f4a565b60405180910390fd5b610e9d8383613050565b505050565b6000600b5442101580610edb57507f0000000000000000000000000000000000000000000000000000000000000000610ed9610f00565b145b905090565b60008060105411905090565b600063150b7a0260e01b9050949350505050565b6000600880549050905090565b610f1e610f18613048565b82613109565b610f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f549061504a565b60405180910390fd5b610f688383836131e7565b505050565b6060610f793383611728565b9050919050565b60006045601154610f9191906151f0565b431015905090565b610fa1610ee0565b610fd7576040517f8df38bf400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fdf610f80565b611015576040517f56cacac700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061101f6112ed565b9050600181141561105c576040517f0eeca4a400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000811415611097576040517fdf469ccb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060ff60456011546110aa91906151f0565b436110b591906152d1565b11156110e6576001604580436110cb9190615246565b6110d59190615277565b6110df91906152d1565b9050611104565b600160456011546110f791906151f0565b61110191906152d1565b90505b6000814060001c9050600081141561111f5761111e61555f565b5b4360118190555060136000815480929190611139906154ad565b9190505550600061114861189f565b90506000602067ffffffffffffffff811115611167576111666156a8565b5b6040519080825280601f01601f1916602001820160405280156111995781602001600182028036833780820191505090505b50905060005b8281101561121f5760008185019050806020840152600087848051906020012060001c6111cc919061552e565b905060006111da3083611248565b90506111fb30737039d65e346fdeebbc72514d718c88699c74ba4b836131e7565b888061120690615420565b9950505050508080611217906154ad565b91505061119f565b50600185141561123b57611234306000611248565b6012819055505b5050505050565b611b3981565b600061125383611ef4565b8210611294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128b90614e6a565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60006112f830611ef4565b905090565b611305612552565b61133b576040517ffd270db700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601481511115611377576040517f59a363c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81518110156113b9576113a682828151811061139957611398615679565b5b6020026020010151613443565b80806113b1906154ad565b91505061137a565b5050565b6002808111156113d0576113cf6155ec565b5b600a60159054906101000a900460ff1660028111156113f2576113f16155ec565b5b1415806114035750611402610ea2565b5b1561143a576040517f445dce4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600066f52322698080003461144f9190615246565b9050600081141561148c576040517fc755930f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601481111561149a57601490505b7f00000000000000000000000000000000000000000000000000000000000000006114c3610f00565b826114ce91906151f0565b111561150a576114dc610f00565b7f000000000000000000000000000000000000000000000000000000000000000061150791906152d1565b90505b60005b818110156115305761151d6134a3565b8080611528906154ad565b91505061150d565b506115396134bc565b60008166f523226980800061154e9190615277565b3461155991906152d1565b905060008111156115dc5760003373ffffffffffffffffffffffffffffffffffffffff168260405161158a90614c1f565b60006040518083038185875af1925050503d80600081146115c7576040519150601f19603f3d011682016040523d82523d6000602084013e6115cc565b606091505b50509050806115da57600080fd5b505b5050565b6115e8613048565b73ffffffffffffffffffffffffffffffffffffffff166116066121ec565b73ffffffffffffffffffffffffffffffffffffffff161461165c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165390614fea565b60405180910390fd5b611664610ee0565b1561169b576040517ff87a2c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600a60146101000a81548160ff0219169083151502179055506116be6121ec565b73ffffffffffffffffffffffffffffffffffffffff16476040516116e190614c1f565b60006040518083038185875af1925050503d806000811461171e576040519150601f19603f3d011682016040523d82523d6000602084013e611723565b606091505b505050565b60606000821561173a57309050611752565b737039d65e346fdeebbc72514d718c88699c74ba4b90505b600061175d82611ef4565b905060008167ffffffffffffffff81111561177b5761177a6156a8565b5b6040519080825280602002602001820160405280156117a95781602001602082028036833780820191505090505b5090506000805b8381101561186e5760006117c48683611248565b90508873ffffffffffffffffffffffffffffffffffffffff166014600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561185a578084848061183a906154ad565b95508151811061184d5761184c615679565b5b6020026020010181815250505b508080611866906154ad565b9150506117b0565b508082528194505050505092915050565b61189a838383604051806020016040528060008152506124dd565b505050565b6000806118aa6112ed565b905060008114156118bf57600091505061191d565b6000600190506107d082106118f25760006103e8836118de91906152d1565b90506101f4816118ee9190615246565b9150505b8181106119095760018261190691906152d1565b90505b603281111561191757603290505b80925050505b90565b3373ffffffffffffffffffffffffffffffffffffffff166014600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119b8576040517f81e1388300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006119c26112ed565b9050600181141580156119d957506119d8610f80565b5b15611a10576040517f7a8d10d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000601354905060006013541415611a54576040517fa77f4ebc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060156000858152602001908152602001600020819055506014600084815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560008247611ab09190615246565b9050611abd3033866131e7565b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611b03573d6000803e3d6000fd5b506002831415611b1f57611b18306000611248565b6012819055505b50505050565b6000611b39601054611b3791906151f0565b905090565b6000611b46610f00565b8210611b87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7e9061506a565b60405180910390fd5b60088281548110611b9b57611b9a615679565b5b90600052602060002001549050919050565b600b5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b611bdf613048565b73ffffffffffffffffffffffffffffffffffffffff16611bfd6121ec565b73ffffffffffffffffffffffffffffffffffffffff1614611c53576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4a90614fea565b60405180910390fd5b60016002811115611c6757611c666155ec565b5b600a60159054906101000a900460ff166002811115611c8957611c886155ec565b5b14611cc0576040517f34e6c21f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600a60156101000a81548160ff02191690836002811115611ce657611ce56155ec565b5b0217905550610e1042611cf991906151f0565b600b81905550565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611daa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da190614f8a565b60405180910390fd5b80915050919050565b606081611dbf81612fdc565b611df5576040517f9430a17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637fb7eac060006002811115611e4757611e466155ec565b5b600a60159054906101000a900460ff166002811115611e6957611e686155ec565b5b1485611e74876134d5565b6040518463ffffffff1660e01b8152600401611e9293929190614d6d565b60006040518083038186803b158015611eaa57600080fd5b505afa158015611ebe573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611ee791906145d2565b915050919050565b604581565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611f65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5c90614f6a565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611fb4613048565b73ffffffffffffffffffffffffffffffffffffffff16611fd26121ec565b73ffffffffffffffffffffffffffffffffffffffff1614612028576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201f90614fea565b60405180910390fd5b612032600061350c565b565b61203c613048565b73ffffffffffffffffffffffffffffffffffffffff1661205a6121ec565b73ffffffffffffffffffffffffffffffffffffffff16146120b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a790614fea565b60405180910390fd5b600060028111156120c4576120c36155ec565b5b600a60159054906101000a900460ff1660028111156120e6576120e56155ec565b5b1461211d576040517f1b44f83200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612125610ee0565b1561215c576040517ff87a2c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a60149054906101000a900460ff16156121a3576040517f61865db000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b43601081905550611b39436121b891906151f0565b601181905550565b60135481565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600180546122259061544a565b80601f01602080910402602001604051908101604052809291908181526020018280546122519061544a565b801561229e5780601f106122735761010080835404028352916020019161229e565b820191906000526020600020905b81548152906001019060200180831161228157829003601f168201915b5050505050905090565b600080610100836122b99190615246565b90506000610100846122cb919061552e565b90506000600c60008481526020019081526020016000205490506000826001901b90508081831614945050505050919050565b612310612309613048565b83836135d2565b5050565b61231c613048565b73ffffffffffffffffffffffffffffffffffffffff1661233a6121ec565b73ffffffffffffffffffffffffffffffffffffffff1614612390576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161238790614fea565b60405180910390fd5b6002808111156123a3576123a26155ec565b5b600a60159054906101000a900460ff1660028111156123c5576123c46155ec565b5b146123fc576040517fc6940a8600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612404610ea2565b61243a576040517ff1da374500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d548160405160200161244e9190614c34565b6040516020818303038152906040528051906020012060001c1461249e576040517f9ea6d12700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e548118600d81905550600e600090556000600a60156101000a81548160ff021916908360028111156124d5576124d46155ec565b5b021790555050565b6124ee6124e8613048565b83613109565b61252d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125249061504a565b60405180910390fd5b6125398484848461373f565b50505050565b600a60159054906101000a900460ff1681565b600061255c610ee0565b801561256e575061256b611b25565b43105b905090565b60608161257f81612fdc565b6125b5576040517f9430a17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f7db218c60006002811115612607576126066155ec565b5b600a60159054906101000a900460ff166002811115612629576126286155ec565b5b1485612634876134d5565b601560008981526020019081526020016000205461265189611d01565b6040518663ffffffff1660e01b8152600401612671959493929190614da4565b60006040518083038186803b15801561268957600080fd5b505afa15801561269d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906126c691906145d2565b915050919050565b600160028111156126e2576126e16155ec565b5b600a60159054906101000a900460ff166002811115612704576127036155ec565b5b1461273b576040517f34e6c21f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612744866122a8565b1561277b576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008114156127b6576040517f843ce46b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084866127c491906151f0565b905080821115612800576040517f843ce46b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008683111561281957868361281691906152d1565b90505b66f52322698080008161282c9190615277565b341015612865576040517fc23e2d6200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008833898960405160200161287e9493929190614c4f565b604051602081830303815290604052805190602001209050612902868680806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050507f00000000000000000000000000000000000000000000000000000000000000008361379b565b612938576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612941896137b2565b60005b84811015612967576129546134a3565b808061295f906154ad565b915050612944565b506129706134bc565b505050505050505050565b60156020528060005260406000206000915090505481565b610e1081565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b612a35614099565b612a52737039d65e346fdeebbc72514d718c88699c74ba4b611ef4565b816000018181525050612a6430611ef4565b81602001818152505060135481604001818152505047816060018181525050612a8b61189f565b8160800181815250506012548160c0018181525050612aa8611b25565b8160e0018181525050612ab9610f80565b612ae157436045601154612acd91906151f0565b612ad791906152d1565b8160a00181815250505b612ae9610f80565b81610100019015159081151581525050612b01612552565b81610120019015159081151581525050612b19610ee0565b816101400190151590811515815250508060e0015143118015612b4157506001816020015111155b8161016001901515908115158152505090565b612b5c613048565b73ffffffffffffffffffffffffffffffffffffffff16612b7a6121ec565b73ffffffffffffffffffffffffffffffffffffffff1614612bd0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bc790614fea565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612c40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c3790614eaa565b60405180910390fd5b612c498161350c565b50565b66f523226980800081565b612c5f612552565b612c95576040517ffd270db700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c9e81613443565b50565b606081612cad81612fdc565b612ce3576040517f9430a17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003073ffffffffffffffffffffffffffffffffffffffff16612d0585611d01565b73ffffffffffffffffffffffffffffffffffffffff161415612d2b576013549050612d42565b601560008581526020019081526020016000205490505b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a98edced60006002811115612d9457612d936155ec565b5b600a60159054906101000a900460ff166002811115612db657612db56155ec565b5b1486612dc1886134d5565b85612dcb8a611d01565b6040518663ffffffff1660e01b8152600401612deb959493929190614da4565b60006040518083038186803b158015612e0357600080fd5b505afa158015612e17573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612e4091906145d2565b92505050919050565b612e54838383612f5d565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612e9757612e928161380c565b612ed6565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612ed557612ed48382613855565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612f1957612f14816139c2565b612f58565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612f5757612f568282613a93565b5b5b505050565b505050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612fd55750612fd482613b12565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166130c383611d01565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061311482612fdc565b613153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161314a90614f2a565b60405180910390fd5b600061315e83611d01565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806131cd57508373ffffffffffffffffffffffffffffffffffffffff166131b584610d05565b73ffffffffffffffffffffffffffffffffffffffff16145b806131de57506131dd8185612999565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661320782611d01565b73ffffffffffffffffffffffffffffffffffffffff161461325d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132549061500a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156132cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132c490614eea565b60405180910390fd5b6132d8838383613bf4565b6132e3600082613050565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461333391906152d1565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461338a91906151f0565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b61344e333083610f0d565b336014600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60006134ad610f00565b90506134b93382613c04565b50565b600143034060001c600e60008282540192505081905550565b6000600d54826040516020016134ec929190614c9d565b6040516020818303038152906040528051906020012060001c9050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161363890614f0a565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516137329190614d52565b60405180910390a3505050565b61374a8484846131e7565b61375684848484613dd2565b613795576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161378c90614e8a565b60405180910390fd5b50505050565b6000826137a88584613f69565b1490509392505050565b6000610100826137c29190615246565b90506000610100836137d4919061552e565b9050806001901b600c60008481526020019081526020016000205417600c600084815260200190815260200160002081905550505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161386284611ef4565b61386c91906152d1565b9050600060076000848152602001908152602001600020549050818114613951576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b600060016008805490506139d691906152d1565b9050600060096000848152602001908152602001600020549050600060088381548110613a0657613a05615679565b5b906000526020600020015490508060088381548110613a2857613a27615679565b5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480613a7757613a7661564a565b5b6001900381819060005260206000200160009055905550505050565b6000613a9e83611ef4565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480613bdd57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80613bed5750613bec8261401c565b5b9050919050565b613bff838383612e49565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613c74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c6b90614faa565b60405180910390fd5b613c7d81612fdc565b15613cbd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cb490614eca565b60405180910390fd5b613cc960008383613bf4565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613d1991906151f0565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b6000613df38473ffffffffffffffffffffffffffffffffffffffff16614086565b15613f5c578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613e1c613048565b8786866040518563ffffffff1660e01b8152600401613e3e9493929190614ce4565b602060405180830381600087803b158015613e5857600080fd5b505af1925050508015613e8957506040513d601f19601f82011682018060405250810190613e8691906145a5565b60015b613f0c573d8060008114613eb9576040519150601f19603f3d011682016040523d82523d6000602084013e613ebe565b606091505b50600081511415613f04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613efb90614e8a565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613f61565b600190505b949350505050565b60008082905060005b8451811015614011576000858281518110613f9057613f8f615679565b5b60200260200101519050808311613fd1578281604051602001613fb4929190614bf3565b604051602081830303815290604052805190602001209250613ffd565b8083604051602001613fe4929190614bf3565b6040516020818303038152906040528051906020012092505b508080614009906154ad565b915050613f72565b508091505092915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600080823b905060008111915050919050565b60405180610180016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581526020016000151581526020016000151581525090565b6000614115614110846150e6565b6150c1565b90508083825260208201905082856020860282011115614138576141376156e1565b5b60005b85811015614168578161414e888261432a565b84526020840193506020830192505060018101905061413b565b5050509392505050565b600061418561418084615112565b6150c1565b9050828152602081018484840111156141a1576141a06156e6565b5b6141ac8482856153de565b509392505050565b60006141c76141c284615143565b6150c1565b9050828152602081018484840111156141e3576141e26156e6565b5b6141ee8482856153ed565b509392505050565b60008135905061420581615bd1565b92915050565b60008083601f840112614221576142206156dc565b5b8235905067ffffffffffffffff81111561423e5761423d6156d7565b5b60208301915083602082028301111561425a576142596156e1565b5b9250929050565b600082601f830112614276576142756156dc565b5b8135614286848260208601614102565b91505092915050565b60008135905061429e81615be8565b92915050565b6000813590506142b381615bff565b92915050565b6000815190506142c881615bff565b92915050565b600082601f8301126142e3576142e26156dc565b5b81356142f3848260208601614172565b91505092915050565b600082601f830112614311576143106156dc565b5b81516143218482602086016141b4565b91505092915050565b60008135905061433981615c16565b92915050565b600060208284031215614355576143546156f0565b5b6000614363848285016141f6565b91505092915050565b60008060408385031215614383576143826156f0565b5b6000614391858286016141f6565b92505060206143a2858286016141f6565b9150509250929050565b6000806000606084860312156143c5576143c46156f0565b5b60006143d3868287016141f6565b93505060206143e4868287016141f6565b92505060406143f58682870161432a565b9150509250925092565b60008060008060808587031215614419576144186156f0565b5b6000614427878288016141f6565b9450506020614438878288016141f6565b93505060406144498782880161432a565b925050606085013567ffffffffffffffff81111561446a576144696156eb565b5b614476878288016142ce565b91505092959194509250565b60008060408385031215614499576144986156f0565b5b60006144a7858286016141f6565b92505060206144b88582860161428f565b9150509250929050565b600080604083850312156144d9576144d86156f0565b5b60006144e7858286016141f6565b92505060206144f88582860161432a565b9150509250929050565b600060208284031215614518576145176156f0565b5b600082013567ffffffffffffffff811115614536576145356156eb565b5b61454284828501614261565b91505092915050565b600060208284031215614561576145606156f0565b5b600061456f8482850161428f565b91505092915050565b60006020828403121561458e5761458d6156f0565b5b600061459c848285016142a4565b91505092915050565b6000602082840312156145bb576145ba6156f0565b5b60006145c9848285016142b9565b91505092915050565b6000602082840312156145e8576145e76156f0565b5b600082015167ffffffffffffffff811115614606576146056156eb565b5b614612848285016142fc565b91505092915050565b600060208284031215614631576146306156f0565b5b600061463f8482850161432a565b91505092915050565b60008060008060008060a08789031215614665576146646156f0565b5b600061467389828a0161432a565b965050602061468489828a0161432a565b955050604061469589828a0161432a565b945050606087013567ffffffffffffffff8111156146b6576146b56156eb565b5b6146c289828a0161420b565b935093505060806146d589828a0161432a565b9150509295509295509295565b60006146ee8383614bbe565b60208301905092915050565b61470381615305565b82525050565b61471a61471582615305565b6154f6565b82525050565b600061472b82615184565b61473581856151b2565b935061474083615174565b8060005b8381101561477157815161475888826146e2565b9750614763836151a5565b925050600181019050614744565b5085935050505092915050565b61478781615317565b82525050565b61479681615317565b82525050565b6147ad6147a882615323565b615508565b82525050565b6147bc8161532d565b82525050565b60006147cd8261518f565b6147d781856151c3565b93506147e78185602086016153ed565b6147f0816156f5565b840191505092915050565b61480481615396565b82525050565b614813816153a8565b82525050565b60006148248261519a565b61482e81856151df565b935061483e8185602086016153ed565b614847816156f5565b840191505092915050565b600061485f602b836151df565b915061486a82615713565b604082019050919050565b60006148826032836151df565b915061488d82615762565b604082019050919050565b60006148a56026836151df565b91506148b0826157b1565b604082019050919050565b60006148c8601c836151df565b91506148d382615800565b602082019050919050565b60006148eb6024836151df565b91506148f682615829565b604082019050919050565b600061490e6019836151df565b915061491982615878565b602082019050919050565b6000614931602c836151df565b915061493c826158a1565b604082019050919050565b60006149546038836151df565b915061495f826158f0565b604082019050919050565b6000614977602a836151df565b91506149828261593f565b604082019050919050565b600061499a6029836151df565b91506149a58261598e565b604082019050919050565b60006149bd6020836151df565b91506149c8826159dd565b602082019050919050565b60006149e0602c836151df565b91506149eb82615a06565b604082019050919050565b6000614a036020836151df565b9150614a0e82615a55565b602082019050919050565b6000614a266029836151df565b9150614a3182615a7e565b604082019050919050565b6000614a496021836151df565b9150614a5482615acd565b604082019050919050565b6000614a6c6000836151d4565b9150614a7782615b1c565b600082019050919050565b6000614a8f6031836151df565b9150614a9a82615b1f565b604082019050919050565b6000614ab2602c836151df565b9150614abd82615b6e565b604082019050919050565b61018082016000820151614adf6000850182614bbe565b506020820151614af26020850182614bbe565b506040820151614b056040850182614bbe565b506060820151614b186060850182614bbe565b506080820151614b2b6080850182614bbe565b5060a0820151614b3e60a0850182614bbe565b5060c0820151614b5160c0850182614bbe565b5060e0820151614b6460e0850182614bbe565b50610100820151614b7961010085018261477e565b50610120820151614b8e61012085018261477e565b50610140820151614ba361014085018261477e565b50610160820151614bb861016085018261477e565b50505050565b614bc78161538c565b82525050565b614bd68161538c565b82525050565b614bed614be88261538c565b615524565b82525050565b6000614bff828561479c565b602082019150614c0f828461479c565b6020820191508190509392505050565b6000614c2a82614a5f565b9150819050919050565b6000614c408284614bdc565b60208201915081905092915050565b6000614c5b8287614bdc565b602082019150614c6b8286614709565b601482019150614c7b8285614bdc565b602082019150614c8b8284614bdc565b60208201915081905095945050505050565b6000614ca98285614bdc565b602082019150614cb98284614bdc565b6020820191508190509392505050565b6000602082019050614cde60008301846146fa565b92915050565b6000608082019050614cf960008301876146fa565b614d0660208301866146fa565b614d136040830185614bcd565b8181036060830152614d2581846147c2565b905095945050505050565b60006020820190508181036000830152614d4a8184614720565b905092915050565b6000602082019050614d67600083018461478d565b92915050565b6000606082019050614d82600083018661478d565b614d8f6020830185614bcd565b614d9c6040830184614bcd565b949350505050565b600060a082019050614db9600083018861478d565b614dc66020830187614bcd565b614dd36040830186614bcd565b614de06060830185614bcd565b614ded60808301846146fa565b9695505050505050565b6000602082019050614e0c60008301846147b3565b92915050565b6000602082019050614e2760008301846147fb565b92915050565b6000602082019050614e42600083018461480a565b92915050565b60006020820190508181036000830152614e628184614819565b905092915050565b60006020820190508181036000830152614e8381614852565b9050919050565b60006020820190508181036000830152614ea381614875565b9050919050565b60006020820190508181036000830152614ec381614898565b9050919050565b60006020820190508181036000830152614ee3816148bb565b9050919050565b60006020820190508181036000830152614f03816148de565b9050919050565b60006020820190508181036000830152614f2381614901565b9050919050565b60006020820190508181036000830152614f4381614924565b9050919050565b60006020820190508181036000830152614f6381614947565b9050919050565b60006020820190508181036000830152614f838161496a565b9050919050565b60006020820190508181036000830152614fa38161498d565b9050919050565b60006020820190508181036000830152614fc3816149b0565b9050919050565b60006020820190508181036000830152614fe3816149d3565b9050919050565b60006020820190508181036000830152615003816149f6565b9050919050565b6000602082019050818103600083015261502381614a19565b9050919050565b6000602082019050818103600083015261504381614a3c565b9050919050565b6000602082019050818103600083015261506381614a82565b9050919050565b6000602082019050818103600083015261508381614aa5565b9050919050565b6000610180820190506150a06000830184614ac8565b92915050565b60006020820190506150bb6000830184614bcd565b92915050565b60006150cb6150dc565b90506150d7828261547c565b919050565b6000604051905090565b600067ffffffffffffffff821115615101576151006156a8565b5b602082029050602081019050919050565b600067ffffffffffffffff82111561512d5761512c6156a8565b5b615136826156f5565b9050602081019050919050565b600067ffffffffffffffff82111561515e5761515d6156a8565b5b615167826156f5565b9050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b60006151fb8261538c565b91506152068361538c565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561523b5761523a61558e565b5b828201905092915050565b60006152518261538c565b915061525c8361538c565b92508261526c5761526b6155bd565b5b828204905092915050565b60006152828261538c565b915061528d8361538c565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156152c6576152c561558e565b5b828202905092915050565b60006152dc8261538c565b91506152e78361538c565b9250828210156152fa576152f961558e565b5b828203905092915050565b60006153108261536c565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061536782615bbd565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006153a1826153ba565b9050919050565b60006153b382615359565b9050919050565b60006153c5826153cc565b9050919050565b60006153d78261536c565b9050919050565b82818337600083830152505050565b60005b8381101561540b5780820151818401526020810190506153f0565b8381111561541a576000848401525b50505050565b600061542b8261538c565b9150600082141561543f5761543e61558e565b5b600182039050919050565b6000600282049050600182168061546257607f821691505b602082108114156154765761547561561b565b5b50919050565b615485826156f5565b810181811067ffffffffffffffff821117156154a4576154a36156a8565b5b80604052505050565b60006154b88261538c565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156154eb576154ea61558e565b5b600182019050919050565b600061550182615512565b9050919050565b6000819050919050565b600061551d82615706565b9050919050565b6000819050919050565b60006155398261538c565b91506155448361538c565b925082615554576155536155bd565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b50565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b60038110615bce57615bcd6155ec565b5b50565b615bda81615305565b8114615be557600080fd5b50565b615bf181615317565b8114615bfc57600080fd5b50565b615c088161532d565b8114615c1357600080fd5b50565b615c1f8161538c565b8114615c2a57600080fd5b5056fea264697066735822122009d11035e224d456653d3b88fb2d8bf786beafbfe72192b9ab49912b2bd1c48664736f6c634300080700330000000000000000000000000000000000000000000000000000000000006959c7b6f06e1d9d671518e2a41b937f4c13f46dc5e4ce9ceee0cbd4267c94d98ba800000000000000000000000018c4a85e52c23675f0a57cfa9a55e4d407654017c91445c29574411c6ba72be81edb6acd5d12a3418e2082b993f0e9c00a5bf3cc
Deployed Bytecode
0x60806040526004361061031e5760003560e01c8063580e77d4116101ab578063acedb5b4116100f7578063e13cbe3811610095578063f2fde38b1161006f578063f2fde38b14610ba7578063f51f96dd14610bd0578063f6b3a00a14610bfb578063fd5ad31914610c245761031f565b8063e13cbe3814610b14578063e985e9c514610b3f578063f2e45a4f14610b7c5761031f565b8063c57540b9116100d1578063c57540b914610a53578063c87b56dd14610a7e578063cb0274d514610abb578063d0f9e2be14610ad75761031f565b8063acedb5b4146109d6578063b88d4fde146109ff578063c040e6b814610a285761031f565b806378aafea2116101645780638da5cb5b1161013e5780638da5cb5b1461091a57806395d89b41146109455780639e34070f14610970578063a22cb465146109ad5761031f565b806378aafea2146108ba5780638a19c8bc146108c45780638ada6b0f146108ef5761031f565b8063580e77d4146107aa5780636352211e146107c157806364d34c11146107fe5780636e4ed7961461083b57806370a0823114610866578063715018a6146108a35761031f565b80632f745c591161026a57806342842e0e11610223578063473e3ea4116101fd578063473e3ea4146106ec5780634f6ccce7146107175780635533f19a1461075457806356c7627e1461077f5761031f565b806342842e0e1461066f578063469fc9241461069857806346feb24a146106c35761031f565b80632f745c5914610580578063305f7dbb146105bd57806339af9afe146105e85780633ad3bfc4146106115780633ccfd60b1461061b5780633d8d47ee146106325761031f565b8063150b7a02116102d757806326a67c91116102b157806326a67c91146104d657806327f70b0f14610513578063291e5fe01461053e5780632ae07c33146105555761031f565b8063150b7a021461044557806318160ddd1461048257806323b872dd146104ad5761031f565b806301ffc9a71461032157806306fdde031461035e578063081812fc14610389578063095ea7b3146103c65780630a212469146103ef578063130eb2f61461041a5761031f565b5b005b34801561032d57600080fd5b5061034860048036038101906103439190614578565b610c61565b6040516103559190614d52565b60405180910390f35b34801561036a57600080fd5b50610373610c73565b6040516103809190614e48565b60405180910390f35b34801561039557600080fd5b506103b060048036038101906103ab919061461b565b610d05565b6040516103bd9190614cc9565b60405180910390f35b3480156103d257600080fd5b506103ed60048036038101906103e891906144c2565b610d8a565b005b3480156103fb57600080fd5b50610404610ea2565b6040516104119190614d52565b60405180910390f35b34801561042657600080fd5b5061042f610ee0565b60405161043c9190614d52565b60405180910390f35b34801561045157600080fd5b5061046c600480360381019061046791906143ff565b610eec565b6040516104799190614df7565b60405180910390f35b34801561048e57600080fd5b50610497610f00565b6040516104a491906150a6565b60405180910390f35b3480156104b957600080fd5b506104d460048036038101906104cf91906143ac565b610f0d565b005b3480156104e257600080fd5b506104fd60048036038101906104f8919061454b565b610f6d565b60405161050a9190614d30565b60405180910390f35b34801561051f57600080fd5b50610528610f80565b6040516105359190614d52565b60405180910390f35b34801561054a57600080fd5b50610553610f99565b005b34801561056157600080fd5b5061056a611242565b60405161057791906150a6565b60405180910390f35b34801561058c57600080fd5b506105a760048036038101906105a291906144c2565b611248565b6040516105b491906150a6565b60405180910390f35b3480156105c957600080fd5b506105d26112ed565b6040516105df91906150a6565b60405180910390f35b3480156105f457600080fd5b5061060f600480360381019061060a9190614502565b6112fd565b005b6106196113bd565b005b34801561062757600080fd5b506106306115e0565b005b34801561063e57600080fd5b5061065960048036038101906106549190614482565b611728565b6040516106669190614d30565b60405180910390f35b34801561067b57600080fd5b50610696600480360381019061069191906143ac565b61187f565b005b3480156106a457600080fd5b506106ad61189f565b6040516106ba91906150a6565b60405180910390f35b3480156106cf57600080fd5b506106ea60048036038101906106e5919061461b565b611920565b005b3480156106f857600080fd5b50610701611b25565b60405161070e91906150a6565b60405180910390f35b34801561072357600080fd5b5061073e6004803603810190610739919061461b565b611b3c565b60405161074b91906150a6565b60405180910390f35b34801561076057600080fd5b50610769611bad565b60405161077691906150a6565b60405180910390f35b34801561078b57600080fd5b50610794611bb3565b6040516107a191906150a6565b60405180910390f35b3480156107b657600080fd5b506107bf611bd7565b005b3480156107cd57600080fd5b506107e860048036038101906107e3919061461b565b611d01565b6040516107f59190614cc9565b60405180910390f35b34801561080a57600080fd5b506108256004803603810190610820919061461b565b611db3565b6040516108329190614e48565b60405180910390f35b34801561084757600080fd5b50610850611eef565b60405161085d91906150a6565b60405180910390f35b34801561087257600080fd5b5061088d6004803603810190610888919061433f565b611ef4565b60405161089a91906150a6565b60405180910390f35b3480156108af57600080fd5b506108b8611fac565b005b6108c2612034565b005b3480156108d057600080fd5b506108d96121c0565b6040516108e691906150a6565b60405180910390f35b3480156108fb57600080fd5b506109046121c6565b6040516109119190614e12565b60405180910390f35b34801561092657600080fd5b5061092f6121ec565b60405161093c9190614cc9565b60405180910390f35b34801561095157600080fd5b5061095a612216565b6040516109679190614e48565b60405180910390f35b34801561097c57600080fd5b506109976004803603810190610992919061461b565b6122a8565b6040516109a49190614d52565b60405180910390f35b3480156109b957600080fd5b506109d460048036038101906109cf9190614482565b6122fe565b005b3480156109e257600080fd5b506109fd60048036038101906109f8919061461b565b612314565b005b348015610a0b57600080fd5b50610a266004803603810190610a2191906143ff565b6124dd565b005b348015610a3457600080fd5b50610a3d61253f565b604051610a4a9190614e2d565b60405180910390f35b348015610a5f57600080fd5b50610a68612552565b604051610a759190614d52565b60405180910390f35b348015610a8a57600080fd5b50610aa56004803603810190610aa0919061461b565b612573565b604051610ab29190614e48565b60405180910390f35b610ad56004803603810190610ad09190614648565b6126ce565b005b348015610ae357600080fd5b50610afe6004803603810190610af9919061461b565b61297b565b604051610b0b91906150a6565b60405180910390f35b348015610b2057600080fd5b50610b29612993565b604051610b3691906150a6565b60405180910390f35b348015610b4b57600080fd5b50610b666004803603810190610b61919061436c565b612999565b604051610b739190614d52565b60405180910390f35b348015610b8857600080fd5b50610b91612a2d565b604051610b9e919061508a565b60405180910390f35b348015610bb357600080fd5b50610bce6004803603810190610bc9919061433f565b612b54565b005b348015610bdc57600080fd5b50610be5612c4c565b604051610bf291906150a6565b60405180910390f35b348015610c0757600080fd5b50610c226004803603810190610c1d919061461b565b612c57565b005b348015610c3057600080fd5b50610c4b6004803603810190610c46919061461b565b612ca1565b604051610c589190614e48565b60405180910390f35b6000610c6c82612f62565b9050919050565b606060008054610c829061544a565b80601f0160208091040260200160405190810160405280929190818152602001828054610cae9061544a565b8015610cfb5780601f10610cd057610100808354040283529160200191610cfb565b820191906000526020600020905b815481529060010190602001808311610cde57829003601f168201915b5050505050905090565b6000610d1082612fdc565b610d4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d4690614fca565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610d9582611d01565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd9061502a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610e25613048565b73ffffffffffffffffffffffffffffffffffffffff161480610e545750610e5381610e4e613048565b612999565b5b610e93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e8a90614f4a565b60405180910390fd5b610e9d8383613050565b505050565b6000600b5442101580610edb57507f0000000000000000000000000000000000000000000000000000000000006959610ed9610f00565b145b905090565b60008060105411905090565b600063150b7a0260e01b9050949350505050565b6000600880549050905090565b610f1e610f18613048565b82613109565b610f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f549061504a565b60405180910390fd5b610f688383836131e7565b505050565b6060610f793383611728565b9050919050565b60006045601154610f9191906151f0565b431015905090565b610fa1610ee0565b610fd7576040517f8df38bf400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fdf610f80565b611015576040517f56cacac700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061101f6112ed565b9050600181141561105c576040517f0eeca4a400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000811415611097576040517fdf469ccb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060ff60456011546110aa91906151f0565b436110b591906152d1565b11156110e6576001604580436110cb9190615246565b6110d59190615277565b6110df91906152d1565b9050611104565b600160456011546110f791906151f0565b61110191906152d1565b90505b6000814060001c9050600081141561111f5761111e61555f565b5b4360118190555060136000815480929190611139906154ad565b9190505550600061114861189f565b90506000602067ffffffffffffffff811115611167576111666156a8565b5b6040519080825280601f01601f1916602001820160405280156111995781602001600182028036833780820191505090505b50905060005b8281101561121f5760008185019050806020840152600087848051906020012060001c6111cc919061552e565b905060006111da3083611248565b90506111fb30737039d65e346fdeebbc72514d718c88699c74ba4b836131e7565b888061120690615420565b9950505050508080611217906154ad565b91505061119f565b50600185141561123b57611234306000611248565b6012819055505b5050505050565b611b3981565b600061125383611ef4565b8210611294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128b90614e6a565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60006112f830611ef4565b905090565b611305612552565b61133b576040517ffd270db700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601481511115611377576040517f59a363c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81518110156113b9576113a682828151811061139957611398615679565b5b6020026020010151613443565b80806113b1906154ad565b91505061137a565b5050565b6002808111156113d0576113cf6155ec565b5b600a60159054906101000a900460ff1660028111156113f2576113f16155ec565b5b1415806114035750611402610ea2565b5b1561143a576040517f445dce4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600066f52322698080003461144f9190615246565b9050600081141561148c576040517fc755930f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601481111561149a57601490505b7f00000000000000000000000000000000000000000000000000000000000069596114c3610f00565b826114ce91906151f0565b111561150a576114dc610f00565b7f000000000000000000000000000000000000000000000000000000000000695961150791906152d1565b90505b60005b818110156115305761151d6134a3565b8080611528906154ad565b91505061150d565b506115396134bc565b60008166f523226980800061154e9190615277565b3461155991906152d1565b905060008111156115dc5760003373ffffffffffffffffffffffffffffffffffffffff168260405161158a90614c1f565b60006040518083038185875af1925050503d80600081146115c7576040519150601f19603f3d011682016040523d82523d6000602084013e6115cc565b606091505b50509050806115da57600080fd5b505b5050565b6115e8613048565b73ffffffffffffffffffffffffffffffffffffffff166116066121ec565b73ffffffffffffffffffffffffffffffffffffffff161461165c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165390614fea565b60405180910390fd5b611664610ee0565b1561169b576040517ff87a2c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600a60146101000a81548160ff0219169083151502179055506116be6121ec565b73ffffffffffffffffffffffffffffffffffffffff16476040516116e190614c1f565b60006040518083038185875af1925050503d806000811461171e576040519150601f19603f3d011682016040523d82523d6000602084013e611723565b606091505b505050565b60606000821561173a57309050611752565b737039d65e346fdeebbc72514d718c88699c74ba4b90505b600061175d82611ef4565b905060008167ffffffffffffffff81111561177b5761177a6156a8565b5b6040519080825280602002602001820160405280156117a95781602001602082028036833780820191505090505b5090506000805b8381101561186e5760006117c48683611248565b90508873ffffffffffffffffffffffffffffffffffffffff166014600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561185a578084848061183a906154ad565b95508151811061184d5761184c615679565b5b6020026020010181815250505b508080611866906154ad565b9150506117b0565b508082528194505050505092915050565b61189a838383604051806020016040528060008152506124dd565b505050565b6000806118aa6112ed565b905060008114156118bf57600091505061191d565b6000600190506107d082106118f25760006103e8836118de91906152d1565b90506101f4816118ee9190615246565b9150505b8181106119095760018261190691906152d1565b90505b603281111561191757603290505b80925050505b90565b3373ffffffffffffffffffffffffffffffffffffffff166014600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119b8576040517f81e1388300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006119c26112ed565b9050600181141580156119d957506119d8610f80565b5b15611a10576040517f7a8d10d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000601354905060006013541415611a54576040517fa77f4ebc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060156000858152602001908152602001600020819055506014600084815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560008247611ab09190615246565b9050611abd3033866131e7565b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611b03573d6000803e3d6000fd5b506002831415611b1f57611b18306000611248565b6012819055505b50505050565b6000611b39601054611b3791906151f0565b905090565b6000611b46610f00565b8210611b87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7e9061506a565b60405180910390fd5b60088281548110611b9b57611b9a615679565b5b90600052602060002001549050919050565b600b5481565b7f000000000000000000000000000000000000000000000000000000000000695981565b611bdf613048565b73ffffffffffffffffffffffffffffffffffffffff16611bfd6121ec565b73ffffffffffffffffffffffffffffffffffffffff1614611c53576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4a90614fea565b60405180910390fd5b60016002811115611c6757611c666155ec565b5b600a60159054906101000a900460ff166002811115611c8957611c886155ec565b5b14611cc0576040517f34e6c21f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600a60156101000a81548160ff02191690836002811115611ce657611ce56155ec565b5b0217905550610e1042611cf991906151f0565b600b81905550565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611daa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da190614f8a565b60405180910390fd5b80915050919050565b606081611dbf81612fdc565b611df5576040517f9430a17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637fb7eac060006002811115611e4757611e466155ec565b5b600a60159054906101000a900460ff166002811115611e6957611e686155ec565b5b1485611e74876134d5565b6040518463ffffffff1660e01b8152600401611e9293929190614d6d565b60006040518083038186803b158015611eaa57600080fd5b505afa158015611ebe573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611ee791906145d2565b915050919050565b604581565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611f65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5c90614f6a565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611fb4613048565b73ffffffffffffffffffffffffffffffffffffffff16611fd26121ec565b73ffffffffffffffffffffffffffffffffffffffff1614612028576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201f90614fea565b60405180910390fd5b612032600061350c565b565b61203c613048565b73ffffffffffffffffffffffffffffffffffffffff1661205a6121ec565b73ffffffffffffffffffffffffffffffffffffffff16146120b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a790614fea565b60405180910390fd5b600060028111156120c4576120c36155ec565b5b600a60159054906101000a900460ff1660028111156120e6576120e56155ec565b5b1461211d576040517f1b44f83200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612125610ee0565b1561215c576040517ff87a2c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a60149054906101000a900460ff16156121a3576040517f61865db000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b43601081905550611b39436121b891906151f0565b601181905550565b60135481565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600180546122259061544a565b80601f01602080910402602001604051908101604052809291908181526020018280546122519061544a565b801561229e5780601f106122735761010080835404028352916020019161229e565b820191906000526020600020905b81548152906001019060200180831161228157829003601f168201915b5050505050905090565b600080610100836122b99190615246565b90506000610100846122cb919061552e565b90506000600c60008481526020019081526020016000205490506000826001901b90508081831614945050505050919050565b612310612309613048565b83836135d2565b5050565b61231c613048565b73ffffffffffffffffffffffffffffffffffffffff1661233a6121ec565b73ffffffffffffffffffffffffffffffffffffffff1614612390576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161238790614fea565b60405180910390fd5b6002808111156123a3576123a26155ec565b5b600a60159054906101000a900460ff1660028111156123c5576123c46155ec565b5b146123fc576040517fc6940a8600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612404610ea2565b61243a576040517ff1da374500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d548160405160200161244e9190614c34565b6040516020818303038152906040528051906020012060001c1461249e576040517f9ea6d12700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e548118600d81905550600e600090556000600a60156101000a81548160ff021916908360028111156124d5576124d46155ec565b5b021790555050565b6124ee6124e8613048565b83613109565b61252d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125249061504a565b60405180910390fd5b6125398484848461373f565b50505050565b600a60159054906101000a900460ff1681565b600061255c610ee0565b801561256e575061256b611b25565b43105b905090565b60608161257f81612fdc565b6125b5576040517f9430a17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f7db218c60006002811115612607576126066155ec565b5b600a60159054906101000a900460ff166002811115612629576126286155ec565b5b1485612634876134d5565b601560008981526020019081526020016000205461265189611d01565b6040518663ffffffff1660e01b8152600401612671959493929190614da4565b60006040518083038186803b15801561268957600080fd5b505afa15801561269d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906126c691906145d2565b915050919050565b600160028111156126e2576126e16155ec565b5b600a60159054906101000a900460ff166002811115612704576127036155ec565b5b1461273b576040517f34e6c21f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612744866122a8565b1561277b576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008114156127b6576040517f843ce46b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084866127c491906151f0565b905080821115612800576040517f843ce46b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008683111561281957868361281691906152d1565b90505b66f52322698080008161282c9190615277565b341015612865576040517fc23e2d6200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008833898960405160200161287e9493929190614c4f565b604051602081830303815290604052805190602001209050612902868680806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050507fc91445c29574411c6ba72be81edb6acd5d12a3418e2082b993f0e9c00a5bf3cc8361379b565b612938576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612941896137b2565b60005b84811015612967576129546134a3565b808061295f906154ad565b915050612944565b506129706134bc565b505050505050505050565b60156020528060005260406000206000915090505481565b610e1081565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b612a35614099565b612a52737039d65e346fdeebbc72514d718c88699c74ba4b611ef4565b816000018181525050612a6430611ef4565b81602001818152505060135481604001818152505047816060018181525050612a8b61189f565b8160800181815250506012548160c0018181525050612aa8611b25565b8160e0018181525050612ab9610f80565b612ae157436045601154612acd91906151f0565b612ad791906152d1565b8160a00181815250505b612ae9610f80565b81610100019015159081151581525050612b01612552565b81610120019015159081151581525050612b19610ee0565b816101400190151590811515815250508060e0015143118015612b4157506001816020015111155b8161016001901515908115158152505090565b612b5c613048565b73ffffffffffffffffffffffffffffffffffffffff16612b7a6121ec565b73ffffffffffffffffffffffffffffffffffffffff1614612bd0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bc790614fea565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612c40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c3790614eaa565b60405180910390fd5b612c498161350c565b50565b66f523226980800081565b612c5f612552565b612c95576040517ffd270db700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c9e81613443565b50565b606081612cad81612fdc565b612ce3576040517f9430a17e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003073ffffffffffffffffffffffffffffffffffffffff16612d0585611d01565b73ffffffffffffffffffffffffffffffffffffffff161415612d2b576013549050612d42565b601560008581526020019081526020016000205490505b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a98edced60006002811115612d9457612d936155ec565b5b600a60159054906101000a900460ff166002811115612db657612db56155ec565b5b1486612dc1886134d5565b85612dcb8a611d01565b6040518663ffffffff1660e01b8152600401612deb959493929190614da4565b60006040518083038186803b158015612e0357600080fd5b505afa158015612e17573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612e4091906145d2565b92505050919050565b612e54838383612f5d565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612e9757612e928161380c565b612ed6565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612ed557612ed48382613855565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612f1957612f14816139c2565b612f58565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612f5757612f568282613a93565b5b5b505050565b505050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612fd55750612fd482613b12565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166130c383611d01565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061311482612fdc565b613153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161314a90614f2a565b60405180910390fd5b600061315e83611d01565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806131cd57508373ffffffffffffffffffffffffffffffffffffffff166131b584610d05565b73ffffffffffffffffffffffffffffffffffffffff16145b806131de57506131dd8185612999565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661320782611d01565b73ffffffffffffffffffffffffffffffffffffffff161461325d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132549061500a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156132cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132c490614eea565b60405180910390fd5b6132d8838383613bf4565b6132e3600082613050565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461333391906152d1565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461338a91906151f0565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b61344e333083610f0d565b336014600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60006134ad610f00565b90506134b93382613c04565b50565b600143034060001c600e60008282540192505081905550565b6000600d54826040516020016134ec929190614c9d565b6040516020818303038152906040528051906020012060001c9050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161363890614f0a565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516137329190614d52565b60405180910390a3505050565b61374a8484846131e7565b61375684848484613dd2565b613795576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161378c90614e8a565b60405180910390fd5b50505050565b6000826137a88584613f69565b1490509392505050565b6000610100826137c29190615246565b90506000610100836137d4919061552e565b9050806001901b600c60008481526020019081526020016000205417600c600084815260200190815260200160002081905550505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161386284611ef4565b61386c91906152d1565b9050600060076000848152602001908152602001600020549050818114613951576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b600060016008805490506139d691906152d1565b9050600060096000848152602001908152602001600020549050600060088381548110613a0657613a05615679565b5b906000526020600020015490508060088381548110613a2857613a27615679565b5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480613a7757613a7661564a565b5b6001900381819060005260206000200160009055905550505050565b6000613a9e83611ef4565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480613bdd57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80613bed5750613bec8261401c565b5b9050919050565b613bff838383612e49565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613c74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c6b90614faa565b60405180910390fd5b613c7d81612fdc565b15613cbd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cb490614eca565b60405180910390fd5b613cc960008383613bf4565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613d1991906151f0565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b6000613df38473ffffffffffffffffffffffffffffffffffffffff16614086565b15613f5c578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613e1c613048565b8786866040518563ffffffff1660e01b8152600401613e3e9493929190614ce4565b602060405180830381600087803b158015613e5857600080fd5b505af1925050508015613e8957506040513d601f19601f82011682018060405250810190613e8691906145a5565b60015b613f0c573d8060008114613eb9576040519150601f19603f3d011682016040523d82523d6000602084013e613ebe565b606091505b50600081511415613f04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613efb90614e8a565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613f61565b600190505b949350505050565b60008082905060005b8451811015614011576000858281518110613f9057613f8f615679565b5b60200260200101519050808311613fd1578281604051602001613fb4929190614bf3565b604051602081830303815290604052805190602001209250613ffd565b8083604051602001613fe4929190614bf3565b6040516020818303038152906040528051906020012092505b508080614009906154ad565b915050613f72565b508091505092915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600080823b905060008111915050919050565b60405180610180016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581526020016000151581526020016000151581525090565b6000614115614110846150e6565b6150c1565b90508083825260208201905082856020860282011115614138576141376156e1565b5b60005b85811015614168578161414e888261432a565b84526020840193506020830192505060018101905061413b565b5050509392505050565b600061418561418084615112565b6150c1565b9050828152602081018484840111156141a1576141a06156e6565b5b6141ac8482856153de565b509392505050565b60006141c76141c284615143565b6150c1565b9050828152602081018484840111156141e3576141e26156e6565b5b6141ee8482856153ed565b509392505050565b60008135905061420581615bd1565b92915050565b60008083601f840112614221576142206156dc565b5b8235905067ffffffffffffffff81111561423e5761423d6156d7565b5b60208301915083602082028301111561425a576142596156e1565b5b9250929050565b600082601f830112614276576142756156dc565b5b8135614286848260208601614102565b91505092915050565b60008135905061429e81615be8565b92915050565b6000813590506142b381615bff565b92915050565b6000815190506142c881615bff565b92915050565b600082601f8301126142e3576142e26156dc565b5b81356142f3848260208601614172565b91505092915050565b600082601f830112614311576143106156dc565b5b81516143218482602086016141b4565b91505092915050565b60008135905061433981615c16565b92915050565b600060208284031215614355576143546156f0565b5b6000614363848285016141f6565b91505092915050565b60008060408385031215614383576143826156f0565b5b6000614391858286016141f6565b92505060206143a2858286016141f6565b9150509250929050565b6000806000606084860312156143c5576143c46156f0565b5b60006143d3868287016141f6565b93505060206143e4868287016141f6565b92505060406143f58682870161432a565b9150509250925092565b60008060008060808587031215614419576144186156f0565b5b6000614427878288016141f6565b9450506020614438878288016141f6565b93505060406144498782880161432a565b925050606085013567ffffffffffffffff81111561446a576144696156eb565b5b614476878288016142ce565b91505092959194509250565b60008060408385031215614499576144986156f0565b5b60006144a7858286016141f6565b92505060206144b88582860161428f565b9150509250929050565b600080604083850312156144d9576144d86156f0565b5b60006144e7858286016141f6565b92505060206144f88582860161432a565b9150509250929050565b600060208284031215614518576145176156f0565b5b600082013567ffffffffffffffff811115614536576145356156eb565b5b61454284828501614261565b91505092915050565b600060208284031215614561576145606156f0565b5b600061456f8482850161428f565b91505092915050565b60006020828403121561458e5761458d6156f0565b5b600061459c848285016142a4565b91505092915050565b6000602082840312156145bb576145ba6156f0565b5b60006145c9848285016142b9565b91505092915050565b6000602082840312156145e8576145e76156f0565b5b600082015167ffffffffffffffff811115614606576146056156eb565b5b614612848285016142fc565b91505092915050565b600060208284031215614631576146306156f0565b5b600061463f8482850161432a565b91505092915050565b60008060008060008060a08789031215614665576146646156f0565b5b600061467389828a0161432a565b965050602061468489828a0161432a565b955050604061469589828a0161432a565b945050606087013567ffffffffffffffff8111156146b6576146b56156eb565b5b6146c289828a0161420b565b935093505060806146d589828a0161432a565b9150509295509295509295565b60006146ee8383614bbe565b60208301905092915050565b61470381615305565b82525050565b61471a61471582615305565b6154f6565b82525050565b600061472b82615184565b61473581856151b2565b935061474083615174565b8060005b8381101561477157815161475888826146e2565b9750614763836151a5565b925050600181019050614744565b5085935050505092915050565b61478781615317565b82525050565b61479681615317565b82525050565b6147ad6147a882615323565b615508565b82525050565b6147bc8161532d565b82525050565b60006147cd8261518f565b6147d781856151c3565b93506147e78185602086016153ed565b6147f0816156f5565b840191505092915050565b61480481615396565b82525050565b614813816153a8565b82525050565b60006148248261519a565b61482e81856151df565b935061483e8185602086016153ed565b614847816156f5565b840191505092915050565b600061485f602b836151df565b915061486a82615713565b604082019050919050565b60006148826032836151df565b915061488d82615762565b604082019050919050565b60006148a56026836151df565b91506148b0826157b1565b604082019050919050565b60006148c8601c836151df565b91506148d382615800565b602082019050919050565b60006148eb6024836151df565b91506148f682615829565b604082019050919050565b600061490e6019836151df565b915061491982615878565b602082019050919050565b6000614931602c836151df565b915061493c826158a1565b604082019050919050565b60006149546038836151df565b915061495f826158f0565b604082019050919050565b6000614977602a836151df565b91506149828261593f565b604082019050919050565b600061499a6029836151df565b91506149a58261598e565b604082019050919050565b60006149bd6020836151df565b91506149c8826159dd565b602082019050919050565b60006149e0602c836151df565b91506149eb82615a06565b604082019050919050565b6000614a036020836151df565b9150614a0e82615a55565b602082019050919050565b6000614a266029836151df565b9150614a3182615a7e565b604082019050919050565b6000614a496021836151df565b9150614a5482615acd565b604082019050919050565b6000614a6c6000836151d4565b9150614a7782615b1c565b600082019050919050565b6000614a8f6031836151df565b9150614a9a82615b1f565b604082019050919050565b6000614ab2602c836151df565b9150614abd82615b6e565b604082019050919050565b61018082016000820151614adf6000850182614bbe565b506020820151614af26020850182614bbe565b506040820151614b056040850182614bbe565b506060820151614b186060850182614bbe565b506080820151614b2b6080850182614bbe565b5060a0820151614b3e60a0850182614bbe565b5060c0820151614b5160c0850182614bbe565b5060e0820151614b6460e0850182614bbe565b50610100820151614b7961010085018261477e565b50610120820151614b8e61012085018261477e565b50610140820151614ba361014085018261477e565b50610160820151614bb861016085018261477e565b50505050565b614bc78161538c565b82525050565b614bd68161538c565b82525050565b614bed614be88261538c565b615524565b82525050565b6000614bff828561479c565b602082019150614c0f828461479c565b6020820191508190509392505050565b6000614c2a82614a5f565b9150819050919050565b6000614c408284614bdc565b60208201915081905092915050565b6000614c5b8287614bdc565b602082019150614c6b8286614709565b601482019150614c7b8285614bdc565b602082019150614c8b8284614bdc565b60208201915081905095945050505050565b6000614ca98285614bdc565b602082019150614cb98284614bdc565b6020820191508190509392505050565b6000602082019050614cde60008301846146fa565b92915050565b6000608082019050614cf960008301876146fa565b614d0660208301866146fa565b614d136040830185614bcd565b8181036060830152614d2581846147c2565b905095945050505050565b60006020820190508181036000830152614d4a8184614720565b905092915050565b6000602082019050614d67600083018461478d565b92915050565b6000606082019050614d82600083018661478d565b614d8f6020830185614bcd565b614d9c6040830184614bcd565b949350505050565b600060a082019050614db9600083018861478d565b614dc66020830187614bcd565b614dd36040830186614bcd565b614de06060830185614bcd565b614ded60808301846146fa565b9695505050505050565b6000602082019050614e0c60008301846147b3565b92915050565b6000602082019050614e2760008301846147fb565b92915050565b6000602082019050614e42600083018461480a565b92915050565b60006020820190508181036000830152614e628184614819565b905092915050565b60006020820190508181036000830152614e8381614852565b9050919050565b60006020820190508181036000830152614ea381614875565b9050919050565b60006020820190508181036000830152614ec381614898565b9050919050565b60006020820190508181036000830152614ee3816148bb565b9050919050565b60006020820190508181036000830152614f03816148de565b9050919050565b60006020820190508181036000830152614f2381614901565b9050919050565b60006020820190508181036000830152614f4381614924565b9050919050565b60006020820190508181036000830152614f6381614947565b9050919050565b60006020820190508181036000830152614f838161496a565b9050919050565b60006020820190508181036000830152614fa38161498d565b9050919050565b60006020820190508181036000830152614fc3816149b0565b9050919050565b60006020820190508181036000830152614fe3816149d3565b9050919050565b60006020820190508181036000830152615003816149f6565b9050919050565b6000602082019050818103600083015261502381614a19565b9050919050565b6000602082019050818103600083015261504381614a3c565b9050919050565b6000602082019050818103600083015261506381614a82565b9050919050565b6000602082019050818103600083015261508381614aa5565b9050919050565b6000610180820190506150a06000830184614ac8565b92915050565b60006020820190506150bb6000830184614bcd565b92915050565b60006150cb6150dc565b90506150d7828261547c565b919050565b6000604051905090565b600067ffffffffffffffff821115615101576151006156a8565b5b602082029050602081019050919050565b600067ffffffffffffffff82111561512d5761512c6156a8565b5b615136826156f5565b9050602081019050919050565b600067ffffffffffffffff82111561515e5761515d6156a8565b5b615167826156f5565b9050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b60006151fb8261538c565b91506152068361538c565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561523b5761523a61558e565b5b828201905092915050565b60006152518261538c565b915061525c8361538c565b92508261526c5761526b6155bd565b5b828204905092915050565b60006152828261538c565b915061528d8361538c565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156152c6576152c561558e565b5b828202905092915050565b60006152dc8261538c565b91506152e78361538c565b9250828210156152fa576152f961558e565b5b828203905092915050565b60006153108261536c565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061536782615bbd565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006153a1826153ba565b9050919050565b60006153b382615359565b9050919050565b60006153c5826153cc565b9050919050565b60006153d78261536c565b9050919050565b82818337600083830152505050565b60005b8381101561540b5780820151818401526020810190506153f0565b8381111561541a576000848401525b50505050565b600061542b8261538c565b9150600082141561543f5761543e61558e565b5b600182039050919050565b6000600282049050600182168061546257607f821691505b602082108114156154765761547561561b565b5b50919050565b615485826156f5565b810181811067ffffffffffffffff821117156154a4576154a36156a8565b5b80604052505050565b60006154b88261538c565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156154eb576154ea61558e565b5b600182019050919050565b600061550182615512565b9050919050565b6000819050919050565b600061551d82615706565b9050919050565b6000819050919050565b60006155398261538c565b91506155448361538c565b925082615554576155536155bd565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b50565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b60038110615bce57615bcd6155ec565b5b50565b615bda81615305565b8114615be557600080fd5b50565b615bf181615317565b8114615bfc57600080fd5b50565b615c088161532d565b8114615c1357600080fd5b50565b615c1f8161538c565b8114615c2a57600080fd5b5056fea264697066735822122009d11035e224d456653d3b88fb2d8bf786beafbfe72192b9ab49912b2bd1c48664736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000006959c7b6f06e1d9d671518e2a41b937f4c13f46dc5e4ce9ceee0cbd4267c94d98ba800000000000000000000000018c4a85e52c23675f0a57cfa9a55e4d407654017c91445c29574411c6ba72be81edb6acd5d12a3418e2082b993f0e9c00a5bf3cc
-----Decoded View---------------
Arg [0] : _tokenLimit (uint256): 26969
Arg [1] : _secretCommit (uint256): 90333482421695848515465926835468518679924540404336990496885294470248321878952
Arg [2] : _renderer (address): 0x18c4a85E52c23675F0a57Cfa9a55e4d407654017
Arg [3] : _merkleRoot (bytes32): 0xc91445c29574411c6ba72be81edb6acd5d12a3418e2082b993f0e9c00a5bf3cc
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000006959
Arg [1] : c7b6f06e1d9d671518e2a41b937f4c13f46dc5e4ce9ceee0cbd4267c94d98ba8
Arg [2] : 00000000000000000000000018c4a85e52c23675f0a57cfa9a55e4d407654017
Arg [3] : c91445c29574411c6ba72be81edb6acd5d12a3418e2082b993f0e9c00a5bf3cc
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.