Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 41 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Renounce Ownersh... | 19609902 | 712 days ago | IN | 0 ETH | 0.00051708 | ||||
| Approve | 19588930 | 715 days ago | IN | 0 ETH | 0.00042133 | ||||
| Approve | 19588897 | 715 days ago | IN | 0 ETH | 0.00041023 | ||||
| Approve | 19588870 | 715 days ago | IN | 0 ETH | 0.00042386 | ||||
| Approve | 19588836 | 715 days ago | IN | 0 ETH | 0.00039664 | ||||
| Approve | 19588804 | 715 days ago | IN | 0 ETH | 0.00038626 | ||||
| Approve | 19588796 | 715 days ago | IN | 0 ETH | 0.0004094 | ||||
| Approve | 19588792 | 715 days ago | IN | 0 ETH | 0.00038851 | ||||
| Set ERC721Transf... | 19588759 | 715 days ago | IN | 0 ETH | 0.00082838 | ||||
| Transfer | 19588753 | 715 days ago | IN | 0 ETH | 0.00294184 | ||||
| Approve | 19588719 | 715 days ago | IN | 0 ETH | 0.00042569 | ||||
| Approve | 19588620 | 715 days ago | IN | 0 ETH | 0.0004817 | ||||
| Approve | 19588561 | 715 days ago | IN | 0 ETH | 0.00049607 | ||||
| Set Approval For... | 19588555 | 715 days ago | IN | 0 ETH | 0.00087346 | ||||
| Approve | 19588543 | 715 days ago | IN | 0 ETH | 0.00050327 | ||||
| Approve | 19588516 | 715 days ago | IN | 0 ETH | 0.00063769 | ||||
| Approve | 19588513 | 715 days ago | IN | 0 ETH | 0.00068407 | ||||
| Set Custom Ratio | 19588304 | 715 days ago | IN | 0 ETH | 0.00069591 | ||||
| Set Custom Ratio | 19588286 | 715 days ago | IN | 0 ETH | 0.00034536 | ||||
| Set ERC721Transf... | 19588283 | 715 days ago | IN | 0 ETH | 0.00043032 | ||||
| Set Continue Evo... | 19580573 | 716 days ago | IN | 0 ETH | 0.00077972 | ||||
| Set Pause Evolut... | 19580570 | 716 days ago | IN | 0 ETH | 0.00080673 | ||||
| Set Pause Evolut... | 19574738 | 717 days ago | IN | 0 ETH | 0.0010506 | ||||
| Transfer | 19574730 | 717 days ago | IN | 0 ETH | 0.00494478 | ||||
| Set Custom Ratio | 19573063 | 717 days ago | IN | 0 ETH | 0.00060606 |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Pokemoon
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {ERC404} from "./ERC404.sol";
contract Pokemoon is Ownable, ERC404 {
string public dataURI;
string public baseTokenURI;
string private constant evo1Path = "evo1/";
string private constant evo2Path1 = "evo2/1/";
string private constant evo2Path2 = "evo2/2/";
string private constant evo3Path1 = "evo3/1/";
string private constant evo3Path2 = "evo3/2/";
string private constant evo3Path3 = "evo3/3/";
string private constant evo4Path1 = "evo4/1/";
string private constant evo4Path2 = "evo4/2/";
string private constant evo4Path3 = "evo4/3/";
string private constant evo4Path4 = "evo4/4/";
string private constant evo5Path1 = "evo5/1/";
string private constant evo5Path2 = "evo5/2/";
string private constant evo5Path3 = "evo5/3/";
string private constant evo5Path4 = "evo5/4/";
string private constant evo5Path5 = "evo5/5/";
string private constant evo9Path1 = "evo9/1/";
string private constant evo9Path2 = "evo9/2/";
string private constant evo9Path3 = "evo9/3/";
string private constant evo9Path4 = "evo9/4/";
string private constant evo9Path5 = "evo9/5/";
string private constant evo9Path6 = "evo9/6/";
string private constant evo9Path7 = "evo9/7/";
string private constant evo9Path8 = "evo9/8/";
string private constant evo9Path9 = "evo9/9/";
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
uint256 maxTotalSupplyERC721_,
address initialOwner_,
address initialMintRecipient_
)
ERC404(name_, symbol_, decimals_) Ownable(initialOwner_)
{
// Do not mint the ERC721s to the initial owner, as it's a waste of gas.
_setERC721TransferExempt(initialMintRecipient_, true);
_mintERC20(initialMintRecipient_, maxTotalSupplyERC721_ * units);
}
function setDataURI(string memory _dataURI) public onlyOwner {
dataURI = _dataURI;
}
function setTokenURI(string memory _tokenURI) public onlyOwner {
baseTokenURI = _tokenURI;
}
function tokenURI(uint256 id_) public view override returns (string memory) {
if (bytes(baseTokenURI).length > 0) {
return string.concat(baseTokenURI, Strings.toString(id_));
} else {
uint8 seed = uint8(bytes1(keccak256(abi.encodePacked(id_))));
string memory folderPath;
string memory jsonFileName;
uint256 lastTransferTimestamp = _getERC721LastTransferTimestamp(id_);
if (seed <= 100) {
folderPath = evo1Path;
jsonFileName = string.concat(Strings.toString((id_ % 203) + 1), ".json");
} else if (seed <= 160) {
folderPath = getEvo2Path(lastTransferTimestamp, id_);
jsonFileName = string.concat(Strings.toString((id_ % 213) + 1), ".json");
} else if (seed <= 210) {
folderPath = getEvo3Path(lastTransferTimestamp, id_);
jsonFileName = string.concat(Strings.toString((id_ % 117) + 1), ".json");
} else if (seed <= 235) {
folderPath = getEvo4Path(lastTransferTimestamp, id_);
jsonFileName = string.concat(Strings.toString((id_ % 5) + 1), ".json");
} else if (seed <= 250) {
folderPath = getEvo5Path(lastTransferTimestamp, id_);
jsonFileName = string.concat(Strings.toString((id_ % 2) + 1), ".json");
} else if (seed <= 255) {
folderPath = getEvo9Path(lastTransferTimestamp, id_);
jsonFileName = "1.json";
}
string memory fullURI = string.concat(dataURI, folderPath, jsonFileName);
return fullURI;
}
}
function getEvo2Path(uint256 lastTransferTimestamp, uint256 id_) internal view returns (string memory) {
uint256 evolutionTime = block.timestamp - lastTransferTimestamp - getTimeSpentOnPause(id_);
if (evolutionTime >= 7 days) {
return evo2Path2;
} else {
return evo2Path1;
}
}
function getEvo3Path(uint256 lastTransferTimestamp, uint256 id_) internal view returns (string memory) {
uint256 evolutionTime = block.timestamp - lastTransferTimestamp - getTimeSpentOnPause(id_);
if (evolutionTime >= 14 days) {
return evo3Path3;
} else if (evolutionTime >= 7 days) {
return evo3Path2;
} else {
return evo3Path1;
}
}
function getEvo4Path(uint256 lastTransferTimestamp, uint256 id_) internal view returns (string memory) {
uint256 evolutionTime = block.timestamp - lastTransferTimestamp - getTimeSpentOnPause(id_);
if (evolutionTime >= 21 days) {
return evo4Path4;
} else if (evolutionTime >= 14 days) {
return evo4Path3;
} else if (evolutionTime >= 7 days) {
return evo4Path2;
} else {
return evo4Path1;
}
}
function getEvo5Path(uint256 lastTransferTimestamp, uint256 id_) internal view returns (string memory) {
uint256 evolutionTime = block.timestamp - lastTransferTimestamp - getTimeSpentOnPause(id_);
if (evolutionTime >= 28 days) {
return evo5Path5;
} else if (evolutionTime >= 21 days) {
return evo5Path4;
} else if (evolutionTime >= 14 days) {
return evo5Path3;
} else if (evolutionTime >= 7 days) {
return evo5Path2;
} else {
return evo5Path1;
}
}
function getEvo9Path(uint256 lastTransferTimestamp, uint256 id_) internal view returns (string memory) {
uint256 evolutionTime = block.timestamp - lastTransferTimestamp - getTimeSpentOnPause(id_);
if (evolutionTime >= 56 days) {
return evo9Path9;
} else if (evolutionTime >= 49 days) {
return evo9Path8;
} else if (evolutionTime >= 42 days) {
return evo9Path7;
} else if (evolutionTime >= 35 days) {
return evo9Path6;
} else if (evolutionTime >= 28 days) {
return evo9Path5;
} else if (evolutionTime >= 21 days) {
return evo9Path4;
} else if (evolutionTime >= 14 days) {
return evo9Path3;
} else if (evolutionTime >= 7 days) {
return evo9Path2;
} else {
return evo9Path1;
}
}
function setERC721TransferExempt(address account_, bool value_) external onlyOwner {
_setERC721TransferExempt(account_, value_);
}
// Function for replacing the customRatio value, which determines the ratio of transmitted ERC20/ERC721
function setCustomRatio(uint256 newRatio) external onlyOwner {
customRatio = newRatio;
}
function getTimeUntilNextEvolution(uint256 id_) external view returns (uint256) {
uint256 lastTransferTimestamp = _getERC721LastTransferTimestamp(id_);
uint256 evolutionTime = block.timestamp - lastTransferTimestamp - getTimeSpentOnPause(id_);
uint256 evolutionInterval = 7 days;
if (getPauseEvolutionTime(id_) > 0) {
return 11; // Special code indicating pause
}
if (containsSubstring(tokenURI(id_), evo1Path)) {
return 13; // Special code indicating Not Evo
} else if (containsSubstring(tokenURI(id_), evo2Path2)) {
return 12; // Special code indicating evo2Path2
} else if (containsSubstring(tokenURI(id_), evo3Path3)) {
return 12; // Special code indicating evo3Path3
} else if (containsSubstring(tokenURI(id_), evo4Path4)) {
return 12; // Special code indicating evo4Path4
} else if (containsSubstring(tokenURI(id_), evo5Path5)) {
return 12; // Special code indicating evo5Path5
} else if (containsSubstring(tokenURI(id_), evo9Path9)) {
return 12; // Special code indicating evo9Path9
}
uint256 timeRemaining = (evolutionInterval - (evolutionTime) % evolutionInterval) / 1 days;
return timeRemaining;
}
}//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IERC721Receiver} from "@openzeppelin/contracts/interfaces/IERC721Receiver.sol";
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
import {IERC404} from "./interfaces/IERC404.sol";
import {DoubleEndedQueue} from "./lib/DoubleEndedQueue.sol";
import {ERC721Events} from "./lib/ERC721Events.sol";
import {ERC20Events} from "./lib/ERC20Events.sol";
abstract contract ERC404 is IERC404 {
using DoubleEndedQueue for DoubleEndedQueue.Uint256Deque;
/// @dev The queue of ERC-721 tokens stored in the contract.
DoubleEndedQueue.Uint256Deque private _storedERC721Ids;
/// @dev Token name
string public name;
/// @dev Token symbol
string public symbol;
/// @dev Decimals for ERC-20 representation
uint8 public immutable decimals;
/// @dev Units for ERC-20 representation
uint256 public immutable units;
/// @dev Total supply in ERC-20 representation
uint256 public totalSupply;
/// @dev Current mint counter which also represents the highest
/// minted id, monotonically increasing to ensure accurate ownership
uint256 public minted;
/// @dev Initial chain id for EIP-2612 support
uint256 internal immutable _INITIAL_CHAIN_ID;
/// @dev Initial domain separator for EIP-2612 support
bytes32 internal immutable _INITIAL_DOMAIN_SEPARATOR;
/// @dev Balance of user in ERC-20 representation
mapping(address => uint256) public balanceOf;
/// @dev Allowance of user in ERC-20 representation
mapping(address => mapping(address => uint256)) public allowance;
/// @dev Approval in ERC-721 representaion
mapping(uint256 => address) public getApproved;
/// @dev Approval for all in ERC-721 representation
mapping(address => mapping(address => bool)) public isApprovedForAll;
/// @dev Packed representation of ownerOf and owned indices
mapping(uint256 => uint256) internal _ownedData;
/// @dev Array of owned ids in ERC-721 representation
mapping(address => uint256[]) internal _owned;
/// @dev Addresses that are exempt from ERC-721 transfer, typically for gas savings (pairs, routers, etc)
mapping(address => bool) internal _erc721TransferExempt;
/// @dev EIP-2612 nonces
mapping(address => uint256) public nonces;
// Mapping to store the last transfer time for each token
mapping(uint256 => uint256) private lastTransferTimestamp;
// Event for logging the update of the time of the last transfer
event TokenTransferWithTimestampUpdated(uint256 id_, uint256 timestamp);
/// @dev Address bitmask for packed ownership data
uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;
/// @dev Owned index bitmask for packed ownership data
uint256 private constant _BITMASK_OWNED_INDEX = ((1 << 96) - 1) << 160;
/// @dev Constant for token id encoding
uint256 public constant ID_ENCODING_PREFIX = (1 << 255);
uint256 public customRatio;
mapping(uint256 => uint256) private pauseEvolutionTime;
mapping(uint256 => uint256) private continueEvolution;
mapping(uint256 => uint256) private timeOnPause;
event EvolutionPaused(uint256 id_, uint256 timestamp);
event EvolutionContinued(uint256 id_, uint256 timestamp);
constructor(string memory name_, string memory symbol_, uint8 decimals_) {
name = name_;
symbol = symbol_;
if (decimals_ < 18) {
revert DecimalsTooLow();
}
decimals = decimals_;
units = 10 ** decimals;
// EIP-2612 initialization
_INITIAL_CHAIN_ID = block.chainid;
_INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator();
}
/// @notice Function to find owner of a given ERC-721 token
function ownerOf(
uint256 id_
) public view virtual returns (address erc721Owner) {
erc721Owner = _getOwnerOf(id_);
if (!_isValidTokenId(id_)) {
revert InvalidTokenId();
}
if (erc721Owner == address(0)) {
revert NotFound();
}
}
function owned(
address owner_
) public view virtual returns (uint256[] memory) {
return _owned[owner_];
}
function erc721BalanceOf(
address owner_
) public view virtual returns (uint256) {
return _owned[owner_].length;
}
function erc20BalanceOf(
address owner_
) public view virtual returns (uint256) {
return balanceOf[owner_];
}
function erc20TotalSupply() public view virtual returns (uint256) {
return totalSupply;
}
function erc721TotalSupply() public view virtual returns (uint256) {
return minted;
}
function getERC721QueueLength() public view virtual returns (uint256) {
return _storedERC721Ids.length();
}
function getERC721TokensInQueue(
uint256 start_,
uint256 count_
) public view virtual returns (uint256[] memory) {
uint256[] memory tokensInQueue = new uint256[](count_);
for (uint256 i = start_; i < start_ + count_; ) {
tokensInQueue[i - start_] = _storedERC721Ids.at(i);
unchecked {
++i;
}
}
return tokensInQueue;
}
/// @notice tokenURI must be implemented by child contract
function tokenURI(uint256 id_) public view virtual returns (string memory);
/// @notice Function for token approvals
/// @dev This function assumes the operator is attempting to approve
/// an ERC-721 if valueOrId_ is a possibly valid ERC-721 token id.
/// Unlike setApprovalForAll, spender_ must be allowed to be 0x0 so
/// that approval can be revoked.
function approve(
address spender_,
uint256 valueOrId_
) public virtual returns (bool) {
if (_isValidTokenId(valueOrId_)) {
erc721Approve(spender_, valueOrId_);
} else {
return erc20Approve(spender_, valueOrId_);
}
return true;
}
function erc721Approve(address spender_, uint256 id_) public virtual {
// Intention is to approve as ERC-721 token (id).
address erc721Owner = _getOwnerOf(id_);
if (
msg.sender != erc721Owner && !isApprovedForAll[erc721Owner][msg.sender]
) {
revert Unauthorized();
}
getApproved[id_] = spender_;
emit ERC721Events.Approval(erc721Owner, spender_, id_);
}
/// @dev Providing type(uint256).max for approval value results in an
/// unlimited approval that is not deducted from on transfers.
function erc20Approve(
address spender_,
uint256 value_
) public virtual returns (bool) {
// Prevent granting 0x0 an ERC-20 allowance.
if (spender_ == address(0)) {
revert InvalidSpender();
}
allowance[msg.sender][spender_] = value_;
emit ERC20Events.Approval(msg.sender, spender_, value_);
return true;
}
/// @notice Function for ERC-721 approvals
function setApprovalForAll(address operator_, bool approved_) public virtual {
// Prevent approvals to 0x0.
if (operator_ == address(0)) {
revert InvalidOperator();
}
isApprovedForAll[msg.sender][operator_] = approved_;
emit ERC721Events.ApprovalForAll(msg.sender, operator_, approved_);
}
/// @notice Function for mixed transfers from an operator that may be different than 'from'.
/// @dev This function assumes the operator is attempting to transfer an ERC-721
/// if valueOrId is a possible valid token id.
function transferFrom(
address from_,
address to_,
uint256 valueOrId_
) public virtual returns (bool) {
if (_isValidTokenId(valueOrId_)) {
erc721TransferFrom(from_, to_, valueOrId_);
} else {
// Intention is to transfer as ERC-20 token (value).
return erc20TransferFrom(from_, to_, valueOrId_);
}
return true;
}
/// @notice Function for ERC-721 transfers from.
/// @dev This function is recommended for ERC721 transfers.
function erc721TransferFrom(
address from_,
address to_,
uint256 id_
) public virtual {
// Prevent minting tokens from 0x0.
if (from_ == address(0)) {
revert InvalidSender();
}
// Prevent burning tokens to 0x0.
if (to_ == address(0)) {
revert InvalidRecipient();
}
if (from_ != _getOwnerOf(id_)) {
revert Unauthorized();
}
// Check that the operator is either the sender or approved for the transfer.
if (
msg.sender != from_ &&
!isApprovedForAll[from_][msg.sender] &&
msg.sender != getApproved[id_]
) {
revert Unauthorized();
}
// We only need to check ERC-721 transfer exempt status for the recipient
// since the sender being ERC-721 transfer exempt means they have already
// had their ERC-721s stripped away during the rebalancing process.
if (erc721TransferExempt(to_)) {
revert RecipientIsERC721TransferExempt();
}
// Transfer 1 * units ERC-20 and 1 ERC-721 token.
// ERC-721 transfer exemptions handled above. Can't make it to this point if either is transfer exempt.
_transferERC20(from_, to_, units);
_transferERC721(from_, to_, id_);
}
/// @notice Function for ERC-20 transfers from.
/// @dev This function is recommended for ERC20 transfers
function erc20TransferFrom(
address from_,
address to_,
uint256 value_
) public virtual returns (bool) {
// Prevent minting tokens from 0x0.
if (from_ == address(0)) {
revert InvalidSender();
}
// Prevent burning tokens to 0x0.
if (to_ == address(0)) {
revert InvalidRecipient();
}
uint256 allowed = allowance[from_][msg.sender];
// Check that the operator has sufficient allowance.
if (allowed != type(uint256).max) {
allowance[from_][msg.sender] = allowed - value_;
}
// Transferring ERC-20s directly requires the _transferERC20WithERC721 function.
// Handles ERC-721 exemptions internally.
return _transferERC20WithERC721(from_, to_, value_);
}
/// @notice Function for ERC-20 transfers.
/// @dev This function assumes the operator is attempting to transfer as ERC-20
/// given this function is only supported on the ERC-20 interface.
/// Treats even large amounts that are valid ERC-721 ids as ERC-20s.
function transfer(address to_, uint256 value_) public virtual returns (bool) {
// Prevent burning tokens to 0x0.
if (to_ == address(0)) {
revert InvalidRecipient();
}
// Transferring ERC-20s directly requires the _transferERC20WithERC721 function.
// Handles ERC-721 exemptions internally.
return _transferERC20WithERC721(msg.sender, to_, value_);
}
/// @notice Function for ERC-721 transfers with contract support.
/// This function only supports moving valid ERC-721 ids, as it does not exist on the ERC-20
/// spec and will revert otherwise.
function safeTransferFrom(
address from_,
address to_,
uint256 id_
) public virtual {
safeTransferFrom(from_, to_, id_, "");
}
/// @notice Function for ERC-721 transfers with contract support and callback data.
/// This function only supports moving valid ERC-721 ids, as it does not exist on the
/// ERC-20 spec and will revert otherwise.
function safeTransferFrom(
address from_,
address to_,
uint256 id_,
bytes memory data_
) public virtual {
if (!_isValidTokenId(id_)) {
revert InvalidTokenId();
}
transferFrom(from_, to_, id_);
if (
to_.code.length != 0 &&
IERC721Receiver(to_).onERC721Received(msg.sender, from_, id_, data_) !=
IERC721Receiver.onERC721Received.selector
) {
revert UnsafeRecipient();
}
}
/// @notice Function for EIP-2612 permits (ERC-20 only).
/// @dev Providing type(uint256).max for permit value results in an
/// unlimited approval that is not deducted from on transfers.
function permit(
address owner_,
address spender_,
uint256 value_,
uint256 deadline_,
uint8 v_,
bytes32 r_,
bytes32 s_
) public virtual {
if (deadline_ < block.timestamp) {
revert PermitDeadlineExpired();
}
// permit cannot be used for ERC-721 token approvals, so ensure
// the value does not fall within the valid range of ERC-721 token ids.
if (_isValidTokenId(value_)) {
revert InvalidApproval();
}
if (spender_ == address(0)) {
revert InvalidSpender();
}
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner_,
spender_,
value_,
nonces[owner_]++,
deadline_
)
)
)
),
v_,
r_,
s_
);
if (recoveredAddress == address(0) || recoveredAddress != owner_) {
revert InvalidSigner();
}
allowance[recoveredAddress][spender_] = value_;
}
emit ERC20Events.Approval(owner_, spender_, value_);
}
/// @notice Returns domain initial domain separator, or recomputes if chain id is not equal to initial chain id
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return
block.chainid == _INITIAL_CHAIN_ID
? _INITIAL_DOMAIN_SEPARATOR
: _computeDomainSeparator();
}
function supportsInterface(
bytes4 interfaceId
) public view virtual returns (bool) {
return
interfaceId == type(IERC404).interfaceId ||
interfaceId == type(IERC165).interfaceId;
}
/// @notice Function for self-exemption
function setSelfERC721TransferExempt(bool state_) public virtual {
_setERC721TransferExempt(msg.sender, state_);
}
/// @notice Function to check if address is transfer exempt
function erc721TransferExempt(
address target_
) public view virtual returns (bool) {
return target_ == address(0) || _erc721TransferExempt[target_];
}
/// @notice For a token token id to be considered valid, it just needs
/// to fall within the range of possible token ids, it does not
/// necessarily have to be minted yet.
function _isValidTokenId(uint256 id_) internal pure returns (bool) {
return id_ > ID_ENCODING_PREFIX % 1e7 && id_ != type(uint256).max;
}
/// @notice Internal function to compute domain separator for EIP-2612 permits
function _computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/// @notice This is the lowest level ERC-20 transfer function, which
/// should be used for both normal ERC-20 transfers as well as minting.
/// Note that this function allows transfers to and from 0x0.
function _transferERC20(
address from_,
address to_,
uint256 value_
) internal virtual {
// Minting is a special case for which we should not check the balance of
// the sender, and we should increase the total supply.
if (from_ == address(0)) {
totalSupply += value_;
} else {
// Deduct value from sender's balance.
balanceOf[from_] -= value_;
}
// Update the recipient's balance.
// Can be unchecked because on mint, adding to totalSupply is checked, and on transfer balance deduction is checked.
unchecked {
balanceOf[to_] += value_;
}
emit ERC20Events.Transfer(from_, to_, value_);
}
// Function to get the time of the last ERC-721 transfer
function _getERC721LastTransferTimestamp(uint256 id_) internal view returns (uint256) {
return lastTransferTimestamp[id_];
}
// Function to update the time of the last ERC-721 transfer
function _updateERC721LastTransferTimestamp(uint256 id_) internal {
lastTransferTimestamp[id_] = block.timestamp;
// Log the time update event
emit TokenTransferWithTimestampUpdated(id_, block.timestamp);
}
function getPauseEvolutionTime(uint256 id_) internal view returns (uint256) {
return pauseEvolutionTime[id_];
}
function getTimeSpentOnPause(uint256 id_) internal view returns (uint256) {
// Return the time spent on pause for the specific token
if (pauseEvolutionTime[id_] > 0) {
return timeOnPause[id_] + block.timestamp - pauseEvolutionTime[id_];
}
return timeOnPause[id_];
}
/**
* @dev Function to pause evolution for a specific token.
* @param id_ The ID of the token to pause evolution for.
* Requirements:
* - The caller must be the owner of the token.
* - Evolution must not already be paused for the token.
*/
function setPauseEvolution(uint256 id_) external {
require(ownerOf(id_) == msg.sender, "Pokemoon: caller is not the owner of the token");
if ( pauseEvolutionTime[id_] == 0) {
pauseEvolutionTime[id_] = block.timestamp;
emit EvolutionPaused(id_, block.timestamp);
}
}
/**
* @dev Function to resume evolution for a specific token.
* @param id_ The ID of the token to resume evolution for.
* Requirements:
* - The caller must be the owner of the token.
* - Evolution must be paused for the token.
*/
function setContinueEvolution(uint256 id_) external {
require(ownerOf(id_) == msg.sender, "Pokemoon: caller is not the owner of the token");
timeOnPause[id_] = getTimeSpentOnPause(id_);
pauseEvolutionTime[id_] = 0;
emit EvolutionContinued(id_, block.timestamp);
}
/// @notice Consolidated record keeping function for transferring ERC-721s.
/// @dev Assign the token to the new owner, and remove from the old owner.
/// Note that this function allows transfers to and from 0x0.
/// Does not handle ERC-721 exemptions.
function _transferERC721(
address from_,
address to_,
uint256 id_
) internal virtual {
// If this is not a mint, handle record keeping for transfer from previous owner.
if (from_ != address(0)) {
// On transfer of an NFT, any previous approval is reset.
delete getApproved[id_];
uint256 updatedId = _owned[from_][_owned[from_].length - 1];
if (updatedId != id_) {
uint256 updatedIndex = _getOwnedIndex(id_);
// update _owned for sender
_owned[from_][updatedIndex] = updatedId;
// update index for the moved id
_setOwnedIndex(updatedId, updatedIndex);
}
// pop
_owned[from_].pop();
}
// Check if this is a burn.
if (to_ != address(0)) {
// If not a burn, update the owner of the token to the new owner.
// Update owner of the token to the new owner.
_setOwnerOf(id_, to_);
// Push token onto the new owner's stack.
_owned[to_].push(id_);
// Update index for new owner's stack.
_setOwnedIndex(id_, _owned[to_].length - 1);
} else {
// If this is a burn, reset the owner of the token to 0x0 by deleting the token from _ownedData.
delete _ownedData[id_];
}
emit ERC721Events.Transfer(from_, to_, id_);
_updateERC721LastTransferTimestamp(id_);
pauseEvolutionTime[id_] = 0;
timeOnPause[id_] = 0;
}
/// @notice Internal function for ERC-20 transfers. Also handles any ERC-721 transfers that may be required.
// Handles ERC-721 exemptions.
function _transferERC20WithERC721(
address from_,
address to_,
uint256 value_
) internal virtual returns (bool) {
uint256 erc20BalanceOfSenderBefore = erc20BalanceOf(from_);
uint256 erc20BalanceOfReceiverBefore = erc20BalanceOf(to_);
_transferERC20(from_, to_, value_);
// Preload for gas savings on branches
bool isFromERC721TransferExempt = erc721TransferExempt(from_);
bool isToERC721TransferExempt = erc721TransferExempt(to_);
// Skip _withdrawAndStoreERC721 and/or _retrieveOrMintERC721 for ERC-721 transfer exempt addresses
// 1) to save gas
// 2) because ERC-721 transfer exempt addresses won't always have/need ERC-721s corresponding to their ERC20s.
if (isFromERC721TransferExempt && isToERC721TransferExempt) {
// Case 1) Both sender and recipient are ERC-721 transfer exempt. No ERC-721s need to be transferred.
// NOOP.
} else if (isFromERC721TransferExempt) {
// Case 2) The sender is ERC-721 transfer exempt, but the recipient is not. Contract should not attempt
// to transfer ERC-721s from the sender, but the recipient should receive ERC-721s
// from the bank/minted for any whole number increase in their balance.
// Only cares about whole number increments.
uint256 tokensToRetrieveOrMint = (balanceOf[to_] / (customRatio * units)) -
(erc20BalanceOfReceiverBefore / (customRatio * units));
for (uint256 i = 0; i < tokensToRetrieveOrMint; ) {
_retrieveOrMintERC721(to_);
unchecked {
++i;
}
}
} else if (isToERC721TransferExempt) {
// Case 3) The sender is not ERC-721 transfer exempt, but the recipient is. Contract should attempt
// to withdraw and store ERC-721s from the sender, but the recipient should not
// receive ERC-721s from the bank/minted.
// Only cares about whole number increments.
uint256 tokensToWithdrawAndStore = (erc20BalanceOfSenderBefore / (customRatio * units)) -
(balanceOf[from_] / (customRatio * units));
for (uint256 i = 0; i < tokensToWithdrawAndStore; ) {
_withdrawAndStoreERC721(from_);
unchecked {
++i;
}
}
} else {
// Case 4) Neither the sender nor the recipient are ERC-721 transfer exempt.
// Strategy:
// 1. First deal with the whole tokens. These are easy and will just be transferred.
// 2. Look at the fractional part of the value:
// a) If it causes the sender to lose a whole token that was represented by an NFT due to a
// fractional part being transferred, withdraw and store an additional NFT from the sender.
// b) If it causes the receiver to gain a whole new token that should be represented by an NFT
// due to receiving a fractional part that completes a whole token, retrieve or mint an NFT to the recevier.
// Whole tokens worth of ERC-20s get transferred as ERC-721s without any burning/minting.
uint256 nftsToTransfer = value_ / (customRatio * units);
for (uint256 i = 0; i < nftsToTransfer; ) {
// Pop from sender's ERC-721 stack and transfer them (LIFO)
uint256 indexOfLastToken = _owned[from_].length - 1;
uint256 tokenId = _owned[from_][indexOfLastToken];
_transferERC721(from_, to_, tokenId);
unchecked {
++i;
}
}
// If the transfer changes either the sender or the recipient's holdings from a fractional to a non-fractional
// amount (or vice versa), adjust ERC-721s.
// First check if the send causes the sender to lose a whole token that was represented by an ERC-721
// due to a fractional part being transferred.
//
// Process:
// Take the difference between the whole number of tokens before and after the transfer for the sender.
// If that difference is greater than the number of ERC-721s transferred (whole units), then there was
// an additional ERC-721 lost due to the fractional portion of the transfer.
// If this is a self-send and the before and after balances are equal (not always the case but often),
// then no ERC-721s will be lost here.
if (
(erc20BalanceOfSenderBefore / (customRatio * units)) - (erc20BalanceOf(from_) / (customRatio * units)) >
nftsToTransfer
) {
_withdrawAndStoreERC721(from_);
}
// Then, check if the transfer causes the receiver to gain a whole new token which requires gaining
// an additional ERC-721.
//
// Process:
// Take the difference between the whole number of tokens before and after the transfer for the recipient.
// If that difference is greater than the number of ERC-721s transferred (whole units), then there was
// an additional ERC-721 gained due to the fractional portion of the transfer.
// Again, for self-sends where the before and after balances are equal, no ERC-721s will be gained here.
if (
(erc20BalanceOf(to_) / (customRatio * units)) - (erc20BalanceOfReceiverBefore / (customRatio * units)) >
nftsToTransfer
) {
_retrieveOrMintERC721(to_);
}
}
return true;
}
/// @notice Internal function for ERC20 minting
/// @dev This function will allow minting of new ERC20s.
/// If mintCorrespondingERC721s_ is true, and the recipient is not ERC-721 exempt, it will
/// also mint the corresponding ERC721s.
/// Handles ERC-721 exemptions.
function _mintERC20(address to_, uint256 value_) internal virtual {
/// You cannot mint to the zero address (you can't mint and immediately burn in the same transfer).
if (to_ == address(0)) {
revert InvalidRecipient();
}
if (totalSupply + value_ > ID_ENCODING_PREFIX / 1e7) {
revert MintLimitReached();
}
_transferERC20WithERC721(address(0), to_, value_);
}
/// @notice Internal function for ERC-721 minting and retrieval from the bank.
/// @dev This function will allow minting of new ERC-721s up to the total fractional supply. It will
/// first try to pull from the bank, and if the bank is empty, it will mint a new token.
/// Does not handle ERC-721 exemptions.
function _retrieveOrMintERC721(address to_) internal virtual {
if (to_ == address(0)) {
revert InvalidRecipient();
}
uint256 id;
if (!_storedERC721Ids.empty()) {
// If there are any tokens in the bank, use those first.
// Pop off the end of the queue (FIFO).
id = _storedERC721Ids.popBack();
} else {
// Otherwise, mint a new token, should not be able to go over the total fractional supply.
++minted;
// Reserve max uint256 for approvals
if (minted == type(uint256).max) {
revert MintLimitReached();
}
id = (ID_ENCODING_PREFIX + minted) % 1e7;
}
address erc721Owner = _getOwnerOf(id);
// The token should not already belong to anyone besides 0x0 or this contract.
// If it does, something is wrong, as this should never happen.
if (erc721Owner != address(0)) {
revert AlreadyExists();
}
// Transfer the token to the recipient, either transferring from the contract's bank or minting.
// Does not handle ERC-721 exemptions.
_transferERC721(erc721Owner, to_, id);
}
/// @notice Internal function for ERC-721 deposits to bank (this contract).
/// @dev This function will allow depositing of ERC-721s to the bank, which can be retrieved by future minters.
// Does not handle ERC-721 exemptions.
function _withdrawAndStoreERC721(address from_) internal virtual {
if (from_ == address(0)) {
revert InvalidSender();
}
// Retrieve the latest token added to the owner's stack (LIFO).
uint256 id = _owned[from_][_owned[from_].length - 1];
// Transfer to 0x0.
// Does not handle ERC-721 exemptions.
_transferERC721(from_, address(0), id);
// Record the token in the contract's bank queue.
_storedERC721Ids.pushFront(id);
}
/// @notice Initialization function to set pairs / etc, saving gas by avoiding mint / burn on unnecessary targets
function _setERC721TransferExempt(
address target_,
bool state_
) internal virtual {
if (target_ == address(0)) {
revert InvalidExemption();
}
// Adjust the ERC721 balances of the target to respect exemption rules.
// Despite this logic, it is still recommended practice to exempt prior to the target
// having an active balance.
if (state_) {
_clearERC721Balance(target_);
} else {
_reinstateERC721Balance(target_);
}
_erc721TransferExempt[target_] = state_;
}
/// @notice Function to reinstate balance on exemption removal
function _reinstateERC721Balance(address target_) private {
uint256 expectedERC721Balance = erc20BalanceOf(target_) / units;
uint256 actualERC721Balance = erc721BalanceOf(target_);
for (uint256 i = 0; i < expectedERC721Balance - actualERC721Balance; ) {
// Transfer ERC721 balance in from pool
_retrieveOrMintERC721(target_);
unchecked {
++i;
}
}
}
/// @notice Function to clear balance on exemption inclusion
function _clearERC721Balance(address target_) private {
uint256 erc721Balance = erc721BalanceOf(target_);
for (uint256 i = 0; i < erc721Balance; ) {
// Transfer out ERC721 balance
_withdrawAndStoreERC721(target_);
unchecked {
++i;
}
}
}
function _getOwnerOf(
uint256 id_
) internal view virtual returns (address ownerOf_) {
uint256 data = _ownedData[id_];
assembly {
ownerOf_ := and(data, _BITMASK_ADDRESS)
}
}
function _setOwnerOf(uint256 id_, address owner_) internal virtual {
uint256 data = _ownedData[id_];
assembly {
data := add(
and(data, _BITMASK_OWNED_INDEX),
and(owner_, _BITMASK_ADDRESS)
)
}
_ownedData[id_] = data;
}
function _getOwnedIndex(
uint256 id_
) internal view virtual returns (uint256 ownedIndex_) {
uint256 data = _ownedData[id_];
assembly {
ownedIndex_ := shr(160, data)
}
}
function _setOwnedIndex(uint256 id_, uint256 index_) internal virtual {
uint256 data = _ownedData[id_];
if (index_ > _BITMASK_OWNED_INDEX >> 160) {
revert OwnedIndexOverflow();
}
assembly {
data := add(
and(data, _BITMASK_ADDRESS),
and(shl(160, index_), _BITMASK_OWNED_INDEX)
)
}
_ownedData[id_] = data;
}
function containsSubstring(string memory str, string memory substr) internal pure returns (bool) {
bytes memory strBytes = bytes(str);
bytes memory substrBytes = bytes(substr);
for (uint i = 0; i <= strBytes.length - substrBytes.length; i++) {
bool found = true;
for (uint j = 0; j < substrBytes.length; j++) {
if (strBytes[i + j] != substrBytes[j]) {
found = false;
break;
}
}
if (found) {
return true;
}
}
return false;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../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.
*
* The initial owner is set to the address provided by the deployer. 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;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling 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 {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_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
pragma solidity ^0.8.20;
library ERC20Events {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 amount);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library ERC721Events {
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
event Approval(
address indexed owner,
address indexed spender,
uint256 indexed id
);
event Transfer(address indexed from, address indexed to, uint256 indexed id);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/DoubleEndedQueue.sol)
// Modified by Pandora Labs to support native uint256 operations
pragma solidity ^0.8.20;
/**
* @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of
* the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and
* FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that
* the existing queue contents are left in storage.
*
* The struct is called `Uint256Deque`. This data structure can only be used in storage, and not in memory.
*
* ```solidity
* DoubleEndedQueue.Uint256Deque queue;
* ```
*/
library DoubleEndedQueue {
/**
* @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.
*/
error QueueEmpty();
/**
* @dev A push operation couldn't be completed due to the queue being full.
*/
error QueueFull();
/**
* @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.
*/
error QueueOutOfBounds();
/**
* @dev Indices are 128 bits so begin and end are packed in a single storage slot for efficient access.
*
* Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
* directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
* lead to unexpected behavior.
*
* The first item is at data[begin] and the last item is at data[end - 1]. This range can wrap around.
*/
struct Uint256Deque {
uint128 _begin;
uint128 _end;
mapping(uint128 index => uint256) _data;
}
/**
* @dev Inserts an item at the end of the queue.
*
* Reverts with {QueueFull} if the queue is full.
*/
function pushBack(Uint256Deque storage deque, uint256 value) internal {
unchecked {
uint128 backIndex = deque._end;
if (backIndex + 1 == deque._begin) revert QueueFull();
deque._data[backIndex] = value;
deque._end = backIndex + 1;
}
}
/**
* @dev Removes the item at the end of the queue and returns it.
*
* Reverts with {QueueEmpty} if the queue is empty.
*/
function popBack(
Uint256Deque storage deque
) internal returns (uint256 value) {
unchecked {
uint128 backIndex = deque._end;
if (backIndex == deque._begin) revert QueueEmpty();
--backIndex;
value = deque._data[backIndex];
delete deque._data[backIndex];
deque._end = backIndex;
}
}
/**
* @dev Inserts an item at the beginning of the queue.
*
* Reverts with {QueueFull} if the queue is full.
*/
function pushFront(Uint256Deque storage deque, uint256 value) internal {
unchecked {
uint128 frontIndex = deque._begin - 1;
if (frontIndex == deque._end) revert QueueFull();
deque._data[frontIndex] = value;
deque._begin = frontIndex;
}
}
/**
* @dev Removes the item at the beginning of the queue and returns it.
*
* Reverts with `QueueEmpty` if the queue is empty.
*/
function popFront(
Uint256Deque storage deque
) internal returns (uint256 value) {
unchecked {
uint128 frontIndex = deque._begin;
if (frontIndex == deque._end) revert QueueEmpty();
value = deque._data[frontIndex];
delete deque._data[frontIndex];
deque._begin = frontIndex + 1;
}
}
/**
* @dev Returns the item at the beginning of the queue.
*
* Reverts with `QueueEmpty` if the queue is empty.
*/
function front(
Uint256Deque storage deque
) internal view returns (uint256 value) {
if (empty(deque)) revert QueueEmpty();
return deque._data[deque._begin];
}
/**
* @dev Returns the item at the end of the queue.
*
* Reverts with `QueueEmpty` if the queue is empty.
*/
function back(
Uint256Deque storage deque
) internal view returns (uint256 value) {
if (empty(deque)) revert QueueEmpty();
unchecked {
return deque._data[deque._end - 1];
}
}
/**
* @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at
* `length(deque) - 1`.
*
* Reverts with `QueueOutOfBounds` if the index is out of bounds.
*/
function at(
Uint256Deque storage deque,
uint256 index
) internal view returns (uint256 value) {
if (index >= length(deque)) revert QueueOutOfBounds();
// By construction, length is a uint128, so the check above ensures that index can be safely downcast to uint128
unchecked {
return deque._data[deque._begin + uint128(index)];
}
}
/**
* @dev Resets the queue back to being empty.
*
* NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses
* out on potential gas refunds.
*/
function clear(Uint256Deque storage deque) internal {
deque._begin = 0;
deque._end = 0;
}
/**
* @dev Returns the number of items in the queue.
*/
function length(Uint256Deque storage deque) internal view returns (uint256) {
unchecked {
return uint256(deque._end - deque._begin);
}
}
/**
* @dev Returns true if the queue is empty.
*/
function empty(Uint256Deque storage deque) internal view returns (bool) {
return deque._end == deque._begin;
}
}//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
interface IERC404 is IERC165 {
error NotFound();
error InvalidTokenId();
error AlreadyExists();
error InvalidRecipient();
error InvalidSender();
error InvalidSpender();
error InvalidOperator();
error UnsafeRecipient();
error RecipientIsERC721TransferExempt();
error Unauthorized();
error InsufficientAllowance();
error DecimalsTooLow();
error PermitDeadlineExpired();
error InvalidSigner();
error InvalidApproval();
error OwnedIndexOverflow();
error MintLimitReached();
error InvalidExemption();
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function erc20TotalSupply() external view returns (uint256);
function erc721TotalSupply() external view returns (uint256);
function balanceOf(address owner_) external view returns (uint256);
function erc721BalanceOf(address owner_) external view returns (uint256);
function erc20BalanceOf(address owner_) external view returns (uint256);
function erc721TransferExempt(address account_) external view returns (bool);
function isApprovedForAll(
address owner_,
address operator_
) external view returns (bool);
function allowance(
address owner_,
address spender_
) external view returns (uint256);
function owned(address owner_) external view returns (uint256[] memory);
function ownerOf(uint256 id_) external view returns (address erc721Owner);
function tokenURI(uint256 id_) external view returns (string memory);
function approve(
address spender_,
uint256 valueOrId_
) external returns (bool);
function erc20Approve(
address spender_,
uint256 value_
) external returns (bool);
function erc721Approve(address spender_, uint256 id_) external;
function setApprovalForAll(address operator_, bool approved_) external;
function transferFrom(
address from_,
address to_,
uint256 valueOrId_
) external returns (bool);
function erc20TransferFrom(
address from_,
address to_,
uint256 value_
) external returns (bool);
function erc721TransferFrom(address from_, address to_, uint256 id_) external;
function transfer(address to_, uint256 amount_) external returns (bool);
function getERC721QueueLength() external view returns (uint256);
function getERC721TokensInQueue(
uint256 start_,
uint256 count_
) external view returns (uint256[] memory);
function setSelfERC721TransferExempt(bool state_) external;
function safeTransferFrom(address from_, address to_, uint256 id_) external;
function safeTransferFrom(
address from_,
address to_,
uint256 id_,
bytes calldata data_
) external;
function DOMAIN_SEPARATOR() external view returns (bytes32);
function permit(
address owner_,
address spender_,
uint256 value_,
uint256 deadline_,
uint8 v_,
bytes32 r_,
bytes32 s_
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Receiver.sol)
pragma solidity ^0.8.20;
import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @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 `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @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);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"uint256","name":"maxTotalSupplyERC721_","type":"uint256"},{"internalType":"address","name":"initialOwner_","type":"address"},{"internalType":"address","name":"initialMintRecipient_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyExists","type":"error"},{"inputs":[],"name":"DecimalsTooLow","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InvalidApproval","type":"error"},{"inputs":[],"name":"InvalidExemption","type":"error"},{"inputs":[],"name":"InvalidOperator","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidSender","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidTokenId","type":"error"},{"inputs":[],"name":"MintLimitReached","type":"error"},{"inputs":[],"name":"NotFound","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnedIndexOverflow","type":"error"},{"inputs":[],"name":"PermitDeadlineExpired","type":"error"},{"inputs":[],"name":"QueueEmpty","type":"error"},{"inputs":[],"name":"QueueFull","type":"error"},{"inputs":[],"name":"QueueOutOfBounds","type":"error"},{"inputs":[],"name":"RecipientIsERC721TransferExempt","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsafeRecipient","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","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":false,"internalType":"uint256","name":"id_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EvolutionContinued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EvolutionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokenTransferWithTimestampUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","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":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ID_ENCODING_PREFIX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"valueOrId_","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"customRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"erc20Approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"erc20BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc20TotalSupply","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":"value_","type":"uint256"}],"name":"erc20TransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"erc721Approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"erc721BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc721TotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target_","type":"address"}],"name":"erc721TransferExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"erc721TransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getERC721QueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start_","type":"uint256"},{"internalType":"uint256","name":"count_","type":"uint256"}],"name":"getERC721TokensInQueue","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"getTimeUntilNextEvolution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minted","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"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"owned","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"erc721Owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","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":"id_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"approved_","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"setContinueEvolution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"setCustomRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_dataURI","type":"string"}],"name":"setDataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"bool","name":"value_","type":"bool"}],"name":"setERC721TransferExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"setPauseEvolution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state_","type":"bool"}],"name":"setSelfERC721TransferExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"setTokenURI","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":"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":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"valueOrId_","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"units","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
61010060405234801562000011575f80fd5b506040516200456738038062004567833981016040819052620000349162000d9e565b858585846001600160a01b0381166200006657604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b620000718162000119565b50600362000080848262000ed2565b5060046200008f838262000ed2565b5060128160ff161015620000b6576040516398790fd560e01b815260040160405180910390fd5b60ff81166080819052620000cc90600a620010ab565b60a0524660c052620000dd62000168565b60e05250620000f29150829050600162000203565b6200010d8160a05185620001079190620010c2565b62000278565b50505050505062001205565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60036040516200019b9190620010dc565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166200022b5760405163a41e3d3f60e01b815260040160405180910390fd5b801562000243576200023d82620002f5565b6200024e565b6200024e826200032c565b6001600160a01b03919091165f908152600d60205260409020805460ff1916911515919091179055565b6001600160a01b038216620002a057604051634e46966960e11b815260040160405180910390fd5b620002b362989680600160ff1b6200116a565b81600554620002c3919062001180565b1115620002e35760405163303b682f60e01b815260040160405180910390fd5b620002f05f8383620003b0565b505050565b6001600160a01b0381165f908152600c6020526040812054905b81811015620002f0576200032383620006cb565b6001016200030f565b60a0515f9062000350836001600160a01b03165f9081526007602052604090205490565b6200035c91906200116a565b90505f6200037e836001600160a01b03165f908152600c602052604090205490565b90505f5b6200038e828462001196565b811015620003aa57620003a1846200075c565b60010162000382565b50505050565b6001600160a01b038381165f90815260076020526040808220549285168252812054909190620003e286868662000860565b5f620003ee876200090e565b90505f620003fc876200090e565b9050818015620004095750805b620006bd5781156200049f575f60a051601054620004289190620010c2565b6200043490856200116a565b60a051601054620004469190620010c2565b6001600160a01b038a165f908152600760205260409020546200046a91906200116a565b62000476919062001196565b90505f5b8181101562000497576200048e896200075c565b6001016200047a565b5050620006bd565b801562000528575f60a051601054620004b99190620010c2565b6001600160a01b038a165f90815260076020526040902054620004dd91906200116a565b60a051601054620004ef9190620010c2565b620004fb90876200116a565b62000507919062001196565b90505f5b8181101562000497576200051f8a620006cb565b6001016200050b565b5f60a0516010546200053b9190620010c2565b6200054790886200116a565b90505f5b81811015620005d4576001600160a01b038a165f908152600c60205260408120546200057a9060019062001196565b6001600160a01b038c165f908152600c602052604081208054929350909183908110620005ab57620005ab620011ac565b905f5260205f2001549050620005c98c8c836200094360201b60201c565b50506001016200054b565b508060a051601054620005e89190620010c2565b6001600160a01b038b165f908152600760205260409020546200060c91906200116a565b60a0516010546200061e9190620010c2565b6200062a90886200116a565b62000636919062001196565b111562000648576200064889620006cb565b8060a0516010546200065b9190620010c2565b6200066790866200116a565b60a051601054620006799190620010c2565b6001600160a01b038b165f908152600760205260409020546200069d91906200116a565b620006a9919062001196565b1115620006bb57620006bb886200075c565b505b506001979650505050505050565b6001600160a01b038116620006f357604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b0381165f908152600c6020526040812080546200071a9060019062001196565b815481106200072d576200072d620011ac565b905f5260205f20015490506200074b825f836200094360201b60201c565b6200075860018262000b37565b5050565b6001600160a01b0381166200078457604051634e46966960e11b815260040160405180910390fd5b5f620007a4600154600160801b81046001600160801b0390811691161490565b620007bd57620007b5600162000ba0565b90506200081c565b60065f8154620007cd90620011c0565b90915550600654600101620007f55760405163303b682f60e01b815260040160405180910390fd5b62989680600654600160ff1b6200080d919062001180565b620008199190620011db565b90505b5f818152600b60205260409020546001600160a01b03168015620008535760405163119b4fd360e11b815260040160405180910390fd5b620002f081848462000943565b6001600160a01b0383166200088e578060055f82825462000882919062001180565b90915550620008bd9050565b6001600160a01b0383165f9081526007602052604081208054839290620008b790849062001196565b90915550505b6001600160a01b038083165f81815260076020526040908190208054850190555190918516905f805160206200454783398151915290620009019085815260200190565b60405180910390a3505050565b5f6001600160a01b03821615806200093d57506001600160a01b0382165f908152600d602052604090205460ff165b92915050565b6001600160a01b0383161562000a53575f81815260096020908152604080832080546001600160a01b03191690556001600160a01b0386168352600c90915281208054620009949060019062001196565b81548110620009a757620009a7620011ac565b905f5260205f200154905081811462000a15575f828152600b602052604081205460a01c6001600160a01b0386165f908152600c602052604090208054919250839183908110620009fc57620009fc620011ac565b5f9182526020909120015562000a13828262000c0e565b505b6001600160a01b0384165f908152600c6020526040902080548062000a3e5762000a3e620011f1565b600190038181905f5260205f20015f90559055505b6001600160a01b0382161562000acf575f818152600b6020908152604080832080546001600160a01b0319166001600160a01b038716908101909155808452600c8352908320805460018181018355828652938520018590559252905462000ac991839162000ac3919062001196565b62000c0e565b62000ade565b5f818152600b60205260408120555b80826001600160a01b0316846001600160a01b03165f805160206200454783398151915260405160405180910390a462000b188162000c74565b5f90815260116020908152604080832083905560139091528120555050565b81546001600160801b038082165f190191600160801b900481169082160362000b7357604051638acb5f2760e01b815260040160405180910390fd5b6001600160801b03165f81815260018401602052604090209190915581546001600160801b031916179055565b80545f906001600160801b03600160801b820481169116810362000bd7576040516375e52f4f60e01b815260040160405180910390fd5b5f19016001600160801b039081165f818152600185016020526040812080549190558454909216600160801b909102179092555090565b5f828152600b60205260409020546001600160601b0382111562000c4557604051633f2cd0e360e21b815260040160405180910390fd5b5f928352600b60205260409092206001600160a01b039290921660a09190911b6001600160a01b031916019055565b5f818152600f602090815260409182902042908190558251848152918201527fc46c7931bda1e2e1d4f011c47e83de0acbba59885cadf0a829e3c8be59564da7910160405180910390a150565b634e487b7160e01b5f52604160045260245ffd5b5f82601f83011262000ce5575f80fd5b81516001600160401b038082111562000d025762000d0262000cc1565b604051601f8301601f19908116603f0116810190828211818310171562000d2d5762000d2d62000cc1565b816040528381526020925086602085880101111562000d4a575f80fd5b5f91505b8382101562000d6d578582018301518183018401529082019062000d4e565b5f602085830101528094505050505092915050565b80516001600160a01b038116811462000d99575f80fd5b919050565b5f805f805f8060c0878903121562000db4575f80fd5b86516001600160401b038082111562000dcb575f80fd5b62000dd98a838b0162000cd5565b9750602089015191508082111562000def575f80fd5b5062000dfe89828a0162000cd5565b955050604087015160ff8116811462000e15575f80fd5b6060880151909450925062000e2d6080880162000d82565b915062000e3d60a0880162000d82565b90509295509295509295565b600181811c9082168062000e5e57607f821691505b60208210810362000e7d57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115620002f057805f5260205f20601f840160051c8101602085101562000eaa5750805b601f840160051c820191505b8181101562000ecb575f815560010162000eb6565b5050505050565b81516001600160401b0381111562000eee5762000eee62000cc1565b62000f068162000eff845462000e49565b8462000e83565b602080601f83116001811462000f3c575f841562000f245750858301515b5f19600386901b1c1916600185901b17855562000f96565b5f85815260208120601f198616915b8281101562000f6c5788860151825594840194600190910190840162000f4b565b508582101562000f8a57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b600181815b8085111562000ff257815f190482111562000fd65762000fd662000f9e565b8085161562000fe457918102915b93841c939080029062000fb7565b509250929050565b5f826200100a575060016200093d565b816200101857505f6200093d565b81600181146200103157600281146200103c576200105c565b60019150506200093d565b60ff84111562001050576200105062000f9e565b50506001821b6200093d565b5060208310610133831016604e8410600b841016171562001081575081810a6200093d565b6200108d838362000fb2565b805f1904821115620010a357620010a362000f9e565b029392505050565b5f620010bb60ff84168362000ffa565b9392505050565b80820281158282048414176200093d576200093d62000f9e565b5f808354620010eb8162000e49565b600182811680156200110657600181146200111c576200114a565b60ff19841687528215158302870194506200114a565b875f526020805f205f5b85811015620011415781548a82015290840190820162001126565b50505082870194505b50929695505050505050565b634e487b7160e01b5f52601260045260245ffd5b5f826200117b576200117b62001156565b500490565b808201808211156200093d576200093d62000f9e565b818103818111156200093d576200093d62000f9e565b634e487b7160e01b5f52603260045260245ffd5b5f60018201620011d457620011d462000f9e565b5060010190565b5f82620011ec57620011ec62001156565b500690565b634e487b7160e01b5f52603160045260245ffd5b60805160a05160c05160e0516132c1620012865f395f6108bf01525f61088f01525f81816104e6015281816115be015281816119aa015281816119e201528181611a6701528181611ab701528181611b1701528181611bcf01528181611c1f01528181611c7101528181611ca901526126cf01525f6103cc01526132c15ff3fe608060405234801561000f575f80fd5b50600436106102b1575f3560e01c806395d89b411161017b578063d36517b6116100e4578063dd6376991161009e578063e985e9c511610079578063e985e9c51461068a578063f28ca1dd146106b7578063f2fde38b146106bf578063f780bc1a146106d2575f80fd5b8063dd63769914610651578063dfabc03314610664578063e0df5b6f14610677575f80fd5b8063d36517b6146105dd578063d505accf146105f0578063d547cfb714610603578063d73d17771461060b578063d96ca0b914610614578063dd62ed3e14610627575f80fd5b8063b3f9ea3411610135578063b3f9ea3414610561578063b88d4fde14610589578063c336c8171461059c578063c5ab3ba6146105af578063c6e672b9146105b7578063c87b56dd146105ca575f80fd5b806395d89b41146104d9578063976a8435146104e1578063a22cb46514610508578063a9059cbb1461051b578063ade7f0db1461052e578063b1ab931714610541575f80fd5b806342842e0e1161021d578063715018a6116101d7578063715018a6146104745780637ecebe001461047c57806389fb4c661461049b5780638a696e50146104a35780638da5cb5b146104b65780638e0146ae146104c6575f80fd5b806342842e0e146104085780634d9660721461041b5780634f02c4201461042e5780636352211e146104375780636e8f624b1461044a57806370a0823114610455575f80fd5b806309f0ef651161026e57806309f0ef651461038357806318160ddd1461039657806318d217c31461039f57806323b872dd146103b4578063313ce567146103c75780633644e51514610400575f80fd5b806301ffc9a7146102b557806302519da3146102dd57806306fdde0314610313578063081812fc14610328578063095ea7b31461036857806309674eb01461037b575b5f80fd5b6102c86102c3366004612b27565b6106e5565b60405190151581526020015b60405180910390f35b6103056102eb366004612b58565b6001600160a01b03165f9081526007602052604090205490565b6040519081526020016102d4565b61031b61071b565b6040516102d49190612bbe565b610350610336366004612bd0565b60096020525f90815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016102d4565b6102c8610376366004612be7565b6107a7565b6103056107df565b6102c8610391366004612b58565b610808565b61030560055481565b6103b26103ad366004612c96565b610838565b005b6102c86103c2366004612ce3565b610850565b6103ee7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff90911681526020016102d4565b61030561088c565b6103b2610416366004612ce3565b6108e1565b6102c8610429366004612be7565b610900565b61030560065481565b610350610445366004612bd0565b61098b565b610305600160ff1b81565b610305610463366004612b58565b60076020525f908152604090205481565b6103b26109f4565b61030561048a366004612b58565b600e6020525f908152604090205481565b600554610305565b6103b26104b1366004612d2b565b610a07565b5f546001600160a01b0316610350565b6103b26104d4366004612bd0565b610a14565b61031b610a21565b6103057f000000000000000000000000000000000000000000000000000000000000000081565b6103b2610516366004612d44565b610a2e565b6102c8610529366004612be7565b610ac0565b61030561053c366004612bd0565b610af3565b61055461054f366004612b58565b610cf6565b6040516102d49190612d75565b61030561056f366004612b58565b6001600160a01b03165f908152600c602052604090205490565b6103b2610597366004612db8565b610d5f565b6103b26105aa366004612bd0565b610e4a565b600654610305565b6103b26105c5366004612d44565b610eec565b61031b6105d8366004612bd0565b610efe565b6103b26105eb366004612bd0565b6110fe565b6103b26105fe366004612e2f565b611189565b61031b6113c6565b61030560105481565b6102c8610622366004612ce3565b6113d3565b610305610635366004612e9c565b600860209081525f928352604080842090915290825290205481565b6103b261065f366004612ce3565b61148f565b6103b2610672366004612be7565b6115ed565b6103b2610685366004612c96565b6116af565b6102c8610698366004612e9c565b600a60209081525f928352604080842090915290825290205460ff1681565b61031b6116c3565b6103b26106cd366004612b58565b6116d0565b6105546106e0366004612ec4565b61170a565b5f6001600160e01b0319821663caf91ff560e01b148061071557506001600160e01b031982166301ffc9a760e01b145b92915050565b6003805461072890612ee4565b80601f016020809104026020016040519081016040528092919081815260200182805461075490612ee4565b801561079f5780601f106107765761010080835404028352916020019161079f565b820191905f5260205f20905b81548152906001019060200180831161078257829003601f168201915b505050505081565b5f6107b1826117a6565b156107c5576107c083836115ed565b6107d6565b6107cf8383610900565b9050610715565b50600192915050565b5f6108036001546001600160801b03808216600160801b9092048116919091031690565b905090565b5f6001600160a01b03821615806107155750506001600160a01b03165f908152600d602052604090205460ff1690565b6108406117c9565b601461084c8282612f67565b5050565b5f61085a826117a6565b1561086f5761086a84848461148f565b610881565b61087a8484846113d3565b9050610885565b5060015b9392505050565b5f7f000000000000000000000000000000000000000000000000000000000000000046146108bc576108036117f5565b507f000000000000000000000000000000000000000000000000000000000000000090565b6108fb83838360405180602001604052805f815250610d5f565b505050565b5f6001600160a01b03831661092857604051635461585f60e01b815260040160405180910390fd5b335f8181526008602090815260408083206001600160a01b03881680855290835292819020869055518581529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350600192915050565b5f818152600b60205260409020546001600160a01b03166109ab826117a6565b6109c8576040516307ed98ed60e31b815260040160405180910390fd5b6001600160a01b0381166109ef5760405163c5723b5160e01b815260040160405180910390fd5b919050565b6109fc6117c9565b610a055f61188e565b565b610a1133826118dd565b50565b610a1c6117c9565b601055565b6004805461072890612ee4565b6001600160a01b038216610a555760405163ccea9e6f60e01b815260040160405180910390fd5b335f818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b5f6001600160a01b038316610ae857604051634e46966960e11b815260040160405180910390fd5b61088533848461194b565b5f818152600f60205260408120545f610b0b84611d20565b610b15834261303b565b610b1f919061303b565b5f8581526011602052604090205490915062093a809015610b455750600b949350505050565b610b74610b5186610efe565b6040518060400160405280600581526020016465766f312f60d81b815250611d74565b15610b845750600d949350505050565b610bb5610b9086610efe565b6040518060400160405280600781526020016665766f322f322f60c81b815250611d74565b15610bc55750600c949350505050565b610bf6610bd186610efe565b6040518060400160405280600781526020016665766f332f332f60c81b815250611d74565b15610c065750600c949350505050565b610c37610c1286610efe565b6040518060400160405280600781526020016665766f342f342f60c81b815250611d74565b15610c475750600c949350505050565b610c78610c5386610efe565b6040518060400160405280600781526020016665766f352f352f60c81b815250611d74565b15610c885750600c949350505050565b610cb9610c9486610efe565b6040518060400160405280600781526020016665766f392f392f60c81b815250611d74565b15610cc95750600c949350505050565b5f62015180610cd88385613062565b610ce2908461303b565b610cec9190613075565b9695505050505050565b6001600160a01b0381165f908152600c6020908152604091829020805483518184028101840190945280845260609392830182828015610d5357602002820191905f5260205f20905b815481526020019060010190808311610d3f575b50505050509050919050565b610d68826117a6565b610d85576040516307ed98ed60e31b815260040160405180910390fd5b610d90848484610850565b506001600160a01b0383163b15801590610e265750604051630a85bd0160e11b808252906001600160a01b0385169063150b7a0290610dd9903390899088908890600401613088565b6020604051808303815f875af1158015610df5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1991906130ba565b6001600160e01b03191614155b15610e4457604051633da6393160e01b815260040160405180910390fd5b50505050565b33610e548261098b565b6001600160a01b031614610e835760405162461bcd60e51b8152600401610e7a906130d5565b60405180910390fd5b610e8c81611d20565b5f828152601360209081526040808320939093556011905281812055517f98c21bc2032e58861a23595af0cfbce0e3221dbe1723e1823f7e779bc61ff20890610ee19083904290918252602082015260400190565b60405180910390a150565b610ef46117c9565b61084c82826118dd565b60605f60158054610f0e90612ee4565b90501115610f48576015610f2183611e2c565b604051602001610f32929190613192565b6040516020818303038152906040529050919050565b5f82604051602001610f5c91815260200190565b6040516020818303038152906040528051906020012060f81c90506060805f610f90865f908152600f602052604090205490565b905060648460ff1611610fff5760408051808201909152600581526465766f312f60d81b60208201529250610fd9610fc960cb88613062565b610fd49060016131b6565b611e2c565b604051602001610fe991906131c9565b60405160208183030381529060405291506110cc565b60a08460ff1611611024576110148187611ebc565b9250610fd9610fc960d588613062565b60d28460ff1611611049576110398187611f32565b9250610fd9610fc9607588613062565b60eb8460ff161161106e5761105e8187611fd7565b9250610fd9610fc9600588613062565b60fa8460ff16116110935761108381876120ab565b9250610fd9610fc9600288613062565b60ff8460ff16116110cc576110a881876121ae565b92506040518060400160405280600681526020016518973539b7b760d11b81525091505b5f601484846040516020016110e3939291906131f1565b60408051601f19818403018152919052979650505050505050565b336111088261098b565b6001600160a01b03161461112e5760405162461bcd60e51b8152600401610e7a906130d5565b5f818152601160205260408120549003610a11575f8181526011602090815260409182902042908190558251848152918201527fbb59a1d111e5148e18a57f7aba44e8d0e6203a977af333189ae719a05e53a5039101610ee1565b428410156111aa576040516305787bdf60e01b815260040160405180910390fd5b6111b3856117a6565b156111d1576040516303e7c1bd60e31b815260040160405180910390fd5b6001600160a01b0386166111f857604051635461585f60e01b815260040160405180910390fd5b5f600161120361088c565b6001600160a01b038a81165f818152600e602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f1981840301815282825280516020918201205f84529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa15801561130b573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811615806113405750876001600160a01b0316816001600160a01b031614155b1561135e57604051632057875960e21b815260040160405180910390fd5b6001600160a01b039081165f9081526008602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6015805461072890612ee4565b5f6001600160a01b0384166113fb57604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b03831661142257604051634e46966960e11b815260040160405180910390fd5b6001600160a01b0384165f9081526008602090815260408083203384529091529020545f19811461147b57611457838261303b565b6001600160a01b0386165f9081526008602090815260408083203384529091529020555b61148685858561194b565b95945050505050565b6001600160a01b0383166114b657604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b0382166114dd57604051634e46966960e11b815260040160405180910390fd5b5f818152600b60205260409020546001600160a01b03848116911614611515576040516282b42960e81b815260040160405180910390fd5b336001600160a01b0384161480159061155157506001600160a01b0383165f908152600a6020908152604080832033845290915290205460ff16155b801561157357505f818152600960205260409020546001600160a01b03163314155b15611590576040516282b42960e81b815260040160405180910390fd5b61159982610808565b156115b757604051635ce7539760e01b815260040160405180910390fd5b6115e283837f000000000000000000000000000000000000000000000000000000000000000061236d565b6108fb838383612426565b5f818152600b60205260409020546001600160a01b031633811480159061163757506001600160a01b0381165f908152600a6020908152604080832033845290915290205460ff16155b15611654576040516282b42960e81b815260040160405180910390fd5b5f8281526009602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6116b76117c9565b601561084c8282612f67565b6014805461072890612ee4565b6116d86117c9565b6001600160a01b03811661170157604051631e4fbdf760e01b81525f6004820152602401610e7a565b610a118161188e565b60605f8267ffffffffffffffff81111561172657611726612c0f565b60405190808252806020026020018201604052801561174f578160200160208202803683370190505b509050835b61175e84866131b6565b81101561179e57611770600182612615565b8261177b878461303b565b8151811061178b5761178b613229565b6020908102919091010152600101611754565b509392505050565b5f6117b862989680600160ff1b613062565b821180156107155750505f19141590565b5f546001600160a01b03163314610a055760405163118cdaa760e01b8152336004820152602401610e7a565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6003604051611826919061323d565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0382166119045760405163a41e3d3f60e01b815260040160405180910390fd5b8015611918576119138261267e565b611921565b611921826126b1565b6001600160a01b03919091165f908152600d60205260409020805460ff1916911515919091179055565b6001600160a01b038381165f9081526007602052604080822054928516825281205490919061197b86868661236d565b5f61198587610808565b90505f61199187610808565b905081801561199d5750805b611d12578115611a5e575f7f00000000000000000000000000000000000000000000000000000000000000006010546119d69190613248565b6119e09085613075565b7f0000000000000000000000000000000000000000000000000000000000000000601054611a0e9190613248565b6001600160a01b038a165f90815260076020526040902054611a309190613075565b611a3a919061303b565b90505f5b81811015611a5757611a4f8961273b565b600101611a3e565b5050611d12565b8015611b14575f7f0000000000000000000000000000000000000000000000000000000000000000601054611a939190613248565b6001600160a01b038a165f90815260076020526040902054611ab59190613075565b7f0000000000000000000000000000000000000000000000000000000000000000601054611ae39190613248565b611aed9087613075565b611af7919061303b565b90505f5b81811015611a5757611b0c8a61282f565b600101611afb565b5f7f0000000000000000000000000000000000000000000000000000000000000000601054611b439190613248565b611b4d9088613075565b90505f5b81811015611bcb576001600160a01b038a165f908152600c6020526040812054611b7d9060019061303b565b6001600160a01b038c165f908152600c602052604081208054929350909183908110611bab57611bab613229565b905f5260205f2001549050611bc18c8c83612426565b5050600101611b51565b50807f0000000000000000000000000000000000000000000000000000000000000000601054611bfb9190613248565b6001600160a01b038b165f90815260076020526040902054611c1d9190613075565b7f0000000000000000000000000000000000000000000000000000000000000000601054611c4b9190613248565b611c559088613075565b611c5f919061303b565b1115611c6e57611c6e8961282f565b807f0000000000000000000000000000000000000000000000000000000000000000601054611c9d9190613248565b611ca79086613075565b7f0000000000000000000000000000000000000000000000000000000000000000601054611cd59190613248565b6001600160a01b038b165f90815260076020526040902054611cf79190613075565b611d01919061303b565b1115611d1057611d108861273b565b505b506001979650505050505050565b5f8181526011602052604081205415611d62575f82815260116020908152604080832054601390925290912054611d589042906131b6565b610715919061303b565b505f9081526013602052604090205490565b5f8282825b81518351611d87919061303b565b8111611e215760015f5b8351811015611dfa57838181518110611dac57611dac613229565b01602001516001600160f81b03191685611dc683866131b6565b81518110611dd657611dd6613229565b01602001516001600160f81b03191614611df2575f9150611dfa565b600101611d91565b508015611e0e576001945050505050610715565b5080611e198161325f565b915050611d79565b505f95945050505050565b60605f611e38836128ac565b60010190505f8167ffffffffffffffff811115611e5757611e57612c0f565b6040519080825280601f01601f191660200182016040528015611e81576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084611e8b57509392505050565b60605f611ec883611d20565b611ed2854261303b565b611edc919061303b565b905062093a808110611f0d57505060408051808201909152600781526665766f322f322f60c81b6020820152610715565b505060408051808201909152600781526665766f322f312f60c81b6020820152610715565b60605f611f3e83611d20565b611f48854261303b565b611f52919061303b565b9050621275008110611f8357505060408051808201909152600781526665766f332f332f60c81b6020820152610715565b62093a808110611fb257505060408051808201909152600781526665766f332f322f60c81b6020820152610715565b505060408051808201909152600781526665766f332f312f60c81b6020820152610715565b60605f611fe383611d20565b611fed854261303b565b611ff7919061303b565b9050621baf80811061202857505060408051808201909152600781526665766f342f342f60c81b6020820152610715565b62127500811061205757505060408051808201909152600781526665766f342f332f60c81b6020820152610715565b62093a80811061208657505060408051808201909152600781526665766f342f322f60c81b6020820152610715565b505060408051808201909152600781526665766f342f312f60c81b6020820152610715565b60605f6120b783611d20565b6120c1854261303b565b6120cb919061303b565b90506224ea0081106120fc57505060408051808201909152600781526665766f352f352f60c81b6020820152610715565b621baf80811061212b57505060408051808201909152600781526665766f352f342f60c81b6020820152610715565b62127500811061215a57505060408051808201909152600781526665766f352f332f60c81b6020820152610715565b62093a80811061218957505060408051808201909152600781526665766f352f322f60c81b6020820152610715565b505060408051808201909152600781526665766f352f312f60c81b6020820152610715565b60605f6121ba83611d20565b6121c4854261303b565b6121ce919061303b565b90506249d40081106121ff57505060408051808201909152600781526665766f392f392f60c81b6020820152610715565b62409980811061222e57505060408051808201909152600781526665766f392f382f60c81b6020820152610715565b62375f00811061225d57505060408051808201909152600781526665766f392f372f60c81b6020820152610715565b622e2480811061228c57505060408051808201909152600781526665766f392f362f60c81b6020820152610715565b6224ea0081106122bb57505060408051808201909152600781526665766f392f352f60c81b6020820152610715565b621baf8081106122ea57505060408051808201909152600781526665766f392f342f60c81b6020820152610715565b62127500811061231957505060408051808201909152600781526665766f392f332f60c81b6020820152610715565b62093a80811061234857505060408051808201909152600781526665766f392f322f60c81b6020820152610715565b505060408051808201909152600781526665766f392f312f60c81b6020820152610715565b6001600160a01b038316612397578060055f82825461238c91906131b6565b909155506123c49050565b6001600160a01b0383165f90815260076020526040812080548392906123be90849061303b565b90915550505b6001600160a01b038083165f81815260076020526040908190208054850190555190918516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906124199085815260200190565b60405180910390a3505050565b6001600160a01b03831615612527575f81815260096020908152604080832080546001600160a01b03191690556001600160a01b0386168352600c909152812080546124749060019061303b565b8154811061248457612484613229565b905f5260205f20015490508181146124ec575f828152600b602052604081205460a01c6001600160a01b0386165f908152600c6020526040902080549192508391839081106124d5576124d5613229565b5f918252602090912001556124ea8282612983565b505b6001600160a01b0384165f908152600c6020526040902080548061251257612512613277565b600190038181905f5260205f20015f90559055505b6001600160a01b0382161561259d575f818152600b6020908152604080832080546001600160a01b0319166001600160a01b038716908101909155808452600c83529083208054600181810183558286529385200185905592529054612598918391612593919061303b565b612983565b6125ac565b5f818152600b60205260408120555b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46125f6816129ed565b5f90815260116020908152604080832083905560139091528120555050565b5f61263883546001600160801b03808216600160801b9092048116919091031690565b82106126575760405163580821e760e01b815260040160405180910390fd5b5081546001600160801b039081168201165f90815260018301602052604090205492915050565b6001600160a01b0381165f908152600c6020526040812054905b818110156108fb576126a98361282f565b600101612698565b6001600160a01b0381165f908152600760205260408120546126f4907f000000000000000000000000000000000000000000000000000000000000000090613075565b90505f612715836001600160a01b03165f908152600c602052604090205490565b90505f5b612723828461303b565b811015610e44576127338461273b565b600101612719565b6001600160a01b03811661276257604051634e46966960e11b815260040160405180910390fd5b5f612781600154600160801b81046001600160801b0390811691161490565b6127965761278f6001612a34565b90506127ee565b60065f81546127a49061325f565b909155506006546001016127cb5760405163303b682f60e01b815260040160405180910390fd5b62989680600654600160ff1b6127e191906131b6565b6127eb9190613062565b90505b5f818152600b60205260409020546001600160a01b031680156128245760405163119b4fd360e11b815260040160405180910390fd5b6108fb818484612426565b6001600160a01b03811661285657604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b0381165f908152600c60205260408120805461287b9060019061303b565b8154811061288b5761288b613229565b905f5260205f20015490506128a1825f83612426565b61084c600182612aa1565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106128ea5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612916576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061293457662386f26fc10000830492506010015b6305f5e100831061294c576305f5e100830492506008015b612710831061296057612710830492506004015b60648310612972576064830492506002015b600a83106107155760010192915050565b5f828152600b60205260409020546bffffffffffffffffffffffff8211156129be57604051633f2cd0e360e21b815260040160405180910390fd5b5f928352600b60205260409092206001600160a01b039290921660a09190911b6001600160a01b031916019055565b5f818152600f602090815260409182902042908190558251848152918201527fc46c7931bda1e2e1d4f011c47e83de0acbba59885cadf0a829e3c8be59564da79101610ee1565b80545f906001600160801b03600160801b8204811691168103612a6a576040516375e52f4f60e01b815260040160405180910390fd5b5f19016001600160801b039081165f818152600185016020526040812080549190558454909216600160801b909102179092555090565b81546001600160801b038082165f190191600160801b9004811690821603612adc57604051638acb5f2760e01b815260040160405180910390fd5b6001600160801b03165f81815260018401602052604090209190915581546fffffffffffffffffffffffffffffffff1916179055565b6001600160e01b031981168114610a11575f80fd5b5f60208284031215612b37575f80fd5b813561088581612b12565b80356001600160a01b03811681146109ef575f80fd5b5f60208284031215612b68575f80fd5b61088582612b42565b5f5b83811015612b8b578181015183820152602001612b73565b50505f910152565b5f8151808452612baa816020860160208601612b71565b601f01601f19169290920160200192915050565b602081525f6108856020830184612b93565b5f60208284031215612be0575f80fd5b5035919050565b5f8060408385031215612bf8575f80fd5b612c0183612b42565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f67ffffffffffffffff80841115612c3d57612c3d612c0f565b604051601f8501601f19908116603f01168101908282118183101715612c6557612c65612c0f565b81604052809350858152868686011115612c7d575f80fd5b858560208301375f602087830101525050509392505050565b5f60208284031215612ca6575f80fd5b813567ffffffffffffffff811115612cbc575f80fd5b8201601f81018413612ccc575f80fd5b612cdb84823560208401612c23565b949350505050565b5f805f60608486031215612cf5575f80fd5b612cfe84612b42565b9250612d0c60208501612b42565b9150604084013590509250925092565b803580151581146109ef575f80fd5b5f60208284031215612d3b575f80fd5b61088582612d1c565b5f8060408385031215612d55575f80fd5b612d5e83612b42565b9150612d6c60208401612d1c565b90509250929050565b602080825282518282018190525f9190848201906040850190845b81811015612dac57835183529284019291840191600101612d90565b50909695505050505050565b5f805f8060808587031215612dcb575f80fd5b612dd485612b42565b9350612de260208601612b42565b925060408501359150606085013567ffffffffffffffff811115612e04575f80fd5b8501601f81018713612e14575f80fd5b612e2387823560208401612c23565b91505092959194509250565b5f805f805f805f60e0888a031215612e45575f80fd5b612e4e88612b42565b9650612e5c60208901612b42565b95506040880135945060608801359350608088013560ff81168114612e7f575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215612ead575f80fd5b612eb683612b42565b9150612d6c60208401612b42565b5f8060408385031215612ed5575f80fd5b50508035926020909101359150565b600181811c90821680612ef857607f821691505b602082108103612f1657634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156108fb57805f5260205f20601f840160051c81016020851015612f415750805b601f840160051c820191505b81811015612f60575f8155600101612f4d565b5050505050565b815167ffffffffffffffff811115612f8157612f81612c0f565b612f9581612f8f8454612ee4565b84612f1c565b602080601f831160018114612fc8575f8415612fb15750858301515b5f19600386901b1c1916600185901b17855561301f565b5f85815260208120601f198616915b82811015612ff657888601518255948401946001909101908401612fd7565b508582101561301357878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561071557610715613027565b634e487b7160e01b5f52601260045260245ffd5b5f826130705761307061304e565b500690565b5f826130835761308361304e565b500490565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90610cec90830184612b93565b5f602082840312156130ca575f80fd5b815161088581612b12565b6020808252602e908201527f506f6b656d6f6f6e3a2063616c6c6572206973206e6f7420746865206f776e6560408201526d391037b3103a3432903a37b5b2b760911b606082015260800190565b5f815461312f81612ee4565b60018281168015613147576001811461315c57613188565b60ff1984168752821515830287019450613188565b855f526020805f205f5b8581101561317f5781548a820152908401908201613166565b50505082870194505b5050505092915050565b5f61319d8285613123565b83516131ad818360208801612b71565b01949350505050565b8082018082111561071557610715613027565b5f82516131da818460208701612b71565b64173539b7b760d91b920191825250600501919050565b5f6131fc8286613123565b845161320c818360208901612b71565b845191019061321f818360208801612b71565b0195945050505050565b634e487b7160e01b5f52603260045260245ffd5b5f6108858284613123565b808202811582820484141761071557610715613027565b5f6001820161327057613270613027565b5060010190565b634e487b7160e01b5f52603160045260245ffdfea26469706673582212204784f1a23e942f1cabb94bcd654a201dd8dc5d8b69cc02a2254061e46fd0424164736f6c63430008180033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000494eaa9783fc44336178c18c69435273c4a22d03000000000000000000000000494eaa9783fc44336178c18c69435273c4a22d030000000000000000000000000000000000000000000000000000000000000008506f6b656d6f6f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008504f4b454d4f4f4e000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106102b1575f3560e01c806395d89b411161017b578063d36517b6116100e4578063dd6376991161009e578063e985e9c511610079578063e985e9c51461068a578063f28ca1dd146106b7578063f2fde38b146106bf578063f780bc1a146106d2575f80fd5b8063dd63769914610651578063dfabc03314610664578063e0df5b6f14610677575f80fd5b8063d36517b6146105dd578063d505accf146105f0578063d547cfb714610603578063d73d17771461060b578063d96ca0b914610614578063dd62ed3e14610627575f80fd5b8063b3f9ea3411610135578063b3f9ea3414610561578063b88d4fde14610589578063c336c8171461059c578063c5ab3ba6146105af578063c6e672b9146105b7578063c87b56dd146105ca575f80fd5b806395d89b41146104d9578063976a8435146104e1578063a22cb46514610508578063a9059cbb1461051b578063ade7f0db1461052e578063b1ab931714610541575f80fd5b806342842e0e1161021d578063715018a6116101d7578063715018a6146104745780637ecebe001461047c57806389fb4c661461049b5780638a696e50146104a35780638da5cb5b146104b65780638e0146ae146104c6575f80fd5b806342842e0e146104085780634d9660721461041b5780634f02c4201461042e5780636352211e146104375780636e8f624b1461044a57806370a0823114610455575f80fd5b806309f0ef651161026e57806309f0ef651461038357806318160ddd1461039657806318d217c31461039f57806323b872dd146103b4578063313ce567146103c75780633644e51514610400575f80fd5b806301ffc9a7146102b557806302519da3146102dd57806306fdde0314610313578063081812fc14610328578063095ea7b31461036857806309674eb01461037b575b5f80fd5b6102c86102c3366004612b27565b6106e5565b60405190151581526020015b60405180910390f35b6103056102eb366004612b58565b6001600160a01b03165f9081526007602052604090205490565b6040519081526020016102d4565b61031b61071b565b6040516102d49190612bbe565b610350610336366004612bd0565b60096020525f90815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016102d4565b6102c8610376366004612be7565b6107a7565b6103056107df565b6102c8610391366004612b58565b610808565b61030560055481565b6103b26103ad366004612c96565b610838565b005b6102c86103c2366004612ce3565b610850565b6103ee7f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff90911681526020016102d4565b61030561088c565b6103b2610416366004612ce3565b6108e1565b6102c8610429366004612be7565b610900565b61030560065481565b610350610445366004612bd0565b61098b565b610305600160ff1b81565b610305610463366004612b58565b60076020525f908152604090205481565b6103b26109f4565b61030561048a366004612b58565b600e6020525f908152604090205481565b600554610305565b6103b26104b1366004612d2b565b610a07565b5f546001600160a01b0316610350565b6103b26104d4366004612bd0565b610a14565b61031b610a21565b6103057f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b6103b2610516366004612d44565b610a2e565b6102c8610529366004612be7565b610ac0565b61030561053c366004612bd0565b610af3565b61055461054f366004612b58565b610cf6565b6040516102d49190612d75565b61030561056f366004612b58565b6001600160a01b03165f908152600c602052604090205490565b6103b2610597366004612db8565b610d5f565b6103b26105aa366004612bd0565b610e4a565b600654610305565b6103b26105c5366004612d44565b610eec565b61031b6105d8366004612bd0565b610efe565b6103b26105eb366004612bd0565b6110fe565b6103b26105fe366004612e2f565b611189565b61031b6113c6565b61030560105481565b6102c8610622366004612ce3565b6113d3565b610305610635366004612e9c565b600860209081525f928352604080842090915290825290205481565b6103b261065f366004612ce3565b61148f565b6103b2610672366004612be7565b6115ed565b6103b2610685366004612c96565b6116af565b6102c8610698366004612e9c565b600a60209081525f928352604080842090915290825290205460ff1681565b61031b6116c3565b6103b26106cd366004612b58565b6116d0565b6105546106e0366004612ec4565b61170a565b5f6001600160e01b0319821663caf91ff560e01b148061071557506001600160e01b031982166301ffc9a760e01b145b92915050565b6003805461072890612ee4565b80601f016020809104026020016040519081016040528092919081815260200182805461075490612ee4565b801561079f5780601f106107765761010080835404028352916020019161079f565b820191905f5260205f20905b81548152906001019060200180831161078257829003601f168201915b505050505081565b5f6107b1826117a6565b156107c5576107c083836115ed565b6107d6565b6107cf8383610900565b9050610715565b50600192915050565b5f6108036001546001600160801b03808216600160801b9092048116919091031690565b905090565b5f6001600160a01b03821615806107155750506001600160a01b03165f908152600d602052604090205460ff1690565b6108406117c9565b601461084c8282612f67565b5050565b5f61085a826117a6565b1561086f5761086a84848461148f565b610881565b61087a8484846113d3565b9050610885565b5060015b9392505050565b5f7f000000000000000000000000000000000000000000000000000000000000000146146108bc576108036117f5565b507fcbcd1b0efe1d164d3838177ac602ff35c8d978844c332cef616e94b412eac55690565b6108fb83838360405180602001604052805f815250610d5f565b505050565b5f6001600160a01b03831661092857604051635461585f60e01b815260040160405180910390fd5b335f8181526008602090815260408083206001600160a01b03881680855290835292819020869055518581529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350600192915050565b5f818152600b60205260409020546001600160a01b03166109ab826117a6565b6109c8576040516307ed98ed60e31b815260040160405180910390fd5b6001600160a01b0381166109ef5760405163c5723b5160e01b815260040160405180910390fd5b919050565b6109fc6117c9565b610a055f61188e565b565b610a1133826118dd565b50565b610a1c6117c9565b601055565b6004805461072890612ee4565b6001600160a01b038216610a555760405163ccea9e6f60e01b815260040160405180910390fd5b335f818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b5f6001600160a01b038316610ae857604051634e46966960e11b815260040160405180910390fd5b61088533848461194b565b5f818152600f60205260408120545f610b0b84611d20565b610b15834261303b565b610b1f919061303b565b5f8581526011602052604090205490915062093a809015610b455750600b949350505050565b610b74610b5186610efe565b6040518060400160405280600581526020016465766f312f60d81b815250611d74565b15610b845750600d949350505050565b610bb5610b9086610efe565b6040518060400160405280600781526020016665766f322f322f60c81b815250611d74565b15610bc55750600c949350505050565b610bf6610bd186610efe565b6040518060400160405280600781526020016665766f332f332f60c81b815250611d74565b15610c065750600c949350505050565b610c37610c1286610efe565b6040518060400160405280600781526020016665766f342f342f60c81b815250611d74565b15610c475750600c949350505050565b610c78610c5386610efe565b6040518060400160405280600781526020016665766f352f352f60c81b815250611d74565b15610c885750600c949350505050565b610cb9610c9486610efe565b6040518060400160405280600781526020016665766f392f392f60c81b815250611d74565b15610cc95750600c949350505050565b5f62015180610cd88385613062565b610ce2908461303b565b610cec9190613075565b9695505050505050565b6001600160a01b0381165f908152600c6020908152604091829020805483518184028101840190945280845260609392830182828015610d5357602002820191905f5260205f20905b815481526020019060010190808311610d3f575b50505050509050919050565b610d68826117a6565b610d85576040516307ed98ed60e31b815260040160405180910390fd5b610d90848484610850565b506001600160a01b0383163b15801590610e265750604051630a85bd0160e11b808252906001600160a01b0385169063150b7a0290610dd9903390899088908890600401613088565b6020604051808303815f875af1158015610df5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1991906130ba565b6001600160e01b03191614155b15610e4457604051633da6393160e01b815260040160405180910390fd5b50505050565b33610e548261098b565b6001600160a01b031614610e835760405162461bcd60e51b8152600401610e7a906130d5565b60405180910390fd5b610e8c81611d20565b5f828152601360209081526040808320939093556011905281812055517f98c21bc2032e58861a23595af0cfbce0e3221dbe1723e1823f7e779bc61ff20890610ee19083904290918252602082015260400190565b60405180910390a150565b610ef46117c9565b61084c82826118dd565b60605f60158054610f0e90612ee4565b90501115610f48576015610f2183611e2c565b604051602001610f32929190613192565b6040516020818303038152906040529050919050565b5f82604051602001610f5c91815260200190565b6040516020818303038152906040528051906020012060f81c90506060805f610f90865f908152600f602052604090205490565b905060648460ff1611610fff5760408051808201909152600581526465766f312f60d81b60208201529250610fd9610fc960cb88613062565b610fd49060016131b6565b611e2c565b604051602001610fe991906131c9565b60405160208183030381529060405291506110cc565b60a08460ff1611611024576110148187611ebc565b9250610fd9610fc960d588613062565b60d28460ff1611611049576110398187611f32565b9250610fd9610fc9607588613062565b60eb8460ff161161106e5761105e8187611fd7565b9250610fd9610fc9600588613062565b60fa8460ff16116110935761108381876120ab565b9250610fd9610fc9600288613062565b60ff8460ff16116110cc576110a881876121ae565b92506040518060400160405280600681526020016518973539b7b760d11b81525091505b5f601484846040516020016110e3939291906131f1565b60408051601f19818403018152919052979650505050505050565b336111088261098b565b6001600160a01b03161461112e5760405162461bcd60e51b8152600401610e7a906130d5565b5f818152601160205260408120549003610a11575f8181526011602090815260409182902042908190558251848152918201527fbb59a1d111e5148e18a57f7aba44e8d0e6203a977af333189ae719a05e53a5039101610ee1565b428410156111aa576040516305787bdf60e01b815260040160405180910390fd5b6111b3856117a6565b156111d1576040516303e7c1bd60e31b815260040160405180910390fd5b6001600160a01b0386166111f857604051635461585f60e01b815260040160405180910390fd5b5f600161120361088c565b6001600160a01b038a81165f818152600e602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f1981840301815282825280516020918201205f84529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa15801561130b573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811615806113405750876001600160a01b0316816001600160a01b031614155b1561135e57604051632057875960e21b815260040160405180910390fd5b6001600160a01b039081165f9081526008602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6015805461072890612ee4565b5f6001600160a01b0384166113fb57604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b03831661142257604051634e46966960e11b815260040160405180910390fd5b6001600160a01b0384165f9081526008602090815260408083203384529091529020545f19811461147b57611457838261303b565b6001600160a01b0386165f9081526008602090815260408083203384529091529020555b61148685858561194b565b95945050505050565b6001600160a01b0383166114b657604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b0382166114dd57604051634e46966960e11b815260040160405180910390fd5b5f818152600b60205260409020546001600160a01b03848116911614611515576040516282b42960e81b815260040160405180910390fd5b336001600160a01b0384161480159061155157506001600160a01b0383165f908152600a6020908152604080832033845290915290205460ff16155b801561157357505f818152600960205260409020546001600160a01b03163314155b15611590576040516282b42960e81b815260040160405180910390fd5b61159982610808565b156115b757604051635ce7539760e01b815260040160405180910390fd5b6115e283837f0000000000000000000000000000000000000000000000000de0b6b3a764000061236d565b6108fb838383612426565b5f818152600b60205260409020546001600160a01b031633811480159061163757506001600160a01b0381165f908152600a6020908152604080832033845290915290205460ff16155b15611654576040516282b42960e81b815260040160405180910390fd5b5f8281526009602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6116b76117c9565b601561084c8282612f67565b6014805461072890612ee4565b6116d86117c9565b6001600160a01b03811661170157604051631e4fbdf760e01b81525f6004820152602401610e7a565b610a118161188e565b60605f8267ffffffffffffffff81111561172657611726612c0f565b60405190808252806020026020018201604052801561174f578160200160208202803683370190505b509050835b61175e84866131b6565b81101561179e57611770600182612615565b8261177b878461303b565b8151811061178b5761178b613229565b6020908102919091010152600101611754565b509392505050565b5f6117b862989680600160ff1b613062565b821180156107155750505f19141590565b5f546001600160a01b03163314610a055760405163118cdaa760e01b8152336004820152602401610e7a565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6003604051611826919061323d565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0382166119045760405163a41e3d3f60e01b815260040160405180910390fd5b8015611918576119138261267e565b611921565b611921826126b1565b6001600160a01b03919091165f908152600d60205260409020805460ff1916911515919091179055565b6001600160a01b038381165f9081526007602052604080822054928516825281205490919061197b86868661236d565b5f61198587610808565b90505f61199187610808565b905081801561199d5750805b611d12578115611a5e575f7f0000000000000000000000000000000000000000000000000de0b6b3a76400006010546119d69190613248565b6119e09085613075565b7f0000000000000000000000000000000000000000000000000de0b6b3a7640000601054611a0e9190613248565b6001600160a01b038a165f90815260076020526040902054611a309190613075565b611a3a919061303b565b90505f5b81811015611a5757611a4f8961273b565b600101611a3e565b5050611d12565b8015611b14575f7f0000000000000000000000000000000000000000000000000de0b6b3a7640000601054611a939190613248565b6001600160a01b038a165f90815260076020526040902054611ab59190613075565b7f0000000000000000000000000000000000000000000000000de0b6b3a7640000601054611ae39190613248565b611aed9087613075565b611af7919061303b565b90505f5b81811015611a5757611b0c8a61282f565b600101611afb565b5f7f0000000000000000000000000000000000000000000000000de0b6b3a7640000601054611b439190613248565b611b4d9088613075565b90505f5b81811015611bcb576001600160a01b038a165f908152600c6020526040812054611b7d9060019061303b565b6001600160a01b038c165f908152600c602052604081208054929350909183908110611bab57611bab613229565b905f5260205f2001549050611bc18c8c83612426565b5050600101611b51565b50807f0000000000000000000000000000000000000000000000000de0b6b3a7640000601054611bfb9190613248565b6001600160a01b038b165f90815260076020526040902054611c1d9190613075565b7f0000000000000000000000000000000000000000000000000de0b6b3a7640000601054611c4b9190613248565b611c559088613075565b611c5f919061303b565b1115611c6e57611c6e8961282f565b807f0000000000000000000000000000000000000000000000000de0b6b3a7640000601054611c9d9190613248565b611ca79086613075565b7f0000000000000000000000000000000000000000000000000de0b6b3a7640000601054611cd59190613248565b6001600160a01b038b165f90815260076020526040902054611cf79190613075565b611d01919061303b565b1115611d1057611d108861273b565b505b506001979650505050505050565b5f8181526011602052604081205415611d62575f82815260116020908152604080832054601390925290912054611d589042906131b6565b610715919061303b565b505f9081526013602052604090205490565b5f8282825b81518351611d87919061303b565b8111611e215760015f5b8351811015611dfa57838181518110611dac57611dac613229565b01602001516001600160f81b03191685611dc683866131b6565b81518110611dd657611dd6613229565b01602001516001600160f81b03191614611df2575f9150611dfa565b600101611d91565b508015611e0e576001945050505050610715565b5080611e198161325f565b915050611d79565b505f95945050505050565b60605f611e38836128ac565b60010190505f8167ffffffffffffffff811115611e5757611e57612c0f565b6040519080825280601f01601f191660200182016040528015611e81576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084611e8b57509392505050565b60605f611ec883611d20565b611ed2854261303b565b611edc919061303b565b905062093a808110611f0d57505060408051808201909152600781526665766f322f322f60c81b6020820152610715565b505060408051808201909152600781526665766f322f312f60c81b6020820152610715565b60605f611f3e83611d20565b611f48854261303b565b611f52919061303b565b9050621275008110611f8357505060408051808201909152600781526665766f332f332f60c81b6020820152610715565b62093a808110611fb257505060408051808201909152600781526665766f332f322f60c81b6020820152610715565b505060408051808201909152600781526665766f332f312f60c81b6020820152610715565b60605f611fe383611d20565b611fed854261303b565b611ff7919061303b565b9050621baf80811061202857505060408051808201909152600781526665766f342f342f60c81b6020820152610715565b62127500811061205757505060408051808201909152600781526665766f342f332f60c81b6020820152610715565b62093a80811061208657505060408051808201909152600781526665766f342f322f60c81b6020820152610715565b505060408051808201909152600781526665766f342f312f60c81b6020820152610715565b60605f6120b783611d20565b6120c1854261303b565b6120cb919061303b565b90506224ea0081106120fc57505060408051808201909152600781526665766f352f352f60c81b6020820152610715565b621baf80811061212b57505060408051808201909152600781526665766f352f342f60c81b6020820152610715565b62127500811061215a57505060408051808201909152600781526665766f352f332f60c81b6020820152610715565b62093a80811061218957505060408051808201909152600781526665766f352f322f60c81b6020820152610715565b505060408051808201909152600781526665766f352f312f60c81b6020820152610715565b60605f6121ba83611d20565b6121c4854261303b565b6121ce919061303b565b90506249d40081106121ff57505060408051808201909152600781526665766f392f392f60c81b6020820152610715565b62409980811061222e57505060408051808201909152600781526665766f392f382f60c81b6020820152610715565b62375f00811061225d57505060408051808201909152600781526665766f392f372f60c81b6020820152610715565b622e2480811061228c57505060408051808201909152600781526665766f392f362f60c81b6020820152610715565b6224ea0081106122bb57505060408051808201909152600781526665766f392f352f60c81b6020820152610715565b621baf8081106122ea57505060408051808201909152600781526665766f392f342f60c81b6020820152610715565b62127500811061231957505060408051808201909152600781526665766f392f332f60c81b6020820152610715565b62093a80811061234857505060408051808201909152600781526665766f392f322f60c81b6020820152610715565b505060408051808201909152600781526665766f392f312f60c81b6020820152610715565b6001600160a01b038316612397578060055f82825461238c91906131b6565b909155506123c49050565b6001600160a01b0383165f90815260076020526040812080548392906123be90849061303b565b90915550505b6001600160a01b038083165f81815260076020526040908190208054850190555190918516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906124199085815260200190565b60405180910390a3505050565b6001600160a01b03831615612527575f81815260096020908152604080832080546001600160a01b03191690556001600160a01b0386168352600c909152812080546124749060019061303b565b8154811061248457612484613229565b905f5260205f20015490508181146124ec575f828152600b602052604081205460a01c6001600160a01b0386165f908152600c6020526040902080549192508391839081106124d5576124d5613229565b5f918252602090912001556124ea8282612983565b505b6001600160a01b0384165f908152600c6020526040902080548061251257612512613277565b600190038181905f5260205f20015f90559055505b6001600160a01b0382161561259d575f818152600b6020908152604080832080546001600160a01b0319166001600160a01b038716908101909155808452600c83529083208054600181810183558286529385200185905592529054612598918391612593919061303b565b612983565b6125ac565b5f818152600b60205260408120555b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46125f6816129ed565b5f90815260116020908152604080832083905560139091528120555050565b5f61263883546001600160801b03808216600160801b9092048116919091031690565b82106126575760405163580821e760e01b815260040160405180910390fd5b5081546001600160801b039081168201165f90815260018301602052604090205492915050565b6001600160a01b0381165f908152600c6020526040812054905b818110156108fb576126a98361282f565b600101612698565b6001600160a01b0381165f908152600760205260408120546126f4907f0000000000000000000000000000000000000000000000000de0b6b3a764000090613075565b90505f612715836001600160a01b03165f908152600c602052604090205490565b90505f5b612723828461303b565b811015610e44576127338461273b565b600101612719565b6001600160a01b03811661276257604051634e46966960e11b815260040160405180910390fd5b5f612781600154600160801b81046001600160801b0390811691161490565b6127965761278f6001612a34565b90506127ee565b60065f81546127a49061325f565b909155506006546001016127cb5760405163303b682f60e01b815260040160405180910390fd5b62989680600654600160ff1b6127e191906131b6565b6127eb9190613062565b90505b5f818152600b60205260409020546001600160a01b031680156128245760405163119b4fd360e11b815260040160405180910390fd5b6108fb818484612426565b6001600160a01b03811661285657604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b0381165f908152600c60205260408120805461287b9060019061303b565b8154811061288b5761288b613229565b905f5260205f20015490506128a1825f83612426565b61084c600182612aa1565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106128ea5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612916576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061293457662386f26fc10000830492506010015b6305f5e100831061294c576305f5e100830492506008015b612710831061296057612710830492506004015b60648310612972576064830492506002015b600a83106107155760010192915050565b5f828152600b60205260409020546bffffffffffffffffffffffff8211156129be57604051633f2cd0e360e21b815260040160405180910390fd5b5f928352600b60205260409092206001600160a01b039290921660a09190911b6001600160a01b031916019055565b5f818152600f602090815260409182902042908190558251848152918201527fc46c7931bda1e2e1d4f011c47e83de0acbba59885cadf0a829e3c8be59564da79101610ee1565b80545f906001600160801b03600160801b8204811691168103612a6a576040516375e52f4f60e01b815260040160405180910390fd5b5f19016001600160801b039081165f818152600185016020526040812080549190558454909216600160801b909102179092555090565b81546001600160801b038082165f190191600160801b9004811690821603612adc57604051638acb5f2760e01b815260040160405180910390fd5b6001600160801b03165f81815260018401602052604090209190915581546fffffffffffffffffffffffffffffffff1916179055565b6001600160e01b031981168114610a11575f80fd5b5f60208284031215612b37575f80fd5b813561088581612b12565b80356001600160a01b03811681146109ef575f80fd5b5f60208284031215612b68575f80fd5b61088582612b42565b5f5b83811015612b8b578181015183820152602001612b73565b50505f910152565b5f8151808452612baa816020860160208601612b71565b601f01601f19169290920160200192915050565b602081525f6108856020830184612b93565b5f60208284031215612be0575f80fd5b5035919050565b5f8060408385031215612bf8575f80fd5b612c0183612b42565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f67ffffffffffffffff80841115612c3d57612c3d612c0f565b604051601f8501601f19908116603f01168101908282118183101715612c6557612c65612c0f565b81604052809350858152868686011115612c7d575f80fd5b858560208301375f602087830101525050509392505050565b5f60208284031215612ca6575f80fd5b813567ffffffffffffffff811115612cbc575f80fd5b8201601f81018413612ccc575f80fd5b612cdb84823560208401612c23565b949350505050565b5f805f60608486031215612cf5575f80fd5b612cfe84612b42565b9250612d0c60208501612b42565b9150604084013590509250925092565b803580151581146109ef575f80fd5b5f60208284031215612d3b575f80fd5b61088582612d1c565b5f8060408385031215612d55575f80fd5b612d5e83612b42565b9150612d6c60208401612d1c565b90509250929050565b602080825282518282018190525f9190848201906040850190845b81811015612dac57835183529284019291840191600101612d90565b50909695505050505050565b5f805f8060808587031215612dcb575f80fd5b612dd485612b42565b9350612de260208601612b42565b925060408501359150606085013567ffffffffffffffff811115612e04575f80fd5b8501601f81018713612e14575f80fd5b612e2387823560208401612c23565b91505092959194509250565b5f805f805f805f60e0888a031215612e45575f80fd5b612e4e88612b42565b9650612e5c60208901612b42565b95506040880135945060608801359350608088013560ff81168114612e7f575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215612ead575f80fd5b612eb683612b42565b9150612d6c60208401612b42565b5f8060408385031215612ed5575f80fd5b50508035926020909101359150565b600181811c90821680612ef857607f821691505b602082108103612f1657634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156108fb57805f5260205f20601f840160051c81016020851015612f415750805b601f840160051c820191505b81811015612f60575f8155600101612f4d565b5050505050565b815167ffffffffffffffff811115612f8157612f81612c0f565b612f9581612f8f8454612ee4565b84612f1c565b602080601f831160018114612fc8575f8415612fb15750858301515b5f19600386901b1c1916600185901b17855561301f565b5f85815260208120601f198616915b82811015612ff657888601518255948401946001909101908401612fd7565b508582101561301357878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561071557610715613027565b634e487b7160e01b5f52601260045260245ffd5b5f826130705761307061304e565b500690565b5f826130835761308361304e565b500490565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90610cec90830184612b93565b5f602082840312156130ca575f80fd5b815161088581612b12565b6020808252602e908201527f506f6b656d6f6f6e3a2063616c6c6572206973206e6f7420746865206f776e6560408201526d391037b3103a3432903a37b5b2b760911b606082015260800190565b5f815461312f81612ee4565b60018281168015613147576001811461315c57613188565b60ff1984168752821515830287019450613188565b855f526020805f205f5b8581101561317f5781548a820152908401908201613166565b50505082870194505b5050505092915050565b5f61319d8285613123565b83516131ad818360208801612b71565b01949350505050565b8082018082111561071557610715613027565b5f82516131da818460208701612b71565b64173539b7b760d91b920191825250600501919050565b5f6131fc8286613123565b845161320c818360208901612b71565b845191019061321f818360208801612b71565b0195945050505050565b634e487b7160e01b5f52603260045260245ffd5b5f6108858284613123565b808202811582820484141761071557610715613027565b5f6001820161327057613270613027565b5060010190565b634e487b7160e01b5f52603160045260245ffdfea26469706673582212204784f1a23e942f1cabb94bcd654a201dd8dc5d8b69cc02a2254061e46fd0424164736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000494eaa9783fc44336178c18c69435273c4a22d03000000000000000000000000494eaa9783fc44336178c18c69435273c4a22d030000000000000000000000000000000000000000000000000000000000000008506f6b656d6f6f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008504f4b454d4f4f4e000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name_ (string): Pokemoon
Arg [1] : symbol_ (string): POKEMOON
Arg [2] : decimals_ (uint8): 18
Arg [3] : maxTotalSupplyERC721_ (uint256): 1000000
Arg [4] : initialOwner_ (address): 0x494EAA9783fC44336178C18C69435273c4a22D03
Arg [5] : initialMintRecipient_ (address): 0x494EAA9783fC44336178C18C69435273c4a22D03
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [3] : 00000000000000000000000000000000000000000000000000000000000f4240
Arg [4] : 000000000000000000000000494eaa9783fc44336178c18c69435273c4a22d03
Arg [5] : 000000000000000000000000494eaa9783fc44336178c18c69435273c4a22d03
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [7] : 506f6b656d6f6f6e000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [9] : 504f4b454d4f4f4e000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.