编译器
0.8.16+commit.07a7930e
文件 1 的 8:Addresses.sol
pragma solidity 0.8.16;
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly {
codehash := extcodehash(account)
}
return (codehash != accountHash && codehash != 0x0);
}
}
文件 2 的 8:BaseERC721.sol
pragma solidity 0.8.16;
import "./Addresses.sol";
import "./Strings.sol";
import "./ERC721Receiver.sol";
import "./IERC721.sol";
abstract contract ERC721BasicToken is IERC721 {
using Address for address;
using Strings for uint256;
bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd;
bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79;
bytes4 private constant ERC721_RECEIVED = 0xf0b9e5ba;
bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63;
bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f;
bytes4 private constant InterfaceId_ERC165 = 0x01ffc9a7;
string internal name_;
string internal symbol_;
string public baseTokenURI;
uint256[] internal allTokens;
mapping(bytes4 => bool) internal supportedInterfaces;
mapping(address => mapping(uint256 => uint256)) internal ownedTokens;
mapping(uint256 => uint256) internal ownedTokensIndex;
mapping(uint256 => uint256) internal allTokensIndex;
mapping(uint256 => address) internal tokenOwner;
mapping(uint256 => address) internal tokenApprovals;
mapping(address => uint256) internal ownedTokensCount;
mapping(address => mapping(address => bool)) internal operatorApprovals;
modifier onlyOwnerOf(uint256 _tokenId) {
require(ownerOf(_tokenId) == msg.sender, "Only asset owner is allowed");
_;
}
modifier canTransfer(uint256 _tokenId) {
require(isApprovedOrOwner(msg.sender, _tokenId), "Can not transfer");
_;
}
constructor(
string memory _name,
string memory _symbol,
string memory _baseTokenUri
) {
name_ = _name;
symbol_ = _symbol;
baseTokenURI = _baseTokenUri;
_registerInterface(InterfaceId_ERC721Enumerable);
_registerInterface(InterfaceId_ERC721Metadata);
_registerInterface(InterfaceId_ERC721);
_registerInterface(InterfaceId_ERC721Exists);
_registerInterface(InterfaceId_ERC165);
}
function name() external view returns (string memory) {
return name_;
}
function symbol() external view returns (string memory) {
return symbol_;
}
function tokenURI(uint256 _tokenId)
public
view
virtual
returns (string memory)
{
require(exists(_tokenId), "Asset does not exist");
return string(abi.encodePacked(baseTokenURI, _tokenId.toString()));
}
function balanceOf(address _owner) public view returns (uint256) {
require(_owner != address(0), "Zero address not allowed");
return ownedTokensCount[_owner];
}
function ownerOf(uint256 _tokenId) public view returns (address) {
address owner = tokenOwner[_tokenId];
require(owner != address(0), "Token does not exists");
return owner;
}
function exists(uint256 _tokenId) public view returns (bool) {
address owner = tokenOwner[_tokenId];
return owner != address(0);
}
function _approve(address _to, uint256 _tokenId) internal {
address owner = ownerOf(_tokenId);
require(_to != owner, "Can not approve to self");
require(
msg.sender == owner || isApprovedForAll(owner, msg.sender),
"Not allowed to update approvals"
);
tokenApprovals[_tokenId] = _to;
emit Approval(owner, _to, _tokenId);
}
function getApproved(uint256 _tokenId) public view returns (address) {
return tokenApprovals[_tokenId];
}
function _setApprovalForAll(address _to, bool _approved) internal {
require(_to != msg.sender, "Can not approve to self");
operatorApprovals[msg.sender][_to] = _approved;
emit ApprovalForAll(msg.sender, _to, _approved);
}
function isApprovedForAll(address _owner, address _operator)
public
view
returns (bool)
{
return operatorApprovals[_owner][_operator];
}
function _transferFrom(
address _from,
address _to,
uint256 _tokenId
) internal canTransfer(_tokenId) {
_transfer(_from, _to, _tokenId);
}
function _transferOnBehalf(
address _from,
address _to,
uint256 _tokenId
) internal {
require(isApprovedOrOwner(_from, _tokenId), "Can not transfer");
_transfer(_from, _to, _tokenId);
}
function _transfer(
address _from,
address _to,
uint256 _tokenId
) private {
require(_to != address(0), "Zero address not allowed");
clearApproval(_from, _tokenId);
removeTokenFrom(_from, _tokenId);
addTokenTo(_to, _tokenId);
emit Transfer(_from, _to, _tokenId);
}
function _safeTransferFrom(
address _from,
address _to,
uint256 _tokenId
) internal {
_safeTransferFrom(_from, _to, _tokenId, "");
}
function _safeTransferFrom(
address _from,
address _to,
uint256 _tokenId,
bytes memory _data
) internal {
_transferFrom(_from, _to, _tokenId);
require(
checkAndCallSafeTransfer(_from, _to, _tokenId, _data),
"Safe Transfer failed"
);
}
function isApprovedOrOwner(address _spender, uint256 _tokenId)
internal
view
returns (bool)
{
address owner = ownerOf(_tokenId);
return (_spender == owner ||
getApproved(_tokenId) == _spender ||
isApprovedForAll(owner, _spender));
}
function _mint(address _to, uint256 _tokenId) internal {
require(_to != address(0), "Zero address not allowed");
require(!exists(_tokenId), "Asset already exists");
addTokenTo(_to, _tokenId);
allTokensIndex[_tokenId] = allTokens.length;
allTokens.push(_tokenId);
emit Transfer(address(0), _to, _tokenId);
}
function removeFromAllTokens(uint256 tokenId) private {
uint256 lastTokenIndex = allTokens.length - 1;
uint256 tokenIndex = allTokensIndex[tokenId];
uint256 lastTokenId = allTokens[lastTokenIndex];
allTokens[tokenIndex] = lastTokenId;
allTokensIndex[lastTokenId] = tokenIndex;
delete allTokensIndex[tokenId];
allTokens.pop();
}
function _burn(address _owner, uint256 _tokenId)
internal
canTransfer(_tokenId)
{
clearApproval(_owner, _tokenId);
removeTokenFrom(_owner, _tokenId);
removeFromAllTokens(_tokenId);
tokenOwner[_tokenId] = address(0);
emit Transfer(_owner, address(0), _tokenId);
}
function clearApproval(address _owner, uint256 _tokenId) internal {
require(
ownerOf(_tokenId) == _owner,
"Asset does not belong to given owmer"
);
if (tokenApprovals[_tokenId] != address(0)) {
tokenApprovals[_tokenId] = address(0);
emit Approval(_owner, address(0), _tokenId);
}
}
function addTokenTo(address _to, uint256 _tokenId) internal {
uint256 length = balanceOf(_to);
ownedTokens[_to][length] = _tokenId;
ownedTokensIndex[_tokenId] = length;
ownedTokensCount[_to] = ownedTokensCount[_to] + 1;
tokenOwner[_tokenId] = _to;
}
function removeTokenFrom(address _from, uint256 _tokenId) internal {
uint256 lastTokenIndex = ownedTokensCount[_from] - 1;
uint256 tokenIndex = ownedTokensIndex[_tokenId];
if(lastTokenIndex != tokenIndex) {
uint256 lastTokenId = ownedTokens[_from][lastTokenIndex];
ownedTokens[_from][tokenIndex] = lastTokenId;
ownedTokensIndex[lastTokenId] = tokenIndex;
}
delete ownedTokensIndex[_tokenId];
delete ownedTokens[_from][lastTokenIndex];
ownedTokensCount[_from] = ownedTokensCount[_from]-1;
}
function checkAndCallSafeTransfer(
address _from,
address _to,
uint256 _tokenId,
bytes memory _data
) internal returns (bool) {
if (!_to.isContract()) {
return true;
}
bytes4 retval = ERC721Receiver(_to).onERC721Received(
_from,
_tokenId,
_data
);
return (retval == ERC721_RECEIVED);
}
function tokenOfOwnerByIndex(address _owner, uint256 _index)
public
view
returns (uint256)
{
require(_index < balanceOf(_owner), "Invalid index");
return ownedTokens[_owner][_index];
}
function totalSupply() public view returns (uint256) {
return allTokens.length;
}
function tokenByIndex(uint256 _index) public view returns (uint256) {
require(_index < totalSupply(), "Invalid index");
return allTokens[_index];
}
function supportsInterface(bytes4 _interfaceId)
external
view
returns (bool)
{
return supportedInterfaces[_interfaceId];
}
function _registerInterface(bytes4 _interfaceId) internal {
require(_interfaceId != 0xffffffff);
supportedInterfaces[_interfaceId] = true;
}
}
文件 3 的 8:ERC721.sol
pragma solidity 0.8.16;
import "./BaseERC721.sol";
contract ERC721 is ERC721BasicToken {
using Strings for uint256;
mapping(uint256 => string) internal _tokenUri;
string public extension;
event TokenURIUpdated(uint256 tokenId, string _url);
event BaseTokenURIUpdated(string _baseUrl);
constructor(
string memory _name,
string memory _symbol,
string memory _baseTokenUri,
string memory _extension
) ERC721BasicToken(_name, _symbol, _baseTokenUri) {
extension= _extension;
emit BaseTokenURIUpdated(_baseTokenUri);
}
function approve(address _to, uint256 _tokenId) public {
super._approve(_to, _tokenId);
}
function setApprovalForAll(address _to, bool _approved) public {
super._setApprovalForAll(_to, _approved);
}
function transferFrom(
address _from,
address _to,
uint256 _tokenId
) public virtual {
super._transferFrom(_from, _to, _tokenId);
}
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId
) public virtual {
super._safeTransferFrom(_from, _to, _tokenId, "0x");
}
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId,
bytes memory _data
) public virtual {
super._safeTransferFrom(_from, _to, _tokenId, _data);
}
function _updateTokenUri(uint256 _tokenId, string memory _url) internal {
_tokenUri[_tokenId] = _url;
emit TokenURIUpdated(_tokenId, _url);
}
function _updateBaseTokenUri(string memory _baseTokenUri) internal {
baseTokenURI = _baseTokenUri;
emit BaseTokenURIUpdated(_baseTokenUri);
}
function mint(
address _to,
uint256 _tokenId
) internal {
super._mint(_to, _tokenId);
}
function burn(uint256 _tokenId) public virtual {
super._burn(ownerOf(_tokenId), _tokenId);
}
function _tokenURI(uint256 _tokenId)
public
view
virtual
returns (string memory)
{
if (bytes(_tokenUri[_tokenId]).length == 0) {
return string(abi.encodePacked(baseTokenURI, _tokenId.toString(), extension));
}
return string(abi.encodePacked(baseTokenURI, _tokenUri[_tokenId], extension));
}
}
文件 4 的 8:ERC721Receiver.sol
pragma solidity 0.8.16;
abstract contract ERC721Receiver {
bytes4 internal constant ERC721_RECEIVED = 0xf0b9e5ba;
function onERC721Received(
address _from,
uint256 _tokenId,
bytes memory _data
) public virtual returns (bytes4);
}
文件 5 的 8:IERC721.sol
pragma solidity 0.8.16;
interface IERC721 {
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 exists(uint256 _tokenId) external view returns (bool _exists);
function approve(address _to, uint256 _tokenId) external;
function getApproved(uint256 _tokenId)
external
view
returns (address _operator);
function setApprovalForAll(address _operator, bool _approved) external;
function isApprovedForAll(address _owner, address _operator)
external
view
returns (bool);
function transferFrom(
address _from,
address _to,
uint256 _tokenId
) external;
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId
) external;
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId,
bytes memory _data
) external;
function name() external view returns (string memory _name);
function symbol() external view returns (string memory _symbol);
function tokenURI(uint256 _tokenId) external view returns (string memory);
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address _owner, uint256 _index)
external
view
returns (uint256 _tokenId);
function tokenByIndex(uint256 _index) external view returns (uint256);
function supportsInterface(bytes4 _interfaceId)
external
view
returns (bool);
}
文件 6 的 8:Ownership.sol
pragma solidity 0.8.16;
contract Ownership {
address public owner;
address[] public deputyOwners;
mapping(address => bool) public isDeputyOwner;
event OwnershipUpdated(address oldOwner, address newOwner);
event DeputyOwnerUpdated(address _do, bool _isAdded);
constructor() {
owner = msg.sender;
addDeputyOwner(msg.sender);
}
modifier onlyOwner() {
require(msg.sender == owner, "Caller is not owner");
_;
}
modifier onlyDeputyOrOwner() {
require(
msg.sender == owner || isDeputyOwner[msg.sender],
"Caller is not owner or deputy"
);
_;
}
function updateOwner(address _newOwner) public onlyOwner {
require(_newOwner != address(0x0), "Invalid address");
owner = _newOwner;
emit OwnershipUpdated(msg.sender, owner);
}
function addDeputyOwner(address _newDO) public onlyOwner {
require(!isDeputyOwner[_newDO], "Deputy Owner already exists");
deputyOwners.push(_newDO);
isDeputyOwner[_newDO] = true;
emit DeputyOwnerUpdated(_newDO, true);
}
function removeDeputyOwner(address _existingDO) public onlyOwner {
require(isDeputyOwner[_existingDO], "Deputy Owner does not exits");
uint256 existingId;
for (uint256 i = 0; i < deputyOwners.length; i++) {
if (deputyOwners[i] == _existingDO) existingId = i;
}
deputyOwners[existingId] = deputyOwners[deputyOwners.length - 1];
delete deputyOwners[deputyOwners.length - 1];
isDeputyOwner[_existingDO] = false;
emit DeputyOwnerUpdated(_existingDO, false);
}
function renounceOwnership(uint256 _validationCode) public onlyOwner {
require(_validationCode == 123456789, "Invalid code");
owner = address(0);
emit OwnershipUpdated(msg.sender, owner);
}
}
文件 7 的 8:Strings.sol
pragma solidity 0.8.16;
library Strings {
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
}
文件 8 的 8:Thunderbirds.sol
pragma solidity 0.8.16;
import "./ERC721.sol";
import "./Ownership.sol";
interface IMintPass {
function getRedeemedTimes(uint256 tokenId) external view returns(uint8);
function ownerOf(uint256 _tokenId) external view returns (address);
function balanceOf(address _owner) external view returns (uint256);
function exists(uint256 _tokenId) external view returns (bool);
function tokenOfOwnerByIndex(address _owner, uint256 _index)
external
view
returns (uint256 _tokenId);
function updateRedeemedTimes(uint256 tokenId, uint8 _redeemedTimes) external;
}
contract Thunderbirds is ERC721, Ownership {
uint256 public maxSupply;
uint256 public preSaleStarts;
uint256 public preSaleEnds;
uint256 public saleEnds;
IMintPass private mintPass;
bool public isPaused = false;
uint256 public price;
address payable public coldWallet;
uint256 public mintedForTeam;
bool public isRevealed;
uint256 private constant reservedForTeam = 30;
uint8 private constant MAX_REDEEME_COUNT = 3;
mapping(address => mapping(uint => bool)) public isSignerNonceUsed;
struct Signature {
bytes32 r;
bytes32 s;
uint8 v;
}
event Paused(bool _isPaused);
event PriceUpdate(uint256 oldPrice, uint256 newPrice);
modifier notPaused() {
require(!isPaused, "Contract paused");
_;
}
modifier canMint(uint8 quantity) {
require(block.timestamp >= preSaleStarts , "Sale not live yet");
require(block.timestamp < saleEnds, "Sale closed");
require(totalSupply() + quantity <= maxSupply - reservedForTeam, "Sold out");
require(msg.value == price*quantity, "Incorrect fee");
_;
}
constructor(
address _mintPassContract,
uint256 _preSaleStarts,
uint256 _preSaleEnds,
address payable _coldWallet,
uint256 _price,
string memory _baseurl
)
ERC721("Thunderbirds International Rescue Club", "FAB", _baseurl, ".json")
{
mintPass = IMintPass(_mintPassContract);
maxSupply = 5432;
price = _price;
coldWallet = _coldWallet;
preSaleStarts = _preSaleStarts;
preSaleEnds = _preSaleEnds;
saleEnds = preSaleEnds + 1 weeks;
isRevealed = false;
}
function mint(address user, uint8 quantity) public payable canMint(quantity) notPaused {
require(block.timestamp >= preSaleEnds, "Only mintpass holders allowed in presale");
coldWallet.transfer(msg.value);
_batchMint(user, quantity);
}
function mintWithPass(address user, uint8 quantity, uint256 mintPassId) public payable canMint(quantity) {
require(block.timestamp < preSaleEnds, "Pre-sale ended");
require(mintPass.exists(mintPassId), "Invalid mint pass");
require(mintPass.ownerOf(mintPassId) == msg.sender, "Sender does not own given mint pass");
coldWallet.transfer(msg.value);
uint8 redeemedTimes = mintPass.getRedeemedTimes(mintPassId);
require(redeemedTimes+quantity <= MAX_REDEEME_COUNT, "Mint pass redeemed");
mintPass.updateRedeemedTimes(mintPassId, redeemedTimes+quantity);
_batchMint(user, quantity);
}
function mintReservedTokens(address[] memory users) public onlyDeputyOrOwner {
require(mintedForTeam + users.length <= reservedForTeam, "Max reserved tokens minted");
unchecked {
mintedForTeam += users.length;
}
for(uint8 i=0; i<users.length; i++) {
super.mint(users[i], totalSupply()+1);
}
}
function updatePrice(uint256 _price) public onlyOwner {
emit PriceUpdate(price, _price);
price = _price;
}
function _batchMint(address user, uint8 quantity) internal {
for(uint8 i=0; i<quantity; i++) {
super.mint(user, totalSupply() + 1);
}
}
function transferFrom(
address _from,
address _to,
uint256 _tokenId
) public override notPaused {
super._transferFrom(_from, _to, _tokenId);
}
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId
) public override notPaused {
super._safeTransferFrom(_from, _to, _tokenId, "0x");
}
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId,
bytes memory _data
) public override notPaused {
super._safeTransferFrom(_from, _to, _tokenId, _data);
}
function burn(uint256 _tokenId) public override notPaused {
super.burn(_tokenId);
}
function preAuthTransfer(
address _from, address _to, uint256 _tokenId, uint256 signerNonce, Signature memory signature
) public notPaused {
require(
!isSignerNonceUsed[_from][signerNonce],
"Duplicate nonce in signature"
);
bytes32 hash = keccak256(
abi.encodePacked(
bytes4(keccak256("transfer")),
address(this),
signerNonce,
getChainID(),
_from,
_to,
_tokenId
)
);
address signer = getSigner(hash, signature);
require(signer == _from, "Owner and signer don't match");
isSignerNonceUsed[signer][signerNonce] = true;
super._transferOnBehalf(signer, _to, _tokenId);
}
function updateBaseTokenUri(string memory _baseTokenUri) public onlyOwner {
super._updateBaseTokenUri(_baseTokenUri);
}
function pauseContract(bool _isPaused) public onlyOwner{
isPaused = _isPaused;
emit Paused(_isPaused);
}
function reveal() public onlyOwner {
isRevealed = true;
}
function tokenURI(uint256 _tokenId)
public
view
override
returns (string memory)
{
require(exists(_tokenId), "Asset does not exist");
if(!isRevealed) return baseTokenURI;
return super._tokenURI(_tokenId);
}
function getSigner(bytes32 message, Signature memory sig)
public
pure
returns (address)
{
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, message));
address signer = ecrecover(prefixedHash, sig.v, sig.r, sig.s);
return signer;
}
function getChainID() internal view returns (uint256) {
uint256 id;
assembly {
id := chainid()
}
return id;
}
}
{
"compilationTarget": {
"Thunderbirds.sol": "Thunderbirds"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_mintPassContract","type":"address"},{"internalType":"uint256","name":"_preSaleStarts","type":"uint256"},{"internalType":"uint256","name":"_preSaleEnds","type":"uint256"},{"internalType":"address payable","name":"_coldWallet","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"string","name":"_baseurl","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"_baseUrl","type":"string"}],"name":"BaseTokenURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_do","type":"address"},{"indexed":false,"internalType":"bool","name":"_isAdded","type":"bool"}],"name":"DeputyOwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_isPaused","type":"bool"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"PriceUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"_url","type":"string"}],"name":"TokenURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"_tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newDO","type":"address"}],"name":"addDeputyOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"coldWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"deputyOwners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extension","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"message","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct Thunderbirds.Signature","name":"sig","type":"tuple"}],"name":"getSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isDeputyOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRevealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"isSignerNonceUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint8","name":"quantity","type":"uint8"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"}],"name":"mintReservedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint8","name":"quantity","type":"uint8"},{"internalType":"uint256","name":"mintPassId","type":"uint256"}],"name":"mintWithPass","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintedForTeam","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isPaused","type":"bool"}],"name":"pauseContract","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":"uint256","name":"signerNonce","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct Thunderbirds.Signature","name":"signature","type":"tuple"}],"name":"preAuthTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"preSaleEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preSaleStarts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_existingDO","type":"address"}],"name":"removeDeputyOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_validationCode","type":"uint256"}],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reveal","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":"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":[],"name":"saleEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseTokenUri","type":"string"}],"name":"updateBaseTokenUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"updateOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"updatePrice","outputs":[],"stateMutability":"nonpayable","type":"function"}]