Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Kubz
Compiler Version
v0.8.16+commit.07a7930e
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.16;
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
// import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
// import "@openzeppelin/contracts/utils/Strings.sol";
import "./Guardian/Erc721LockRegistry.sol";
import "./OPR/upgradeable/DefaultOperatorFiltererUpgradeable.sol";
import "./interfaces/IBreedingInfoV2.sol";
// import "hardhat/console.sol";
contract Kubz is
ERC721x,
DefaultOperatorFiltererUpgradeable,
ReentrancyGuardUpgradeable
{
IBreedingInfoV2 public genesisContract;
uint256 public MAX_SUPPLY;
uint256 public BREED_PER_SECONDS;
// uint256 public claimStartAfter;
// mapping(address => bool) public hasClaimed;
// address public signer;
string public baseTokenURI;
string public tokenURISuffix;
string public tokenURIOverride;
bool public canStake;
mapping(uint256 => uint256) public tokensLastStakedAt; // tokenId => timestamp
event Stake(uint256 indexed tokenId, address indexed by, uint256 stakedAt);
event Unstake(
uint256 indexed tokenId,
address indexed by,
uint256 stakedAt,
uint256 unstakedAt
);
bool public canBreed;
// genesis tokenId => (genesis) getHoldingSinceExternal(tokenId) => breed count
mapping(uint256 => mapping(uint256 => uint256)) public breedMap;
event Breed(
uint256 indexed genesisTokenId,
address indexed genesisTokenOwner,
uint256 babyCount
);
// V2
uint256 public tolStart;
/* V3: unused */ mapping(uint256 => mapping(address => uint256)) tokenOwnershipsLengths; // tokenId => address => [token] holded how long by [address] in seconds
mapping(uint256 => uint256) public holdingSinceOverride; // tokenId => holdingSince
function initialize(
string memory baseURI,
address genesisContractAddress /*, address signerAddress*/
) public initializer {
ERC721x.__ERC721x_init("Kubz", "Kubz");
ReentrancyGuardUpgradeable.__ReentrancyGuard_init();
baseTokenURI = baseURI;
genesisContract = IBreedingInfoV2(genesisContractAddress);
MAX_SUPPLY = 10000;
BREED_PER_SECONDS = 30 days;
// signer = signerAddress;
}
function initializeV2() public onlyOwner reinitializer(2) {
DefaultOperatorFiltererUpgradeable.__DefaultOperatorFilterer_init();
}
// =============== AIR DROP ===============
function airdrop(address receiver, uint256 tokenAmount) external onlyOwner {
safeMint(receiver, tokenAmount);
}
function airdropList(address[] calldata receivers) external onlyOwner {
require(receivers.length >= 1, "at least 1 receiver");
for (uint256 i = 0; i < receivers.length; i++) {
safeMint(receivers[i], 1);
}
}
function airdropListWithAmounts(
address[] calldata receivers,
uint256[] calldata amounts
) external onlyOwner {
require(receivers.length >= 1, "at least 1 receiver");
for (uint256 i = 0; i < receivers.length; i++) {
safeMint(receivers[i], amounts[i]);
}
}
function safeMint(address receiver, uint256 quantity) internal {
require(_totalMinted() + quantity <= MAX_SUPPLY, "exceed MAX_SUPPLY");
_mint(receiver, quantity);
}
// =============== SUPPLY CONTROL ===============
function burnSupply(uint256 maxSupplyNew) external onlyOwner {
require(maxSupplyNew > 0, "new max supply should > 0");
require(maxSupplyNew < MAX_SUPPLY, "can only reduce max supply");
require(
maxSupplyNew >= _totalMinted(),
"cannot burn more than current supply"
);
MAX_SUPPLY = maxSupplyNew;
}
// =============== Breed ===============
function setCanBreed(bool b) external onlyOwner {
canBreed = b;
}
function setBreedPerDays(uint256 d) external onlyOwner {
require(d >= 1);
BREED_PER_SECONDS = d * 1 days;
}
function getCanBreedCount(uint256 genesisTokenId)
external
view
returns (uint256)
{
require(canBreed, "breeding not open");
require(
address(genesisContract) != address(0),
"genesisContract not set"
);
uint256 hse = genesisContract.getHoldingSinceExternal(genesisTokenId);
if (hse == 0) return 0;
uint256 holdingForSeconds = block.timestamp - hse;
uint256 canBreedCount = holdingForSeconds / BREED_PER_SECONDS;
uint256 alreadyBreedCount = breedMap[genesisTokenId][hse];
return canBreedCount - alreadyBreedCount;
}
// Breed
function breed(uint256 genesisTokenId, uint256 count)
external
nonReentrant
{
require(canBreed, "breeding not open");
require(
address(genesisContract) != address(0),
"genesisContract not set"
);
require(
msg.sender == genesisContract.ownerOfGenesis(genesisTokenId),
"Not owner of genesis tokenId"
);
require(count >= 1, "should breed at least 1");
uint256 hse = genesisContract.getHoldingSinceExternal(genesisTokenId);
uint256 holdingForSeconds = block.timestamp - hse;
uint256 canBreedCount = holdingForSeconds / BREED_PER_SECONDS;
uint256 alreadyBreedCount = breedMap[genesisTokenId][hse];
require(
alreadyBreedCount + count <= canBreedCount,
"Not ready to breed that many babies"
);
breedMap[genesisTokenId][hse] += count;
safeMint(msg.sender, count);
emit Breed(genesisTokenId, msg.sender, count);
}
// =============== BASE URI ===============
function compareStrings(string memory a, string memory b)
public
pure
returns (bool)
{
return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
}
function _baseURI() internal view virtual override returns (string memory) {
return baseTokenURI;
}
function tokenURI(uint256 _tokenId)
public
view
override(ERC721AUpgradeable, IERC721AUpgradeable)
returns (string memory)
{
if (bytes(tokenURIOverride).length > 0) {
return tokenURIOverride;
}
return string.concat(super.tokenURI(_tokenId), tokenURISuffix);
}
function setBaseURI(string calldata baseURI) external onlyOwner {
baseTokenURI = baseURI;
}
function setTokenURISuffix(string calldata _tokenURISuffix)
external
onlyOwner
{
if (compareStrings(_tokenURISuffix, "!empty!")) {
tokenURISuffix = "";
} else {
tokenURISuffix = _tokenURISuffix;
}
}
function setTokenURIOverride(string calldata _tokenURIOverride)
external
onlyOwner
{
if (compareStrings(_tokenURIOverride, "!empty!")) {
tokenURIOverride = "";
} else {
tokenURIOverride = _tokenURIOverride;
}
}
// =============== MARKETPLACE CONTROL ===============
function transferFrom(
address _from,
address _to,
uint256 _tokenId
) public virtual override(ERC721x) onlyAllowedOperator(_from) {
require(
tokensLastStakedAt[_tokenId] == 0,
"Cannot transfer staked token"
);
holdingSinceOverride[_tokenId] = 0;
super.transferFrom(_from, _to, _tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override(ERC721x) onlyAllowedOperator(from) {
require(
tokensLastStakedAt[tokenId] == 0,
"Cannot transfer staked token"
);
holdingSinceOverride[tokenId] = 0;
super.safeTransferFrom(from, to, tokenId, data);
}
// =============== Stake ===============
function stake(uint256 tokenId) public nonReentrant {
require(canStake, "staking not open");
require(
msg.sender == ownerOf(tokenId) || msg.sender == owner(),
"caller must be owner of token or contract owner"
);
require(tokensLastStakedAt[tokenId] == 0, "already staking");
tokensLastStakedAt[tokenId] = block.timestamp;
emit Stake(tokenId, msg.sender, tokensLastStakedAt[tokenId]);
}
function unstake(uint256 tokenId) public nonReentrant {
require(
msg.sender == ownerOf(tokenId) || msg.sender == owner(),
"caller must be owner of token or contract owner"
);
require(tokensLastStakedAt[tokenId] > 0, "not staking");
uint256 lsa = tokensLastStakedAt[tokenId];
tokensLastStakedAt[tokenId] = 0;
emit Unstake(tokenId, msg.sender, block.timestamp, lsa);
}
function setTokensStakeStatus(uint256[] memory tokenIds, bool setStake)
external
nonReentrant
{
for (uint256 i; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
if (setStake) {
stake(tokenId);
} else {
unstake(tokenId);
}
}
}
function setCanStake(bool b) external onlyOwner {
canStake = b;
}
// =============== TOKEN TRANSFER RECORD ===============
function keepTOLTransferFrom(
address from,
address to,
uint256 tokenId
) public {
require(
ownerOf(tokenId) == from,
"Only token owner can do keep TOL transfer"
);
require(msg.sender == from, "Sender must be from token owner");
require(from != to, "From and To must be different");
if (holdingSinceOverride[tokenId] == 0) {
uint256 holdingSince = explicitOwnershipOf(tokenId).startTimestamp;
holdingSinceOverride[tokenId] = holdingSince;
}
super.transferFrom(from, to, tokenId);
}
function setTOLStart(uint256 ts) external onlyOwner {
tolStart = ts;
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function getHoldingLength(uint256 tokenId) internal view returns (uint256) {
uint256 holdingLength;
if (holdingSinceOverride[tokenId] > 0) {
holdingLength =
block.timestamp -
max(holdingSinceOverride[tokenId], tolStart);
} else {
holdingLength =
block.timestamp -
max(explicitOwnershipOf(tokenId).startTimestamp, tolStart);
}
return holdingLength;
}
function getTokenOwnershipLength(uint256 tokenId)
public
view
returns (uint256)
{
uint256 holdingLength = getHoldingLength(tokenId);
// holdingLength += tokenOwnershipsLengths[tokenId][owner];
holdingLength /= 5;
return holdingLength;
}
function getTokenOwnershipLengths(uint256[] calldata tokenIds)
public
view
returns (uint256[] memory)
{
uint256[] memory ret = new uint256[](tokenIds.length);
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
ret[i] = getTokenOwnershipLength(tokenId);
}
return ret;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.14;
/*
* ,_,
* (',')
* {/"\}
* -"-"-
*/
import "./ERC721ANamable.sol";
import "./LockRegistry.sol";
import "./IERC721x.sol";
contract ERC721x is ERC721ANamable, LockRegistry {
/*
* bytes4(keccak256('freeId(uint256,address)')) == 0x94d216d6
* bytes4(keccak256('isUnlocked(uint256)')) == 0x72abc8b7
* bytes4(keccak256('lockCount(uint256)')) == 0x650b00f6
* bytes4(keccak256('lockId(uint256)')) == 0x2799cde0
* bytes4(keccak256('lockMap(uint256,uint256)')) == 0x2cba8123
* bytes4(keccak256('lockMapIndex(uint256,address)')) == 0x09308e5d
* bytes4(keccak256('unlockId(uint256)')) == 0x40a9c8df
* bytes4(keccak256('approvedContract(address)')) == 0xb1a6505f
*
* => 0x94d216d6 ^ 0x72abc8b7 ^ 0x650b00f6 ^ 0x2799cde0 ^
* 0x2cba8123 ^ 0x09308e5d ^ 0x40a9c8df ^ 0xb1a6505f == 0x706e8489
*/
bytes4 private constant _INTERFACE_ID_ERC721x = 0x706e8489;
function __ERC721x_init(string memory _name, string memory _symbol)
internal
onlyInitializing
{
ERC721ANamable.__ERC721ANamable_init(_name, _symbol);
LockRegistry.__LockRegistry_init();
}
function supportsInterface(bytes4 _interfaceId)
public
view
virtual
override(ERC721AUpgradeable, IERC721AUpgradeable)
returns (bool)
{
return
_interfaceId == _INTERFACE_ID_ERC721x ||
super.supportsInterface(_interfaceId);
}
function transferFrom(
address _from,
address _to,
uint256 _tokenId
) public virtual override(ERC721AUpgradeable, IERC721AUpgradeable) {
require(isUnlocked(_tokenId), "Token is locked");
ERC721AUpgradeable.transferFrom(_from, _to, _tokenId);
}
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId,
bytes memory _data
) public virtual override(ERC721AUpgradeable, IERC721AUpgradeable) {
require(isUnlocked(_tokenId), "Token is locked");
ERC721AUpgradeable.safeTransferFrom(
_from,
_to,
_tokenId,
_data
);
}
function lockId(uint256 _id) external virtual override {
require(_exists(_id), "Token !exist");
_lockId(_id);
}
function unlockId(uint256 _id) external virtual override {
require(_exists(_id), "Token !exist");
_unlockId(_id);
}
function freeId(uint256 _id, address _contract) external virtual override {
require(_exists(_id), "Token !exist");
_freeId(_id, _contract);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {OperatorFiltererUpgradeable} from "./OperatorFiltererUpgradeable.sol";
abstract contract DefaultOperatorFiltererUpgradeable is OperatorFiltererUpgradeable {
address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);
function __DefaultOperatorFilterer_init() public onlyInitializing {
OperatorFiltererUpgradeable.__OperatorFilterer_init(DEFAULT_SUBSCRIPTION, true);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
interface IBreedingInfoV2 {
function getHoldingSinceExternal(uint256 tokenId) external view returns (uint256);
function ownerOfGenesis(uint256 tokenId) external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
* initialization step. This is essential to configure modules that are added through upgrades and that require
* initialization.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;
import "erc721a-upgradeable/contracts/extensions/ERC721AQueryableUpgradeable.sol";
contract ERC721ANamable is ERC721AQueryableUpgradeable {
mapping(uint256 => string) public bio;
// Mapping from token ID to name
mapping(uint256 => string) private _tokenName;
// Mapping if certain name string has already been reserved
mapping(string => bool) private _nameReserved;
event NameChange(uint256 indexed tokenId, string newName);
event BioChange(uint256 indexed tokenId, string bio);
function __ERC721ANamable_init(string memory _name, string memory _symbol)
internal
initializerERC721A
{
ERC721AUpgradeable.__ERC721A_init(_name, _symbol);
}
function changeBio(uint256 _tokenId, string memory _bio) public virtual {
address owner = ownerOf(_tokenId);
require(msg.sender == owner, "ERC721: caller is not the owner");
bio[_tokenId] = _bio;
emit BioChange(_tokenId, _bio);
}
function changeName(uint256 tokenId, string memory newName) public virtual {
address owner = ownerOf(tokenId);
require(msg.sender == owner, "ERC721: caller is not the owner");
require(validateName(newName) == true, "Not a valid new name");
require(
sha256(bytes(newName)) != sha256(bytes(_tokenName[tokenId])),
"New name is same as the current one"
);
require(isNameReserved(newName) == false, "Name already reserved");
// If already named, dereserve old name
if (bytes(_tokenName[tokenId]).length > 0) {
toggleReserveName(_tokenName[tokenId], false);
}
toggleReserveName(newName, true);
_tokenName[tokenId] = newName;
emit NameChange(tokenId, newName);
}
/**
* @dev Reserves the name if isReserve is set to true, de-reserves if set to false
*/
function toggleReserveName(string memory str, bool isReserve) internal {
_nameReserved[toLower(str)] = isReserve;
}
/**
* @dev Returns name of the NFT at index.
*/
function tokenNameByIndex(uint256 index)
public
view
returns (string memory)
{
return _tokenName[index];
}
/**
* @dev Returns if the name has been reserved.
*/
function isNameReserved(string memory nameString)
public
view
returns (bool)
{
return _nameReserved[toLower(nameString)];
}
function validateName(string memory str) public pure returns (bool) {
bytes memory b = bytes(str);
if (b.length < 1) return false;
if (b.length > 25) return false; // Cannot be longer than 25 characters
if (b[0] == 0x20) return false; // Leading space
if (b[b.length - 1] == 0x20) return false; // Trailing space
bytes1 lastChar = b[0];
for (uint256 i; i < b.length; i++) {
bytes1 char = b[i];
if (char == 0x20 && lastChar == 0x20) return false; // Cannot contain continous spaces
if (
!(char >= 0x30 && char <= 0x39) && //9-0
!(char >= 0x41 && char <= 0x5A) && //A-Z
!(char >= 0x61 && char <= 0x7A) && //a-z
!(char == 0x20) //space
) return false;
lastChar = char;
}
return true;
}
/**
* @dev Converts the string to lowercase
*/
function toLower(string memory str) public pure returns (string memory) {
bytes memory bStr = bytes(str);
bytes memory bLower = new bytes(bStr.length);
for (uint256 i = 0; i < bStr.length; i++) {
// Uppercase character
if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {
bLower[i] = bytes1(uint8(bStr[i]) + 32);
} else {
bLower[i] = bStr[i];
}
}
return string(bLower);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.14;
/*
* ,_,
* (',')
* {/"\}
* -"-"-
*/
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
// import "@openzeppelin/contracts/access/Ownable.sol";
import "./IERC721x.sol";
abstract contract LockRegistry is OwnableUpgradeable, IERC721x {
mapping(address => bool) public override approvedContract;
mapping(uint256 => uint256) public override lockCount;
mapping(uint256 => mapping(uint256 => address)) public override lockMap;
mapping(uint256 => mapping(address => uint256))
public
override lockMapIndex;
event TokenLocked(
uint256 indexed tokenId,
address indexed approvedContract
);
event TokenUnlocked(
uint256 indexed tokenId,
address indexed approvedContract
);
function __LockRegistry_init() internal onlyInitializing {
OwnableUpgradeable.__Ownable_init();
}
function isUnlocked(uint256 _id) public view override returns (bool) {
return lockCount[_id] == 0;
}
function updateApprovedContracts(
address[] calldata _contracts,
bool[] calldata _values
) external onlyOwner {
require(_contracts.length == _values.length, "!length");
for (uint256 i = 0; i < _contracts.length; i++)
approvedContract[_contracts[i]] = _values[i];
}
function _lockId(uint256 _id) internal {
require(approvedContract[msg.sender], "Cannot update map");
require(
lockMapIndex[_id][msg.sender] == 0,
"ID already locked by caller"
);
uint256 count = lockCount[_id] + 1;
lockMap[_id][count] = msg.sender;
lockMapIndex[_id][msg.sender] = count;
lockCount[_id]++;
emit TokenLocked(_id, msg.sender);
}
function _unlockId(uint256 _id) internal {
require(approvedContract[msg.sender], "Cannot update map");
uint256 index = lockMapIndex[_id][msg.sender];
require(index != 0, "ID not locked by caller");
uint256 last = lockCount[_id];
if (index != last) {
address lastContract = lockMap[_id][last];
lockMap[_id][index] = lastContract;
lockMap[_id][last] = address(0);
lockMapIndex[_id][lastContract] = index;
} else lockMap[_id][index] = address(0);
lockMapIndex[_id][msg.sender] = 0;
lockCount[_id]--;
emit TokenUnlocked(_id, msg.sender);
}
function _freeId(uint256 _id, address _contract) internal {
require(!approvedContract[_contract], "Cannot update map");
uint256 index = lockMapIndex[_id][_contract];
require(index != 0, "ID not locked");
uint256 last = lockCount[_id];
if (index != last) {
address lastContract = lockMap[_id][last];
lockMap[_id][index] = lastContract;
lockMap[_id][last] = address(0);
lockMapIndex[_id][lastContract] = index;
} else lockMap[_id][index] = address(0);
lockMapIndex[_id][_contract] = 0;
lockCount[_id]--;
emit TokenUnlocked(_id, _contract);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.14;
interface IERC721x {
/**
* @dev Returns if the token is locked (non-transferrable) or not.
*/
function isUnlocked(uint256 _id) external view returns (bool);
/**
* @dev Returns the amount of locks on the token.
*/
function lockCount(uint256 _tokenId) external view returns (uint256);
/**
* @dev Returns if a contract is allowed to lock/unlock tokens.
*/
function approvedContract(address _contract) external view returns (bool);
/**
* @dev Returns the contract that locked a token at a specific index in the mapping.
*/
function lockMap(uint256 _tokenId, uint256 _index)
external
view
returns (address);
/**
* @dev Returns the mapping index of a contract that locked a token.
*/
function lockMapIndex(uint256 _tokenId, address _contract)
external
view
returns (uint256);
/**
* @dev Locks a token, preventing it from being transferrable
*/
function lockId(uint256 _id) external;
/**
* @dev Unlocks a token.
*/
function unlockId(uint256 _id) external;
/**
* @dev Unlocks a token from a given contract if the contract is no longer approved.
*/
function freeId(uint256 _id, address _contract) external;
}// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.2
// Creator: Chiru Labs
pragma solidity ^0.8.4;
import './IERC721AQueryableUpgradeable.sol';
import '../ERC721AUpgradeable.sol';
import '../ERC721A__Initializable.sol';
/**
* @title ERC721AQueryable.
*
* @dev ERC721A subclass with convenience query functions.
*/
abstract contract ERC721AQueryableUpgradeable is
ERC721A__Initializable,
ERC721AUpgradeable,
IERC721AQueryableUpgradeable
{
function __ERC721AQueryable_init() internal onlyInitializingERC721A {
__ERC721AQueryable_init_unchained();
}
function __ERC721AQueryable_init_unchained() internal onlyInitializingERC721A {}
/**
* @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
*
* If the `tokenId` is out of bounds:
*
* - `addr = address(0)`
* - `startTimestamp = 0`
* - `burned = false`
* - `extraData = 0`
*
* If the `tokenId` is burned:
*
* - `addr = <Address of owner before token was burned>`
* - `startTimestamp = <Timestamp when token was burned>`
* - `burned = true`
* - `extraData = <Extra data when token was burned>`
*
* Otherwise:
*
* - `addr = <Address of owner>`
* - `startTimestamp = <Timestamp of start of ownership>`
* - `burned = false`
* - `extraData = <Extra data at start of ownership>`
*/
function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory) {
TokenOwnership memory ownership;
if (tokenId < _startTokenId() || tokenId >= _nextTokenId()) {
return ownership;
}
ownership = _ownershipAt(tokenId);
if (ownership.burned) {
return ownership;
}
return _ownershipOf(tokenId);
}
/**
* @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
* See {ERC721AQueryable-explicitOwnershipOf}
*/
function explicitOwnershipsOf(uint256[] calldata tokenIds)
external
view
virtual
override
returns (TokenOwnership[] memory)
{
unchecked {
uint256 tokenIdsLength = tokenIds.length;
TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength);
for (uint256 i; i != tokenIdsLength; ++i) {
ownerships[i] = explicitOwnershipOf(tokenIds[i]);
}
return ownerships;
}
}
/**
* @dev Returns an array of token IDs owned by `owner`,
* in the range [`start`, `stop`)
* (i.e. `start <= tokenId < stop`).
*
* This function allows for tokens to be queried if the collection
* grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
*
* Requirements:
*
* - `start < stop`
*/
function tokensOfOwnerIn(
address owner,
uint256 start,
uint256 stop
) external view virtual override returns (uint256[] memory) {
unchecked {
if (start >= stop) revert InvalidQueryRange();
uint256 tokenIdsIdx;
uint256 stopLimit = _nextTokenId();
// Set `start = max(start, _startTokenId())`.
if (start < _startTokenId()) {
start = _startTokenId();
}
// Set `stop = min(stop, stopLimit)`.
if (stop > stopLimit) {
stop = stopLimit;
}
uint256 tokenIdsMaxLength = balanceOf(owner);
// Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`,
// to cater for cases where `balanceOf(owner)` is too big.
if (start < stop) {
uint256 rangeLength = stop - start;
if (rangeLength < tokenIdsMaxLength) {
tokenIdsMaxLength = rangeLength;
}
} else {
tokenIdsMaxLength = 0;
}
uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength);
if (tokenIdsMaxLength == 0) {
return tokenIds;
}
// We need to call `explicitOwnershipOf(start)`,
// because the slot at `start` may not be initialized.
TokenOwnership memory ownership = explicitOwnershipOf(start);
address currOwnershipAddr;
// If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`.
// `ownership.address` will not be zero, as `start` is clamped to the valid token ID range.
if (!ownership.burned) {
currOwnershipAddr = ownership.addr;
}
for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) {
ownership = _ownershipAt(i);
if (ownership.burned) {
continue;
}
if (ownership.addr != address(0)) {
currOwnershipAddr = ownership.addr;
}
if (currOwnershipAddr == owner) {
tokenIds[tokenIdsIdx++] = i;
}
}
// Downsize the array to fit.
assembly {
mstore(tokenIds, tokenIdsIdx)
}
return tokenIds;
}
}
/**
* @dev Returns an array of token IDs owned by `owner`.
*
* This function scans the ownership mapping and is O(`totalSupply`) in complexity.
* It is meant to be called off-chain.
*
* See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
* multiple smaller scans if the collection is large enough to cause
* an out-of-gas error (10K collections should be fine).
*/
function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) {
unchecked {
uint256 tokenIdsIdx;
address currOwnershipAddr;
uint256 tokenIdsLength = balanceOf(owner);
uint256[] memory tokenIds = new uint256[](tokenIdsLength);
TokenOwnership memory ownership;
for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) {
ownership = _ownershipAt(i);
if (ownership.burned) {
continue;
}
if (ownership.addr != address(0)) {
currOwnershipAddr = ownership.addr;
}
if (currOwnershipAddr == owner) {
tokenIds[tokenIdsIdx++] = i;
}
}
return tokenIds;
}
}
}// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.2
// Creator: Chiru Labs
pragma solidity ^0.8.4;
import '../IERC721AUpgradeable.sol';
/**
* @dev Interface of ERC721AQueryable.
*/
interface IERC721AQueryableUpgradeable is IERC721AUpgradeable {
/**
* Invalid query range (`start` >= `stop`).
*/
error InvalidQueryRange();
/**
* @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
*
* If the `tokenId` is out of bounds:
*
* - `addr = address(0)`
* - `startTimestamp = 0`
* - `burned = false`
* - `extraData = 0`
*
* If the `tokenId` is burned:
*
* - `addr = <Address of owner before token was burned>`
* - `startTimestamp = <Timestamp when token was burned>`
* - `burned = true`
* - `extraData = <Extra data when token was burned>`
*
* Otherwise:
*
* - `addr = <Address of owner>`
* - `startTimestamp = <Timestamp of start of ownership>`
* - `burned = false`
* - `extraData = <Extra data at start of ownership>`
*/
function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory);
/**
* @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
* See {ERC721AQueryable-explicitOwnershipOf}
*/
function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory);
/**
* @dev Returns an array of token IDs owned by `owner`,
* in the range [`start`, `stop`)
* (i.e. `start <= tokenId < stop`).
*
* This function allows for tokens to be queried if the collection
* grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
*
* Requirements:
*
* - `start < stop`
*/
function tokensOfOwnerIn(
address owner,
uint256 start,
uint256 stop
) external view returns (uint256[] memory);
/**
* @dev Returns an array of token IDs owned by `owner`.
*
* This function scans the ownership mapping and is O(`totalSupply`) in complexity.
* It is meant to be called off-chain.
*
* See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
* multiple smaller scans if the collection is large enough to cause
* an out-of-gas error (10K collections should be fine).
*/
function tokensOfOwner(address owner) external view returns (uint256[] memory);
}// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.2
// Creator: Chiru Labs
pragma solidity ^0.8.4;
import './IERC721AUpgradeable.sol';
import {ERC721AStorage} from './ERC721AStorage.sol';
import './ERC721A__Initializable.sol';
/**
* @dev Interface of ERC721 token receiver.
*/
interface ERC721A__IERC721ReceiverUpgradeable {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
/**
* @title ERC721A
*
* @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
* Non-Fungible Token Standard, including the Metadata extension.
* Optimized for lower gas during batch mints.
*
* Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
* starting from `_startTokenId()`.
*
* Assumptions:
*
* - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
* - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
*/
contract ERC721AUpgradeable is ERC721A__Initializable, IERC721AUpgradeable {
using ERC721AStorage for ERC721AStorage.Layout;
// =============================================================
// CONSTANTS
// =============================================================
// Mask of an entry in packed address data.
uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;
// The bit position of `numberMinted` in packed address data.
uint256 private constant _BITPOS_NUMBER_MINTED = 64;
// The bit position of `numberBurned` in packed address data.
uint256 private constant _BITPOS_NUMBER_BURNED = 128;
// The bit position of `aux` in packed address data.
uint256 private constant _BITPOS_AUX = 192;
// Mask of all 256 bits in packed address data except the 64 bits for `aux`.
uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;
// The bit position of `startTimestamp` in packed ownership.
uint256 private constant _BITPOS_START_TIMESTAMP = 160;
// The bit mask of the `burned` bit in packed ownership.
uint256 private constant _BITMASK_BURNED = 1 << 224;
// The bit position of the `nextInitialized` bit in packed ownership.
uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;
// The bit mask of the `nextInitialized` bit in packed ownership.
uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;
// The bit position of `extraData` in packed ownership.
uint256 private constant _BITPOS_EXTRA_DATA = 232;
// Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;
// The mask of the lower 160 bits for addresses.
uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;
// The maximum `quantity` that can be minted with {_mintERC2309}.
// This limit is to prevent overflows on the address data entries.
// For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
// is required to cause an overflow, which is unrealistic.
uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;
// The `Transfer` event signature is given by:
// `keccak256(bytes("Transfer(address,address,uint256)"))`.
bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
// =============================================================
// CONSTRUCTOR
// =============================================================
function __ERC721A_init(string memory name_, string memory symbol_) internal onlyInitializingERC721A {
__ERC721A_init_unchained(name_, symbol_);
}
function __ERC721A_init_unchained(string memory name_, string memory symbol_) internal onlyInitializingERC721A {
ERC721AStorage.layout()._name = name_;
ERC721AStorage.layout()._symbol = symbol_;
ERC721AStorage.layout()._currentIndex = _startTokenId();
}
// =============================================================
// TOKEN COUNTING OPERATIONS
// =============================================================
/**
* @dev Returns the starting token ID.
* To change the starting token ID, please override this function.
*/
function _startTokenId() internal view virtual returns (uint256) {
return 0;
}
/**
* @dev Returns the next token ID to be minted.
*/
function _nextTokenId() internal view virtual returns (uint256) {
return ERC721AStorage.layout()._currentIndex;
}
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() public view virtual override returns (uint256) {
// Counter underflow is impossible as _burnCounter cannot be incremented
// more than `_currentIndex - _startTokenId()` times.
unchecked {
return ERC721AStorage.layout()._currentIndex - ERC721AStorage.layout()._burnCounter - _startTokenId();
}
}
/**
* @dev Returns the total amount of tokens minted in the contract.
*/
function _totalMinted() internal view virtual returns (uint256) {
// Counter underflow is impossible as `_currentIndex` does not decrement,
// and it is initialized to `_startTokenId()`.
unchecked {
return ERC721AStorage.layout()._currentIndex - _startTokenId();
}
}
/**
* @dev Returns the total number of tokens burned.
*/
function _totalBurned() internal view virtual returns (uint256) {
return ERC721AStorage.layout()._burnCounter;
}
// =============================================================
// ADDRESS DATA OPERATIONS
// =============================================================
/**
* @dev Returns the number of tokens in `owner`'s account.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
if (owner == address(0)) revert BalanceQueryForZeroAddress();
return ERC721AStorage.layout()._packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the number of tokens minted by `owner`.
*/
function _numberMinted(address owner) internal view returns (uint256) {
return
(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the number of tokens burned by or on behalf of `owner`.
*/
function _numberBurned(address owner) internal view returns (uint256) {
return
(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
*/
function _getAux(address owner) internal view returns (uint64) {
return uint64(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_AUX);
}
/**
* Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
* If there are multiple variables, please pack them into a uint64.
*/
function _setAux(address owner, uint64 aux) internal virtual {
uint256 packed = ERC721AStorage.layout()._packedAddressData[owner];
uint256 auxCasted;
// Cast `aux` with assembly to avoid redundant masking.
assembly {
auxCasted := aux
}
packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
ERC721AStorage.layout()._packedAddressData[owner] = packed;
}
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
// The interface IDs are constants representing the first 4 bytes
// of the XOR of all function selectors in the interface.
// See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
// (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
return
interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
}
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @dev Returns the token collection name.
*/
function name() public view virtual override returns (string memory) {
return ERC721AStorage.layout()._name;
}
/**
* @dev Returns the token collection symbol.
*/
function symbol() public view virtual override returns (string memory) {
return ERC721AStorage.layout()._symbol;
}
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
if (!_exists(tokenId)) revert URIQueryForNonexistentToken();
string memory baseURI = _baseURI();
return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, it can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return '';
}
// =============================================================
// OWNERSHIPS OPERATIONS
// =============================================================
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
return address(uint160(_packedOwnershipOf(tokenId)));
}
/**
* @dev Gas spent here starts off proportional to the maximum mint batch size.
* It gradually moves to O(1) as tokens get transferred around over time.
*/
function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {
return _unpackedOwnership(_packedOwnershipOf(tokenId));
}
/**
* @dev Returns the unpacked `TokenOwnership` struct at `index`.
*/
function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {
return _unpackedOwnership(ERC721AStorage.layout()._packedOwnerships[index]);
}
/**
* @dev Initializes the ownership slot minted at `index` for efficiency purposes.
*/
function _initializeOwnershipAt(uint256 index) internal virtual {
if (ERC721AStorage.layout()._packedOwnerships[index] == 0) {
ERC721AStorage.layout()._packedOwnerships[index] = _packedOwnershipOf(index);
}
}
/**
* Returns the packed ownership data of `tokenId`.
*/
function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) {
uint256 curr = tokenId;
unchecked {
if (_startTokenId() <= curr)
if (curr < ERC721AStorage.layout()._currentIndex) {
uint256 packed = ERC721AStorage.layout()._packedOwnerships[curr];
// If not burned.
if (packed & _BITMASK_BURNED == 0) {
// Invariant:
// There will always be an initialized ownership slot
// (i.e. `ownership.addr != address(0) && ownership.burned == false`)
// before an unintialized ownership slot
// (i.e. `ownership.addr == address(0) && ownership.burned == false`)
// Hence, `curr` will not underflow.
//
// We can directly compare the packed value.
// If the address is zero, packed will be zero.
while (packed == 0) {
packed = ERC721AStorage.layout()._packedOwnerships[--curr];
}
return packed;
}
}
}
revert OwnerQueryForNonexistentToken();
}
/**
* @dev Returns the unpacked `TokenOwnership` struct from `packed`.
*/
function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
ownership.addr = address(uint160(packed));
ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
ownership.burned = packed & _BITMASK_BURNED != 0;
ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
}
/**
* @dev Packs ownership data into a single uint256.
*/
function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {
assembly {
// Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
owner := and(owner, _BITMASK_ADDRESS)
// `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
}
}
/**
* @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
*/
function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {
// For branchless setting of the `nextInitialized` flag.
assembly {
// `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
}
}
// =============================================================
// APPROVAL OPERATIONS
// =============================================================
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the
* zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ownerOf(tokenId);
if (_msgSenderERC721A() != owner)
if (!isApprovedForAll(owner, _msgSenderERC721A())) {
revert ApprovalCallerNotOwnerNorApproved();
}
ERC721AStorage.layout()._tokenApprovals[tokenId].value = to;
emit Approval(owner, to, tokenId);
}
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();
return ERC721AStorage.layout()._tokenApprovals[tokenId].value;
}
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom}
* for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
if (operator == _msgSenderERC721A()) revert ApproveToCaller();
ERC721AStorage.layout()._operatorApprovals[_msgSenderERC721A()][operator] = approved;
emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
}
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return ERC721AStorage.layout()._operatorApprovals[owner][operator];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted. See {_mint}.
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return
_startTokenId() <= tokenId &&
tokenId < ERC721AStorage.layout()._currentIndex && // If within bounds,
ERC721AStorage.layout()._packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned.
}
/**
* @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
*/
function _isSenderApprovedOrOwner(
address approvedAddress,
address owner,
address msgSender
) private pure returns (bool result) {
assembly {
// Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
owner := and(owner, _BITMASK_ADDRESS)
// Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
msgSender := and(msgSender, _BITMASK_ADDRESS)
// `msgSender == owner || msgSender == approvedAddress`.
result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
}
}
/**
* @dev Returns the storage slot and value for the approved address of `tokenId`.
*/
function _getApprovedSlotAndAddress(uint256 tokenId)
private
view
returns (uint256 approvedAddressSlot, address approvedAddress)
{
ERC721AStorage.TokenApprovalRef storage tokenApproval = ERC721AStorage.layout()._tokenApprovals[tokenId];
// The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
assembly {
approvedAddressSlot := tokenApproval.slot
approvedAddress := sload(approvedAddressSlot)
}
}
// =============================================================
// TRANSFER OPERATIONS
// =============================================================
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner();
(uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);
// The nested ifs save around 20+ gas over a compound boolean condition.
if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();
if (to == address(0)) revert TransferToZeroAddress();
_beforeTokenTransfers(from, to, tokenId, 1);
// Clear approvals from the previous owner.
assembly {
if approvedAddress {
// This is equivalent to `delete _tokenApprovals[tokenId]`.
sstore(approvedAddressSlot, 0)
}
}
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
// Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
unchecked {
// We can directly increment and decrement the balances.
--ERC721AStorage.layout()._packedAddressData[from]; // Updates: `balance -= 1`.
++ERC721AStorage.layout()._packedAddressData[to]; // Updates: `balance += 1`.
// Updates:
// - `address` to the next owner.
// - `startTimestamp` to the timestamp of transfering.
// - `burned` to `false`.
// - `nextInitialized` to `true`.
ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData(
to,
_BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
);
// If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
uint256 nextTokenId = tokenId + 1;
// If the next slot's address is zero and not burned (i.e. packed value is zero).
if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) {
// If the next slot is within bounds.
if (nextTokenId != ERC721AStorage.layout()._currentIndex) {
// Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
emit Transfer(from, to, tokenId);
_afterTokenTransfers(from, to, tokenId, 1);
}
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, '');
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
transferFrom(from, to, tokenId);
if (to.code.length != 0)
if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
revert TransferToNonERC721ReceiverImplementer();
}
}
/**
* @dev Hook that is called before a set of serially-ordered token IDs
* are about to be transferred. This includes minting.
* And also called before burning one token.
*
* `startTokenId` - the first token ID to be transferred.
* `quantity` - the amount to be transferred.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, `tokenId` will be burned by `from`.
* - `from` and `to` are never both zero.
*/
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
/**
* @dev Hook that is called after a set of serially-ordered token IDs
* have been transferred. This includes minting.
* And also called after one token has been burned.
*
* `startTokenId` - the first token ID to be transferred.
* `quantity` - the amount to be transferred.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
* transferred to `to`.
* - When `from` is zero, `tokenId` has been minted for `to`.
* - When `to` is zero, `tokenId` has been burned by `from`.
* - `from` and `to` are never both zero.
*/
function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
*
* `from` - Previous owner of the given token ID.
* `to` - Target address that will receive the token.
* `tokenId` - Token ID to be transferred.
* `_data` - Optional data to send along with the call.
*
* Returns whether the call correctly returned the expected magic value.
*/
function _checkContractOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
try
ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data)
returns (bytes4 retval) {
return retval == ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert TransferToNonERC721ReceiverImplementer();
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
// =============================================================
// MINT OPERATIONS
// =============================================================
/**
* @dev Mints `quantity` tokens and transfers them to `to`.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `quantity` must be greater than 0.
*
* Emits a {Transfer} event for each mint.
*/
function _mint(address to, uint256 quantity) internal virtual {
uint256 startTokenId = ERC721AStorage.layout()._currentIndex;
if (quantity == 0) revert MintZeroQuantity();
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
// Overflows are incredibly unrealistic.
// `balance` and `numberMinted` have a maximum limit of 2**64.
// `tokenId` has a maximum limit of 2**256.
unchecked {
// Updates:
// - `balance += quantity`.
// - `numberMinted += quantity`.
//
// We can directly add to the `balance` and `numberMinted`.
ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);
// Updates:
// - `address` to the owner.
// - `startTimestamp` to the timestamp of minting.
// - `burned` to `false`.
// - `nextInitialized` to `quantity == 1`.
ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData(
to,
_nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
);
uint256 toMasked;
uint256 end = startTokenId + quantity;
// Use assembly to loop and emit the `Transfer` event for gas savings.
// The duplicated `log4` removes an extra check and reduces stack juggling.
// The assembly, together with the surrounding Solidity code, have been
// delicately arranged to nudge the compiler into producing optimized opcodes.
assembly {
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
toMasked := and(to, _BITMASK_ADDRESS)
// Emit the `Transfer` event.
log4(
0, // Start of data (0, since no data).
0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.
0, // `address(0)`.
toMasked, // `to`.
startTokenId // `tokenId`.
)
for {
let tokenId := add(startTokenId, 1)
} iszero(eq(tokenId, end)) {
tokenId := add(tokenId, 1)
} {
// Emit the `Transfer` event. Similar to above.
log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId)
}
}
if (toMasked == 0) revert MintToZeroAddress();
ERC721AStorage.layout()._currentIndex = end;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
/**
* @dev Mints `quantity` tokens and transfers them to `to`.
*
* This function is intended for efficient minting only during contract creation.
*
* It emits only one {ConsecutiveTransfer} as defined in
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
* instead of a sequence of {Transfer} event(s).
*
* Calling this function outside of contract creation WILL make your contract
* non-compliant with the ERC721 standard.
* For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
* {ConsecutiveTransfer} event is only permissible during contract creation.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `quantity` must be greater than 0.
*
* Emits a {ConsecutiveTransfer} event.
*/
function _mintERC2309(address to, uint256 quantity) internal virtual {
uint256 startTokenId = ERC721AStorage.layout()._currentIndex;
if (to == address(0)) revert MintToZeroAddress();
if (quantity == 0) revert MintZeroQuantity();
if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit();
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
// Overflows are unrealistic due to the above check for `quantity` to be below the limit.
unchecked {
// Updates:
// - `balance += quantity`.
// - `numberMinted += quantity`.
//
// We can directly add to the `balance` and `numberMinted`.
ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);
// Updates:
// - `address` to the owner.
// - `startTimestamp` to the timestamp of minting.
// - `burned` to `false`.
// - `nextInitialized` to `quantity == 1`.
ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData(
to,
_nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
);
emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);
ERC721AStorage.layout()._currentIndex = startTokenId + quantity;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
/**
* @dev Safely mints `quantity` tokens and transfers them to `to`.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
* - `quantity` must be greater than 0.
*
* See {_mint}.
*
* Emits a {Transfer} event for each mint.
*/
function _safeMint(
address to,
uint256 quantity,
bytes memory _data
) internal virtual {
_mint(to, quantity);
unchecked {
if (to.code.length != 0) {
uint256 end = ERC721AStorage.layout()._currentIndex;
uint256 index = end - quantity;
do {
if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
revert TransferToNonERC721ReceiverImplementer();
}
} while (index < end);
// Reentrancy protection.
if (ERC721AStorage.layout()._currentIndex != end) revert();
}
}
}
/**
* @dev Equivalent to `_safeMint(to, quantity, '')`.
*/
function _safeMint(address to, uint256 quantity) internal virtual {
_safeMint(to, quantity, '');
}
// =============================================================
// BURN OPERATIONS
// =============================================================
/**
* @dev Equivalent to `_burn(tokenId, false)`.
*/
function _burn(uint256 tokenId) internal virtual {
_burn(tokenId, false);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
address from = address(uint160(prevOwnershipPacked));
(uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);
if (approvalCheck) {
// The nested ifs save around 20+ gas over a compound boolean condition.
if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();
}
_beforeTokenTransfers(from, address(0), tokenId, 1);
// Clear approvals from the previous owner.
assembly {
if approvedAddress {
// This is equivalent to `delete _tokenApprovals[tokenId]`.
sstore(approvedAddressSlot, 0)
}
}
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
// Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
unchecked {
// Updates:
// - `balance -= 1`.
// - `numberBurned += 1`.
//
// We can directly decrement the balance, and increment the number burned.
// This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
ERC721AStorage.layout()._packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;
// Updates:
// - `address` to the last owner.
// - `startTimestamp` to the timestamp of burning.
// - `burned` to `true`.
// - `nextInitialized` to `true`.
ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData(
from,
(_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
);
// If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
uint256 nextTokenId = tokenId + 1;
// If the next slot's address is zero and not burned (i.e. packed value is zero).
if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) {
// If the next slot is within bounds.
if (nextTokenId != ERC721AStorage.layout()._currentIndex) {
// Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
emit Transfer(from, address(0), tokenId);
_afterTokenTransfers(from, address(0), tokenId, 1);
// Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
unchecked {
ERC721AStorage.layout()._burnCounter++;
}
}
// =============================================================
// EXTRA DATA OPERATIONS
// =============================================================
/**
* @dev Directly sets the extra data for the ownership data `index`.
*/
function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
uint256 packed = ERC721AStorage.layout()._packedOwnerships[index];
if (packed == 0) revert OwnershipNotInitializedForExtraData();
uint256 extraDataCasted;
// Cast `extraData` with assembly to avoid redundant masking.
assembly {
extraDataCasted := extraData
}
packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
ERC721AStorage.layout()._packedOwnerships[index] = packed;
}
/**
* @dev Called during each token transfer to set the 24bit `extraData` field.
* Intended to be overridden by the cosumer contract.
*
* `previousExtraData` - the value of `extraData` before transfer.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, `tokenId` will be burned by `from`.
* - `from` and `to` are never both zero.
*/
function _extraData(
address from,
address to,
uint24 previousExtraData
) internal view virtual returns (uint24) {}
/**
* @dev Returns the next extra data for the packed ownership data.
* The returned result is shifted into position.
*/
function _nextExtraData(
address from,
address to,
uint256 prevOwnershipPacked
) private view returns (uint256) {
uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
}
// =============================================================
// OTHER OPERATIONS
// =============================================================
/**
* @dev Returns the message sender (defaults to `msg.sender`).
*
* If you are writing GSN compatible contracts, you need to override this function.
*/
function _msgSenderERC721A() internal view virtual returns (address) {
return msg.sender;
}
/**
* @dev Converts a uint256 to its ASCII string decimal representation.
*/
function _toString(uint256 value) internal pure virtual returns (string memory str) {
assembly {
// The maximum value of a uint256 contains 78 digits (1 byte per digit),
// but we allocate 0x80 bytes to keep the free memory pointer 32-byte word aligned.
// We will need 1 32-byte word to store the length,
// and 3 32-byte words to store a maximum of 78 digits. Total: 0x20 + 3 * 0x20 = 0x80.
str := add(mload(0x40), 0x80)
// Update the free memory pointer to allocate.
mstore(0x40, str)
// Cache the end of the memory to calculate the length later.
let end := str
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
// prettier-ignore
for { let temp := value } 1 {} {
str := sub(str, 1)
// Write the character to the pointer.
// The ASCII index of the '0' character is 48.
mstore8(str, add(48, mod(temp, 10)))
// Keep dividing `temp` until zero.
temp := div(temp, 10)
// prettier-ignore
if iszero(temp) { break }
}
let length := sub(end, str)
// Move the pointer 32 bytes leftwards to make room for the length.
str := sub(str, 0x20)
// Store the length.
mstore(str, length)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable diamond facet contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
import {ERC721A__InitializableStorage} from './ERC721A__InitializableStorage.sol';
abstract contract ERC721A__Initializable {
using ERC721A__InitializableStorage for ERC721A__InitializableStorage.Layout;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializerERC721A() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(
ERC721A__InitializableStorage.layout()._initializing
? _isConstructor()
: !ERC721A__InitializableStorage.layout()._initialized,
'ERC721A__Initializable: contract is already initialized'
);
bool isTopLevelCall = !ERC721A__InitializableStorage.layout()._initializing;
if (isTopLevelCall) {
ERC721A__InitializableStorage.layout()._initializing = true;
ERC721A__InitializableStorage.layout()._initialized = true;
}
_;
if (isTopLevelCall) {
ERC721A__InitializableStorage.layout()._initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializingERC721A() {
require(
ERC721A__InitializableStorage.layout()._initializing,
'ERC721A__Initializable: contract is not initializing'
);
_;
}
/// @dev Returns true if and only if the function is running in the constructor
function _isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly {
cs := extcodesize(self)
}
return cs == 0;
}
}// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.2
// Creator: Chiru Labs
pragma solidity ^0.8.4;
/**
* @dev Interface of ERC721A.
*/
interface IERC721AUpgradeable {
/**
* The caller must own the token or be an approved operator.
*/
error ApprovalCallerNotOwnerNorApproved();
/**
* The token does not exist.
*/
error ApprovalQueryForNonexistentToken();
/**
* The caller cannot approve to their own address.
*/
error ApproveToCaller();
/**
* Cannot query the balance for the zero address.
*/
error BalanceQueryForZeroAddress();
/**
* Cannot mint to the zero address.
*/
error MintToZeroAddress();
/**
* The quantity of tokens minted must be more than zero.
*/
error MintZeroQuantity();
/**
* The token does not exist.
*/
error OwnerQueryForNonexistentToken();
/**
* The caller must own the token or be an approved operator.
*/
error TransferCallerNotOwnerNorApproved();
/**
* The token must be owned by `from`.
*/
error TransferFromIncorrectOwner();
/**
* Cannot safely transfer to a contract that does not implement the
* ERC721Receiver interface.
*/
error TransferToNonERC721ReceiverImplementer();
/**
* Cannot transfer to the zero address.
*/
error TransferToZeroAddress();
/**
* The token does not exist.
*/
error URIQueryForNonexistentToken();
/**
* The `quantity` minted with ERC2309 exceeds the safety limit.
*/
error MintERC2309QuantityExceedsLimit();
/**
* The `extraData` cannot be set on an unintialized ownership slot.
*/
error OwnershipNotInitializedForExtraData();
// =============================================================
// STRUCTS
// =============================================================
struct TokenOwnership {
// The address of the owner.
address addr;
// Stores the start time of ownership with minimal overhead for tokenomics.
uint64 startTimestamp;
// Whether the token has been burned.
bool burned;
// Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
uint24 extraData;
}
// =============================================================
// TOKEN COUNTERS
// =============================================================
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() external view returns (uint256);
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
// =============================================================
// IERC721
// =============================================================
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables
* (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in `owner`'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`,
* checking first that contract recipients are aware of the ERC721 protocol
* to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move
* this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom}
* whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the
* zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom}
* for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
// =============================================================
// IERC2309
// =============================================================
/**
* @dev Emitted when tokens in `fromTokenId` to `toTokenId`
* (inclusive) is transferred from `from` to `to`, as defined in the
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
*
* See {_mintERC2309} for more details.
*/
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library ERC721AStorage {
// Reference type for token approval.
struct TokenApprovalRef {
address value;
}
struct Layout {
// =============================================================
// STORAGE
// =============================================================
// The next token ID to be minted.
uint256 _currentIndex;
// The number of tokens burned.
uint256 _burnCounter;
// Token name
string _name;
// Token symbol
string _symbol;
// Mapping from token ID to ownership details
// An empty struct value does not necessarily mean the token is unowned.
// See {_packedOwnershipOf} implementation for details.
//
// Bits Layout:
// - [0..159] `addr`
// - [160..223] `startTimestamp`
// - [224] `burned`
// - [225] `nextInitialized`
// - [232..255] `extraData`
mapping(uint256 => uint256) _packedOwnerships;
// Mapping owner address to address data.
//
// Bits Layout:
// - [0..63] `balance`
// - [64..127] `numberMinted`
// - [128..191] `numberBurned`
// - [192..255] `aux`
mapping(address => uint256) _packedAddressData;
// Mapping from token ID to approved address.
mapping(uint256 => ERC721AStorage.TokenApprovalRef) _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) _operatorApprovals;
}
bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.ERC721A');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This is a base storage for the initialization function for upgradeable diamond facet contracts
**/
library ERC721A__InitializableStorage {
struct Layout {
/*
* Indicates that the contract has been initialized.
*/
bool _initialized;
/*
* Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.initializable.facet');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @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 {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {IOperatorFilterRegistry} from "../IOperatorFilterRegistry.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
abstract contract OperatorFiltererUpgradeable is Initializable {
error OperatorNotAllowed(address operator);
IOperatorFilterRegistry constant operatorFilterRegistry =
IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);
function __OperatorFilterer_init(address subscriptionOrRegistrantToCopy, bool subscribe) public onlyInitializing {
// If an inheriting token contract is deployed to a network without the registry deployed, the modifier
// will not revert, but the contract will need to be registered with the registry once it is deployed in
// order for the modifier to filter addresses.
if (address(operatorFilterRegistry).code.length > 0) {
if (!operatorFilterRegistry.isRegistered(address(this))) {
if (subscribe) {
operatorFilterRegistry.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
} else {
if (subscriptionOrRegistrantToCopy != address(0)) {
operatorFilterRegistry.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
} else {
operatorFilterRegistry.register(address(this));
}
}
}
}
}
modifier onlyAllowedOperator(address from) virtual {
// Check registry code length to facilitate testing in environments without a deployed registry.
if (address(operatorFilterRegistry).code.length > 0) {
// Allow spending tokens from addresses with balance
// Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
// from an EOA.
if (from == msg.sender) {
_;
return;
}
if (
!(
operatorFilterRegistry.isOperatorAllowed(address(this), msg.sender)
&& operatorFilterRegistry.isOperatorAllowed(address(this), from)
)
) {
revert OperatorNotAllowed(msg.sender);
}
}
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IOperatorFilterRegistry {
function isOperatorAllowed(address registrant, address operator) external view returns (bool);
function register(address registrant) external;
function registerAndSubscribe(address registrant, address subscription) external;
function registerAndCopyEntries(address registrant, address registrantToCopy) external;
function updateOperator(address registrant, address operator, bool filtered) external;
function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
function subscribe(address registrant, address registrantToSubscribe) external;
function unsubscribe(address registrant, bool copyExistingEntries) external;
function subscriptionOf(address addr) external returns (address registrant);
function subscribers(address registrant) external returns (address[] memory);
function subscriberAt(address registrant, uint256 index) external returns (address);
function copyEntriesOf(address registrant, address registrantToCopy) external;
function isOperatorFiltered(address registrant, address operator) external returns (bool);
function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
function filteredOperators(address addr) external returns (address[] memory);
function filteredCodeHashes(address addr) external returns (bytes32[] memory);
function filteredOperatorAt(address registrant, uint256 index) external returns (address);
function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
function isRegistered(address addr) external returns (bool);
function codeHashOf(address addr) external returns (bytes32);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"bio","type":"string"}],"name":"BioChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"genesisTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"genesisTokenOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"babyCount","type":"uint256"}],"name":"Breed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"newName","type":"string"}],"name":"NameChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakedAt","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"approvedContract","type":"address"}],"name":"TokenLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"approvedContract","type":"address"}],"name":"TokenUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakedAt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakedAt","type":"uint256"}],"name":"Unstake","type":"event"},{"inputs":[],"name":"BREED_PER_SECONDS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"__DefaultOperatorFilterer_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"subscriptionOrRegistrantToCopy","type":"address"},{"internalType":"bool","name":"subscribe","type":"bool"}],"name":"__OperatorFilterer_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"receivers","type":"address[]"}],"name":"airdropList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"receivers","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"airdropListWithAmounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bio","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"genesisTokenId","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"breed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"breedMap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxSupplyNew","type":"uint256"}],"name":"burnSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"canBreed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canStake","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"string","name":"_bio","type":"string"}],"name":"changeBio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"newName","type":"string"}],"name":"changeName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"a","type":"string"},{"internalType":"string","name":"b","type":"string"}],"name":"compareStrings","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721AUpgradeable.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721AUpgradeable.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"address","name":"_contract","type":"address"}],"name":"freeId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisContract","outputs":[{"internalType":"contract IBreedingInfoV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"genesisTokenId","type":"uint256"}],"name":"getCanBreedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTokenOwnershipLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"getTokenOwnershipLengths","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"holdingSinceOverride","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"address","name":"genesisContractAddress","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"nameString","type":"string"}],"name":"isNameReserved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"isUnlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"keepTOLTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"lockId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockMap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"lockMapIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"name":"setBreedPerDays","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"b","type":"bool"}],"name":"setCanBreed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"b","type":"bool"}],"name":"setCanStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"setTOLStart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURIOverride","type":"string"}],"name":"setTokenURIOverride","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURISuffix","type":"string"}],"name":"setTokenURISuffix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bool","name":"setStake","type":"bool"}],"name":"setTokensStakeStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stake","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":"string","name":"str","type":"string"}],"name":"toLower","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenNameByIndex","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenURIOverride","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenURISuffix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokensLastStakedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tolStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"unlockId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_contracts","type":"address[]"},{"internalType":"bool[]","name":"_values","type":"bool[]"}],"name":"updateApprovedContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"validateName","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50615263806100206000396000f3fe608060405234801561001057600080fd5b50600436106104335760003560e01c80637ed5067c11610236578063c39cbef11161013b578063e512bee9116100c3578063f2fde38b11610087578063f2fde38b146109a4578063f6344969146109b7578063f90a82c8146109ca578063fc0f1eeb146109dd578063ff633d5514610a0857600080fd5b8063e512bee91461094f578063e886718014610962578063e985e9c514610975578063eaf16e1314610988578063ecbb3a741461099157600080fd5b8063d595c3311161010a578063d595c33114610906578063d76b47cb14610919578063d8e99f9214610921578063d9ecad7b14610934578063dbbc853b1461094757600080fd5b8063c39cbef1146108c5578063c87b56dd146108d8578063ca0ed7d5146108eb578063d547cfb7146108fe57600080fd5b80639ffdb65a116101be578063ac52e6441161018d578063ac52e64414610849578063b1a6505f1461085c578063b88d4fde1461087f578063bed34bba14610892578063c23dc68f146108a557600080fd5b80639ffdb65a146107fd578063a22cb46514610810578063a694fc3a14610823578063a9852bfb1461083657600080fd5b80639416b423116102055780639416b423146107af57806394d216d6146107c257806395d89b41146107d557806399a2557a146107dd5780639ed27809146107f057600080fd5b80637ed5067c1461076f5780638462151c146107785780638ba4cc3c1461078b5780638da5cb5b1461079e57600080fd5b8063352dd1bd1161033c5780635cd8a76b116102c45780636d522418116102935780636d5224181461070d57806370a0823114610720578063715018a61461073357806372abc8b71461073b5780637ab4339d1461075c57600080fd5b80635cd8a76b146106bf5780636343e0a2146106c75780636352211e146106da578063650b00f6146106ed57600080fd5b806342842e0e1161030b57806342842e0e146106535780634d426528146106665780634faf88471461067957806355f804b31461068c5780635bbb21771461069f57600080fd5b8063352dd1bd146105ed57806335b504c51461060d57806336033deb1461062d57806340a9c8df1461064057600080fd5b806315b56d10116103bf57806327938bb41161038e57806327938bb4146105775780632799cde01461058a5780632cba81231461059d5780632e17de78146105d157806332cb6b0c146105e457600080fd5b806315b56d101461052957806318160ddd1461053c57806323b872dd14610544578063264cd3391461055757600080fd5b8063081812fc11610406578063081812fc1461049257806309308e5d146104bd578063095ea7b3146104f65780630c886c10146105095780630d9341f21461051c57600080fd5b806301ffc9a71461043857806303eaebec1461046057806306e707f31461046a57806306fdde031461047d575b600080fd5b61044b610446366004614416565b610a1b565b60405190151581526020015b60405180910390f35b610468610a46565b005b610468610478366004614433565b610a97565b610485610aa4565b604051610457919061449c565b6104a56104a0366004614433565b610b3f565b6040516001600160a01b039091168152602001610457565b6104e86104cb3660046144c4565b606b60209081526000928352604080842090915290825290205481565b604051908152602001610457565b6104686105043660046144f4565b610b8c565b61046861051736600461456b565b610c3a565b60a65461044b9060ff1681565b61044b610537366004614693565b610cf5565b6104e8610d28565b6104686105523660046146c7565b610d47565b6104e8610565366004614433565b60aa6020526000908152604090205481565b610468610585366004614708565b610f19565b610468610598366004614433565b610fbb565b6104a56105ab366004614749565b606a6020908152600092835260408084209091529082529020546001600160a01b031681565b6104686105df366004614433565b610fec565b6104e8609f5481565b6106006105fb366004614708565b611103565b604051610457919061476b565b6104e861061b366004614433565b60a56020526000908152604090205481565b61048561063b366004614433565b6111b4565b61046861064e366004614433565b61124e565b6104686106613660046146c7565b61127c565b6104686106743660046147a3565b611297565b6104686106873660046146c7565b611352565b61046861069a3660046147e9565b6114d5565b6106b26106ad366004614708565b6114ea565b6040516104579190614896565b6104686115b5565b6104686106d53660046147e9565b61165b565b6104a56106e8366004614433565b6116f3565b6104e86106fb366004614433565b60696020526000908152604090205481565b61048561071b366004614433565b6116fe565b6104e861072e3660046148d8565b6117a0565b610468611808565b61044b610749366004614433565b6000908152606960205260409020541590565b61046861076a3660046148f5565b61181a565b6104e860a85481565b6106006107863660046148d8565b61195c565b6104686107993660046144f4565b611a64565b6036546001600160a01b03166104a5565b6104856107bd366004614693565b611a76565b6104686107d03660046144c4565b611bd0565b610485611bff565b6106006107eb36600461493b565b611c17565b60a45461044b9060ff1681565b61044b61080b366004614693565b611d8f565b61046861081e36600461498e565b611f9a565b610468610831366004614433565b612040565b6104686108443660046147e9565b61219b565b61046861085736600461456b565b61222f565b61044b61086a3660046148d8565b60686020526000908152604090205460ff1681565b61046861088d3660046149bc565b612307565b61044b6108a0366004614a3b565b6124d5565b6108b86108b3366004614433565b61252e565b6040516104579190614a94565b6104686108d33660046147a3565b6125aa565b6104856108e6366004614433565b6128cd565b6104e86108f9366004614433565b612925565b610485612a90565b610468610914366004614433565b612a9d565b610485612bae565b609e546104a5906001600160a01b031681565b610468610942366004614749565b612bbb565b610485612f25565b61046861095d366004614aa2565b612f32565b610468610970366004614aa2565b612f4d565b61044b610983366004614abf565b612f68565b6104e860a05481565b6104e861099f366004614433565b612fa5565b6104686109b23660046148d8565b612fbe565b6104686109c5366004614433565b613034565b6104686109d8366004614aed565b61305d565b6104e86109eb366004614749565b60a760209081526000928352604080842090915290825290205481565b610468610a1636600461498e565b6130e8565b60006001600160e01b0319821663706e848960e01b1480610a405750610a408261328f565b92915050565b600354610100900460ff16610a765760405162461bcd60e51b8152600401610a6d90614ba4565b60405180910390fd5b610a95733cc6cdda760b79bafa08df41ecfa224f810dceb660016130e8565b565b610a9f6132dd565b60a855565b6060610aae613337565b6002018054610abc90614bef565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae890614bef565b8015610b355780601f10610b0a57610100808354040283529160200191610b35565b820191906000526020600020905b815481529060010190602001808311610b1857829003601f168201915b5050505050905090565b6000610b4a8261335b565b610b67576040516333d1c03960e21b815260040160405180910390fd5b610b6f613337565b60009283526006016020525060409020546001600160a01b031690565b6000610b97826116f3565b9050336001600160a01b03821614610bd057610bb38133612f68565b610bd0576040516367d9dca160e11b815260040160405180910390fd5b82610bd9613337565b6000848152600691909101602052604080822080546001600160a01b0319166001600160a01b0394851617905551849286811692908516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a4505050565b610c426132dd565b6001831015610c895760405162461bcd60e51b815260206004820152601360248201527230ba103632b0b9ba1018903932b1b2b4bb32b960691b6044820152606401610a6d565b60005b83811015610cee57610cdc858583818110610ca957610ca9614c29565b9050602002016020810190610cbe91906148d8565b848484818110610cd057610cd0614c29565b90506020020135613397565b80610ce681614c55565b915050610c8c565b5050505050565b60006002610d0283611a76565b604051610d0f9190614c6e565b9081526040519081900360200190205460ff1692915050565b600080610d33613337565b60010154610d3f613337565b540303919050565b826daaeb6d7670e522a718067333cd4e3b15610ecd57336001600160a01b03821603610db857600082815260a5602052604090205415610d995760405162461bcd60e51b8152600401610a6d90614c8a565b600082815260aa6020526040812055610db38484846133f9565b610f13565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610e07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2b9190614cc1565b8015610eae5750604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610e8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eae9190614cc1565b610ecd57604051633b79c77360e21b8152336004820152602401610a6d565b600082815260a5602052604090205415610ef95760405162461bcd60e51b8152600401610a6d90614c8a565b600082815260aa6020526040812055610f138484846133f9565b50505050565b610f216132dd565b6001811015610f685760405162461bcd60e51b815260206004820152601360248201527230ba103632b0b9ba1018903932b1b2b4bb32b960691b6044820152606401610a6d565b60005b81811015610fb657610fa4838383818110610f8857610f88614c29565b9050602002016020810190610f9d91906148d8565b6001613397565b80610fae81614c55565b915050610f6b565b505050565b610fc48161335b565b610fe05760405162461bcd60e51b8152600401610a6d90614cde565b610fe981613452565b50565b6002606c540361100e5760405162461bcd60e51b8152600401610a6d90614d04565b6002606c5561101c816116f3565b6001600160a01b0316336001600160a01b0316148061104557506036546001600160a01b031633145b6110615760405162461bcd60e51b8152600401610a6d90614d3b565b600081815260a560205260409020546110aa5760405162461bcd60e51b815260206004820152600b60248201526a6e6f74207374616b696e6760a81b6044820152606401610a6d565b600081815260a56020908152604080832080549390558051428152918201839052339184917fc1e00202ee2c06861d326fc6374026b751863ff64218ccbaa38c3e603a8e72c2910160405180910390a350506001606c55565b60606000826001600160401b0381111561111f5761111f6145d6565b604051908082528060200260200182016040528015611148578160200160208202803683370190505b50905060005b838110156111ac57600085858381811061116a5761116a614c29565b90506020020135905061117c81612fa5565b83838151811061118e5761118e614c29565b602090810291909101015250806111a481614c55565b91505061114e565b509392505050565b600060208190529081526040902080546111cd90614bef565b80601f01602080910402602001604051908101604052809291908181526020018280546111f990614bef565b80156112465780601f1061121b57610100808354040283529160200191611246565b820191906000526020600020905b81548152906001019060200180831161122957829003601f168201915b505050505081565b6112578161335b565b6112735760405162461bcd60e51b8152600401610a6d90614cde565b610fe981613592565b610fb683838360405180602001604052806000815250612307565b60006112a2836116f3565b9050336001600160a01b038216146112fc5760405162461bcd60e51b815260206004820152601f60248201527f4552433732313a2063616c6c6572206973206e6f7420746865206f776e6572006044820152606401610a6d565b60008381526020819052604090206113148382614dd0565b50827fbe3e2fc72ea4bd0d860e908b1ee27aa9856809e62a75bfc0cb7f04b5d791873d83604051611345919061449c565b60405180910390a2505050565b826001600160a01b0316611365826116f3565b6001600160a01b0316146113cd5760405162461bcd60e51b815260206004820152602960248201527f4f6e6c7920746f6b656e206f776e65722063616e20646f206b65657020544f4c604482015268103a3930b739b332b960b91b6064820152608401610a6d565b336001600160a01b038416146114255760405162461bcd60e51b815260206004820152601f60248201527f53656e646572206d7573742062652066726f6d20746f6b656e206f776e6572006044820152606401610a6d565b816001600160a01b0316836001600160a01b0316036114865760405162461bcd60e51b815260206004820152601d60248201527f46726f6d20616e6420546f206d75737420626520646966666572656e740000006044820152606401610a6d565b600081815260aa602052604081205490036114ca5760006114a68261252e565b602090810151600084815260aa90925260409091206001600160401b039091169055505b610fb68383836133f9565b6114dd6132dd565b60a1610fb6828483614e8f565b6060816000816001600160401b03811115611507576115076145d6565b60405190808252806020026020018201604052801561155957816020015b6040805160808101825260008082526020808301829052928201819052606082015282526000199092019101816115255790505b50905060005b8281146115ac5761158786868381811061157b5761157b614c29565b9050602002013561252e565b82828151811061159957611599614c29565b602090810291909101015260010161155f565b50949350505050565b6115bd6132dd565b600354600290610100900460ff161580156115df575060035460ff8083169116105b6115fb5760405162461bcd60e51b8152600401610a6d90614f4e565b6003805461ffff191660ff831617610100179055611617610a46565b6003805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b6116636132dd565b6116c182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600781526621656d7074792160c81b602082015291506124d59050565b156116e25760408051602081019091526000815260a390610fb69082614dd0565b60a3610fb6828483614e8f565b5050565b6000610a4082613732565b600081815260016020526040902080546060919061171b90614bef565b80601f016020809104026020016040519081016040528092919081815260200182805461174790614bef565b80156117945780601f1061176957610100808354040283529160200191611794565b820191906000526020600020905b81548152906001019060200180831161177757829003601f168201915b50505050509050919050565b60006001600160a01b0382166117c9576040516323d3ad8160e21b815260040160405180910390fd5b6001600160401b036117d9613337565b6005016000846001600160a01b03166001600160a01b0316815260200190815260200160002054169050919050565b6118106132dd565b610a9560006137be565b600354610100900460ff161580801561183a5750600354600160ff909116105b806118545750303b158015611854575060035460ff166001145b6118705760405162461bcd60e51b8152600401610a6d90614f4e565b6003805460ff191660011790558015611893576003805461ff0019166101001790555b6118d56040518060400160405280600481526020016325bab13d60e11b8152506040518060400160405280600481526020016325bab13d60e11b815250613810565b6118dd613849565b60a16118e98482614dd0565b50609e80546001600160a01b0319166001600160a01b038416179055612710609f5562278d0060a0558015610fb6576003805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b6060600080600061196c856117a0565b90506000816001600160401b03811115611988576119886145d6565b6040519080825280602002602001820160405280156119b1578160200160208202803683370190505b5090506119de60408051608081018252600080825260208201819052918101829052606081019190915290565b60005b838614611a58576119f181613878565b91508160400151611a505781516001600160a01b031615611a1157815194505b876001600160a01b0316856001600160a01b031603611a505780838780600101985081518110611a4357611a43614c29565b6020026020010181815250505b6001016119e1565b50909695505050505050565b611a6c6132dd565b6116ef8282613397565b60606000829050600081516001600160401b03811115611a9857611a986145d6565b6040519080825280601f01601f191660200182016040528015611ac2576020820181803683370190505b50905060005b82518110156111ac576041838281518110611ae557611ae5614c29565b016020015160f81c10801590611b155750605a838281518110611b0a57611b0a614c29565b016020015160f81c11155b15611b7757828181518110611b2c57611b2c614c29565b602001015160f81c60f81b60f81c6020611b469190614f9c565b60f81b828281518110611b5b57611b5b614c29565b60200101906001600160f81b031916908160001a905350611bbe565b828181518110611b8957611b89614c29565b602001015160f81c60f81b828281518110611ba657611ba6614c29565b60200101906001600160f81b031916908160001a9053505b80611bc881614c55565b915050611ac8565b611bd98261335b565b611bf55760405162461bcd60e51b8152600401610a6d90614cde565b6116ef82826138bf565b6060611c09613337565b6003018054610abc90614bef565b6060818310611c3957604051631960ccad60e11b815260040160405180910390fd5b600080611c44613a75565b905080841115611c52578093505b6000611c5d876117a0565b905084861015611c7c5785850381811015611c76578091505b50611c80565b5060005b6000816001600160401b03811115611c9a57611c9a6145d6565b604051908082528060200260200182016040528015611cc3578160200160208202803683370190505b50905081600003611cd9579350611d8892505050565b6000611ce48861252e565b905060008160400151611cf5575080515b885b888114158015611d075750848714155b15611d7c57611d1581613878565b92508260400151611d745782516001600160a01b031615611d3557825191505b8a6001600160a01b0316826001600160a01b031603611d745780848880600101995081518110611d6757611d67614c29565b6020026020010181815250505b600101611cf7565b50505092835250909150505b9392505050565b600080829050600181511015611da85750600092915050565b601981511115611dbb5750600092915050565b80600081518110611dce57611dce614c29565b01602001516001600160f81b031916600160fd1b03611df05750600092915050565b8060018251611dff9190614fb5565b81518110611e0f57611e0f614c29565b01602001516001600160f81b031916600160fd1b03611e315750600092915050565b600081600081518110611e4657611e46614c29565b01602001516001600160f81b031916905060005b8251811015611f8f576000838281518110611e7757611e77614c29565b01602001516001600160f81b0319169050600160fd1b81148015611ea85750600160fd1b6001600160f81b03198416145b15611eb95750600095945050505050565b600360fc1b6001600160f81b0319821610801590611ee55750603960f81b6001600160f81b0319821611155b158015611f1b5750604160f81b6001600160f81b0319821610801590611f195750602d60f91b6001600160f81b0319821611155b155b8015611f505750606160f81b6001600160f81b0319821610801590611f4e5750603d60f91b6001600160f81b0319821611155b155b8015611f6a5750600160fd1b6001600160f81b0319821614155b15611f7b5750600095945050505050565b915080611f8781614c55565b915050611e5a565b506001949350505050565b336001600160a01b03831603611fc35760405163b06307db60e01b815260040160405180910390fd5b80611fcc613337565b336000818152600792909201602090815260408084206001600160a01b03881680865290835293819020805460ff19169515159590951790945592518415158152919290917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6002606c54036120625760405162461bcd60e51b8152600401610a6d90614d04565b6002606c5560a45460ff166120ac5760405162461bcd60e51b815260206004820152601060248201526f39ba30b5b4b733903737ba1037b832b760811b6044820152606401610a6d565b6120b5816116f3565b6001600160a01b0316336001600160a01b031614806120de57506036546001600160a01b031633145b6120fa5760405162461bcd60e51b8152600401610a6d90614d3b565b600081815260a56020526040902054156121485760405162461bcd60e51b815260206004820152600f60248201526e616c7265616479207374616b696e6760881b6044820152606401610a6d565b600081815260a5602090815260409182902042908190559151918252339183917f02567b2553aeb44e4ddd5d68462774dc3de158cb0f2c2da1740e729b22086aff910160405180910390a3506001606c55565b6121a36132dd565b61220182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600781526621656d7074792160c81b602082015291506124d59050565b156122225760408051602081019091526000815260a290610fb69082614dd0565b60a2610fb6828483614e8f565b6122376132dd565b8281146122705760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610a6d565b60005b83811015610cee5782828281811061228d5761228d614c29565b90506020020160208101906122a29190614aa2565b606860008787858181106122b8576122b8614c29565b90506020020160208101906122cd91906148d8565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055806122ff81614c55565b915050612273565b836daaeb6d7670e522a718067333cd4e3b1561248e57336001600160a01b0382160361237957600083815260a56020526040902054156123595760405162461bcd60e51b8152600401610a6d90614c8a565b600083815260aa602052604081205561237485858585613a85565b610cee565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa1580156123c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ec9190614cc1565b801561246f5750604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa15801561244b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246f9190614cc1565b61248e57604051633b79c77360e21b8152336004820152602401610a6d565b600083815260a56020526040902054156124ba5760405162461bcd60e51b8152600401610a6d90614c8a565b600083815260aa6020526040812055610cee85858585613a85565b6000816040516020016124e89190614c6e565b604051602081830303815290604052805190602001208360405160200161250f9190614c6e565b6040516020818303038152906040528051906020012014905092915050565b604080516080808201835260008083526020808401829052838501829052606080850183905285519384018652828452908301829052938201819052928101929092529061257a613a75565b83106125865792915050565b61258f83613878565b90508060400151156125a15792915050565b611d8883613adf565b60006125b5836116f3565b9050336001600160a01b0382161461260f5760405162461bcd60e51b815260206004820152601f60248201527f4552433732313a2063616c6c6572206973206e6f7420746865206f776e6572006044820152606401610a6d565b61261882611d8f565b15156001146126605760405162461bcd60e51b81526020600482015260146024820152734e6f7420612076616c6964206e6577206e616d6560601b6044820152606401610a6d565b60008381526001602052604090819020905160029161267e9161503b565b602060405180830381855afa15801561269b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906126be9190615047565b6002836040516126ce9190614c6e565b602060405180830381855afa1580156126eb573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061270e9190615047565b036127675760405162461bcd60e51b815260206004820152602360248201527f4e6577206e616d652069732073616d65206173207468652063757272656e74206044820152626f6e6560e81b6064820152608401610a6d565b61277082610cf5565b156127b55760405162461bcd60e51b815260206004820152601560248201527413985b5948185b1c9958591e481c995cd95c9d9959605a1b6044820152606401610a6d565b600083815260016020526040812080546127ce90614bef565b90501115612879576000838152600160205260409020805461287991906127f490614bef565b80601f016020809104026020016040519081016040528092919081815260200182805461282090614bef565b801561286d5780601f106128425761010080835404028352916020019161286d565b820191906000526020600020905b81548152906001019060200180831161285057829003601f168201915b50505050506000613b14565b612884826001613b14565b600083815260016020526040902061289c8382614dd0565b50827f7e632a301794d8d4a81ea7e20f37d1947158d36e66403af04ba85dd194b66f1b83604051611345919061449c565b6060600060a380546128de90614bef565b905011156128f35760a3805461171b90614bef565b6128fc82613b51565b60a260405160200161290f929190615060565b6040516020818303038152906040529050919050565b60a65460009060ff1661296e5760405162461bcd60e51b8152602060048201526011602482015270313932b2b234b733903737ba1037b832b760791b6044820152606401610a6d565b609e546001600160a01b03166129c05760405162461bcd60e51b815260206004820152601760248201527619d95b995cda5cd0dbdb9d1c9858dd081b9bdd081cd95d604a1b6044820152606401610a6d565b609e5460405163e76abcc760e01b8152600481018490526000916001600160a01b03169063e76abcc790602401602060405180830381865afa158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190615047565b905080600003612a415750600092915050565b6000612a4d8242614fb5565b9050600060a05482612a5f9190615087565b600086815260a760209081526040808320878452909152902054909150612a868183614fb5565b9695505050505050565b60a180546111cd90614bef565b612aa56132dd565b60008111612af55760405162461bcd60e51b815260206004820152601960248201527f6e6577206d617820737570706c792073686f756c64203e2030000000000000006044820152606401610a6d565b609f548110612b465760405162461bcd60e51b815260206004820152601a60248201527f63616e206f6e6c7920726564756365206d617820737570706c790000000000006044820152606401610a6d565b612b4e613bd4565b811015612ba95760405162461bcd60e51b8152602060048201526024808201527f63616e6e6f74206275726e206d6f7265207468616e2063757272656e7420737560448201526370706c7960e01b6064820152608401610a6d565b609f55565b60a380546111cd90614bef565b6002606c5403612bdd5760405162461bcd60e51b8152600401610a6d90614d04565b6002606c5560a65460ff16612c285760405162461bcd60e51b8152602060048201526011602482015270313932b2b234b733903737ba1037b832b760791b6044820152606401610a6d565b609e546001600160a01b0316612c7a5760405162461bcd60e51b815260206004820152601760248201527619d95b995cda5cd0dbdb9d1c9858dd081b9bdd081cd95d604a1b6044820152606401610a6d565b609e5460405163dd7eb9a960e01b8152600481018490526001600160a01b039091169063dd7eb9a990602401602060405180830381865afa158015612cc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce791906150a9565b6001600160a01b0316336001600160a01b031614612d475760405162461bcd60e51b815260206004820152601c60248201527f4e6f74206f776e6572206f662067656e6573697320746f6b656e4964000000006044820152606401610a6d565b6001811015612d985760405162461bcd60e51b815260206004820152601760248201527f73686f756c64206272656564206174206c6561737420310000000000000000006044820152606401610a6d565b609e5460405163e76abcc760e01b8152600481018490526000916001600160a01b03169063e76abcc790602401602060405180830381865afa158015612de2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e069190615047565b90506000612e148242614fb5565b9050600060a05482612e269190615087565b600086815260a76020908152604080832087845290915290205490915081612e4e86836150c6565b1115612ea85760405162461bcd60e51b815260206004820152602360248201527f4e6f7420726561647920746f2062726565642074686174206d616e792062616260448201526269657360e81b6064820152608401610a6d565b600086815260a76020908152604080832087845290915281208054879290612ed19084906150c6565b90915550612ee190503386613397565b604051858152339087907fbf76824ab67eb782060757df49f901075d21a0d5068827dffbb31f8095d783869060200160405180910390a350506001606c5550505050565b60a280546111cd90614bef565b612f3a6132dd565b60a6805460ff1916911515919091179055565b612f556132dd565b60a4805460ff1916911515919091179055565b6000612f72613337565b6001600160a01b039384166000908152600791909101602090815260408083209490951682529290925250205460ff1690565b600080612fb183613be6565b9050611d88600582615087565b612fc66132dd565b6001600160a01b03811661302b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a6d565b610fe9816137be565b61303c6132dd565b600181101561304a57600080fd5b61305781620151806150d9565b60a05550565b6002606c540361307f5760405162461bcd60e51b8152600401610a6d90614d04565b6002606c5560005b82518110156130de5760008382815181106130a4576130a4614c29565b6020026020010151905082156130c2576130bd81612040565b6130cb565b6130cb81610fec565b50806130d681614c55565b915050613087565b50506001606c5550565b600354610100900460ff1661310f5760405162461bcd60e51b8152600401610a6d90614ba4565b6daaeb6d7670e522a718067333cd4e3b156116ef5760405163c3c5a54760e01b81523060048201526daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af115801561316f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131939190614cc1565b6116ef57801561320f57604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b1580156131f357600080fd5b505af1158015613207573d6000803e3d6000fd5b505050505050565b6001600160a01b0382161561325e5760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af2903906044016131d9565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e486906024016131d9565b60006301ffc9a760e01b6001600160e01b0319831614806132c057506380ac58cd60e01b6001600160e01b03198316145b80610a405750506001600160e01b031916635b5e139f60e01b1490565b6036546001600160a01b03163314610a955760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a6d565b7f2569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c4090565b6000613365613337565b5482108015610a405750600160e01b61337c613337565b60008481526004919091016020526040902054161592915050565b609f54816133a3613bd4565b6133ad91906150c6565b11156133ef5760405162461bcd60e51b8152602060048201526011602482015270657863656564204d41585f535550504c5960781b6044820152606401610a6d565b6116ef8282613c54565b600081815260696020526040902054156134475760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881a5cc81b1bd8dad959608a1b6044820152606401610a6d565b610fb6838383613d8f565b3360009081526068602052604090205460ff166134815760405162461bcd60e51b8152600401610a6d906150f8565b6000818152606b60209081526040808320338452909152902054156134e85760405162461bcd60e51b815260206004820152601b60248201527f494420616c7265616479206c6f636b65642062792063616c6c657200000000006044820152606401610a6d565b6000818152606960205260408120546135029060016150c6565b6000838152606a60209081526040808320848452825280832080546001600160a01b03191633908117909155868452606b835281842090845282528083208490558583526069909152812080549293509061355c83614c55565b9091555050604051339083907f9ecfd70e9ff36df72989324a49559383d39f9290d700b10cf5ac10dcb68d264390600090a35050565b3360009081526068602052604090205460ff166135c15760405162461bcd60e51b8152600401610a6d906150f8565b6000818152606b602090815260408083203384529091528120549081900361362b5760405162461bcd60e51b815260206004820152601760248201527f4944206e6f74206c6f636b65642062792063616c6c65720000000000000000006044820152606401610a6d565b6000828152606960205260409020548181146136a1576000838152606a602090815260408083208484528252808320805486855282852080546001600160a01b03199081166001600160a01b03909316928317909155825416909155868452606b835281842090845290915290208290556136c9565b6000838152606a60209081526040808320858452909152902080546001600160a01b03191690555b6000838152606b602090815260408083203384528252808320839055858352606990915281208054916136fb83615123565b9091555050604051339084907f0fe7d9801197f79ef3b1595d19379eb58f0fff5f98b0f6d6f34c03cae5306c3790600090a3505050565b60008161373d613337565b548110156137a557600061374f613337565b600083815260049190910160205260408120549150600160e01b821690036137a3575b80600003611d8857613782613337565b60001990920160008181526004939093016020526040909220549050613772565b505b604051636f96cda160e11b815260040160405180910390fd5b603680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600354610100900460ff166138375760405162461bcd60e51b8152600401610a6d90614ba4565b6138418282613f82565b6116ef614096565b600354610100900460ff166138705760405162461bcd60e51b8152600401610a6d90614ba4565b610a956140c5565b604080516080810182526000808252602082018190529181018290526060810191909152610a406138a7613337565b600084815260049190910160205260409020546140f3565b6001600160a01b03811660009081526068602052604090205460ff16156138f85760405162461bcd60e51b8152600401610a6d906150f8565b6000828152606b602090815260408083206001600160a01b03851684529091528120549081900361395b5760405162461bcd60e51b815260206004820152600d60248201526c1251081b9bdd081b1bd8dad959609a1b6044820152606401610a6d565b6000838152606960205260409020548181146139d1576000848152606a602090815260408083208484528252808320805486855282852080546001600160a01b03199081166001600160a01b03909316928317909155825416909155878452606b835281842090845290915290208290556139f9565b6000848152606a60209081526040808320858452909152902080546001600160a01b03191690555b6000848152606b602090815260408083206001600160a01b0387168452825280832083905586835260699091528120805491613a3483615123565b90915550506040516001600160a01b0384169085907f0fe7d9801197f79ef3b1595d19379eb58f0fff5f98b0f6d6f34c03cae5306c3790600090a350505050565b6000613a7f613337565b54919050565b60008281526069602052604090205415613ad35760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881a5cc81b1bd8dad959608a1b6044820152606401610a6d565b610f138484848461413a565b604080516080810182526000808252602082018190529181018290526060810191909152610a40613b0f83613732565b6140f3565b806002613b2084611a76565b604051613b2d9190614c6e565b908152604051908190036020019020805491151560ff199092169190911790555050565b6060613b5c8261335b565b613b7957604051630a14c4b560e41b815260040160405180910390fd5b6000613b8361417e565b90508051600003613ba35760405180602001604052806000815250611d88565b80613bad8461418d565b604051602001613bbe92919061513a565b6040516020818303038152906040529392505050565b600080613bdf613337565b5403919050565b600081815260aa6020526040812054819015613c2957600083815260aa602052604090205460a854613c1891906141c5565b613c229042614fb5565b9050610a40565b613c4a613c358461252e565b602001516001600160401b031660a8546141c5565b611d889042614fb5565b6000613c5e613337565b5490506000829003613c835760405163b562e8dd60e01b815260040160405180910390fd5b680100000000000000018202613c97613337565b6001600160a01b038516600081815260059290920160205260409091208054929092019091554260a01b6001841460e11b1717613cd2613337565b600083815260049190910160205260408120919091556001600160a01b0384169083830190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b818114613d5c57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600101613d24565b5081600003613d7d57604051622e076360e81b815260040160405180910390fd5b80613d86613337565b5550610fb69050565b6000613d9a82613732565b9050836001600160a01b0316816001600160a01b031614613dcd5760405162a1148160e81b815260040160405180910390fd5b600080613dd9846141dc565b91509150613dfe8187613de93390565b6001600160a01b039081169116811491141790565b613e2957613e0c8633612f68565b613e2957604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b038516613e5057604051633a954ecd60e21b815260040160405180910390fd5b8015613e5b57600082555b613e63613337565b6001600160a01b0387166000908152600591909101602052604090208054600019019055613e8f613337565b6001600160a01b03861660008181526005929092016020526040909120805460010190554260a01b17600160e11b17613ec6613337565b60008681526004919091016020526040812091909155600160e11b84169003613f3c5760018401613ef5613337565b600082815260049190910160205260408120549003613f3a57613f16613337565b548114613f3a5783613f26613337565b600083815260049190910160205260409020555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613207565b60008051602061520e83398151915254610100900460ff16613fb75760008051602061520e8339815191525460ff1615613fbb565b303b155b61402d5760405162461bcd60e51b815260206004820152603760248201527f455243373231415f5f496e697469616c697a61626c653a20636f6e747261637460448201527f20697320616c726561647920696e697469616c697a65640000000000000000006064820152608401610a6d565b60008051602061520e83398151915254610100900460ff161580156140695760008051602061520e833981519152805461ffff19166101011790555b6140738383614204565b8015610fb657505060008051602061520e833981519152805461ff001916905550565b600354610100900460ff166140bd5760405162461bcd60e51b8152600401610a6d90614ba4565b610a95614242565b600354610100900460ff166140ec5760405162461bcd60e51b8152600401610a6d90614ba4565b6001606c55565b604080516080810182526001600160a01b038316815260a083901c6001600160401b03166020820152600160e01b831615159181019190915260e89190911c606082015290565b614145848484610d47565b6001600160a01b0383163b15610f135761416184848484614271565b610f13576040516368d2bf6b60e11b815260040160405180910390fd5b606060a18054610abc90614bef565b604080516080019081905280825b600183039250600a81066030018353600a90048061419b5750819003601f19909101908152919050565b6000818310156141d55781611d88565b5090919050565b60008060006141e9613337565b60009485526006016020525050604090912080549092909150565b60008051602061520e83398151915254610100900460ff166142385760405162461bcd60e51b8152600401610a6d90615169565b6116ef828261435d565b600354610100900460ff166142695760405162461bcd60e51b8152600401610a6d90614ba4565b610a956143d0565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906142a69033908990889088906004016151bd565b6020604051808303816000875af19250505080156142e1575060408051601f3d908101601f191682019092526142de918101906151f0565b60015b61433f573d80801561430f576040519150601f19603f3d011682016040523d82523d6000602084013e614314565b606091505b508051600003614337576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b60008051602061520e83398151915254610100900460ff166143915760405162461bcd60e51b8152600401610a6d90615169565b8161439a613337565b600201906143a89082614dd0565b50806143b2613337565b600301906143c09082614dd0565b5060006143cb613337565b555050565b600354610100900460ff166143f75760405162461bcd60e51b8152600401610a6d90614ba4565b610a95336137be565b6001600160e01b031981168114610fe957600080fd5b60006020828403121561442857600080fd5b8135611d8881614400565b60006020828403121561444557600080fd5b5035919050565b60005b8381101561446757818101518382015260200161444f565b50506000910152565b6000815180845261448881602086016020860161444c565b601f01601f19169290920160200192915050565b602081526000611d886020830184614470565b6001600160a01b0381168114610fe957600080fd5b600080604083850312156144d757600080fd5b8235915060208301356144e9816144af565b809150509250929050565b6000806040838503121561450757600080fd5b8235614512816144af565b946020939093013593505050565b60008083601f84011261453257600080fd5b5081356001600160401b0381111561454957600080fd5b6020830191508360208260051b850101111561456457600080fd5b9250929050565b6000806000806040858703121561458157600080fd5b84356001600160401b038082111561459857600080fd5b6145a488838901614520565b909650945060208701359150808211156145bd57600080fd5b506145ca87828801614520565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614614576146146145d6565b604052919050565b60006001600160401b03831115614635576146356145d6565b614648601f8401601f19166020016145ec565b905082815283838301111561465c57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261468457600080fd5b611d888383356020850161461c565b6000602082840312156146a557600080fd5b81356001600160401b038111156146bb57600080fd5b61435584828501614673565b6000806000606084860312156146dc57600080fd5b83356146e7816144af565b925060208401356146f7816144af565b929592945050506040919091013590565b6000806020838503121561471b57600080fd5b82356001600160401b0381111561473157600080fd5b61473d85828601614520565b90969095509350505050565b6000806040838503121561475c57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015611a5857835183529284019291840191600101614787565b600080604083850312156147b657600080fd5b8235915060208301356001600160401b038111156147d357600080fd5b6147df85828601614673565b9150509250929050565b600080602083850312156147fc57600080fd5b82356001600160401b038082111561481357600080fd5b818501915085601f83011261482757600080fd5b81358181111561483657600080fd5b86602082850101111561484857600080fd5b60209290920196919550909350505050565b80516001600160a01b031682526020808201516001600160401b03169083015260408082015115159083015260609081015162ffffff16910152565b6020808252825182820181905260009190848201906040850190845b81811015611a58576148c583855161485a565b92840192608092909201916001016148b2565b6000602082840312156148ea57600080fd5b8135611d88816144af565b6000806040838503121561490857600080fd5b82356001600160401b0381111561491e57600080fd5b61492a85828601614673565b92505060208301356144e9816144af565b60008060006060848603121561495057600080fd5b833561495b816144af565b95602085013595506040909401359392505050565b8015158114610fe957600080fd5b803561498981614970565b919050565b600080604083850312156149a157600080fd5b82356149ac816144af565b915060208301356144e981614970565b600080600080608085870312156149d257600080fd5b84356149dd816144af565b935060208501356149ed816144af565b92506040850135915060608501356001600160401b03811115614a0f57600080fd5b8501601f81018713614a2057600080fd5b614a2f8782356020840161461c565b91505092959194509250565b60008060408385031215614a4e57600080fd5b82356001600160401b0380821115614a6557600080fd5b614a7186838701614673565b93506020850135915080821115614a8757600080fd5b506147df85828601614673565b60808101610a40828461485a565b600060208284031215614ab457600080fd5b8135611d8881614970565b60008060408385031215614ad257600080fd5b8235614add816144af565b915060208301356144e9816144af565b60008060408385031215614b0057600080fd5b82356001600160401b0380821115614b1757600080fd5b818501915085601f830112614b2b57600080fd5b8135602082821115614b3f57614b3f6145d6565b8160051b9250614b508184016145ec565b8281529284018101928181019089851115614b6a57600080fd5b948201945b84861015614b8857853582529482019490820190614b6f565b9650614b97905087820161497e565b9450505050509250929050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600181811c90821680614c0357607f821691505b602082108103614c2357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201614c6757614c67614c3f565b5060010190565b60008251614c8081846020870161444c565b9190910192915050565b6020808252601c908201527f43616e6e6f74207472616e73666572207374616b656420746f6b656e00000000604082015260600190565b600060208284031215614cd357600080fd5b8151611d8881614970565b6020808252600c908201526b151bdad95b8808595e1a5cdd60a21b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602f908201527f63616c6c6572206d757374206265206f776e6572206f6620746f6b656e206f7260408201526e1031b7b73a3930b1ba1037bbb732b960891b606082015260800190565b601f821115610fb657600081815260208120601f850160051c81016020861015614db15750805b601f850160051c820191505b8181101561320757828155600101614dbd565b81516001600160401b03811115614de957614de96145d6565b614dfd81614df78454614bef565b84614d8a565b602080601f831160018114614e325760008415614e1a5750858301515b600019600386901b1c1916600185901b178555613207565b600085815260208120601f198616915b82811015614e6157888601518255948401946001909101908401614e42565b5085821015614e7f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160401b03831115614ea657614ea66145d6565b614eba83614eb48354614bef565b83614d8a565b6000601f841160018114614eee5760008515614ed65750838201355b600019600387901b1c1916600186901b178355610cee565b600083815260209020601f19861690835b82811015614f1f5786850135825560209485019460019092019101614eff565b5086821015614f3c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60ff8181168382160190811115610a4057610a40614c3f565b81810381811115610a4057610a40614c3f565b60008154614fd581614bef565b60018281168015614fed576001811461500257615031565b60ff1984168752821515830287019450615031565b8560005260208060002060005b858110156150285781548a82015290840190820161500f565b50505082870194505b5050505092915050565b6000611d888284614fc8565b60006020828403121561505957600080fd5b5051919050565b6000835161507281846020880161444c565b61507e81840185614fc8565b95945050505050565b6000826150a457634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156150bb57600080fd5b8151611d88816144af565b80820180821115610a4057610a40614c3f565b60008160001904831182151516156150f3576150f3614c3f565b500290565b602080825260119082015270043616e6e6f7420757064617465206d617607c1b604082015260600190565b60008161513257615132614c3f565b506000190190565b6000835161514c81846020880161444c565b83519083019061516081836020880161444c565b01949350505050565b60208082526034908201527f455243373231415f5f496e697469616c697a61626c653a20636f6e7472616374604082015273206973206e6f7420696e697469616c697a696e6760601b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612a8690830184614470565b60006020828403121561520257600080fd5b8151611d888161440056feee151c8401928dc223602bb187aff91b9a56c7cae5476ef1b3287b085a16c85fa264697066735822122067dbc51832c7efa73553cde410ad7de5c27d4ba9d13406b5860e224380d7297264736f6c63430008100033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104335760003560e01c80637ed5067c11610236578063c39cbef11161013b578063e512bee9116100c3578063f2fde38b11610087578063f2fde38b146109a4578063f6344969146109b7578063f90a82c8146109ca578063fc0f1eeb146109dd578063ff633d5514610a0857600080fd5b8063e512bee91461094f578063e886718014610962578063e985e9c514610975578063eaf16e1314610988578063ecbb3a741461099157600080fd5b8063d595c3311161010a578063d595c33114610906578063d76b47cb14610919578063d8e99f9214610921578063d9ecad7b14610934578063dbbc853b1461094757600080fd5b8063c39cbef1146108c5578063c87b56dd146108d8578063ca0ed7d5146108eb578063d547cfb7146108fe57600080fd5b80639ffdb65a116101be578063ac52e6441161018d578063ac52e64414610849578063b1a6505f1461085c578063b88d4fde1461087f578063bed34bba14610892578063c23dc68f146108a557600080fd5b80639ffdb65a146107fd578063a22cb46514610810578063a694fc3a14610823578063a9852bfb1461083657600080fd5b80639416b423116102055780639416b423146107af57806394d216d6146107c257806395d89b41146107d557806399a2557a146107dd5780639ed27809146107f057600080fd5b80637ed5067c1461076f5780638462151c146107785780638ba4cc3c1461078b5780638da5cb5b1461079e57600080fd5b8063352dd1bd1161033c5780635cd8a76b116102c45780636d522418116102935780636d5224181461070d57806370a0823114610720578063715018a61461073357806372abc8b71461073b5780637ab4339d1461075c57600080fd5b80635cd8a76b146106bf5780636343e0a2146106c75780636352211e146106da578063650b00f6146106ed57600080fd5b806342842e0e1161030b57806342842e0e146106535780634d426528146106665780634faf88471461067957806355f804b31461068c5780635bbb21771461069f57600080fd5b8063352dd1bd146105ed57806335b504c51461060d57806336033deb1461062d57806340a9c8df1461064057600080fd5b806315b56d10116103bf57806327938bb41161038e57806327938bb4146105775780632799cde01461058a5780632cba81231461059d5780632e17de78146105d157806332cb6b0c146105e457600080fd5b806315b56d101461052957806318160ddd1461053c57806323b872dd14610544578063264cd3391461055757600080fd5b8063081812fc11610406578063081812fc1461049257806309308e5d146104bd578063095ea7b3146104f65780630c886c10146105095780630d9341f21461051c57600080fd5b806301ffc9a71461043857806303eaebec1461046057806306e707f31461046a57806306fdde031461047d575b600080fd5b61044b610446366004614416565b610a1b565b60405190151581526020015b60405180910390f35b610468610a46565b005b610468610478366004614433565b610a97565b610485610aa4565b604051610457919061449c565b6104a56104a0366004614433565b610b3f565b6040516001600160a01b039091168152602001610457565b6104e86104cb3660046144c4565b606b60209081526000928352604080842090915290825290205481565b604051908152602001610457565b6104686105043660046144f4565b610b8c565b61046861051736600461456b565b610c3a565b60a65461044b9060ff1681565b61044b610537366004614693565b610cf5565b6104e8610d28565b6104686105523660046146c7565b610d47565b6104e8610565366004614433565b60aa6020526000908152604090205481565b610468610585366004614708565b610f19565b610468610598366004614433565b610fbb565b6104a56105ab366004614749565b606a6020908152600092835260408084209091529082529020546001600160a01b031681565b6104686105df366004614433565b610fec565b6104e8609f5481565b6106006105fb366004614708565b611103565b604051610457919061476b565b6104e861061b366004614433565b60a56020526000908152604090205481565b61048561063b366004614433565b6111b4565b61046861064e366004614433565b61124e565b6104686106613660046146c7565b61127c565b6104686106743660046147a3565b611297565b6104686106873660046146c7565b611352565b61046861069a3660046147e9565b6114d5565b6106b26106ad366004614708565b6114ea565b6040516104579190614896565b6104686115b5565b6104686106d53660046147e9565b61165b565b6104a56106e8366004614433565b6116f3565b6104e86106fb366004614433565b60696020526000908152604090205481565b61048561071b366004614433565b6116fe565b6104e861072e3660046148d8565b6117a0565b610468611808565b61044b610749366004614433565b6000908152606960205260409020541590565b61046861076a3660046148f5565b61181a565b6104e860a85481565b6106006107863660046148d8565b61195c565b6104686107993660046144f4565b611a64565b6036546001600160a01b03166104a5565b6104856107bd366004614693565b611a76565b6104686107d03660046144c4565b611bd0565b610485611bff565b6106006107eb36600461493b565b611c17565b60a45461044b9060ff1681565b61044b61080b366004614693565b611d8f565b61046861081e36600461498e565b611f9a565b610468610831366004614433565b612040565b6104686108443660046147e9565b61219b565b61046861085736600461456b565b61222f565b61044b61086a3660046148d8565b60686020526000908152604090205460ff1681565b61046861088d3660046149bc565b612307565b61044b6108a0366004614a3b565b6124d5565b6108b86108b3366004614433565b61252e565b6040516104579190614a94565b6104686108d33660046147a3565b6125aa565b6104856108e6366004614433565b6128cd565b6104e86108f9366004614433565b612925565b610485612a90565b610468610914366004614433565b612a9d565b610485612bae565b609e546104a5906001600160a01b031681565b610468610942366004614749565b612bbb565b610485612f25565b61046861095d366004614aa2565b612f32565b610468610970366004614aa2565b612f4d565b61044b610983366004614abf565b612f68565b6104e860a05481565b6104e861099f366004614433565b612fa5565b6104686109b23660046148d8565b612fbe565b6104686109c5366004614433565b613034565b6104686109d8366004614aed565b61305d565b6104e86109eb366004614749565b60a760209081526000928352604080842090915290825290205481565b610468610a1636600461498e565b6130e8565b60006001600160e01b0319821663706e848960e01b1480610a405750610a408261328f565b92915050565b600354610100900460ff16610a765760405162461bcd60e51b8152600401610a6d90614ba4565b60405180910390fd5b610a95733cc6cdda760b79bafa08df41ecfa224f810dceb660016130e8565b565b610a9f6132dd565b60a855565b6060610aae613337565b6002018054610abc90614bef565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae890614bef565b8015610b355780601f10610b0a57610100808354040283529160200191610b35565b820191906000526020600020905b815481529060010190602001808311610b1857829003601f168201915b5050505050905090565b6000610b4a8261335b565b610b67576040516333d1c03960e21b815260040160405180910390fd5b610b6f613337565b60009283526006016020525060409020546001600160a01b031690565b6000610b97826116f3565b9050336001600160a01b03821614610bd057610bb38133612f68565b610bd0576040516367d9dca160e11b815260040160405180910390fd5b82610bd9613337565b6000848152600691909101602052604080822080546001600160a01b0319166001600160a01b0394851617905551849286811692908516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a4505050565b610c426132dd565b6001831015610c895760405162461bcd60e51b815260206004820152601360248201527230ba103632b0b9ba1018903932b1b2b4bb32b960691b6044820152606401610a6d565b60005b83811015610cee57610cdc858583818110610ca957610ca9614c29565b9050602002016020810190610cbe91906148d8565b848484818110610cd057610cd0614c29565b90506020020135613397565b80610ce681614c55565b915050610c8c565b5050505050565b60006002610d0283611a76565b604051610d0f9190614c6e565b9081526040519081900360200190205460ff1692915050565b600080610d33613337565b60010154610d3f613337565b540303919050565b826daaeb6d7670e522a718067333cd4e3b15610ecd57336001600160a01b03821603610db857600082815260a5602052604090205415610d995760405162461bcd60e51b8152600401610a6d90614c8a565b600082815260aa6020526040812055610db38484846133f9565b610f13565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610e07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2b9190614cc1565b8015610eae5750604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610e8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eae9190614cc1565b610ecd57604051633b79c77360e21b8152336004820152602401610a6d565b600082815260a5602052604090205415610ef95760405162461bcd60e51b8152600401610a6d90614c8a565b600082815260aa6020526040812055610f138484846133f9565b50505050565b610f216132dd565b6001811015610f685760405162461bcd60e51b815260206004820152601360248201527230ba103632b0b9ba1018903932b1b2b4bb32b960691b6044820152606401610a6d565b60005b81811015610fb657610fa4838383818110610f8857610f88614c29565b9050602002016020810190610f9d91906148d8565b6001613397565b80610fae81614c55565b915050610f6b565b505050565b610fc48161335b565b610fe05760405162461bcd60e51b8152600401610a6d90614cde565b610fe981613452565b50565b6002606c540361100e5760405162461bcd60e51b8152600401610a6d90614d04565b6002606c5561101c816116f3565b6001600160a01b0316336001600160a01b0316148061104557506036546001600160a01b031633145b6110615760405162461bcd60e51b8152600401610a6d90614d3b565b600081815260a560205260409020546110aa5760405162461bcd60e51b815260206004820152600b60248201526a6e6f74207374616b696e6760a81b6044820152606401610a6d565b600081815260a56020908152604080832080549390558051428152918201839052339184917fc1e00202ee2c06861d326fc6374026b751863ff64218ccbaa38c3e603a8e72c2910160405180910390a350506001606c55565b60606000826001600160401b0381111561111f5761111f6145d6565b604051908082528060200260200182016040528015611148578160200160208202803683370190505b50905060005b838110156111ac57600085858381811061116a5761116a614c29565b90506020020135905061117c81612fa5565b83838151811061118e5761118e614c29565b602090810291909101015250806111a481614c55565b91505061114e565b509392505050565b600060208190529081526040902080546111cd90614bef565b80601f01602080910402602001604051908101604052809291908181526020018280546111f990614bef565b80156112465780601f1061121b57610100808354040283529160200191611246565b820191906000526020600020905b81548152906001019060200180831161122957829003601f168201915b505050505081565b6112578161335b565b6112735760405162461bcd60e51b8152600401610a6d90614cde565b610fe981613592565b610fb683838360405180602001604052806000815250612307565b60006112a2836116f3565b9050336001600160a01b038216146112fc5760405162461bcd60e51b815260206004820152601f60248201527f4552433732313a2063616c6c6572206973206e6f7420746865206f776e6572006044820152606401610a6d565b60008381526020819052604090206113148382614dd0565b50827fbe3e2fc72ea4bd0d860e908b1ee27aa9856809e62a75bfc0cb7f04b5d791873d83604051611345919061449c565b60405180910390a2505050565b826001600160a01b0316611365826116f3565b6001600160a01b0316146113cd5760405162461bcd60e51b815260206004820152602960248201527f4f6e6c7920746f6b656e206f776e65722063616e20646f206b65657020544f4c604482015268103a3930b739b332b960b91b6064820152608401610a6d565b336001600160a01b038416146114255760405162461bcd60e51b815260206004820152601f60248201527f53656e646572206d7573742062652066726f6d20746f6b656e206f776e6572006044820152606401610a6d565b816001600160a01b0316836001600160a01b0316036114865760405162461bcd60e51b815260206004820152601d60248201527f46726f6d20616e6420546f206d75737420626520646966666572656e740000006044820152606401610a6d565b600081815260aa602052604081205490036114ca5760006114a68261252e565b602090810151600084815260aa90925260409091206001600160401b039091169055505b610fb68383836133f9565b6114dd6132dd565b60a1610fb6828483614e8f565b6060816000816001600160401b03811115611507576115076145d6565b60405190808252806020026020018201604052801561155957816020015b6040805160808101825260008082526020808301829052928201819052606082015282526000199092019101816115255790505b50905060005b8281146115ac5761158786868381811061157b5761157b614c29565b9050602002013561252e565b82828151811061159957611599614c29565b602090810291909101015260010161155f565b50949350505050565b6115bd6132dd565b600354600290610100900460ff161580156115df575060035460ff8083169116105b6115fb5760405162461bcd60e51b8152600401610a6d90614f4e565b6003805461ffff191660ff831617610100179055611617610a46565b6003805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b6116636132dd565b6116c182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600781526621656d7074792160c81b602082015291506124d59050565b156116e25760408051602081019091526000815260a390610fb69082614dd0565b60a3610fb6828483614e8f565b5050565b6000610a4082613732565b600081815260016020526040902080546060919061171b90614bef565b80601f016020809104026020016040519081016040528092919081815260200182805461174790614bef565b80156117945780601f1061176957610100808354040283529160200191611794565b820191906000526020600020905b81548152906001019060200180831161177757829003601f168201915b50505050509050919050565b60006001600160a01b0382166117c9576040516323d3ad8160e21b815260040160405180910390fd5b6001600160401b036117d9613337565b6005016000846001600160a01b03166001600160a01b0316815260200190815260200160002054169050919050565b6118106132dd565b610a9560006137be565b600354610100900460ff161580801561183a5750600354600160ff909116105b806118545750303b158015611854575060035460ff166001145b6118705760405162461bcd60e51b8152600401610a6d90614f4e565b6003805460ff191660011790558015611893576003805461ff0019166101001790555b6118d56040518060400160405280600481526020016325bab13d60e11b8152506040518060400160405280600481526020016325bab13d60e11b815250613810565b6118dd613849565b60a16118e98482614dd0565b50609e80546001600160a01b0319166001600160a01b038416179055612710609f5562278d0060a0558015610fb6576003805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b6060600080600061196c856117a0565b90506000816001600160401b03811115611988576119886145d6565b6040519080825280602002602001820160405280156119b1578160200160208202803683370190505b5090506119de60408051608081018252600080825260208201819052918101829052606081019190915290565b60005b838614611a58576119f181613878565b91508160400151611a505781516001600160a01b031615611a1157815194505b876001600160a01b0316856001600160a01b031603611a505780838780600101985081518110611a4357611a43614c29565b6020026020010181815250505b6001016119e1565b50909695505050505050565b611a6c6132dd565b6116ef8282613397565b60606000829050600081516001600160401b03811115611a9857611a986145d6565b6040519080825280601f01601f191660200182016040528015611ac2576020820181803683370190505b50905060005b82518110156111ac576041838281518110611ae557611ae5614c29565b016020015160f81c10801590611b155750605a838281518110611b0a57611b0a614c29565b016020015160f81c11155b15611b7757828181518110611b2c57611b2c614c29565b602001015160f81c60f81b60f81c6020611b469190614f9c565b60f81b828281518110611b5b57611b5b614c29565b60200101906001600160f81b031916908160001a905350611bbe565b828181518110611b8957611b89614c29565b602001015160f81c60f81b828281518110611ba657611ba6614c29565b60200101906001600160f81b031916908160001a9053505b80611bc881614c55565b915050611ac8565b611bd98261335b565b611bf55760405162461bcd60e51b8152600401610a6d90614cde565b6116ef82826138bf565b6060611c09613337565b6003018054610abc90614bef565b6060818310611c3957604051631960ccad60e11b815260040160405180910390fd5b600080611c44613a75565b905080841115611c52578093505b6000611c5d876117a0565b905084861015611c7c5785850381811015611c76578091505b50611c80565b5060005b6000816001600160401b03811115611c9a57611c9a6145d6565b604051908082528060200260200182016040528015611cc3578160200160208202803683370190505b50905081600003611cd9579350611d8892505050565b6000611ce48861252e565b905060008160400151611cf5575080515b885b888114158015611d075750848714155b15611d7c57611d1581613878565b92508260400151611d745782516001600160a01b031615611d3557825191505b8a6001600160a01b0316826001600160a01b031603611d745780848880600101995081518110611d6757611d67614c29565b6020026020010181815250505b600101611cf7565b50505092835250909150505b9392505050565b600080829050600181511015611da85750600092915050565b601981511115611dbb5750600092915050565b80600081518110611dce57611dce614c29565b01602001516001600160f81b031916600160fd1b03611df05750600092915050565b8060018251611dff9190614fb5565b81518110611e0f57611e0f614c29565b01602001516001600160f81b031916600160fd1b03611e315750600092915050565b600081600081518110611e4657611e46614c29565b01602001516001600160f81b031916905060005b8251811015611f8f576000838281518110611e7757611e77614c29565b01602001516001600160f81b0319169050600160fd1b81148015611ea85750600160fd1b6001600160f81b03198416145b15611eb95750600095945050505050565b600360fc1b6001600160f81b0319821610801590611ee55750603960f81b6001600160f81b0319821611155b158015611f1b5750604160f81b6001600160f81b0319821610801590611f195750602d60f91b6001600160f81b0319821611155b155b8015611f505750606160f81b6001600160f81b0319821610801590611f4e5750603d60f91b6001600160f81b0319821611155b155b8015611f6a5750600160fd1b6001600160f81b0319821614155b15611f7b5750600095945050505050565b915080611f8781614c55565b915050611e5a565b506001949350505050565b336001600160a01b03831603611fc35760405163b06307db60e01b815260040160405180910390fd5b80611fcc613337565b336000818152600792909201602090815260408084206001600160a01b03881680865290835293819020805460ff19169515159590951790945592518415158152919290917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6002606c54036120625760405162461bcd60e51b8152600401610a6d90614d04565b6002606c5560a45460ff166120ac5760405162461bcd60e51b815260206004820152601060248201526f39ba30b5b4b733903737ba1037b832b760811b6044820152606401610a6d565b6120b5816116f3565b6001600160a01b0316336001600160a01b031614806120de57506036546001600160a01b031633145b6120fa5760405162461bcd60e51b8152600401610a6d90614d3b565b600081815260a56020526040902054156121485760405162461bcd60e51b815260206004820152600f60248201526e616c7265616479207374616b696e6760881b6044820152606401610a6d565b600081815260a5602090815260409182902042908190559151918252339183917f02567b2553aeb44e4ddd5d68462774dc3de158cb0f2c2da1740e729b22086aff910160405180910390a3506001606c55565b6121a36132dd565b61220182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600781526621656d7074792160c81b602082015291506124d59050565b156122225760408051602081019091526000815260a290610fb69082614dd0565b60a2610fb6828483614e8f565b6122376132dd565b8281146122705760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610a6d565b60005b83811015610cee5782828281811061228d5761228d614c29565b90506020020160208101906122a29190614aa2565b606860008787858181106122b8576122b8614c29565b90506020020160208101906122cd91906148d8565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055806122ff81614c55565b915050612273565b836daaeb6d7670e522a718067333cd4e3b1561248e57336001600160a01b0382160361237957600083815260a56020526040902054156123595760405162461bcd60e51b8152600401610a6d90614c8a565b600083815260aa602052604081205561237485858585613a85565b610cee565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa1580156123c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ec9190614cc1565b801561246f5750604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa15801561244b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246f9190614cc1565b61248e57604051633b79c77360e21b8152336004820152602401610a6d565b600083815260a56020526040902054156124ba5760405162461bcd60e51b8152600401610a6d90614c8a565b600083815260aa6020526040812055610cee85858585613a85565b6000816040516020016124e89190614c6e565b604051602081830303815290604052805190602001208360405160200161250f9190614c6e565b6040516020818303038152906040528051906020012014905092915050565b604080516080808201835260008083526020808401829052838501829052606080850183905285519384018652828452908301829052938201819052928101929092529061257a613a75565b83106125865792915050565b61258f83613878565b90508060400151156125a15792915050565b611d8883613adf565b60006125b5836116f3565b9050336001600160a01b0382161461260f5760405162461bcd60e51b815260206004820152601f60248201527f4552433732313a2063616c6c6572206973206e6f7420746865206f776e6572006044820152606401610a6d565b61261882611d8f565b15156001146126605760405162461bcd60e51b81526020600482015260146024820152734e6f7420612076616c6964206e6577206e616d6560601b6044820152606401610a6d565b60008381526001602052604090819020905160029161267e9161503b565b602060405180830381855afa15801561269b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906126be9190615047565b6002836040516126ce9190614c6e565b602060405180830381855afa1580156126eb573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061270e9190615047565b036127675760405162461bcd60e51b815260206004820152602360248201527f4e6577206e616d652069732073616d65206173207468652063757272656e74206044820152626f6e6560e81b6064820152608401610a6d565b61277082610cf5565b156127b55760405162461bcd60e51b815260206004820152601560248201527413985b5948185b1c9958591e481c995cd95c9d9959605a1b6044820152606401610a6d565b600083815260016020526040812080546127ce90614bef565b90501115612879576000838152600160205260409020805461287991906127f490614bef565b80601f016020809104026020016040519081016040528092919081815260200182805461282090614bef565b801561286d5780601f106128425761010080835404028352916020019161286d565b820191906000526020600020905b81548152906001019060200180831161285057829003601f168201915b50505050506000613b14565b612884826001613b14565b600083815260016020526040902061289c8382614dd0565b50827f7e632a301794d8d4a81ea7e20f37d1947158d36e66403af04ba85dd194b66f1b83604051611345919061449c565b6060600060a380546128de90614bef565b905011156128f35760a3805461171b90614bef565b6128fc82613b51565b60a260405160200161290f929190615060565b6040516020818303038152906040529050919050565b60a65460009060ff1661296e5760405162461bcd60e51b8152602060048201526011602482015270313932b2b234b733903737ba1037b832b760791b6044820152606401610a6d565b609e546001600160a01b03166129c05760405162461bcd60e51b815260206004820152601760248201527619d95b995cda5cd0dbdb9d1c9858dd081b9bdd081cd95d604a1b6044820152606401610a6d565b609e5460405163e76abcc760e01b8152600481018490526000916001600160a01b03169063e76abcc790602401602060405180830381865afa158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190615047565b905080600003612a415750600092915050565b6000612a4d8242614fb5565b9050600060a05482612a5f9190615087565b600086815260a760209081526040808320878452909152902054909150612a868183614fb5565b9695505050505050565b60a180546111cd90614bef565b612aa56132dd565b60008111612af55760405162461bcd60e51b815260206004820152601960248201527f6e6577206d617820737570706c792073686f756c64203e2030000000000000006044820152606401610a6d565b609f548110612b465760405162461bcd60e51b815260206004820152601a60248201527f63616e206f6e6c7920726564756365206d617820737570706c790000000000006044820152606401610a6d565b612b4e613bd4565b811015612ba95760405162461bcd60e51b8152602060048201526024808201527f63616e6e6f74206275726e206d6f7265207468616e2063757272656e7420737560448201526370706c7960e01b6064820152608401610a6d565b609f55565b60a380546111cd90614bef565b6002606c5403612bdd5760405162461bcd60e51b8152600401610a6d90614d04565b6002606c5560a65460ff16612c285760405162461bcd60e51b8152602060048201526011602482015270313932b2b234b733903737ba1037b832b760791b6044820152606401610a6d565b609e546001600160a01b0316612c7a5760405162461bcd60e51b815260206004820152601760248201527619d95b995cda5cd0dbdb9d1c9858dd081b9bdd081cd95d604a1b6044820152606401610a6d565b609e5460405163dd7eb9a960e01b8152600481018490526001600160a01b039091169063dd7eb9a990602401602060405180830381865afa158015612cc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce791906150a9565b6001600160a01b0316336001600160a01b031614612d475760405162461bcd60e51b815260206004820152601c60248201527f4e6f74206f776e6572206f662067656e6573697320746f6b656e4964000000006044820152606401610a6d565b6001811015612d985760405162461bcd60e51b815260206004820152601760248201527f73686f756c64206272656564206174206c6561737420310000000000000000006044820152606401610a6d565b609e5460405163e76abcc760e01b8152600481018490526000916001600160a01b03169063e76abcc790602401602060405180830381865afa158015612de2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e069190615047565b90506000612e148242614fb5565b9050600060a05482612e269190615087565b600086815260a76020908152604080832087845290915290205490915081612e4e86836150c6565b1115612ea85760405162461bcd60e51b815260206004820152602360248201527f4e6f7420726561647920746f2062726565642074686174206d616e792062616260448201526269657360e81b6064820152608401610a6d565b600086815260a76020908152604080832087845290915281208054879290612ed19084906150c6565b90915550612ee190503386613397565b604051858152339087907fbf76824ab67eb782060757df49f901075d21a0d5068827dffbb31f8095d783869060200160405180910390a350506001606c5550505050565b60a280546111cd90614bef565b612f3a6132dd565b60a6805460ff1916911515919091179055565b612f556132dd565b60a4805460ff1916911515919091179055565b6000612f72613337565b6001600160a01b039384166000908152600791909101602090815260408083209490951682529290925250205460ff1690565b600080612fb183613be6565b9050611d88600582615087565b612fc66132dd565b6001600160a01b03811661302b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a6d565b610fe9816137be565b61303c6132dd565b600181101561304a57600080fd5b61305781620151806150d9565b60a05550565b6002606c540361307f5760405162461bcd60e51b8152600401610a6d90614d04565b6002606c5560005b82518110156130de5760008382815181106130a4576130a4614c29565b6020026020010151905082156130c2576130bd81612040565b6130cb565b6130cb81610fec565b50806130d681614c55565b915050613087565b50506001606c5550565b600354610100900460ff1661310f5760405162461bcd60e51b8152600401610a6d90614ba4565b6daaeb6d7670e522a718067333cd4e3b156116ef5760405163c3c5a54760e01b81523060048201526daaeb6d7670e522a718067333cd4e9063c3c5a547906024016020604051808303816000875af115801561316f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131939190614cc1565b6116ef57801561320f57604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b1580156131f357600080fd5b505af1158015613207573d6000803e3d6000fd5b505050505050565b6001600160a01b0382161561325e5760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af2903906044016131d9565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e486906024016131d9565b60006301ffc9a760e01b6001600160e01b0319831614806132c057506380ac58cd60e01b6001600160e01b03198316145b80610a405750506001600160e01b031916635b5e139f60e01b1490565b6036546001600160a01b03163314610a955760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a6d565b7f2569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c4090565b6000613365613337565b5482108015610a405750600160e01b61337c613337565b60008481526004919091016020526040902054161592915050565b609f54816133a3613bd4565b6133ad91906150c6565b11156133ef5760405162461bcd60e51b8152602060048201526011602482015270657863656564204d41585f535550504c5960781b6044820152606401610a6d565b6116ef8282613c54565b600081815260696020526040902054156134475760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881a5cc81b1bd8dad959608a1b6044820152606401610a6d565b610fb6838383613d8f565b3360009081526068602052604090205460ff166134815760405162461bcd60e51b8152600401610a6d906150f8565b6000818152606b60209081526040808320338452909152902054156134e85760405162461bcd60e51b815260206004820152601b60248201527f494420616c7265616479206c6f636b65642062792063616c6c657200000000006044820152606401610a6d565b6000818152606960205260408120546135029060016150c6565b6000838152606a60209081526040808320848452825280832080546001600160a01b03191633908117909155868452606b835281842090845282528083208490558583526069909152812080549293509061355c83614c55565b9091555050604051339083907f9ecfd70e9ff36df72989324a49559383d39f9290d700b10cf5ac10dcb68d264390600090a35050565b3360009081526068602052604090205460ff166135c15760405162461bcd60e51b8152600401610a6d906150f8565b6000818152606b602090815260408083203384529091528120549081900361362b5760405162461bcd60e51b815260206004820152601760248201527f4944206e6f74206c6f636b65642062792063616c6c65720000000000000000006044820152606401610a6d565b6000828152606960205260409020548181146136a1576000838152606a602090815260408083208484528252808320805486855282852080546001600160a01b03199081166001600160a01b03909316928317909155825416909155868452606b835281842090845290915290208290556136c9565b6000838152606a60209081526040808320858452909152902080546001600160a01b03191690555b6000838152606b602090815260408083203384528252808320839055858352606990915281208054916136fb83615123565b9091555050604051339084907f0fe7d9801197f79ef3b1595d19379eb58f0fff5f98b0f6d6f34c03cae5306c3790600090a3505050565b60008161373d613337565b548110156137a557600061374f613337565b600083815260049190910160205260408120549150600160e01b821690036137a3575b80600003611d8857613782613337565b60001990920160008181526004939093016020526040909220549050613772565b505b604051636f96cda160e11b815260040160405180910390fd5b603680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600354610100900460ff166138375760405162461bcd60e51b8152600401610a6d90614ba4565b6138418282613f82565b6116ef614096565b600354610100900460ff166138705760405162461bcd60e51b8152600401610a6d90614ba4565b610a956140c5565b604080516080810182526000808252602082018190529181018290526060810191909152610a406138a7613337565b600084815260049190910160205260409020546140f3565b6001600160a01b03811660009081526068602052604090205460ff16156138f85760405162461bcd60e51b8152600401610a6d906150f8565b6000828152606b602090815260408083206001600160a01b03851684529091528120549081900361395b5760405162461bcd60e51b815260206004820152600d60248201526c1251081b9bdd081b1bd8dad959609a1b6044820152606401610a6d565b6000838152606960205260409020548181146139d1576000848152606a602090815260408083208484528252808320805486855282852080546001600160a01b03199081166001600160a01b03909316928317909155825416909155878452606b835281842090845290915290208290556139f9565b6000848152606a60209081526040808320858452909152902080546001600160a01b03191690555b6000848152606b602090815260408083206001600160a01b0387168452825280832083905586835260699091528120805491613a3483615123565b90915550506040516001600160a01b0384169085907f0fe7d9801197f79ef3b1595d19379eb58f0fff5f98b0f6d6f34c03cae5306c3790600090a350505050565b6000613a7f613337565b54919050565b60008281526069602052604090205415613ad35760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881a5cc81b1bd8dad959608a1b6044820152606401610a6d565b610f138484848461413a565b604080516080810182526000808252602082018190529181018290526060810191909152610a40613b0f83613732565b6140f3565b806002613b2084611a76565b604051613b2d9190614c6e565b908152604051908190036020019020805491151560ff199092169190911790555050565b6060613b5c8261335b565b613b7957604051630a14c4b560e41b815260040160405180910390fd5b6000613b8361417e565b90508051600003613ba35760405180602001604052806000815250611d88565b80613bad8461418d565b604051602001613bbe92919061513a565b6040516020818303038152906040529392505050565b600080613bdf613337565b5403919050565b600081815260aa6020526040812054819015613c2957600083815260aa602052604090205460a854613c1891906141c5565b613c229042614fb5565b9050610a40565b613c4a613c358461252e565b602001516001600160401b031660a8546141c5565b611d889042614fb5565b6000613c5e613337565b5490506000829003613c835760405163b562e8dd60e01b815260040160405180910390fd5b680100000000000000018202613c97613337565b6001600160a01b038516600081815260059290920160205260409091208054929092019091554260a01b6001841460e11b1717613cd2613337565b600083815260049190910160205260408120919091556001600160a01b0384169083830190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b818114613d5c57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600101613d24565b5081600003613d7d57604051622e076360e81b815260040160405180910390fd5b80613d86613337565b5550610fb69050565b6000613d9a82613732565b9050836001600160a01b0316816001600160a01b031614613dcd5760405162a1148160e81b815260040160405180910390fd5b600080613dd9846141dc565b91509150613dfe8187613de93390565b6001600160a01b039081169116811491141790565b613e2957613e0c8633612f68565b613e2957604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b038516613e5057604051633a954ecd60e21b815260040160405180910390fd5b8015613e5b57600082555b613e63613337565b6001600160a01b0387166000908152600591909101602052604090208054600019019055613e8f613337565b6001600160a01b03861660008181526005929092016020526040909120805460010190554260a01b17600160e11b17613ec6613337565b60008681526004919091016020526040812091909155600160e11b84169003613f3c5760018401613ef5613337565b600082815260049190910160205260408120549003613f3a57613f16613337565b548114613f3a5783613f26613337565b600083815260049190910160205260409020555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613207565b60008051602061520e83398151915254610100900460ff16613fb75760008051602061520e8339815191525460ff1615613fbb565b303b155b61402d5760405162461bcd60e51b815260206004820152603760248201527f455243373231415f5f496e697469616c697a61626c653a20636f6e747261637460448201527f20697320616c726561647920696e697469616c697a65640000000000000000006064820152608401610a6d565b60008051602061520e83398151915254610100900460ff161580156140695760008051602061520e833981519152805461ffff19166101011790555b6140738383614204565b8015610fb657505060008051602061520e833981519152805461ff001916905550565b600354610100900460ff166140bd5760405162461bcd60e51b8152600401610a6d90614ba4565b610a95614242565b600354610100900460ff166140ec5760405162461bcd60e51b8152600401610a6d90614ba4565b6001606c55565b604080516080810182526001600160a01b038316815260a083901c6001600160401b03166020820152600160e01b831615159181019190915260e89190911c606082015290565b614145848484610d47565b6001600160a01b0383163b15610f135761416184848484614271565b610f13576040516368d2bf6b60e11b815260040160405180910390fd5b606060a18054610abc90614bef565b604080516080019081905280825b600183039250600a81066030018353600a90048061419b5750819003601f19909101908152919050565b6000818310156141d55781611d88565b5090919050565b60008060006141e9613337565b60009485526006016020525050604090912080549092909150565b60008051602061520e83398151915254610100900460ff166142385760405162461bcd60e51b8152600401610a6d90615169565b6116ef828261435d565b600354610100900460ff166142695760405162461bcd60e51b8152600401610a6d90614ba4565b610a956143d0565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906142a69033908990889088906004016151bd565b6020604051808303816000875af19250505080156142e1575060408051601f3d908101601f191682019092526142de918101906151f0565b60015b61433f573d80801561430f576040519150601f19603f3d011682016040523d82523d6000602084013e614314565b606091505b508051600003614337576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b60008051602061520e83398151915254610100900460ff166143915760405162461bcd60e51b8152600401610a6d90615169565b8161439a613337565b600201906143a89082614dd0565b50806143b2613337565b600301906143c09082614dd0565b5060006143cb613337565b555050565b600354610100900460ff166143f75760405162461bcd60e51b8152600401610a6d90614ba4565b610a95336137be565b6001600160e01b031981168114610fe957600080fd5b60006020828403121561442857600080fd5b8135611d8881614400565b60006020828403121561444557600080fd5b5035919050565b60005b8381101561446757818101518382015260200161444f565b50506000910152565b6000815180845261448881602086016020860161444c565b601f01601f19169290920160200192915050565b602081526000611d886020830184614470565b6001600160a01b0381168114610fe957600080fd5b600080604083850312156144d757600080fd5b8235915060208301356144e9816144af565b809150509250929050565b6000806040838503121561450757600080fd5b8235614512816144af565b946020939093013593505050565b60008083601f84011261453257600080fd5b5081356001600160401b0381111561454957600080fd5b6020830191508360208260051b850101111561456457600080fd5b9250929050565b6000806000806040858703121561458157600080fd5b84356001600160401b038082111561459857600080fd5b6145a488838901614520565b909650945060208701359150808211156145bd57600080fd5b506145ca87828801614520565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614614576146146145d6565b604052919050565b60006001600160401b03831115614635576146356145d6565b614648601f8401601f19166020016145ec565b905082815283838301111561465c57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261468457600080fd5b611d888383356020850161461c565b6000602082840312156146a557600080fd5b81356001600160401b038111156146bb57600080fd5b61435584828501614673565b6000806000606084860312156146dc57600080fd5b83356146e7816144af565b925060208401356146f7816144af565b929592945050506040919091013590565b6000806020838503121561471b57600080fd5b82356001600160401b0381111561473157600080fd5b61473d85828601614520565b90969095509350505050565b6000806040838503121561475c57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015611a5857835183529284019291840191600101614787565b600080604083850312156147b657600080fd5b8235915060208301356001600160401b038111156147d357600080fd5b6147df85828601614673565b9150509250929050565b600080602083850312156147fc57600080fd5b82356001600160401b038082111561481357600080fd5b818501915085601f83011261482757600080fd5b81358181111561483657600080fd5b86602082850101111561484857600080fd5b60209290920196919550909350505050565b80516001600160a01b031682526020808201516001600160401b03169083015260408082015115159083015260609081015162ffffff16910152565b6020808252825182820181905260009190848201906040850190845b81811015611a58576148c583855161485a565b92840192608092909201916001016148b2565b6000602082840312156148ea57600080fd5b8135611d88816144af565b6000806040838503121561490857600080fd5b82356001600160401b0381111561491e57600080fd5b61492a85828601614673565b92505060208301356144e9816144af565b60008060006060848603121561495057600080fd5b833561495b816144af565b95602085013595506040909401359392505050565b8015158114610fe957600080fd5b803561498981614970565b919050565b600080604083850312156149a157600080fd5b82356149ac816144af565b915060208301356144e981614970565b600080600080608085870312156149d257600080fd5b84356149dd816144af565b935060208501356149ed816144af565b92506040850135915060608501356001600160401b03811115614a0f57600080fd5b8501601f81018713614a2057600080fd5b614a2f8782356020840161461c565b91505092959194509250565b60008060408385031215614a4e57600080fd5b82356001600160401b0380821115614a6557600080fd5b614a7186838701614673565b93506020850135915080821115614a8757600080fd5b506147df85828601614673565b60808101610a40828461485a565b600060208284031215614ab457600080fd5b8135611d8881614970565b60008060408385031215614ad257600080fd5b8235614add816144af565b915060208301356144e9816144af565b60008060408385031215614b0057600080fd5b82356001600160401b0380821115614b1757600080fd5b818501915085601f830112614b2b57600080fd5b8135602082821115614b3f57614b3f6145d6565b8160051b9250614b508184016145ec565b8281529284018101928181019089851115614b6a57600080fd5b948201945b84861015614b8857853582529482019490820190614b6f565b9650614b97905087820161497e565b9450505050509250929050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600181811c90821680614c0357607f821691505b602082108103614c2357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201614c6757614c67614c3f565b5060010190565b60008251614c8081846020870161444c565b9190910192915050565b6020808252601c908201527f43616e6e6f74207472616e73666572207374616b656420746f6b656e00000000604082015260600190565b600060208284031215614cd357600080fd5b8151611d8881614970565b6020808252600c908201526b151bdad95b8808595e1a5cdd60a21b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602f908201527f63616c6c6572206d757374206265206f776e6572206f6620746f6b656e206f7260408201526e1031b7b73a3930b1ba1037bbb732b960891b606082015260800190565b601f821115610fb657600081815260208120601f850160051c81016020861015614db15750805b601f850160051c820191505b8181101561320757828155600101614dbd565b81516001600160401b03811115614de957614de96145d6565b614dfd81614df78454614bef565b84614d8a565b602080601f831160018114614e325760008415614e1a5750858301515b600019600386901b1c1916600185901b178555613207565b600085815260208120601f198616915b82811015614e6157888601518255948401946001909101908401614e42565b5085821015614e7f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160401b03831115614ea657614ea66145d6565b614eba83614eb48354614bef565b83614d8a565b6000601f841160018114614eee5760008515614ed65750838201355b600019600387901b1c1916600186901b178355610cee565b600083815260209020601f19861690835b82811015614f1f5786850135825560209485019460019092019101614eff565b5086821015614f3c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60ff8181168382160190811115610a4057610a40614c3f565b81810381811115610a4057610a40614c3f565b60008154614fd581614bef565b60018281168015614fed576001811461500257615031565b60ff1984168752821515830287019450615031565b8560005260208060002060005b858110156150285781548a82015290840190820161500f565b50505082870194505b5050505092915050565b6000611d888284614fc8565b60006020828403121561505957600080fd5b5051919050565b6000835161507281846020880161444c565b61507e81840185614fc8565b95945050505050565b6000826150a457634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156150bb57600080fd5b8151611d88816144af565b80820180821115610a4057610a40614c3f565b60008160001904831182151516156150f3576150f3614c3f565b500290565b602080825260119082015270043616e6e6f7420757064617465206d617607c1b604082015260600190565b60008161513257615132614c3f565b506000190190565b6000835161514c81846020880161444c565b83519083019061516081836020880161444c565b01949350505050565b60208082526034908201527f455243373231415f5f496e697469616c697a61626c653a20636f6e7472616374604082015273206973206e6f7420696e697469616c697a696e6760601b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612a8690830184614470565b60006020828403121561520257600080fd5b8151611d888161440056feee151c8401928dc223602bb187aff91b9a56c7cae5476ef1b3287b085a16c85fa264697066735822122067dbc51832c7efa73553cde410ad7de5c27d4ba9d13406b5860e224380d7297264736f6c63430008100033
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
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.