¡El código fuente de este contrato está verificado!
Metadatos del Contrato
Compilador
0.8.10+commit.fc410830
Idioma
Solidity
Código Fuente del Contrato
Archivo 1 de 5: DropMetadataRenderer.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.10;import {StringsUpgradeable} from"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
import {IMetadataRenderer} from"../interfaces/IMetadataRenderer.sol";
import {MetadataRenderAdminCheck} from"./MetadataRenderAdminCheck.sol";
/// @notice Drops metadata systemcontractDropMetadataRendererisIMetadataRenderer, MetadataRenderAdminCheck{
errorMetadataFrozen();
/// Event to mark updated metadata informationeventMetadataUpdated(addressindexed target,
string metadataBase,
string metadataExtension,
string contractURI,
uint256 freezeAt
);
/// @notice Hash to mark updated provenance hasheventProvenanceHashUpdated(addressindexed target, bytes32 provenanceHash);
/// @notice Struct to store metadata info and update datastructMetadataURIInfo {
string base;
string extension;
string contractURI;
uint256 freezeAt;
}
/// @notice NFT metadata by contractmapping(address=> MetadataURIInfo) public metadataBaseByContract;
/// @notice Optional provenance hashes for NFT metadata by contractmapping(address=>bytes32) public provenanceHashes;
/// @notice Standard init for drop metadata from root drop contract/// @param data passed in for initializationfunctioninitializeWithData(bytesmemory data) external{
// data format: string baseURI, string newContractURI
(stringmemory initialBaseURI, stringmemory initialContractURI) =abi
.decode(data, (string, string));
_updateMetadataDetails(
msg.sender,
initialBaseURI,
"",
initialContractURI,
0
);
}
/// @notice Update the provenance hash (optional) for a given nft/// @param target target address to update/// @param provenanceHash provenance hash to setfunctionupdateProvenanceHash(address target, bytes32 provenanceHash)
externalrequireSenderAdmin(target)
{
provenanceHashes[target] = provenanceHash;
emit ProvenanceHashUpdated(target, provenanceHash);
}
/// @notice Update metadata base URI and contract URI/// @param baseUri new base URI/// @param newContractUri new contract URI (can be an empty string)functionupdateMetadataBase(address target,
stringmemory baseUri,
stringmemory newContractUri
) externalrequireSenderAdmin(target) {
_updateMetadataDetails(target, baseUri, "", newContractUri, 0);
}
/// @notice Update metadata base URI, extension, contract URI and freezing detailsUpdate metadata base URI, extension, contract URI and freezing detailsUpdate metadata base URI, extension, contract URI and freezing detailsUpdate metadata base URI, extension, contract URI and freezing detailsUpdate metadata base URI, extension, contract URI and freezing detailsUpdate metadata base URI, extension, contract URI and freezing detailsUpdate metadata base URI, extension, contract URI and freezing detailsUpdate metadata base URI, extension, contract URI and freezing details/// @param target target contract to update metadata for/// @param metadataBase new base URI to update metadata with/// @param metadataExtension new extension to append to base metadata URI/// @param freezeAt time to freeze the contract metadata at (set to 0 to disable)functionupdateMetadataBaseWithDetails(address target,
stringmemory metadataBase,
stringmemory metadataExtension,
stringmemory newContractURI,
uint256 freezeAt
) externalrequireSenderAdmin(target) {
_updateMetadataDetails(
target,
metadataBase,
metadataExtension,
newContractURI,
freezeAt
);
}
/// @notice Internal metadata update function/// @param metadataBase Base URI to update metadata for/// @param metadataExtension Extension URI to update metadata for/// @param freezeAt timestamp to freeze metadata (set to 0 to disable freezing)function_updateMetadataDetails(address target,
stringmemory metadataBase,
stringmemory metadataExtension,
stringmemory newContractURI,
uint256 freezeAt
) internal{
if (freezeAt !=0&& freezeAt >block.timestamp) {
revert MetadataFrozen();
}
metadataBaseByContract[target] = MetadataURIInfo({
base: metadataBase,
extension: metadataExtension,
contractURI: newContractURI,
freezeAt: freezeAt
});
emit MetadataUpdated({
target: target,
metadataBase: metadataBase,
metadataExtension: metadataExtension,
contractURI: newContractURI,
freezeAt: freezeAt
});
}
/// @notice A contract URI for the given drop contract/// @dev reverts if a contract uri is not provided/// @return contract uri for the contract metadatafunctioncontractURI() externalviewoverridereturns (stringmemory) {
stringmemory uri = metadataBaseByContract[msg.sender].contractURI;
if (bytes(uri).length==0) revert();
return uri;
}
/// @notice A token URI for the given drops contract/// @dev reverts if a contract uri is not set/// @return token URI for the given token ID and contract (set by msg.sender)functiontokenURI(uint256 tokenId)
externalviewoverridereturns (stringmemory)
{
MetadataURIInfo memory info = metadataBaseByContract[msg.sender];
if (bytes(info.base).length==0) revert();
returnstring(
abi.encodePacked(
info.base,
StringsUpgradeable.toString(tokenId),
info.extension
)
);
}
}
Código Fuente del Contrato
Archivo 2 de 5: IERC721Drop.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.10;import {IMetadataRenderer} from"../interfaces/IMetadataRenderer.sol";
/**
________ _____ ____ ______ ____
/\_____ \ /\ __`\/\ _`\ /\ _ \ /\ _`\
\/____//'/'\ \ \/\ \ \ \L\ \ \ \L\ \ \ \ \/\ \ _ __ ___ _____ ____
//'/' \ \ \ \ \ \ , /\ \ __ \ \ \ \ \ \/\`'__\/ __`\/\ '__`\ /',__\
//'/'___ \ \ \_\ \ \ \\ \\ \ \/\ \ \ \ \_\ \ \ \//\ \L\ \ \ \L\ \/\__, `\
/\_______\\ \_____\ \_\ \_\ \_\ \_\ \ \____/\ \_\\ \____/\ \ ,__/\/\____/
\/_______/ \/_____/\/_/\/ /\/_/\/_/ \/___/ \/_/ \/___/ \ \ \/ \/___/
\ \_\
\/_/
*//// @notice Interface for ZORA Drops contractinterfaceIERC721Drop{
// Access errors/// @notice Only admin can access this functionerrorAccess_OnlyAdmin();
/// @notice Missing the given role or admin accesserrorAccess_MissingRoleOrAdmin(bytes32 role);
/// @notice Withdraw is not allowed by this usererrorAccess_WithdrawNotAllowed();
/// @notice Cannot withdraw funds due to ETH send failure.errorWithdraw_FundsSendFailure();
// Sale/Purchase errors/// @notice Sale is inactiveerrorSale_Inactive();
/// @notice Presale is inactiveerrorPresale_Inactive();
/// @notice Presale merkle root is invaliderrorPresale_MerkleNotApproved();
/// @notice Wrong price for purchaseerrorPurchase_WrongPrice(uint256 correctPrice);
/// @notice NFT sold outerrorMint_SoldOut();
/// @notice Too many purchase for addresserrorPurchase_TooManyForAddress();
/// @notice Too many presale for addresserrorPresale_TooManyForAddress();
// Admin errors/// @notice Royalty percentage too higherrorSetup_RoyaltyPercentageTooHigh(uint16 maxRoyaltyBPS);
/// @notice Invalid admin upgrade addresserrorAdmin_InvalidUpgradeAddress(address proposedAddress);
/// @notice Unable to finalize an edition not marked as open (size set to uint64_max_value)errorAdmin_UnableToFinalizeNotOpenEdition();
/// @notice Event emitted for each sale/// @param to address sale was made to/// @param quantity quantity of the minted nfts/// @param pricePerToken price for each token/// @param firstPurchasedTokenId first purchased token ID (to get range add to quantity for max)eventSale(addressindexed to,
uint256indexed quantity,
uint256indexed pricePerToken,
uint256 firstPurchasedTokenId
);
/// @notice General configuration for NFT Minting and bookkeepingstructConfiguration {
/// @dev Metadata renderer (uint160)
IMetadataRenderer metadataRenderer;
/// @dev Total size of edition that can be minted (uint160+64 = 224)uint64 editionSize;
/// @dev Royalty amount in bps (uint224+16 = 240)uint16 royaltyBPS;
/// @dev Funds recipient for sale (new slot, uint160)addresspayable fundsRecipient;
}
/// @notice Sales states and configuration/// @dev Uses 3 storage slotsstructSalesConfiguration {
/// @dev Public sale price (max ether value > 1000 ether with this value)uint104 publicSalePrice;
/// @notice Purchase mint limit per address (if set to 0 === unlimited mints)/// @dev Max purchase number per txn (90+32 = 122)uint32 maxSalePurchasePerAddress;
/// @dev uint64 type allows for dates into 292 billion years/// @notice Public sale start timestamp (136+64 = 186)uint64 publicSaleStart;
/// @notice Public sale end timestamp (186+64 = 250)uint64 publicSaleEnd;
/// @notice Presale start timestamp/// @dev new storage slotuint64 presaleStart;
/// @notice Presale end timestampuint64 presaleEnd;
/// @notice Presale merkle rootbytes32 presaleMerkleRoot;
}
/// @notice Return value for sales details to use with front-endsstructSaleDetails {
// Synthesized status variables for sale and presalebool publicSaleActive;
bool presaleActive;
// Price for public saleuint256 publicSalePrice;
// Timed sale actions for public saleuint64 publicSaleStart;
uint64 publicSaleEnd;
// Timed sale actions for presaleuint64 presaleStart;
uint64 presaleEnd;
// Merkle root (includes address, quantity, and price data for each entry)bytes32 presaleMerkleRoot;
// Limit public sale to a specific number of mints per walletuint256 maxSalePurchasePerAddress;
// Information about the rest of the supply// Total that have been minteduint256 totalMinted;
// The total supply availableuint256 maxSupply;
}
/// @notice Return type of specific mint counts and details per addressstructAddressMintDetails {
/// Number of total mints from the given addressuint256 totalMints;
/// Number of presale mints from the given addressuint256 presaleMints;
/// Number of public mints from the given addressuint256 publicMints;
}
/// @notice External purchase function (payable in eth)/// @param quantity to purchase/// @return first minted token IDfunctionpurchase(uint256 quantity) externalpayablereturns (uint256);
/// @notice External purchase presale function (takes a merkle proof and matches to root) (payable in eth)/// @param quantity to purchase/// @param maxQuantity can purchase (verified by merkle root)/// @param pricePerToken price per token allowed (verified by merkle root)/// @param merkleProof input for merkle proof leaf verified by merkle root/// @return first minted token IDfunctionpurchasePresale(uint256 quantity,
uint256 maxQuantity,
uint256 pricePerToken,
bytes32[] memory merkleProof
) externalpayablereturns (uint256);
/// @notice Function to return the global sales details for the given dropfunctionsaleDetails() externalviewreturns (SaleDetails memory);
/// @notice Function to return the specific sales details for a given address/// @param minter address for minter to return mint information forfunctionmintedPerAddress(address minter)
externalviewreturns (AddressMintDetails memory);
/// @notice This is the opensea/public owner setting that can be set by the contract adminfunctionowner() externalviewreturns (address);
/// @notice This is an admin mint function to mint a quantity to a specific address/// @param to address to mint to/// @param quantity quantity to mint/// @return the id of the first minted NFTfunctionadminMint(address to, uint256 quantity) externalreturns (uint256);
/// @notice This is an admin mint function to mint a single nft each to a list of addresses/// @param to list of addresses to mint an NFT each to/// @return the id of the first minted NFTfunctionadminMintAirdrop(address[] memory to) externalreturns (uint256);
/// @dev Getter for admin role associated with the contract to handle metadata/// @return boolean if address is adminfunctionisAdmin(address user) externalviewreturns (bool);
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.10;import {IERC721Drop} from"../interfaces/IERC721Drop.sol";
contractMetadataRenderAdminCheck{
errorAccess_OnlyAdmin();
/// @notice Modifier to require the sender to be an admin/// @param target address that the user wants to modifymodifierrequireSenderAdmin(address target) {
if (target !=msg.sender&&!IERC721Drop(target).isAdmin(msg.sender)) {
revert Access_OnlyAdmin();
}
_;
}
}
Código Fuente del Contrato
Archivo 5 de 5: StringsUpgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)pragmasolidity ^0.8.0;/**
* @dev String operations.
*/libraryStringsUpgradeable{
bytes16privateconstant _HEX_SYMBOLS ="0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
// Inspired by OraclizeAPI's implementation - MIT licence// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.solif (value ==0) {
return"0";
}
uint256 temp = value;
uint256 digits;
while (temp !=0) {
digits++;
temp /=10;
}
bytesmemory buffer =newbytes(digits);
while (value !=0) {
digits -=1;
buffer[digits] =bytes1(uint8(48+uint256(value %10)));
value /=10;
}
returnstring(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
if (value ==0) {
return"0x00";
}
uint256 temp = value;
uint256 length =0;
while (temp !=0) {
length++;
temp >>=8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = _HEX_SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
}