¡El código fuente de este contrato está verificado!
Metadatos del Contrato
Compilador
0.8.19+commit.7dd6d404
Idioma
Solidity
¡El código fuente de este contrato está verificado!
Metadatos del Contrato
Compilador
0.8.18+commit.87f61d96
Idioma
Solidity
Código Fuente del Contrato
Archivo 1 de 14: BitMaps.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/BitMaps.sol)pragmasolidity ^0.8.0;/**
* @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential.
* Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
*/libraryBitMaps{
structBitMap {
mapping(uint256=>uint256) _data;
}
/**
* @dev Returns whether the bit at `index` is set.
*/functionget(BitMap storage bitmap, uint256 index) internalviewreturns (bool) {
uint256 bucket = index >>8;
uint256 mask =1<< (index &0xff);
return bitmap._data[bucket] & mask !=0;
}
/**
* @dev Sets the bit at `index` to the boolean `value`.
*/functionsetTo(BitMap storage bitmap, uint256 index, bool value) internal{
if (value) {
set(bitmap, index);
} else {
unset(bitmap, index);
}
}
/**
* @dev Sets the bit at `index`.
*/functionset(BitMap storage bitmap, uint256 index) internal{
uint256 bucket = index >>8;
uint256 mask =1<< (index &0xff);
bitmap._data[bucket] |= mask;
}
/**
* @dev Unsets the bit at `index`.
*/functionunset(BitMap storage bitmap, uint256 index) internal{
uint256 bucket = index >>8;
uint256 mask =1<< (index &0xff);
bitmap._data[bucket] &=~mask;
}
}
Código Fuente del Contrato
Archivo 2 de 14: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^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.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Código Fuente del Contrato
Archivo 3 de 14: ERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)pragmasolidity ^0.8.0;import"./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/abstractcontractERC165isIERC165{
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==type(IERC165).interfaceId;
}
}
Código Fuente del Contrato
Archivo 4 de 14: ERC2981.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)pragmasolidity ^0.8.0;import"../../interfaces/IERC2981.sol";
import"../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*
* _Available since v4.5._
*/abstractcontractERC2981isIERC2981, ERC165{
structRoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256=> RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(IERC165, ERC165) returns (bool) {
return interfaceId ==type(IERC2981).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/functionroyaltyInfo(uint256 tokenId, uint256 salePrice) publicviewvirtualoverridereturns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];
if (royalty.receiver ==address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/function_feeDenominator() internalpurevirtualreturns (uint96) {
return10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/function_setDefaultRoyalty(address receiver, uint96 feeNumerator) internalvirtual{
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver !=address(0), "ERC2981: invalid receiver");
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/function_deleteDefaultRoyalty() internalvirtual{
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/function_setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internalvirtual{
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver !=address(0), "ERC2981: Invalid parameters");
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/function_resetTokenRoyalty(uint256 tokenId) internalvirtual{
delete _tokenRoyaltyInfo[tokenId];
}
}
Código Fuente del Contrato
Archivo 5 de 14: ERC721.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;/// @notice Modern, minimalist, and gas-optimized ERC721 implementation./// @author SolDAO (https://github.com/Sol-DAO/solbase/blob/main/src/tokens/ERC721.sol)/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)abstractcontractERC721{
/// -----------------------------------------------------------------------/// Events/// -----------------------------------------------------------------------eventTransfer(addressindexedfrom, addressindexed to, uint256indexed id);
eventApproval(addressindexed owner, addressindexed spender, uint256indexed id);
eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/// -----------------------------------------------------------------------/// Custom Errors/// -----------------------------------------------------------------------errorNotMinted();
errorZeroAddress();
errorUnauthorized();
errorWrongFrom();
errorInvalidRecipient();
errorUnsafeRecipient();
errorAlreadyMinted();
/// -----------------------------------------------------------------------/// Metadata Storage/Logic/// -----------------------------------------------------------------------stringpublic name;
stringpublic symbol;
functiontokenURI(uint256 id) publicviewvirtualreturns (stringmemory);
/// -----------------------------------------------------------------------/// ERC721 Balance/Owner Storage/// -----------------------------------------------------------------------mapping(uint256=>address) internal _ownerOf;
mapping(address=>uint256) internal _balanceOf;
functionownerOf(uint256 id) publicviewvirtualreturns (address owner) {
if ((owner = _ownerOf[id]) ==address(0)) revert NotMinted();
}
functionbalanceOf(address owner) publicviewvirtualreturns (uint256) {
if (owner ==address(0)) revert ZeroAddress();
return _balanceOf[owner];
}
/// -----------------------------------------------------------------------/// ERC721 Approval Storage/// -----------------------------------------------------------------------mapping(uint256=>address) public getApproved;
mapping(address=>mapping(address=>bool)) public isApprovedForAll;
/// -----------------------------------------------------------------------/// Constructor/// -----------------------------------------------------------------------constructor(stringmemory _name, stringmemory _symbol) {
name = _name;
symbol = _symbol;
}
/// -----------------------------------------------------------------------/// ERC721 Logic/// -----------------------------------------------------------------------functionapprove(address spender, uint256 id) publicvirtual{
address owner = _ownerOf[id];
if (msg.sender!= owner &&!isApprovedForAll[owner][msg.sender]) revert Unauthorized();
getApproved[id] = spender;
emit Approval(owner, spender, id);
}
functionsetApprovalForAll(address operator, bool approved) publicvirtual{
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
functiontransferFrom(addressfrom, address to, uint256 id) publicvirtual{
if (from!= _ownerOf[id]) revert WrongFrom();
if (to ==address(0)) revert InvalidRecipient();
if (msg.sender!=from&&!isApprovedForAll[from][msg.sender] &&msg.sender!= getApproved[id])
revert Unauthorized();
// Underflow of the sender's balance is impossible because we check for// ownership above and the recipient's balance can't realistically overflow.unchecked {
_balanceOf[from]--;
_balanceOf[to]++;
}
_ownerOf[id] = to;
delete getApproved[id];
emit Transfer(from, to, id);
}
functionsafeTransferFrom(addressfrom, address to, uint256 id) publicvirtual{
transferFrom(from, to, id);
if (to.code.length!=0) {
if (
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") !=
ERC721TokenReceiver.onERC721Received.selector
) revert UnsafeRecipient();
}
}
functionsafeTransferFrom(addressfrom, address to, uint256 id, bytescalldata data) publicvirtual{
transferFrom(from, to, id);
if (to.code.length!=0) {
if (
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) !=
ERC721TokenReceiver.onERC721Received.selector
) revert UnsafeRecipient();
}
}
/// -----------------------------------------------------------------------/// ERC165 Logic/// -----------------------------------------------------------------------functionsupportsInterface(bytes4 interfaceId) publicviewvirtualreturns (bool) {
return
interfaceId ==0x01ffc9a7||// ERC165 Interface ID for ERC165
interfaceId ==0x80ac58cd||// ERC165 Interface ID for ERC721
interfaceId ==0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
}
/// -----------------------------------------------------------------------/// Internal Mint/Burn Logic/// -----------------------------------------------------------------------function_mint(address to, uint256 id) internalvirtual{
if (to ==address(0)) revert InvalidRecipient();
if (_ownerOf[id] !=address(0)) revert AlreadyMinted();
// Counter overflow is incredibly unrealistic.unchecked {
_balanceOf[to]++;
}
_ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function_burn(uint256 id) internalvirtual{
address owner = _ownerOf[id];
if (owner ==address(0)) revert NotMinted();
// Ownership check above ensures no underflow.unchecked {
_balanceOf[owner]--;
}
delete _ownerOf[id];
delete getApproved[id];
emit Transfer(owner, address(0), id);
}
/// -----------------------------------------------------------------------/// Internal Safe Mint Logic/// -----------------------------------------------------------------------function_safeMint(address to, uint256 id) internalvirtual{
_mint(to, id);
if (to.code.length!=0) {
if (
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") !=
ERC721TokenReceiver.onERC721Received.selector
) revert UnsafeRecipient();
}
}
function_safeMint(address to, uint256 id, bytesmemory data) internalvirtual{
_mint(to, id);
if (to.code.length!=0) {
if (
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) !=
ERC721TokenReceiver.onERC721Received.selector
) revert UnsafeRecipient();
}
}
}
/// @notice A generic interface for a contract which properly accepts ERC721 tokens./// @author SolDAO (https://github.com/Sol-DAO/solbase/blob/main/src/tokens/ERC721.sol)/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)abstractcontractERC721TokenReceiver{
functiononERC721Received(address, address, uint256, bytescalldata) externalvirtualreturns (bytes4) {
return ERC721TokenReceiver.onERC721Received.selector;
}
}
Código Fuente del Contrato
Archivo 6 de 14: Elemental.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.18;import"solbase/src/tokens/ERC721/ERC721.sol";
import"@openzeppelin/contracts/access/Ownable.sol";
import"@openzeppelin/contracts/utils/Strings.sol";
import"@openzeppelin/contracts/token/common/ERC2981.sol";
import {BitMaps} from"@openzeppelin/contracts/utils/structs/BitMaps.sol";
import"closedsea/OperatorFilterer.sol";
import"./MultisigOwnable.sol";
errorNotAllowedByRegistry();
errorRegistryNotSet();
errorInvalidTokenId();
errorBeanAddressNotSet();
errorRedeemBeanNotOpen();
errorInvalidRedeemer();
errorNoMoreTokenIds();
interfaceIRegistry{
functionisAllowedOperator(address operator) externalviewreturns (bool);
}
contractElementalisERC2981, ERC721, MultisigOwnable, OperatorFilterer{
usingStringsforuint256;
usingBitMapsforBitMaps.BitMap;
eventBeanRedeemed(addressindexed to,
uint256indexed tokenId,
uint256indexed beanId
);
boolpublic operatorFilteringEnabled =true;
boolpublic isRegistryActive =false;
addresspublic registryAddress;
structRedeemInfo {
bool redeemBeanOpen;
address beanAddress;
}
RedeemInfo public redeemInfo;
uint16publicimmutable MAX_SUPPLY;
uint16internal _numAvailableRemainingTokens;
// Data structure used for Fisher Yates shuffleuint16[65536] internal _availableRemainingTokens;
constructor(stringmemory _name,
stringmemory _symbol,
uint16 maxSupply_
) ERC721(_name, _symbol) {
MAX_SUPPLY = maxSupply_;
_numAvailableRemainingTokens = maxSupply_;
_registerForOperatorFiltering();
operatorFilteringEnabled =true;
}
// ---------------// Name and symbol// ---------------functionsetNameAndSymbol(stringcalldata _newName,
stringcalldata _newSymbol
) externalonlyOwner{
name = _newName;
symbol = _newSymbol;
}
// ------------// Redeem beans// ------------functionredeemBeans(address to, uint256[] calldata beanIds)
publicreturns (uint256[] memory)
{
RedeemInfo memory info = redeemInfo;
if (!info.redeemBeanOpen) {
revert RedeemBeanNotOpen();
}
if (msg.sender!= info.beanAddress) {
revert InvalidRedeemer();
}
uint256 amount = beanIds.length;
uint256[] memory tokenIds =newuint256[](amount);
// Assume data has already been validated by the bean contractfor (uint256 i; i < amount; ) {
uint256 beanId = beanIds[i];
uint256 tokenId = _useRandomAvailableTokenId();
// Don't need safeMint, as the calling address has a MysteryBean in it already
_mint(to, tokenId);
emit BeanRedeemed(to, tokenId, beanId);
tokenIds[i] = tokenId;
unchecked {
++i;
}
}
return tokenIds;
}
// Generates a pseudorandom number between [0,MAX_SUPPLY) that has not yet been generated before, in O(1) time.//// Uses Durstenfeld's version of the Yates Shuffle https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle// with a twist to avoid having to manually spend gas to preset an array's values to be values 0...n.// It does this by interpreting zero-values for an index X as meaning that index X itself is an available value// that is returnable.//// How it works:// - zero-initialize a mapping (_availableRemainingTokens) and track its length (_numAvailableRemainingTokens). functionally similar to an array with dynamic sizing// - this mapping will track all remaining valid values that haven't been generated yet, through a combination of its indices and values// - if _availableRemainingTokens[x] == 0, that means x has not been generated yet// - if _availableRemainingTokens[x] != 0, that means _availableRemainingTokens[x] has not been generated yet// - when prompted for a random number between [0,MAX_SUPPLY) that hasn't already been used:// - generate a random index randIndex between [0,_numAvailableRemainingTokens)// - examine the value at _availableRemainingTokens[randIndex]// - if the value is zero, it means randIndex has not been used, so we can return randIndex// - if the value is non-zero, it means the value has not been used, so we can return _availableRemainingTokens[randIndex]// - update the _availableRemainingTokens mapping state// - set _availableRemainingTokens[randIndex] to either the index or the value of the last entry in the mapping (depends on the last entry's state)// - decrement _numAvailableRemainingTokens to mimic the shrinking of an arrayfunction_useRandomAvailableTokenId() internalreturns (uint256) {
uint256 numAvailableRemainingTokens = _numAvailableRemainingTokens;
if (numAvailableRemainingTokens ==0) {
revert NoMoreTokenIds();
}
uint256 randomNum = _getRandomNum(numAvailableRemainingTokens);
uint256 randomIndex = randomNum % numAvailableRemainingTokens;
uint256 valAtIndex = _availableRemainingTokens[randomIndex];
uint256 result;
if (valAtIndex ==0) {
// This means the index itself is still an available token
result = randomIndex;
} else {
// This means the index itself is not an available token, but the val at that index is.
result = valAtIndex;
}
uint256 lastIndex = numAvailableRemainingTokens -1;
if (randomIndex != lastIndex) {
// Replace the value at randomIndex, now that it's been used.// Replace it with the data from the last index in the array, since we are going to decrease the array size afterwards.uint256 lastValInArray = _availableRemainingTokens[lastIndex];
if (lastValInArray ==0) {
// This means the index itself is still an available token// Cast is safe as we know that lastIndex cannot > MAX_SUPPLY, which is a uint16
_availableRemainingTokens[randomIndex] =uint16(lastIndex);
} else {
// This means the index itself is not an available token, but the val at that index is.// Cast is safe as we know that lastValInArray cannot > MAX_SUPPLY, which is a uint16
_availableRemainingTokens[randomIndex] =uint16(lastValInArray);
delete _availableRemainingTokens[lastIndex];
}
}
--_numAvailableRemainingTokens;
return result;
}
// On-chain randomness tradeoffs are acceptable here as it's only used for the Elemental's id number itself, not the resulting Elemental's metadata (which is determined by the source MysteryBean).function_getRandomNum(uint256 numAvailableRemainingTokens)
internalviewreturns (uint256)
{
returnuint256(
keccak256(
abi.encode(
block.prevrandao,
blockhash(block.number-1),
address(this),
numAvailableRemainingTokens
)
)
);
}
functionsetBeanAddress(address contractAddress) externalonlyOwner{
redeemInfo = RedeemInfo(redeemInfo.redeemBeanOpen, contractAddress);
}
functionsetRedeemBeanState(bool _redeemBeanOpen) externalonlyOwner{
address beanAddress = redeemInfo.beanAddress;
if (beanAddress ==address(0)) {
revert BeanAddressNotSet();
}
redeemInfo = RedeemInfo(_redeemBeanOpen, beanAddress);
}
// ------------// Total Supply// ------------functiontotalSupply() externalviewreturns (uint256) {
unchecked {
// Does not need to account for burns as they aren't supported.return MAX_SUPPLY - _numAvailableRemainingTokens;
}
}
// --------// Metadata// --------functiontokenURI(uint256 tokenId)
publicviewoverridereturns (stringmemory)
{
if (_ownerOf[tokenId] ==address(0)) {
revert InvalidTokenId();
}
stringmemory baseURI = _getBaseURIForToken(tokenId);
returnbytes(baseURI).length>0
? string(abi.encodePacked(baseURI, tokenId.toString()))
: "";
}
stringprivate _baseTokenURI;
stringprivate _baseTokenURIPermanent;
// Keys are Elemental token ids
BitMaps.BitMap private _isUriPermanentForToken;
function_getBaseURIForToken(uint256 tokenId)
privateviewreturns (stringmemory)
{
return
_isUriPermanentForToken.get(tokenId)
? _baseTokenURIPermanent
: _baseTokenURI;
}
functionsetBaseURI(stringcalldata baseURI) externalonlyOwner{
_baseTokenURI = baseURI;
}
functionsetBaseURIPermanent(stringcalldata baseURIPermanent)
externalonlyOwner{
_baseTokenURIPermanent = baseURIPermanent;
}
functionsetIsUriPermanent(uint256[] calldata tokenIds) externalonlyOwner{
for (uint256 i =0; i < tokenIds.length; ) {
_isUriPermanentForToken.set(tokenIds[i]);
unchecked {
++i;
}
}
}
// --------// EIP-2981// --------functionsetDefaultRoyalty(address receiver, uint96 feeNumerator)
externalonlyOwner{
_setDefaultRoyalty(receiver, feeNumerator);
}
functionsetTokenRoyalty(uint256 tokenId,
address receiver,
uint96 feeNumerator
) externalonlyOwner{
_setTokenRoyalty(tokenId, receiver, feeNumerator);
}
// ---------------------------------------------------// OperatorFilterer overrides (overrides, values etc.)// ---------------------------------------------------functionsetApprovalForAll(address operator, bool approved)
publicoverrideonlyAllowedOperatorApproval(operator)
{
super.setApprovalForAll(operator, approved);
}
functionsetOperatorFilteringEnabled(bool value) publiconlyOwner{
operatorFilteringEnabled = value;
}
function_operatorFilteringEnabled() internalviewoverridereturns (bool) {
return operatorFilteringEnabled;
}
functionapprove(address operator, uint256 tokenId)
publicoverrideonlyAllowedOperatorApproval(operator)
{
super.approve(operator, tokenId);
}
// --------------// Registry check// --------------// Solbase ERC721 calls transferFrom internally in its two safeTransferFrom functions, so we don't need to override those.// Also, onlyAllowedOperator is from closedseafunctiontransferFrom(addressfrom,
address to,
uint256 id
) publicoverrideonlyAllowedOperator(from) {
if (!_isValidAgainstRegistry(msg.sender)) {
revert NotAllowedByRegistry();
}
super.transferFrom(from, to, id);
}
function_isValidAgainstRegistry(address operator)
internalviewreturns (bool)
{
if (isRegistryActive) {
IRegistry registry = IRegistry(registryAddress);
return registry.isAllowedOperator(operator);
}
returntrue;
}
functionsetIsRegistryActive(bool _isRegistryActive) externalonlyOwner{
if (registryAddress ==address(0)) revert RegistryNotSet();
isRegistryActive = _isRegistryActive;
}
functionsetRegistryAddress(address _registryAddress) externalonlyOwner{
registryAddress = _registryAddress;
}
// -------// EIP-165// -------functionsupportsInterface(bytes4 interfaceId)
publicviewoverride(ERC721, ERC2981)
returns (bool)
{
return
ERC721.supportsInterface(interfaceId) ||
ERC2981.supportsInterface(interfaceId);
}
}
Código Fuente del Contrato
Archivo 7 de 14: IERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)pragmasolidity ^0.8.0;/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/interfaceIERC165{
/**
* @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.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Código Fuente del Contrato
Archivo 8 de 14: IERC2981.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)pragmasolidity ^0.8.0;import"../utils/introspection/IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*
* _Available since v4.5._
*/interfaceIERC2981isIERC165{
/**
* @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.
*/functionroyaltyInfo(uint256 tokenId,
uint256 salePrice
) externalviewreturns (address receiver, uint256 royaltyAmount);
}
Código Fuente del Contrato
Archivo 9 de 14: Math.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)pragmasolidity ^0.8.0;/**
* @dev Standard math utilities missing in the Solidity language.
*/libraryMath{
enumRounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/functionmax(uint256 a, uint256 b) internalpurereturns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/functionmin(uint256 a, uint256 b) internalpurereturns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/functionaverage(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b) / 2 can overflow.return (a & b) + (a ^ b) /2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/functionceilDiv(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.return a ==0 ? 0 : (a -1) / b +1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/functionmulDiv(uint256 x, uint256 y, uint256 denominator) internalpurereturns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256// variables such that product = prod1 * 2^256 + prod0.uint256 prod0; // Least significant 256 bits of the productuint256 prod1; // Most significant 256 bits of the productassembly {
let mm :=mulmod(x, y, not(0))
prod0 :=mul(x, y)
prod1 :=sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.if (prod1 ==0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.// The surrounding unchecked block does not change this fact.// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////// 512 by 256 division.///////////////////////////////////////////////// Make division exact by subtracting the remainder from [prod1 prod0].uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder :=mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 :=sub(prod1, gt(remainder, prod0))
prod0 :=sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.// See https://cs.stackexchange.com/q/138556/92363.// Does not overflow because the denominator cannot be zero at this stage in the function.uint256 twos = denominator & (~denominator +1);
assembly {
// Divide denominator by twos.
denominator :=div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 :=div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos :=add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for// four bits. That is, denominator * inv = 1 mod 2^4.uint256 inverse = (3* denominator) ^2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works// in modular arithmetic, doubling the correct bits in each step.
inverse *=2- denominator * inverse; // inverse mod 2^8
inverse *=2- denominator * inverse; // inverse mod 2^16
inverse *=2- denominator * inverse; // inverse mod 2^32
inverse *=2- denominator * inverse; // inverse mod 2^64
inverse *=2- denominator * inverse; // inverse mod 2^128
inverse *=2- denominator * inverse; // inverse mod 2^256// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/functionmulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internalpurereturns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up &&mulmod(x, y, denominator) >0) {
result +=1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/functionsqrt(uint256 a) internalpurereturns (uint256) {
if (a ==0) {
return0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.//// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.//// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`//// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.uint256 result =1<< (log2(a) >>1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision// into the expected uint128 result.unchecked {
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/functionsqrt(uint256 a, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=128;
}
if (value >>64>0) {
value >>=64;
result +=64;
}
if (value >>32>0) {
value >>=32;
result +=32;
}
if (value >>16>0) {
value >>=16;
result +=16;
}
if (value >>8>0) {
value >>=8;
result +=8;
}
if (value >>4>0) {
value >>=4;
result +=4;
}
if (value >>2>0) {
value >>=2;
result +=2;
}
if (value >>1>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result =log2(value);
return result + (rounding == Rounding.Up &&1<< result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >=10**64) {
value /=10**64;
result +=64;
}
if (value >=10**32) {
value /=10**32;
result +=32;
}
if (value >=10**16) {
value /=10**16;
result +=16;
}
if (value >=10**8) {
value /=10**8;
result +=8;
}
if (value >=10**4) {
value /=10**4;
result +=4;
}
if (value >=10**2) {
value /=10**2;
result +=2;
}
if (value >=10**1) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up &&10** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/functionlog256(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=16;
}
if (value >>64>0) {
value >>=64;
result +=8;
}
if (value >>32>0) {
value >>=32;
result +=4;
}
if (value >>16>0) {
value >>=16;
result +=2;
}
if (value >>8>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog256(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up &&1<< (result <<3) < value ? 1 : 0);
}
}
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;/// @notice Optimized and flexible operator filterer to abide to OpenSea's/// mandatory on-chain royalty enforcement in order for new collections to/// receive royalties./// For more information, see:/// See: https://github.com/ProjectOpenSea/operator-filter-registryabstractcontractOperatorFilterer{
/// @dev The default OpenSea operator blocklist subscription.addressinternalconstant _DEFAULT_SUBSCRIPTION =0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6;
/// @dev The OpenSea operator filter registry.addressinternalconstant _OPERATOR_FILTER_REGISTRY =0x000000000000AAeB6D7670E522A718067333cd4E;
/// @dev Registers the current contract to OpenSea's operator filter,/// and subscribe to the default OpenSea operator blocklist./// Note: Will not revert nor update existing settings for repeated registration.function_registerForOperatorFiltering() internalvirtual{
_registerForOperatorFiltering(_DEFAULT_SUBSCRIPTION, true);
}
/// @dev Registers the current contract to OpenSea's operator filter./// Note: Will not revert nor update existing settings for repeated registration.function_registerForOperatorFiltering(address subscriptionOrRegistrantToCopy, bool subscribe)
internalvirtual{
/// @solidity memory-safe-assemblyassembly {
let functionSelector :=0x7d3e3dbe// `registerAndSubscribe(address,address)`.// Clean the upper 96 bits of `subscriptionOrRegistrantToCopy` in case they are dirty.
subscriptionOrRegistrantToCopy :=shr(96, shl(96, subscriptionOrRegistrantToCopy))
for {} iszero(subscribe) {} {
ifiszero(subscriptionOrRegistrantToCopy) {
functionSelector :=0x4420e486// `register(address)`.break
}
functionSelector :=0xa0af2903// `registerAndCopyEntries(address,address)`.break
}
// Store the function selector.mstore(0x00, shl(224, functionSelector))
// Store the `address(this)`.mstore(0x04, address())
// Store the `subscriptionOrRegistrantToCopy`.mstore(0x24, subscriptionOrRegistrantToCopy)
// Register into the registry.ifiszero(call(gas(), _OPERATOR_FILTER_REGISTRY, 0, 0x00, 0x44, 0x00, 0x04)) {
// If the function selector has not been overwritten,// it is an out-of-gas error.ifeq(shr(224, mload(0x00)), functionSelector) {
// To prevent gas under-estimation.revert(0, 0)
}
}
// Restore the part of the free memory pointer that was overwritten,// which is guaranteed to be zero, because of Solidity's memory size limits.mstore(0x24, 0)
}
}
/// @dev Modifier to guard a function and revert if the caller is a blocked operator.modifieronlyAllowedOperator(addressfrom) virtual{
if (from!=msg.sender) {
if (!_isPriorityOperator(msg.sender)) {
if (_operatorFilteringEnabled()) _revertIfBlocked(msg.sender);
}
}
_;
}
/// @dev Modifier to guard a function from approving a blocked operator..modifieronlyAllowedOperatorApproval(address operator) virtual{
if (!_isPriorityOperator(operator)) {
if (_operatorFilteringEnabled()) _revertIfBlocked(operator);
}
_;
}
/// @dev Helper function that reverts if the `operator` is blocked by the registry.function_revertIfBlocked(address operator) privateview{
/// @solidity memory-safe-assemblyassembly {
// Store the function selector of `isOperatorAllowed(address,address)`,// shifted left by 6 bytes, which is enough for 8tb of memory.// We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL).mstore(0x00, 0xc6171134001122334455)
// Store the `address(this)`.mstore(0x1a, address())
// Store the `operator`.mstore(0x3a, operator)
// `isOperatorAllowed` always returns true if it does not revert.ifiszero(staticcall(gas(), _OPERATOR_FILTER_REGISTRY, 0x16, 0x44, 0x00, 0x00)) {
// Bubble up the revert if the staticcall reverts.returndatacopy(0x00, 0x00, returndatasize())
revert(0x00, returndatasize())
}
// We'll skip checking if `from` is inside the blacklist.// Even though that can block transferring out of wrapper contracts,// we don't want tokens to be stuck.// Restore the part of the free memory pointer that was overwritten,// which is guaranteed to be zero, if less than 8tb of memory is used.mstore(0x3a, 0)
}
}
/// @dev For deriving contracts to override, so that operator filtering/// can be turned on / off./// Returns true by default.function_operatorFilteringEnabled() internalviewvirtualreturns (bool) {
returntrue;
}
/// @dev For deriving contracts to override, so that preferred marketplaces can/// skip operator filtering, helping users save gas./// Returns false for all inputs by default.function_isPriorityOperator(address) internalviewvirtualreturns (bool) {
returnfalse;
}
}
Código Fuente del Contrato
Archivo 12 de 14: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)pragmasolidity ^0.8.0;import"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed 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.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
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.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
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) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Código Fuente del Contrato
Archivo 13 de 14: SignedMath.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)pragmasolidity ^0.8.0;/**
* @dev Standard signed math utilities missing in the Solidity language.
*/librarySignedMath{
/**
* @dev Returns the largest of two signed numbers.
*/functionmax(int256 a, int256 b) internalpurereturns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/functionmin(int256 a, int256 b) internalpurereturns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/functionaverage(int256 a, int256 b) internalpurereturns (int256) {
// Formula from the book "Hacker's Delight"int256 x = (a & b) + ((a ^ b) >>1);
return x + (int256(uint256(x) >>255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/functionabs(int256 n) internalpurereturns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`returnuint256(n >=0 ? n : -n);
}
}
}
Código Fuente del Contrato
Archivo 14 de 14: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)pragmasolidity ^0.8.0;import"./math/Math.sol";
import"./math/SignedMath.sol";
/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant _SYMBOLS ="0123456789abcdef";
uint8privateconstant _ADDRESS_LENGTH =20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
uint256 length = Math.log10(value) +1;
stringmemory buffer =newstring(length);
uint256 ptr;
/// @solidity memory-safe-assemblyassembly {
ptr :=add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assemblyassembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /=10;
if (value ==0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/functiontoString(int256 value) internalpurereturns (stringmemory) {
returnstring(abi.encodePacked(value <0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
return toHexString(value, Math.log256(value) +1);
}
}
/**
* @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] = _SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/functiontoHexString(address addr) internalpurereturns (stringmemory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/functionequal(stringmemory a, stringmemory b) internalpurereturns (bool) {
returnkeccak256(bytes(a)) ==keccak256(bytes(b));
}
}