Source Code
Overview
MON Balance
MON Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 5 from a total of 5 transactions
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 37705285 | 62 days ago | Contract Creation | 0 MON |
Loading...
Loading
Contract Name:
FlexiPunkTLD
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "./interfaces/IFlexiPunkMetadata.sol";
import "./interfaces/IBasePunkTLD.sol";
import "../lib/strings.sol";
import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { Base64 } from "@openzeppelin/contracts/utils/Base64.sol";
/// @title Punk Domains TLD contract (Flexi)
/// @author Tempe Techie
/// @notice Dynamically generated NFT contract which represents a top-level domain
contract FlexiPunkTLD is IBasePunkTLD, ERC721, Ownable, ReentrancyGuard {
using strings for string;
// Custom errors
error DomainAlreadyExists();
error DomainBuyingDisabled();
error DomainMintingDisabledForever();
error DomainNameContainsDots();
error DomainNameContainsSpaces();
error DomainNameEmpty();
error DomainNameTooLong();
error FailedToSendDomainPayment();
error FailedToSendReferralFee();
error FailedToSendRoyalty();
error InsufficientPayment();
error MetadataFrozen();
error NotDomainHolder();
error NotRoyaltyFeeReceiver();
error NotRoyaltyFeeUpdater();
error ReferralFeeTooHigh();
error RoyaltyTooHigh();
// Domain struct is defined in IBasePunkTLD
address public immutable factoryAddress; // FlexiPunkTLDFactory address
address public metadataAddress; // FlexiPunkMetadata address
address public minter; // address which is allowed to mint domains even if contract is paused
address public royaltyFeeUpdater; // address which is allowed to change the royalty fee
address public royaltyFeeReceiver; // address which receives the royalty fee
bool public buyingEnabled = false; // buying domains enabled
bool public buyingDisabledForever = false; // buying domains disabled forever
bool public metadataFrozen = false; // metadata address frozen forever
uint256 public totalSupply;
uint256 public idCounter = 1; // up only
uint256 public override price; // domain price
uint256 public royalty; // share of each domain purchase (in bips) that goes to Punk Domains
uint256 public override referral = 1000; // share of each domain purchase (in bips) that goes to the referrer (referral fee)
uint256 public nameMaxLength = 140; // max length for minting a domain name
mapping (string => Domain) public override domains; // mapping (domain name => Domain struct); Domain struct is defined in IBasePunkTLD
mapping (uint256 => string) public domainIdsNames; // mapping (tokenId => domain name)
mapping (address => string) public override defaultNames; // user's default domain
constructor(
string memory _name,
string memory _symbol,
address _tldOwner,
uint256 _domainPrice,
bool _buyingEnabled,
uint256 _royalty,
address _factoryAddress,
address _metadataAddress
) ERC721(_name, _symbol) {
price = _domainPrice;
buyingEnabled = _buyingEnabled;
royalty = _royalty;
metadataAddress = _metadataAddress;
Ownable factory = Ownable(_factoryAddress);
factoryAddress = _factoryAddress;
royaltyFeeUpdater = factory.owner();
royaltyFeeReceiver = factory.owner();
transferOwnership(_tldOwner);
}
// READ
// Domain getters - you can also get all Domain data by calling the auto-generated domains(domainName) method
function getDomainHolder(string calldata _domainName) public override view returns(address) {
return domains[strings.lower(_domainName)].holder;
}
function getDomainData(string calldata _domainName) public override view returns(string memory) {
return domains[strings.lower(_domainName)].data; // should be a JSON object
}
function tokenURI(uint256 _tokenId) public view override returns (string memory) {
return IFlexiPunkMetadata(metadataAddress).getMetadata(
address(this),
domains[domainIdsNames[_tokenId]].name,
name(),
_tokenId
);
}
// WRITE
/// @notice Flexi-specific function
function burn(string calldata _domainName) external {
string memory dName = strings.lower(_domainName);
if (domains[dName].holder != _msgSender()) revert NotDomainHolder();
uint256 tokenId = domains[dName].tokenId;
delete domainIdsNames[tokenId]; // delete tokenId => domainName mapping
delete domains[dName]; // delete string => Domain struct mapping
if (keccak256(bytes(defaultNames[_msgSender()])) == keccak256(bytes(dName))) delete defaultNames[_msgSender()];
_burn(tokenId); // burn the token
--totalSupply;
emit DomainBurned(_msgSender(), dName);
}
/// @notice Default domain is the domain name that reverse resolver returns for a given address.
function editDefaultDomain(string calldata _domainName) external {
string memory dName = strings.lower(_domainName);
if (domains[dName].holder != _msgSender()) revert NotDomainHolder();
defaultNames[_msgSender()] = dName;
emit DefaultDomainChanged(_msgSender(), dName);
}
/// @notice Edit domain custom data. Make sure to not accidentally delete previous data. Fetch previous data first.
/// @param _domainName Only domain name, no TLD/extension.
/// @param _data Custom data needs to be in a JSON object format.
function editData(string calldata _domainName, string calldata _data) external {
string memory dName = strings.lower(_domainName);
if (domains[dName].holder != _msgSender()) revert NotDomainHolder();
domains[dName].data = _data;
emit DataChanged(_msgSender(), _domainName);
}
/// @notice Mint a new domain name as NFT (no dots and spaces allowed).
/// @param _domainName Enter domain name without TLD and make sure letters are in lowercase form.
/// @return token ID
function mint(
string memory _domainName,
address _domainHolder,
address _referrer
) external payable override nonReentrant returns(uint256) {
if (buyingDisabledForever) revert DomainMintingDisabledForever();
if (!buyingEnabled && _msgSender() != owner() && _msgSender() != minter) revert DomainBuyingDisabled();
if (msg.value < price) revert InsufficientPayment();
_sendPayment(msg.value, _referrer);
return _mintDomain(_domainName, _domainHolder, "");
}
function _mintDomain(
string memory _domainNameRaw,
address _domainHolder,
string memory _data
) internal returns(uint256) {
string memory _domainName = strings.lower(_domainNameRaw);
if (strings.len(strings.toSlice(_domainName)) == 0) revert DomainNameEmpty();
if (bytes(_domainName).length >= nameMaxLength) revert DomainNameTooLong();
if (strings.count(strings.toSlice(_domainName), strings.toSlice(".")) > 0) revert DomainNameContainsDots();
if (strings.count(strings.toSlice(_domainName), strings.toSlice(" ")) > 0) revert DomainNameContainsSpaces();
if (domains[_domainName].holder != address(0)) revert DomainAlreadyExists();
_mint(_domainHolder, idCounter);
Domain memory newDomain; // Domain struct is defined in IBasePunkTLD
// store data in Domain struct
newDomain.name = _domainName;
newDomain.tokenId = idCounter;
newDomain.holder = _domainHolder;
newDomain.data = _data;
// add to both mappings
domains[_domainName] = newDomain;
domainIdsNames[idCounter] = _domainName;
// if default domain name is not set for that holder, set it now
if (bytes(defaultNames[_domainHolder]).length == 0) defaultNames[_domainHolder] = _domainName;
emit DomainCreated(_msgSender(), _domainHolder, string(abi.encodePacked(_domainName, name())));
++idCounter;
++totalSupply;
return idCounter-1;
}
function _sendPayment(uint256 _paymentAmount, address _referrer) internal {
if (royalty > 0 && royalty < 5000) {
// send royalty - must be less than 50% (5000 bips)
(bool sentRoyalty, ) = payable(royaltyFeeReceiver).call{value: ((_paymentAmount * royalty) / 10000)}("");
if (!sentRoyalty) revert FailedToSendRoyalty();
}
if (_referrer != address(0) && referral > 0 && referral < 5000) {
// send referral fee - must be less than 50% (5000 bips)
(bool sentReferralFee, ) = payable(_referrer).call{value: ((_paymentAmount * referral) / 10000)}("");
if (!sentReferralFee) revert FailedToSendReferralFee();
}
// send the rest to TLD owner
(bool sent, ) = payable(owner()).call{value: address(this).balance}("");
if (!sent) revert FailedToSendDomainPayment();
}
///@dev Hook that is called before any token transfer. This includes minting and burning.
function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) internal override {
super._beforeTokenTransfer(from, to, tokenId, batchSize);
if (from != address(0)) { // run on every transfer but not on mint
domains[domainIdsNames[tokenId]].holder = to; // change holder address in Domain struct
if (bytes(defaultNames[to]).length == 0 && to != address(0)) {
defaultNames[to] = domains[domainIdsNames[tokenId]].name; // if default domain name is not set for that holder, set it now
}
if (strings.equals(strings.toSlice(domains[domainIdsNames[tokenId]].name), strings.toSlice(defaultNames[from]))) {
delete defaultNames[from]; // if previous owner had this domain name as default, unset it as default
}
}
}
// OWNER
/// @notice Only TLD contract owner can call this function. Flexi-specific function.
function changeMetadataAddress(address _metadataAddress) external onlyOwner {
if (metadataFrozen) revert MetadataFrozen();
address previousAddress = metadataAddress;
metadataAddress = _metadataAddress;
emit MetadataAddressChanged(previousAddress, _metadataAddress);
}
/// @notice Only TLD contract owner can call this function. Flexi-specific function.
function changeMinter(address _minter) external onlyOwner {
address previousMinter = minter;
minter = _minter;
emit MinterAddressChanged(previousMinter, _minter);
}
/// @notice Only TLD contract owner can call this function.
function changeNameMaxLength(uint256 _maxLength) external override onlyOwner {
uint256 previousLength = nameMaxLength;
nameMaxLength = _maxLength;
emit NameMaxLengthChanged(_msgSender(), previousLength, _maxLength);
}
/// @notice Only TLD contract owner can call this function.
function changePrice(uint256 _price) external override onlyOwner {
price = _price;
emit TldPriceChanged(_msgSender(), _price);
}
/// @notice Only TLD contract owner can call this function.
function changeReferralFee(uint256 _referral) external override onlyOwner {
if (_referral >= 5000) revert ReferralFeeTooHigh();
referral = _referral;
emit ReferralFeeChanged(_msgSender(), _referral);
}
/// @notice Only TLD contract owner can call this function. Flexi-specific function.
function disableBuyingForever() external onlyOwner {
buyingDisabledForever = true; // this action is irreversible
emit MintingDisabledForever(_msgSender());
}
/// @notice Freeze metadata address. Only TLD contract owner can call this function.
function freezeMetadata() external onlyOwner {
metadataFrozen = true; // this action is irreversible
emit MetadataFreeze(_msgSender());
}
/// @notice Only TLD contract owner can call this function.
function toggleBuyingDomains() external onlyOwner {
buyingEnabled = !buyingEnabled;
emit DomainBuyingToggle(_msgSender(), buyingEnabled);
}
// ROYALTY FEE UPDATER
/// @notice This changes royalty fee in the wrapper contract. Use basis points (bips) for the value.
function changeRoyalty(uint256 _royalty) external {
if (_royalty > 5000) revert RoyaltyTooHigh(); // cannot exceed 50% (5000 basis points or bips)
if (_msgSender() != royaltyFeeUpdater) revert NotRoyaltyFeeUpdater();
royalty = _royalty;
emit TldRoyaltyChanged(_msgSender(), _royalty);
}
/// @notice This changes royalty fee receiver address. Flexi-specific function.
function changeRoyaltyFeeReceiver(address _newReceiver) external {
if (_msgSender() != royaltyFeeReceiver) revert NotRoyaltyFeeReceiver();
address previousReceiver = royaltyFeeReceiver;
royaltyFeeReceiver = _newReceiver;
emit RoyaltyFeeReceiverChanged(previousReceiver, _newReceiver);
}
/// @notice This changes royalty fee updater address. Flexi-specific function.
function changeRoyaltyFeeUpdater(address _newUpdater) external {
if (_msgSender() != royaltyFeeUpdater) revert NotRoyaltyFeeUpdater();
address previousUpdater = royaltyFeeUpdater;
royaltyFeeUpdater = _newUpdater;
emit RoyaltyFeeUpdaterChanged(previousUpdater, _newUpdater);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev 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. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @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 ReentrancyGuard {
// 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;
constructor() {
_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() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId, 1);
// Check that tokenId was not minted by `_beforeTokenTransfer` hook
require(!_exists(tokenId), "ERC721: token already minted");
unchecked {
// Will not overflow unless all 2**256 token ids are minted to the same owner.
// Given that tokens are minted one by one, it is impossible in practice that
// this ever happens. Might change if we allow batch minting.
// The ERC fails to describe this case.
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvals
delete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred
// out than the owner initially received through minting and transferring in.
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hook
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
// Clear approvals from the previous owner
delete _tokenApprovals[tokenId];
unchecked {
// `_balances[from]` cannot overflow for the same reason as described in `_burn`:
// `from`'s balance is the number of token held, which is at least one before the current
// transfer.
// `_balances[to]` could overflow in the conditions described in `_mint`. That would require
// all 2**256 token ids to be minted, which in practice is impossible.
_balances[from] -= 1;
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
* - When `from` is zero, the tokens will be minted for `to`.
* - When `to` is zero, ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
/**
* @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
* - When `from` is zero, the tokens were minted for `to`.
* - When `to` is zero, ``from``'s tokens were burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
* being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
* that `ownerOf(tokenId)` is `a`.
*/
// solhint-disable-next-line func-name-mixedcase
function __unsafe_increaseBalance(address account, uint256 amount) internal {
_balances[account] += amount;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @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 have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* 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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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 (last updated v4.9.6) (utils/Base64.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides a set of functions to operate with Base64 strings.
*
* _Available since v4.5._
*/
library Base64 {
/**
* @dev Base64 Encoding/Decoding Table
*/
string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* @dev Converts a `bytes` to its Bytes64 `string` representation.
*/
function encode(bytes memory data) internal pure returns (string memory) {
/**
* Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
* https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
*/
if (data.length == 0) return "";
// Loads the table into memory
string memory table = _TABLE;
// Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
// and split into 4 numbers of 6 bits.
// The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
// - `data.length + 2` -> Round up
// - `/ 3` -> Number of 3-bytes chunks
// - `4 *` -> 4 characters for each chunk
string memory result = new string(4 * ((data.length + 2) / 3));
/// @solidity memory-safe-assembly
assembly {
// Prepare the lookup table (skip the first "length" byte)
let tablePtr := add(table, 1)
// Prepare result pointer, jump over length
let resultPtr := add(result, 0x20)
let dataPtr := data
let endPtr := add(data, mload(data))
// In some cases, the last iteration will read bytes after the end of the data. We cache the value, and
// set it to zero to make sure no dirty bytes are read in that section.
let afterPtr := add(endPtr, 0x20)
let afterCache := mload(afterPtr)
mstore(afterPtr, 0x00)
// Run over the input, 3 bytes at a time
for {
} lt(dataPtr, endPtr) {
} {
// Advance 3 bytes
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
// To write each character, shift the 3 byte (24 bits) chunk
// 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
// and apply logical AND with 0x3F to bitmask the least significant 6 bits.
// Use this as an index into the lookup table, mload an entire word
// so the desired character is in the least significant byte, and
// mstore8 this least significant byte into the result and continue.
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
}
// Reset the value that was cached
mstore(afterPtr, afterCache)
// When data `bytes` is not exactly 3 bytes long
// it is padded with `=` characters at the end
switch mod(mload(data), 3)
case 1 {
mstore8(sub(resultPtr, 1), 0x3d)
mstore8(sub(resultPtr, 2), 0x3d)
}
case 2 {
mstore8(sub(resultPtr, 1), 0x3d)
}
}
return result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
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] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: Apache-2.0 /* * @title String & slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> */ pragma solidity ^0.8.0; library strings { struct slice { uint _len; uint _ptr; } function memcpy(uint dest, uint src, uint _len) private pure { // Copy word-length chunks while possible for(; _len >= 32; _len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes uint mask = type(uint).max; if (_len > 0) { mask = 256 ** (32 - _len) - 1; } assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } /* * @dev Returns a slice containing the entire string. * @param self The string to make a slice from. * @return A newly allocated slice containing the entire string. */ function toSlice(string memory self) internal pure returns (slice memory) { uint ptr; assembly { ptr := add(self, 0x20) } return slice(bytes(self).length, ptr); } /* * @dev Returns the length of a null-terminated bytes32 string. * @param self The value to find the length of. * @return The length of the string, from 0 to 32. */ function len(bytes32 self) internal pure returns (uint) { uint ret; if (self == 0) return 0; if (uint(self) & type(uint128).max == 0) { ret += 16; self = bytes32(uint(self) / 0x100000000000000000000000000000000); } if (uint(self) & type(uint64).max == 0) { ret += 8; self = bytes32(uint(self) / 0x10000000000000000); } if (uint(self) & type(uint32).max == 0) { ret += 4; self = bytes32(uint(self) / 0x100000000); } if (uint(self) & type(uint16).max == 0) { ret += 2; self = bytes32(uint(self) / 0x10000); } if (uint(self) & type(uint8).max == 0) { ret += 1; } return 32 - ret; } /* * @dev Returns a slice containing the entire bytes32, interpreted as a * null-terminated utf-8 string. * @param self The bytes32 value to convert to a slice. * @return A new slice containing the value of the input argument up to the * first null. */ function toSliceB32(bytes32 self) internal pure returns (slice memory ret) { // Allocate space for `self` in memory, copy it there, and point ret at it assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 0x20)) mstore(ptr, self) mstore(add(ret, 0x20), ptr) } ret._len = len(self); } /* * @dev Returns a new slice containing the same data as the current slice. * @param self The slice to copy. * @return A new slice containing the same data as `self`. */ function copy(slice memory self) internal pure returns (slice memory) { return slice(self._len, self._ptr); } /* * @dev Copies a slice to a new string. * @param self The slice to copy. * @return A newly allocated string containing the slice's text. */ function toString(slice memory self) internal pure returns (string memory) { string memory ret = new string(self._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); return ret; } /* * @dev Returns the length in runes of the slice. Note that this operation * takes time proportional to the length of the slice; avoid using it * in loops, and call `slice.empty()` if you only need to know whether * the slice is empty or not. * @param self The slice to operate on. * @return The length of the slice in runes. */ function len(slice memory self) internal pure returns (uint l) { // Starting at ptr-31 means the LSB will be the byte we care about uint ptr = self._ptr - 31; uint end = ptr + self._len; for (l = 0; ptr < end; l++) { uint8 b; assembly { b := and(mload(ptr), 0xFF) } if (b < 0x80) { ptr += 1; } else if(b < 0xE0) { ptr += 2; } else if(b < 0xF0) { ptr += 3; } else if(b < 0xF8) { ptr += 4; } else if(b < 0xFC) { ptr += 5; } else { ptr += 6; } } } /* * @dev Returns true if the slice is empty (has a length of 0). * @param self The slice to operate on. * @return True if the slice is empty, False otherwise. */ function empty(slice memory self) internal pure returns (bool) { return self._len == 0; } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two slices are equal. Comparison is done per-rune, * on unicode codepoints. * @param self The first slice to compare. * @param other The second slice to compare. * @return The result of the comparison. */ function compare(slice memory self, slice memory other) internal pure returns (int) { uint shortest = self._len; if (other._len < self._len) shortest = other._len; uint selfptr = self._ptr; uint otherptr = other._ptr; for (uint idx = 0; idx < shortest; idx += 32) { uint a; uint b; assembly { a := mload(selfptr) b := mload(otherptr) } if (a != b) { // Mask out irrelevant bytes and check again uint mask = type(uint).max; // 0xffff... if(shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } unchecked { uint diff = (a & mask) - (b & mask); if (diff != 0) return int(diff); } } selfptr += 32; otherptr += 32; } return int(self._len) - int(other._len); } /* * @dev Returns true if the two slices contain the same text. * @param self The first slice to compare. * @param self The second slice to compare. * @return True if the slices are equal, false otherwise. */ function equals(slice memory self, slice memory other) internal pure returns (bool) { return compare(self, other) == 0; } /* * @dev Extracts the first rune in the slice into `rune`, advancing the * slice to point to the next rune and returning `self`. * @param self The slice to operate on. * @param rune The slice that will contain the first rune. * @return `rune`. */ function nextRune(slice memory self, slice memory rune) internal pure returns (slice memory) { rune._ptr = self._ptr; if (self._len == 0) { rune._len = 0; return rune; } uint l; uint b; // Load the first byte of the rune into the LSBs of b assembly { b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) } if (b < 0x80) { l = 1; } else if(b < 0xE0) { l = 2; } else if(b < 0xF0) { l = 3; } else { l = 4; } // Check for truncated codepoints if (l > self._len) { rune._len = self._len; self._ptr += self._len; self._len = 0; return rune; } self._ptr += l; self._len -= l; rune._len = l; return rune; } /* * @dev Returns the first rune in the slice, advancing the slice to point * to the next rune. * @param self The slice to operate on. * @return A slice containing only the first rune from `self`. */ function nextRune(slice memory self) internal pure returns (slice memory ret) { nextRune(self, ret); } /* * @dev Returns the number of the first codepoint in the slice. * @param self The slice to operate on. * @return The number of the first codepoint in the slice. */ function ord(slice memory self) internal pure returns (uint ret) { if (self._len == 0) { return 0; } uint word; uint length; uint divisor = 2 ** 248; // Load the rune into the MSBs of b assembly { word:= mload(mload(add(self, 32))) } uint b = word / divisor; if (b < 0x80) { ret = b; length = 1; } else if(b < 0xE0) { ret = b & 0x1F; length = 2; } else if(b < 0xF0) { ret = b & 0x0F; length = 3; } else { ret = b & 0x07; length = 4; } // Check for truncated codepoints if (length > self._len) { return 0; } for (uint i = 1; i < length; i++) { divisor = divisor / 256; b = (word / divisor) & 0xFF; if (b & 0xC0 != 0x80) { // Invalid UTF-8 sequence return 0; } ret = (ret * 64) | (b & 0x3F); } return ret; } /* * @dev Returns the keccak-256 hash of the slice. * @param self The slice to hash. * @return The hash of the slice. */ function keccak(slice memory self) internal pure returns (bytes32 ret) { assembly { ret := keccak256(mload(add(self, 32)), mload(self)) } } /* * @dev Returns true if `self` starts with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function startsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } if (self._ptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` starts with `needle`, `needle` is removed from the * beginning of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function beyond(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } bool equal = true; if (self._ptr != needle._ptr) { assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; self._ptr += needle._len; } return self; } /* * @dev Returns true if the slice ends with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function endsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } uint selfptr = self._ptr + self._len - needle._len; if (selfptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` ends with `needle`, `needle` is removed from the * end of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function until(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } uint selfptr = self._ptr + self._len - needle._len; bool equal = true; if (selfptr != needle._ptr) { assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; } return self; } // Returns the memory address of the first byte of the first occurrence of // `needle` in `self`, or the first byte after `self` if not found. function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr = selfptr; uint idx; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask; if (needlelen > 0) { mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); } bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } uint end = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr >= end) return selfptr + selflen; ptr++; assembly { ptrdata := and(mload(ptr), mask) } } return ptr; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; } } } return selfptr + selflen; } // Returns the memory address of the first byte after the last occurrence of // `needle` in `self`, or the address of `self` if not found. function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask; if (needlelen > 0) { mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); } bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } ptr = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr <= selfptr) return selfptr; ptr--; assembly { ptrdata := and(mload(ptr), mask) } } return ptr + needlelen; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr + (selflen - needlelen); while (ptr >= selfptr) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr + needlelen; ptr -= 1; } } } return selfptr; } /* * @dev Modifies `self` to contain everything from the first occurrence of * `needle` to the end of the slice. `self` is set to the empty slice * if `needle` is not found. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function find(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); self._len -= ptr - self._ptr; self._ptr = ptr; return self; } /* * @dev Modifies `self` to contain the part of the string from the start of * `self` to the end of the first occurrence of `needle`. If `needle` * is not found, `self` is set to the empty slice. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function rfind(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); self._len = ptr - self._ptr; return self; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and `token` to everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function split(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = self._ptr; token._len = ptr - self._ptr; if (ptr == self._ptr + self._len) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; self._ptr = ptr + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and returning everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` up to the first occurrence of `delim`. */ function split(slice memory self, slice memory needle) internal pure returns (slice memory token) { split(self, needle, token); } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and `token` to everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function rsplit(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = ptr; token._len = self._len - (ptr - self._ptr); if (ptr == self._ptr) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and returning everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` after the last occurrence of `delim`. */ function rsplit(slice memory self, slice memory needle) internal pure returns (slice memory token) { rsplit(self, needle, token); } /* * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return The number of occurrences of `needle` found in `self`. */ function count(slice memory self, slice memory needle) internal pure returns (uint cnt) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len; while (ptr <= self._ptr + self._len) { cnt++; ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len; } } /* * @dev Returns True if `self` contains `needle`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return True if `needle` is found in `self`, false otherwise. */ function contains(slice memory self, slice memory needle) internal pure returns (bool) { return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; } /* * @dev Returns a newly allocated string containing the concatenation of * `self` and `other`. * @param self The first slice to concatenate. * @param other The second slice to concatenate. * @return The concatenation of the two strings. */ function concat(slice memory self, slice memory other) internal pure returns (string memory) { string memory ret = new string(self._len + other._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); memcpy(retptr + self._len, other._ptr, other._len); return ret; } /* * @dev Joins an array of slices, using `self` as a delimiter, returning a * newly allocated string. * @param self The delimiter to use. * @param parts A list of slices to join. * @return A newly allocated string containing all the slices in `parts`, * joined with `self`. */ function join(slice memory self, slice[] memory parts) internal pure returns (string memory) { if (parts.length == 0) return ""; uint length = self._len * (parts.length - 1); for(uint i = 0; i < parts.length; i++) length += parts[i]._len; string memory ret = new string(length); uint retptr; assembly { retptr := add(ret, 32) } for(uint i = 0; i < parts.length; i++) { memcpy(retptr, parts[i]._ptr, parts[i]._len); retptr += parts[i]._len; if (i < parts.length - 1) { memcpy(retptr, self._ptr, self._len); retptr += self._len; } } return ret; } /** * Lower * * Converts all the values of a string to their corresponding lower case * value. * * @param _base When being used for a data type this is the extended object * otherwise this is the string base to convert to lower case * @return string */ function lower(string memory _base) internal pure returns (string memory) { bytes memory _baseBytes = bytes(_base); for (uint i = 0; i < _baseBytes.length; i++) { _baseBytes[i] = _lower(_baseBytes[i]); } return string(_baseBytes); } /** * Lower * * Convert an alphabetic character to lower case and return the original * value when not alphabetic * * @param _b1 The byte to be converted to lower case * @return bytes1 The converted value if the passed value was alphabetic * and in a upper case otherwise returns the original value */ function _lower(bytes1 _b1) private pure returns (bytes1) { if (_b1 >= 0x41 && _b1 <= 0x5A) { return bytes1(uint8(_b1) + 32); } return _b1; } }
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IBasePunkTLD is IERC721 {
struct Domain {
string name; // domain name that goes before the TLD name; example: "tempetechie" in "tempetechie.web3"
uint256 tokenId;
address holder;
string data; // stringified JSON object, example: {"description": "Some text", "twitter": "@techie1239", "friends": ["0x123..."], "url": "https://punk.domains"}
}
event DomainCreated(address indexed user, address indexed owner, string fullDomainName);
event DomainBurned(address indexed user, string fullDomainName);
event DefaultDomainChanged(address indexed user, string defaultDomain);
event DataChanged(address indexed user, string indexed domain); // note that domain may be missing on events from older contracts
event TldPriceChanged(address indexed user, uint256 tldPrice);
event ReferralFeeChanged(address indexed user, uint256 referralFee);
event TldRoyaltyChanged(address indexed user, uint256 tldRoyalty);
event DomainBuyingToggle(address indexed user, bool domainBuyingToggle);
event MintingDisabledForever(address user);
event RoyaltyFeeReceiverChanged(address indexed previousReceiver, address indexed newReceiver);
event RoyaltyFeeUpdaterChanged(address indexed previousUpdater, address indexed newUpdater);
event MetadataAddressChanged(address indexed previousAddress, address indexed newAddress);
event NameMaxLengthChanged(address indexed user, uint256 previousLength, uint256 newLength);
event MinterAddressChanged(address indexed previousMinter, address indexed newMinter);
event MetadataFreeze(address indexed user);
function domains(string calldata _domainName) external view returns(string memory, uint256, address, string memory);
function defaultNames(address) external view returns(string memory);
function getDomainData(string calldata _domainName) external view returns(string memory);
function getDomainHolder(string calldata _domainName) external view returns(address);
function price() external view returns (uint256);
function referral() external view returns (uint256);
function changeNameMaxLength(uint256 _maxLength) external;
function changePrice(uint256 _price) external;
function changeReferralFee(uint256 _referral) external;
function mint(
string memory _domainName,
address _domainHolder,
address _referrer
) external payable returns(uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface IFlexiPunkMetadata {
function getMetadata(address _tldAddress, string calldata _domainName, string calldata _tld, uint256 _tokenId) external view returns(string memory);
}{
"evmVersion": "london",
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/"
]
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_tldOwner","type":"address"},{"internalType":"uint256","name":"_domainPrice","type":"uint256"},{"internalType":"bool","name":"_buyingEnabled","type":"bool"},{"internalType":"uint256","name":"_royalty","type":"uint256"},{"internalType":"address","name":"_factoryAddress","type":"address"},{"internalType":"address","name":"_metadataAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DomainAlreadyExists","type":"error"},{"inputs":[],"name":"DomainBuyingDisabled","type":"error"},{"inputs":[],"name":"DomainMintingDisabledForever","type":"error"},{"inputs":[],"name":"DomainNameContainsDots","type":"error"},{"inputs":[],"name":"DomainNameContainsSpaces","type":"error"},{"inputs":[],"name":"DomainNameEmpty","type":"error"},{"inputs":[],"name":"DomainNameTooLong","type":"error"},{"inputs":[],"name":"FailedToSendDomainPayment","type":"error"},{"inputs":[],"name":"FailedToSendReferralFee","type":"error"},{"inputs":[],"name":"FailedToSendRoyalty","type":"error"},{"inputs":[],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"MetadataFrozen","type":"error"},{"inputs":[],"name":"NotDomainHolder","type":"error"},{"inputs":[],"name":"NotRoyaltyFeeReceiver","type":"error"},{"inputs":[],"name":"NotRoyaltyFeeUpdater","type":"error"},{"inputs":[],"name":"ReferralFeeTooHigh","type":"error"},{"inputs":[],"name":"RoyaltyTooHigh","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"string","name":"domain","type":"string"}],"name":"DataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"string","name":"defaultDomain","type":"string"}],"name":"DefaultDomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"string","name":"fullDomainName","type":"string"}],"name":"DomainBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"domainBuyingToggle","type":"bool"}],"name":"DomainBuyingToggle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"string","name":"fullDomainName","type":"string"}],"name":"DomainCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"MetadataAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"MetadataFreeze","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousMinter","type":"address"},{"indexed":true,"internalType":"address","name":"newMinter","type":"address"}],"name":"MinterAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"MintingDisabledForever","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLength","type":"uint256"}],"name":"NameMaxLengthChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"referralFee","type":"uint256"}],"name":"ReferralFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousReceiver","type":"address"},{"indexed":true,"internalType":"address","name":"newReceiver","type":"address"}],"name":"RoyaltyFeeReceiverChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousUpdater","type":"address"},{"indexed":true,"internalType":"address","name":"newUpdater","type":"address"}],"name":"RoyaltyFeeUpdaterChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tldPrice","type":"uint256"}],"name":"TldPriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tldRoyalty","type":"uint256"}],"name":"TldRoyaltyChanged","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"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyingDisabledForever","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_metadataAddress","type":"address"}],"name":"changeMetadataAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"changeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLength","type":"uint256"}],"name":"changeNameMaxLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"changePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_referral","type":"uint256"}],"name":"changeReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royalty","type":"uint256"}],"name":"changeRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newReceiver","type":"address"}],"name":"changeRoyaltyFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newUpdater","type":"address"}],"name":"changeRoyaltyFeeUpdater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"defaultNames","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableBuyingForever","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"domainIdsNames","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"domains","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"holder","type":"address"},{"internalType":"string","name":"data","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"},{"internalType":"string","name":"_data","type":"string"}],"name":"editData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"}],"name":"editDefaultDomain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factoryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freezeMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"}],"name":"getDomainData","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"}],"name":"getDomainHolder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"idCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_domainName","type":"string"},{"internalType":"address","name":"_domainHolder","type":"address"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nameMaxLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyFeeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyFeeUpdater","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"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":"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":[],"name":"toggleBuyingDomains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"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"}]Contract Creation Code
60a0604052600b805462ffffff60a01b191690556001600d556103e8601055608c6011553480156200003057600080fd5b506040516200427e3803806200427e83398101604081905262000053916200041e565b878760006200006383826200057c565b5060016200007282826200057c565b5050506200008f620000896200020560201b60201c565b62000209565b6001600755600e859055600b805460ff60a01b1916600160a01b86151502179055600f839055600880546001600160a01b0319166001600160a01b03838116919091179091558216608081905260408051638da5cb5b60e01b81529051849291638da5cb5b9160048083019260209291908290030181865afa1580156200011a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000140919062000648565b600a60006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001cb919062000648565b600b80546001600160a01b0319166001600160a01b0392909216919091179055620001f6876200025b565b5050505050505050506200066d565b3390565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b62000265620002de565b6001600160a01b038116620002d05760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b620002db8162000209565b50565b6006546001600160a01b031633146200033a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620002c7565b565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200036457600080fd5b81516001600160401b03808211156200038157620003816200033c565b604051601f8301601f19908116603f01168101908282118183101715620003ac57620003ac6200033c565b81604052838152602092508683858801011115620003c957600080fd5b600091505b83821015620003ed5785820183015181830184015290820190620003ce565b600093810190920192909252949350505050565b80516001600160a01b03811681146200041957600080fd5b919050565b600080600080600080600080610100898b0312156200043c57600080fd5b88516001600160401b03808211156200045457600080fd5b620004628c838d0162000352565b995060208b01519150808211156200047957600080fd5b50620004888b828c0162000352565b9750506200049960408a0162000401565b95506060890151945060808901518015158114620004b657600080fd5b60a08a01519094509250620004ce60c08a0162000401565b9150620004de60e08a0162000401565b90509295985092959890939650565b600181811c908216806200050257607f821691505b6020821081036200052357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200057757600081815260208120601f850160051c81016020861015620005525750805b601f850160051c820191505b8181101562000573578281556001016200055e565b5050505b505050565b81516001600160401b038111156200059857620005986200033c565b620005b081620005a98454620004ed565b8462000529565b602080601f831160018114620005e85760008415620005cf5750858301515b600019600386901b1c1916600185901b17855562000573565b600085815260208120601f198616915b828110156200061957888601518255948401946001909101908401620005f8565b5085821015620006385787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156200065b57600080fd5b620006668262000401565b9392505050565b608051613bf562000689600039600061066d0152613bf56000f3fe6080604052600436106102c95760003560e01c80638da5cb5b11610175578063bfcdd7c3116100dc578063dafa1d2d11610095578063e985e9c51161006f578063e985e9c51461087b578063eb08ab28146108c4578063f2fde38b146108da578063fb3cc6c2146108fa57600080fd5b8063dafa1d2d14610826578063db6bf92014610846578063dbd843b51461086657600080fd5b8063bfcdd7c314610770578063c1e2515114610790578063c87b56dd146107b0578063d111515d146107d0578063d2b525d3146107e5578063d85451ff1461080557600080fd5b8063a035b1fe1161012e578063a035b1fe146106c5578063a22cb465146106db578063a2b40d19146106fb578063b88d4fde1461071b578063ba833c4b1461073b578063bf70e90d1461075b57600080fd5b80638da5cb5b146106075780638ed2fe911461062557806395d89b4114610646578063966dae0e1461065b5780639f0346911461068f5780639fbb8e86146106a557600080fd5b80633a516d17116102345780636eb3500d116101ed57806374305d09116101c757806374305d091461059457806378a6743b146105b45780637afdfb4f146105d45780637e6d945e146105f457600080fd5b80636eb3500d1461053f57806370a082311461055f578063715018a61461057f57600080fd5b80633a516d171461047f57806342842e0e1461049f5780634c6dcb7f146104bf5780635dedf3b5146104df57806362ac7a84146104ff5780636352211e1461051f57600080fd5b806318160ddd1161028657806318160ddd146103c35780631fd21214146103d957806323b872dd146103f9578063264492351461041957806329ee566c146104495780632c4d4d181461045f57600080fd5b806301ffc9a7146102ce57806306fdde03146103035780630754617214610325578063081812fc1461035d578063095ea7b31461037d5780631441a5a91461039f575b600080fd5b3480156102da57600080fd5b506102ee6102e9366004612f0e565b61091b565b60405190151581526020015b60405180910390f35b34801561030f57600080fd5b5061031861096d565b6040516102fa9190612f7b565b34801561033157600080fd5b50600954610345906001600160a01b031681565b6040516001600160a01b0390911681526020016102fa565b34801561036957600080fd5b50610345610378366004612f8e565b6109ff565b34801561038957600080fd5b5061039d610398366004612fc3565b610a26565b005b3480156103ab57600080fd5b506103b560105481565b6040519081526020016102fa565b3480156103cf57600080fd5b506103b5600c5481565b3480156103e557600080fd5b50600a54610345906001600160a01b031681565b34801561040557600080fd5b5061039d610414366004612fed565b610b40565b34801561042557600080fd5b506104396104343660046130f6565b610b71565b6040516102fa949392919061312b565b34801561045557600080fd5b506103b5600f5481565b34801561046b57600080fd5b5061039d61047a366004613166565b610cc2565b34801561048b57600080fd5b5061039d61049a366004613166565b610d1c565b3480156104ab57600080fd5b5061039d6104ba366004612fed565b610da1565b3480156104cb57600080fd5b5061039d6104da366004613166565b610dbc565b3480156104eb57600080fd5b5061039d6104fa366004612f8e565b610e42565b34801561050b57600080fd5b5061031861051a366004613166565b610e91565b34801561052b57600080fd5b5061034561053a366004612f8e565b610f2b565b34801561054b57600080fd5b50600854610345906001600160a01b031681565b34801561056b57600080fd5b506103b561057a366004613166565b610f8b565b34801561058b57600080fd5b5061039d611011565b3480156105a057600080fd5b5061039d6105af366004613166565b611025565b3480156105c057600080fd5b5061039d6105cf366004612f8e565b6110ab565b3480156105e057600080fd5b506103186105ef3660046131ca565b611113565b6103b561060236600461320c565b611205565b34801561061357600080fd5b506006546001600160a01b0316610345565b34801561063157600080fd5b50600b546102ee90600160a01b900460ff1681565b34801561065257600080fd5b506103186112f7565b34801561066757600080fd5b506103457f000000000000000000000000000000000000000000000000000000000000000081565b34801561069b57600080fd5b506103b560115481565b3480156106b157600080fd5b50600b54610345906001600160a01b031681565b3480156106d157600080fd5b506103b5600e5481565b3480156106e757600080fd5b5061039d6106f636600461326a565b611306565b34801561070757600080fd5b5061039d610716366004612f8e565b611315565b34801561072757600080fd5b5061039d6107363660046132a6565b611354565b34801561074757600080fd5b5061039d610756366004613322565b61138c565b34801561076757600080fd5b5061039d6114af565b34801561077c57600080fd5b5061034561078b3660046131ca565b61151a565b34801561079c57600080fd5b5061039d6107ab366004612f8e565b61158e565b3480156107bc57600080fd5b506103186107cb366004612f8e565b61161c565b3480156107dc57600080fd5b5061039d6116cf565b3480156107f157600080fd5b50610318610800366004612f8e565b611728565b34801561081157600080fd5b50600b546102ee90600160a81b900460ff1681565b34801561083257600080fd5b5061039d6108413660046131ca565b611741565b34801561085257600080fd5b5061039d6108613660046131ca565b611934565b34801561087257600080fd5b5061039d611a2b565b34801561088757600080fd5b506102ee61089636600461338e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b3480156108d057600080fd5b506103b5600d5481565b3480156108e657600080fd5b5061039d6108f5366004613166565b611a8b565b34801561090657600080fd5b50600b546102ee90600160b01b900460ff1681565b60006001600160e01b031982166380ac58cd60e01b148061094c57506001600160e01b03198216635b5e139f60e01b145b8061096757506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461097c906133c1565b80601f01602080910402602001604051908101604052809291908181526020018280546109a8906133c1565b80156109f55780601f106109ca576101008083540402835291602001916109f5565b820191906000526020600020905b8154815290600101906020018083116109d857829003601f168201915b5050505050905090565b6000610a0a82611b04565b506000908152600460205260409020546001600160a01b031690565b6000610a3182610f2b565b9050806001600160a01b0316836001600160a01b031603610aa35760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610abf5750610abf8133610896565b610b315760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610a9a565b610b3b8383611b63565b505050565b610b4a3382611bd1565b610b665760405162461bcd60e51b8152600401610a9a906133fb565b610b3b838383611c50565b8051602081830181018051601282529282019190930120915280548190610b97906133c1565b80601f0160208091040260200160405190810160405280929190818152602001828054610bc3906133c1565b8015610c105780601f10610be557610100808354040283529160200191610c10565b820191906000526020600020905b815481529060010190602001808311610bf357829003601f168201915b5050505060018301546002840154600385018054949592946001600160a01b03909216935090610c3f906133c1565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6b906133c1565b8015610cb85780601f10610c8d57610100808354040283529160200191610cb8565b820191906000526020600020905b815481529060010190602001808311610c9b57829003601f168201915b5050505050905084565b610cca611dc1565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f62381f3a59a05d19239e59370fb6883ce1ed0e49e805be84b13db7cee387a4e290600090a35050565b610d24611dc1565b600b54600160b01b900460ff1615610d4f5760405163777821ff60e11b815260040160405180910390fd5b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f183e7700783be387cdd17a9740651b6e2aff464377defedf1e49dd9a34a008fe90600090a35050565b610b3b83838360405180602001604052806000815250611354565b600a546001600160a01b0316336001600160a01b031614610df057604051636a7c157960e11b815260040160405180910390fd5b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fae01cd00a6259ad2af35d4bd313756efc850467bba11f960003fc7f0af94663e90600090a35050565b610e4a611dc1565b6011805490829055604080518281526020810184905233917fbdc00d562a3da913e01026bac7d30036ab2f8eb33c68c8b021f91821ec958714910160405180910390a25050565b60146020526000908152604090208054610eaa906133c1565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed6906133c1565b8015610f235780601f10610ef857610100808354040283529160200191610f23565b820191906000526020600020905b815481529060010190602001808311610f0657829003601f168201915b505050505081565b6000818152600260205260408120546001600160a01b0316806109675760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610a9a565b60006001600160a01b038216610ff55760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610a9a565b506001600160a01b031660009081526003602052604090205490565b611019611dc1565b6110236000611e1b565b565b600b546001600160a01b0316336001600160a01b031614611059576040516362742dd360e01b815260040160405180910390fd5b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f10076a51a4fbb8ef3703bb7b5da4a8f34cf9360d641301bd3ddc3c299aad8f3390600090a35050565b6110b3611dc1565b61138881106110d557604051635537108960e11b815260040160405180910390fd5b601081905560405181815233907f38d0cf7a8174d3978a2d52052d658cfb52bae5c6ffdad178bf1052ba56ea122e906020015b60405180910390a250565b6060601261115684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b6040516111639190613448565b9081526020016040518091039020600301805461117f906133c1565b80601f01602080910402602001604051908101604052809291908181526020018280546111ab906133c1565b80156111f85780601f106111cd576101008083540402835291602001916111f8565b820191906000526020600020905b8154815290600101906020018083116111db57829003601f168201915b5050505050905092915050565b600061120f611ee7565b600b54600160a81b900460ff161561123a5760405163135d774360e11b815260040160405180910390fd5b600b54600160a01b900460ff1615801561125f57506006546001600160a01b03163314155b801561127f57506009546001600160a01b0316336001600160a01b031614155b1561129d5760405163f381367360e01b815260040160405180910390fd5b600e543410156112c05760405163cd1c886760e01b815260040160405180910390fd5b6112ca3483611f40565b6112e4848460405180602001604052806000815250612129565b90506112f06001600755565b9392505050565b60606001805461097c906133c1565b611311338383612473565b5050565b61131d611dc1565b600e81905560405181815233907fee635c8a0d26ec216072a8c63e35b6ae1a6c900a63c37c014e4ebaac5186104190602001611108565b61135e3383611bd1565b61137a5760405162461bcd60e51b8152600401610a9a906133fb565b61138684848484612541565b50505050565b60006113cd85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b9050336001600160a01b03166012826040516113e99190613448565b908152604051908190036020019020600201546001600160a01b031614611423576040516390a9799f60e01b815260040160405180910390fd5b82826012836040516114359190613448565b908152602001604051809103902060030191826114539291906134c7565b508484604051611464929190613582565b60405180910390206114733390565b6001600160a01b03167fb3706db6f4ec3b24e5d5597b58ae2a43c743a5701b2c0cc17a57a099d29a7c9560405160405180910390a35050505050565b6114b7611dc1565b600b805460ff600160a01b808304821615810260ff60a01b199093169290921792839055604051919092049091161515815233907f8e6cbfe6ffa62410f48c7f382a4560f2b634197f39f7ba9b666914af6674cfdb9060200160405180910390a2565b6000601261155d84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b60405161156a9190613448565b908152604051908190036020019020600201546001600160a01b0316905092915050565b6113888111156115b15760405163c2b03beb60e01b815260040160405180910390fd5b600a546001600160a01b0316336001600160a01b0316146115e557604051636a7c157960e11b815260040160405180910390fd5b600f81905560405181815233907ff76f683b30b41f9eb23902413792df5ff4569a8a274170d9e1b9a16e53558dec90602001611108565b6008546000828152601360205260409081902090516060926001600160a01b0316916389cff9849130916012916116539190613605565b90815260405190819003602001902061166a61096d565b866040518563ffffffff1660e01b815260040161168a9493929190613611565b600060405180830381865afa1580156116a7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261096791908101906136c7565b6116d7611dc1565b600b805460ff60b01b1916600160b01b1790556116f13390565b6001600160a01b03167f4dabf039d151f962abf45ea6c71bbe274f55124300d9c922b8205ed2fa6d92d560405160405180910390a2565b60136020526000908152604090208054610eaa906133c1565b600061178283838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b9050336001600160a01b031660128260405161179e9190613448565b908152604051908190036020019020600201546001600160a01b0316146117d8576040516390a9799f60e01b815260040160405180910390fd5b60006012826040516117ea9190613448565b908152602001604051809103902060010154905060136000828152602001908152602001600020600061181d9190612eae565b60128260405161182d9190613448565b90815260405190819003602001902060006118488282612eae565b6000600183018190556002830180546001600160a01b0319169055611871906003840190612eae565b50508151602083012060146000336001600160a01b03166001600160a01b031681526020019081526020016000206040516118ac9190613605565b6040518091039020036118d1573360009081526014602052604081206118d191612eae565b6118da81612574565b600c600081546118e990613754565b90915550336001600160a01b03167fa37475cf96c0b9779814af0b62cf67583091c685221d6a2c12369240539cb9ef836040516119269190612f7b565b60405180910390a250505050565b600061197583838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b9050336001600160a01b03166012826040516119919190613448565b908152604051908190036020019020600201546001600160a01b0316146119cb576040516390a9799f60e01b815260040160405180910390fd5b3360009081526014602052604090206119e4828261376b565b50336001600160a01b03167f068caa4b2fe151c4db5ef003b9da9f85e1f84c0fa8eaf77f66a095b19998b98882604051611a1e9190612f7b565b60405180910390a2505050565b611a33611dc1565b600b805460ff60a81b1916600160a81b1790557f6d74cc13fa7ed2a0177961820c3be5913f7b4cf15397d50b80357e80ec4ea78a611a6e3390565b6040516001600160a01b03909116815260200160405180910390a1565b611a93611dc1565b6001600160a01b038116611af85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a9a565b611b0181611e1b565b50565b6000818152600260205260409020546001600160a01b0316611b015760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610a9a565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611b9882610f2b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611bdd83610f2b565b9050806001600160a01b0316846001600160a01b03161480611c2457506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b80611c485750836001600160a01b0316611c3d846109ff565b6001600160a01b0316145b949350505050565b826001600160a01b0316611c6382610f2b565b6001600160a01b031614611c895760405162461bcd60e51b8152600401610a9a90613825565b6001600160a01b038216611ceb5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610a9a565b611cf88383836001612617565b826001600160a01b0316611d0b82610f2b565b6001600160a01b031614611d315760405162461bcd60e51b8152600401610a9a90613825565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6006546001600160a01b031633146110235760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9a565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60608160005b8151811015611ee057611ea5828281518110611e9157611e9161386a565b01602001516001600160f81b031916612816565b828281518110611eb757611eb761386a565b60200101906001600160f81b031916908160001a90535080611ed881613880565b915050611e73565b5092915050565b600260075403611f395760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a9a565b6002600755565b6000600f54118015611f555750611388600f54105b15611fea57600b54600f546000916001600160a01b03169061271090611f7b9086613899565b611f8591906138b0565b604051600081818185875af1925050503d8060008114611fc1576040519150601f19603f3d011682016040523d82523d6000602084013e611fc6565b606091505b5050905080611fe8576040516354ef1ec960e01b815260040160405180910390fd5b505b6001600160a01b0381161580159061200457506000601054115b80156120135750611388601054105b156120a4576000816001600160a01b0316612710601054856120359190613899565b61203f91906138b0565b604051600081818185875af1925050503d806000811461207b576040519150601f19603f3d011682016040523d82523d6000602084013e612080565b606091505b50509050806120a25760405163fb4b0bb360e01b815260040160405180910390fd5b505b60006120b86006546001600160a01b031690565b6001600160a01b03164760405160006040518083038185875af1925050503d8060008114612102576040519150601f19603f3d011682016040523d82523d6000602084013e612107565b606091505b5050905080610b3b57604051630767165f60e51b815260040160405180910390fd5b60008061213585611e6d565b905061214861214382612865565b612892565b60000361216857604051631e79693360e11b815260040160405180910390fd5b60115481511061218b5760405163341d4b7560e11b815260040160405180910390fd5b60006121c061219983612865565b6121bb604051806040016040528060018152602001601760f91b815250612865565b61296b565b11156121df576040516335e9eb3f60e21b815260040160405180910390fd5b600061220f6121ed83612865565b6121bb604051806040016040528060018152602001600160fd1b815250612865565b111561222e5760405163eaa7a56d60e01b815260040160405180910390fd5b60006001600160a01b03166012826040516122499190613448565b908152604051908190036020019020600201546001600160a01b0316146122835760405163bd45fcaf60e01b815260040160405180910390fd5b61228f84600d54612a05565b6122c36040518060800160405280606081526020016000815260200160006001600160a01b03168152602001606081525090565b818152600d5460208201526001600160a01b038516604080830191909152606082018590525181906012906122f9908590613448565b90815260405190819003602001902081518190612316908261376b565b506020820151600182015560408201516002820180546001600160a01b0319166001600160a01b039092169190911790556060820151600382019061235b908261376b565b5050600d546000908152601360205260409020905061237a838261376b565b506001600160a01b0385166000908152601460205260409020805461239e906133c1565b90506000036123cb576001600160a01b03851660009081526014602052604090206123c9838261376b565b505b6001600160a01b038516337f6a48f46f419774a1b2d37bbb2e1214ca73c6d3367d4e9ae39c08a9cf99bdd19b8461240061096d565b6040516020016124119291906138d2565b60408051601f198184030181529082905261242b91612f7b565b60405180910390a3600d6000815461244290613880565b90915550600c805460009061245690613880565b90915550600d5461246990600190613901565b9695505050505050565b816001600160a01b0316836001600160a01b0316036124d45760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a9a565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b61254c848484611c50565b61255884848484612b9e565b6113865760405162461bcd60e51b8152600401610a9a90613914565b600061257f82610f2b565b905061258f816000846001612617565b61259882610f2b565b600083815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0385168085526003845282852080546000190190558785526002909352818420805490911690555192935084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b0384161561138657826012601360008581526020019081526020016000206040516126499190613605565b908152604080516020928190038301902060020180546001600160a01b0319166001600160a01b0394851617905591851660009081526014909152208054612690906133c1565b15905080156126a757506001600160a01b03831615155b156126fe576000828152601360205260409081902090516012916126ca91613605565b90815260408051602092819003830190206001600160a01b038616600090815260149093529120906126fc9082613966565b505b6127f06127c36012601360008681526020019081526020016000206040516127269190613605565b9081526040519081900360200190208054612740906133c1565b80601f016020809104026020016040519081016040528092919081815260200182805461276c906133c1565b80156127b95780601f1061278e576101008083540402835291602001916127b9565b820191906000526020600020905b81548152906001019060200180831161279c57829003601f168201915b5050505050612865565b6001600160a01b038616600090815260146020526040902080546127eb9190612740906133c1565b612c9f565b15611386576001600160a01b038416600090815260146020526040812061138691612eae565b6000604160f81b6001600160f81b03198316108015906128445750602d60f91b6001600160f81b0319831611155b156128615761285860f883901c6020613a33565b60f81b92915050565b5090565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b600080601f83602001516128a69190613901565b83519091506000906128b89083613a4c565b9050600092505b8082101561296457815160ff1660808110156128e7576128e0600184613a4c565b9250612951565b60e08160ff1610156128fe576128e0600284613a4c565b60f08160ff161015612915576128e0600384613a4c565b60f88160ff16101561292c576128e0600484613a4c565b60fc8160ff161015612943576128e0600584613a4c565b61294e600684613a4c565b92505b508261295c81613880565b9350506128bf565b5050919050565b600080826000015161298f8560000151866020015186600001518760200151612cb3565b6129999190613a4c565b90505b835160208501516129ad9190613a4c565b8111611ee057816129bd81613880565b92505082600001516129f48560200151836129d89190613901565b86516129e49190613901565b8386600001518760200151612cb3565b6129fe9190613a4c565b905061299c565b6001600160a01b038216612a5b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a9a565b6000818152600260205260409020546001600160a01b031615612ac05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a9a565b612ace600083836001612617565b6000818152600260205260409020546001600160a01b031615612b335760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a9a565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160a01b0384163b15612c9457604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612be2903390899088908890600401613a5f565b6020604051808303816000875af1925050508015612c1d575060408051601f3d908101601f19168201909252612c1a91810190613a92565b60015b612c7a573d808015612c4b576040519150601f19603f3d011682016040523d82523d6000602084013e612c50565b606091505b508051600003612c725760405162461bcd60e51b8152600401610a9a90613914565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611c48565b506001949350505050565b6000612cab8383612dd3565b159392505050565b60008381868511612dbe5760208511612d6d5760008515612cff576001612cdb876020613901565b612ce6906008613899565b612cf1906002613b93565b612cfb9190613901565b1990505b84518116600087612d108b8b613a4c565b612d1a9190613901565b855190915083165b828114612d5f57818610612d4757612d3a8b8b613a4c565b9650505050505050611c48565b85612d5181613880565b965050838651169050612d22565b859650505050505050611c48565b508383206000905b612d7f8689613901565b8211612dbc57858320808203612d9b5783945050505050611c48565b612da6600185613a4c565b9350508180612db490613880565b925050612d75565b505b612dc88787613a4c565b979650505050505050565b8151815160009190811115612de6575081515b6020808501519084015160005b83811015612e9f5782518251808214612e6f576000196020871015612e4e57600184612e20896020613901565b612e2a9190613a4c565b612e35906008613899565b612e40906002613b93565b612e4a9190613901565b1990505b8181168382168181039114612e6c5797506109679650505050505050565b50505b612e7a602086613a4c565b9450612e87602085613a4c565b93505050602081612e989190613a4c565b9050612df3565b50845186516124699190613b9f565b508054612eba906133c1565b6000825580601f10612eca575050565b601f016020900490600052602060002090810190611b0191905b808211156128615760008155600101612ee4565b6001600160e01b031981168114611b0157600080fd5b600060208284031215612f2057600080fd5b81356112f081612ef8565b60005b83811015612f46578181015183820152602001612f2e565b50506000910152565b60008151808452612f67816020860160208601612f2b565b601f01601f19169290920160200192915050565b6020815260006112f06020830184612f4f565b600060208284031215612fa057600080fd5b5035919050565b80356001600160a01b0381168114612fbe57600080fd5b919050565b60008060408385031215612fd657600080fd5b612fdf83612fa7565b946020939093013593505050565b60008060006060848603121561300257600080fd5b61300b84612fa7565b925061301960208501612fa7565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561306857613068613029565b604052919050565b600067ffffffffffffffff82111561308a5761308a613029565b50601f01601f191660200190565b60006130ab6130a684613070565b61303f565b90508281528383830111156130bf57600080fd5b828260208301376000602084830101529392505050565b600082601f8301126130e757600080fd5b6112f083833560208501613098565b60006020828403121561310857600080fd5b813567ffffffffffffffff81111561311f57600080fd5b611c48848285016130d6565b60808152600061313e6080830187612f4f565b602083018690526001600160a01b03851660408401528281036060840152612dc88185612f4f565b60006020828403121561317857600080fd5b6112f082612fa7565b60008083601f84011261319357600080fd5b50813567ffffffffffffffff8111156131ab57600080fd5b6020830191508360208285010111156131c357600080fd5b9250929050565b600080602083850312156131dd57600080fd5b823567ffffffffffffffff8111156131f457600080fd5b61320085828601613181565b90969095509350505050565b60008060006060848603121561322157600080fd5b833567ffffffffffffffff81111561323857600080fd5b613244868287016130d6565b93505061325360208501612fa7565b915061326160408501612fa7565b90509250925092565b6000806040838503121561327d57600080fd5b61328683612fa7565b91506020830135801515811461329b57600080fd5b809150509250929050565b600080600080608085870312156132bc57600080fd5b6132c585612fa7565b93506132d360208601612fa7565b925060408501359150606085013567ffffffffffffffff8111156132f657600080fd5b8501601f8101871361330757600080fd5b61331687823560208401613098565b91505092959194509250565b6000806000806040858703121561333857600080fd5b843567ffffffffffffffff8082111561335057600080fd5b61335c88838901613181565b9096509450602087013591508082111561337557600080fd5b5061338287828801613181565b95989497509550505050565b600080604083850312156133a157600080fd5b6133aa83612fa7565b91506133b860208401612fa7565b90509250929050565b600181811c908216806133d557607f821691505b6020821081036133f557634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6000825161345a818460208701612f2b565b9190910192915050565b601f821115610b3b57600081815260208120601f850160051c8101602086101561348b5750805b601f850160051c820191505b818110156134aa57828155600101613497565b505050505050565b600019600383901b1c191660019190911b1790565b67ffffffffffffffff8311156134df576134df613029565b6134f3836134ed83546133c1565b83613464565b6000601f841160018114613521576000851561350f5750838201355b61351986826134b2565b84555061357b565b600083815260209020601f19861690835b828110156135525786850135825560209485019460019092019101613532565b508682101561356f5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183823760009101908152919050565b6000815461359f816133c1565b600182811680156135b757600181146135cc576135fb565b60ff19841687528215158302870194506135fb565b8560005260208060002060005b858110156135f25781548a8201529084019082016135d9565b50505082870194505b5050505092915050565b60006112f08284613592565b60018060a01b03851681526000602060808184015260008654613633816133c1565b80608087015260a0600180841660008114613655576001811461366f5761369d565b60ff1985168984015283151560051b89018301955061369d565b8b6000528660002060005b858110156136955781548b820186015290830190880161367a565b8a0184019650505b505050505083810360408501526136b48187612f4f565b9250505082606083015295945050505050565b6000602082840312156136d957600080fd5b815167ffffffffffffffff8111156136f057600080fd5b8201601f8101841361370157600080fd5b805161370f6130a682613070565b81815285602083850101111561372457600080fd5b613735826020830160208601612f2b565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b6000816137635761376361373e565b506000190190565b815167ffffffffffffffff81111561378557613785613029565b6137998161379384546133c1565b84613464565b602080601f8311600181146137c857600084156137b65750858301515b6137c085826134b2565b8655506134aa565b600085815260208120601f198616915b828110156137f7578886015182559484019460019091019084016137d8565b50858210156138155787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6000600182016138925761389261373e565b5060010190565b80820281158282048414176109675761096761373e565b6000826138cd57634e487b7160e01b600052601260045260246000fd5b500490565b600083516138e4818460208801612f2b565b8351908301906138f8818360208801612f2b565b01949350505050565b818103818111156109675761096761373e565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b818103613971575050565b61397b82546133c1565b67ffffffffffffffff81111561399357613993613029565b6139a18161379384546133c1565b6000601f8211600181146139cf57600083156139bd5750848201545b6139c784826134b2565b85555061357b565b600085815260209020601f19841690600086815260209020845b83811015613a0957828601548255600195860195909101906020016139e9565b50858310156138155793015460001960f8600387901b161c19169092555050600190811b01905550565b60ff81811683821601908111156109675761096761373e565b808201808211156109675761096761373e565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061246990830184612f4f565b600060208284031215613aa457600080fd5b81516112f081612ef8565b600181815b80851115613aea578160001904821115613ad057613ad061373e565b80851615613add57918102915b93841c9390800290613ab4565b509250929050565b600082613b0157506001610967565b81613b0e57506000610967565b8160018114613b245760028114613b2e57613b4a565b6001915050610967565b60ff841115613b3f57613b3f61373e565b50506001821b610967565b5060208310610133831016604e8410600b8410161715613b6d575081810a610967565b613b778383613aaf565b8060001904821115613b8b57613b8b61373e565b029392505050565b60006112f08383613af2565b8181036000831280158383131683831282161715611ee057611ee061373e56fea26469706673582212202b79b85cc3914331582ac7d64120d60052d37f88f1026d40bcb4a037793760ea64736f6c6343000811003300000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000d22c9708d7638575801eb042be1d2bfeab94bc23000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000be98ce1fe53cac243c092f7d98d1a1262e090a8c000000000000000000000000a37a65518ef4ff8b9584fbb0c322f2532800d0a000000000000000000000000000000000000000000000000000000000000000062e6d6f6e6674000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000062e4d4f4e46540000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102c95760003560e01c80638da5cb5b11610175578063bfcdd7c3116100dc578063dafa1d2d11610095578063e985e9c51161006f578063e985e9c51461087b578063eb08ab28146108c4578063f2fde38b146108da578063fb3cc6c2146108fa57600080fd5b8063dafa1d2d14610826578063db6bf92014610846578063dbd843b51461086657600080fd5b8063bfcdd7c314610770578063c1e2515114610790578063c87b56dd146107b0578063d111515d146107d0578063d2b525d3146107e5578063d85451ff1461080557600080fd5b8063a035b1fe1161012e578063a035b1fe146106c5578063a22cb465146106db578063a2b40d19146106fb578063b88d4fde1461071b578063ba833c4b1461073b578063bf70e90d1461075b57600080fd5b80638da5cb5b146106075780638ed2fe911461062557806395d89b4114610646578063966dae0e1461065b5780639f0346911461068f5780639fbb8e86146106a557600080fd5b80633a516d17116102345780636eb3500d116101ed57806374305d09116101c757806374305d091461059457806378a6743b146105b45780637afdfb4f146105d45780637e6d945e146105f457600080fd5b80636eb3500d1461053f57806370a082311461055f578063715018a61461057f57600080fd5b80633a516d171461047f57806342842e0e1461049f5780634c6dcb7f146104bf5780635dedf3b5146104df57806362ac7a84146104ff5780636352211e1461051f57600080fd5b806318160ddd1161028657806318160ddd146103c35780631fd21214146103d957806323b872dd146103f9578063264492351461041957806329ee566c146104495780632c4d4d181461045f57600080fd5b806301ffc9a7146102ce57806306fdde03146103035780630754617214610325578063081812fc1461035d578063095ea7b31461037d5780631441a5a91461039f575b600080fd5b3480156102da57600080fd5b506102ee6102e9366004612f0e565b61091b565b60405190151581526020015b60405180910390f35b34801561030f57600080fd5b5061031861096d565b6040516102fa9190612f7b565b34801561033157600080fd5b50600954610345906001600160a01b031681565b6040516001600160a01b0390911681526020016102fa565b34801561036957600080fd5b50610345610378366004612f8e565b6109ff565b34801561038957600080fd5b5061039d610398366004612fc3565b610a26565b005b3480156103ab57600080fd5b506103b560105481565b6040519081526020016102fa565b3480156103cf57600080fd5b506103b5600c5481565b3480156103e557600080fd5b50600a54610345906001600160a01b031681565b34801561040557600080fd5b5061039d610414366004612fed565b610b40565b34801561042557600080fd5b506104396104343660046130f6565b610b71565b6040516102fa949392919061312b565b34801561045557600080fd5b506103b5600f5481565b34801561046b57600080fd5b5061039d61047a366004613166565b610cc2565b34801561048b57600080fd5b5061039d61049a366004613166565b610d1c565b3480156104ab57600080fd5b5061039d6104ba366004612fed565b610da1565b3480156104cb57600080fd5b5061039d6104da366004613166565b610dbc565b3480156104eb57600080fd5b5061039d6104fa366004612f8e565b610e42565b34801561050b57600080fd5b5061031861051a366004613166565b610e91565b34801561052b57600080fd5b5061034561053a366004612f8e565b610f2b565b34801561054b57600080fd5b50600854610345906001600160a01b031681565b34801561056b57600080fd5b506103b561057a366004613166565b610f8b565b34801561058b57600080fd5b5061039d611011565b3480156105a057600080fd5b5061039d6105af366004613166565b611025565b3480156105c057600080fd5b5061039d6105cf366004612f8e565b6110ab565b3480156105e057600080fd5b506103186105ef3660046131ca565b611113565b6103b561060236600461320c565b611205565b34801561061357600080fd5b506006546001600160a01b0316610345565b34801561063157600080fd5b50600b546102ee90600160a01b900460ff1681565b34801561065257600080fd5b506103186112f7565b34801561066757600080fd5b506103457f000000000000000000000000be98ce1fe53cac243c092f7d98d1a1262e090a8c81565b34801561069b57600080fd5b506103b560115481565b3480156106b157600080fd5b50600b54610345906001600160a01b031681565b3480156106d157600080fd5b506103b5600e5481565b3480156106e757600080fd5b5061039d6106f636600461326a565b611306565b34801561070757600080fd5b5061039d610716366004612f8e565b611315565b34801561072757600080fd5b5061039d6107363660046132a6565b611354565b34801561074757600080fd5b5061039d610756366004613322565b61138c565b34801561076757600080fd5b5061039d6114af565b34801561077c57600080fd5b5061034561078b3660046131ca565b61151a565b34801561079c57600080fd5b5061039d6107ab366004612f8e565b61158e565b3480156107bc57600080fd5b506103186107cb366004612f8e565b61161c565b3480156107dc57600080fd5b5061039d6116cf565b3480156107f157600080fd5b50610318610800366004612f8e565b611728565b34801561081157600080fd5b50600b546102ee90600160a81b900460ff1681565b34801561083257600080fd5b5061039d6108413660046131ca565b611741565b34801561085257600080fd5b5061039d6108613660046131ca565b611934565b34801561087257600080fd5b5061039d611a2b565b34801561088757600080fd5b506102ee61089636600461338e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b3480156108d057600080fd5b506103b5600d5481565b3480156108e657600080fd5b5061039d6108f5366004613166565b611a8b565b34801561090657600080fd5b50600b546102ee90600160b01b900460ff1681565b60006001600160e01b031982166380ac58cd60e01b148061094c57506001600160e01b03198216635b5e139f60e01b145b8061096757506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461097c906133c1565b80601f01602080910402602001604051908101604052809291908181526020018280546109a8906133c1565b80156109f55780601f106109ca576101008083540402835291602001916109f5565b820191906000526020600020905b8154815290600101906020018083116109d857829003601f168201915b5050505050905090565b6000610a0a82611b04565b506000908152600460205260409020546001600160a01b031690565b6000610a3182610f2b565b9050806001600160a01b0316836001600160a01b031603610aa35760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610abf5750610abf8133610896565b610b315760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610a9a565b610b3b8383611b63565b505050565b610b4a3382611bd1565b610b665760405162461bcd60e51b8152600401610a9a906133fb565b610b3b838383611c50565b8051602081830181018051601282529282019190930120915280548190610b97906133c1565b80601f0160208091040260200160405190810160405280929190818152602001828054610bc3906133c1565b8015610c105780601f10610be557610100808354040283529160200191610c10565b820191906000526020600020905b815481529060010190602001808311610bf357829003601f168201915b5050505060018301546002840154600385018054949592946001600160a01b03909216935090610c3f906133c1565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6b906133c1565b8015610cb85780601f10610c8d57610100808354040283529160200191610cb8565b820191906000526020600020905b815481529060010190602001808311610c9b57829003601f168201915b5050505050905084565b610cca611dc1565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f62381f3a59a05d19239e59370fb6883ce1ed0e49e805be84b13db7cee387a4e290600090a35050565b610d24611dc1565b600b54600160b01b900460ff1615610d4f5760405163777821ff60e11b815260040160405180910390fd5b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f183e7700783be387cdd17a9740651b6e2aff464377defedf1e49dd9a34a008fe90600090a35050565b610b3b83838360405180602001604052806000815250611354565b600a546001600160a01b0316336001600160a01b031614610df057604051636a7c157960e11b815260040160405180910390fd5b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fae01cd00a6259ad2af35d4bd313756efc850467bba11f960003fc7f0af94663e90600090a35050565b610e4a611dc1565b6011805490829055604080518281526020810184905233917fbdc00d562a3da913e01026bac7d30036ab2f8eb33c68c8b021f91821ec958714910160405180910390a25050565b60146020526000908152604090208054610eaa906133c1565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed6906133c1565b8015610f235780601f10610ef857610100808354040283529160200191610f23565b820191906000526020600020905b815481529060010190602001808311610f0657829003601f168201915b505050505081565b6000818152600260205260408120546001600160a01b0316806109675760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610a9a565b60006001600160a01b038216610ff55760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610a9a565b506001600160a01b031660009081526003602052604090205490565b611019611dc1565b6110236000611e1b565b565b600b546001600160a01b0316336001600160a01b031614611059576040516362742dd360e01b815260040160405180910390fd5b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f10076a51a4fbb8ef3703bb7b5da4a8f34cf9360d641301bd3ddc3c299aad8f3390600090a35050565b6110b3611dc1565b61138881106110d557604051635537108960e11b815260040160405180910390fd5b601081905560405181815233907f38d0cf7a8174d3978a2d52052d658cfb52bae5c6ffdad178bf1052ba56ea122e906020015b60405180910390a250565b6060601261115684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b6040516111639190613448565b9081526020016040518091039020600301805461117f906133c1565b80601f01602080910402602001604051908101604052809291908181526020018280546111ab906133c1565b80156111f85780601f106111cd576101008083540402835291602001916111f8565b820191906000526020600020905b8154815290600101906020018083116111db57829003601f168201915b5050505050905092915050565b600061120f611ee7565b600b54600160a81b900460ff161561123a5760405163135d774360e11b815260040160405180910390fd5b600b54600160a01b900460ff1615801561125f57506006546001600160a01b03163314155b801561127f57506009546001600160a01b0316336001600160a01b031614155b1561129d5760405163f381367360e01b815260040160405180910390fd5b600e543410156112c05760405163cd1c886760e01b815260040160405180910390fd5b6112ca3483611f40565b6112e4848460405180602001604052806000815250612129565b90506112f06001600755565b9392505050565b60606001805461097c906133c1565b611311338383612473565b5050565b61131d611dc1565b600e81905560405181815233907fee635c8a0d26ec216072a8c63e35b6ae1a6c900a63c37c014e4ebaac5186104190602001611108565b61135e3383611bd1565b61137a5760405162461bcd60e51b8152600401610a9a906133fb565b61138684848484612541565b50505050565b60006113cd85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b9050336001600160a01b03166012826040516113e99190613448565b908152604051908190036020019020600201546001600160a01b031614611423576040516390a9799f60e01b815260040160405180910390fd5b82826012836040516114359190613448565b908152602001604051809103902060030191826114539291906134c7565b508484604051611464929190613582565b60405180910390206114733390565b6001600160a01b03167fb3706db6f4ec3b24e5d5597b58ae2a43c743a5701b2c0cc17a57a099d29a7c9560405160405180910390a35050505050565b6114b7611dc1565b600b805460ff600160a01b808304821615810260ff60a01b199093169290921792839055604051919092049091161515815233907f8e6cbfe6ffa62410f48c7f382a4560f2b634197f39f7ba9b666914af6674cfdb9060200160405180910390a2565b6000601261155d84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b60405161156a9190613448565b908152604051908190036020019020600201546001600160a01b0316905092915050565b6113888111156115b15760405163c2b03beb60e01b815260040160405180910390fd5b600a546001600160a01b0316336001600160a01b0316146115e557604051636a7c157960e11b815260040160405180910390fd5b600f81905560405181815233907ff76f683b30b41f9eb23902413792df5ff4569a8a274170d9e1b9a16e53558dec90602001611108565b6008546000828152601360205260409081902090516060926001600160a01b0316916389cff9849130916012916116539190613605565b90815260405190819003602001902061166a61096d565b866040518563ffffffff1660e01b815260040161168a9493929190613611565b600060405180830381865afa1580156116a7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261096791908101906136c7565b6116d7611dc1565b600b805460ff60b01b1916600160b01b1790556116f13390565b6001600160a01b03167f4dabf039d151f962abf45ea6c71bbe274f55124300d9c922b8205ed2fa6d92d560405160405180910390a2565b60136020526000908152604090208054610eaa906133c1565b600061178283838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b9050336001600160a01b031660128260405161179e9190613448565b908152604051908190036020019020600201546001600160a01b0316146117d8576040516390a9799f60e01b815260040160405180910390fd5b60006012826040516117ea9190613448565b908152602001604051809103902060010154905060136000828152602001908152602001600020600061181d9190612eae565b60128260405161182d9190613448565b90815260405190819003602001902060006118488282612eae565b6000600183018190556002830180546001600160a01b0319169055611871906003840190612eae565b50508151602083012060146000336001600160a01b03166001600160a01b031681526020019081526020016000206040516118ac9190613605565b6040518091039020036118d1573360009081526014602052604081206118d191612eae565b6118da81612574565b600c600081546118e990613754565b90915550336001600160a01b03167fa37475cf96c0b9779814af0b62cf67583091c685221d6a2c12369240539cb9ef836040516119269190612f7b565b60405180910390a250505050565b600061197583838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6d92505050565b9050336001600160a01b03166012826040516119919190613448565b908152604051908190036020019020600201546001600160a01b0316146119cb576040516390a9799f60e01b815260040160405180910390fd5b3360009081526014602052604090206119e4828261376b565b50336001600160a01b03167f068caa4b2fe151c4db5ef003b9da9f85e1f84c0fa8eaf77f66a095b19998b98882604051611a1e9190612f7b565b60405180910390a2505050565b611a33611dc1565b600b805460ff60a81b1916600160a81b1790557f6d74cc13fa7ed2a0177961820c3be5913f7b4cf15397d50b80357e80ec4ea78a611a6e3390565b6040516001600160a01b03909116815260200160405180910390a1565b611a93611dc1565b6001600160a01b038116611af85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a9a565b611b0181611e1b565b50565b6000818152600260205260409020546001600160a01b0316611b015760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610a9a565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611b9882610f2b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611bdd83610f2b565b9050806001600160a01b0316846001600160a01b03161480611c2457506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b80611c485750836001600160a01b0316611c3d846109ff565b6001600160a01b0316145b949350505050565b826001600160a01b0316611c6382610f2b565b6001600160a01b031614611c895760405162461bcd60e51b8152600401610a9a90613825565b6001600160a01b038216611ceb5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610a9a565b611cf88383836001612617565b826001600160a01b0316611d0b82610f2b565b6001600160a01b031614611d315760405162461bcd60e51b8152600401610a9a90613825565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6006546001600160a01b031633146110235760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9a565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60608160005b8151811015611ee057611ea5828281518110611e9157611e9161386a565b01602001516001600160f81b031916612816565b828281518110611eb757611eb761386a565b60200101906001600160f81b031916908160001a90535080611ed881613880565b915050611e73565b5092915050565b600260075403611f395760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a9a565b6002600755565b6000600f54118015611f555750611388600f54105b15611fea57600b54600f546000916001600160a01b03169061271090611f7b9086613899565b611f8591906138b0565b604051600081818185875af1925050503d8060008114611fc1576040519150601f19603f3d011682016040523d82523d6000602084013e611fc6565b606091505b5050905080611fe8576040516354ef1ec960e01b815260040160405180910390fd5b505b6001600160a01b0381161580159061200457506000601054115b80156120135750611388601054105b156120a4576000816001600160a01b0316612710601054856120359190613899565b61203f91906138b0565b604051600081818185875af1925050503d806000811461207b576040519150601f19603f3d011682016040523d82523d6000602084013e612080565b606091505b50509050806120a25760405163fb4b0bb360e01b815260040160405180910390fd5b505b60006120b86006546001600160a01b031690565b6001600160a01b03164760405160006040518083038185875af1925050503d8060008114612102576040519150601f19603f3d011682016040523d82523d6000602084013e612107565b606091505b5050905080610b3b57604051630767165f60e51b815260040160405180910390fd5b60008061213585611e6d565b905061214861214382612865565b612892565b60000361216857604051631e79693360e11b815260040160405180910390fd5b60115481511061218b5760405163341d4b7560e11b815260040160405180910390fd5b60006121c061219983612865565b6121bb604051806040016040528060018152602001601760f91b815250612865565b61296b565b11156121df576040516335e9eb3f60e21b815260040160405180910390fd5b600061220f6121ed83612865565b6121bb604051806040016040528060018152602001600160fd1b815250612865565b111561222e5760405163eaa7a56d60e01b815260040160405180910390fd5b60006001600160a01b03166012826040516122499190613448565b908152604051908190036020019020600201546001600160a01b0316146122835760405163bd45fcaf60e01b815260040160405180910390fd5b61228f84600d54612a05565b6122c36040518060800160405280606081526020016000815260200160006001600160a01b03168152602001606081525090565b818152600d5460208201526001600160a01b038516604080830191909152606082018590525181906012906122f9908590613448565b90815260405190819003602001902081518190612316908261376b565b506020820151600182015560408201516002820180546001600160a01b0319166001600160a01b039092169190911790556060820151600382019061235b908261376b565b5050600d546000908152601360205260409020905061237a838261376b565b506001600160a01b0385166000908152601460205260409020805461239e906133c1565b90506000036123cb576001600160a01b03851660009081526014602052604090206123c9838261376b565b505b6001600160a01b038516337f6a48f46f419774a1b2d37bbb2e1214ca73c6d3367d4e9ae39c08a9cf99bdd19b8461240061096d565b6040516020016124119291906138d2565b60408051601f198184030181529082905261242b91612f7b565b60405180910390a3600d6000815461244290613880565b90915550600c805460009061245690613880565b90915550600d5461246990600190613901565b9695505050505050565b816001600160a01b0316836001600160a01b0316036124d45760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a9a565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b61254c848484611c50565b61255884848484612b9e565b6113865760405162461bcd60e51b8152600401610a9a90613914565b600061257f82610f2b565b905061258f816000846001612617565b61259882610f2b565b600083815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0385168085526003845282852080546000190190558785526002909352818420805490911690555192935084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b0384161561138657826012601360008581526020019081526020016000206040516126499190613605565b908152604080516020928190038301902060020180546001600160a01b0319166001600160a01b0394851617905591851660009081526014909152208054612690906133c1565b15905080156126a757506001600160a01b03831615155b156126fe576000828152601360205260409081902090516012916126ca91613605565b90815260408051602092819003830190206001600160a01b038616600090815260149093529120906126fc9082613966565b505b6127f06127c36012601360008681526020019081526020016000206040516127269190613605565b9081526040519081900360200190208054612740906133c1565b80601f016020809104026020016040519081016040528092919081815260200182805461276c906133c1565b80156127b95780601f1061278e576101008083540402835291602001916127b9565b820191906000526020600020905b81548152906001019060200180831161279c57829003601f168201915b5050505050612865565b6001600160a01b038616600090815260146020526040902080546127eb9190612740906133c1565b612c9f565b15611386576001600160a01b038416600090815260146020526040812061138691612eae565b6000604160f81b6001600160f81b03198316108015906128445750602d60f91b6001600160f81b0319831611155b156128615761285860f883901c6020613a33565b60f81b92915050565b5090565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b600080601f83602001516128a69190613901565b83519091506000906128b89083613a4c565b9050600092505b8082101561296457815160ff1660808110156128e7576128e0600184613a4c565b9250612951565b60e08160ff1610156128fe576128e0600284613a4c565b60f08160ff161015612915576128e0600384613a4c565b60f88160ff16101561292c576128e0600484613a4c565b60fc8160ff161015612943576128e0600584613a4c565b61294e600684613a4c565b92505b508261295c81613880565b9350506128bf565b5050919050565b600080826000015161298f8560000151866020015186600001518760200151612cb3565b6129999190613a4c565b90505b835160208501516129ad9190613a4c565b8111611ee057816129bd81613880565b92505082600001516129f48560200151836129d89190613901565b86516129e49190613901565b8386600001518760200151612cb3565b6129fe9190613a4c565b905061299c565b6001600160a01b038216612a5b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a9a565b6000818152600260205260409020546001600160a01b031615612ac05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a9a565b612ace600083836001612617565b6000818152600260205260409020546001600160a01b031615612b335760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a9a565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160a01b0384163b15612c9457604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612be2903390899088908890600401613a5f565b6020604051808303816000875af1925050508015612c1d575060408051601f3d908101601f19168201909252612c1a91810190613a92565b60015b612c7a573d808015612c4b576040519150601f19603f3d011682016040523d82523d6000602084013e612c50565b606091505b508051600003612c725760405162461bcd60e51b8152600401610a9a90613914565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611c48565b506001949350505050565b6000612cab8383612dd3565b159392505050565b60008381868511612dbe5760208511612d6d5760008515612cff576001612cdb876020613901565b612ce6906008613899565b612cf1906002613b93565b612cfb9190613901565b1990505b84518116600087612d108b8b613a4c565b612d1a9190613901565b855190915083165b828114612d5f57818610612d4757612d3a8b8b613a4c565b9650505050505050611c48565b85612d5181613880565b965050838651169050612d22565b859650505050505050611c48565b508383206000905b612d7f8689613901565b8211612dbc57858320808203612d9b5783945050505050611c48565b612da6600185613a4c565b9350508180612db490613880565b925050612d75565b505b612dc88787613a4c565b979650505050505050565b8151815160009190811115612de6575081515b6020808501519084015160005b83811015612e9f5782518251808214612e6f576000196020871015612e4e57600184612e20896020613901565b612e2a9190613a4c565b612e35906008613899565b612e40906002613b93565b612e4a9190613901565b1990505b8181168382168181039114612e6c5797506109679650505050505050565b50505b612e7a602086613a4c565b9450612e87602085613a4c565b93505050602081612e989190613a4c565b9050612df3565b50845186516124699190613b9f565b508054612eba906133c1565b6000825580601f10612eca575050565b601f016020900490600052602060002090810190611b0191905b808211156128615760008155600101612ee4565b6001600160e01b031981168114611b0157600080fd5b600060208284031215612f2057600080fd5b81356112f081612ef8565b60005b83811015612f46578181015183820152602001612f2e565b50506000910152565b60008151808452612f67816020860160208601612f2b565b601f01601f19169290920160200192915050565b6020815260006112f06020830184612f4f565b600060208284031215612fa057600080fd5b5035919050565b80356001600160a01b0381168114612fbe57600080fd5b919050565b60008060408385031215612fd657600080fd5b612fdf83612fa7565b946020939093013593505050565b60008060006060848603121561300257600080fd5b61300b84612fa7565b925061301960208501612fa7565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561306857613068613029565b604052919050565b600067ffffffffffffffff82111561308a5761308a613029565b50601f01601f191660200190565b60006130ab6130a684613070565b61303f565b90508281528383830111156130bf57600080fd5b828260208301376000602084830101529392505050565b600082601f8301126130e757600080fd5b6112f083833560208501613098565b60006020828403121561310857600080fd5b813567ffffffffffffffff81111561311f57600080fd5b611c48848285016130d6565b60808152600061313e6080830187612f4f565b602083018690526001600160a01b03851660408401528281036060840152612dc88185612f4f565b60006020828403121561317857600080fd5b6112f082612fa7565b60008083601f84011261319357600080fd5b50813567ffffffffffffffff8111156131ab57600080fd5b6020830191508360208285010111156131c357600080fd5b9250929050565b600080602083850312156131dd57600080fd5b823567ffffffffffffffff8111156131f457600080fd5b61320085828601613181565b90969095509350505050565b60008060006060848603121561322157600080fd5b833567ffffffffffffffff81111561323857600080fd5b613244868287016130d6565b93505061325360208501612fa7565b915061326160408501612fa7565b90509250925092565b6000806040838503121561327d57600080fd5b61328683612fa7565b91506020830135801515811461329b57600080fd5b809150509250929050565b600080600080608085870312156132bc57600080fd5b6132c585612fa7565b93506132d360208601612fa7565b925060408501359150606085013567ffffffffffffffff8111156132f657600080fd5b8501601f8101871361330757600080fd5b61331687823560208401613098565b91505092959194509250565b6000806000806040858703121561333857600080fd5b843567ffffffffffffffff8082111561335057600080fd5b61335c88838901613181565b9096509450602087013591508082111561337557600080fd5b5061338287828801613181565b95989497509550505050565b600080604083850312156133a157600080fd5b6133aa83612fa7565b91506133b860208401612fa7565b90509250929050565b600181811c908216806133d557607f821691505b6020821081036133f557634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6000825161345a818460208701612f2b565b9190910192915050565b601f821115610b3b57600081815260208120601f850160051c8101602086101561348b5750805b601f850160051c820191505b818110156134aa57828155600101613497565b505050505050565b600019600383901b1c191660019190911b1790565b67ffffffffffffffff8311156134df576134df613029565b6134f3836134ed83546133c1565b83613464565b6000601f841160018114613521576000851561350f5750838201355b61351986826134b2565b84555061357b565b600083815260209020601f19861690835b828110156135525786850135825560209485019460019092019101613532565b508682101561356f5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183823760009101908152919050565b6000815461359f816133c1565b600182811680156135b757600181146135cc576135fb565b60ff19841687528215158302870194506135fb565b8560005260208060002060005b858110156135f25781548a8201529084019082016135d9565b50505082870194505b5050505092915050565b60006112f08284613592565b60018060a01b03851681526000602060808184015260008654613633816133c1565b80608087015260a0600180841660008114613655576001811461366f5761369d565b60ff1985168984015283151560051b89018301955061369d565b8b6000528660002060005b858110156136955781548b820186015290830190880161367a565b8a0184019650505b505050505083810360408501526136b48187612f4f565b9250505082606083015295945050505050565b6000602082840312156136d957600080fd5b815167ffffffffffffffff8111156136f057600080fd5b8201601f8101841361370157600080fd5b805161370f6130a682613070565b81815285602083850101111561372457600080fd5b613735826020830160208601612f2b565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b6000816137635761376361373e565b506000190190565b815167ffffffffffffffff81111561378557613785613029565b6137998161379384546133c1565b84613464565b602080601f8311600181146137c857600084156137b65750858301515b6137c085826134b2565b8655506134aa565b600085815260208120601f198616915b828110156137f7578886015182559484019460019091019084016137d8565b50858210156138155787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6000600182016138925761389261373e565b5060010190565b80820281158282048414176109675761096761373e565b6000826138cd57634e487b7160e01b600052601260045260246000fd5b500490565b600083516138e4818460208801612f2b565b8351908301906138f8818360208801612f2b565b01949350505050565b818103818111156109675761096761373e565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b818103613971575050565b61397b82546133c1565b67ffffffffffffffff81111561399357613993613029565b6139a18161379384546133c1565b6000601f8211600181146139cf57600083156139bd5750848201545b6139c784826134b2565b85555061357b565b600085815260209020601f19841690600086815260209020845b83811015613a0957828601548255600195860195909101906020016139e9565b50858310156138155793015460001960f8600387901b161c19169092555050600190811b01905550565b60ff81811683821601908111156109675761096761373e565b808201808211156109675761096761373e565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061246990830184612f4f565b600060208284031215613aa457600080fd5b81516112f081612ef8565b600181815b80851115613aea578160001904821115613ad057613ad061373e565b80851615613add57918102915b93841c9390800290613ab4565b509250929050565b600082613b0157506001610967565b81613b0e57506000610967565b8160018114613b245760028114613b2e57613b4a565b6001915050610967565b60ff841115613b3f57613b3f61373e565b50506001821b610967565b5060208310610133831016604e8410600b8410161715613b6d575081810a610967565b613b778383613aaf565b8060001904821115613b8b57613b8b61373e565b029392505050565b60006112f08383613af2565b8181036000831280158383131683831282161715611ee057611ee061373e56fea26469706673582212202b79b85cc3914331582ac7d64120d60052d37f88f1026d40bcb4a037793760ea64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000d22c9708d7638575801eb042be1d2bfeab94bc23000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000be98ce1fe53cac243c092f7d98d1a1262e090a8c000000000000000000000000a37a65518ef4ff8b9584fbb0c322f2532800d0a000000000000000000000000000000000000000000000000000000000000000062e6d6f6e6674000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000062e4d4f4e46540000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): .monft
Arg [1] : _symbol (string): .MONFT
Arg [2] : _tldOwner (address): 0xD22c9708D7638575801Eb042be1d2BFEab94BC23
Arg [3] : _domainPrice (uint256): 0
Arg [4] : _buyingEnabled (bool): False
Arg [5] : _royalty (uint256): 0
Arg [6] : _factoryAddress (address): 0xbe98cE1fE53CAc243C092F7d98D1A1262E090A8c
Arg [7] : _metadataAddress (address): 0xA37a65518ef4ff8b9584Fbb0C322f2532800D0A0
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 000000000000000000000000d22c9708d7638575801eb042be1d2bfeab94bc23
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 000000000000000000000000be98ce1fe53cac243c092f7d98d1a1262e090a8c
Arg [7] : 000000000000000000000000a37a65518ef4ff8b9584fbb0c322f2532800d0a0
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [9] : 2e6d6f6e66740000000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [11] : 2e4d4f4e46540000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MON
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.