Overview
ETH Balance
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 31 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Approval For... | 19034208 | 262 days ago | IN | 0 ETH | 0.00000005 | ||||
| Set Approval For... | 16363776 | 324 days ago | IN | 0 ETH | 0.00000154 | ||||
| Set Approval For... | 14203916 | 374 days ago | IN | 0 ETH | 0.00001888 | ||||
| Set Approval For... | 7805373 | 522 days ago | IN | 0 ETH | 0.00000162 | ||||
| Set Approval For... | 6412320 | 554 days ago | IN | 0 ETH | 0 | ||||
| Set Approval For... | 6119215 | 561 days ago | IN | 0 ETH | 0.00000022 | ||||
| Set Approval For... | 4558597 | 597 days ago | IN | 0 ETH | 0.00000047 | ||||
| Transfer From | 4169977 | 606 days ago | IN | 0 ETH | 0.0000009 | ||||
| Transfer From | 4125211 | 607 days ago | IN | 0 ETH | 0.00000084 | ||||
| Transfer From | 4122445 | 607 days ago | IN | 0 ETH | 0.00000098 | ||||
| Set Approval For... | 3877808 | 613 days ago | IN | 0 ETH | 0.00002907 | ||||
| Set Approval For... | 3877805 | 613 days ago | IN | 0 ETH | 0.0000293 | ||||
| Set Approval For... | 3395742 | 624 days ago | IN | 0 ETH | 0.00000782 | ||||
| Set Approval For... | 3395717 | 624 days ago | IN | 0 ETH | 0.00000785 | ||||
| Set Approval For... | 3258522 | 627 days ago | IN | 0 ETH | 0.00000762 | ||||
| Set Approval For... | 3137320 | 630 days ago | IN | 0 ETH | 0.00001296 | ||||
| Set Approval For... | 2139843 | 653 days ago | IN | 0 ETH | 0.00001794 | ||||
| Set Approval For... | 2138365 | 653 days ago | IN | 0 ETH | 0.00002136 | ||||
| Set Approval For... | 1918342 | 658 days ago | IN | 0 ETH | 0.00003778 | ||||
| Set Approval For... | 1892605 | 659 days ago | IN | 0 ETH | 0.00008083 | ||||
| Set Approval For... | 1889585 | 659 days ago | IN | 0 ETH | 0.00004728 | ||||
| Set Approval For... | 1884645 | 659 days ago | IN | 0 ETH | 0.00003667 | ||||
| Set Approval For... | 1759515 | 662 days ago | IN | 0 ETH | 0.00005395 | ||||
| Set Approval For... | 1387579 | 671 days ago | IN | 0 ETH | 0.00005077 | ||||
| Set Approval For... | 1309687 | 673 days ago | IN | 0 ETH | 0.00002838 |
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import './ERC721Tradable.sol';
/**
* @title Avatar
* Avatar - a contract for my non-fungible avatars.
*/
contract Avatar is ERC721Tradable {
string baseURI;
constructor(
string memory _initialBaseURI,
address _defaultRoyaltyReceiver,
uint96 _defaultFeeNumerator
) ERC721Tradable('FP Avatar', 'FPIKER', _defaultRoyaltyReceiver, _defaultFeeNumerator) Ownable(msg.sender) {
baseURI = _initialBaseURI;
}
function baseTokenURI() public view override returns (string memory) {
return baseURI;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view returns (address receiver, uint256 royaltyAmount);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/common/ERC2981.sol)
pragma solidity ^0.8.20;
import {IERC2981} from "../../interfaces/IERC2981.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*/
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
*/
error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);
/**
* @dev The default royalty receiver is invalid.
*/
error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);
/**
* @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
*/
error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
/**
* @dev The royalty receiver for `tokenId` is invalid.
*/
error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/
function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];
if (royalty.receiver == address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
}
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
}
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.20;
import {IERC721} from "./IERC721.sol";
import {IERC721Receiver} from "./IERC721Receiver.sol";
import {IERC721Metadata} from "./extensions/IERC721Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {Strings} from "../../utils/Strings.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
import {IERC721Errors} from "../../interfaces/draft-IERC6093.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}.
*/
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
mapping(uint256 tokenId => address) private _owners;
mapping(address owner => uint256) private _balances;
mapping(uint256 tokenId => address) private _tokenApprovals;
mapping(address owner => mapping(address operator => 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 returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(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 {
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is 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`.
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
* the `spender` for the specific `tokenId`.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
// Perform (optional) operator check
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the update
if (from != address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
/**
* @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 {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* 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 {
_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);
_checkOnERC721Received(address(0), to, tokenId, data);
}
/**
* @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 {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC721 standard 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 like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` cannot be the zero address.
* - 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) internal {
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
// Avoid reading the owner unless necessary
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approve
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
* recipient doesn't accept the token transfer. 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
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
revert ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert ERC721InvalidReceiver(to);
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.20;
import {ERC721} from "../ERC721.sol";
import {IERC721Enumerable} from "./IERC721Enumerable.sol";
import {IERC165} from "../../../utils/introspection/ERC165.sol";
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds enumerability
* of all the token ids in the contract as well as all token ids owned by each account.
*
* CAUTION: `ERC721` extensions that implement custom `balanceOf` logic, such as `ERC721Consecutive`,
* interfere with enumerability and should not be used together with `ERC721Enumerable`.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
mapping(uint256 tokenId => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 tokenId => uint256) private _allTokensIndex;
/**
* @dev An `owner`'s token query was out of bounds for `index`.
*
* NOTE: The owner being `address(0)` indicates a global out of bounds index.
*/
error ERC721OutOfBoundsIndex(address owner, uint256 index);
/**
* @dev Batch mint is not allowed.
*/
error ERC721EnumerableForbiddenBatchMint();
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
/**
* @dev See {ERC721-_update}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
address previousOwner = super._update(to, tokenId, auth);
if (previousOwner == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = balanceOf(to) - 1;
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
/**
* See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
*/
function _increaseBalance(address account, uint128 amount) internal virtual override {
if (amount > 0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Royalty.sol)
pragma solidity ^0.8.20;
import {ERC721} from "../ERC721.sol";
import {ERC2981} from "../../common/ERC2981.sol";
/**
* @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment
* information.
*
* Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually
* for specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*/
abstract contract ERC721Royalty is ERC2981, ERC721 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
return super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.20;
import {IERC721} from "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.20;
import {IERC721} from "../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 v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../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 address zero.
*
* 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 v5.0.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @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 or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* 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.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @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`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) 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 FailedInnerCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Arrays.sol)
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
import {Math} from "./math/Math.sol";
/**
* @dev Collection of functions related to array types.
*/
library Arrays {
using StorageSlot for bytes32;
/**
* @dev Searches a sorted `array` and returns the first index that contains
* a value greater or equal to `element`. If no such index exists (i.e. all
* values in the array are strictly less than `element`), the array length is
* returned. Time complexity O(log n).
*
* `array` is expected to be sorted in ascending order, and to contain no
* repeated elements.
*/
function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
low = mid + 1;
}
}
// At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
if (low > 0 && unsafeAccess(array, low - 1).value == element) {
return low - 1;
} else {
return low;
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getAddressSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getBytes32Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getUint256Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./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);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @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;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
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
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// 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 v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/utils/Strings.sol';
import './interfaces/IFactoryERC721.sol';
import './interfaces/IBlast.sol';
import './Avatar.sol';
import './AvatarLootbox.sol';
contract AvatarFactory is FactoryERC721, Ownable {
IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002);
using Strings for string;
address public avatarAddress;
address public lootboxAddress;
address payable public treasuryAddress;
uint256[] public lootboxPrices;
mapping(address => bool) public whitelist;
uint256 public whitelistLootboxPrice;
/*
* Enforce the existence of only 10000 FortunePike avatars.
*/
uint256 RESERVED_AVATAR_SUPPLY = 10000;
/*
* Three different options for minting.
*/
uint256 SINGLE_ITEM_OPTION = 0;
uint256 LOOTBOX_OPTION = 1;
uint256 REGULAR_SINGLE_ITEM_OPTION = 2;
uint256 REGULAR_LOOTBOX_OPTION = 3;
event Transfer(address indexed from, address indexed to);
event Withdraw(address target, uint amount);
constructor(address _avatarAddress, address _lootboxAddress, address payable _treasuryAddress) Ownable(msg.sender) {
avatarAddress = _avatarAddress;
lootboxAddress = _lootboxAddress;
emit Transfer(address(0), owner());
lootboxPrices = new uint256[](5);
lootboxPrices[0] = 0.07 ether;
lootboxPrices[1] = 0.15 ether;
lootboxPrices[2] = 0.25 ether;
lootboxPrices[3] = 0.35 ether;
lootboxPrices[4] = 0.5 ether;
whitelistLootboxPrice = 0.05 ether;
treasuryAddress = payable(_treasuryAddress);
BLAST.configureClaimableYield();
BLAST.configureClaimableGas();
}
function name() external pure override returns (string memory) {
return 'Fortune Pike';
}
function symbol() external pure override returns (string memory) {
return 'FPGAME';
}
function supportsFactoryInterface() public pure override returns (bool) {
return true;
}
function transferOwnership(address newOwner) public override onlyOwner {
address _prevOwner = owner();
super.transferOwnership(newOwner);
emit Transfer(_prevOwner, newOwner);
}
function mintSingle() public {
Avatar(avatarAddress).mintTo(msg.sender);
}
function mint(uint256 _optionId, address _toAddress) public override {
require(isAuthorizedSender(_optionId), 'AvatarFactory: Unauthorized sender');
require(canMint(_optionId), 'AvatarFactory: Cannot mint the requested option');
uint256 newTokenId;
if (_optionId == SINGLE_ITEM_OPTION) {
Avatar(avatarAddress).mintReservedTo(_toAddress);
} else if (_optionId == LOOTBOX_OPTION) {
newTokenId = AvatarLootbox(lootboxAddress).mintReservedTo(_toAddress);
AvatarLootbox(lootboxAddress).setLootboxType(newTokenId, _optionId);
} else if (_optionId == REGULAR_SINGLE_ITEM_OPTION) {
Avatar(avatarAddress).mintTo(_toAddress);
} else if (_optionId == REGULAR_LOOTBOX_OPTION) {
newTokenId = AvatarLootbox(lootboxAddress).mintTo(_toAddress);
AvatarLootbox(lootboxAddress).setLootboxType(newTokenId, _optionId);
}
}
function mintMultiple(uint256 _optionId, address[] calldata _toAddresses) external {
require(
owner() == msg.sender ||
Avatar(avatarAddress).isServiceAccount(msg.sender) ||
AvatarLootbox(lootboxAddress).isServiceAccount(msg.sender),
'AvatarFactory: Caller is not authorized to mint multiple tokens'
);
for (uint256 i = 0; i < _toAddresses.length; i++) {
require(canMint(_optionId), 'AvatarFactory: Cannot mint the requested option');
if (_optionId == REGULAR_SINGLE_ITEM_OPTION) {
Avatar(avatarAddress).mintTo(_toAddresses[i]);
} else if (_optionId == REGULAR_LOOTBOX_OPTION) {
uint256 newTokenId = AvatarLootbox(lootboxAddress).mintTo(_toAddresses[i]);
AvatarLootbox(lootboxAddress).setLootboxType(newTokenId, _optionId);
}
}
}
function isAuthorizedSender(uint256 _optionId) private view returns (bool) {
if (_optionId == REGULAR_SINGLE_ITEM_OPTION) return true;
return
owner() == msg.sender ||
msg.sender == lootboxAddress ||
Avatar(avatarAddress).isServiceAccount(msg.sender) ||
AvatarLootbox(lootboxAddress).isServiceAccount(msg.sender);
}
function canMint(uint256 _optionId) public view override returns (bool) {
if (_optionId == REGULAR_SINGLE_ITEM_OPTION || _optionId == REGULAR_LOOTBOX_OPTION) return true;
uint256 currentSupply = 0;
if (_optionId == SINGLE_ITEM_OPTION) {
currentSupply = Avatar(avatarAddress).totalSupply();
} else if (_optionId == LOOTBOX_OPTION) {
currentSupply = AvatarLootbox(lootboxAddress).totalSupply();
}
// Проверяем, достаточно ли осталось места для minting новых элементов
require(currentSupply + 1 <= RESERVED_AVATAR_SUPPLY, 'AvatarFactory: Not enough supply left to mint');
return true;
}
function buyLootbox(uint256 numOfBoxes) external payable {
require(numOfBoxes > 0, 'Invalid number of boxes');
// Определение цены на основе белого списка
uint256 currentPrice = whitelist[msg.sender] ? whitelistLootboxPrice : getLootboxCurrentPrice();
// Проверка достаточности средств
uint256 totalPrice = numOfBoxes * currentPrice;
require(msg.value >= totalPrice, 'Insufficient funds');
// Mint'инг лутбоксов
AvatarLootbox avatarLootbox = AvatarLootbox(lootboxAddress);
for (uint256 i = 0; i < numOfBoxes; i++) {
avatarLootbox.mintReservedTo(msg.sender);
}
// Возврат излишков
uint256 excessPayment = msg.value - totalPrice;
if (excessPayment > 0) {
payable(msg.sender).transfer(excessPayment);
}
}
function setLootboxPrice(uint256 stage, uint256 price) external onlyOwner {
require(stage < 5, 'AvatarFactory: Invalid stage');
lootboxPrices[stage] = price;
}
function getLootboxCurrentPrice() public view returns (uint256) {
uint256 totalMinted = AvatarLootbox(lootboxAddress).totalSupply();
if (totalMinted >= 7000) {
return lootboxPrices[4];
} else if (totalMinted >= 4000) {
return lootboxPrices[3];
} else if (totalMinted >= 2000) {
return lootboxPrices[2];
} else if (totalMinted >= 1000) {
return lootboxPrices[1];
} else {
return lootboxPrices[0];
}
}
function addToWhitelist(address[] calldata addresses) external onlyOwner {
for (uint i = 0; i < addresses.length; i++) {
whitelist[addresses[i]] = true;
}
}
function removeFromWhitelist(address[] calldata addresses) external onlyOwner {
for (uint i = 0; i < addresses.length; i++) {
whitelist[addresses[i]] = false;
}
}
function setWhitelistPrice(uint256 newPrice) external onlyOwner {
whitelistLootboxPrice = newPrice;
}
function withdraw() external onlyOwner {
uint256 value = address(this).balance;
require(value > 0, 'AvatarFactory: No funds to withdraw');
(bool success, ) = treasuryAddress.call{ value: value }('');
require(success, 'AvatarFactory: Transfer failed');
emit Withdraw(treasuryAddress, value);
}
function updateAvatarAddress(address _newAvatarAddress) external onlyOwner {
avatarAddress = _newAvatarAddress;
}
function updateAvatarOwner(address _newOwner) external onlyOwner {
require(avatarAddress != address(0), 'AvatarFactory: Avatar address is not set');
Avatar(avatarAddress).updateOwner(_newOwner);
}
function updateLootboxAddress(address _newLootboxAddress) external onlyOwner {
lootboxAddress = _newLootboxAddress;
}
function updateLootboxOwner(address _newOwner) external onlyOwner {
require(lootboxAddress != address(0), 'AvatarFactory: Avatar lootbox address is not set');
AvatarLootbox(lootboxAddress).updateOwner(_newOwner);
}
function updateAvatarFactoryAddressInLootbox(address _newAvatarFactoryAddress) external onlyOwner {
require(_newAvatarFactoryAddress != address(0), 'AvatarFactory: New AvatarFactory address is the zero address');
require(lootboxAddress != address(0), 'AvatarFactory: AvatarLootbox address is not set');
AvatarLootbox(lootboxAddress).setAvatarFactoryAddress(_newAvatarFactoryAddress);
}
function addServiceAccount(address _address) external onlyOwner {
Avatar(avatarAddress).addServiceAccount(_address);
}
function removeServiceAccount(address _address) external onlyOwner {
Avatar(avatarAddress).removeServiceAccount(_address);
}
function claimYield(uint256 amount) external onlyOwner {
Avatar(avatarAddress).claimYield(msg.sender, amount);
AvatarLootbox(lootboxAddress).claimYield(msg.sender, amount);
BLAST.claimYield(address(this), msg.sender, amount);
}
function claimAllYield() external onlyOwner {
Avatar(avatarAddress).claimAllYield(msg.sender);
AvatarLootbox(lootboxAddress).claimAllYield(msg.sender);
BLAST.claimAllYield(address(this), msg.sender);
}
function claimAllGas() external onlyOwner {
Avatar(avatarAddress).claimAllGas(msg.sender);
AvatarLootbox(lootboxAddress).claimAllGas(msg.sender);
BLAST.claimAllGas(address(this), msg.sender);
}
function readClaimableYield() external view returns (uint256) {
return
Avatar(avatarAddress).readClaimableYield() +
AvatarLootbox(lootboxAddress).readClaimableYield() +
BLAST.readClaimableYield(address(this));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import './interfaces/IFactoryERC721.sol';
import './ERC721Tradable.sol';
import './Avatar.sol';
/**
* @title AvatarLootbox
*
* AvatarLootbox - a tradeable lootbox of Avatars.
*/
contract AvatarLootbox is ERC721Tradable {
address public avatarFactoryAddress;
string baseURI;
uint256 SINGLE_ITEM_OPTION = 0;
uint256 LOOTBOX_OPTION = 1;
uint256 REGULAR_SINGLE_ITEM_OPTION = 2;
uint256 REGULAR_LOOTBOX_OPTION = 3;
mapping(uint256 => uint256) public lootboxType;
mapping(uint256 => bool) public unpackedBoxes;
constructor(
string memory _initialBaseURI,
address _defaultRoyaltyReceiver,
uint96 _defaultFeeNumerator
) ERC721Tradable('Fortune Box', 'FBOX', _defaultRoyaltyReceiver, _defaultFeeNumerator) Ownable(msg.sender) {
baseURI = _initialBaseURI;
}
function unpack(uint256 _tokenId) public {
require(ownerOf(_tokenId) == msg.sender, 'AvatarLootbox: You must own the token to unpack it');
require(!unpackedBoxes[_tokenId], 'AvatarLootbox: Box has already been unpacked');
FactoryERC721 factory = FactoryERC721(avatarFactoryAddress);
// Проверяем тип лутбокса и вызываем mint с соответствующей опцией
uint256 optionId = lootboxType[_tokenId] == REGULAR_LOOTBOX_OPTION
? REGULAR_SINGLE_ITEM_OPTION
: SINGLE_ITEM_OPTION;
factory.mint(optionId, msg.sender);
unpackedBoxes[_tokenId] = true;
_burn(_tokenId); // Сжигаем лутбокс после распаковки
}
// Функция для установки типа лутбокса при его создании или распределении
function setLootboxType(uint256 _tokenId, uint256 _optionId) external {
require(owner() == msg.sender, 'AvatarLootbox: Not authorized to set type');
// Устанавливаем тип лутбокса
lootboxType[_tokenId] = _optionId;
unpackedBoxes[_tokenId] = false;
}
function baseTokenURI() public view override returns (string memory) {
return baseURI;
}
function setAvatarFactoryAddress(address _newAvatarFactoryAddress) external onlyOwner {
require(_newAvatarFactoryAddress != address(0), 'AvatarLootbox: new avatar factory address is the zero address');
avatarFactoryAddress = _newAvatarFactoryAddress;
}
// Функция для миграции данных о лутбоксах
function migrateLootboxes(
uint256[] calldata _tokenIds,
address[] calldata _addresses,
uint256[] calldata _optionIds,
bool[] calldata _unpacked
) external onlyOwner {
require(
_tokenIds.length == _optionIds.length && _tokenIds.length == _unpacked.length,
'AvatarLootbox: Arrays must have the same length'
);
for (uint256 i = 0; i < _tokenIds.length; i++) {
if (_optionIds[i] == REGULAR_LOOTBOX_OPTION) mintTo(_addresses[i]);
else if (_optionIds[i] == LOOTBOX_OPTION) mintReservedTo(_addresses[i]);
else revert('AvatarLootbox: Invalid optionId');
lootboxType[_tokenIds[i]] = _optionIds[i];
unpackedBoxes[_tokenIds[i]] = _unpacked[i];
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import './interfaces/IBlast.sol';
import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/utils/Strings.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol';
import '@openzeppelin/contracts/access/AccessControl.sol';
/**
* @title ERC721Tradable
* ERC721Tradable - ERC721 contract that whitelists a trading address, and has minting functionality.
*/
abstract contract ERC721Tradable is ERC721, Ownable, ERC721Enumerable, ERC721Royalty, AccessControl {
IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002);
uint256 RESERVED_TOKEN_SUPPLY = 10000;
uint96 public denominator;
uint256 private nextReservedTokenId;
uint256 private nextTokenId;
mapping(address => bool) public serviceAccounts;
event MintEvent(address _toAddress, uint256 newTokenId);
event DenominatorChanged(uint96 denominator);
constructor(
string memory _name,
string memory _symbol,
address _defaultRoyaltyReceiver,
uint96 _defaultFeeNumerator
) ERC721(_name, _symbol) {
nextReservedTokenId = 1;
nextTokenId = RESERVED_TOKEN_SUPPLY + 1;
_setDefaultRoyalty(_defaultRoyaltyReceiver, _defaultFeeNumerator);
BLAST.configureClaimableYield();
BLAST.configureClaimableGas();
}
/**
* @dev Mints a token to an address with a tokenURI.
* @param _to address of the future owner of the token
*/
function mintTo(address _to) public returns (uint256) {
require(serviceAccounts[msg.sender] || owner() == msg.sender, 'Sender not authorized to mint tokens');
uint256 currentTokenId = nextTokenId;
nextTokenId++;
_safeMint(_to, currentTokenId);
emit MintEvent(_to, currentTokenId);
return currentTokenId;
}
/**
* @dev Mints a reserved token to an address with a tokenURI.
* @param _to address of the future owner of the token
*/
function mintReservedTo(address _to) public onlyOwner returns (uint256) {
require(nextReservedTokenId <= RESERVED_TOKEN_SUPPLY, 'All reserved tokens have been minted');
uint256 currentTokenId = nextReservedTokenId;
nextReservedTokenId++;
_safeMint(_to, currentTokenId);
emit MintEvent(_to, currentTokenId);
return currentTokenId;
}
/**
* @dev Returns the total tokens minted so far.
* 1 is always subtracted from the Counter since it tracks the next available tokenId.
*/
function totalSupply() public view override returns (uint256) {
uint256 reservedCount = nextReservedTokenId - 1;
uint256 regularCount = nextTokenId - RESERVED_TOKEN_SUPPLY - 1;
return reservedCount + regularCount;
}
function baseTokenURI() public view virtual returns (string memory);
function tokenURI(uint256 _tokenId) public view override returns (string memory) {
return string(abi.encodePacked(baseTokenURI(), Strings.toString(_tokenId)));
}
function changeDenominator(uint96 _denominator) public onlyOwner returns (uint96) {
denominator = _denominator;
emit DenominatorChanged(denominator);
return denominator;
}
function setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) public onlyOwner {
_setTokenRoyalty(tokenId, receiver, feeNumerator);
}
function updateOwner(address _newOwner) public onlyOwner {
transferOwnership(_newOwner);
}
function supportsInterface(
bytes4 interfaceId
) public view override(ERC721, ERC721Enumerable, ERC721Royalty, AccessControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
/**
* @dev Adds a single address to the whitelist.
* @param _address Address to be added to the whitelist
*/
function addServiceAccount(address _address) public onlyOwner {
serviceAccounts[_address] = true;
}
/**
* @dev Removes a single address from the whitelist.
* @param _address Address to be removed from the whitelist
*/
function removeServiceAccount(address _address) public onlyOwner {
serviceAccounts[_address] = false;
}
/**
* @dev Returns true if the address is on the whitelist.
* @param _address Address to be checked
*/
function isServiceAccount(address _address) public view returns (bool) {
return serviceAccounts[_address];
}
function _update(
address to,
uint256 tokenId,
address auth
) internal override(ERC721, ERC721Enumerable) returns (address) {
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 value) internal override(ERC721, ERC721Enumerable) {
super._increaseBalance(account, value);
}
function claimYield(address recipient, uint256 amount) external onlyOwner {
BLAST.claimYield(address(this), recipient, amount);
}
function claimAllYield(address recipient) external onlyOwner {
BLAST.claimAllYield(address(this), recipient);
}
function claimAllGas(address recipient) external onlyOwner {
BLAST.claimAllGas(address(this), recipient);
}
function readClaimableYield() public view returns (uint256) {
return BLAST.readClaimableYield(address(this));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
enum YieldMode {
AUTOMATIC,
VOID,
CLAIMABLE
}
enum GasMode {
VOID,
CLAIMABLE
}
interface IBlast {
// configure
function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external;
function configure(YieldMode _yield, GasMode gasMode, address governor) external;
// base configuration options
function configureClaimableYield() external;
function configureClaimableYieldOnBehalf(address contractAddress) external;
function configureAutomaticYield() external;
function configureAutomaticYieldOnBehalf(address contractAddress) external;
function configureVoidYield() external;
function configureVoidYieldOnBehalf(address contractAddress) external;
function configureClaimableGas() external;
function configureClaimableGasOnBehalf(address contractAddress) external;
function configureVoidGas() external;
function configureVoidGasOnBehalf(address contractAddress) external;
function configureGovernor(address _governor) external;
function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external;
// claim yield
function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256);
function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256);
// claim gas
function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGasAtMinClaimRate(
address contractAddress,
address recipientOfGas,
uint256 minClaimRateBips
) external returns (uint256);
function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGas(
address contractAddress,
address recipientOfGas,
uint256 gasToClaim,
uint256 gasSecondsToConsume
) external returns (uint256);
// read functions
function readClaimableYield(address contractAddress) external view returns (uint256);
function readYieldConfiguration(address contractAddress) external view returns (uint8);
function readGasParams(
address contractAddress
) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/**
* This is a generic factory contract that can be used to mint tokens. The configuration
* for minting is specified by an _optionId, which can be used to delineate various
* ways of minting.
*/
interface FactoryERC721 {
/**
* Returns the name of this factory.
*/
function name() external view returns (string memory);
/**
* Returns the symbol for this factory.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns whether the option ID can be minted. Can return false if the developer wishes to
* restrict a total supply per option ID (or overall).
*/
function canMint(uint256 _optionId) external view returns (bool);
/**
* Indicates that this is a factory contract. Ideally would use EIP 165 supportsInterface()
*/
function supportsFactoryInterface() external view returns (bool);
/**
* @dev Mints asset(s) in accordance to a specific address with a particular "option". This should be
* callable only by the contract owner or the owner's Wyvern Proxy (later universal login will solve this).
* Options should also be delineated 0 - (numOptions() - 1) for convenient indexing.
* @param _optionId the option id
* @param _toAddress address of the future owner of the asset(s)
*/
function mint(uint256 _optionId, address _toAddress) external;
}{
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 800
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_initialBaseURI","type":"string"},{"internalType":"address","name":"_defaultRoyaltyReceiver","type":"address"},{"internalType":"uint96","name":"_defaultFeeNumerator","type":"uint96"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","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":false,"internalType":"uint96","name":"denominator","type":"uint96"}],"name":"DenominatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTokenId","type":"uint256"}],"name":"MintEvent","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":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","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":[],"name":"BLAST","outputs":[{"internalType":"contract IBlast","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"addServiceAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"_denominator","type":"uint96"}],"name":"changeDenominator","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"claimAllGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"claimAllYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"denominator","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isServiceAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"mintReservedTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"mintTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readClaimableYield","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"removeServiceAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"serviceAccounts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_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"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"updateOwner","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052612710600e553480156200001757600080fd5b50604051620027d1380380620027d18339810160408190526200003a9162000338565b6040518060400160405280600981526020016823281020bb30ba30b960b91b81525060405180604001604052806006815260200165232824a5a2a960d11b81525083833384848160029081620000919190620004c3565b506003620000a08282620004c3565b5050506001600160a01b038116620000d357604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620000de81620001f4565b5060016010819055600e54620000f4916200058f565b60115562000103828262000246565b7343000000000000000000000000000000000000026001600160a01b031663f098767a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200015357600080fd5b505af115801562000168573d6000803e3d6000fd5b505050507343000000000000000000000000000000000000026001600160a01b0316634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b158015620001bc57600080fd5b505af1158015620001d1573d6000803e3d6000fd5b50505050505050508260139081620001ea9190620004c3565b50505050620005b7565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6127106001600160601b0382168110156200028757604051636f483d0960e01b81526001600160601b038316600482015260248101829052604401620000ca565b6001600160a01b038316620002b357604051635b6cc80560e11b815260006004820152602401620000ca565b50604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600055565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200031b57600080fd5b919050565b80516001600160601b03811681146200031b57600080fd5b6000806000606084860312156200034e57600080fd5b83516001600160401b03808211156200036657600080fd5b818601915086601f8301126200037b57600080fd5b815181811115620003905762000390620002ed565b604051601f8201601f19908116603f01168101908382118183101715620003bb57620003bb620002ed565b81604052828152602093508984848701011115620003d857600080fd5b600091505b82821015620003fc5784820184015181830185015290830190620003dd565b60008484830101528097505050506200041781870162000303565b93505050620004296040850162000320565b90509250925092565b600181811c908216806200044757607f821691505b6020821081036200046857634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620004be576000816000526020600020601f850160051c81016020861015620004995750805b601f850160051c820191505b81811015620004ba57828155600101620004a5565b5050505b505050565b81516001600160401b03811115620004df57620004df620002ed565b620004f781620004f0845462000432565b846200046e565b602080601f8311600181146200052f5760008415620005165750858301515b600019600386901b1c1916600185901b178555620004ba565b600085815260208120601f198616915b8281101562000560578886015182559484019460019091019084016200053f565b50858210156200057f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115620005b157634e487b7160e01b600052601160045260246000fd5b92915050565b61220a80620005c76000396000f3fe608060405234801561001057600080fd5b50600436106102de5760003560e01c8063880cdc3111610186578063ab51e23a116100e3578063d547741f11610097578063e985e9c511610071578063e985e9c514610654578063f2fde38b14610690578063ff1fd8ba146106a357600080fd5b8063d547741f14610626578063d547cfb714610639578063e22dc81d1461064157600080fd5b8063c2d94aec116100c8578063c2d94aec146105f8578063c87b56dd1461060b578063d39dd6841461061e57600080fd5b8063ab51e23a146105d2578063b88d4fde146105e557600080fd5b806397d757761161013a578063a22cb4651161011f578063a22cb46514610580578063a7d48f5114610593578063aaad98ab146105a657600080fd5b806397d757761461056a578063a217fddf1461057857600080fd5b806391d148541161016b57806391d14854146104fe57806395d89b411461053757806396ce07951461053f57600080fd5b8063880cdc31146104da5780638da5cb5b146104ed57600080fd5b80632f2ff15d1161023f5780635944c753116101f3578063715018a6116101cd578063715018a61461049c578063755edd17146104a45780637cb662bc146104b757600080fd5b80635944c753146104635780636352211e1461047657806370a082311461048957600080fd5b806336568abe1161022457806336568abe1461042a57806342842e0e1461043d5780634f6ccce71461045057600080fd5b80632f2ff15d146104045780632f745c591461041757600080fd5b80631869ebda11610296578063248a9ca31161027b578063248a9ca31461039c578063272b1323146103bf5780632a55205a146103d257600080fd5b80631869ebda1461037657806323b872dd1461038957600080fd5b8063081812fc116102c7578063081812fc14610320578063095ea7b31461034b57806318160ddd1461036057600080fd5b806301ffc9a7146102e357806306fdde031461030b575b600080fd5b6102f66102f1366004611d1c565b6106b6565b60405190151581526020015b60405180910390f35b6103136106c7565b6040516103029190611d90565b61033361032e366004611da3565b610759565b6040516001600160a01b039091168152602001610302565b61035e610359366004611dd3565b610782565b005b610368610791565b604051908152602001610302565b61035e610384366004611dd3565b6107d6565b61035e610397366004611dfd565b610861565b6103686103aa366004611da3565b6000908152600d602052604090206001015490565b61035e6103cd366004611e39565b6108f1565b6103e56103e0366004611e54565b610971565b604080516001600160a01b039093168352602083019190915201610302565b61035e610412366004611e76565b610a1d565b610368610425366004611dd3565b610a42565b61035e610438366004611e76565b610aa7565b61035e61044b366004611dfd565b610ada565b61036861045e366004611da3565b610af5565b61035e610471366004611eb9565b610b4d565b610333610484366004611da3565b610b60565b610368610497366004611e39565b610b6b565b61035e610bb3565b6103686104b2366004611e39565b610bc7565b6102f66104c5366004611e39565b60126020526000908152604090205460ff1681565b61035e6104e8366004611e39565b610cbf565b6008546001600160a01b0316610333565b6102f661050c366004611e76565b6000918252600d602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610313610cd3565b600f54610552906001600160601b031681565b6040516001600160601b039091168152602001610302565b6103336002604360981b0181565b610368600081565b61035e61058e366004611ef5565b610ce2565b6103686105a1366004611e39565b610ced565b6102f66105b4366004611e39565b6001600160a01b031660009081526012602052604090205460ff1690565b6105526105e0366004611f31565b610d6e565b61035e6105f3366004611f62565b610ddf565b61035e610606366004611e39565b610df6565b610313610619366004611da3565b610e37565b610368610e71565b61035e610634366004611e76565b610edf565b610313610f04565b61035e61064f366004611e39565b610f13565b6102f661066236600461203e565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b61035e61069e366004611e39565b610f3c565b61035e6106b1366004611e39565b610f77565b60006106c182610fa3565b92915050565b6060600280546106d690612068565b80601f016020809104026020016040519081016040528092919081815260200182805461070290612068565b801561074f5780601f106107245761010080835404028352916020019161074f565b820191906000526020600020905b81548152906001019060200180831161073257829003601f168201915b5050505050905090565b600061076482610fc8565b506000828152600660205260409020546001600160a01b03166106c1565b61078d828233611001565b5050565b60008060016010546107a391906120b8565b905060006001600e546011546107b991906120b8565b6107c391906120b8565b90506107cf81836120cb565b9250505090565b6107de61100e565b604051637cb8cb3160e11b81523060048201526001600160a01b0383166024820152604481018290526002604360981b019063f9719662906064016020604051808303816000875af1158015610838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085c91906120de565b505050565b6001600160a01b03821661089057604051633250574960e11b8152600060048201526024015b60405180910390fd5b600061089d83833361103b565b9050836001600160a01b0316816001600160a01b0316146108eb576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610887565b50505050565b6108f961100e565b604051634aa7d2f760e11b81523060048201526001600160a01b03821660248201526002604360981b019063954fa5ee906044015b6020604051808303816000875af115801561094d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078d91906120de565b60008281526001602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916109e65750604080518082019091526000546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090610a05906001600160601b0316876120f7565b610a0f919061210e565b915196919550909350505050565b6000828152600d6020526040902060010154610a3881611050565b6108eb838361105a565b6000610a4d83610b6b565b8210610a7e5760405163295f44f760e21b81526001600160a01b038416600482015260248101839052604401610887565b506001600160a01b03919091166000908152600960209081526040808320938352929052205490565b6001600160a01b0381163314610ad05760405163334bd91960e11b815260040160405180910390fd5b61085c8282611108565b61085c83838360405180602001604052806000815250610ddf565b6000610aff610791565b8210610b285760405163295f44f760e21b81526000600482015260248101839052604401610887565b600b8281548110610b3b57610b3b612130565b90600052602060002001549050919050565b610b5561100e565b61085c83838361118f565b60006106c182610fc8565b60006001600160a01b038216610b97576040516322718ad960e21b815260006004820152602401610887565b506001600160a01b031660009081526005602052604090205490565b610bbb61100e565b610bc56000611251565b565b3360009081526012602052604081205460ff1680610bfe575033610bf36008546001600160a01b031690565b6001600160a01b0316145b610c565760405162461bcd60e51b8152602060048201526024808201527f53656e646572206e6f7420617574686f72697a656420746f206d696e7420746f6044820152636b656e7360e01b6064820152608401610887565b601180549081906000610c6883612146565b9190505550610c7783826112b0565b604080516001600160a01b0385168152602081018390527f3fffaa5804a26fcec0d70b1d0fb0a2d0031df3a5f9c8af2127c2f4360e97b463910160405180910390a192915050565b610cc761100e565b610cd081610f3c565b50565b6060600380546106d690612068565b61078d3383836112ca565b6000610cf761100e565b600e546010541115610d575760405162461bcd60e51b8152602060048201526024808201527f416c6c20726573657276656420746f6b656e732068617665206265656e206d696044820152631b9d195960e21b6064820152608401610887565b601080549081906000610c6883612146565b919050565b6000610d7861100e565b600f80546bffffffffffffffffffffffff19166001600160601b0384169081179091556040519081527f601b85aa9305dbcfbfc81aa2d4b5126c1ce24afdd1bad47d6880e5b6df081f579060200160405180910390a15050600f546001600160601b031690565b610dea848484610861565b6108eb84848484611369565b610dfe61100e565b60405163430021db60e11b81523060048201526001600160a01b03821660248201526002604360981b019063860043b69060440161092e565b6060610e41610f04565b610e4a83611492565b604051602001610e5b92919061215f565b6040516020818303038152906040529050919050565b604051631d864f1d60e31b81523060048201526000906002604360981b019063ec3278e890602401602060405180830381865afa158015610eb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eda91906120de565b905090565b6000828152600d6020526040902060010154610efa81611050565b6108eb8383611108565b6060601380546106d690612068565b610f1b61100e565b6001600160a01b03166000908152601260205260409020805460ff19169055565b610f4461100e565b6001600160a01b038116610f6e57604051631e4fbdf760e01b815260006004820152602401610887565b610cd081611251565b610f7f61100e565b6001600160a01b03166000908152601260205260409020805460ff19166001179055565b60006001600160e01b03198216637965db0b60e01b14806106c157506106c182611532565b6000818152600460205260408120546001600160a01b0316806106c157604051637e27328960e01b815260048101849052602401610887565b61085c838383600161153d565b6008546001600160a01b03163314610bc55760405163118cdaa760e01b8152336004820152602401610887565b600061104884848461166f565b949350505050565b610cd0813361173c565b6000828152600d602090815260408083206001600160a01b038516845290915281205460ff16611100576000838152600d602090815260408083206001600160a01b03861684529091529020805460ff191660011790556110b83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016106c1565b5060006106c1565b6000828152600d602090815260408083206001600160a01b038516845290915281205460ff1615611100576000838152600d602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016106c1565b6127106001600160601b0382168110156111d55760405163dfd1fc1b60e01b8152600481018590526001600160601b038316602482015260448101829052606401610887565b6001600160a01b03831661120657604051634b4f842960e11b81526004810185905260006024820152604401610887565b506040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182526000968752600190529190942093519051909116600160a01b029116179055565b600880546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61078d828260405180602001604052806000815250611791565b6001600160a01b0382166112fc57604051630b61174360e31b81526001600160a01b0383166004820152602401610887565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b156108eb57604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906113ab90339088908790879060040161218e565b6020604051808303816000875af19250505080156113e6575060408051601f3d908101601f191682019092526113e3918101906121ca565b60015b61144f573d808015611414576040519150601f19603f3d011682016040523d82523d6000602084013e611419565b606091505b50805160000361144757604051633250574960e11b81526001600160a01b0385166004820152602401610887565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b1461148b57604051633250574960e11b81526001600160a01b0385166004820152602401610887565b5050505050565b6060600061149f836117a8565b600101905060008167ffffffffffffffff8111156114bf576114bf611f4c565b6040519080825280601f01601f1916602001820160405280156114e9576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450846114f357509392505050565b60006106c18261188a565b808061155157506001600160a01b03821615155b1561163257600061156184610fc8565b90506001600160a01b0383161580159061158d5750826001600160a01b0316816001600160a01b031614155b80156115bf57506001600160a01b0380821660009081526007602090815260408083209387168352929052205460ff16155b156115e85760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610887565b81156116305783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50506000908152600660205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60008061167d8585856118af565b90506001600160a01b0381166116da576116d584600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6116fd565b846001600160a01b0316816001600160a01b0316146116fd576116fd81856119b5565b6001600160a01b0385166117195761171484611a46565b611048565b846001600160a01b0316816001600160a01b031614611048576110488585611af5565b6000828152600d602090815260408083206001600160a01b038516845290915290205460ff1661078d5760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610887565b61179b8383611b45565b61085c6000848484611369565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106117f1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831061181d576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061183b57662386f26fc10000830492506010015b6305f5e1008310611853576305f5e100830492506008015b612710831061186757612710830492506004015b60648310611879576064830492506002015b600a83106106c15760010192915050565b60006001600160e01b0319821663780e9d6360e01b14806106c157506106c182611baa565b6000828152600460205260408120546001600160a01b03908116908316156118dc576118dc818486611bea565b6001600160a01b0381161561191a576118f960008560008061153d565b6001600160a01b038116600090815260056020526040902080546000190190555b6001600160a01b03851615611949576001600160a01b0385166000908152600560205260409020805460010190555b600084815260046020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b60006119c083610b6b565b6000838152600a6020526040902054909150808214611a13576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b54600090611a58906001906120b8565b6000838152600c6020526040812054600b8054939450909284908110611a8057611a80612130565b9060005260206000200154905080600b8381548110611aa157611aa1612130565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480611ad957611ad96121e7565b6001900381819060005260206000200160009055905550505050565b60006001611b0284610b6b565b611b0c91906120b8565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b6001600160a01b038216611b6f57604051633250574960e11b815260006004820152602401610887565b6000611b7d8383600061103b565b90506001600160a01b0381161561085c576040516339e3563760e11b815260006004820152602401610887565b60006001600160e01b031982166380ac58cd60e01b1480611bdb57506001600160e01b03198216635b5e139f60e01b145b806106c157506106c182611c4e565b611bf5838383611c83565b61085c576001600160a01b038316611c2357604051637e27328960e01b815260048101829052602401610887565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610887565b60006001600160e01b0319821663152a902d60e11b14806106c157506301ffc9a760e01b6001600160e01b03198316146106c1565b60006001600160a01b038316158015906110485750826001600160a01b0316846001600160a01b03161480611cdd57506001600160a01b0380851660009081526007602090815260408083209387168352929052205460ff165b806110485750506000908152600660205260409020546001600160a01b03908116911614919050565b6001600160e01b031981168114610cd057600080fd5b600060208284031215611d2e57600080fd5b8135611d3981611d06565b9392505050565b60005b83811015611d5b578181015183820152602001611d43565b50506000910152565b60008151808452611d7c816020860160208601611d40565b601f01601f19169290920160200192915050565b602081526000611d396020830184611d64565b600060208284031215611db557600080fd5b5035919050565b80356001600160a01b0381168114610d6957600080fd5b60008060408385031215611de657600080fd5b611def83611dbc565b946020939093013593505050565b600080600060608486031215611e1257600080fd5b611e1b84611dbc565b9250611e2960208501611dbc565b9150604084013590509250925092565b600060208284031215611e4b57600080fd5b611d3982611dbc565b60008060408385031215611e6757600080fd5b50508035926020909101359150565b60008060408385031215611e8957600080fd5b82359150611e9960208401611dbc565b90509250929050565b80356001600160601b0381168114610d6957600080fd5b600080600060608486031215611ece57600080fd5b83359250611ede60208501611dbc565b9150611eec60408501611ea2565b90509250925092565b60008060408385031215611f0857600080fd5b611f1183611dbc565b915060208301358015158114611f2657600080fd5b809150509250929050565b600060208284031215611f4357600080fd5b611d3982611ea2565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611f7857600080fd5b611f8185611dbc565b9350611f8f60208601611dbc565b925060408501359150606085013567ffffffffffffffff80821115611fb357600080fd5b818701915087601f830112611fc757600080fd5b813581811115611fd957611fd9611f4c565b604051601f8201601f19908116603f0116810190838211818310171561200157612001611f4c565b816040528281528a602084870101111561201a57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561205157600080fd5b61205a83611dbc565b9150611e9960208401611dbc565b600181811c9082168061207c57607f821691505b60208210810361209c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156106c1576106c16120a2565b808201808211156106c1576106c16120a2565b6000602082840312156120f057600080fd5b5051919050565b80820281158282048414176106c1576106c16120a2565b60008261212b57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060018201612158576121586120a2565b5060010190565b60008351612171818460208801611d40565b835190830190612185818360208801611d40565b01949350505050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526121c06080830184611d64565b9695505050505050565b6000602082840312156121dc57600080fd5b8151611d3981611d06565b634e487b7160e01b600052603160045260246000fdfea164736f6c6343000818000a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000005953229b9b3dbc58970e5496331c6b5af805c9cb00000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000002c68747470733a2f2f67616d652e666f7274756e6570696b652e78797a2f6170692f6e66742f6176617461722f0000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102de5760003560e01c8063880cdc3111610186578063ab51e23a116100e3578063d547741f11610097578063e985e9c511610071578063e985e9c514610654578063f2fde38b14610690578063ff1fd8ba146106a357600080fd5b8063d547741f14610626578063d547cfb714610639578063e22dc81d1461064157600080fd5b8063c2d94aec116100c8578063c2d94aec146105f8578063c87b56dd1461060b578063d39dd6841461061e57600080fd5b8063ab51e23a146105d2578063b88d4fde146105e557600080fd5b806397d757761161013a578063a22cb4651161011f578063a22cb46514610580578063a7d48f5114610593578063aaad98ab146105a657600080fd5b806397d757761461056a578063a217fddf1461057857600080fd5b806391d148541161016b57806391d14854146104fe57806395d89b411461053757806396ce07951461053f57600080fd5b8063880cdc31146104da5780638da5cb5b146104ed57600080fd5b80632f2ff15d1161023f5780635944c753116101f3578063715018a6116101cd578063715018a61461049c578063755edd17146104a45780637cb662bc146104b757600080fd5b80635944c753146104635780636352211e1461047657806370a082311461048957600080fd5b806336568abe1161022457806336568abe1461042a57806342842e0e1461043d5780634f6ccce71461045057600080fd5b80632f2ff15d146104045780632f745c591461041757600080fd5b80631869ebda11610296578063248a9ca31161027b578063248a9ca31461039c578063272b1323146103bf5780632a55205a146103d257600080fd5b80631869ebda1461037657806323b872dd1461038957600080fd5b8063081812fc116102c7578063081812fc14610320578063095ea7b31461034b57806318160ddd1461036057600080fd5b806301ffc9a7146102e357806306fdde031461030b575b600080fd5b6102f66102f1366004611d1c565b6106b6565b60405190151581526020015b60405180910390f35b6103136106c7565b6040516103029190611d90565b61033361032e366004611da3565b610759565b6040516001600160a01b039091168152602001610302565b61035e610359366004611dd3565b610782565b005b610368610791565b604051908152602001610302565b61035e610384366004611dd3565b6107d6565b61035e610397366004611dfd565b610861565b6103686103aa366004611da3565b6000908152600d602052604090206001015490565b61035e6103cd366004611e39565b6108f1565b6103e56103e0366004611e54565b610971565b604080516001600160a01b039093168352602083019190915201610302565b61035e610412366004611e76565b610a1d565b610368610425366004611dd3565b610a42565b61035e610438366004611e76565b610aa7565b61035e61044b366004611dfd565b610ada565b61036861045e366004611da3565b610af5565b61035e610471366004611eb9565b610b4d565b610333610484366004611da3565b610b60565b610368610497366004611e39565b610b6b565b61035e610bb3565b6103686104b2366004611e39565b610bc7565b6102f66104c5366004611e39565b60126020526000908152604090205460ff1681565b61035e6104e8366004611e39565b610cbf565b6008546001600160a01b0316610333565b6102f661050c366004611e76565b6000918252600d602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610313610cd3565b600f54610552906001600160601b031681565b6040516001600160601b039091168152602001610302565b6103336002604360981b0181565b610368600081565b61035e61058e366004611ef5565b610ce2565b6103686105a1366004611e39565b610ced565b6102f66105b4366004611e39565b6001600160a01b031660009081526012602052604090205460ff1690565b6105526105e0366004611f31565b610d6e565b61035e6105f3366004611f62565b610ddf565b61035e610606366004611e39565b610df6565b610313610619366004611da3565b610e37565b610368610e71565b61035e610634366004611e76565b610edf565b610313610f04565b61035e61064f366004611e39565b610f13565b6102f661066236600461203e565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b61035e61069e366004611e39565b610f3c565b61035e6106b1366004611e39565b610f77565b60006106c182610fa3565b92915050565b6060600280546106d690612068565b80601f016020809104026020016040519081016040528092919081815260200182805461070290612068565b801561074f5780601f106107245761010080835404028352916020019161074f565b820191906000526020600020905b81548152906001019060200180831161073257829003601f168201915b5050505050905090565b600061076482610fc8565b506000828152600660205260409020546001600160a01b03166106c1565b61078d828233611001565b5050565b60008060016010546107a391906120b8565b905060006001600e546011546107b991906120b8565b6107c391906120b8565b90506107cf81836120cb565b9250505090565b6107de61100e565b604051637cb8cb3160e11b81523060048201526001600160a01b0383166024820152604481018290526002604360981b019063f9719662906064016020604051808303816000875af1158015610838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085c91906120de565b505050565b6001600160a01b03821661089057604051633250574960e11b8152600060048201526024015b60405180910390fd5b600061089d83833361103b565b9050836001600160a01b0316816001600160a01b0316146108eb576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610887565b50505050565b6108f961100e565b604051634aa7d2f760e11b81523060048201526001600160a01b03821660248201526002604360981b019063954fa5ee906044015b6020604051808303816000875af115801561094d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078d91906120de565b60008281526001602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916109e65750604080518082019091526000546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090610a05906001600160601b0316876120f7565b610a0f919061210e565b915196919550909350505050565b6000828152600d6020526040902060010154610a3881611050565b6108eb838361105a565b6000610a4d83610b6b565b8210610a7e5760405163295f44f760e21b81526001600160a01b038416600482015260248101839052604401610887565b506001600160a01b03919091166000908152600960209081526040808320938352929052205490565b6001600160a01b0381163314610ad05760405163334bd91960e11b815260040160405180910390fd5b61085c8282611108565b61085c83838360405180602001604052806000815250610ddf565b6000610aff610791565b8210610b285760405163295f44f760e21b81526000600482015260248101839052604401610887565b600b8281548110610b3b57610b3b612130565b90600052602060002001549050919050565b610b5561100e565b61085c83838361118f565b60006106c182610fc8565b60006001600160a01b038216610b97576040516322718ad960e21b815260006004820152602401610887565b506001600160a01b031660009081526005602052604090205490565b610bbb61100e565b610bc56000611251565b565b3360009081526012602052604081205460ff1680610bfe575033610bf36008546001600160a01b031690565b6001600160a01b0316145b610c565760405162461bcd60e51b8152602060048201526024808201527f53656e646572206e6f7420617574686f72697a656420746f206d696e7420746f6044820152636b656e7360e01b6064820152608401610887565b601180549081906000610c6883612146565b9190505550610c7783826112b0565b604080516001600160a01b0385168152602081018390527f3fffaa5804a26fcec0d70b1d0fb0a2d0031df3a5f9c8af2127c2f4360e97b463910160405180910390a192915050565b610cc761100e565b610cd081610f3c565b50565b6060600380546106d690612068565b61078d3383836112ca565b6000610cf761100e565b600e546010541115610d575760405162461bcd60e51b8152602060048201526024808201527f416c6c20726573657276656420746f6b656e732068617665206265656e206d696044820152631b9d195960e21b6064820152608401610887565b601080549081906000610c6883612146565b919050565b6000610d7861100e565b600f80546bffffffffffffffffffffffff19166001600160601b0384169081179091556040519081527f601b85aa9305dbcfbfc81aa2d4b5126c1ce24afdd1bad47d6880e5b6df081f579060200160405180910390a15050600f546001600160601b031690565b610dea848484610861565b6108eb84848484611369565b610dfe61100e565b60405163430021db60e11b81523060048201526001600160a01b03821660248201526002604360981b019063860043b69060440161092e565b6060610e41610f04565b610e4a83611492565b604051602001610e5b92919061215f565b6040516020818303038152906040529050919050565b604051631d864f1d60e31b81523060048201526000906002604360981b019063ec3278e890602401602060405180830381865afa158015610eb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eda91906120de565b905090565b6000828152600d6020526040902060010154610efa81611050565b6108eb8383611108565b6060601380546106d690612068565b610f1b61100e565b6001600160a01b03166000908152601260205260409020805460ff19169055565b610f4461100e565b6001600160a01b038116610f6e57604051631e4fbdf760e01b815260006004820152602401610887565b610cd081611251565b610f7f61100e565b6001600160a01b03166000908152601260205260409020805460ff19166001179055565b60006001600160e01b03198216637965db0b60e01b14806106c157506106c182611532565b6000818152600460205260408120546001600160a01b0316806106c157604051637e27328960e01b815260048101849052602401610887565b61085c838383600161153d565b6008546001600160a01b03163314610bc55760405163118cdaa760e01b8152336004820152602401610887565b600061104884848461166f565b949350505050565b610cd0813361173c565b6000828152600d602090815260408083206001600160a01b038516845290915281205460ff16611100576000838152600d602090815260408083206001600160a01b03861684529091529020805460ff191660011790556110b83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016106c1565b5060006106c1565b6000828152600d602090815260408083206001600160a01b038516845290915281205460ff1615611100576000838152600d602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016106c1565b6127106001600160601b0382168110156111d55760405163dfd1fc1b60e01b8152600481018590526001600160601b038316602482015260448101829052606401610887565b6001600160a01b03831661120657604051634b4f842960e11b81526004810185905260006024820152604401610887565b506040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182526000968752600190529190942093519051909116600160a01b029116179055565b600880546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61078d828260405180602001604052806000815250611791565b6001600160a01b0382166112fc57604051630b61174360e31b81526001600160a01b0383166004820152602401610887565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b156108eb57604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906113ab90339088908790879060040161218e565b6020604051808303816000875af19250505080156113e6575060408051601f3d908101601f191682019092526113e3918101906121ca565b60015b61144f573d808015611414576040519150601f19603f3d011682016040523d82523d6000602084013e611419565b606091505b50805160000361144757604051633250574960e11b81526001600160a01b0385166004820152602401610887565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b1461148b57604051633250574960e11b81526001600160a01b0385166004820152602401610887565b5050505050565b6060600061149f836117a8565b600101905060008167ffffffffffffffff8111156114bf576114bf611f4c565b6040519080825280601f01601f1916602001820160405280156114e9576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450846114f357509392505050565b60006106c18261188a565b808061155157506001600160a01b03821615155b1561163257600061156184610fc8565b90506001600160a01b0383161580159061158d5750826001600160a01b0316816001600160a01b031614155b80156115bf57506001600160a01b0380821660009081526007602090815260408083209387168352929052205460ff16155b156115e85760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610887565b81156116305783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50506000908152600660205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60008061167d8585856118af565b90506001600160a01b0381166116da576116d584600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6116fd565b846001600160a01b0316816001600160a01b0316146116fd576116fd81856119b5565b6001600160a01b0385166117195761171484611a46565b611048565b846001600160a01b0316816001600160a01b031614611048576110488585611af5565b6000828152600d602090815260408083206001600160a01b038516845290915290205460ff1661078d5760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610887565b61179b8383611b45565b61085c6000848484611369565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106117f1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831061181d576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061183b57662386f26fc10000830492506010015b6305f5e1008310611853576305f5e100830492506008015b612710831061186757612710830492506004015b60648310611879576064830492506002015b600a83106106c15760010192915050565b60006001600160e01b0319821663780e9d6360e01b14806106c157506106c182611baa565b6000828152600460205260408120546001600160a01b03908116908316156118dc576118dc818486611bea565b6001600160a01b0381161561191a576118f960008560008061153d565b6001600160a01b038116600090815260056020526040902080546000190190555b6001600160a01b03851615611949576001600160a01b0385166000908152600560205260409020805460010190555b600084815260046020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b60006119c083610b6b565b6000838152600a6020526040902054909150808214611a13576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b54600090611a58906001906120b8565b6000838152600c6020526040812054600b8054939450909284908110611a8057611a80612130565b9060005260206000200154905080600b8381548110611aa157611aa1612130565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480611ad957611ad96121e7565b6001900381819060005260206000200160009055905550505050565b60006001611b0284610b6b565b611b0c91906120b8565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b6001600160a01b038216611b6f57604051633250574960e11b815260006004820152602401610887565b6000611b7d8383600061103b565b90506001600160a01b0381161561085c576040516339e3563760e11b815260006004820152602401610887565b60006001600160e01b031982166380ac58cd60e01b1480611bdb57506001600160e01b03198216635b5e139f60e01b145b806106c157506106c182611c4e565b611bf5838383611c83565b61085c576001600160a01b038316611c2357604051637e27328960e01b815260048101829052602401610887565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610887565b60006001600160e01b0319821663152a902d60e11b14806106c157506301ffc9a760e01b6001600160e01b03198316146106c1565b60006001600160a01b038316158015906110485750826001600160a01b0316846001600160a01b03161480611cdd57506001600160a01b0380851660009081526007602090815260408083209387168352929052205460ff165b806110485750506000908152600660205260409020546001600160a01b03908116911614919050565b6001600160e01b031981168114610cd057600080fd5b600060208284031215611d2e57600080fd5b8135611d3981611d06565b9392505050565b60005b83811015611d5b578181015183820152602001611d43565b50506000910152565b60008151808452611d7c816020860160208601611d40565b601f01601f19169290920160200192915050565b602081526000611d396020830184611d64565b600060208284031215611db557600080fd5b5035919050565b80356001600160a01b0381168114610d6957600080fd5b60008060408385031215611de657600080fd5b611def83611dbc565b946020939093013593505050565b600080600060608486031215611e1257600080fd5b611e1b84611dbc565b9250611e2960208501611dbc565b9150604084013590509250925092565b600060208284031215611e4b57600080fd5b611d3982611dbc565b60008060408385031215611e6757600080fd5b50508035926020909101359150565b60008060408385031215611e8957600080fd5b82359150611e9960208401611dbc565b90509250929050565b80356001600160601b0381168114610d6957600080fd5b600080600060608486031215611ece57600080fd5b83359250611ede60208501611dbc565b9150611eec60408501611ea2565b90509250925092565b60008060408385031215611f0857600080fd5b611f1183611dbc565b915060208301358015158114611f2657600080fd5b809150509250929050565b600060208284031215611f4357600080fd5b611d3982611ea2565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611f7857600080fd5b611f8185611dbc565b9350611f8f60208601611dbc565b925060408501359150606085013567ffffffffffffffff80821115611fb357600080fd5b818701915087601f830112611fc757600080fd5b813581811115611fd957611fd9611f4c565b604051601f8201601f19908116603f0116810190838211818310171561200157612001611f4c565b816040528281528a602084870101111561201a57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561205157600080fd5b61205a83611dbc565b9150611e9960208401611dbc565b600181811c9082168061207c57607f821691505b60208210810361209c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156106c1576106c16120a2565b808201808211156106c1576106c16120a2565b6000602082840312156120f057600080fd5b5051919050565b80820281158282048414176106c1576106c16120a2565b60008261212b57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060018201612158576121586120a2565b5060010190565b60008351612171818460208801611d40565b835190830190612185818360208801611d40565b01949350505050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526121c06080830184611d64565b9695505050505050565b6000602082840312156121dc57600080fd5b8151611d3981611d06565b634e487b7160e01b600052603160045260246000fdfea164736f6c6343000818000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000600000000000000000000000005953229b9b3dbc58970e5496331c6b5af805c9cb00000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000002c68747470733a2f2f67616d652e666f7274756e6570696b652e78797a2f6170692f6e66742f6176617461722f0000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _initialBaseURI (string): https://game.fortunepike.xyz/api/nft/avatar/
Arg [1] : _defaultRoyaltyReceiver (address): 0x5953229B9b3Dbc58970E5496331c6b5aF805c9cb
Arg [2] : _defaultFeeNumerator (uint96): 1000
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 0000000000000000000000005953229b9b3dbc58970e5496331c6b5af805c9cb
Arg [2] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [3] : 000000000000000000000000000000000000000000000000000000000000002c
Arg [4] : 68747470733a2f2f67616d652e666f7274756e6570696b652e78797a2f617069
Arg [5] : 2f6e66742f6176617461722f0000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
168:419:24:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3522:201:27;;;;;;:::i;:::-;;:::i;:::-;;;565:14:30;;558:22;540:41;;528:2;513:18;3522:201:27;;;;;;;;2365:89:6;;;:::i;:::-;;;;;;;:::i;3497:154::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1697:55:30;;;1679:74;;1667:2;1652:18;3497:154:6;1533:226:30;3323:113:6;;;;;;:::i;:::-;;:::i;:::-;;2595:229:27;;;:::i;:::-;;;2370:25:30;;;2358:2;2343:18;2595:229:27;2224:177:30;4777:135:27;;;;;;:::i;:::-;;:::i;4143:578:6:-;;;;;;:::i;:::-;;:::i;3810:120:0:-;;;;;;:::i;:::-;3875:7;3901:12;;;:6;:12;;;;;:22;;;;3810:120;5037:113:27;;;;;;:::i;:::-;;:::i;2379:419:13:-;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;3742:55:30;;;3724:74;;3829:2;3814:18;;3807:34;;;;3697:18;2379:419:13;3550:297:30;4226:136:0;;;;;;:::i;:::-;;:::i;1736:255:9:-;;;;;;:::i;:::-;;:::i;5328:245:0:-;;;;;;:::i;:::-;;:::i;4787:132:6:-;;;;;;:::i;:::-;;:::i;2236:226:9:-;;;;;;:::i;:::-;;:::i;3260:158:27:-;;;;;;:::i;:::-;;:::i;2185:118:6:-;;;;;;:::i;:::-;;:::i;1920:208::-;;;;;;:::i;:::-;;:::i;2293:101:2:-;;;:::i;1611:333:27:-;;;;;;:::i;:::-;;:::i;939:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;3422:96;;;;;;:::i;:::-;;:::i;1638:85:2:-;1710:6;;-1:-1:-1;;;;;1710:6:2;1638:85;;2854:136:0;;;;;;:::i;:::-;2931:4;2954:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2954:29:0;;;;;;;;;;;;;;;2854:136;2518:93:6;;;:::i;839:25:27:-;;;;;-1:-1:-1;;;;;839:25:27;;;;;;-1:-1:-1;;;;;4788:39:30;;;4770:58;;4758:2;4743:18;839:25:27;4626:208:30;711:81:27;;-1:-1:-1;;;;;711:81:27;;2187:49:0;;2232:4;2187:49;;3718:144:6;;;;;;:::i;:::-;;:::i;2081:359:27:-;;;;;;:::i;:::-;;:::i;4312:114::-;;;;;;:::i;:::-;-1:-1:-1;;;;;4396:25:27;4377:4;4396:25;;;:15;:25;;;;;;;;;4312:114;3071:185;;;;;;:::i;:::-;;:::i;4985:208:6:-;;;;;;:::i;:::-;;:::i;4916:117:27:-;;;;;;:::i;:::-;;:::i;2900:167::-;;;;;;:::i;:::-;;:::i;5154:117::-;;;:::i;4642:138:0:-;;;;;;:::i;:::-;;:::i;491:94:24:-;;;:::i;4085:109:27:-;;;;;;:::i;:::-;;:::i;3928:153:6:-;;;;;;:::i;:::-;-1:-1:-1;;;;;4039:25:6;;;4016:4;4039:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;3928:153;2543:215:2;;;;;;:::i;:::-;;:::i;3847:105:27:-;;;;;;:::i;:::-;;:::i;3522:201::-;3663:4;3682:36;3706:11;3682:23;:36::i;:::-;3675:43;3522:201;-1:-1:-1;;3522:201:27:o;2365:89:6:-;2410:13;2442:5;2435:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2365:89;:::o;3497:154::-;3564:7;3583:22;3597:7;3583:13;:22::i;:::-;-1:-1:-1;6008:7:6;6034:24;;;:15;:24;;;;;;-1:-1:-1;;;;;6034:24:6;3623:21;5938:127;3323:113;3394:35;3403:2;3407:7;735:10:16;3394:8:6;:35::i;:::-;3323:113;;:::o;2595:229:27:-;2648:7;2663:21;2709:1;2687:19;;:23;;;;:::i;:::-;2663:47;;2716:20;2777:1;2753:21;;2739:11;;:35;;;;:::i;:::-;:39;;;;:::i;:::-;2716:62;-1:-1:-1;2791:28:27;2716:62;2791:13;:28;:::i;:::-;2784:35;;;;2595:229;:::o;4777:135::-;1531:13:2;:11;:13::i;:::-;4857:50:27::1;::::0;-1:-1:-1;;;4857:50:27;;4882:4:::1;4857:50;::::0;::::1;8209:34:30::0;-1:-1:-1;;;;;8279:15:30;;8259:18;;;8252:43;8311:18;;;8304:34;;;-1:-1:-1;;;;;749:42:27;4857:16:::1;::::0;8121:18:30;;4857:50:27::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;4777:135:::0;;:::o;4143:578:6:-;-1:-1:-1;;;;;4237:16:6;;4233:87;;4276:33;;-1:-1:-1;;;4276:33:6;;4306:1;4276:33;;;1679:74:30;1652:18;;4276:33:6;;;;;;;;4233:87;4538:21;4562:34;4570:2;4574:7;735:10:16;4562:7:6;:34::i;:::-;4538:58;;4627:4;-1:-1:-1;;;;;4610:21:6;:13;-1:-1:-1;;;;;4610:21:6;;4606:109;;4654:50;;-1:-1:-1;;;4654:50:6;;-1:-1:-1;;;;;8819:15:30;;;4654:50:6;;;8801:34:30;8851:18;;;8844:34;;;8914:15;;8894:18;;;8887:43;8713:18;;4654:50:6;8538:398:30;4606:109:6;4223:498;4143:578;;;:::o;5037:113:27:-;1531:13:2;:11;:13::i;:::-;5102:43:27::1;::::0;-1:-1:-1;;;5102:43:27;;5128:4:::1;5102:43;::::0;::::1;9176:34:30::0;-1:-1:-1;;;;;9246:15:30;;9226:18;;;9219:43;-1:-1:-1;;;;;749:42:27;5102:17:::1;::::0;9088:18:30;;5102:43:27::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;2379:419:13:-:0;2465:7;2522:26;;;:17;:26;;;;;;;;2493:55;;;;;;;;;-1:-1:-1;;;;;2493:55:13;;;;;-1:-1:-1;;;2493:55:13;;;-1:-1:-1;;;;;2493:55:13;;;;;;;;2465:7;;2559:90;;-1:-1:-1;2609:29:13;;;;;;;;;-1:-1:-1;2609:29:13;-1:-1:-1;;;;;2609:29:13;;;;-1:-1:-1;;;2609:29:13;;-1:-1:-1;;;;;2609:29:13;;;;;2559:90;2696:23;;;;2659:21;;3156:5;;2684:35;;-1:-1:-1;;;;;2684:35:13;:9;:35;:::i;:::-;2683:57;;;;:::i;:::-;2759:16;;;;;-1:-1:-1;2379:419:13;;-1:-1:-1;;;;2379:419:13:o;4226:136:0:-;3875:7;3901:12;;;:6;:12;;;;;:22;;;2464:16;2475:4;2464:10;:16::i;:::-;4330:25:::1;4341:4;4347:7;4330:10;:25::i;1736:255:9:-:0;1824:7;1856:16;1866:5;1856:9;:16::i;:::-;1847:5;:25;1843:99;;1895:36;;-1:-1:-1;;;1895:36:9;;-1:-1:-1;;;;;3742:55:30;;1895:36:9;;;3724:74:30;3814:18;;;3807:34;;;3697:18;;1895:36:9;3550:297:30;1843:99:9;-1:-1:-1;;;;;;1958:19:9;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;1736:255::o;5328:245:0:-;-1:-1:-1;;;;;5421:34:0;;735:10:16;5421:34:0;5417:102;;5478:30;;-1:-1:-1;;;5478:30:0;;;;;;;;;;;5417:102;5529:37;5541:4;5547:18;5529:11;:37::i;4787:132:6:-;4873:39;4890:4;4896:2;4900:7;4873:39;;;;;;;;;;;;:16;:39::i;2236:226:9:-;2302:7;2334:13;:11;:13::i;:::-;2325:5;:22;2321:101;;2370:41;;-1:-1:-1;;;2370:41:9;;2401:1;2370:41;;;3724:74:30;3814:18;;;3807:34;;;3697:18;;2370:41:9;3550:297:30;2321:101:9;2438:10;2449:5;2438:17;;;;;;;;:::i;:::-;;;;;;;;;2431:24;;2236:226;;;:::o;3260:158:27:-;1531:13:2;:11;:13::i;:::-;3364:49:27::1;3381:7;3390:8;3400:12;3364:16;:49::i;2185:118:6:-:0;2248:7;2274:22;2288:7;2274:13;:22::i;1920:208::-;1983:7;-1:-1:-1;;;;;2006:19:6;;2002:87;;2048:30;;-1:-1:-1;;;2048:30:6;;2075:1;2048:30;;;1679:74:30;1652:18;;2048:30:6;1533:226:30;2002:87:6;-1:-1:-1;;;;;;2105:16:6;;;;;:9;:16;;;;;;;1920:208::o;2293:101:2:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;1611:333:27:-;1695:10;1656:7;1679:27;;;:15;:27;;;;;;;;;:52;;-1:-1:-1;1721:10:27;1710:7;:6:2;;-1:-1:-1;;;;;1710:6:2;;1638:85;1710:7:27;-1:-1:-1;;;;;1710:21:27;;1679:52;1671:101;;;;-1:-1:-1;;;1671:101:27;;10134:2:30;1671:101:27;;;10116:21:30;10173:2;10153:18;;;10146:30;10212:34;10192:18;;;10185:62;-1:-1:-1;;;10263:18:30;;;10256:34;10307:19;;1671:101:27;9932:400:30;1671:101:27;1804:11;;;;;;1779:22;1821:13;1804:11;1821:13;:::i;:::-;;;;;;1840:30;1850:3;1855:14;1840:9;:30::i;:::-;1881;;;-1:-1:-1;;;;;3742:55:30;;3724:74;;3829:2;3814:18;;3807:34;;;1881:30:27;;3697:18:30;1881:30:27;;;;;;;1925:14;1611:333;-1:-1:-1;;1611:333:27:o;3422:96::-;1531:13:2;:11;:13::i;:::-;3485:28:27::1;3503:9;3485:17;:28::i;:::-;3422:96:::0;:::o;2518:93:6:-;2565:13;2597:7;2590:14;;;;;:::i;3718:144::-;3803:52;735:10:16;3836:8:6;3846;3803:18;:52::i;2081:359:27:-;2144:7;1531:13:2;:11;:13::i;:::-;2190:21:27::1;;2167:19;;:44;;2159:93;;;::::0;-1:-1:-1;;;2159:93:27;;10679:2:30;2159:93:27::1;::::0;::::1;10661:21:30::0;10718:2;10698:18;;;10691:30;10757:34;10737:18;;;10730:62;-1:-1:-1;;;10808:18:30;;;10801:34;10852:19;;2159:93:27::1;10477:400:30::0;2159:93:27::1;2284:19;::::0;;;;;2259:22:::1;2309:21;2284:19:::0;2309:21:::1;:::i;1554:1:2:-;2081:359:27::0;;;:::o;3071:185::-;3145:6;1531:13:2;:11;:13::i;:::-;3159:11:27::1;:26:::0;;-1:-1:-1;;3159:26:27::1;-1:-1:-1::0;;;;;3159:26:27;::::1;::::0;;::::1;::::0;;;3196:31:::1;::::0;4770:58:30;;;3196:31:27::1;::::0;4758:2:30;4743:18;3196:31:27::1;;;;;;;-1:-1:-1::0;;3240:11:27::1;::::0;-1:-1:-1;;;;;3240:11:27::1;::::0;3071:185::o;4985:208:6:-;5098:31;5111:4;5117:2;5121:7;5098:12;:31::i;:::-;5139:47;5162:4;5168:2;5172:7;5181:4;5139:22;:47::i;4916:117:27:-;1531:13:2;:11;:13::i;:::-;4983:45:27::1;::::0;-1:-1:-1;;;4983:45:27;;5011:4:::1;4983:45;::::0;::::1;9176:34:30::0;-1:-1:-1;;;;;9246:15:30;;9226:18;;;9219:43;-1:-1:-1;;;;;749:42:27;4983:19:::1;::::0;9088:18:30;;4983:45:27::1;8941:327:30::0;2900:167:27;2966:13;3018:14;:12;:14::i;:::-;3034:26;3051:8;3034:16;:26::i;:::-;3001:60;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2987:75;;2900:167;;;:::o;5154:117::-;5227:39;;-1:-1:-1;;;5227:39:27;;5260:4;5227:39;;;1679:74:30;5205:7:27;;-1:-1:-1;;;;;749:42:27;5227:24;;1652:18:30;;5227:39:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5220:46;;5154:117;:::o;4642:138:0:-;3875:7;3901:12;;;:6;:12;;;;;:22;;;2464:16;2475:4;2464:10;:16::i;:::-;4747:26:::1;4759:4;4765:7;4747:11;:26::i;491:94:24:-:0;545:13;573:7;566:14;;;;;:::i;4085:109:27:-;1531:13:2;:11;:13::i;:::-;-1:-1:-1;;;;;4156:25:27::1;4184:5;4156:25:::0;;;:15:::1;:25;::::0;;;;:33;;-1:-1:-1;;4156:33:27::1;::::0;;4085:109::o;2543:215:2:-;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:2;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:2;;2700:1:::1;2672:31;::::0;::::1;1679:74:30::0;1652:18;;2672:31:2::1;1533:226:30::0;2623:91:2::1;2723:28;2742:8;2723:18;:28::i;3847:105:27:-:0;1531:13:2;:11;:13::i;:::-;-1:-1:-1;;;;;3915:25:27::1;;::::0;;;:15:::1;:25;::::0;;;;:32;;-1:-1:-1;;3915:32:27::1;3943:4;3915:32;::::0;;3847:105::o;2565:202:0:-;2650:4;-1:-1:-1;;;;;;2673:47:0;;-1:-1:-1;;;2673:47:0;;:87;;;2724:36;2748:11;2724:23;:36::i;16138:241:6:-;16201:7;5799:16;;;:7;:16;;;;;;-1:-1:-1;;;;;5799:16:6;;16263:88;;16309:31;;-1:-1:-1;;;16309:31:6;;;;;2370:25:30;;;2343:18;;16309:31:6;2224:177:30;14418:120:6;14498:33;14507:2;14511:7;14520:4;14526;14498:8;:33::i;1796:162:2:-;1710:6;;-1:-1:-1;;;;;1710:6:2;735:10:16;1855:23:2;1851:101;;1901:40;;-1:-1:-1;;;1901:40:2;;735:10:16;1901:40:2;;;1679:74:30;1652:18;;1901:40:2;1533:226:30;4430:188:27;4559:7;4581:32;4595:2;4599:7;4608:4;4581:13;:32::i;:::-;4574:39;4430:188;-1:-1:-1;;;;4430:188:27:o;3199:103:0:-;3265:30;3276:4;735:10:16;3265::0;:30::i;6179:316::-;6256:4;2954:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2954:29:0;;;;;;;;;;;;6272:217;;6315:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6315:29:0;;;;;;;;;:36;;-1:-1:-1;;6315:36:0;6347:4;6315:36;;;6397:12;735:10:16;;656:96;6397:12:0;-1:-1:-1;;;;;6370:40:0;6388:7;-1:-1:-1;;;;;6370:40:0;6382:4;6370:40;;;;;;;;;;-1:-1:-1;6431:4:0;6424:11;;6272:217;-1:-1:-1;6473:5:0;6466:12;;6730:317;6808:4;2954:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2954:29:0;;;;;;;;;;;;6824:217;;;6898:5;6866:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6866:29:0;;;;;;;;;;:37;;-1:-1:-1;;6866:37:0;;;6922:40;735:10:16;;6866:12:0;;6922:40;;6898:5;6922:40;-1:-1:-1;6983:4:0;6976:11;;4370:543:13;3156:5;-1:-1:-1;;;;;4532:26:13;;;-1:-1:-1;4528:180:13;;;4635:62;;-1:-1:-1;;;4635:62:13;;;;;11584:25:30;;;-1:-1:-1;;;;;11645:39:30;;11625:18;;;11618:67;11701:18;;;11694:34;;;11557:18;;4635:62:13;11383:351:30;4528:180:13;-1:-1:-1;;;;;4721:22:13;;4717:115;;4766:55;;-1:-1:-1;;;4766:55:13;;;;;11913:25:30;;;4818:1:13;11954:18:30;;;11947:83;11886:18;;4766:55:13;11739:297:30;4717:115:13;-1:-1:-1;4871:35:13;;;;;;;;-1:-1:-1;;;;;4871:35:13;;;;;-1:-1:-1;;;;;4871:35:13;;;;;;;;;;-1:-1:-1;4842:26:13;;;:17;:26;;;;;;:64;;;;;;;-1:-1:-1;;;4842:64:13;;;;;;4370:543::o;2912:187:2:-;3004:6;;;-1:-1:-1;;;;;3020:17:2;;;-1:-1:-1;;3020:17:2;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;10633:100:6:-;10700:26;10710:2;10714:7;10700:26;;;;;;;;;;;;:9;:26::i;15591:312::-;-1:-1:-1;;;;;15698:22:6;;15694:91;;15743:31;;-1:-1:-1;;;15743:31:6;;-1:-1:-1;;;;;1697:55:30;;15743:31:6;;;1679:74:30;1652:18;;15743:31:6;1533:226:30;15694:91:6;-1:-1:-1;;;;;15794:25:6;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;15794:46:6;;;;;;;;;;15855:41;;540::30;;;15855::6;;513:18:30;15855:41:6;;;;;;;15591:312;;;:::o;16918:782::-;-1:-1:-1;;;;;17034:14:6;;;:18;17030:664;;17072:71;;-1:-1:-1;;;17072:71:6;;-1:-1:-1;;;;;17072:36:6;;;;;:71;;735:10:16;;17123:4:6;;17129:7;;17138:4;;17072:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;17072:71:6;;;;;;;;-1:-1:-1;;17072:71:6;;;;;;;;;;;;:::i;:::-;;;17068:616;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17381:6;:13;17398:1;17381:18;17377:293;;17430:25;;-1:-1:-1;;;17430:25:6;;-1:-1:-1;;;;;1697:55:30;;17430:25:6;;;1679:74:30;1652:18;;17430:25:6;1533:226:30;17377:293:6;17622:6;17616:13;17607:6;17603:2;17599:15;17592:38;17068:616;-1:-1:-1;;;;;;17190:51:6;;-1:-1:-1;;;17190:51:6;17186:130;;17272:25;;-1:-1:-1;;;17272:25:6;;-1:-1:-1;;;;;1697:55:30;;17272:25:6;;;1679:74:30;1652:18;;17272:25:6;1533:226:30;17186:130:6;17144:186;16918:782;;;;:::o;637:698:19:-;693:13;742:14;759:17;770:5;759:10;:17::i;:::-;779:1;759:21;742:38;;794:20;828:6;817:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;817:18:19;-1:-1:-1;794:41:19;-1:-1:-1;955:28:19;;;971:2;955:28;1010:282;-1:-1:-1;;1041:5:19;1180:10;1175:2;1164:14;;1159:32;1041:5;1146:46;1236:2;1227:11;;;-1:-1:-1;1256:21:19;1010:282;1256:21;-1:-1:-1;1312:6:19;637:698;-1:-1:-1;;;637:698:19:o;1065:168:10:-;1167:4;1190:36;1214:11;1190:23;:36::i;14720:662:6:-;14880:9;:31;;;-1:-1:-1;;;;;;14893:18:6;;;;14880:31;14876:460;;;14927:13;14943:22;14957:7;14943:13;:22::i;:::-;14927:38;-1:-1:-1;;;;;;15093:18:6;;;;;;:35;;;15124:4;-1:-1:-1;;;;;15115:13:6;:5;-1:-1:-1;;;;;15115:13:6;;;15093:35;:69;;;;-1:-1:-1;;;;;;4039:25:6;;;4016:4;4039:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;15132:30;15093:69;15089:142;;;15189:27;;-1:-1:-1;;;15189:27:6;;-1:-1:-1;;;;;1697:55:30;;15189:27:6;;;1679:74:30;1652:18;;15189:27:6;1533:226:30;15089:142:6;15249:9;15245:81;;;15303:7;15299:2;-1:-1:-1;;;;;15283:28:6;15292:5;-1:-1:-1;;;;;15283:28:6;;;;;;;;;;;15245:81;14913:423;14876:460;-1:-1:-1;;15346:24:6;;;;:15;:24;;;;;:29;;-1:-1:-1;;15346:29:6;-1:-1:-1;;;;;15346:29:6;;;;;;;;;;14720:662::o;2518:625:9:-;2613:7;2632:21;2656:32;2670:2;2674:7;2683:4;2656:13;:32::i;:::-;2632:56;-1:-1:-1;;;;;;2703:27:9;;2699:210;;2746:40;2778:7;3949:10;:17;;3922:24;;;;:15;:24;;;;;:44;;;3976:24;;;;;;;;;;;;3846:161;2746:40;2699:210;;;2824:2;-1:-1:-1;;;;;2807:19:9;:13;-1:-1:-1;;;;;2807:19:9;;2803:106;;2842:56;2875:13;2890:7;2842:32;:56::i;:::-;-1:-1:-1;;;;;2922:16:9;;2918:188;;2954:45;2991:7;2954:36;:45::i;:::-;2918:188;;;3037:2;-1:-1:-1;;;;;3020:19:9;:13;-1:-1:-1;;;;;3020:19:9;;3016:90;;3055:40;3083:2;3087:7;3055:27;:40::i;3432:197:0:-;2931:4;2954:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2954:29:0;;;;;;;;;;;;3515:108;;3565:47;;-1:-1:-1;;;3565:47:0;;-1:-1:-1;;;;;3742:55:30;;3565:47:0;;;3724:74:30;3814:18;;;3807:34;;;3697:18;;3565:47:0;3550:297:30;10954:182:6;11048:18;11054:2;11058:7;11048:5;:18::i;:::-;11076:53;11107:1;11111:2;11115:7;11124:4;11076:22;:53::i;12214:916:22:-;12267:7;;12351:8;12342:17;;12338:103;;12388:8;12379:17;;;-1:-1:-1;12424:2:22;12414:12;12338:103;12467:8;12458:5;:17;12454:103;;12504:8;12495:17;;;-1:-1:-1;12540:2:22;12530:12;12454:103;12583:8;12574:5;:17;12570:103;;12620:8;12611:17;;;-1:-1:-1;12656:2:22;12646:12;12570:103;12699:7;12690:5;:16;12686:100;;12735:7;12726:16;;;-1:-1:-1;12770:1:22;12760:11;12686:100;12812:7;12803:5;:16;12799:100;;12848:7;12839:16;;;-1:-1:-1;12883:1:22;12873:11;12799:100;12925:7;12916:5;:16;12912:100;;12961:7;12952:16;;;-1:-1:-1;12996:1:22;12986:11;12912:100;13038:7;13029:5;:16;13025:66;;13075:1;13065:11;13117:6;12214:916;-1:-1:-1;;12214:916:22:o;1435:222:9:-;1537:4;-1:-1:-1;;;;;;1560:50:9;;-1:-1:-1;;;1560:50:9;;:90;;;1614:36;1638:11;1614:23;:36::i;8838:795:6:-;8924:7;5799:16;;;:7;:16;;;;;;-1:-1:-1;;;;;5799:16:6;;;;9035:18;;;9031:86;;9069:37;9086:4;9092;9098:7;9069:16;:37::i;:::-;-1:-1:-1;;;;;9161:18:6;;;9157:256;;9277:48;9294:1;9298:7;9315:1;9319:5;9277:8;:48::i;:::-;-1:-1:-1;;;;;9368:15:6;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;9368:20:6;;;9157:256;-1:-1:-1;;;;;9427:16:6;;;9423:107;;-1:-1:-1;;;;;9487:13:6;;;;;;:9;:13;;;;;:18;;9504:1;9487:18;;;9423:107;9540:16;;;;:7;:16;;;;;;:21;;-1:-1:-1;;9540:21:6;-1:-1:-1;;;;;9540:21:6;;;;;;;;;9577:27;;9540:16;;9577:27;;;;;;;9622:4;8838:795;-1:-1:-1;;;;8838:795:6:o;4624:959:9:-;4886:22;4911:15;4921:4;4911:9;:15::i;:::-;4936:18;4957:26;;;:17;:26;;;;;;4886:40;;-1:-1:-1;5087:28:9;;;5083:323;;-1:-1:-1;;;;;5153:18:9;;5131:19;5153:18;;;:12;:18;;;;;;;;:34;;;;;;;;;5202:30;;;;;;:44;;;5318:30;;:17;:30;;;;;:43;;;5083:323;-1:-1:-1;5499:26:9;;;;:17;:26;;;;;;;;5492:33;;;-1:-1:-1;;;;;5542:18:9;;;;;:12;:18;;;;;:34;;;;;;;5535:41;4624:959::o;5871:1061::-;6145:10;:17;6120:22;;6145:21;;6165:1;;6145:21;:::i;:::-;6176:18;6197:24;;;:15;:24;;;;;;6565:10;:26;;6120:46;;-1:-1:-1;6197:24:9;;6120:46;;6565:26;;;;;;:::i;:::-;;;;;;;;;6543:48;;6627:11;6602:10;6613;6602:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;6706:28;;;:15;:28;;;;;;;:41;;;6875:24;;;;;6868:31;6909:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;5942:990;;;5871:1061;:::o;3437:214::-;3521:14;3554:1;3538:13;3548:2;3538:9;:13::i;:::-;:17;;;;:::i;:::-;-1:-1:-1;;;;;3565:16:9;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;3609:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;3437:214:9:o;9955:327:6:-;-1:-1:-1;;;;;10022:16:6;;10018:87;;10061:33;;-1:-1:-1;;;10061:33:6;;10091:1;10061:33;;;1679:74:30;1652:18;;10061:33:6;1533:226:30;10018:87:6;10114:21;10138:32;10146:2;10150:7;10167:1;10138:7;:32::i;:::-;10114:56;-1:-1:-1;;;;;;10184:27:6;;;10180:96;;10234:31;;-1:-1:-1;;;10234:31:6;;10262:1;10234:31;;;1679:74:30;1652:18;;10234:31:6;1533:226:30;1561:300:6;1663:4;-1:-1:-1;;;;;;1698:40:6;;-1:-1:-1;;;1698:40:6;;:104;;-1:-1:-1;;;;;;;1754:48:6;;-1:-1:-1;;;1754:48:6;1698:104;:156;;;;1818:36;1842:11;1818:23;:36::i;7082:368::-;7194:38;7208:5;7215:7;7224;7194:13;:38::i;:::-;7189:255;;-1:-1:-1;;;;;7252:19:6;;7248:186;;7298:31;;-1:-1:-1;;;7298:31:6;;;;;2370:25:30;;;2343:18;;7298:31:6;2224:177:30;7248:186:6;7375:44;;-1:-1:-1;;;7375:44:6;;-1:-1:-1;;;;;3742:55:30;;7375:44:6;;;3724:74:30;3814:18;;;3807:34;;;3697:18;;7375:44:6;3550:297:30;2116:213:13;2218:4;-1:-1:-1;;;;;;2241:41:13;;-1:-1:-1;;;2241:41:13;;:81;;-1:-1:-1;;;;;;;;;;861:40:20;;;2286:36:13;762:146:20;6376:272:6;6479:4;-1:-1:-1;;;;;6514:21:6;;;;;;:127;;;6561:7;-1:-1:-1;;;;;6552:16:6;:5;-1:-1:-1;;;;;6552:16:6;;:52;;;-1:-1:-1;;;;;;4039:25:6;;;4016:4;4039:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;6572:32;6552:88;;;-1:-1:-1;;6008:7:6;6034:24;;;:15;:24;;;;;;-1:-1:-1;;;;;6034:24:6;;;6608:32;;;;;-1:-1:-1;6376:272:6:o;14:131:30:-;-1:-1:-1;;;;;;88:32:30;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;:::-;384:5;150:245;-1:-1:-1;;;150:245:30:o;592:250::-;677:1;687:113;701:6;698:1;695:13;687:113;;;777:11;;;771:18;758:11;;;751:39;723:2;716:10;687:113;;;-1:-1:-1;;834:1:30;816:16;;809:27;592:250::o;847:271::-;889:3;927:5;921:12;954:6;949:3;942:19;970:76;1039:6;1032:4;1027:3;1023:14;1016:4;1009:5;1005:16;970:76;:::i;:::-;1100:2;1079:15;-1:-1:-1;;1075:29:30;1066:39;;;;1107:4;1062:50;;847:271;-1:-1:-1;;847:271:30:o;1123:220::-;1272:2;1261:9;1254:21;1235:4;1292:45;1333:2;1322:9;1318:18;1310:6;1292:45;:::i;1348:180::-;1407:6;1460:2;1448:9;1439:7;1435:23;1431:32;1428:52;;;1476:1;1473;1466:12;1428:52;-1:-1:-1;1499:23:30;;1348:180;-1:-1:-1;1348:180:30:o;1764:196::-;1832:20;;-1:-1:-1;;;;;1881:54:30;;1871:65;;1861:93;;1950:1;1947;1940:12;1965:254;2033:6;2041;2094:2;2082:9;2073:7;2069:23;2065:32;2062:52;;;2110:1;2107;2100:12;2062:52;2133:29;2152:9;2133:29;:::i;:::-;2123:39;2209:2;2194:18;;;;2181:32;;-1:-1:-1;;;1965:254:30:o;2406:328::-;2483:6;2491;2499;2552:2;2540:9;2531:7;2527:23;2523:32;2520:52;;;2568:1;2565;2558:12;2520:52;2591:29;2610:9;2591:29;:::i;:::-;2581:39;;2639:38;2673:2;2662:9;2658:18;2639:38;:::i;:::-;2629:48;;2724:2;2713:9;2709:18;2696:32;2686:42;;2406:328;;;;;:::o;3106:186::-;3165:6;3218:2;3206:9;3197:7;3193:23;3189:32;3186:52;;;3234:1;3231;3224:12;3186:52;3257:29;3276:9;3257:29;:::i;3297:248::-;3365:6;3373;3426:2;3414:9;3405:7;3401:23;3397:32;3394:52;;;3442:1;3439;3432:12;3394:52;-1:-1:-1;;3465:23:30;;;3535:2;3520:18;;;3507:32;;-1:-1:-1;3297:248:30:o;3852:254::-;3920:6;3928;3981:2;3969:9;3960:7;3956:23;3952:32;3949:52;;;3997:1;3994;3987:12;3949:52;4033:9;4020:23;4010:33;;4062:38;4096:2;4085:9;4081:18;4062:38;:::i;:::-;4052:48;;3852:254;;;;;:::o;4111:179::-;4178:20;;-1:-1:-1;;;;;4227:38:30;;4217:49;;4207:77;;4280:1;4277;4270:12;4295:326;4371:6;4379;4387;4440:2;4428:9;4419:7;4415:23;4411:32;4408:52;;;4456:1;4453;4446:12;4408:52;4492:9;4479:23;4469:33;;4521:38;4555:2;4544:9;4540:18;4521:38;:::i;:::-;4511:48;;4578:37;4611:2;4600:9;4596:18;4578:37;:::i;:::-;4568:47;;4295:326;;;;;:::o;5085:347::-;5150:6;5158;5211:2;5199:9;5190:7;5186:23;5182:32;5179:52;;;5227:1;5224;5217:12;5179:52;5250:29;5269:9;5250:29;:::i;:::-;5240:39;;5329:2;5318:9;5314:18;5301:32;5376:5;5369:13;5362:21;5355:5;5352:32;5342:60;;5398:1;5395;5388:12;5342:60;5421:5;5411:15;;;5085:347;;;;;:::o;5437:184::-;5495:6;5548:2;5536:9;5527:7;5523:23;5519:32;5516:52;;;5564:1;5561;5554:12;5516:52;5587:28;5605:9;5587:28;:::i;5626:127::-;5687:10;5682:3;5678:20;5675:1;5668:31;5718:4;5715:1;5708:15;5742:4;5739:1;5732:15;5758:1138;5853:6;5861;5869;5877;5930:3;5918:9;5909:7;5905:23;5901:33;5898:53;;;5947:1;5944;5937:12;5898:53;5970:29;5989:9;5970:29;:::i;:::-;5960:39;;6018:38;6052:2;6041:9;6037:18;6018:38;:::i;:::-;6008:48;;6103:2;6092:9;6088:18;6075:32;6065:42;;6158:2;6147:9;6143:18;6130:32;6181:18;6222:2;6214:6;6211:14;6208:34;;;6238:1;6235;6228:12;6208:34;6276:6;6265:9;6261:22;6251:32;;6321:7;6314:4;6310:2;6306:13;6302:27;6292:55;;6343:1;6340;6333:12;6292:55;6379:2;6366:16;6401:2;6397;6394:10;6391:36;;;6407:18;;:::i;:::-;6482:2;6476:9;6450:2;6536:13;;-1:-1:-1;;6532:22:30;;;6556:2;6528:31;6524:40;6512:53;;;6580:18;;;6600:22;;;6577:46;6574:72;;;6626:18;;:::i;:::-;6666:10;6662:2;6655:22;6701:2;6693:6;6686:18;6741:7;6736:2;6731;6727;6723:11;6719:20;6716:33;6713:53;;;6762:1;6759;6752:12;6713:53;6818:2;6813;6809;6805:11;6800:2;6792:6;6788:15;6775:46;6863:1;6858:2;6853;6845:6;6841:15;6837:24;6830:35;6884:6;6874:16;;;;;;;5758:1138;;;;;;;:::o;6901:260::-;6969:6;6977;7030:2;7018:9;7009:7;7005:23;7001:32;6998:52;;;7046:1;7043;7036:12;6998:52;7069:29;7088:9;7069:29;:::i;:::-;7059:39;;7117:38;7151:2;7140:9;7136:18;7117:38;:::i;7166:380::-;7245:1;7241:12;;;;7288;;;7309:61;;7363:4;7355:6;7351:17;7341:27;;7309:61;7416:2;7408:6;7405:14;7385:18;7382:38;7379:161;;7462:10;7457:3;7453:20;7450:1;7443:31;7497:4;7494:1;7487:15;7525:4;7522:1;7515:15;7379:161;;7166:380;;;:::o;7551:127::-;7612:10;7607:3;7603:20;7600:1;7593:31;7643:4;7640:1;7633:15;7667:4;7664:1;7657:15;7683:128;7750:9;;;7771:11;;;7768:37;;;7785:18;;:::i;7816:125::-;7881:9;;;7902:10;;;7899:36;;;7915:18;;:::i;8349:184::-;8419:6;8472:2;8460:9;8451:7;8447:23;8443:32;8440:52;;;8488:1;8485;8478:12;8440:52;-1:-1:-1;8511:16:30;;8349:184;-1:-1:-1;8349:184:30:o;9273:168::-;9346:9;;;9377;;9394:15;;;9388:22;;9374:37;9364:71;;9415:18;;:::i;9578:217::-;9618:1;9644;9634:132;;9688:10;9683:3;9679:20;9676:1;9669:31;9723:4;9720:1;9713:15;9751:4;9748:1;9741:15;9634:132;-1:-1:-1;9780:9:30;;9578:217::o;9800:127::-;9861:10;9856:3;9852:20;9849:1;9842:31;9892:4;9889:1;9882:15;9916:4;9913:1;9906:15;10337:135;10376:3;10397:17;;;10394:43;;10417:18;;:::i;:::-;-1:-1:-1;10464:1:30;10453:13;;10337:135::o;10882:496::-;11061:3;11099:6;11093:13;11115:66;11174:6;11169:3;11162:4;11154:6;11150:17;11115:66;:::i;:::-;11244:13;;11203:16;;;;11266:70;11244:13;11203:16;11313:4;11301:17;;11266:70;:::i;:::-;11352:20;;10882:496;-1:-1:-1;;;;10882:496:30:o;12041:512::-;12235:4;-1:-1:-1;;;;;12345:2:30;12337:6;12333:15;12322:9;12315:34;12397:2;12389:6;12385:15;12380:2;12369:9;12365:18;12358:43;;12437:6;12432:2;12421:9;12417:18;12410:34;12480:3;12475:2;12464:9;12460:18;12453:31;12501:46;12542:3;12531:9;12527:19;12519:6;12501:46;:::i;:::-;12493:54;12041:512;-1:-1:-1;;;;;;12041:512:30:o;12558:249::-;12627:6;12680:2;12668:9;12659:7;12655:23;12651:32;12648:52;;;12696:1;12693;12686:12;12648:52;12728:9;12722:16;12747:30;12771:5;12747:30;:::i;13114:127::-;13175:10;13170:3;13166:20;13163:1;13156:31;13206:4;13203:1;13196:15;13230:4;13227:1;13220:15
Swarm Source
none
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.