文件 1 的 8:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 8:ERC721A.sol
pragma solidity ^0.8.4;
import './IERC721A.sol';
interface ERC721A__IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
contract ERC721A is IERC721A {
uint256 private constant BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;
uint256 private constant BITPOS_NUMBER_MINTED = 64;
uint256 private constant BITPOS_NUMBER_BURNED = 128;
uint256 private constant BITPOS_AUX = 192;
uint256 private constant BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;
uint256 private constant BITPOS_START_TIMESTAMP = 160;
uint256 private constant BITMASK_BURNED = 1 << 224;
uint256 private constant BITPOS_NEXT_INITIALIZED = 225;
uint256 private constant BITMASK_NEXT_INITIALIZED = 1 << 225;
uint256 private _currentIndex;
uint256 private _burnCounter;
string private _name;
string private _symbol;
mapping(uint256 => uint256) private _packedOwnerships;
mapping(address => uint256) private _packedAddressData;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
_currentIndex = _startTokenId();
}
function _startTokenId() internal view virtual returns (uint256) {
return 0;
}
function _nextTokenId() internal view returns (uint256) {
return _currentIndex;
}
function totalSupply() public view override returns (uint256) {
unchecked {
return _currentIndex - _burnCounter - _startTokenId();
}
}
function _totalMinted() internal view returns (uint256) {
unchecked {
return _currentIndex - _startTokenId();
}
}
function _totalBurned() internal view returns (uint256) {
return _burnCounter;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0x80ac58cd ||
interfaceId == 0x5b5e139f;
}
function balanceOf(address owner) public view override returns (uint256) {
if (owner == address(0)) revert BalanceQueryForZeroAddress();
return _packedAddressData[owner] & BITMASK_ADDRESS_DATA_ENTRY;
}
function _numberMinted(address owner) internal view returns (uint256) {
return (_packedAddressData[owner] >> BITPOS_NUMBER_MINTED) & BITMASK_ADDRESS_DATA_ENTRY;
}
function _numberBurned(address owner) internal view returns (uint256) {
return (_packedAddressData[owner] >> BITPOS_NUMBER_BURNED) & BITMASK_ADDRESS_DATA_ENTRY;
}
function _getAux(address owner) internal view returns (uint64) {
return uint64(_packedAddressData[owner] >> BITPOS_AUX);
}
function _setAux(address owner, uint64 aux) internal {
uint256 packed = _packedAddressData[owner];
uint256 auxCasted;
assembly {
auxCasted := aux
}
packed = (packed & BITMASK_AUX_COMPLEMENT) | (auxCasted << BITPOS_AUX);
_packedAddressData[owner] = packed;
}
function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) {
uint256 curr = tokenId;
unchecked {
if (_startTokenId() <= curr)
if (curr < _currentIndex) {
uint256 packed = _packedOwnerships[curr];
if (packed & BITMASK_BURNED == 0) {
while (packed == 0) {
packed = _packedOwnerships[--curr];
}
return packed;
}
}
}
revert OwnerQueryForNonexistentToken();
}
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;
}
function _ownershipAt(uint256 index) internal view returns (TokenOwnership memory) {
return _unpackedOwnership(_packedOwnerships[index]);
}
function _initializeOwnershipAt(uint256 index) internal {
if (_packedOwnerships[index] == 0) {
_packedOwnerships[index] = _packedOwnershipOf(index);
}
}
function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) {
return _unpackedOwnership(_packedOwnershipOf(tokenId));
}
function ownerOf(uint256 tokenId) public view override returns (address) {
return address(uint160(_packedOwnershipOf(tokenId)));
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
if (!_exists(tokenId)) revert URIQueryForNonexistentToken();
string memory baseURI = _baseURI();
return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
}
function _baseURI() internal view virtual returns (string memory) {
return '';
}
function _addressToUint256(address value) private pure returns (uint256 result) {
assembly {
result := value
}
}
function _boolToUint256(bool value) private pure returns (uint256 result) {
assembly {
result := value
}
}
function approve(address to, uint256 tokenId) public override {
address owner = address(uint160(_packedOwnershipOf(tokenId)));
if (to == owner) revert ApprovalToCurrentOwner();
if (_msgSenderERC721A() != owner)
if (!isApprovedForAll(owner, _msgSenderERC721A())) {
revert ApprovalCallerNotOwnerNorApproved();
}
_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}
function getApproved(uint256 tokenId) public view override returns (address) {
if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
if (operator == _msgSenderERC721A()) revert ApproveToCaller();
_operatorApprovals[_msgSenderERC721A()][operator] = approved;
emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, '');
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
_transfer(from, to, tokenId);
if (to.code.length != 0)
if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
revert TransferToNonERC721ReceiverImplementer();
}
}
function _exists(uint256 tokenId) internal view returns (bool) {
return
_startTokenId() <= tokenId &&
tokenId < _currentIndex &&
_packedOwnerships[tokenId] & BITMASK_BURNED == 0;
}
function _safeMint(address to, uint256 quantity) internal {
_safeMint(to, quantity, '');
}
function _safeMint(
address to,
uint256 quantity,
bytes memory _data
) internal {
uint256 startTokenId = _currentIndex;
if (to == address(0)) revert MintToZeroAddress();
if (quantity == 0) revert MintZeroQuantity();
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
unchecked {
_packedAddressData[to] += quantity * ((1 << BITPOS_NUMBER_MINTED) | 1);
_packedOwnerships[startTokenId] =
_addressToUint256(to) |
(block.timestamp << BITPOS_START_TIMESTAMP) |
(_boolToUint256(quantity == 1) << BITPOS_NEXT_INITIALIZED);
uint256 updatedIndex = startTokenId;
uint256 end = updatedIndex + quantity;
if (to.code.length != 0) {
do {
emit Transfer(address(0), to, updatedIndex);
if (!_checkContractOnERC721Received(address(0), to, updatedIndex++, _data)) {
revert TransferToNonERC721ReceiverImplementer();
}
} while (updatedIndex < end);
if (_currentIndex != startTokenId) revert();
} else {
do {
emit Transfer(address(0), to, updatedIndex++);
} while (updatedIndex < end);
}
_currentIndex = updatedIndex;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
function _mint(address to, uint256 quantity) internal {
uint256 startTokenId = _currentIndex;
if (to == address(0)) revert MintToZeroAddress();
if (quantity == 0) revert MintZeroQuantity();
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
unchecked {
_packedAddressData[to] += quantity * ((1 << BITPOS_NUMBER_MINTED) | 1);
_packedOwnerships[startTokenId] =
_addressToUint256(to) |
(block.timestamp << BITPOS_START_TIMESTAMP) |
(_boolToUint256(quantity == 1) << BITPOS_NEXT_INITIALIZED);
uint256 updatedIndex = startTokenId;
uint256 end = updatedIndex + quantity;
do {
emit Transfer(address(0), to, updatedIndex++);
} while (updatedIndex < end);
_currentIndex = updatedIndex;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
function _transfer(
address from,
address to,
uint256 tokenId
) private {
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner();
bool isApprovedOrOwner = (_msgSenderERC721A() == from ||
isApprovedForAll(from, _msgSenderERC721A()) ||
getApproved(tokenId) == _msgSenderERC721A());
if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
if (to == address(0)) revert TransferToZeroAddress();
_beforeTokenTransfers(from, to, tokenId, 1);
delete _tokenApprovals[tokenId];
unchecked {
--_packedAddressData[from];
++_packedAddressData[to];
_packedOwnerships[tokenId] =
_addressToUint256(to) |
(block.timestamp << BITPOS_START_TIMESTAMP) |
BITMASK_NEXT_INITIALIZED;
if (prevOwnershipPacked & BITMASK_NEXT_INITIALIZED == 0) {
uint256 nextTokenId = tokenId + 1;
if (_packedOwnerships[nextTokenId] == 0) {
if (nextTokenId != _currentIndex) {
_packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
emit Transfer(from, to, tokenId);
_afterTokenTransfers(from, to, tokenId, 1);
}
function _burn(uint256 tokenId) internal virtual {
_burn(tokenId, false);
}
function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
address from = address(uint160(prevOwnershipPacked));
if (approvalCheck) {
bool isApprovedOrOwner = (_msgSenderERC721A() == from ||
isApprovedForAll(from, _msgSenderERC721A()) ||
getApproved(tokenId) == _msgSenderERC721A());
if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
}
_beforeTokenTransfers(from, address(0), tokenId, 1);
delete _tokenApprovals[tokenId];
unchecked {
_packedAddressData[from] += (1 << BITPOS_NUMBER_BURNED) - 1;
_packedOwnerships[tokenId] =
_addressToUint256(from) |
(block.timestamp << BITPOS_START_TIMESTAMP) |
BITMASK_BURNED |
BITMASK_NEXT_INITIALIZED;
if (prevOwnershipPacked & BITMASK_NEXT_INITIALIZED == 0) {
uint256 nextTokenId = tokenId + 1;
if (_packedOwnerships[nextTokenId] == 0) {
if (nextTokenId != _currentIndex) {
_packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
emit Transfer(from, address(0), tokenId);
_afterTokenTransfers(from, address(0), tokenId, 1);
unchecked {
_burnCounter++;
}
}
function _checkContractOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
bytes4 retval
) {
return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert TransferToNonERC721ReceiverImplementer();
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
function _msgSenderERC721A() internal view virtual returns (address) {
return msg.sender;
}
function _toString(uint256 value) internal pure returns (string memory ptr) {
assembly {
ptr := add(mload(0x40), 128)
mstore(0x40, ptr)
let end := ptr
for {
let temp := value
ptr := sub(ptr, 1)
mstore8(ptr, add(48, mod(temp, 10)))
temp := div(temp, 10)
} temp {
temp := div(temp, 10)
} {
ptr := sub(ptr, 1)
mstore8(ptr, add(48, mod(temp, 10)))
}
let length := sub(end, ptr)
ptr := sub(ptr, 32)
mstore(ptr, length)
}
}
}
文件 3 的 8:HyewonNft.sol
pragma solidity ^0.8.4;
import "erc721a/contracts/ERC721A.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "./IHyewonNft.sol";
contract HyewonNft is IHyewonNft, ERC721A, Ownable, ReentrancyGuard, Pausable {
uint256 public maximumSupply;
bool public permanent;
mapping(uint16 => Round) rounds;
uint256 public revealBlockOffset = 3000;
mapping(uint16 => mapping(address => uint16)) whitelists;
uint16 public currentRoundNumber;
address private _receiver;
address private _signer;
string public baseURI;
string private defaultUnrevealedURI;
modifier onlyOwnerOrAdmin(uint16 roundNumber) {
Round memory r = rounds[roundNumber];
address admin = rounds[roundNumber].admin;
if (admin == address(0)) {
revert BadRequest("Not allowed address");
}
if (msg.sender != owner() && msg.sender != admin) {
revert NotOwnerNorAdmin(msg.sender);
}
_;
}
constructor(
address receiver,
uint256 maxSupply,
string memory _baseUri,
string memory _defaultUnrevealedURI
)
ERC721A("Hyewon's Album of Genre Paintings", "HyewonPaintings")
Ownable()
Pausable()
{
_receiver = receiver;
maximumSupply = maxSupply;
baseURI = _baseUri;
defaultUnrevealedURI = _defaultUnrevealedURI;
}
function getState() public view returns (State) {
if (currentRoundNumber == 0) {
return State.DEPLOYED;
}
Round memory currentRound = rounds[currentRoundNumber];
uint256 startTime = currentRound.startTime;
uint256 endTime = currentRound.endTime;
uint256 currentTime = block.timestamp;
State currentState;
if (currentTime < startTime) {
currentState = State.PREPARE_MINTING;
} else if (currentTime < endTime) {
if (currentRound.maxMintingId > totalSupply()) {
currentState = State.ON_MINTING;
} else {
currentState = State.END_MINTING;
}
} else {
currentState = State.END_MINTING;
}
return currentState;
}
function mint(uint256 quantity)
external
payable
nonReentrant
whenNotPaused
{
Round memory currentRound = getRound(currentRoundNumber);
if (currentRound.whitelisted) {
revert WhitelistOnlyRound();
}
_sanityCheckForMinting(currentRound, quantity);
require(safeMint(msg.sender, quantity));
}
function whitelistMint(
uint8 v,
bytes32 r,
bytes32 s,
uint16 quantity
) external payable nonReentrant whenNotPaused {
Round memory currentRound = getRound(currentRoundNumber);
if (!currentRound.whitelisted) {
revert NotWhitelistOnlyRound();
}
_sanityCheckForMinting(currentRound, quantity);
uint16 claimed = whitelists[currentRoundNumber][_msgSender()];
uint16 maxAllowedQuantity = currentRound.maxAllowedMintingQuantity;
if (claimed + quantity > maxAllowedQuantity) {
revert ExceedAllowedQuantity(maxAllowedQuantity);
}
_updateWhitelistUsed(currentRoundNumber, quantity, v, r, s);
require(safeMint(msg.sender, quantity));
}
function safeMint(address receiver, uint256 quantity)
private
returns (bool)
{
_safeMint(receiver, quantity);
return true;
}
function adminMint(uint256 quantity)
external
onlyOwnerOrAdmin(currentRoundNumber)
nonReentrant
{
Round memory currentRound = rounds[currentRoundNumber];
uint256 maxMintingId = currentRound.maxMintingId;
if (!_isTokenAvailable(quantity, maxMintingId)) {
revert ExceedMaximumForTheRound();
}
require(safeMint(msg.sender, quantity));
}
function adminMintTo(address[] calldata tos, uint256[] calldata quantities)
external
payable
onlyOwner
{
uint256 length = tos.length;
if (length != quantities.length) {
revert BadRequest("Input size not match");
}
uint256 totalQuantity = 0;
for (uint256 i = 0; i < tos.length; i++) {
totalQuantity += quantities[i];
}
Round memory currentRound = rounds[currentRoundNumber];
uint256 maxMintingId = currentRound.maxMintingId;
if (!_isTokenAvailable(totalQuantity, maxMintingId)) {
revert ExceedMaximumForTheRound();
}
for (uint256 i = 0; i < length; i++) {
require(safeMint(tos[i], quantities[i]));
}
}
function transferBatch(uint256[] calldata tokenIds, address to)
external
nonReentrant
{
for (uint256 i = 0; i < tokenIds.length; i++) {
safeTransferFrom(_msgSender(), to, tokenIds[i]);
}
}
function tokenURI(uint256 tokenId)
public
view
override
returns (string memory)
{
Round memory round = _getRoundByTokenId(tokenId);
if (
round.revealed &&
keccak256(abi.encodePacked(round.tokenURIPrefix)) !=
keccak256(abi.encodePacked(""))
) {
return
string(
abi.encodePacked(
baseURI,
round.tokenURIPrefix,
"/",
_toString(tokenId),
".json"
)
);
} else {
return
string(
abi.encodePacked(
defaultUnrevealedURI,
_toString(tokenId),
".json"
)
);
}
}
function newRound(
uint256 maxMintingId,
uint256 mintingFee,
uint16 maxAllowedMintingQuantity,
bool whitelisted,
bool revealed,
uint256 startTime,
uint256 endTime,
bool onlyAdminRound,
address admin
) external onlyOwner {
if (currentRoundNumber > 0) {
endRound();
}
if (maxMintingId > maximumSupply) {
revert BadRequest("maxMintingId exceed the maximumSupply");
}
if (startTime >= endTime) {
revert BadRequest("endTime should be bigger");
}
uint16 newRoundNumber = ++currentRoundNumber;
rounds[newRoundNumber] = Round({
roundNumber: newRoundNumber,
maxMintingId: maxMintingId,
startId: _nextTokenId(),
lastMintedId: 0,
tokenURIPrefix: "",
mintingFee: mintingFee,
maxAllowedMintingQuantity: maxAllowedMintingQuantity,
whitelisted: whitelisted,
revealed: revealed,
revealBlockNumber: 0,
randomSelection: 0,
startTime: startTime,
endTime: endTime,
onlyAdminRound: onlyAdminRound,
admin: admin
});
emit NewRoundCreated();
}
function endRound() public onlyOwnerOrAdmin(currentRoundNumber) {
Round storage currentRound = rounds[currentRoundNumber];
currentRound.lastMintedId = _nextTokenId() - 1;
currentRound.endTime = block.timestamp;
}
function getRound(uint16 roundNumber) public view returns (Round memory) {
return rounds[roundNumber];
}
function getCurrentRound() public view returns (Round memory) {
return getRound(currentRoundNumber);
}
function setMaxMintingId(uint256 maxId) external {
setMaxMintingId(currentRoundNumber, maxId);
}
function setMaxMintingId(uint16 roundNumber, uint256 maxId)
public
onlyOwnerOrAdmin(roundNumber)
{
if (maxId < _nextTokenId()) {
revert MaxMintingIdLowerThanCurrentId();
}
if (maxId > maximumSupply) {
revert ExceedMaximumSupply();
}
Round storage round = rounds[roundNumber];
round.maxMintingId = maxId;
emit MaxMintingIdUpdated(roundNumber, maxId);
}
function setTokenURIPrefix(string memory prefix) external {
setTokenURIPrefix(currentRoundNumber, prefix);
}
function setTokenURIPrefix(uint16 roundNumber, string memory prefix)
public
onlyOwnerOrAdmin(roundNumber)
{
if (permanent) {
revert ImmutableState();
}
Round storage round = rounds[roundNumber];
round.tokenURIPrefix = prefix;
emit TokenURIPrefixUpdated(roundNumber, prefix);
}
function setMintingFee(uint256 fee) external {
setMintingFee(currentRoundNumber, fee);
}
function setMintingFee(uint16 roundNumber, uint256 fee)
public
onlyOwnerOrAdmin(roundNumber)
{
Round storage round = rounds[roundNumber];
round.mintingFee = fee;
emit MintingFeeUpdated(roundNumber, fee);
}
function setMaxAllowedMintingQuantity(uint16 quantity) external {
setMaxAllowedMintingQuantity(currentRoundNumber, quantity);
}
function setMaxAllowedMintingQuantity(uint16 roundNumber, uint16 quantity)
public
onlyOwnerOrAdmin(roundNumber)
{
Round storage round = rounds[roundNumber];
round.maxAllowedMintingQuantity = quantity;
emit MaxAllowedMintingCountUpdated(roundNumber, quantity);
}
function setWhitelisted(bool whitelisted) external {
setWhitelisted(currentRoundNumber, whitelisted);
}
function setWhitelisted(uint16 roundNumber, bool whitelisted)
public
onlyOwnerOrAdmin(roundNumber)
{
Round storage round = rounds[roundNumber];
round.whitelisted = whitelisted;
emit WhitelistRequiredChanged(roundNumber, whitelisted);
}
function setRevealBlock() external {
setRevealBlock(currentRoundNumber);
}
function setRevealBlock(uint16 roundNumber)
public
onlyOwnerOrAdmin(roundNumber)
{
Round storage round = rounds[roundNumber];
if (round.lastMintedId == 0) {
revert BadRequest("Round should be closed");
}
round.revealBlockNumber = block.number + revealBlockOffset;
emit SetRevealBlock(round.revealBlockNumber);
}
function setRandomSelection(uint16 roundNumber) public {
Round storage round = rounds[roundNumber];
if (round.revealed) {
revert AlreadyRevealed();
}
uint256 revealBlockNumber = round.revealBlockNumber;
if (revealBlockNumber > block.number) {
revert BadRequest("Random selection is not ready");
}
bytes32 entropy;
if (blockhash(revealBlockNumber - 1) != 0) {
entropy = keccak256(
abi.encodePacked(
blockhash(revealBlockNumber),
blockhash(revealBlockNumber - 1),
block.timestamp
)
);
} else {
entropy = keccak256(
abi.encodePacked(
blockhash(block.number - 1),
blockhash(block.number - 2),
block.timestamp
)
);
}
round.revealed = true;
uint256 selected = _getRandomInRange(
entropy,
round.startId,
round.lastMintedId
);
round.randomSelection = selected;
emit Revealed(roundNumber);
}
function setRevealed() external {
setRevealed(currentRoundNumber);
}
function setRevealed(uint16 roundNumber)
public
onlyOwnerOrAdmin(roundNumber)
{
Round storage round = rounds[roundNumber];
if (round.lastMintedId == 0) {
revert BadRequest("Round is still open");
}
round.revealed = true;
emit Revealed(roundNumber);
}
function setStartTime(uint256 time) external {
setStartTime(currentRoundNumber, time);
}
function setStartTime(uint16 roundNumber, uint256 time)
public
onlyOwnerOrAdmin(roundNumber)
{
Round storage round = rounds[roundNumber];
round.startTime = time;
emit StartTimeUpdated(roundNumber, time);
}
function setEndTime(uint256 time) external {
setEndTime(currentRoundNumber, time);
}
function setEndTime(uint16 roundNumber, uint256 time)
public
onlyOwnerOrAdmin(roundNumber)
{
Round storage round = rounds[roundNumber];
round.endTime = time;
emit EndTimeUpdated(roundNumber, time);
}
function setOnlyAdminRound(bool onlyAdmin) external {
setOnlyAdminRound(currentRoundNumber, onlyAdmin);
}
function setOnlyAdminRound(uint16 roundNumber, bool onlyAdmin)
public
onlyOwner
{
Round storage round = rounds[roundNumber];
round.onlyAdminRound = onlyAdmin;
emit OnlyAdminRoundChanged(roundNumber, onlyAdmin);
}
function setAdmin(address admin) external {
setAdmin(currentRoundNumber, admin);
}
function setAdmin(uint16 roundNumber, address admin) public onlyOwner {
Round storage round = rounds[roundNumber];
round.admin = admin;
emit AdminUpdated(roundNumber, admin);
}
function _baseURI() internal view override returns (string memory) {
return baseURI;
}
function getBaseURI() external view returns (string memory) {
return _baseURI();
}
function setBaseURI(string memory _newBaseURI) external onlyOwner {
if (permanent) {
revert ImmutableState();
}
baseURI = _newBaseURI;
emit BaseURIUpdated(_newBaseURI);
}
function setDefaultUnrevealedURI(string memory _defaultUnrevealedURI)
external
onlyOwner
{
defaultUnrevealedURI = _defaultUnrevealedURI;
emit DefaultUnrevealedURIUpdated(_defaultUnrevealedURI);
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function setReceiver(address receiver) external onlyOwner {
_receiver = receiver;
}
function withdraw() external payable onlyOwner {
uint256 amount = address(this).balance;
(bool success, ) = _receiver.call{value: amount}("");
if (!success) {
revert FailedToSendBalance();
}
emit Withdraw(_receiver, amount);
}
fallback() external payable {
emit Received(_msgSender(), msg.value);
}
receive() external payable {
emit Received(_msgSender(), msg.value);
}
function setPermanent() external onlyOwner {
permanent = true;
}
function updateSigner(address newSigner) external onlyOwner {
_signer = newSigner;
}
function updateRevealBlockOffset(uint256 newOffset) external onlyOwner {
revealBlockOffset = newOffset;
}
function _sanityCheckForMinting(Round memory currentRound, uint256 quantity)
private
{
if (currentRound.onlyAdminRound) {
revert AdminOnlyRound();
}
State currentState = getState();
if (currentState != State.ON_MINTING) {
revert MintingNotAllowed();
}
if (
currentRound.maxAllowedMintingQuantity != 0 &&
currentRound.maxAllowedMintingQuantity < quantity
) {
revert ExceedAllowedQuantity(
currentRound.maxAllowedMintingQuantity
);
}
if (!_isTokenAvailable(quantity, currentRound.maxMintingId)) {
revert ExceedMaximumForTheRound();
}
uint256 neededFee = currentRound.mintingFee * quantity;
if (neededFee != msg.value) revert NoMatchingFee();
}
function _isTokenAvailable(uint256 quantity, uint256 maxId)
private
view
returns (bool)
{
if (_nextTokenId() + quantity > (maxId + 1)) {
return false;
}
return true;
}
function _getRoundByTokenId(uint256 tokenId)
private
view
returns (Round memory r)
{
if (!_exists(tokenId)) revert NonExistingToken(tokenId);
uint16 roundNumber = 1;
while (roundNumber <= currentRoundNumber) {
r = rounds[roundNumber];
uint256 roundMax = r.lastMintedId != 0
? r.lastMintedId
: r.maxMintingId;
if (tokenId > roundMax) {
roundNumber++;
continue;
}
return r;
}
}
function _updateWhitelistUsed(
uint16 round,
uint16 quantity,
uint8 v,
bytes32 r,
bytes32 s
) private {
bytes32 hash = _getHash(round, _msgSender(), "whitelistClaim");
if (!_verifySig(hash, v, r, s)) {
revert SignatureNotMatch();
}
whitelists[round][_msgSender()] += quantity;
}
function _getHash(
uint16 round,
address sender,
string memory message
) private view returns (bytes32) {
return
keccak256(abi.encodePacked(address(this), round, sender, message));
}
function _verifySig(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) private view returns (bool) {
return ecrecover(hash, v, r, s) == _signer;
}
function _getRandomInRange(
bytes32 hash,
uint256 begin,
uint256 end
) private pure returns (uint256) {
uint256 diff = end - begin + 1;
return (uint256(hash) % diff) + begin;
}
}
文件 4 的 8:IERC721A.sol
pragma solidity ^0.8.4;
interface IERC721A {
error ApprovalCallerNotOwnerNorApproved();
error ApprovalQueryForNonexistentToken();
error ApproveToCaller();
error ApprovalToCurrentOwner();
error BalanceQueryForZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error OwnerQueryForNonexistentToken();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TransferToNonERC721ReceiverImplementer();
error TransferToZeroAddress();
error URIQueryForNonexistentToken();
struct TokenOwnership {
address addr;
uint64 startTimestamp;
bool burned;
}
function totalSupply() external view returns (uint256);
function supportsInterface(bytes4 interfaceId) external view returns (bool);
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 5 的 8:IHyewonNft.sol
pragma solidity ^0.8.4;
interface IHyewonNft {
error MintingNotStarted(uint256 startTime);
error MintingEnded(uint256 endTime);
error MintingNotAllowed();
error ExceedMaximumForTheRound();
error ExceedMaximumSupply();
error ExceedAllowedQuantity(uint16 maximumAllowedQuantity);
error MaxMintingIdLowerThanCurrentId();
error NoMatchingFee();
error NonExistingToken(uint256 tokenId);
error AddressNotWhitelisted(address candidate);
error NotEnoughAllowanceLeft(uint16 remainingAllowance);
error FailedToSendBalance();
error NotOwnerNorAdmin(address account);
error AdminOnlyRound();
error BadRequest(string reason);
error WhitelistOnlyRound();
error NotWhitelistOnlyRound();
error SignatureNotMatch();
error AlreadyRevealed();
error ImmutableState();
enum State {
DEPLOYED,
PREPARE_MINTING,
ON_MINTING,
END_MINTING,
ALL_MINTING_DONE
}
struct Round {
uint16 roundNumber;
uint256 maxMintingId;
uint256 startId;
uint256 lastMintedId;
string tokenURIPrefix;
uint256 mintingFee;
uint16 maxAllowedMintingQuantity;
bool whitelisted;
bool revealed;
uint256 revealBlockNumber;
uint256 randomSelection;
uint256 startTime;
uint256 endTime;
bool onlyAdminRound;
address admin;
}
event NewRoundCreated();
event MaxMintingIdUpdated(uint16 roundNumber, uint256 maxId);
event TokenURIPrefixUpdated(uint16 roundNumber, string prefix);
event MintingFeeUpdated(uint16 roundNumber, uint256 fee);
event MaxAllowedMintingCountUpdated(uint16 roundNumber, uint16 count);
event WhitelistRequiredChanged(uint16 roundNumber, bool whitelisted);
event SetRevealBlock(uint256 revealBlockNumber);
event Revealed(uint16 roundNumber);
event UnrevealedURIUpdated(uint16 roundNumber, string uri);
event StartTimeUpdated(uint16 roundNumber, uint256 time);
event EndTimeUpdated(uint16 roundNumber, uint256 time);
event OnlyAdminRoundChanged(uint16 roundNumber, bool onlyAdmin);
event AdminUpdated(uint16 roundNumber, address admin);
event BaseURIUpdated(string baseURI);
event DefaultUnrevealedURIUpdated(string defaultUnrevealedURI);
event MintingFeeChanged(uint256 newFee);
event MaxPublicIdChanged(uint16 newMaxPubId);
event Received(address called, uint256 amount);
event Withdraw(address receiver, uint256 amount);
}
文件 6 的 8:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 7 的 8:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 8 的 8:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
{
"compilationTarget": {
"contracts/HyewonNft.sol": "HyewonNft"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"string","name":"_baseUri","type":"string"},{"internalType":"string","name":"_defaultUnrevealedURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"candidate","type":"address"}],"name":"AddressNotWhitelisted","type":"error"},{"inputs":[],"name":"AdminOnlyRound","type":"error"},{"inputs":[],"name":"AlreadyRevealed","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"BadRequest","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[{"internalType":"uint16","name":"maximumAllowedQuantity","type":"uint16"}],"name":"ExceedAllowedQuantity","type":"error"},{"inputs":[],"name":"ExceedMaximumForTheRound","type":"error"},{"inputs":[],"name":"ExceedMaximumSupply","type":"error"},{"inputs":[],"name":"FailedToSendBalance","type":"error"},{"inputs":[],"name":"ImmutableState","type":"error"},{"inputs":[],"name":"MaxMintingIdLowerThanCurrentId","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"MintingEnded","type":"error"},{"inputs":[],"name":"MintingNotAllowed","type":"error"},{"inputs":[{"internalType":"uint256","name":"startTime","type":"uint256"}],"name":"MintingNotStarted","type":"error"},{"inputs":[],"name":"NoMatchingFee","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NonExistingToken","type":"error"},{"inputs":[{"internalType":"uint16","name":"remainingAllowance","type":"uint16"}],"name":"NotEnoughAllowanceLeft","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotOwnerNorAdmin","type":"error"},{"inputs":[],"name":"NotWhitelistOnlyRound","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"SignatureNotMatch","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":"WhitelistOnlyRound","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"AdminUpdated","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":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"defaultUnrevealedURI","type":"string"}],"name":"DefaultUnrevealedURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"EndTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"count","type":"uint16"}],"name":"MaxAllowedMintingCountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"maxId","type":"uint256"}],"name":"MaxMintingIdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"newMaxPubId","type":"uint16"}],"name":"MaxPublicIdChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"MintingFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"MintingFeeUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"NewRoundCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"bool","name":"onlyAdmin","type":"bool"}],"name":"OnlyAdminRoundChanged","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"called","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"}],"name":"Revealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"revealBlockNumber","type":"uint256"}],"name":"SetRevealBlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"StartTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"string","name":"prefix","type":"string"}],"name":"TokenURIPrefixUpdated","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"UnrevealedURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"roundNumber","type":"uint16"},{"indexed":false,"internalType":"bool","name":"whitelisted","type":"bool"}],"name":"WhitelistRequiredChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"adminMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tos","type":"address[]"},{"internalType":"uint256[]","name":"quantities","type":"uint256[]"}],"name":"adminMintTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRoundNumber","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endRound","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":[],"name":"getBaseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentRound","outputs":[{"components":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"uint256","name":"maxMintingId","type":"uint256"},{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"lastMintedId","type":"uint256"},{"internalType":"string","name":"tokenURIPrefix","type":"string"},{"internalType":"uint256","name":"mintingFee","type":"uint256"},{"internalType":"uint16","name":"maxAllowedMintingQuantity","type":"uint16"},{"internalType":"bool","name":"whitelisted","type":"bool"},{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"uint256","name":"revealBlockNumber","type":"uint256"},{"internalType":"uint256","name":"randomSelection","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"onlyAdminRound","type":"bool"},{"internalType":"address","name":"admin","type":"address"}],"internalType":"struct IHyewonNft.Round","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"}],"name":"getRound","outputs":[{"components":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"uint256","name":"maxMintingId","type":"uint256"},{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"lastMintedId","type":"uint256"},{"internalType":"string","name":"tokenURIPrefix","type":"string"},{"internalType":"uint256","name":"mintingFee","type":"uint256"},{"internalType":"uint16","name":"maxAllowedMintingQuantity","type":"uint16"},{"internalType":"bool","name":"whitelisted","type":"bool"},{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"uint256","name":"revealBlockNumber","type":"uint256"},{"internalType":"uint256","name":"randomSelection","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"onlyAdminRound","type":"bool"},{"internalType":"address","name":"admin","type":"address"}],"internalType":"struct IHyewonNft.Round","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"internalType":"enum IHyewonNft.State","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxMintingId","type":"uint256"},{"internalType":"uint256","name":"mintingFee","type":"uint256"},{"internalType":"uint16","name":"maxAllowedMintingQuantity","type":"uint16"},{"internalType":"bool","name":"whitelisted","type":"bool"},{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"onlyAdminRound","type":"bool"},{"internalType":"address","name":"admin","type":"address"}],"name":"newRound","outputs":[],"stateMutability":"nonpayable","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":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permanent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealBlockOffset","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":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"address","name":"admin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_defaultUnrevealedURI","type":"string"}],"name":"setDefaultUnrevealedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setEndTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setEndTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"uint16","name":"quantity","type":"uint16"}],"name":"setMaxAllowedMintingQuantity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"quantity","type":"uint16"}],"name":"setMaxAllowedMintingQuantity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"uint256","name":"maxId","type":"uint256"}],"name":"setMaxMintingId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxId","type":"uint256"}],"name":"setMaxMintingId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setMintingFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setMintingFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"onlyAdmin","type":"bool"}],"name":"setOnlyAdminRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"bool","name":"onlyAdmin","type":"bool"}],"name":"setOnlyAdminRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setPermanent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"}],"name":"setRandomSelection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"setReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setRevealBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"}],"name":"setRevealBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setRevealed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"}],"name":"setRevealed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"whitelisted","type":"bool"}],"name":"setWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"roundNumber","type":"uint16"},{"internalType":"bool","name":"whitelisted","type":"bool"}],"name":"setWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"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":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"transferBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newOffset","type":"uint256"}],"name":"updateRevealBlockOffset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigner","type":"address"}],"name":"updateSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint16","name":"quantity","type":"uint16"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]