Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
415827 | 82 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ERC721SingleEditionDFS
Compiler Version
v0.8.10+commit.fc410830
ZkSolc Version
v1.5.6
Optimization Enabled:
Yes with Mode z
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "../utils/Ownable.sol"; import "../metadata/interfaces/IMetadataRenderer.sol"; import "../metadata/interfaces/IEditionsMetadataRenderer.sol"; import "./interfaces/IEditionCollection.sol"; import "./ERC721MinimizedBase.sol"; import "../tokenManager/interfaces/IPostTransfer.sol"; import "../tokenManager/interfaces/IPostBurn.sol"; import "./interfaces/IERC721EditionMint.sol"; import "./MarketplaceFilterer/MarketplaceFilterer.sol"; import "../tokenManager/interfaces/ITokenManagerEditions.sol"; import "./erc721a/ERC721AUpgradeable.sol"; /** * @title ERC721 Single Edition * @author highlight.xyz * @notice Single Edition Per Collection * @dev Using Decentralized File Storage */ contract ERC721SingleEditionDFS is IERC721EditionMint, IEditionCollection, ERC721MinimizedBase, ERC721AUpgradeable, MarketplaceFilterer { using EnumerableSet for EnumerableSet.AddressSet; /** * @notice Throw when edition doesn't exist */ error EditionDoesNotExist(); /** * @notice Throw when token doesn't exist */ error TokenDoesNotExist(); /** * @notice Throw when attempting to mint, while mint is frozen */ error MintFrozen(); /** * @notice Throw when tokens on edition are sold out */ error SoldOut(); /** * @notice Throw when editionIds length is invalid */ error InvalidEditionIdsLength(); /** * @notice Throw when editionId is invalid */ error InvalidEditionId(); /** * @notice Contract metadata */ string public contractURI; /** * @notice Total size of edition that can be minted */ uint256 public size; /** * @notice Stores the edition's metadata */ string public editionUri; /** * @notice Emitted when edition is created * @param size Edition size * @param editionTokenManager Token manager for edition */ event EditionCreated(uint256 indexed size, address indexed editionTokenManager); /** * @notice Initializes the contract * @param creator Creator/owner of contract * @param data Data to initialize contract, in current format: * @ param defaultRoyalty Default royalty object for contract (optional) * @ param _defaultTokenManager Default token manager for contract (optional) * @ param _contractURI Contract metadata * @ param _name Name of token edition * @ param _symbol Symbol of the token edition * @ param _size Edition size * @ param trustedForwarder Trusted minimal forwarder * @ param initialMinter Initial minter to register * @ param useMarketplaceFiltererRegistry Denotes whether to use marketplace filterer registry * @ param _editionUri Edition uri * @param _observability Observability contract address */ function initialize(address creator, bytes memory data, address _observability) external initializer { ( IRoyaltyManager.Royalty memory defaultRoyalty, address _defaultTokenManager, string memory _contractURI, string memory _name, string memory _symbol, uint256 _size, address trustedForwarder, address initialMinter, bool useMarketplaceFiltererRegistry, string memory _editionUri ) = abi.decode( data, (IRoyaltyManager.Royalty, address, string, string, string, uint256, address, address, bool, string) ); _initialize( creator, defaultRoyalty, _defaultTokenManager, _contractURI, _name, _symbol, _editionUri, _size, trustedForwarder, initialMinter, useMarketplaceFiltererRegistry ); IObservability(_observability).emitSingleEditionDeployed(address(this)); observability = IObservability(_observability); } /** * @notice See {IERC721EditionMint-mintOneToRecipient} */ function mintOneToRecipient( uint256 editionId, address recipient ) external onlyMinter nonReentrant returns (uint256) { if (_mintFrozen == 1) { _revert(MintFrozen.selector); } if (!_editionExists(editionId)) { _revert(EditionDoesNotExist.selector); } return _mintEditionsToOne(recipient, 1); } /** * @notice See {IERC721EditionMint-mintAmountToRecipient} */ function mintAmountToRecipient( uint256 editionId, address recipient, uint256 amount ) external onlyMinter nonReentrant returns (uint256) { if (_mintFrozen == 1) { _revert(MintFrozen.selector); } if (!_editionExists(editionId)) { _revert(EditionDoesNotExist.selector); } return _mintEditionsToOne(recipient, amount); } /** * @notice See {IERC721EditionMint-mintOneToRecipients} */ function mintOneToRecipients( uint256 editionId, address[] memory recipients ) external onlyMinter nonReentrant returns (uint256) { if (_mintFrozen == 1) { _revert(MintFrozen.selector); } if (!_editionExists(editionId)) { _revert(EditionDoesNotExist.selector); } return _mintEditions(recipients, 1); } /** * @notice See {IERC721EditionMint-mintAmountToRecipients} */ function mintAmountToRecipients( uint256 editionId, address[] memory recipients, uint256 amount ) external onlyMinter nonReentrant returns (uint256) { if (_mintFrozen == 1) { _revert(MintFrozen.selector); } if (!_editionExists(editionId)) { _revert(EditionDoesNotExist.selector); } return _mintEditions(recipients, amount); } /** * @notice Set contract name * @param newName New name * @param newSymbol New symbol * @param newContractUri New contractURI */ function setContractMetadata( string calldata newName, string calldata newSymbol, string calldata newContractUri ) external onlyOwner { _setContractMetadata(newName, newSymbol); contractURI = newContractUri; observability.emitContractMetadataSet(newName, newSymbol, newContractUri); } /** * @notice See {IEditionCollection-getEditionId} */ function getEditionId(uint256 tokenId) external view returns (uint256) { if (!_exists(tokenId)) { _revert(TokenDoesNotExist.selector); } return 0; } /** * @notice See {IEditionCollection-getEditionDetails} */ function getEditionDetails(uint256 editionId) external view returns (EditionDetails memory) { if (!_editionExists(editionId)) { _revert(EditionDoesNotExist.selector); } return _getEditionDetails(); } /** * @notice See {IEditionCollection-getEditionsDetailsAndUri} */ function getEditionsDetailsAndUri( uint256[] calldata editionIds ) external view returns (EditionDetails[] memory, string[] memory) { if (editionIds.length != 1) { _revert(InvalidEditionIdsLength.selector); } EditionDetails[] memory editionsDetails = new EditionDetails[](1); string[] memory uris = new string[](1); // expected to be 0, validated in editionURI call uint256 editionId = editionIds[0]; uris[0] = editionURI(editionId); editionsDetails[0] = _getEditionDetails(); return (editionsDetails, uris); } /** * @notice See {IERC721-transferFrom}. Overrides default behaviour to check associated tokenManager. */ function transferFrom(address from, address to, uint256 tokenId) public payable override { ERC721AUpgradeable.transferFrom(from, to, tokenId); address _manager = defaultManager; if (_manager != address(0) && IERC165Upgradeable(_manager).supportsInterface(type(IPostTransfer).interfaceId)) { IPostTransfer(_manager).postTransferFrom(_msgSender(), from, to, tokenId); } observability.emitTransfer(from, to, tokenId); } /** * @notice See {IERC721-safeTransferFrom}. Overrides default behaviour to check associated tokenManager. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public payable override { ERC721AUpgradeable.safeTransferFrom(from, to, tokenId, data); address _manager = defaultManager; if (_manager != address(0) && IERC165Upgradeable(_manager).supportsInterface(type(IPostTransfer).interfaceId)) { IPostTransfer(_manager).postSafeTransferFrom(_msgSender(), from, to, tokenId, data); } observability.emitTransfer(from, to, tokenId); } /** * @notice See {IERC721-burn}. Overrides default behaviour to check associated tokenManager. */ function burn(uint256 tokenId) public nonReentrant { address _manager = defaultManager; address msgSender = _msgSender(); if (_manager != address(0) && IERC165Upgradeable(_manager).supportsInterface(type(IPostBurn).interfaceId)) { address owner = ownerOf(tokenId); IPostBurn(_manager).postBurn(msgSender, owner, 0); } else { // default to restricting burn to owner or operator if a valid TM isn't present if (!_isApprovedOrOwner(msgSender, tokenId)) { _revert(Unauthorized.selector); } } _burn(tokenId); observability.emitTransfer(msgSender, address(0), tokenId); } /** * @notice Conforms to ERC-2981. * @param // Token id * @param _salePrice Sale price of token */ function royaltyInfo( uint256 /* _tokenId */, uint256 _salePrice ) public view virtual override returns (address receiver, uint256 royaltyAmount) { return ERC721MinimizedBase.royaltyInfo(0, _salePrice); } /** * @notice Get URI for given edition id * @param editionId edition id to get uri for */ function editionURI(uint256 editionId) public view returns (string memory) { if (!_editionExists(editionId)) { _revert(EditionDoesNotExist.selector); } return editionUri; } /** * @notice Get URI for given token id * @param tokenId token id to get uri for */ function tokenURI(uint256 tokenId) public view override returns (string memory) { if (!_exists(tokenId)) { _revert(TokenDoesNotExist.selector); } return editionUri; } /** * @notice Used to get token manager of token id * @param tokenId ID of the token */ function tokenManagerByTokenId(uint256 tokenId) public view returns (address) { return tokenManager(tokenId); } /** * @notice Set an Edition's uri * @param editionId Edition to set uri for * @param _uri Uri to set on editions */ function setEditionURI(uint256 editionId, string memory _uri) external { if (editionId != 0) { _revert(InvalidEditionId.selector); } address _manager = defaultManager; address msgSender = _msgSender(); if (_manager == address(0)) { address tempOwner = owner(); if (msgSender != tempOwner) { _revert(Unauthorized.selector); } } else { if ( !ITokenManagerEditions(_manager).canUpdateEditionsMetadata( address(this), msgSender, 0, bytes(_uri), ITokenManagerEditions.FieldUpdated.other ) ) { _revert(Unauthorized.selector); } } editionUri = _uri; uint256[] memory _ids = new uint256[](1); _ids[0] = 0; string[] memory _uris = new string[](1); _uris[0] = _uri; observability.emitTokenURIsSet(_ids, _uris); } /** * @notice See {IERC721AUpgradeable-supportsInterface}. */ function supportsInterface( bytes4 interfaceId ) public view virtual override(IERC165Upgradeable, ERC721AUpgradeable) returns (bool) { return ERC721AUpgradeable.supportsInterface(interfaceId); } /** * @notice Private function to mint without any access checks. Called by the public edition minting functions. * @param recipients Recipients of newly minted tokens * @param _amount Amount minted to each recipient */ function _mintEditions(address[] memory recipients, uint256 _amount) internal returns (uint256) { uint256 recipientsLength = recipients.length; uint256 tempCurrent = _nextTokenId(); uint256 endAt = tempCurrent + (recipientsLength * _amount) - 1; if (size != 0 && endAt > size) { _revert(SoldOut.selector); } for (uint256 i = 0; i < recipientsLength; i++) { _mint(recipients[i], _amount); } return endAt; } /** * @notice Private function to mint without any access checks. Called by the public edition minting functions. * @param recipient Recipient of newly minted token * @param _amount Amount minted to recipient */ function _mintEditionsToOne(address recipient, uint256 _amount) internal returns (uint256) { uint256 tempCurrent = _nextTokenId(); uint256 endAt = tempCurrent + _amount - 1; if (size != 0 && endAt > size) { _revert(SoldOut.selector); } _mint(recipient, _amount); return endAt; } /** * @notice Used for meta-transactions */ function _msgSender() internal view override(ERC721MinimizedBase, ContextUpgradeable) returns (address sender) { return ERC2771ContextUpgradeable._msgSender(); } /** * @notice Used for meta-transactions */ function _msgData() internal view override(ERC721MinimizedBase, ContextUpgradeable) returns (bytes calldata) { return ERC2771ContextUpgradeable._msgData(); } /** * @dev For more efficient reverts. */ function _revert( bytes4 errorSelector ) internal pure override(ERC721AUpgradeable, ERC721MinimizedBase, MarketplaceFilterer) { ERC721AUpgradeable._revert(errorSelector); } /** * @notice Used to initialize contract * @param creator Creator/owner of contract * @param defaultRoyalty Default royalty object for contract (optional) * @param _defaultTokenManager Default token manager for contract (optional) * @param _contractURI Contract metadata * @param _name Name of token edition * @param _symbol Symbol of the token edition * @param _editionUri Edition uri (metadata) * @param _size Edition size * @param trustedForwarder Trusted minimal forwarder * @param initialMinter Initial minter to register * @param useMarketplaceFiltererRegistry Denotes whether to use marketplace filterer registry */ function _initialize( address creator, IRoyaltyManager.Royalty memory defaultRoyalty, address _defaultTokenManager, string memory _contractURI, string memory _name, string memory _symbol, string memory _editionUri, uint256 _size, address trustedForwarder, address initialMinter, bool useMarketplaceFiltererRegistry ) private { __ERC721MinimizedBase_initialize(creator, defaultRoyalty, _defaultTokenManager); __ERC721A_init(_name, _symbol); __ERC2771ContextUpgradeable__init__(trustedForwarder); // deprecate but keep input for backwards-compatibility: // __MarketplaceFilterer__init__(useMarketplaceFiltererRegistry); size = _size; editionUri = _editionUri; _minters.add(initialMinter); contractURI = _contractURI; emit EditionCreated(_size, _defaultTokenManager); } /** * @notice Get edition details */ function _getEditionDetails() private view returns (EditionDetails memory) { return EditionDetails(this.name(), size, _nextTokenId() - 1, 1); } /** * @notice Returns whether `editionId` exists. */ function _editionExists(uint256 editionId) private pure returns (bool) { return editionId == 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity 0.8.10; import "@openzeppelin/contracts/utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ /* solhint-disable */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Used to interface with core of EditionsMetadataRenderer * @author Zora, [email protected] */ interface IMetadataRenderer { /** * @notice Store metadata for an edition * @param data Metadata */ function initializeMetadata(bytes memory data) external; /** * @notice Get uri for token * @param tokenId ID of token to get uri for */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Used to interface with EditionsMetadataRenderer * @author highlight.xyz */ interface IEditionsMetadataRenderer { /** * @notice Token edition info * @param name Edition name * @param description Edition description * @param imageUrl Edition image url * @param animationUrl Edition animation url * @param externalUrl Edition external url * @param attributes Edition attributes */ struct TokenEditionInfo { string name; string description; string imageUrl; string animationUrl; string externalUrl; string attributes; } /** * @notice Updates name on edition. Managed by token manager if existent * @param editionsAddress Address of collection that edition is on * @param editionId ID of edition to update * @param name New name of edition */ function updateName(address editionsAddress, uint256 editionId, string calldata name) external; /** * @notice Updates description on edition. Managed by token manager if existent * @param editionsAddress Address of collection that edition is on * @param editionId ID of edition to update * @param description New description of edition */ function updateDescription(address editionsAddress, uint256 editionId, string calldata description) external; /** * @notice Updates imageUrl on edition. Managed by token manager if existent * @param editionsAddress Address of collection that edition is on * @param editionId ID of edition to update * @param imageUrl New imageUrl of edition */ function updateImageUrl(address editionsAddress, uint256 editionId, string calldata imageUrl) external; /** * @notice Updates animationUrl on edition. Managed by token manager if existent * @param editionsAddress Address of collection that edition is on * @param editionId ID of edition to update * @param animationUrl New animationUrl of edition */ function updateAnimationUrl(address editionsAddress, uint256 editionId, string calldata animationUrl) external; /** * @notice Updates externalUrl on edition. Managed by token manager if existent * @param editionsAddress Address of collection that edition is on * @param editionId ID of edition to update * @param externalUrl New externalUrl of edition */ function updateExternalUrl(address editionsAddress, uint256 editionId, string calldata externalUrl) external; /** * @notice Updates attributes on edition. Managed by token manager if existent * @param editionsAddress Address of collection that edition is on * @param editionId ID of edition to update * @param attributes New attributes of edition */ function updateAttributes(address editionsAddress, uint256 editionId, string calldata attributes) external; /** * @notice Updates any set of metadata fields * @param editionsAddress Address of collection that edition is on * @param editionId ID of edition to update * @param tokenEditionInfo New metadata fields * @param updateIds Encoded what metadata fields to update */ function updateMetadata( address editionsAddress, uint256 editionId, TokenEditionInfo calldata tokenEditionInfo, uint256[] calldata updateIds ) external; /** * @notice Get an edition's uri. HAS to be called by collection * @param editionId Edition's id to get uri for */ function editionURI(uint256 editionId) external view returns (string memory); /** * @notice Get an edition's info. * @param editionsAddress Address of collection that edition is on * @param editionsId Edition's id to get info for */ function editionInfo(address editionsAddress, uint256 editionsId) external view returns (TokenEditionInfo memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "./ITokenManager.sol"; /** * @title ITokenManager * @author highlight.xyz * @notice Enables interfacing with custom token managers for editions contracts */ interface ITokenManagerEditions is ITokenManager { /** * @notice The updated field in metadata updates */ enum FieldUpdated { name, description, imageUrl, animationUrl, externalUrl, attributes, other } /** * @notice Returns whether metadata updater is allowed to update * @param editionsAddress Address of editions contract * @param sender Updater * @param editionId Token/edition who's uri is being updated * If id is 0, implementation should decide behaviour for base uri update * @param newData Token's new uri if called by general contract, and any metadata field if called by editions * @param fieldUpdated Which metadata field was updated * @return If invocation can update metadata */ function canUpdateEditionsMetadata( address editionsAddress, address sender, uint256 editionId, bytes calldata newData, FieldUpdated fieldUpdated ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; /** * @author highlight.xyz * @notice If token managers implement this, transfer actions will call * postSafeTransferFrom or postTransferFrom on the token manager. */ interface IPostTransfer { /** * @notice Hook called by community after safe transfers, if token manager of transferred token implements this * interface. * @param operator Operator transferring tokens * @param from Token(s) sender * @param to Token(s) recipient * @param id Transferred token's id * @param data Arbitrary data */ function postSafeTransferFrom(address operator, address from, address to, uint256 id, bytes memory data) external; /** * @notice Hook called by community after transfers, if token manager of transferred token implements * this interface. * @param operator Operator transferring tokens * @param from Token(s) sender * @param to Token(s) recipient * @param id Transferred token's id */ function postTransferFrom(address operator, address from, address to, uint256 id) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Mint interface on editions contracts * @author highlight.xyz */ interface IERC721EditionMint { /** * @notice Mints one NFT to one recipient * @param editionId Edition to mint the NFT on * @param recipient Recipient of minted NFT */ function mintOneToRecipient(uint256 editionId, address recipient) external returns (uint256); /** * @notice Mints an amount of NFTs to one recipient * @param editionId Edition to mint the NFTs on * @param recipient Recipient of minted NFTs * @param amount Amount of NFTs minted */ function mintAmountToRecipient(uint256 editionId, address recipient, uint256 amount) external returns (uint256); /** * @notice Mints one NFT each to a number of recipients * @param editionId Edition to mint the NFTs on * @param recipients Recipients of minted NFTs */ function mintOneToRecipients(uint256 editionId, address[] memory recipients) external returns (uint256); /** * @notice Mints an amount of NFTs each to a number of recipients * @param editionId Edition to mint the NFTs on * @param recipients Recipients of minted NFTs * @param amount Amount of NFTs minted per recipient */ function mintAmountToRecipients( uint256 editionId, address[] memory recipients, uint256 amount ) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; /** * @author highlight.xyz * @notice If token managers implement this, transfer actions will call * postBurn on the token manager. */ interface IPostBurn { /** * @notice Hook called by contract after burn, if token manager of burned token implements this * interface. * @param operator Operator burning tokens * @param sender Msg sender * @param id Burned token's id or id of edition of token that is burned */ function postBurn(address operator, address sender, uint256 id) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import { IOperatorFilterRegistry } from "./interfaces/IOperatorFilterRegistry.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /** * @title MarketplaceFilterer * @notice Abstract contract whose constructor automatically registers and subscribes to default subscription from OpenSea, if a valid registry is passed in. Slightly modified from `OperatorFilterer` contract by ishan@ highlight.xyz. * @dev This smart contract is meant to be inherited by token contracts so they can use the following: * - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods. * - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods. */ abstract contract MarketplaceFilterer is OwnableUpgradeable { error NotAContract(); error OperatorNotAllowed(address operator); /** * @notice MarketplaceFilterer Registry (CORI) */ address public constant MARKETPLACE_FILTERER_REGISTRY = address(0x000000000000AAeB6D7670E522A718067333cd4E); /** * @notice Default subscription to register collection with on CORI Marketplace filterer registry */ address public constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6); /** * @notice CORI Marketplace filterer registry. Set to address(0) when not used to avoid extra inter-contract calls. */ address public operatorFiltererRegistry; /** * @notice Update the address that the contract will make MarketplaceFilterer checks against. * Also register this contract with that registry. */ function setMarketplaceFiltererRegistryAndRegisterDefaultSubscription() public onlyOwner { _setMarketplaceFiltererRegistryAndRegisterDefaultSubscription(MARKETPLACE_FILTERER_REGISTRY); } /** * @notice Update the address that the contract will make MarketplaceFilterer checks against. * Also register this contract with that registry. */ function setCustomMarketplaceFiltererRegistryAndRegisterDefaultSubscription(address newRegistry) public onlyOwner { if (newRegistry.code.length == 0) { _revert(NotAContract.selector); } _setMarketplaceFiltererRegistryAndRegisterDefaultSubscription(newRegistry); } /** * @notice Remove the address that the contract will make MarketplaceFilterer checks against. * Also unregister this contract from that registry. */ function removeMarketplaceFiltererRegistryAndUnregister() public onlyOwner { if (operatorFiltererRegistry.code.length > 0) { IOperatorFilterRegistry(operatorFiltererRegistry).unregister(address(this)); } operatorFiltererRegistry = address(0); } function __MarketplaceFilterer__init__(bool useFilterer) internal onlyInitializing { // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. if (useFilterer) { _setMarketplaceFiltererRegistryAndRegisterDefaultSubscription(MARKETPLACE_FILTERER_REGISTRY); } } function _setMarketplaceFiltererRegistryAndRegisterDefaultSubscription(address newRegistry) private { operatorFiltererRegistry = newRegistry; if (newRegistry.code.length > 0) { IOperatorFilterRegistry(newRegistry).registerAndSubscribe(address(this), DEFAULT_SUBSCRIPTION); } } modifier onlyAllowedOperator(address from) virtual { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from != _msgSender()) { _checkFilterOperator(_msgSender()); } _; } modifier onlyAllowedOperatorApproval(address operator) virtual { _checkFilterOperator(operator); _; } function _checkFilterOperator(address operator) internal view virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (operatorFiltererRegistry != address(0)) { if (!IOperatorFilterRegistry(operatorFiltererRegistry).isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure virtual { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity 0.8.10; import "./IERC721AUpgradeable.sol"; import { ERC721AStorage } from "./ERC721AStorage.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; /* solhint-disable */ /** * @dev Interface of ERC721 token receiver. */ interface ERC721A__IERC721ReceiverUpgradeable { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @title ERC721A * @author Chiru Labs, modified by [email protected] * * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) * Non-Fungible Token Standard, including the Metadata extension. * Optimized for lower gas during batch mints. * * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...) * starting from `_startTokenId()`. * * Assumptions: * * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721AUpgradeable is Initializable, IERC721AUpgradeable, ContextUpgradeable { using ERC721AStorage for ERC721AStorage.Layout; // ============================================================= // CONSTANTS // ============================================================= // Mask of an entry in packed address data. uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant _BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant _BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant _BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant _BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant _BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant _BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225; // The bit position of `extraData` in packed ownership. uint256 private constant _BITPOS_EXTRA_DATA = 232; // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`. uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1; // The mask of the lower 160 bits for addresses. uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; // The maximum `quantity` that can be minted with {_mintERC2309}. // This limit is to prevent overflows on the address data entries. // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309} // is required to cause an overflow, which is unrealistic. uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000; // The `Transfer` event signature is given by: // `keccak256(bytes("Transfer(address,address,uint256)"))`. bytes32 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; // ============================================================= // CONSTRUCTOR // ============================================================= function __ERC721A_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC721A_init_unchained(name_, symbol_); } function __ERC721A_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { ERC721AStorage.layout()._name = name_; ERC721AStorage.layout()._symbol = symbol_; ERC721AStorage.layout()._currentIndex = _startTokenId(); } // ============================================================= // TOKEN COUNTING OPERATIONS // ============================================================= /** * @dev Returns the starting token ID. * To change the starting token ID, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 1; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view virtual returns (uint256) { return ERC721AStorage.layout()._currentIndex; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() public view virtual override returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented // more than `_currentIndex - _startTokenId()` times. unchecked { return ERC721AStorage.layout()._currentIndex - ERC721AStorage.layout()._burnCounter - _startTokenId(); } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view virtual returns (uint256) { // Counter underflow is impossible as `_currentIndex` does not decrement, // and it is initialized to `_startTokenId()`. unchecked { return ERC721AStorage.layout()._currentIndex - _startTokenId(); } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view virtual returns (uint256) { return ERC721AStorage.layout()._burnCounter; } // ============================================================= // ADDRESS DATA OPERATIONS // ============================================================= /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) public view virtual override returns (uint256) { if (owner == address(0)) _revert(BalanceQueryForZeroAddress.selector); return ERC721AStorage.layout()._packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_AUX); } /** * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal virtual { uint256 packed = ERC721AStorage.layout()._packedAddressData[owner]; uint256 auxCasted; // Cast `aux` with assembly to avoid redundant masking. assembly { auxCasted := aux } packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX); ERC721AStorage.layout()._packedAddressData[owner] = packed; } // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes // of the XOR of all function selectors in the interface. // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165) // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`) return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return ERC721AStorage.layout()._name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return ERC721AStorage.layout()._symbol; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, "/", _toString(tokenId))) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } // ============================================================= // OWNERSHIPS OPERATIONS // ============================================================= /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @dev Added by Highlight to facilitate updating of name and symbol */ function _setContractMetadata(string calldata newName, string calldata newSymbol) internal { ERC721AStorage.layout()._name = newName; ERC721AStorage.layout()._symbol = newSymbol; } /** * @dev Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around over time. */ function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(ERC721AStorage.layout()._packedOwnerships[index]); } /** * @dev Returns whether the ownership slot at `index` is initialized. * An uninitialized slot does not necessarily mean that the slot has no owner. */ function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) { return ERC721AStorage.layout()._packedOwnerships[index] != 0; } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal virtual { if (ERC721AStorage.layout()._packedOwnerships[index] == 0) { ERC721AStorage.layout()._packedOwnerships[index] = _packedOwnershipOf(index); } } /** * Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) { if (_startTokenId() <= tokenId) { packed = ERC721AStorage.layout()._packedOwnerships[tokenId]; // If the data at the starting slot does not exist, start the scan. if (packed == 0) { if (tokenId >= ERC721AStorage.layout()._currentIndex) _revert(OwnerQueryForNonexistentToken.selector); // Invariant: // There will always be an initialized ownership slot // (i.e. `ownership.addr != address(0) && ownership.burned == false`) // before an unintialized ownership slot // (i.e. `ownership.addr == address(0) && ownership.burned == false`) // Hence, `tokenId` will not underflow. // // We can directly compare the packed value. // If the address is zero, packed will be zero. for (;;) { unchecked { packed = ERC721AStorage.layout()._packedOwnerships[--tokenId]; } if (packed == 0) continue; if (packed & _BITMASK_BURNED == 0) return packed; // Otherwise, the token is burned, and we must revert. // This handles the case of batch burned tokens, where only the burned bit // of the starting slot is set, and remaining slots are left uninitialized. _revert(OwnerQueryForNonexistentToken.selector); } } // Otherwise, the data exists and we can skip the scan. // This is possible because we have already achieved the target condition. // This saves 2143 gas on transfers of initialized tokens. // If the token is not burned, return `packed`. Otherwise, revert. if (packed & _BITMASK_BURNED == 0) return packed; } _revert(OwnerQueryForNonexistentToken.selector); } /** * @dev Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP); ownership.burned = packed & _BITMASK_BURNED != 0; ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA); } /** * @dev Packs ownership data into a single uint256. */ function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`. result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)) } } /** * @dev Returns the `nextInitialized` flag set if `quantity` equals 1. */ function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) { // For branchless setting of the `nextInitialized` flag. assembly { // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`. result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1)) } } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}. * * Requirements: * * - The caller must own the token or be an approved operator. */ function approve(address to, uint256 tokenId) public payable virtual override { _approve(to, tokenId, true); } /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector); return ERC721AStorage.layout()._tokenApprovals[tokenId].value; } /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) public virtual override { ERC721AStorage.layout()._operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), operator, approved); } /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return ERC721AStorage.layout()._operatorApprovals[owner][operator]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted. See {_mint}. */ function _exists(uint256 tokenId) internal view virtual returns (bool result) { if (_startTokenId() <= tokenId) { if (tokenId < ERC721AStorage.layout()._currentIndex) { uint256 packed; while ((packed = ERC721AStorage.layout()._packedOwnerships[tokenId]) == 0) --tokenId; result = packed & _BITMASK_BURNED == 0; } } } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ownerOf(tokenId); return (isApprovedForAll(owner, spender) || _isSenderApprovedOrOwner(getApproved(tokenId), owner, spender)); } /** * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`. */ function _isSenderApprovedOrOwner( address approvedAddress, address owner, address msgSender ) private pure returns (bool result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean. msgSender := and(msgSender, _BITMASK_ADDRESS) // `msgSender == owner || msgSender == approvedAddress`. result := or(eq(msgSender, owner), eq(msgSender, approvedAddress)) } } /** * @dev Returns the storage slot and value for the approved address of `tokenId`. */ function _getApprovedSlotAndAddress( uint256 tokenId ) private view returns (uint256 approvedAddressSlot, address approvedAddress) { ERC721AStorage.TokenApprovalRef storage tokenApproval = ERC721AStorage.layout()._tokenApprovals[tokenId]; // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`. assembly { approvedAddressSlot := tokenApproval.slot approvedAddress := sload(approvedAddressSlot) } } // ============================================================= // TRANSFER OPERATIONS // ============================================================= /** * @dev Transfers `tokenId` from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) public payable virtual override { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); // Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean. from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS)); if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // We can directly increment and decrement the balances. --ERC721AStorage.layout()._packedAddressData[from]; // Updates: `balance -= 1`. ++ERC721AStorage.layout()._packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData( to, _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != ERC721AStorage.layout()._currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. from, // `from`. toMasked, // `to`. tokenId // `tokenId`. ) } if (toMasked == 0) _revert(TransferToZeroAddress.selector); _afterTokenTransfers(from, to, tokenId); } /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom(address from, address to, uint256 tokenId) public payable virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public payable virtual override { transferFrom(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } /** * @dev Hook that is called after a set of serially-ordered token IDs * have been transferred. This includes minting. * And also called after one token has been burned. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers(address from, address to, uint256 startTokenId) internal virtual {} /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * `from` - Previous owner of the given token ID. * `to` - Target address that will receive the token. * `tokenId` - Token ID to be transferred. * `_data` - Optional data to send along with the call. * * Returns whether the call correctly returned the expected magic value. */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (bytes4 retval) { return retval == ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { _revert(TransferToNonERC721ReceiverImplementer.selector); } assembly { revert(add(32, reason), mload(reason)) } } } // ============================================================= // MINT OPERATIONS // ============================================================= /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event for each mint. */ function _mint(address to, uint256 quantity) internal virtual { uint256 startTokenId = ERC721AStorage.layout()._currentIndex; if (quantity == 0) _revert(MintZeroQuantity.selector); // Overflows are incredibly unrealistic. // `balance` and `numberMinted` have a maximum limit of 2**64. // `tokenId` has a maximum limit of 2**256. unchecked { // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; if (toMasked == 0) _revert(MintToZeroAddress.selector); uint256 end = startTokenId + quantity; uint256 tokenId = startTokenId; do { assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. tokenId // `tokenId`. ) } // The `!=` check ensures that large values of `quantity` // that overflows uint256 will make the loop run out of gas. } while (++tokenId != end); ERC721AStorage.layout()._currentIndex = end; } } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * See {_mint}. * * Emits a {Transfer} event for each mint. */ function _safeMint(address to, uint256 quantity, bytes memory _data) internal virtual { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = ERC721AStorage.layout()._currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } while (index < end); // Reentrancy protection. if (ERC721AStorage.layout()._currentIndex != end) _revert(bytes4(0)); } } } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal virtual { _safeMint(to, quantity, ""); } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Equivalent to `_approve(to, tokenId, false)`. */ function _approve(address to, uint256 tokenId) internal virtual { _approve(to, tokenId, false); } /** * @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: * * - `tokenId` must exist. * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId, bool approvalCheck) internal virtual { address owner = ownerOf(tokenId); if (approvalCheck && _msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { _revert(ApprovalCallerNotOwnerNorApproved.selector); } ERC721AStorage.layout()._tokenApprovals[tokenId].value = to; emit Approval(owner, to, tokenId); } // ============================================================= // BURN OPERATIONS // ============================================================= /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); if (approvalCheck) { // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); } // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`. ERC721AStorage.layout()._packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData( from, (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != ERC721AStorage.layout()._currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, address(0), tokenId); // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times. unchecked { ERC721AStorage.layout()._burnCounter++; } } // ============================================================= // EXTRA DATA OPERATIONS // ============================================================= /** * @dev Directly sets the extra data for the ownership data `index`. */ function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual { uint256 packed = ERC721AStorage.layout()._packedOwnerships[index]; if (packed == 0) _revert(OwnershipNotInitializedForExtraData.selector); uint256 extraDataCasted; // Cast `extraData` with assembly to avoid redundant masking. assembly { extraDataCasted := extraData } packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA); ERC721AStorage.layout()._packedOwnerships[index] = packed; } /** * @dev Called during each token transfer to set the 24bit `extraData` field. * Intended to be overridden by the cosumer contract. * * `previousExtraData` - the value of `extraData` before transfer. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _extraData(address from, address to, uint24 previousExtraData) internal view virtual returns (uint24) {} /** * @dev Returns the next extra data for the packed ownership data. * The returned result is shifted into position. */ function _nextExtraData(address from, address to, uint256 prevOwnershipPacked) private view returns (uint256) { uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA); return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA; } // ============================================================= // OTHER OPERATIONS // ============================================================= /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a uint256 to its ASCII string decimal representation. */ function _toString(uint256 value) internal pure virtual returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0. let m := add(mload(0x40), 0xa0) // Update the free memory pointer to allocate. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure virtual { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Interfaces with the details of editions on collections * @author highlight.xyz */ interface IEditionCollection { /** * @notice Edition details * @param name Edition name * @param size Edition size * @param supply Total number of tokens minted on edition * @param initialTokenId Token id of first token minted in edition */ struct EditionDetails { string name; uint256 size; uint256 supply; uint256 initialTokenId; } /** * @notice Get the edition a token belongs to * @param tokenId The token id of the token */ function getEditionId(uint256 tokenId) external view returns (uint256); /** * @notice Get an edition's details * @param editionId Edition id */ function getEditionDetails(uint256 editionId) external view returns (EditionDetails memory); /** * @notice Get the details and uris of a number of editions * @param editionIds List of editions to get info for */ function getEditionsDetailsAndUri( uint256[] calldata editionIds ) external view returns (EditionDetails[] memory, string[] memory uris); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "../royaltyManager/interfaces/IRoyaltyManager.sol"; import "../tokenManager/interfaces/ITokenManager.sol"; import "../utils/Ownable.sol"; import "../utils/ERC2981/IERC2981Upgradeable.sol"; import "../metatx/ERC2771ContextUpgradeable.sol"; import "../observability/IObservability.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "../utils/ERC165/ERC165CheckerUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; /** * @title Minimized Base ERC721 * @author highlight.xyz * @notice Core piece of Highlight NFT contracts (V2), branch for ERC721SingleEdition */ abstract contract ERC721MinimizedBase is OwnableUpgradeable, IERC2981Upgradeable, ERC2771ContextUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { using EnumerableSet for EnumerableSet.AddressSet; using ERC165CheckerUpgradeable for address; /** * @notice Throw when token or royalty manager is invalid */ error InvalidManager(); /** * @notice Throw when token or royalty manager does not exist */ error ManagerDoesNotExist(); /** * @notice Throw when sender is unauthorized to perform action */ error Unauthorized(); /** * @notice Throw when sender is not a minter */ error NotMinter(); /** * @notice Throw when token manager or royalty manager swap is blocked */ error ManagerSwapBlocked(); /** * @notice Throw when token manager or royalty manager remove is blocked */ error ManagerRemoveBlocked(); /** * @notice Throw when setting default or granular royalty is blocked */ error RoyaltySetBlocked(); /** * @notice Throw when royalty BPS is invalid */ error RoyaltyBPSInvalid(); /** * @notice Throw when minter registration is invalid */ error MinterRegistrationInvalid(); /** * @notice Set of minters allowed to mint on contract */ EnumerableSet.AddressSet internal _minters; /** * @notice Global token/edition manager default */ address public defaultManager; /** * @notice Default royalty for entire contract */ IRoyaltyManager.Royalty internal _defaultRoyalty; /** * @notice Royalty manager - optional contract that defines the conditions around setting royalties */ address public royaltyManager; /** * @notice Freezes minting on smart contract forever */ uint8 internal _mintFrozen; /** * @notice Observability contract */ IObservability public observability; /** * @notice Emitted when minter is registered or unregistered * @param minter Minter that was changed * @param registered True if the minter was registered, false if unregistered */ event MinterRegistrationChanged(address indexed minter, bool indexed registered); /** * @notice Emitted when default token manager changed * @param newDefaultTokenManager New default token manager. Zero address if old one was removed */ event DefaultTokenManagerChanged(address indexed newDefaultTokenManager); /** * @notice Emitted when default royalty is set * @param recipientAddress Royalty recipient * @param royaltyPercentageBPS Percentage of sale (in basis points) owed to royalty recipient */ event DefaultRoyaltySet(address indexed recipientAddress, uint16 indexed royaltyPercentageBPS); /** * @notice Emitted when royalty manager is updated * @param newRoyaltyManager New royalty manager. Zero address if old one was removed */ event RoyaltyManagerChanged(address indexed newRoyaltyManager); /** * @notice Emitted when mints are frozen permanently */ event MintsFrozen(); /** * @notice Restricts calls to minters */ modifier onlyMinter() { if (!_minters.contains(_msgSender())) { _revert(NotMinter.selector); } _; } /** * @notice Restricts calls if input royalty bps is over 10000 */ modifier royaltyValid(uint16 _royaltyBPS) { if (_royaltyBPS > 10000) { _revert(RoyaltyBPSInvalid.selector); } _; } /** * @notice Registers a minter * @param minter New minter */ function registerMinter(address minter) external onlyOwner nonReentrant { if (!_minters.add(minter)) { _revert(MinterRegistrationInvalid.selector); } emit MinterRegistrationChanged(minter, true); observability.emitMinterRegistrationChanged(minter, true); } /** * @notice Unregisters a minter * @param minter Minter to unregister */ function unregisterMinter(address minter) external onlyOwner nonReentrant { if (!_minters.remove(minter)) { _revert(MinterRegistrationInvalid.selector); } emit MinterRegistrationChanged(minter, false); observability.emitMinterRegistrationChanged(minter, false); } /** * @notice Set default token manager if current token manager allows it * @param _defaultTokenManager New default token manager */ function setDefaultTokenManager(address _defaultTokenManager) external nonReentrant { if (!_isValidTokenManager(_defaultTokenManager)) { _revert(InvalidManager.selector); } address msgSender = _msgSender(); address currentTokenManager = defaultManager; if (currentTokenManager == address(0)) { if (msgSender != owner()) { _revert(Unauthorized.selector); } } else { if (!ITokenManager(currentTokenManager).canSwap(msgSender, 0, _defaultTokenManager)) { _revert(ManagerSwapBlocked.selector); } } defaultManager = _defaultTokenManager; emit DefaultTokenManagerChanged(_defaultTokenManager); observability.emitDefaultTokenManagerChanged(_defaultTokenManager); } /** * @notice Removes default token manager if current token manager allows it */ function removeDefaultTokenManager() external nonReentrant { address msgSender = _msgSender(); address currentTokenManager = defaultManager; if (currentTokenManager == address(0)) { _revert(ManagerDoesNotExist.selector); } if (!ITokenManager(currentTokenManager).canRemoveItself(msgSender, 0)) { _revert(ManagerRemoveBlocked.selector); } defaultManager = address(0); emit DefaultTokenManagerChanged(address(0)); observability.emitDefaultTokenManagerChanged(address(0)); } /** * @notice Sets default royalty if royalty manager allows it * @param _royalty New default royalty */ function setDefaultRoyalty( IRoyaltyManager.Royalty calldata _royalty ) external nonReentrant royaltyValid(_royalty.royaltyPercentageBPS) { address msgSender = _msgSender(); address _royaltyManager = royaltyManager; if (_royaltyManager == address(0)) { if (msgSender != owner()) { _revert(Unauthorized.selector); } } else { if (!IRoyaltyManager(_royaltyManager).canSetDefaultRoyalty(_royalty, msgSender)) { _revert(RoyaltySetBlocked.selector); } } _defaultRoyalty = _royalty; emit DefaultRoyaltySet(_royalty.recipientAddress, _royalty.royaltyPercentageBPS); observability.emitDefaultRoyaltySet(_royalty.recipientAddress, _royalty.royaltyPercentageBPS); } /** * @notice Sets royalty manager if current one allows it * @param _royaltyManager New royalty manager */ function setRoyaltyManager(address _royaltyManager) external nonReentrant { if (!_isValidRoyaltyManager(_royaltyManager)) { _revert(InvalidManager.selector); } address msgSender = _msgSender(); address currentRoyaltyManager = royaltyManager; if (currentRoyaltyManager == address(0)) { if (msgSender != owner()) { _revert(Unauthorized.selector); } } else { if (!IRoyaltyManager(currentRoyaltyManager).canSwap(_royaltyManager, msgSender)) { _revert(ManagerSwapBlocked.selector); } } royaltyManager = _royaltyManager; emit RoyaltyManagerChanged(_royaltyManager); observability.emitRoyaltyManagerChanged(_royaltyManager); } /** * @notice Removes royalty manager if current one allows it */ function removeRoyaltyManager() external nonReentrant { address msgSender = _msgSender(); address currentRoyaltyManager = royaltyManager; if (currentRoyaltyManager == address(0)) { _revert(ManagerDoesNotExist.selector); } if (!IRoyaltyManager(currentRoyaltyManager).canRemoveItself(msgSender)) { _revert(ManagerRemoveBlocked.selector); } royaltyManager = address(0); emit RoyaltyManagerChanged(address(0)); observability.emitRoyaltyManagerChanged(address(0)); } /** * @notice Freeze mints on contract forever */ function freezeMints() external onlyOwner nonReentrant { _mintFrozen = 1; emit MintsFrozen(); observability.emitMintsFrozen(); } /** * @notice Return allowed minters on contract */ function minters() external view returns (address[] memory) { return _minters.values(); } /** * @notice Conforms to ERC-2981. Editions should overwrite to return royalty for entire edition * @param // Edition id * @param _salePrice Sale price of token */ function royaltyInfo( uint256 /* _tokenGroupingId */, uint256 _salePrice ) public view virtual override returns (address receiver, uint256 royaltyAmount) { IRoyaltyManager.Royalty memory royalty = _defaultRoyalty; receiver = royalty.recipientAddress; royaltyAmount = (_salePrice * uint256(royalty.royaltyPercentageBPS)) / 10000; } /** * @notice Returns the token manager for the id passed in. * @param // Token ID or Edition ID for Editions implementing contracts */ function tokenManager(uint256 /* id */) public view returns (address manager) { return defaultManager; } /** * @notice Initializes the contract, setting the creator as the initial owner. * @param creator Contract creator * @param defaultRoyalty Default royalty for the contract * @param _defaultTokenManager Default token manager for the contract */ function __ERC721MinimizedBase_initialize( address creator, IRoyaltyManager.Royalty memory defaultRoyalty, address _defaultTokenManager ) internal onlyInitializing royaltyValid(defaultRoyalty.royaltyPercentageBPS) { __Ownable_init(); __ReentrancyGuard_init(); _transferOwnership(creator); _defaultRoyalty = defaultRoyalty; defaultManager = _defaultTokenManager; } /** * @notice See {UUPSUpgradeable-_authorizeUpgrade} * @param // New implementation to upgrade to */ function _authorizeUpgrade(address) internal override { revert("Not upgradeable"); } /** * @notice Returns true if address is a valid tokenManager * @param _tokenManager Token manager being checked */ function _isValidTokenManager(address _tokenManager) internal view returns (bool) { return _tokenManager.supportsInterface(type(ITokenManager).interfaceId); } /** * @notice Returns true if address is a valid royaltyManager * @param _royaltyManager Royalty manager being checked */ function _isValidRoyaltyManager(address _royaltyManager) internal view returns (bool) { return _royaltyManager.supportsInterface(type(IRoyaltyManager).interfaceId); } /** * @notice Used for meta-transactions */ function _msgSender() internal view virtual override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (address sender) { return ERC2771ContextUpgradeable._msgSender(); } /** * @notice Used for meta-transactions */ function _msgData() internal view virtual override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (bytes calldata) { return ERC2771ContextUpgradeable._msgData(); } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure virtual { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (metatx/ERC2771Context.sol) pragma solidity 0.8.10; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @dev Context variant with ERC2771 support. * Openzeppelin contract slightly modified by ishan@ highlight.xyz to be upgradeable. */ abstract contract ERC2771ContextUpgradeable is Initializable { address private _trustedForwarder; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; function isTrustedForwarder(address forwarder) public view virtual returns (bool) { return forwarder == _trustedForwarder; } function __ERC2771ContextUpgradeable__init__(address trustedForwarder) internal onlyInitializing { _trustedForwarder = trustedForwarder; } function _msgSender() internal view virtual returns (address sender) { if (isTrustedForwarder(msg.sender)) { // The assembly code is more direct than the Solidity version using `abi.decode`. /* solhint-disable no-inline-assembly */ assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } /* solhint-enable no-inline-assembly */ } else { return msg.sender; } } function _msgData() internal view virtual returns (bytes calldata) { if (isTrustedForwarder(msg.sender)) { return msg.data[:msg.data.length - 20]; } else { return msg.data; } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "../royaltyManager/interfaces/IRoyaltyManager.sol"; /** * @title IObservability * @author highlight.xyz * @notice Interface to interact with the Highlight observability singleton * @dev Singleton to coalesce select Highlight protocol events */ interface IObservability { /************************** ERC721Base / ERC721MinimizedBase events **************************/ /** * @notice Emitted when minter is registered or unregistered * @param contractAddress Initial contract that emitted event * @param minter Minter that was changed * @param registered True if the minter was registered, false if unregistered */ event MinterRegistrationChanged(address indexed contractAddress, address indexed minter, bool indexed registered); /** * @notice Emitted when token managers are set for token/edition ids * @param contractAddress Initial contract that emitted event * @param _ids Edition / token ids * @param _tokenManagers Token managers to set for tokens / editions */ event GranularTokenManagersSet(address indexed contractAddress, uint256[] _ids, address[] _tokenManagers); /** * @notice Emitted when token managers are removed for token/edition ids * @param contractAddress Initial contract that emitted event * @param _ids Edition / token ids to remove token managers for */ event GranularTokenManagersRemoved(address indexed contractAddress, uint256[] _ids); /** * @notice Emitted when default token manager changed * @param contractAddress Initial contract that emitted event * @param newDefaultTokenManager New default token manager. Zero address if old one was removed */ event DefaultTokenManagerChanged(address indexed contractAddress, address indexed newDefaultTokenManager); /** * @notice Emitted when default royalty is set * @param contractAddress Initial contract that emitted event * @param recipientAddress Royalty recipient * @param royaltyPercentageBPS Percentage of sale (in basis points) owed to royalty recipient */ event DefaultRoyaltySet( address indexed contractAddress, address indexed recipientAddress, uint16 indexed royaltyPercentageBPS ); /** * @notice Emitted when royalties are set for edition / token ids * @param contractAddress Initial contract that emitted event * @param ids Token / edition ids * @param _newRoyalties New royalties for each token / edition */ event GranularRoyaltiesSet(address indexed contractAddress, uint256[] ids, IRoyaltyManager.Royalty[] _newRoyalties); /** * @notice Emitted when royalty manager is updated * @param contractAddress Initial contract that emitted event * @param newRoyaltyManager New royalty manager. Zero address if old one was removed */ event RoyaltyManagerChanged(address indexed contractAddress, address indexed newRoyaltyManager); /** * @notice Emitted when mints are frozen permanently * @param contractAddress Initial contract that emitted event */ event MintsFrozen(address indexed contractAddress); /** * @notice Emitted when contract metadata is set * @param contractAddress Initial contract that emitted event * @param name New name * @param symbol New symbol * @param contractURI New contract uri */ event ContractMetadataSet(address indexed contractAddress, string name, string symbol, string contractURI); /************************** ERC721General events **************************/ /** * @notice Emitted when hashed metadata config is set * @param contractAddress Initial contract that emitted event * @param hashedURIData Hashed uri data * @param hashedRotationData Hashed rotation key * @param _supply Supply of tokens to mint w/ reveal */ event HashedMetadataConfigSet( address indexed contractAddress, bytes hashedURIData, bytes hashedRotationData, uint256 indexed _supply ); /** * @notice Emitted when metadata is revealed * @param contractAddress Initial contract that emitted event * @param key Key used to decode hashed data * @param newRotationKey Actual rotation key to be used */ event Revealed(address indexed contractAddress, bytes key, uint256 newRotationKey); /************************** ERC721GeneralBase events **************************/ /** * @notice Emitted when uris are set for tokens * @param contractAddress Initial contract that emitted event * @param ids IDs of tokens to set uris for * @param uris Uris to set on tokens */ event TokenURIsSet(address indexed contractAddress, uint256[] ids, string[] uris); /** * @notice Emitted when limit supply is set * @param contractAddress Initial contract that emitted event * @param newLimitSupply Limit supply to set */ event LimitSupplySet(address indexed contractAddress, uint256 indexed newLimitSupply); /************************** ERC721StorageUri events **************************/ /** * @notice Emits when a series collection has its base uri set * @param contractAddress Contract with updated base uri * @param newBaseUri New base uri */ event BaseUriSet(address indexed contractAddress, string newBaseUri); /************************** ERC721Editions / ERC721SingleEdition events **************************/ // Not adding EditionCreated, EditionMintedToOneRecipient, EditionMintedToRecipients // EditionCreated - handled by MetadataInitialized // EditionMintedToOneRecipient / EditionMintedToRecipients - handled via mint module events /************************** Deployment events **************************/ /** * @notice Emitted when Generative Series contract is deployed * @param deployer Contract deployer * @param contractAddress Address of contract that was deployed */ event GenerativeSeriesDeployed(address indexed deployer, address indexed contractAddress); /** * @notice Emitted when Series contract is deployed * @param deployer Contract deployer * @param contractAddress Address of contract that was deployed */ event SeriesDeployed(address indexed deployer, address indexed contractAddress); /** * @notice Emitted when MultipleEditions contract is deployed * @param deployer Contract deployer * @param contractAddress Address of contract that was deployed */ event MultipleEditionsDeployed(address indexed deployer, address indexed contractAddress); /** * @notice Emitted when SingleEdition contract is deployed * @param deployer Contract deployer * @param contractAddress Address of contract that was deployed */ event SingleEditionDeployed(address indexed deployer, address indexed contractAddress); /************************** ERC721 events **************************/ /** * @notice Emitted when `tokenId` token is transferred from `from` to `to` on contractAddress * @param contractAddress NFT contract token resides on * @param from Token sender * @param to Token receiver * @param tokenId Token being sent */ event Transfer(address indexed contractAddress, address indexed from, address to, uint256 indexed tokenId); /** * @notice Emit MinterRegistrationChanged */ function emitMinterRegistrationChanged(address minter, bool registered) external; /** * @notice Emit GranularTokenManagersSet */ function emitGranularTokenManagersSet(uint256[] calldata _ids, address[] calldata _tokenManagers) external; /** * @notice Emit GranularTokenManagersRemoved */ function emitGranularTokenManagersRemoved(uint256[] calldata _ids) external; /** * @notice Emit DefaultTokenManagerChanged */ function emitDefaultTokenManagerChanged(address newDefaultTokenManager) external; /** * @notice Emit DefaultRoyaltySet */ function emitDefaultRoyaltySet(address recipientAddress, uint16 royaltyPercentageBPS) external; /** * @notice Emit GranularRoyaltiesSet */ function emitGranularRoyaltiesSet( uint256[] calldata ids, IRoyaltyManager.Royalty[] calldata _newRoyalties ) external; /** * @notice Emit RoyaltyManagerChanged */ function emitRoyaltyManagerChanged(address newRoyaltyManager) external; /** * @notice Emit MintsFrozen */ function emitMintsFrozen() external; /** * @notice Emit ContractMetadataSet */ function emitContractMetadataSet( string calldata name, string calldata symbol, string calldata contractURI ) external; /** * @notice Emit HashedMetadataConfigSet */ function emitHashedMetadataConfigSet( bytes calldata hashedURIData, bytes calldata hashedRotationData, uint256 _supply ) external; /** * @notice Emit Revealed */ function emitRevealed(bytes calldata key, uint256 newRotationKey) external; /** * @notice Emit TokenURIsSet */ function emitTokenURIsSet(uint256[] calldata ids, string[] calldata uris) external; /** * @notice Emit LimitSupplySet */ function emitLimitSupplySet(uint256 newLimitSupply) external; /** * @notice Emit BaseUriSet */ function emitBaseUriSet(string calldata newBaseUri) external; /** * @notice Emit GenerativeSeriesDeployed */ function emitGenerativeSeriesDeployed(address contractAddress) external; /** * @notice Emit SeriesDeployed */ function emitSeriesDeployed(address contractAddress) external; /** * @notice Emit MultipleEditionsDeployed */ function emitMultipleEditionsDeployed(address contractAddress) external; /** * @notice Emit SingleEditionDeployed */ function emitSingleEditionDeployed(address contractAddress) external; /** * @notice Emit Transfer */ function emitTransfer(address from, address to, uint256 tokenId) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @title ITokenManager * @author highlight.xyz * @notice Enables interfacing with custom token managers */ interface ITokenManager { /** * @notice Returns whether metadata updater is allowed to update * @param sender Updater * @param id Token/edition who's uri is being updated * If id is 0, implementation should decide behaviour for base uri update * @param newData Token's new uri if called by general contract, and any metadata field if called by editions * @return If invocation can update metadata */ function canUpdateMetadata(address sender, uint256 id, bytes calldata newData) external returns (bool); /** * @notice Returns whether token manager can be swapped for another one by invocator * @notice Default token manager implementations should ignore id * @param sender Swapper * @param id Token grouping id (token id or edition id) * @param newTokenManager New token manager being swapped to * @return If invocation can swap token managers */ function canSwap(address sender, uint256 id, address newTokenManager) external returns (bool); /** * @notice Returns whether token manager can be removed * @notice Default token manager implementations should ignore id * @param sender Swapper * @param id Token grouping id (token id or edition id) * @return If invocation can remove token manager */ function canRemoveItself(address sender, uint256 id) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; /* solhint-disable */ library ERC721AStorage { // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364). struct TokenApprovalRef { address value; } struct Layout { // ============================================================= // STORAGE // ============================================================= // The next token ID to be minted. uint256 _currentIndex; // The number of tokens burned. uint256 _burnCounter; // Token name string _name; // Token symbol string _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. // See {_packedOwnershipOf} implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` // - [232..255] `extraData` mapping(uint256 => uint256) _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) _packedAddressData; // Mapping from token ID to approved address. mapping(uint256 => ERC721AStorage.TokenApprovalRef) _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) _operatorApprovals; } bytes32 internal constant STORAGE_SLOT = keccak256("ERC721A.contracts.storage.ERC721A"); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity 0.8.10; /* solhint-disable */ /** * @dev Interface of ERC721A. */ interface IERC721AUpgradeable { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom(address from, address to, uint256 tokenId) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external payable; /** * @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 payable; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @title IRoyaltyManager * @author highlight.xyz * @notice Enables interfacing with custom royalty managers that define conditions on setting royalties for * NFT contracts */ interface IRoyaltyManager { /** * @notice Struct containing values required to adhere to ERC-2981 * @param recipientAddress Royalty recipient - can be EOA, royalty splitter contract, etc. * @param royaltyPercentageBPS Royalty cut, in basis points */ struct Royalty { address recipientAddress; uint16 royaltyPercentageBPS; } /** * @notice Defines conditions around being able to swap royalty manager for another one * @param newRoyaltyManager New royalty manager being swapped in * @param sender msg sender */ function canSwap(address newRoyaltyManager, address sender) external view returns (bool); /** * @notice Defines conditions around being able to remove current royalty manager * @param sender msg sender */ function canRemoveItself(address sender) external view returns (bool); /** * @notice Defines conditions around being able to set granular royalty (per token or per edition) * @param id Edition / token ID whose royalty is being set * @param royalty Royalty being set * @param sender msg sender */ function canSetGranularRoyalty(uint256 id, Royalty calldata royalty, address sender) external view returns (bool); /** * @notice Defines conditions around being able to set default royalty * @param royalty Royalty being set * @param sender msg sender */ function canSetDefaultRoyalty(Royalty calldata royalty, address sender) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol) pragma solidity 0.8.10; import "./IERC165Upgradeable.sol"; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ /* solhint-disable */ library ERC165CheckerUpgradeable { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; /** * @dev Returns true if `account` supports the {IERC165} interface, */ function supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return supportsERC165InterfaceUnchecked(account, type(IERC165Upgradeable).interfaceId) && !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId); } /** * @dev Returns a boolean array where each value corresponds to the * interfaces passed in and whether they're supported or not. This allows * you to batch check interfaces for a contract where your expectation * is that some interfaces may not be supported. * * See {IERC165-supportsInterface}. * * _Available since v3.4._ */ function getSupportedInterfaces( address account, bytes4[] memory interfaceIds ) internal view returns (bool[] memory) { // an array of booleans corresponding to interfaceIds and whether they're supported or not bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); // query support of ERC165 itself if (supportsERC165(account)) { // query support of each interface in interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]); } } return interfaceIdsSupported; } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with {supportsERC165}. * Interface identification is specified in ERC-165. */ function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) { // prepare call bytes memory encodedParams = abi.encodeWithSelector(IERC165Upgradeable.supportsInterface.selector, interfaceId); // perform static call bool success; uint256 returnSize; uint256 returnValue; assembly { success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) returnSize := returndatasize() returnValue := mload(0x00) } return success && returnSize >= 0x20 && returnValue > 0; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) external; function updateOperator(address registrant, address operator, bool filtered) external; function updateOperators(address registrant, address[] calldata operators, bool filtered) external; function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981Upgradeable.sol) pragma solidity 0.8.10; import "../ERC165/IERC165Upgradeable.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. * * _Available since v4.5._ */ interface IERC2981Upgradeable is IERC165Upgradeable { /** * @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 v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity 0.8.10; /** * @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}. */ /* solhint-disable */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ 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 v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @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(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ 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 } } }
{ "optimizer": { "enabled": true, "mode": "z" }, "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"EditionDoesNotExist","type":"error"},{"inputs":[],"name":"InvalidEditionId","type":"error"},{"inputs":[],"name":"InvalidEditionIdsLength","type":"error"},{"inputs":[],"name":"InvalidManager","type":"error"},{"inputs":[],"name":"ManagerDoesNotExist","type":"error"},{"inputs":[],"name":"ManagerRemoveBlocked","type":"error"},{"inputs":[],"name":"ManagerSwapBlocked","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintFrozen","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"MinterRegistrationInvalid","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"NotMinter","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"RoyaltyBPSInvalid","type":"error"},{"inputs":[],"name":"RoyaltySetBlocked","type":"error"},{"inputs":[],"name":"SoldOut","type":"error"},{"inputs":[],"name":"TokenDoesNotExist","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipientAddress","type":"address"},{"indexed":true,"internalType":"uint16","name":"royaltyPercentageBPS","type":"uint16"}],"name":"DefaultRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newDefaultTokenManager","type":"address"}],"name":"DefaultTokenManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":true,"internalType":"address","name":"editionTokenManager","type":"address"}],"name":"EditionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"bool","name":"registered","type":"bool"}],"name":"MinterRegistrationChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"MintsFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newRoyaltyManager","type":"address"}],"name":"RoyaltyManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DEFAULT_SUBSCRIPTION","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MARKETPLACE_FILTERER_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"}],"name":"editionURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"editionUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freezeMints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"}],"name":"getEditionDetails","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"initialTokenId","type":"uint256"}],"internalType":"struct IEditionCollection.EditionDetails","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getEditionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"editionIds","type":"uint256[]"}],"name":"getEditionsDetailsAndUri","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"initialTokenId","type":"uint256"}],"internalType":"struct IEditionCollection.EditionDetails[]","name":"","type":"tuple[]"},{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"address","name":"_observability","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintAmountToRecipient","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintAmountToRecipients","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"mintOneToRecipient","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"address[]","name":"recipients","type":"address[]"}],"name":"mintOneToRecipients","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"observability","outputs":[{"internalType":"contract IObservability","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorFiltererRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"registerMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeDefaultTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeMarketplaceFiltererRegistryAndUnregister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeRoyaltyManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newName","type":"string"},{"internalType":"string","name":"newSymbol","type":"string"},{"internalType":"string","name":"newContractUri","type":"string"}],"name":"setContractMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRegistry","type":"address"}],"name":"setCustomMarketplaceFiltererRegistryAndRegisterDefaultSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipientAddress","type":"address"},{"internalType":"uint16","name":"royaltyPercentageBPS","type":"uint16"}],"internalType":"struct IRoyaltyManager.Royalty","name":"_royalty","type":"tuple"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_defaultTokenManager","type":"address"}],"name":"setDefaultTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"string","name":"_uri","type":"string"}],"name":"setEditionURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setMarketplaceFiltererRegistryAndRegisterDefaultSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_royaltyManager","type":"address"}],"name":"setRoyaltyManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"size","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"","type":"uint256"}],"name":"tokenManager","outputs":[{"internalType":"address","name":"manager","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenManagerByTokenId","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"unregisterMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
9c4d535b0000000000000000000000000000000000000000000000000000000000000000010006d38697005179a7376cc5cf8318dd77866f2c9ad888d454eb198943f3aa00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x000400000000000200270000000000020000006004100270000006090340019700030000003103550002000000010355000006090040019d0000000100200190000000000200041600000000040004100000000107000039000000200e000039000000a00000c13d0000008006000039000000400060043f000000040030008c000008c30000413d000000000401043b000000e0084002700000060b0080009c000005b30000613d0000060c0080009c000000200900008a000001980000613d0000060d0080009c000000cd0f000039000007120000613d0000060e0080009c00000024051003700000000404100370000000cb0d000039000000650c000039000006b30000613d0000060f0080009c000001000a00008a000001ae0000613d000006100080009c000007510000613d000006110080009c000007760000613d000006120080009c000000b10000613d000006130080009c000002980000613d000006140080009c000000010a00008a000002850000613d000006150080009c000000ad0000613d000006160080009c00000044071003700000075b0000613d000006170080009c0000055d0000613d000006180080009c0000022e0000613d000006190080009c000000c70000613d0000061a0080009c000000d00a000039000005b70000613d0000061b0080009c000004b70000613d0000061c0080009c000002e80000613d0000061d0080009c000006090000613d0000061e0080009c000006990000613d0000061f0080009c000000e10000613d000006200080009c000000ab0000613d000006210080009c000001c60000613d000006220080009c000002190000613d000006230080009c000002320000613d000006240080009c0000054b0000613d000006250080009c000003f30000613d000006260080009c000005410000613d000006270080009c000000ab0000613d000006280080009c0000063c0000613d000006290080009c000002150000613d0000062a0080009c000006a80000613d0000062b0080009c0000035f0000613d0000062c0080009c000003760000613d0000062d0080009c000006900000613d0000062e0080009c0000056e0000613d0000062f0080009c000004d80000613d000006300080009c000004c10000613d000006310080009c000006120000613d000006320080009c000004dd0000613d000006330080009c000003fe0000613d000006340080009c0000022a0000613d000006350080009c000003b10000613d000006360080009c000002540000613d000006370080009c000004ff0000613d000006380080009c000002f00000613d000006390080009c0000028e0000613d0000063a0080009c0000051c0000613d0000063b0080009c0000038c0000613d0000063c0080009c0000052c0000613d0000063d0080009c000003c40000613d0000063e0080009c0000053d0000613d0000063f0080009c000004d40000613d000006400080009c0000034f0000613d000006410080009c000003d70000613d000006420080009c000003a00000613d000006430080009c000008c30000c13d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b000006a800100198000008c30000c13d000006a901100197000006aa0010009c00000000020000390000000102006039000006730010009c00000001022061bf000006ab0010009c00000001022061bf000000800020043f000006960000013d000000a001000039000000400010043f000000000002004b000008c30000c13d000000800040043f000001400000044300000160004004430000010000e0044300000120007004430000060a01000041000018210001042e000000240030008c000008c30000413d000000000002004b000008c30000c13d00000000010d041a000006940000013d000000000002004b000008c30000c13d0000000001000415001100000001001d1820106b0000040f000000cf01000039000000000101041a001200000001001d002706470010019b000100bc0000003d0000179a0000013d0000065502000041182016870000040f000000000001004b000007a70000c13d000000cf0200003900000012010000290000065001100197000000000012041b00000000010004150000001102000029000001ab0000013d000000440030008c000008c30000413d000000000002004b000008c30000c13d000000000105043b000000c002000039000000400020043f000000cc02000039000000000302041a0000064702300197000000800020043f000000a0033002700000ffff0330018f000000a00030043f000000000001004b000000da0000613d00000000041a00d9000000000034004b0000092a0000413d000000c00020043f00000000011300a9000027100110011a000000e00010043f000000c0010000390000004002000039000009720000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d0000000001000415000e00000001001d182010d60000040f000000cb01000039000000000101041a00000647021001970000006501000039000000000101041a00000647011001970000000003000411001100000003001d000000000013004b000000f90000c13d000000140100008a00000000011000310000000201100367000000000101043b0011006000100278000000000002004b000007cb0000c13d0000001201000029182015360000040f0000064701100197000f00000001001d000000000010043f0000067701000041000000200010043f1820167b0000040f00000011020000290000064702200197001000000002001d000000000020043f000000200010043f1820167b0000040f000000000101041a000000ff00100190000001130000c13d0000001201000029182015570000040f00000010030000290000000f0030006c000001130000613d000000100010006b00000b940000c13d0000001201000029182015360000040f0000001202000029000000000020043f0000068d02000041000000200020043f000f00000001001d1820167b0000040f0000000f02000029001006470020019b000000000201041a000000000002004b000001210000613d000000000001041b0000001001000029000000000010043f0000068001000041000101260000003d000017c80000013d0000068e0220009a000000000021041b0000800b0100003900000004030000390000000004000415000000270440008a00000005044002100000068f02000041182016870000040f0000001202000029000000000020043f0000069002000041000000200020043f000000a00110021000000010011001af000d0691001001cb1820167b0000040f0000000d02000029000000000021041b0000000f0100002900000692001001980000014c0000c13d00000012010000290000000101100039000d00000001001d000000000010043f0000069001000041000000200010043f1820167b0000040f000000000201041a000000000002004b0000014c0000c13d0000066102000041000000000202041a0000000d0020006b0000014c0000613d0000000f02000029000000000021041b000000400100043d000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d0200003900000004030000390000069304000041000000100500002900000000060000190000001207000029182016a50000040f0000000100200190000008c30000613d0000069401000041000000000201041a0000000102200039000000000021041b000000ce01000039000000000101041a001000000001001d002006470010019b000101690000003d000016d80000013d000000200440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d00000010010000290000064702100197000000400500043d000000440150003900000012030000290000000000310435000006950100004100000000001504350000001101000029000006470110019700000004035000390000000000130435000000240150003900000000000104350000000001000414000000040020008c000001890000613d00000064040000390000000003050019001200000005001d0000001205000029000000000600001918200f120000040f0000001205000029000000000001004b0000085a0000613d0001018b0000003d000016dc0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c0000000101000039000008c30000213d0000009702000039000000000012041b00000000010004150000000e02000029000001ab0000013d000000000002004b000008c30000c13d0000000001000415001200000001001d1820106b0000040f000000cf01000039000000000201041a000006500220019700000682022001c7000000000021041b0027068200000045000101a50000003d0000179a0000013d0000065502000041182016870000040f0000001202000029000000000001004b000008210000c13d000000000100041500000000011200490000000001000002000009640000013d000000000002004b000008c30000c13d0000066a01000041000000000201041a000000010320019000000001012002700000007f0110618f0000001f0010008c00000000040000390000000104002039000000000043004b0000056a0000c13d000000800010043f000000000003004b000008c40000613d0000066a02000041000000000020043f0000066b030000410000000002000019000000000012004b000008890000813d000101c50000003d0000175b0000013d000001c10000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d000006470010009c000008c30000213d0000000001000415001100000001001d1820106b0000040f182010d60000040f0000001201000029182010eb0000040f000000000001004b0000038a0000613d000000400100043d000006090010009c001000000001001d000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d02000039000000030300003900000001060000390000067d040000410000001205000029182016a50000040f0000000100200190000008c30000613d000000ce01000039000000000101041a000f00000001001d001e06470010019b000101ef0000003d000016d80000013d0000001e0440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d0000000f01000029000006470210019700000010050000290000002401500039000000010300003900000000003104350000067e0100004100000000001504350000000401500039000000120300002900000000003104350000000001000414000000040020008c0000020b0000613d000000440400003900000000030500190000001005000029000000000600001918200f120000040f0000001005000029000000000001004b0000085a0000613d0001020d0000003d000016dc0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c0000074d0000a13d000008c30000013d000000000002004b000008c30000c13d0000068201000041000006950000013d000000440030008c000008c30000413d000000000204043b000006470020009c000008c30000213d000000000405043b0000064c0040009c000008c30000213d0000002302400039000000000032004b000008c30000813d0000000402400039000000000121034f000000000201043b000000240140003918200f5a0000040f182010a30000040f000000000002004b000008c30000c13d000000cf01000039000006930000013d0000000001030019182010160000040f182011a30000040f000009640000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d000006470010009c000008c30000213d0001023c0000003d0000180a0000013d00000b920000613d00000012010000291820163f0000040f000000000001004b00000b920000c13d000000400100043d00000020031000390000067302000041000000000023043500000024021000390000068704000041000000000042043500000024020000390000000000210435000006750010009c0000088c0000213d0000006002100039000000400020043f0000001202000029000000040020008c00000add0000c13d0000000001030433000000000010043f00000ae10000013d000000440030008c000008c30000413d000000000002004b000008c30000c13d000000000205043b001200000002001d000006470020009c000008c30000213d000000000204043b001100000002001d00000000020c041a00000647042001970000000002000411000000000042004b000002670000c13d000000140230008a000000000121034f000000000101043b000000600210027000000647012001970001026a0000003d000016e50000013d000007740000613d182010d60000040f000000cd01000039000000000101041a0000065f01100197000006600010009c000009830000613d000000110000006b00000a4d0000c13d0000066101000041000000000201041a000000010100008a000000000012004b0000092a0000613d000000d101000039000000000101041a000000000001004b0000027e0000613d000000000012004b00000a4b0000213d0000001201000029001200000002001d182015890000040f000102830000003d000017a90000013d0000001202000029000005490000013d000000000002004b000008c30000c13d0000069401000041000000000101041a0000000001a1013f0000066102000041000000000202041a0000000001120019000006950000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b182015680000040f000000000001004b000004bf0000613d18200fe10000040f0000060f0000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000204043b0000064c0020009c000008c30000213d0000002304200039000000000034004b000008c30000813d001200040020003d0000001201100360000000000101043b0000064c0010009c000008c30000213d000000050410021000000000024200190000002402200039000000000032004b000008c30000213d000000010010008c00000a4f0000c13d000000c001000039000000400010043f000000800070043f182011790000040f000000a00010043f1820118c0000040f000d00000001001d000000120100002900000020011000390000000201100367000000000101043b000000000001004b00000a4d0000c13d18200fe10000040f0000000d020000290000000002020433000000000002004b00000a660000613d0000000d0200002900000020022000390000000000120435182014be0000040f000000800200043d000000000002004b00000a660000613d000000a00010043f0000004001000039000000400200043d0000000001120436000c00000001001d0000004001200039000000800300043d0000000000310435001200800000003d000f00000002001d0000006002200039000e00000003001d0000000501300210001100000002001d000000000221001900000000040000190000000f0120006a001000000004001d0000000e0040006c00000c4f0000813d000000600110008a00000011030000290000000003130436001100000003001d00000012010000290000002001100039001200000001001d000000000101043318200fac0000040f000000100400002900000001044000390000000002010019000002d70000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b000006470010009c000008c30000213d182010a30000040f000000000002004b000008c30000c13d0000000001000415001200000001001d182010d60000040f0000006501000039000000000101041a00000647021001970000000001000411000000000021004b000002fd0000c13d000102fd0000003d000016ec0000013d000000cd02000039000000000202041a0000064702200198000003c20000613d000000400500043d0000065c0300004100000000003504350000064701100197000000040350003900000000001304350000000001000414000000040020008c000003130000613d000000240400003900000020060000390000000003050019001100000005001d000000110500002918200f360000040f0000001105000029000000000001004b0000085a0000613d000103150000003d0000177e0000013d0000064c0030009c0000088c0000213d00000001002001900000088c0000c13d0000001102000029000000400020043f0000064d0010009c000008c30000213d000000200010008c000008c30000413d0000000001050433000103220000003d000016d30000013d000008c30000c13d000000000001004b000008a60000613d000000cd02000039000000000102041a0000065001100197000000000012041b0000001101000029000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d0200003900000002030000390000065d040000410000000005000019182016a50000040f0000000100200190000008c30000613d000000ce01000039000000000101041a001000000001001d001606470010019b000103400000003d000016d80000013d000000160440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d000000100100002900000647021001970000065e010000410000001103000029000000000013043500000004013000390000000000010435000000000100041400000c640000013d000000440030008c000008c30000413d000000000002004b000008c30000c13d0000000001000415001200000001001d182010d60000040f00000002010003670000002402100370000000000302043b0000ffff0030008c000008c30000213d000027100030008c000008c60000a13d000006720100004100000b950000013d000000000002004b000008c30000c13d1820106b0000040f0000003301000039000000000201041a0000065003200197000000000031041b000000400100043d000006090010009c000006090100804100000040011002100000000003000414000006090030009c0000060903008041000000c003300210000000000113019f000006470520019700000653011001c70000800d0200003900000003030000390000067f040000410000000006000019000008c00000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d000006470010009c000008c30000213d0000000001000415001100000001001d1820106b0000040f182010d60000040f0000001201000029000000000010043f000000ca01000039000000200010043f1820167b0000040f000000000301041a000000000003004b000009260000c13d0000068b0100004100000b950000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d000006470010009c000008c30000213d0000000001000415001100000001001d1820106b0000040f002700120000002d0001039a0000003d0000179a0000013d0000065502000041182016870000040f000000000001004b000009300000c13d0000065b0100004100000b950000013d000000000002004b000008c30000c13d000000c902000039000000000102041a000000800010043f000000000020043f00000645020000410000000003000019000000200500008a000000000013004b000007920000813d0000002006600039000000000402041a000000000046043500000001033000390000000102200039000003a90000013d000000000002004b000008c30000c13d0000000001000415001200000001001d182010d60000040f0000006501000039000000000101041a00000647021001970000000001000411000000000021004b000003be0000c13d000103be0000003d000016ec0000013d000000cb02000039000000000202041a0000064702200198000008460000c13d000006660100004100000b950000013d000000440030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b000006470010009c000008c30000213d000000000205043b001200000002001d000006470020009c000008c30000213d1820152b0000040f0000001202000029182015310000040f000000000101041a000000ff001001900000000002000039000000010200c039000005480000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d000006470010009c000008c30000213d1820106b0000040f0000001201000029000000000001004b000009630000c13d000000400100043d0000006402100039000006480300004100000000003204350000004402100039000006490300004100000000003204350000002402100039000000260300003900000000003204350000064a0200004100000000002104350000000402100039000000200300003900000000003204350000087c0000013d000000000002004b000008c30000c13d0000000001030019182010270000040f0000006502000039000000000202041a000000000112013f000006470010019800000000020000390000000102006039000005480000013d000000640030008c000008c30000413d000000000002004b000008c30000c13d000000000204043b001200000002001d000006470020009c000008c30000213d000000000405043b0000064c0040009c000008c30000213d0000002302400039000000000032004b000008c30000813d0000000402400039000000000121034f000000000201043b000000240140003918200f5a0000040f0000000002000410001100000001001d00000044010000390000000201100367000000000101043b001000000001001d000006470010009c000008c30000213d0000000001000415000f00000001001d000000000300041a0000ffff003001900000042e0000613d001a00000002001d0000800201000039000e00000003001d000000240300003900000000040004150000001a0440008a00000005044002100000065502000041182016870000040f0000000e030000290000002004000039000000ff0230018f000000010020008c00000b270000c13d000000000001004b00000b270000c13d0000ff0000300190000001000100008a000000000113016f00000001041001bf000000000040041b0000001106000029000e00200060003d000000400360003900000060026000390000008001600039000d00a00060003d000c00c00060003d000700e00060003d000b01000060003d000a01200060003d000901400060003d000801600060003d00000a6a0000c13d0000ffff0500008a000000000454016f00000100044001bf000000000040041b0000000004000415000600000004001d00000000040604330000064d0040009c000008c30000213d000001600040008c000008c30000413d000000400500043d000500000005001d000006690050009c0000088c0000213d00000005050000290000004005500039000000400050043f0000000e050000290000000005050433000006470050009c000008c30000213d00000005060000290000000005560436000400000005001d00000000030304330000ffff0030008c000008c30000213d000000040500002900000000003504350000000002020433000300000002001d000006470020009c000008c30000213d00000000010104330000064c0010009c000008c30000213d000104670000003d000017ee0000013d0000064c0010009c000008c30000213d0001046b0000003d000018110000013d0000064c0010009c000008c30000213d0001046f0000003d000017e60000013d000006470010009c000008c30000213d0000000a010000290000000001010433000a00000001001d000006470010009c000008c30000213d000000090100002900000000010104330001047a0000003d000016d30000013d000008c30000c13d000000080100002900000000010104330000064c0010009c000008c30000213d000104810000003d0000170c0000013d000027110010008c0000035d0000813d000104850000003d000018030000013d00000647021001970000000001000411000000000021004b0000048b0000c13d0001048b0000003d000016ec0000013d0001048d0000003d000016fc0000013d0000064701100197000000cc03000039000000000203041a0000065102200197000000000112019f00000004020000290000000002020433000000a0022002100000065202200197000000000121019f000000000013041b000000cb02000039000000000102041a00000650011001970001049d0000003d0000172e0000013d0000064c0010009c0000088c0000213d0000066a01000041000104a20000003d000016af0000013d0000056a0000c13d000104a50000003d000017670000013d00000d890000a13d0000066a03000041000000000030043f000000200300008a000000120430017f00000020050000390000066b0300004100000000060000190000000d08000029000000000046004b000000000785001900000d920000813d0000000007070433000000000073041b000000200660003900000020055000390000000103300039000004ae0000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b182015680000040f000000000001004b0000086b0000c13d000006960100004100000b950000013d000000000002004b000008c30000c13d0000066c01000041000000000201041a000104c70000003d000017a00000013d0000056a0000c13d000000800010043f000000000003004b0000086e0000613d0000066c02000041000000000020043f0000066d030000410000000002000019000000000012004b000008890000813d000104d30000003d0000175b0000013d000004cf0000013d000000000002004b000008c30000c13d00000000010f041a000006940000013d000000000002004b000008c30000c13d000000d101000039000000000101041a000006950000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d000006470010009c000008c30000213d000104e70000003d0000180a0000013d00000b920000613d00000012010000291820163f0000040f000000000001004b00000b920000c13d000000400100043d00000020031000390000067302000041000000000023043500000024021000390000067404000041000000000042043500000024020000390000000000210435000006750010009c0000088c0000213d0000006002100039000000400020043f0000001202000029000000040020008c00000b360000c13d0000000001030433000000000010043f00000b3a0000013d000000840030008c000008c30000413d000000000204043b001200000002001d000006470020009c000008c30000213d000000000205043b001100000002001d000006470020009c000008c30000213d0000006402100370000000000402043b0000064c0040009c000008c30000213d0000002302400039000000000032004b000008c30000813d0000000402400039000000000121034f000000000201043b000000000107043b001000000001001d000000240140003918200f5a0000040f0000000004010019000000120100002900000011020000290000001003000029000006a60000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d182011790000040f000000120000006b00000a4d0000c13d182014be0000040f000000400300043d001200000003001d0000002002000039000000000223043618200fac0000040f0000096f0000013d000000000002004b000008c30000c13d00000000020a041a000105310000003d000017a00000013d0000056a0000c13d000000800010043f000000000003004b0000086e0000613d0000000000a0043f00000657030000410000000002000019000000000012004b000008890000813d0001053c0000003d0000175b0000013d000005380000013d000000000002004b000008c30000c13d000000ce01000039000006930000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b182015360000040f0000064702100197000000400100043d0000000000210435000006970000013d000000000002004b000008c30000c13d0000000001000412002700000001001d002600000000003d000080050100003900000044030000390000000004000415000000270440008a00000005044002100000068302000041182016870000040f00000647011001970000000002000410000000000012004b000008710000c13d0000068601000041000006950000013d000000000002004b000008c30000c13d000000d202000039000000000302041a000000010430019000000001013002700000007f0110618f0000001f0010008c00000000050000390000000105002039000000000553013f00000001005001900000087e0000613d0000067b01000041000000000010043f00000022010000390000092d0000013d000000440030008c000008c30000413d000000000002004b000008c30000c13d000000000105043b0000064c0010009c000008c30000213d000000000204043b001200000002001d00000004011000390000000002030019182010320000040f001100000001001d0000006501000039000000000101041a00000647021001970000000001000411000000000021004b000005830000c13d000105830000003d000016ec0000013d0000064701100197000105860000003d000016e50000013d000007740000613d182010d60000040f000000cd01000039000000000101041a0000065f01100197000006600010009c000009830000613d000000120000006b00000a4d0000c13d00000011010000290000000003010433000000010100008a000000000213013f0000066101000041000000000101041a000000000021004b0000092a0000213d000000000131001a0000092a0000613d001000000003001d000e000100100092000000d101000039000000000101041a000000000001004b000005a10000613d0000000e0010006b00000a4b0000213d0000001101000029000f00200010003d0000000002000019000000100020006c00000c7f0000813d00000011010000290000000001010433000000000021004b00000a660000a13d0000000501200210001200000002001d0000000f0110002900000000010104330000064701100197182015890000040f00000012020000290000000102200039000005a40000013d000000000002004b000008c30000c13d0000064401000041000006950000013d000000640030008c000008c30000413d000000000002004b000008c30000c13d000000000204043b0000064c0020009c000008c30000213d0000002304200039000000000034004b000008c30000813d0000000404200039000000000441034f000000000404043b001200000004001d0000064c0040009c000008c30000213d0000002404200039001100000004001d0000001202400029000000000032004b000008c30000213d000000000205043b0000064c0020009c000008c30000213d0000002304200039000000000034004b000008c30000813d0000000404200039000000000441034f000000000404043b001000000004001d0000064c0040009c000008c30000213d0000002404200039000f00000004001d0000001002400029000000000032004b000008c30000213d000000000207043b0000064c0020009c000008c30000213d0000002304200039000000000034004b000008c30000813d0000000404200039000000000141034f000000000101043b000e00000001001d0000064c0010009c000008c30000213d0000002402200039000d00000002001d0000000e01200029000000000031004b000008c30000213d0000000001000415000c00000001001d1820106b0000040f0000066a01000041000105f40000003d000016af0000013d0000056a0000c13d000105f70000003d000017670000013d00000c8e0000a13d0000066a03000041000000000030043f000000200300008a000000120530017f0000066b03000041000000020400036700000000060000190000001108000029000000000056004b000000000786001900000c970000813d000000000774034f000000000707043b000000000073041b00000020066000390000000103300039000006000000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b1820144f0000040f0000000002010019000000400100043d0000096d0000013d000000440030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b001200000001001d000006470010009c000008c30000213d000000000205043b000000000002004b0000000001000039000000010100c039001100000002001d000000000012004b000008c30000c13d00000000010004110000064701100197000000000010043f0000067701000041000000200010043f1820167b0000040f0000001202000029000000000020043f0001062b0000003d000017c80000013d000001000300008a000000000232016f0000001103000029000000000232019f000000000021041b000000800030043f0000000001000414000006090010009c0000060901008041000000c00110021000000678011001c70000800d020000390000000303000039000006790400004100000000050004110000001206000029000003750000013d000000640030008c000008c30000413d000000000002004b000008c30000c13d000000000105043b0000064c0010009c000008c30000213d000000000204043b001200000002001d00000004011000390000000002030019182010320000040f001000000001001d00000002010003670000004402100370000000000202043b001100000002001d0000006502000039000000000202041a00000647032001970000000002000411000000000032004b000006580000c13d000000140200008a0000000002200031000000000121034f000000000101043b000000600210027000000647012001970001065b0000003d000016e50000013d000007740000613d182010d60000040f000000cd01000039000000000101041a0000065f01100197000006600010009c000009830000613d000000120000006b00000a4d0000c13d0000066101000041000000000101041a00000010020000290000000004020433000000000004004b0000066e0000613d000000010200008a00000000024200d9000000110020006c0000092a0000413d00000011024000b9000000010300008a000000000332013f000000000031004b0000092a0000213d000000000112001a0000092a0000613d000f00000004001d000d000100100092000000d101000039000000000101041a000000000001004b0000067d0000613d0000000d0010006b00000a4b0000213d0000001001000029000e00200010003d00000000020000190000000f0020006c00000c830000813d00000010010000290000000001010433000000000021004b00000a660000a13d0000000501200210001200000002001d0000000e01100029000000000101043300000647011001970000001102000029182015c60000040f00000012020000290000000102200039000006800000013d000000000002004b000008c30000c13d0000003301000039000000000101041a0000064701100197000000800010043f00000080010000390000002002000039000009720000013d000000640030008c000008c30000413d000000000104043b000006470010009c000008c30000213d000000000205043b000006470020009c000008c30000213d000000000307043b000000a004000039000000400040043f000000800000043f0000008004000039182012f70000040f000009640000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b000006470010009c000008c30000213d000000000001004b000009740000c13d000006810100004100000b950000013d000000440030008c000008c30000413d000000000002004b000008c30000c13d000000000505043b0000064c0050009c000008c30000213d0000002302500039000000000032004b000008c30000813d0000000402500039000000000121034f000000000201043b000000000104043b001200000001001d000000240150003918200f5a0000040f00000000050100190000000001000415000000120000006b0000097b0000c13d001000000001001d000000cb01000039000000000101041a00000647031001970000006501000039000000000101041a00000647021001970000000001000411000000000021004b000006d40000c13d000106d40000003d000016ec0000013d000000000003004b0000000004000410001100000005001d00000a030000c13d0000003302000039000000000202041a000000000112013f000006470010019800000b940000c13d0000001101000029182014570000040f000000400100043d001200000001001d000006690010009c0000088c0000213d00000012020000290000004001200039000000400010043f0000000101000039000000000112043600000000000104351820118c0000040f000f00000001001d0000000012010434000000000002004b00000a660000613d00000011020000290000000000210435000000ce01000039000000000101041a001100000001001d002306470010019b000106f60000003d000016d80000013d000000230440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d0000001101000029000e06470010019b000000400400043d000006a40100004100000000001404350000000401400039000000400200003900000000002104350000001206000029000000000306043300000044024000390000000000320435001100000004001d00000064024000390000000004000019000000000034004b00000c2d0000813d00000020066000390000000005060433000000000252043600000001044000390000070b0000013d000000000002004b000008c30000c13d0000000001000415001100000001001d1820106b0000040f182010d60000040f000000cd02000039000000000102041a000006a50110019700000660011001c7000000000012041b000000400100043d000006090010009c001200000001001d000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d020000390000000103000039000006a604000041182016a50000040f0000000100200190000008c30000613d000000ce01000039000000000101041a001000000001001d002406470010019b000107340000003d000016d80000013d000000240440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d00000010010000290000064702100197000006a701000041000000120300002900000000001304350000000001000414000000040020008c000007460000613d0000000404000039000107450000003d000017bc0000013d0000085a0000613d000107480000003d000017200000013d0000064c0010009c0000088c0000213d00000001002001900000088c0000c13d000000400010043f00000097010000390000000102000039000000000021041b000000c40000013d000000240030008c000008c30000413d000000000002004b000008c30000c13d000000000104043b182015570000040f000000400300043d00000000001304350000002002000039000009710000013d000000640030008c000008c30000413d000000000002004b000008c30000c13d000000000205043b001200000002001d000006470020009c000008c30000213d000000000207043b001000000002001d000000000204043b001100000002001d00000000020c041a00000647042001970000000002000411000000000042004b000007700000c13d000000140230008a000000000121034f000000000101043b00000060021002700000064701200197000107730000003d000016e50000013d0000097d0000c13d0000069b0100004100000b950000013d000000440030008c000008c30000413d000000000104043b001200000001001d000006470010009c000008c30000213d000000000105043b001100000001001d182015360000040f001006470010019b0000000002000411000000100020006c000008a80000613d0000001001000029000000000010043f0000067701000041000000200010043f1820167b0000040f00000000020004110000064702200197000000000020043f000000200010043f1820167b0000040f000000000101041a000000ff00100190000008a80000c13d0000069f0100004100000b950000013d000000410160008a000000000351016f000006460030009c0000088c0000213d0000008001300039000000400010043f0000000000e10435000000a004300039000000800200043d00000000002404350000008004000039000000c0033000390000000005000019000000000025004b000008690000813d000000200440003900000000060404330000064706600197000000000363043600000001055000390000079f0000013d0000001201000029001206470010019b002200120000002d000107ac0000003d000016d80000013d000000220440008a00000005044002100000065502000041182016870000040f000000000001004b0000000002000410000008c30000613d000000400300043d0000069e0100004100000000001304350000000401300039000000000021043500000000010004140000001202000029000000040020008c000007c10000613d0000002404000039001200000003001d000107c00000003d000017bc0000013d0000085a0000613d000107c30000003d000017200000013d0000064c0010009c0000088c0000213d00000001002001900000088c0000c13d000000400010043f000000cf02000039000000000102041a000000c20000013d000000400500043d0000067301000041000000000015043500000004015000390000068c0300004100000000003104350000000001000414000000040020008c000f00000002001d000007de0000613d000000240400003900000020060000390000000003050019001000000005001d000000100500002918200f360000040f0000001005000029000000000001004b0000085a0000613d000107e00000003d000016dc0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c000008c30000213d000000200010008c000008c30000413d0000000001050433000107ec0000003d000016d30000013d000008c30000c13d000000000001004b000000fb0000613d0000001201000029182015360000040f001f000f0000002d001000000001001d000107f50000003d000016d80000013d0000001f0440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d00000010010000290000064701100197000000400300043d000000240230003900000000001204350000068c0100004100000000001304350000001101000029000006470110019700000004023000390000000000120435001000000003001d0000004401300039000000000001043500000000010004140000000f02000029000000040020008c000008120000613d00000064040000390000001003000029000108110000003d000017290000013d0000085a0000613d00000001010000310000001f02100039000000200300008a000000000332016f0000001002300029000108190000003d0000171c0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c000001130000a13d000008c30000013d0025068200000045000108240000003d000016d80000013d000000250440008a00000005044002100000065502000041182016870000040f000000000001004b0000000003000410000008c30000613d000000400500043d0000002401500039000006440200004100000000002104350000065a0100004100000000001504350000064701300197000000040250003900000000001204350000000001000414000000440400003900000682020000410000000003050019001100000005001d0001083b0000003d000018180000013d000009850000c13d00000003040003670001083f0000003d000016c50000013d000008640000613d000000000704034f0000000008010019000108440000003d0000176e0000013d000008420000c13d000008640000013d000000400500043d00000662030000410000000000350435000006470110019700000004035000390000000000130435000000240150003900000000000104350000000001000414000000040020008c000008940000613d000000440400003900000020060000390000000003050019001100000005001d000000110500002918200f120000040f0000001105000029000000000001004b000008940000c13d000000030400036700000001020000310001085e0000003d000016c50000013d000008640000613d000000000704034f0000000008010019000108630000003d0000176e0000013d000008610000c13d000000000006004b000008680000613d000108680000003d000016b90000013d182016690000040f0000000002130049000009720000013d000000400100043d0000000000010435000006970000013d000001000100008a000000000112016f000009690000013d0000064a01000041000000800010043f0000002001000039000000840010043f0000003801000039000000a40010043f0000068401000041000000c40010043f0000068501000041000000e40010043f00000080010000390000008402000039182016690000040f000000800010043f000000000004004b000009670000613d000000000020043f00000698030000410000000002000019000000000012004b000008890000813d000108880000003d0000175b0000013d000008840000013d000006580120009a000006590010009c000008900000813d0000067b01000041000000000010043f00000041010000390000092d0000013d0000003f01200039000000000191016f00000080011000390000096b0000013d000108960000003d0000177e0000013d0000064c0030009c0000088c0000213d00000001002001900000088c0000c13d0000001102000029000000400020043f0000064d0010009c000008c30000213d000000200010008c000008c30000413d0000000001050433000108a30000003d000016d30000013d000008c30000c13d000000000001004b00000b980000c13d000006650100004100000b950000013d0000001101000029000000000010043f0000068d01000041000108ad0000003d000017c80000013d00000650022001970000001206000029000000000262019f000000000021041b000000400100043d000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d020000390000000403000039000006a00400004100000010050000290000001107000029182016a50000040f0000000100200190000009640000c13d0000177c0000013d0000000001a2016f000009690000013d00000000040004110000006502000039000000000202041a0000064702200197000000000024004b000008d10000c13d000000140200008a0000000002200031000000000221034f000000000202043b0000006004200270000000cd02000039000000000202041a0000064702200198000009930000c13d0000003302000039000000000202041a000000000242013f000006470020019800000b940000c13d0000000402100370000000000502043b000006470050009c000008c30000213d000000cc04000039000000000204041a0000065003200197000000000353019f000000000034041b0000002401100370000000000601043b0000ffff0060008c000008c30000213d0000065101200197000000a0026002100000065202200197000000000121019f000000000151019f000000cc02000039000000000012041b000000400100043d000006090010009c001100000001001d000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d0200003900000003030000390000065404000041182016a50000040f0000000100200190000008c30000613d000000ce01000039000000000101041a00000002020003670000000403200370000000000303043b001000000003001d000006470030009c000008c30000213d0000002402200370000000000202043b000f00000002001d0000ffff0020008c000008c30000213d000e06470010019b0013000e0000002d000109100000003d000016d80000013d000000130440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d000000110200002900000024012000390000000f0300002900000000003104350000065601000041000000000012043500000004012000390000001002000029000000000021043500000000010004140000000e02000029000000040020008c00000c6b0000613d00000044040000390000000e0200002900000c670000013d000000c904000039000000000204041a000000000002004b000009c50000c13d0000067b01000041000000000010043f0000001101000039000000040010043f0000067c010000410000182200010430000000cf01000039000000000201041a000006500220019700000012022001af000000000021041b001500120000002d000109380000003d000016d80000013d000000150440008a00000005044002100000065502000041182016870000040f000000000001004b000000c40000613d001400120000002d000109410000003d000016d80000013d000000140440008a00000005044002100000065502000041182016870000040f000000000001004b0000000004000410000008c30000613d000000400300043d0000002401300039000006440200004100000000002104350000065a01000041000000000013043500000647014001970000000402300039000000000012043500000000010004140000001202000029000000040020008c0000095b0000613d00000044040000390000001202000029001200000003001d0001095a0000003d000017bc0000013d0000085a0000613d0001095d0000003d000017200000013d0000064c0010009c0000088c0000213d00000001002001900000088c0000c13d000000400010043f000000c40000013d182010890000040f000000400100043d0000000002000019000009720000013d000001000100008a000000000113016f000000a00010043f000000c001000039000000400010043f0000008002000039001200000001001d18200fa60000040f0000001203000029000000000231004900000000010300190000000003000019182016710000040f000000000010043f0000068001000041000000200010043f1820167b0000040f000000000101041a0000064c01100197000006950000013d000006a10100004100000b950000013d182010d60000040f000000cd01000039000000000101041a0000065f01100197000006600010009c00000a390000c13d0000069a0100004100000b950000013d0000001f01200039000000200200008a000000000221016f0000001101200029000000000021004b000000000200003900000001020040390000064c0010009c0000088c0000213d00000001002001900000088c0000c13d000000400010043f0000001202000029000001aa0000013d000000400600043d0000064b05000041001100000006001d00000000005604350000000401100370000000000101043b000006470010009c000008c30000213d000006470440019700000011070000290000004405700039000000000045043500000024047000390000000000340435000000040370003900000000001304350000000001000414000000040020008c000009ae0000613d000000640400003900000020060000390000000003070019000000000507001918200f360000040f0000001107000029000000000001004b0000085a0000613d000109b00000003d000017b70000013d0000000002730019000109b30000003d0000171c0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c000008c30000213d000000200010008c000008c30000413d00000011010000290000000001010433000109c00000003d000016d30000013d000008c30000c13d000000000001004b00000c870000c13d0000064e0100004100000b950000013d000000010130008a000000000032004b00000a510000c13d0000067a0230009a000000000002041b000000000014041b0000001201000029000000000010043f000000ca01000039000000200010043f1820167b0000040f000000000001041b000000400100043d000006090010009c001000000001001d000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d0200003900000003030000390000067d0400004100000012050000290000000006000019182016a50000040f0000000100200190000008c30000613d000000ce01000039000000000101041a000f00000001001d001c06470010019b000109ea0000003d000016d80000013d0000001c0440008a00000005044002100000065502000041182016870000040f000000000001004b00000bb90000613d0000000f0100002900000647021001970000067e0100004100000010040000290000000000140435000000040140003900000012030000290000000000310435000000240140003900000000000104350000000001000414000000040020008c00000b810000613d0000004404000039000000100300002900010a010000003d000017290000013d0000085a0000613d00000b810000013d000000400600043d001200000006001d0000006402600039000f00000003001d000000a0030000390000000000320435000006470110019700000024026000390000000000120435000006a201000041000000000016043500000647014001970000000402600039000000000012043500000044016000390000000000010435000000a402600039000000000105001918200f920000040f00000012050000290000008402500039000000060300003900000000003204350000000f0200002900000000030100190000000001000414000000040020008c00000a270000613d000000000453004900000020060000390000000003050019000000120500002918200f120000040f0000001205000029000000000001004b0000085a0000613d00010a290000003d000016dc0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c000008c30000213d000000200010008c000008c30000413d000000000105043300010a350000003d000016d30000013d000008c30000c13d000000000001004b000006dd0000c13d00000b940000013d000000110000006b00000a4d0000c13d000000010100008a0000001003000029000000000213013f0000066101000041000000000101041a000000000021004b0000092a0000213d000000000131001a0000092a0000613d0011000100100092000000d101000039000000000101041a000000000001004b00000c550000613d000000110010006b00000c550000a13d000006990100004100000b950000013d0000069d0100004100000b950000013d0000069c0100004100000b950000013d000000000012004b00000a660000a13d0000067a0120009a000000000101041a0000067a0230009a000000000012041b000000000010043f000000ca01000039000000200010043f001000000003001d1820167b0000040f0000001002000029000000000021041b000000c901000039000000000101041a000000000001004b00000bbc0000c13d0000067b01000041000000000010043f00000031010000390000092d0000013d0000067b01000041000000000010043f00000032010000390000092d0000013d0000000004000415000600000004001d00000000040604330000064d0040009c000008c30000213d000001600040008c000008c30000413d000000400500043d000500000005001d000006690050009c0000088c0000213d00000005050000290000004005500039000000400050043f0000000e050000290000000005050433000006470050009c000008c30000213d00000005060000290000000005560436000400000005001d00000000030304330000ffff0030008c000008c30000213d000000040500002900000000003504350000000002020433000300000002001d000006470020009c000008c30000213d00000000010104330000064c0010009c000008c30000213d00010a8d0000003d000017ee0000013d0000064c0010009c000008c30000213d00010a910000003d000018110000013d0000064c0010009c000008c30000213d00010a950000003d000017e60000013d000006470010009c000008c30000213d0000000a010000290000000001010433000a00000001001d000006470010009c000008c30000213d0000000901000029000000000101043300010aa00000003d000016d30000013d000008c30000c13d000000080100002900000000010104330000064c0010009c000008c30000213d00010aa70000003d0000170c0000013d000027100010008c0000035d0000213d00010aab0000003d000018030000013d00000647021001970000000001000411000000000021004b00000ab10000c13d00010ab10000003d000016ec0000013d00010ab30000003d000016fc0000013d0000064701100197000000cc03000039000000000203041a0000065102200197000000000112019f00000004020000290000000002020433000000a0022002100000065202200197000000000121019f000000000013041b000000cb02000039000000000102041a000006500110019700010ac30000003d0000172e0000013d0000064c0010009c0000088c0000213d0000066a0100004100010ac80000003d000016af0000013d0000056a0000c13d00010acb0000003d000017670000013d00000db30000a13d0000066a03000041000000000030043f000000200300008a000000120430017f00000020050000390000066b0300004100000000060000190000000d08000029000000000046004b000000000785001900000dbc0000813d0000000007070433000000000073041b00000020066000390000002005500039000000010330003900000ad40000013d00010adf0000003d000017480000013d00000b920000613d000000000100043d0000000102000031000000200020008c00000b920000413d000000000001004b00000b920000613d0000006501000039000000000101041a00000647011001970000000004000411000000000014004b00000af10000c13d000000140100008a00000000011000310000000201100367000000000101043b0000006004100270000000cd01000039000000000101041a000006470310019800000bc00000c13d0000003302000039000000000202041a000000000242013f000006470020019800000b940000c13d000000400200043d001000000002001d00000650011001970000001205000029000000000151019f000000cd02000039000000000012041b0000001001000029000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d0200003900000002030000390000065d04000041182016a50000040f0000000100200190000008c30000613d000000ce01000039000000000101041a000f00000001001d001d06470010019b00010b170000003d000016d80000013d0000001d0440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d0000000f0100002900000647021001970000065e0100004100000010030000290000000000130435000000040130003900000012030000290000000000310435000000000100041400000b7f0000013d000000400100043d00000064021000390000066703000041000000000032043500000044021000390000066803000041000000000032043500000024021000390000002e0300003900000000003204350000064a020000410000000000210435000000040210003900000000004204350000087c0000013d00010b380000003d000017480000013d00000b920000613d000000000100043d0000000102000031000000200020008c00000b920000413d000000000001004b00000b920000613d0000006501000039000000000101041a00000647011001970000000004000411000000000014004b00000b4a0000c13d000000140100008a00000000011000310000000201100367000000000101043b0000006004100270000000cb01000039000000000101041a000006470310019800000be00000c13d0000003302000039000000000202041a000000000242013f000006470020019800000b940000c13d000000400200043d001000000002001d00000650011001970000001205000029000000000151019f000000cb02000039000000000012041b0000001001000029000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d0200003900000002030000390000066304000041182016a50000040f0000000100200190000008c30000613d000000ce01000039000000000101041a000f00000001001d001b06470010019b00010b700000003d000016d80000013d0000001b0440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d0000000f0100002900000647021001970000066401000041000000100300002900000000001304350000000401300039000000120300002900000000003104350000000001000414000000040020008c00000c890000c13d00000001010000310000001f02100039000000200300008a000000000332016f000000100230002900010b880000003d0000171c0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c0000000101000039000008c30000213d0000009702000039000000c30000013d0000068a0100004100000b950000013d000006a301000041000000000010043f0000064f010000410000182200010430000000cb02000039000000000102041a0000065001100197000000000012041b0000001101000029000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d02000039000000020300003900000663040000410000000005000019182016a50000040f0000000100200190000008c30000613d000000ce01000039000000000101041a001000000001001d001706470010019b00010bb30000003d000016d80000013d000000170440008a00000005044002100000065502000041182016870000040f000000000001004b00000c5c0000c13d00000000010000190000000002000019182016690000040f0000000003010019000000010110008a000000c904000039000009c80000013d0000064701400197000000400500043d0000002404500039000000000014043500000688010000410000000000150435000f00000005001d0000000401500039000000120400002900000000004104350000000001000414000000040030008c00000c020000613d0000004404000039000000200600003900000000020300190000000f03000029000000000503001918200f360000040f0000000102000031000000000001004b00000c020000c13d000000030400036700010bd90000003d000016c50000013d000008640000613d000000000704034f000000000801001900010bde0000003d0000176e0000013d00000bdc0000c13d000008640000013d000000400600043d00000044016000390000001205000029000000000051043500000676010000410000000000160435000006470140019700000004046000390000000000140435000f00000006001d000000240160003900000000000104350000000001000414000000040030008c00000c180000613d0000006404000039000000200600003900000000020300190000000f03000029000000000503001918200f120000040f0000000102000031000000000001004b00000c180000c13d000000030400036700010bfb0000003d000016c50000013d000008640000613d000000000704034f000000000801001900010c000000003d0000176e0000013d00000bfe0000c13d000008640000013d00010c040000003d000017910000013d0000064c0030009c0000088c0000213d00000001001001900000088c0000c13d0000001001000029000000400010043f0000064d0020009c000008c30000213d000000200020008c000008c30000413d0000000f01000029000000000101043300010c120000003d000016d30000013d000008c30000c13d000000000001004b00000c2b0000613d000000cd01000039000000000101041a00000afc0000013d00010c1a0000003d000017910000013d0000064c0030009c0000088c0000213d00000001001001900000088c0000c13d0000001001000029000000400010043f0000064d0020009c000008c30000213d000000200020008c000008c30000413d0000000f01000029000000000101043300010c280000003d000016d30000013d000008c30000c13d000000000001004b00000c8b0000c13d000006890100004100000b950000013d00000000011200490000001103000029000000240330003900000000001304350000000f0100002918200fc60000040f000000000201001900000000010004140000000e03000029000000040030008c00000c3e0000613d000000110300002900000000043200490000000e0200002900010c3d0000003d000017290000013d0000085a0000613d00000001010000310000001f02100039000000200300008a000000000332016f000000110230002900010c450000003d0000171c0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c000008c30000213d00000000010004150000001002000029000001ab0000013d0000000c0300002900000000001304350000000d0100002918200fc60000040f0000000f03000029000009700000013d00000012010000290000001002000029182015c60000040f00010c5a0000003d000017a90000013d0000001102000029000005490000013d00000010010000290000064702100197000006640100004100000011030000290000000000130435000000040130003900000000000104350000000001000414000000040020008c00000c6b0000613d0000002404000039000000110300002900010c6a0000003d000017290000013d0000085a0000613d00000001010000310000001f02100039000000200300008a000000000332016f000000110230002900010c720000003d0000171c0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c0000000101000039000008c30000213d0000009702000039000000000012041b00000000010004150000001202000029000001ab0000013d00010c810000003d000017a90000013d0000000e02000029000005490000013d00010c850000003d000017a90000013d0000000d02000029000005490000013d0000000201000367000008da0000013d0000002404000039000009fe0000013d000000cb01000039000000000101041a00000b550000013d000000120000006b000000000300001900000c940000613d00000011030000290000000203300367000000000303043b00010c960000003d000017610000013d00000c9c0000013d000000120050006c00000c9b0000813d00010c9b0000003d000017ae0000013d00000001011001bf0000066a02000041000000000012041b0000066c0100004100010ca10000003d000016af0000013d0000056a0000c13d0000001002000029182011550000040f0000001002000029000000200020008c0000000101200210000000030220021000000cba0000413d0000066c03000041000000000030043f000000200300008a000000100530017f0000066d03000041000000020400036700000000060000190000000f08000029000000000056004b000000000786001900000cc30000813d000000000774034f000000000707043b000000000073041b0000002006600039000000010330003900000cb10000013d000000100000006b000000000300001900000cc00000613d0000000f030000290000000203300367000000000303043b00010cc20000003d000017610000013d00000cc80000013d000000100050006c00000cc70000813d00010cc70000003d000017ae0000013d00000001011001bf0000066c02000041000000000012041b000000d00100003900010ccd0000003d000016af0000013d0000056a0000c13d0000000e02000029182011670000040f0000000e01000029000000200010008c00000ce40000413d000000d001000039000000000010043f000000200100008a0000000e0310017f0000065701000041000000020200036700000000040000190000000d06000029000000000034004b000000000564001900000cee0000813d000000000552034f000000000505043b000000000051041b0000002004400039000000010110003900000cdb0000013d0000000e0000006b000000000100001900000cea0000613d0000000d010000290000000201100367000000000101043b0000000e0400002900010ced0000003d000016cb0000013d00000cfd0000013d0000000e0030006c00000cfa0000813d0000000e030000290000000303300210000000f80330018f000000010400008a000000000334022f000000000343013f000000000252034f000000000202043b000000000232016f000000000021041b0000000e01000029000000010110021000000001011001bf000000d002000039000000000012041b000000ce01000039000000000101041a000a00000001001d002106470010019b00010d050000003d000016d80000013d000000210440008a00000005044002100000065502000041182016870000040f000000000001004b000008c30000613d000000400400043d00000697010000410000000000140435000000640140003900000012030000290000000000310435000000040140003900000060020000390000000000210435000000200200008a00000000052301700000001f0630018f000b00000004001d000000840340003900000000045300190000000202000367000000110720036000000d230000613d000000000807034f0000000009030019000000008a08043c0000000009a90436000000000049004b00000d1f0000c13d000000000006004b00000d290000613d000000000557034f000000030660021000010d290000003d000017720000013d0000001205000029000000000453001900000000000404350000001f04500039000000200600008a000000000464016f000000000343001900000000041300490000000b05000029000000240550003900000000004504350000000f052003600000001004000029000000000343043600000000066401700000001f0740018f000000000463001900000d410000613d000000000805034f0000000009030019000000008a08043c0000000009a90436000000000049004b00000d3d0000c13d000000000007004b00000d470000613d000000000565034f000000030670021000010d470000003d000017720000013d0000001005000029000000000453001900000000000404350000001f04500039000000200500008a000000000454016f000000000343001900000000011300490000000b04000029000000440440003900000000001404350000000d042003600000000e01000029000000000313043600000000055101700000001f0610018f000000000153001900000d5f0000613d000000000204034f0000000007030019000000002802043c0000000007870436000000000017004b00000d5b0000c13d0000000a020000290000064702200197000000000006004b00000d690000613d000000000454034f0000000305600210000000000601043300010d680000003d000017f60000013d00000000004104350000000e0130002900000000000104350000000001000414000000040020008c00000d7a0000613d0000000e040000290000001f04400039000000200500008a000000000454016f0000000b05000029000000000454004900000000043400190000000003050019000000000600001918200f120000040f000000000001004b0000085a0000613d00010d7c0000003d000017b70000013d0000000b0230002900010d7f0000003d0000171c0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c000008c30000213d00000000010004150000000c02000029000001ab0000013d000000120000006b000000000300001900000d8f0000613d0000000d030000290000002003300039000000000303043300010d910000003d000017610000013d00000d970000013d000000120040006c00000d960000813d00010d960000003d000017de0000013d00000001011001bf0000066a02000041000000000012041b0000000c010000290000000001010433001200000001001d0000064c0010009c0000088c0000213d0000066c0100004100010da10000003d000016af0000013d0000056a0000c13d0000001202000029182011550000040f0000001201000029000000200010008c00000ddd0000413d0000066c0100004100010daa0000003d000017fe0000013d0000066d0100004100000000040000190000000c06000029000000000024004b000000000563001900000de70000813d00010db20000003d000017c20000013d00000dad0000013d000000120000006b000000000300001900000db90000613d0000000d030000290000002003300039000000000303043300010dbb0000003d000017610000013d00000dc10000013d000000120040006c00000dc00000813d00010dc00000003d000017de0000013d00000001011001bf0000066a02000041000000000012041b0000000c010000290000000001010433001200000001001d0000064c0010009c0000088c0000213d0000066c0100004100010dcb0000003d000016af0000013d0000056a0000c13d0000001202000029182011550000040f0000001201000029000000200010008c00000e0c0000413d0000066c0100004100010dd40000003d000017fe0000013d0000066d0100004100000000040000190000000c06000029000000000024004b000000000563001900000e160000813d00010ddc0000003d000017c20000013d00000dd70000013d000000120000006b000000000100001900000de30000613d0000000c0100002900000020011000390000000001010433000000120400002900010de60000003d000016cb0000013d00000dee0000013d000000120020006c00000deb0000813d00010deb0000003d000016f20000013d0000001201000029000000010110021000000001011001bf0000066c02000041000000000012041b000006610100004100010df30000003d000017880000013d000006500110019700010df60000003d0000173b0000013d0000064c0010009c0000088c0000213d000000d00100003900010dfb0000003d000016af0000013d0000056a0000c13d0000001202000029182011670000040f0000001201000029000000200010008c00000e400000413d000000d00100003900010e040000003d000017fe0000013d00000657010000410000000004000019000000000024004b000000110530002900000e4a0000813d00010e0b0000003d000017c20000013d00000e060000013d000000120000006b000000000100001900000e120000613d0000000c0100002900000020011000390000000001010433000000120400002900010e150000003d000016cb0000013d00000e1d0000013d000000120020006c00000e1a0000813d00010e1a0000003d000016f20000013d0000001201000029000000010110021000000001011001bf0000066c02000041000000000012041b000006610100004100010e220000003d000017880000013d000006500110019700010e250000003d0000173b0000013d0000064c0010009c0000088c0000213d000000d00100003900010e2a0000003d000016af0000013d0000056a0000c13d0000001202000029182011670000040f0000001201000029000000200010008c00000eaf0000413d000000d001000039000000000010043f000000200100008a000000120210017f000006570100004100000000030000190000002005000039000000000023004b000000110450002900000eb90000813d0000000004040433000000000041041b00000020033000390000002005500039000000010110003900000e370000013d000000120000006b000000000100001900000e460000613d000000110100002900000020011000390000000001010433000000120400002900010e490000003d000016cb0000013d00000e510000013d000000120020006c00000e4e0000813d00010e4e0000003d000016f20000013d0000001201000029000000010110021000000001011001bf000000d002000039000000000012041b000000400100043d000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d0200003900000003030000390000066e0400004100000009050000290000000306000029182016a50000040f0000000100200190000008c30000613d0000001001000029001906470010019b00010e690000003d000016d80000013d000000190440008a00000005044002100000065502000041182016870000040f0000000002000410000000000001004b000008c30000613d00000010010000290000064703100197000000400400043d0000066f0100004100000000001404350000064701200197001200000004001d000000040240003900000000001204350000000001000414001100000003001d000000040030008c00000e830000613d00000024040000390000001102000029000000120300002900010e820000003d000017290000013d0000085a0000613d00000001010000310000001f02100039000000200300008a000000000332016f000000120230002900010e8a0000003d0000171c0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c0000000103000039000008c30000213d000000ce01000039000000000201041a000006500220019700000011022001af000000000021041b0000000001000415000000060110006900000000010000020000ff010100008a000000000200041a000000000112016f000000000010041b000000400100043d0000000000310435000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000670011001c70000800d020000390000067104000041182016a50000040f000000010020019000000f0f0000c13d000008c30000013d000000120000006b000000000100001900000eb50000613d000000110100002900000020011000390000000001010433000000120400002900010eb80000003d000016cb0000013d00000ec70000013d000000120020006c00000ec40000813d00000012020000290000000302200210000000f80220018f000000010300008a000000000223022f000000000232013f0000000003040433000000000223016f000000000021041b0000001201000029000000010110021000000001011001bf000000d002000039000000000012041b000000400100043d000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f00000653011001c70000800d0200003900000003030000390000066e0400004100000009050000290000000306000029182016a50000040f0000000100200190000008c30000613d0000001001000029001806470010019b00010edf0000003d000016d80000013d000000180440008a00000005044002100000065502000041182016870000040f0000000002000410000000000001004b000008c30000613d00000010010000290000064703100197000000400400043d0000066f0100004100000000001404350000064701200197001200000004001d000000040240003900000000001204350000000001000414001100000003001d000000040030008c00000ef90000613d00000024040000390000001102000029000000120300002900010ef80000003d000017290000013d0000085a0000613d00000001010000310000001f02100039000000200300008a000000000332016f000000120230002900010f000000003d0000171c0000013d0000064c0020009c0000088c0000213d00000001003001900000088c0000c13d000000400020043f0000064d0010009c000008c30000213d000000ce01000039000000000201041a000006500220019700000011022001af000000000021041b00000000010004150000000601100069000000000100000200000000010004150000000f02000029000001ab0000013d0003000000000002000300000006001d000200000005001d000006090030009c00000609030080410000004003300210000006090040009c00000609040080410000006004400210000000000334019f000006090010009c0000060901008041000000c001100210000000000113019f182016a50000040f000000020900002900000060031002700000060903300197000000030030006c000000030400002900000000040340190000001f0540018f000006ac06400198000000000469001900000f300000613d000000000701034f000000007807043c0000000009890436000000000049004b00000f2c0000c13d000000010220018f000000000005004b00000f350000613d00010f350000003d0000174f0000013d0000181d0000013d0003000000000002000300000006001d000200000005001d000006090030009c00000609030080410000004003300210000006090040009c00000609040080410000006004400210000000000334019f000006090010009c0000060901008041000000c001100210000000000113019f182016aa0000040f000000020900002900000060031002700000060903300197000000030030006c000000030400002900000000040340190000001f0540018f000006ac06400198000000000469001900000f540000613d000000000701034f000000007807043c0000000009890436000000000049004b00000f500000c13d000000010220018f000000000005004b00000f590000613d00010f590000003d0000174f0000013d0000181d0000013d000006ad0020009c00000f8b0000813d00000000040100190000001f01200039000000200600008a000000000161016f0000003f01100039000000000561016f000000400100043d0000000005510019000000000015004b000000000700003900000001070040390000064c0050009c00000f8b0000213d000000010070019000000f8b0000c13d000000400050043f00000000052104360000000007420019000000000037004b00000f910000213d00000000066201700000001f0720018f0000000204400367000000000365001900000f7b0000613d000000000804034f0000000009050019000000008a08043c0000000009a90436000000000039004b00000f770000c13d000000000007004b00000f880000613d000000000464034f0000000306700210000000000703043300000000076701cf000000000767022f000000000404043b0000010006600089000000000464022f00000000046401cf000000000474019f000000000043043500000000022500190000000000020435000000000001042d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c0100004100001822000104300000177c0000013d0000002004100039000000000301043300000000013204360000000002000019000000000032004b00000f9e0000813d0000000005120019000000000624001900000000060604330000000000650435000000200220003900000f960000013d00000fa10000a13d000000000213001900000000000204350000001f02300039000000200300008a000000000232016f0000000001210019000000000001042d000000000302001900000020020000390000000002210436000000000103001918200f920000040f000000000001042d00040000000000020000000003020019000100000002001d000400000001001d0000000021010434000300000002001d00000080020000390000000002230436000200000002001d000000800230003918200f920000040f00000003020000290000000002020433000000020300002900000000002304350000000404000029000000400240003900000000020204330000000105000029000000400350003900000000002304350000006002500039000000600340003900000000030304330000000000320435000000000001042d0005000000000002000500000001001d00000000010104330000000003120436000200000001001d00000005011002100000000002310019000100000003001d000400000003001d0000000003000019000000020030006c00000fe00000813d000000010120006a000300000003001d00000004030000290000000003130436000400000003001d00000005010000290000002001100039000500000001001d000000000101043318200f920000040f00000003030000290000000103300039000000000201001900000fd00000013d000017d40000013d0001000000000002000000d205000039000000000405041a000000010640019000000001024002700000007f0220618f0000001f0020008c00000000010000390000000101002039000000000016004b0000100c0000c13d000000400100043d0000000003210436000000000006004b00000ffb0000613d000000000050043f000006980400004100000000050000190000000006530019000000000025004b00000fff0000813d000000000704041a00000000007604350000002005500039000000010440003900000ff30000013d000001000200008a000000000224016f0000000000230435000000400610003900000000021600490000001f02200039000000200300008a000000000332016f0000000002130019000110060000003d0000171c0000013d0000064c0020009c000010100000213d0000000100300190000010100000c13d000000400020043f000000000001042d0000067b01000041000000000010043f0000002201000039000010130000013d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c0100004100001822000104300000064d0010009c000010260000213d000000630010008c000010260000a13d00000002030003670000000401300370000000000101043b000006470010009c000010260000213d0000002402300370000000000202043b000006470020009c000010260000213d0000004403300370000000000303043b000000000001042d0000177c0000013d0000064d0010009c000010310000213d000000230010008c000010310000a13d00000004010000390000000201100367000000000101043b000006470010009c000010310000213d000000000001042d0000177c0000013d0000001f03100039000000000023004b0000000004000019000006ae04004041000006ae05200197000006ae03300197000000000653013f000000000053004b0000000003000019000006ae03002041000006ae0060009c000000000304c019000000000003004b000010640000613d0000000204000367000000000314034f000000000503043b000006ad0050009c000010650000813d00000005065002100000003f03600039000006af07300197000000400300043d0000000007730019000000000037004b000000000800003900000001080040390000064c0070009c000010650000213d0000000100800190000010650000c13d000000400070043f000000000053043500000000056100190000002005500039000000000025004b000010640000213d00000000020300190000002001100039000000000051004b000010620000813d000000000614034f000000000606043b000006470060009c000010640000213d00000020022000390000000000620435000010580000013d0000000001030019000000000001042d0000177c0000013d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c0100004100001822000104300000003301000039000000000101041a0000006502000039000000000202041a00000647032001970000000002000411000000000032004b000010780000c13d000000140200008a00000000022000310000000202200367000000000202043b0000006002200270000000000112013f00000647001001980000107c0000c13d000000000001042d000000400100043d0000004402100039000006b00300004100000000003204350000064a020000410000000000210435000000240210003900000020030000390000000000320435000000040210003900000000003204350000006402000039182016690000040f000000000601001900000647011001970000003302000039000000000302041a0000065004300197000000000114019f000000000012041b000000400100043d000006090010009c000006090100804100000040011002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f000006470530019700000653011001c70000800d0200003900000003030000390000067f04000041182016a50000040f0000000100200190000010a20000613d000000000001042d0000177c0000013d00020000000000020000000001000412000200000001001d000100000000003d000080050100003900000044030000390000000004000415000000020440008a00000005044002100000068302000041182016870000040f0000064a02000041000000400300043d00000000002304350000000402300039000000200400003900000000004204350000004402300039000000240430003900000647011001970000000005000410000000000015004b000010c10000c13d0000002c010000390000000000140435000006b10100004100000000001204350000006401300039000006b402000041000010d20000013d0000068605000041000000000505041a0000064705500197000000000015004b000010cc0000c13d0000000f010000390000000000140435000006b30100004100000000001204350000006402000039000010d40000013d0000002c010000390000000000140435000006b10100004100000000001204350000006401300039000006b202000041000000000021043500000084020000390000000001030019182016690000040f0000009701000039000000000201041a000000020020008c000010dd0000613d0000000202000039000000000021041b000000000001042d000000400100043d0000004402100039000006b503000041000000000032043500000024021000390000001f0300003900000000003204350000064a0200004100000000002104350000000402100039000000200300003900000000003204350000006402000039182016690000040f0003000000000002000300000001001d000110ef0000003d000016e50000013d0000000001000019000010f20000613d000000000001042d000000ca050000390000000304000029000000c901000039000000000201041a0000064c0020009c000011050000213d0000000103200039000000000031041b000006b60220009a000000000042041b000000000101041a000200000001001d000000000040043f000000200050043f1820167b0000040f0000000202000029000000000021041b0000000101000039000000000001042d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c0100004100001822000104300000001f03100039000000000023004b0000000004000019000006ae04004041000006ae05200197000006ae03300197000000000653013f000000000053004b0000000003000019000006ae03002041000006ae0060009c000000000304c019000000000003004b000011420000613d0000000043010434000006ad0030009c0000113c0000813d0000001f01300039000000200500008a000000000151016f0000003f01100039000000000551016f000000400100043d0000000005510019000000000015004b000000000600003900000001060040390000064c0050009c0000113c0000213d00000001006001900000113c0000c13d000000400050043f00000000053104360000000006340019000000000026004b000011420000213d0000000002000019000000000032004b000011380000813d00000000065200190000000007240019000000000707043300000000007604350000002002200039000011300000013d0000113b0000a13d00000000023500190000000000020435000000000001042d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c0100004100001822000104300000177c0000013d000000200010008c000011540000413d0000066a03000041000000000030043f0000001f032000390000000503300270000006b70330009a000000200020008c0000066b030040410000001f011000390000000501100270000006b70110009a000000000013004b000011540000813d000000000003041b00000001033000390000114f0000013d000000000001042d000000200010008c000011660000413d0000066c03000041000000000030043f0000001f032000390000000503300270000006b80330009a000000200020008c0000066d030040410000001f011000390000000501100270000006b80110009a000000000013004b000011660000813d000000000003041b0000000103300039000011610000013d000000000001042d000000200010008c000011780000413d000000d003000039000000000030043f0000001f032000390000000503300270000006b90330009a000000200020008c00000657030040410000001f011000390000000501100270000006b90110009a000000000013004b000011780000813d000000000003041b0000000103300039000011730000013d000000000001042d000000400100043d000006ba0010009c000011860000813d0000008002100039000000400020043f0000006002000039000000000221043600000060031000390000000000030435000000400310003900000000000304350000000000020435000000000001042d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c010000410000182200010430000000400100043d000006bb0010009c0000119d0000813d0000004002100039000000400020043f000000010500003900000000025104360000006003000039000000000600001900000001005001900000119c0000613d0000000005620019000000000035043500000000050000190000002006000039000011950000013d000000000001042d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c010000410000182200010430000c000000000002000400000002001d000800000001001d000900000003001d0000000001030019182015360000040f00000008020000290000064702200197000600000001001d0000064701100197000700000002001d000000000021004b000012bf0000c13d0000000901000029000000000010043f0000068d01000041000000200010043f1820167b0000040f0000000003010019000000000401041a000000000100041100000647011001970000000702000029000000000021004b000500000001001d000011cf0000613d000000000041004b000011cf0000613d000000000020043f0000067701000041000000200010043f000800000003001d000300000004001d1820167b0000040f0000000502000029000000000020043f000000200010043f1820167b0000040f000000030400002900000008030000290000000702000029000000000101041a000000ff00100190000012c30000613d000000000004004b000011d20000613d000000000003041b000000000020043f0000068001000041000111d60000003d000017c80000013d000000010220008a000000000021041b00000004010000290000064701100197000800000001001d000000000010043f0000068001000041000111df0000003d000017c80000013d0000000102200039000000000021041b0000800b01000039000000040300003900000000040004150000000c0440008a00000005044002100000068f02000041182016870000040f0000000902000029000000000020043f0000069002000041000000200020043f000000a00110021000000008011001af00040692001001cb1820167b0000040f0000000402000029000000000021041b00000006010000290000069200100198000012050000c13d00000009010000290000000101100039000400000001001d000000000010043f0000069001000041000000200010043f1820167b0000040f000000000201041a000000000002004b000012050000c13d0000066102000041000000000202041a000000040020006b000012050000613d0000000602000029000000000021041b0000000001000414000006090010009c0000060901008041000000c00110021000000653011001c70000800d0200003900000004030000390000069304000041000000070500002900000008060000290000000907000029182016a50000040f0000000100200190000012b80000613d000000080000006b000012c10000613d000000cb01000039000000000101041a0000064707100198000012880000613d000000400300043d000006730100004100000000001304350000000401300039000006be0200004100000000002104350000000001000414000000040070008c000600000007001d0000122d0000613d0000002404000039000000200600003900000000020700190000000005030019000400000003001d18200f360000040f00000004030000290000000607000029000000000001004b000012d10000613d00000001060000310000001f01600039000000200200008a000000000521016f0000000004350019000000000054004b000000000100003900000001010040390000064c0040009c000012b90000213d0000000100100190000012b90000c13d000000400040043f0000064d0060009c000012b80000213d000000200060008c000012b80000413d0000000001030433000112410000003d000016d30000013d000012b80000c13d000000000001004b000012880000613d000200000005001d000400000004001d000300000006001d0000006501000039000000000101041a00000647011001970000000002000411000000000012004b000012520000c13d000000140100008a00000000011000310000000201100367000000000101043b0005006000100278000b00000007001d0000800201000039000000240300003900000000040004150000000b0440008a00000005044002100000065502000041182016870000040f0000000606000029000000000001004b0000000902000029000000030500002900000004030000290000000204000029000012b80000613d00000064013000390000000000210435000000440130003900000008020000290000000000210435000000240130003900000007020000290000000000210435000006bf0100004100000000001304350000000401300039000000050200002900000000002104350000000001000414000000040060008c0000127d0000613d000000840400003900000000020600190000000005030019000000000600001918200f120000040f0000000105000031000000000001004b000012e00000613d0000001f01500039000000200200008a000000000421016f00000004030000290000000001340019000000000041004b000000000200003900000001020040390000064c0010009c000012b90000213d0000000100200190000012b90000c13d000000400010043f0000064d0050009c000012b80000213d000000ce01000039000000000101041a000600000001001d000a06470010019b0001128e0000003d000016d80000013d0000000a0440008a00000005044002100000065502000041182016870000040f0000000903000029000000000001004b000012b80000613d00000006010000290000064702100197000000400500043d00000044015000390000000000310435000000240150003900000008030000290000000000310435000006950100004100000000001504350000000401500039000000070300002900000000003104350000000001000414000000040020008c000012a70000c13d0000000102000031000012ae0000013d00000064040000390000000003050019000900000005001d000112ac0000003d000018180000013d000012c70000613d0000000905000029000112b00000003d000017cc0000013d0000064c0010009c000012b90000213d0000000100300190000012b90000c13d000000400010043f0000064d0020009c000012b80000213d000000000001042d0000177c0000013d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c010000410000182200010430000006bc01000041000012c40000013d000006c001000041000012c40000013d000006bd01000041000000000010043f0000064f0100004100001822000104300000000304000367000112ca0000003d000016c50000013d000012db0000613d000000000704034f0000000008010019000112cf0000003d0000176e0000013d000012cd0000c13d000012db0000013d00000003040003670000000102000031000112d50000003d000016c50000013d000012db0000613d000000000704034f0000000008010019000112da0000003d0000176e0000013d000012d80000c13d000000000006004b000012df0000613d000112df0000003d000016b90000013d182016690000040f0000000303000367000000200100008a000000000415017000000000020500190000001f0550018f000000400100043d0000000009410019000012ee0000613d000000000603034f0000000007010019000000006806043c0000000007870436000000000097004b000012ea0000c13d000000000005004b000012df0000613d000000000343034f00000003045002100000000005090433000112f50000003d000017d60000013d0000000000390435182016690000040f000f000000000002000700000004001d0000000004020019000a00000002001d0000000002000415000600000002001d000900000001001d0000000002040019000800000003001d182011a30000040f000f000a0000002d000113040000003d000016d80000013d0000000f0440008a00000005044002100000065502000041182016870000040f000000000001004b0000000001000411000500000001001d000013500000613d0000000001000415000300000001001d000000400300043d00000064013000390000008002000039000200000002001d00000000002104350000004401300039000000080200002900000000002104350000000901000029000006470110019700000024023000390000000000120435000006c1010000410000000000130435000000040130003900000000020004110000000000210435000400000003001d0000008402300039000000070100002918200f920000040f00000000040004150000000e0440008a0000000504400210000000000301001900000000010004140000000a020000290000064702200197000000040020008c000013360000613d000000040500002900000000045300490000002006000039000000000305001918200f120000040f00000000040004150000000d0440008a0000000504400210000000000001004b000014150000613d000113380000003d000017b70000013d000000040500002900000000025300190001133c0000003d0000171c0000013d0000064c0020009c000014470000213d0000000100300190000014470000c13d000000400020043f0000064d0010009c000013fb0000213d0000001f0010008c000013fb0000a13d0000000001050433000006a800100198000013fb0000c13d0000000502400270000000000201001f000000000200041500000003022000690000000002000002000006a901100197000006c10010009c0000141b0000c13d000000000100041500000006011000690000000001000002000000cb01000039000000000101041a0000064705100198000013c80000613d000000400700043d000006730100004100000000001704350000000401700039000006be0200004100000000002104350000000001000414000000040050008c000400000005001d0000136c0000613d00000024040000390000002006000039000000000205001900000000030700190000000005070019000600000007001d18200f360000040f00000006070000290000000405000029000000000001004b000013fc0000613d00000001010000310000001f02100039000000200300008a000000000232016f0000000003720019000000000023004b000000000200003900000001020040390000064c0030009c000014470000213d0000000100200190000014470000c13d000000400030043f0000064d0010009c000013fb0000213d000000200010008c000013fb0000413d0000000001070433000113800000003d000016d30000013d000013fb0000c13d000000000001004b000013c80000613d000600000003001d0000006501000039000000000101041a00000647011001970000000002000411000000000012004b0000138f0000c13d000000140100008a00000000011000310000000201100367000000000101043b0005006000100278000c00000005001d000113920000003d000016d80000013d0000000c0440008a00000005044002100000065502000041182016870000040f000000000001004b0000000603000029000013fb0000613d0000008401300039000000a00200003900000000002104350000006401300039000000080200002900000000002104350000000a010000290000064701100197000000440230003900000000001204350000000901000029000006470110019700000024023000390000000000120435000006c30100004100000000001304350000000501000029000006470110019700000004023000390000000000120435000000a402300039000000070100002918200f920000040f000000040200002900000000030100190000000001000414000000040020008c000013bc0000613d000000060500002900000000045300490000000003050019000000000600001918200f120000040f000000000001004b000013fc0000613d000113be0000003d000017b70000013d0000000602300029000113c10000003d0000171c0000013d0000064c0020009c000014470000213d0000000100300190000014470000c13d000000400020043f0000064d0010009c000013fb0000213d000000ce01000039000000000101041a000700000001001d000b06470010019b0000800201000039000000240300003900000000040004150000000b0440008a00000005044002100000065502000041182016870000040f000000000001004b000013fb0000613d00000007010000290000064702100197000000400500043d0000004401500039000000080300002900000000003104350000000a010000290000064701100197000000240350003900000000001304350000069501000041000000000015043500000009010000290000064701100197000000040350003900000000001304350000000001000414000000040020008c000013ea0000c13d0000000102000031000013f10000013d00000064040000390000000003050019000a00000005001d000113ef0000003d000018180000013d000014070000613d0000000a05000029000113f30000003d000017cc0000013d0000064c0010009c000014470000213d0000000100300190000014470000c13d000000400010043f0000064d0020009c000013fb0000213d000000000001042d0000177c0000013d00000003040003670000000102000031000114000000003d000016c50000013d000014100000613d000000000704034f0000000008010019000114050000003d0000176e0000013d000014030000c13d000014100000013d00000003040003670001140a0000003d000016c50000013d000014100000613d000000000704034f00000000080100190001140f0000003d0000176e0000013d0000140d0000c13d000000000006004b000014140000613d000114140000003d000016b90000013d182016690000040f00000001020000320000141f0000c13d00000060010000390000000002010433000000000002004b0000144d0000c13d000006c201000041000000000010043f0000064f0100004100001822000104300000064c0020009c000014470000213d0000001f01200039000000200300008a000000000131016f0000003f01100039000000000331016f000000400100043d0000000003310019000000000013004b000000000400003900000001040040390000064c0030009c000014470000213d0000000100400190000014470000c13d000000400030043f0000000005210436000000200300008a00000000033201700000001f0420018f000200000005001d000000000235001900000003050003670000143e0000613d000000000605034f0000000207000029000000006806043c0000000007870436000000000027004b0000143a0000c13d000000000004004b000014180000613d000000000335034f00000003044002100000000005020433000114450000003d000017d60000013d0000000000320435000014180000013d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c0100004100001822000104300000000201000029182016690000040f000000000001004b000014530000c13d18200fe10000040f000000000001042d0000069d01000041000000000010043f0000064f0100004100001822000104300000000043010434000006ad0030009c000014a00000813d000000d202000039000000000502041a000000010650019000000001055002700000007f0550618f0000001f0050008c00000000070000390000000107002039000000000076004b000014a40000c13d000000200050008c000014740000413d000000000020043f0000001f063000390000000506600270000006c40660009a000000200030008c00000698060040410000001f055000390000000505500270000006c40550009a000000000056004b000014740000813d000000000006041b00000001066000390000146f0000013d0000001f0030008c000014850000a13d000000000020043f000000200400008a000000000543016f000000200600003900000698040000410000000007000019000000000057004b0000000008160019000014890000813d0000000008080433000000000084041b0000002007700039000000200660003900000001044000390000147c0000013d000000000003004b000014960000613d0000000001040433000014970000013d000000000035004b000014930000813d0000000301300210000000f80110018f000000010500008a000000000115022f000000000151013f0000000005080433000000000115016f000000000014041b000000010130021000000001011001bf0000149e0000013d00000000010000190000000304300210000000010500008a000000000445022f000000000454013f000000000141016f0000000103300210000000000131019f000000000012041b000000000001042d0000067b01000041000000000010043f0000004101000039000014a70000013d0000067b01000041000000000010043f0000002201000039000000040010043f0000067c010000410000182200010430000000000001004b000014ad0000613d000000000001042d000000400100043d0000006402100039000006c50300004100000000003204350000004402100039000006c603000041000000000032043500000024021000390000002b0300003900000000003204350000064a0200004100000000002104350000000402100039000000200300003900000000003204350000008402000039182016690000040f0002000000000002182011790000040f000006c701000041000000400300043d000000000013043500000000010004140000000002000410000000040020008c000014cf0000613d000000040400003900000000050300190000000006000019000200000003001d18200f360000040f0000000203000029000000000001004b000015190000613d0000000304000367000000200200008a000000010100003100000000052101700000001f0610018f000000000a530019000014dc0000613d000000000704034f0000000008030019000000007907043c00000000089804360000000000a8004b000014d80000c13d000000000006004b000014e40000613d000000000454034f000000030560021000000000060a0433000114e30000003d000017f60000013d00000000004a04350000001f04100039000000000424016f0000000002340019000000000042004b000000000400003900000001040040390000064c0020009c0000150f0000213d00000001004001900000150f0000c13d000000400020043f0000064d0010009c0000150e0000213d0000001f0010008c0000150e0000a13d00000000040304330000064c0040009c0000150e0000213d000000000231001900000000013400191820110b0000040f0000066102000041000000000302041a000000000003004b000015130000613d000000400200043d000006ba0020009c0000150f0000813d000000d104000039000000000404041a0000008005200039000000400050043f000000600520003900000001060000390000000000650435000000010330008a00000040052000390000000000350435000000200320003900000000004304350000000000120435000017d40000013d0000177c0000013d0000067b01000041000000000010043f0000004101000039000015160000013d0000067b01000041000000000010043f0000001101000039000000040010043f0000067c0100004100001822000104300000000304000367000000200100008a000000010200003100000000051201700000001f0620018f000000400100043d0000000003510019000015260000613d000000000704034f0000000008010019000115250000003d0000176e0000013d000015230000c13d000000000006004b0000152a0000613d0001152a0000003d000016b90000013d182016690000040f0000064701100197000000000010043f0000067701000041000000200010043f1820167b0000040f000000000001042d0000064702200197000000000020043f000000200010043f1820167b0000040f000000000001042d0001000000000002000000000001004b000015530000613d000000000010043f0000069002000041000000200020043f000100000001001d1820167b0000040f000000000101041a000000000001004b000015500000c13d0000066101000041000000000101041a0000000102000029000000000021004b000015530000a13d000000010220008a000100000002001d000000000020043f0000069001000041000000200010043f1820167b0000040f0000000102000029000000000101041a000000000001004b000015460000613d000006c800100198000015530000c13d000000000001042d000006c901000041000000000010043f0000064f0100004100001822000104300001000000000002000100000001001d182015680000040f000000000001004b000015640000613d0000000101000029000000000010043f0000068d01000041000000200010043f1820167b0000040f000000000101041a0000064701100197000000000001042d000006ca01000041000000000010043f0000064f0100004100001822000104300001000000000002000000000001004b000015830000613d00000000020100190000066101000041000000000101041a000000000021004b0000000001000019000015880000a13d000100000002001d000000000020043f0000069001000041000000200010043f1820167b0000040f000000000101041a000000000001004b000015850000c13d0000000102000029000000000002004b000000010220008a000015710000c13d0000067b01000041000000000010043f0000001101000039000000040010043f0000067c0100004100001822000104300000000001000019000000000001042d000006c80010019800000000010000390000000101006039000000000001042d0005000000000002000400000001001d0000066101000041000000000101041a000300000001001d0000800b0100003900000004030000390000000004000415000000050440008a00000005044002100000068f02000041182016870000040f0000000302000029000000000020043f0000069002000041000000200020043f0000000402000029000406470020019b000000a00110021000000004011001af00020692001001cb1820167b0000040f0000000202000029000000000021041b0000000401000029000000000010043f0000068001000041000115a60000003d000017c80000013d000006cb0220009a000000000021041b000000040000006b000015c20000613d00000000010000190000000100100190000015bd0000c13d0000000001000414000006090010009c0000060901008041000000c00110021000000653011001c70000800d0200003900000004030000390000069304000041000000000500001900000004060000290000000307000029182016a50000040f00000001002001900000000101000039000015ab0000c13d0000177c0000013d000000030100002900000001011000390000066102000041000000000012041b000000000001042d000006cc01000041000000000010043f0000064f0100004100001822000104300005000000000002000300000001001d000200000002001d000000000002004b000016110000613d0000066101000041000000000101041a000400000001001d0000800b0100003900000004030000390000000004000415000000050440008a00000005044002100000068f02000041182016870000040f0000000402000029000000000020043f0000069002000041000000200020043f000000a0011002100000000202000029000000010020008c00000000020000190000069202006041000000000112019f0000000302000029000306470020019b00000003011001af000100000001001d1820167b0000040f0000000102000029000000000021041b0000000301000029000000000010043f0000068001000041000000200010043f1820167b0000040f0000000202000029000006cd022000d1000000000301041a0000000002230019000000000021041b000000030000006b000016130000613d0000000201000029000200040010002d00000000010000190000000100100190000015fc0000613d00000004070000290000000107700039000000020070006c000015fd0000c13d0000160d0000013d00000004070000290000000001000414000006090010009c0000060901008041000000c00110021000000653011001c70000800d020000390000000403000039000006930400004100000000050000190000000306000029000400000007001d182016a50000040f00000001002001900000000101000039000015f50000c13d0000177c0000013d00000661010000410000000202000029000000000021041b000000000001042d000006ce01000041000016140000013d000006cc01000041000000000010043f0000064f01000041000018220001043000010000000000020000000002010019000000400100043d0000002003100039000006730400004100000000004304350000002405100039000000000045043500000024040000390000000000410435000006cf0010009c000016390000813d0000006004100039000000400040043f000000040020008c0000162a0000c13d0000000001030433000000000010043f0000162e0000013d0001162c0000003d000017480000013d000016360000613d000000000100043d0000000102000031000000200020008c0000000002000019000016370000413d000000000001004b0000000002000039000000010200c039000016370000013d0000000002000019000000010120018f000000000001042d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c01000041000018220001043000010000000000020000000002010019000000400100043d0000002003100039000006730400004100000000004304350000002404100039000006a905000041000000000054043500000024040000390000000000410435000006cf0010009c000016620000813d0000006004100039000000400040043f000000040020008c000016530000c13d0000000001030433000000000010043f000016570000013d000116550000003d000017480000013d0000165f0000613d000000000100043d0000000102000031000000200020008c0000000002000019000016600000413d000000000001004b0000000002000039000000010200c039000016600000013d0000000002000019000000010120018f000000000001042d0000067b01000041000000000010043f0000004101000039000000040010043f0000067c010000410000182200010430000000000001042f000006090010009c00000609010080410000004001100210000006090020009c00000609020080410000006002200210000000000112019f0000182200010430000006090010009c00000609010080410000004001100210000006090020009c00000609020080410000006002200210000000000112019f000000e002300210000000000121019f000018210001042e0000000001000414000006090010009c0000060901008041000000c001100210000006d0011001c70000801002000039182016aa0000040f0000000100200190000016860000613d000000000101043b000000000001042d0000177c0000013d00000000050100190000000000200443000000050030008c000016950000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b0000168d0000413d000006090030009c000006090300804100000060013002100000000002000414000006090020009c0000060902008041000000c002200210000000000112019f000006d1011001c70000000002050019182016aa0000040f0000000100200190000016a40000613d000000000101043b000000000001042d000000000001042f000016a8002104210000000102000039000000000001042d0000000002000019000000000001042d000016ad002104230000000102000039000000000001042d0000000002000019000000000001042d000000000201041a000000010020019000000001012002700000007f0110618f0000001f0010008c00000000030000390000000103002039000000000232013f0000000100200190000000010000013b000000000454034f0000000305600210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000430435000000010000013b000000200100008a00000000051201700000001f0620018f000000400100043d0000000003510019000000010000013b0000000302400210000000010300008a000000000223022f000000000232013f000000000121016f0000000102400210000000000121019f000000010000013b000000000001004b0000000002000039000000010200c039000000000021004b000000010000013b000080020100003900000024030000390000000004000415000000010000013b00000001010000310000001f02100039000000200300008a000000000332016f0000000002530019000000000032004b00000000030000390000000103004039000000010000013b000000000010043f000000ca01000039000000200010043f1820167b0000040f000000000101041a000000000001004b000000010000013b000000140100008a00000000011000310000000201100367000000000101043b0000006001100270000000010000013b00000012020000290000000302200210000000f80220018f000000010300008a000000000223022f000000000232013f0000000003050433000000000223016f000000000021041b000000010000013b182010890000040f000000000100041a0000000801100270000000ff0110018f000e00000001001d182014aa0000040f0000000e01000029182014aa0000040f00000001010000390000009702000039000000000012041b0000001201000029182010890000040f00000005010000290000000001010433000000010000013b00000007020000290000000002020433000900000002001d0000000e0110002900000002020000291820110b0000040f000800000001001d000000000100041a0000000801100270000000ff0110018f000e00000001001d182014aa0000040f000000040100002900000000010104330000ffff0110018f000000010000013b000000000032004b00000000030000390000000103004039000000010000013b0000001f010000390000000101100031000000200200008a000000000221016f0000000001320019000000000021004b00000000020000390000000102004039000000010000013b0000000005030019000000000600001918200f120000040f000000000001004b000000010000013b00000003011001af000000000012041b000000000100041a0000000801100270000000ff0110018f001200000001001d182014aa0000040f0000001201000029182014aa0000040f0000000d010000290000000001010433001200000001001d000000010000013b0000000b011001af000000000012041b000000d1010000390000000902000029000000000021041b0000000801000029182014570000040f0000000a01000029182010eb0000040f00000011010000290000000001010433001200000001001d000000010000013b000000000401043300007530010000390000002006000039000000000500001918200f360000040f000000000001004b000000010000013b000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000010000013b000000000403041a000000a005200039000000000045043500000020022000390000000103300039000000010000013b000000010400008a000000000224022f000000000242013f000000000223016f000000000112019f000000010000013b0000001202000029182011430000040f00000012020000290000001f0020008c00000001012002100000000302200210000000010000013b000000007907043c0000000008980436000000000038004b000000010000013b000000000704043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f0000000000540435000000010000013b0000000001000019000018220001043000000001010000310000001f02100039000000200300008a000000000232016f0000000003520019000000000023004b00000000020000390000000102004039001100000003001d000000010000013b0000000102000039000000000021041b000000000100041a0000000801100270000000ff0110018f182014aa0000040f0000006502000039000000000102041a000000010000013b0000001f01200039000000200300008a000000000131016f0000000f03100029000000000013004b00000000010000390000000101004039001000000003001d000000010000013b000080020100003900000024030000390000000004000415000000270440008a0000000504400210000000010000013b000000010320019000000001012002700000007f0110618f0000001f0010008c00000000040000390000000104002039000000000442013f0000000100400190000000010000013b00000001010000390000009702000039000000000012041b000000400100043d000000010000013b000000f80220018f000000010500008a000000000225022f000000000252013f000000000474034f000000000404043b000000000224016f000000000023041b000000010000013b00000001010000310000001f02100039000000200300008a000000000332016f000000010000013b0000001205000029000000000600001918200f120000040f0000001203000029000000000001004b000000010000013b0000000005050433000000000051041b000000200440003900000020033000390000000101100039000000010000013b000000200010043f1820167b0000040f000000000201041a000000010000013b0000001f01200039000000200300008a000000000331016f0000000001530019000000000031004b00000000030000390000000103004039000000010000013b0000000001020019000000000001042d00000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f000000010000013b000000f80220018f000000010400008a000000000224022f000000000242013f0000000004070433000000000224016f000000000023041b000000010000013b0000000e0110002900000002020000291820110b0000040f000c00000001001d0000000b010000290000000001010433000b00000001001d000000010000013b0000000e024000290000000e01100029000200000002001d1820110b0000040f001100000001001d0000000d010000290000000001010433000000010000013b00000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f000000010000013b000000000010043f000000200100008a000000120210017f0000002003000039000000010000013b0000000e01000029182014aa0000040f0000000e01000029182014aa0000040f0000006501000039000000000101041a000000010000013b0000000001000415001100000001001d182010d60000040f0000001201000029182016170000040f000000000001004b000000010000013b0000000e0110002900000002020000291820110b0000040f000d00000001001d0000000c010000290000000001010433000000010000013b000000000600001918200f120000040f0000000102000031000000000001004b000000010000013b000100000003001f0003000000010355000017d40000013d0000182000000432000018210001042e0000182200010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff000000020000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000f9c0611c0000000000000000000000000000000000000000000000000000000004dafa4b00000000000000000000000000000000000000000000000000000000063a7502000000000000000000000000000000000000000000000000000000000690a78d0000000000000000000000000000000000000000000000000000000006fdde0300000000000000000000000000000000000000000000000000000000081812fc00000000000000000000000000000000000000000000000000000000095ea7b3000000000000000000000000000000000000000000000000000000000fd9446c0000000000000000000000000000000000000000000000000000000017360d340000000000000000000000000000000000000000000000000000000018160ddd0000000000000000000000000000000000000000000000000000000018bae6c8000000000000000000000000000000000000000000000000000000001b30808d000000000000000000000000000000000000000000000000000000001d9904260000000000000000000000000000000000000000000000000000000023b872dd000000000000000000000000000000000000000000000000000000002a55205a000000000000000000000000000000000000000000000000000000002a5ac76400000000000000000000000000000000000000000000000000000000336211bf000000000000000000000000000000000000000000000000000000003659cfe600000000000000000000000000000000000000000000000000000000377e5e270000000000000000000000000000000000000000000000000000000042842e0e0000000000000000000000000000000000000000000000000000000042966c680000000000000000000000000000000000000000000000000000000046134b500000000000000000000000000000000000000000000000000000000047230dcb000000000000000000000000000000000000000000000000000000004f1ef2860000000000000000000000000000000000000000000000000000000050cf5a310000000000000000000000000000000000000000000000000000000052d1902d00000000000000000000000000000000000000000000000000000000572b6c05000000000000000000000000000000000000000000000000000000006352211e000000000000000000000000000000000000000000000000000000006502abea00000000000000000000000000000000000000000000000000000000662fff38000000000000000000000000000000000000000000000000000000006d87e4810000000000000000000000000000000000000000000000000000000070a0823100000000000000000000000000000000000000000000000000000000715018a600000000000000000000000000000000000000000000000000000000834a20df000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000009217270400000000000000000000000000000000000000000000000000000000949d225d0000000000000000000000000000000000000000000000000000000095d89b4100000000000000000000000000000000000000000000000000000000a22cb46500000000000000000000000000000000000000000000000000000000a305f5b200000000000000000000000000000000000000000000000000000000abf90f7b00000000000000000000000000000000000000000000000000000000b0e5afe300000000000000000000000000000000000000000000000000000000b5c5801e00000000000000000000000000000000000000000000000000000000b859c93500000000000000000000000000000000000000000000000000000000b88d4fde00000000000000000000000000000000000000000000000000000000c2f5070100000000000000000000000000000000000000000000000000000000c87b56dd00000000000000000000000000000000000000000000000000000000ddf990f900000000000000000000000000000000000000000000000000000000e382c90700000000000000000000000000000000000000000000000000000000e8a3d48500000000000000000000000000000000000000000000000000000000e985e9c500000000000000000000000000000000000000000000000000000000eb87215000000000000000000000000000000000000000000000000000000000ee295d6200000000000000000000000000000000000000000000000000000000ef60ceaf00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000f97b57ec0000000000000000000000000000000000000000000000000000000001ffc9a70000000000000000000000003cc6cdda760b79bafa08df41ecfa224f810dceb666be4f155c5ef2ebd3772b228f2f00681e4ed5826cdb3b1943cc11ad15ad1d28000000000000000000000000000000000000000000000000ffffffffffffff7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff64647265737300000000000000000000000000000000000000000000000000004f776e61626c653a206e6577206f776e657220697320746865207a65726f206108c379a00000000000000000000000000000000000000000000000000000000049a5c0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c39c41c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000ffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002c5ea6e4103e78cb101e796fb2dace540362fc542cbff5145eaa24af7dd8fe411806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83d10072c000000000000000000000000000000000000000000000000000000000e89d44c8fd6a9bac8af33ce47f56337617d449bf7ff3956b618c646de829cbcb000000000000000000000000000000000000000000000000ffffffffffffff41ffffffffffffffffffffffffffffffffffffffffffffffff00000000000000807d3e3dbe0000000000000000000000000000000000000000000000000000000009ee12d500000000000000000000000000000000000000000000000000000000d018c0fa00000000000000000000000000000000000000000000000000000000e236d251e7da4ac8a3c275f80aebc9b74cbf356425fa04864da5043511a81219eabab422000000000000000000000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000002569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c40ce2003a500000000000000000000000000000000000000000000000000000000c407dfe559ca4a63d7cf8439b9fce2965d7a4c8c92eb5d5047f53bb9eec295fd16365cdd000000000000000000000000000000000000000000000000000000004a3891c200000000000000000000000000000000000000000000000000000000bf317c2a00000000000000000000000000000000000000000000000000000000647920696e697469616c697a6564000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c726561000000000000000000000000000000000000000000000000ffffffffffffffbf2569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c42933ecf8acb7824b680a8d16f3ff3db8864228d986aa4c2ebab1eeb2703b4beb32569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c43617167b76dcc8247761fd21f427ad8ec3be6b3be203aed34e3aac08b4d31817cf20a10ce76a8f4f0e4a804c5623806cf04350dc8186b7e02f95c562e94be3331f872381d0000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498f6bdd07c0000000000000000000000000000000000000000000000000000000001ffc9a70000000000000000000000000000000000000000000000000000000076413c5e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f85e335b6000000000000000000000000000000000000000000000000000000002569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c47020000000000000000000000000000000000002000000080000000000000000017307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319941b0eaa3a10d142c88d4dd70d0ff97e1b12a7d9324c4e6bc33ee52ea52e2d94e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000073e05f4c0a27cbf60841afa4a2f8577f5e99db3e3e9c293800d6e6b1f7b8a7aba9292a6f000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e02569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c458f4eb60400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e555550535570677261646561626c653a206d757374206e6f742062652063616c6c6564207468726f7567682064656c656761746563616c6c0000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8808898a00000000000000000000000000000000000000000000000000000000bcdbc94700000000000000000000000000000000000000000000000000000000e10a05050000000000000000000000000000000000000000000000000000000034e70f7a00000000000000000000000000000000000000000000000000000000ea6eb5c300000000000000000000000000000000000000000000000000000000129dae8b000000000000000000000000000000000000000000000000000000002569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c46ffffffffffffffffffffffffffffffff00000000000000000000000000000001796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391322569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c4400000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef2569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c4123de665100000000000000000000000000000000000000000000000000000000ceea21b6000000000000000000000000000000000000000000000000000000005bf57bc300000000000000000000000000000000000000000000000000000000f2192e1030363415d7b4fb0406540a0060e8e2fc8982f3f32289379e11fa654652df9fe50000000000000000000000000000000000000000000000000000000045a9661700000000000000000000000000000000000000000000000000000000f8d2906c00000000000000000000000000000000000000000000000000000000c4e1e8cc00000000000000000000000000000000000000000000000000000000eb492903000000000000000000000000000000000000000000000000000000002ec2c24600000000000000000000000000000000000000000000000000000000cfb3b942000000000000000000000000000000000000000000000000000000008c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9251a3973a9000000000000000000000000000000000000000000000000000000009d22e78e0000000000000000000000000000000000000000000000000000000082b429000000000000000000000000000000000000000000000000000000000074c1ace100000000000000000000000000000000000000000000000000000000ffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9d4b38394dff663b46f53f52ced584161b5021180321b381f6104325eecebf49fd120bd20000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000080ac58cd000000000000000000000000000000000000000000000000000000005b5e139f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000001000000000000000080000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe04f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657246756e6374696f6e206d7573742062652063616c6c6564207468726f756768206163746976652070726f787900000000000000000000000000000000000000004e6f74207570677261646561626c65000000000000000000000000000000000064656c656761746563616c6c00000000000000000000000000000000000000005265656e7472616e637947756172643a207265656e7472616e742063616c6c009941b0eaa3a10d142c88d4dd70d0ff97e1b12a7d9324c4e6bc33ee52ea52e2d86cc130753487db497f572e90c00c24779bdd7267955b3d1454e114d8fc4b414d9e8e984892337db889e02de0bd852713c4194c41dfc512cb1c553f74b2ce7e841762bb3702956453750cc31b80a9cc89e82bb640800c6a949e739b9217d63435000000000000000000000000000000000000000000000000ffffffffffffff80000000000000000000000000000000000000000000000000ffffffffffffffc0a11481000000000000000000000000000000000000000000000000000000000059c896be00000000000000000000000000000000000000000000000000000000f5e8d69e000000000000000000000000000000000000000000000000000000007f1eaf8500000000000000000000000000000000000000000000000000000000ea553b3400000000000000000000000000000000000000000000000000000000150b7a0200000000000000000000000000000000000000000000000000000000d1a57ed6000000000000000000000000000000000000000000000000000000008af6791b000000000000000000000000000000000000000000000000000000000de6d1efcfc9cbea284b04fbf9abf5ff9f171d03767d0c0cdd76c861ee059aba6e697469616c697a696e67000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206906fdde03000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000df2d9b4200000000000000000000000000000000000000000000000000000000cf4700e400000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffff2e076300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001b562e8dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffa0020000000000000000000000000000000000004000000000000000000000000002000002000000000000000000000000000000000000000000000000000000006a866921785126764d620de7d4fb50e2c34f2ea3441f6b876b4cc08d73ea1f4d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.