文件 1 的 19:Address.sol
pragma solidity ^0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 19:ApeHarbourDinghies.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "./base64.sol";
contract ApeHarbourDinghies is ERC721Enumerable, VRFConsumerBase, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
IERC721 private bayc;
IERC721 private bakc;
address private minter;
uint256 public randomSeed;
bytes32 internal keyHash;
uint256 internal chainLinkFee;
bytes32 public requestId;
string constant preRevealImageUrl = 'ipfs://QmNNmPE3FEk5xZ79zTKQC6ekm1vVX25gQivfQguVwRGMbu';
string public revealedCollectionBaseURL;
bool public frozen;
uint8 constant BITMASK = 255;
uint8[][2] private cutoffs;
string[][2] private traitValues;
enum Keys { backgrounds, surfboard }
string[] private traits = [ "Background", "Surfboard" ];
event Reveal(uint256 randomness);
event Mint(address indexed owner);
modifier onlyApeOwner() {
require(
bayc.balanceOf(msg.sender) > 0,
"ApeOwner: Caller is not an ape owner"
);
_;
}
modifier onlyDogOwner() {
require(
bakc.balanceOf(msg.sender) > 0,
"DogOwner: Caller is not a dog owner"
);
_;
}
modifier onlyMinter() {
require(msg.sender == minter, 'Minting only allowed from AHY');
_;
}
constructor(
address _baycAddress,
address _bakcAddress,
address _linkAddress,
address _vrfCoordinatorAddress,
bytes32 _keyHash,
uint256 _chainLinkFee
) ERC721("Ape Harbour Dinghies", "AHD")
VRFConsumerBase(_vrfCoordinatorAddress, _linkAddress) {
bayc = IERC721(_baycAddress);
bakc = IERC721(_bakcAddress);
keyHash = _keyHash;
chainLinkFee = _chainLinkFee;
traitValues[uint256(Keys.backgrounds)] = ['Apelantic', 'Banana Bay', 'Everglades Ape Park', 'Ape Island', 'Apebiza'];
traitValues[uint256(Keys.surfboard)] = ['Black', 'Prison', 'Trippy', 'Cheetah', 'Ocean Green', 'Wooden', 'Diamond', 'Mahogany', 'Classic', 'Pink', 'Gold', 'Pizza', 'White Stripes', 'Radioactive', 'USA', 'Polkadots', 'Plastic', 'Banana Pirates', 'Watermelons', 'Rainbow', 'Fomo Blue', 'Pink HOLD', 'Red Apes', 'Lofi Pink', 'Lofi Blue', 'VHS', 'Static'];
cutoffs[uint256(Keys.backgrounds)] = [30,111,154,197,253];
cutoffs[uint256(Keys.surfboard)] = [12,19,24,29,41,48,50,57,69,81,83,95,107,114,126,133,138,150,162,174,186,193,205,212,224,231,238];
}
function setMinter(address _minter) public onlyOwner {
minter = _minter;
}
function mint(address _to) external onlyMinter returns (uint256) {
_tokenIds.increment();
uint256 newTokenId = _tokenIds.current();
_safeMint(_to, newTokenId);
emit Mint(_to);
return _tokenIds.current();
}
function reveal() public onlyOwner {
require(
LINK.balanceOf(address(this)) >= chainLinkFee,
"Not enough LINK - fill contract with faucet"
);
require(randomSeed == 0, 'Randomness has already been set');
requestId = requestRandomness(keyHash, chainLinkFee);
}
function fulfillRandomness(bytes32 _requestId, uint256 _randomness)
internal
override
{
require(requestId == _requestId);
randomSeed = _randomness;
emit Reveal(_randomness);
}
function decodeTokenId(uint256 randomValue, uint256 _tokenId)
public
view
returns (uint256[] memory)
{
require(randomValue != 0, "Tokens have not been revealed yet");
uint256 tokenCode = uint256(
keccak256(abi.encode(randomValue, _tokenId))
);
uint8[2] memory shifts = [ 0, 8 ];
uint256[] memory tokenPart = new uint256[](shifts.length);
for (uint256 i = 0; i < shifts.length; i++) {
tokenPart[i] = (tokenCode >> shifts[i]) & BITMASK;
}
for (uint256 i = 0; i < tokenPart.length; i++) {
uint256 currentIdx = 0;
for (uint256 j = 0; j < cutoffs[i].length; j++) {
if (tokenPart[i] < cutoffs[i][j]) {
currentIdx = j;
break;
}
}
tokenPart[i] = currentIdx;
}
return tokenPart;
}
function getAttributeBytes(uint256 key, uint256 value)
private
view
returns (bytes memory, bool attributePresent)
{
if (
keccak256(abi.encodePacked(traitValues[key][value])) ==
keccak256(abi.encodePacked("null"))
) {
return ("", false);
}
return (
abi.encodePacked(
'{"trait_type": "',
traits[key],
'", "value": "',
traitValues[key][value],
'"}'
),
true
);
}
function getAttributes(uint256[] memory tokenPart)
private
view
returns (string memory) {
bytes memory attributes = '"attributes": [';
bytes memory singleAtt;
bool attPresent;
(singleAtt, attPresent) = getAttributeBytes(0, tokenPart[0]);
attributes = abi.encodePacked(attributes, singleAtt);
for (uint256 i = 1; i < traits.length; i++) {
(singleAtt, attPresent) = getAttributeBytes(i, tokenPart[i]);
if (attPresent) {
attributes = abi.encodePacked(attributes, ", ", singleAtt);
}
}
return string(attributes);
}
function setRevealedCollectionBaseURL(string memory _ipfsHash) onlyOwner public {
require(!frozen, 'Metadata has been frozen');
revealedCollectionBaseURL = string(abi.encodePacked('ipfs://', _ipfsHash, '/'));
}
function freezeMetadata() onlyOwner public {
frozen = true;
}
function tokenURI(uint256 _tokenId)
public
view
override
returns (string memory)
{
bytes memory tokenName = abi.encodePacked('Board ', Strings.toString(_tokenId));
bytes memory content = abi.encodePacked('{"name":"', tokenName, '"');
if (keccak256(abi.encodePacked(revealedCollectionBaseURL)) == keccak256(abi.encodePacked(''))) {
content = abi.encodePacked(content,
', ',
'"description": "An unrevealed Ape Harbour Surfboard"',
', ',
'"image": "', preRevealImageUrl, '"',
'}');
} else {
uint256[] memory tokenParts = decodeTokenId(randomSeed, _tokenId);
content = abi.encodePacked(content,
', ',
getAttributes(tokenParts),
'], ',
'"image": "', revealedCollectionBaseURL, Strings.toString(_tokenId), '.png"',
'}');
}
string memory result = string(
abi.encodePacked(
"data:application/json;base64,",
Base64.encode(content)
)
);
return result;
}
}
文件 3 的 19:ApeHarbourYachts.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "./base64.sol";
import "./ApeHarbourDinghies.sol";
contract ApeHarbourYachts is ERC721Enumerable, VRFConsumerBase, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
uint256 constant MAX_MINTABLE = 20;
uint256 constant public PRICE = 70000000000000000;
uint256 constant MAX_SUPPLY = 7777;
uint256 constant MAX_RANGE = 100;
uint256 constant MAX_SPEED = 99;
uint8 constant BITMASK = 255;
uint256 immutable startMinting;
string constant preRevealImageUrl = "ipfs://QmWt3pBeGmTEg5RU5j82XoEjGuaD767LfBFJ5g86iccCX7";
string public revealedCollectionBaseURL;
bool public frozen;
IERC721 private bayc;
IERC721 private bakc;
ApeHarbourDinghies private ahd;
uint8[][13] private cutoffs;
string[][13] private traitValues;
enum Keys { backgrounds, hulls_background, masts, sails, anchors, balloons, backprops, bananaboats, centerprops, carpets, chains, flags, cargos, range, speed }
string[] private traits = [ "Background", "Hull", "Mast", "Sail", "Anchor", "Equipment", "Equipment", "Sideboat", "Equipment", "Equipment", "Equipment", "Flag", "Equipment", "Range", "Speed" ];
mapping(uint256 => string) private names;
uint256 public randomSeed;
bytes32 internal keyHash;
uint256 internal chainLinkFee;
bytes32 public requestId;
event Mint(address indexed _to, uint256 _amount);
event NameChange(uint256 indexed _tokenId, string _name);
event Reveal(uint256 randomness);
event SetCollectionHash(string ipfsHash);
modifier onlyApeOwner() {
require(
bayc.balanceOf(msg.sender) > 0,
"ApeOwner: Caller is not an ape owner"
);
_;
}
modifier onlyDogOwner() {
require(
bakc.balanceOf(msg.sender) > 0,
"DogOwner: Caller is not a dog owner"
);
_;
}
constructor(
address _baycAddress,
address _bakcAddress,
address _ahdAddress,
address _linkAddress,
address _vrfCoordinatorAddress,
bytes32 _keyHash,
uint256 _chainLinkFee,
uint256 _startMinting
)
ERC721("Ape Harbour Yachts", "AHY")
VRFConsumerBase(_vrfCoordinatorAddress, _linkAddress)
{
keyHash = _keyHash;
chainLinkFee = _chainLinkFee;
bayc = IERC721(_baycAddress);
bakc = IERC721(_bakcAddress);
ahd = ApeHarbourDinghies(_ahdAddress);
startMinting = _startMinting;
cutoffs[uint256(Keys.backgrounds)] = [30,81,132,170,221,254];
cutoffs[uint256(Keys.hulls_background)] = [58,98,136,184,219,239,249,251];
cutoffs[uint256(Keys.masts)] = [25,204,255];
cutoffs[uint256(Keys.sails)] = [25,63,80,95,115,153,165,180,195,207,219,226,236,243,248];
cutoffs[uint256(Keys.anchors)] = [51,76,114,139,215,253];
cutoffs[uint256(Keys.balloons)] = [51,89,140,178,203,254];
cutoffs[uint256(Keys.backprops)] = [25,53,70,108,125,150,167,190,215,232,249];
cutoffs[uint256(Keys.bananaboats)] = [204,221,254];
cutoffs[uint256(Keys.centerprops)] = [25,48,71,88,100,117,132,144,154,166,189,206,223,235,247];
cutoffs[uint256(Keys.carpets)] = [230,255];
cutoffs[uint256(Keys.chains)] = [38,140,216,254];
cutoffs[uint256(Keys.flags)] = [25,55,85,100,125,140,155,172,189,212,235,250];
cutoffs[uint256(Keys.cargos)] = [40,55,80,103,126,143,155,180,203,220,243,250];
traitValues[uint256(Keys.backgrounds)] = ['Apelantic', 'Banana Bay', 'Everglades Ape Park', 'Ape Harbour', 'Ape Island', 'Apebiza'];
traitValues[uint256(Keys.hulls_background)] = ['Classic', 'Pink', 'Mahogany', 'Royal', 'Ocean Green', 'Robot', 'Gold', 'Diamond'];
traitValues[uint256(Keys.masts)] = ['null', 'Wood', 'Bone'];
traitValues[uint256(Keys.sails)] = ['null', 'Pennant Chain', 'Pink', 'Classic', 'Banana Pirates', 'Bulb Chain', 'Denim', 'White Stripes', 'Cheetah', 'USA', 'Fireflys', 'Trippy', 'Prison', 'Pizza', 'Gold'];
traitValues[uint256(Keys.anchors)] = ['null', 'Royal Gold', 'Pirate', 'Gold', 'Classic', 'Steel'];
traitValues[uint256(Keys.balloons)] = ['null', 'Banana Balloons', 'Colorful Balloons', 'Yellow Balloons', 'Pink Balloons', 'Ape Balloon'];
traitValues[uint256(Keys.backprops)] = ['null', 'Tiki Lamp', 'Water Slide', 'Jumping Board', 'Palm', 'Banana Tree', 'Curved Palm', 'Fish', 'Fishing Set', 'Lamp', 'Disco Ball'];
traitValues[uint256(Keys.bananaboats)] = ['null', 'Banana Boat', 'Flamingo'];
traitValues[uint256(Keys.centerprops)] = ['null', 'DJ Booth', 'Bar', 'Hammock', 'Old Couch', 'Fishbowl Lounge', 'Deewan Couch', 'Jacuzy', 'Bathtub', 'BBQ', 'Deckchair', 'Drums', 'Wine Lounge', 'Pizza Oven', 'Radio'];
traitValues[uint256(Keys.carpets)] = ['null', 'Carpet'];
traitValues[uint256(Keys.chains)] = ['null', 'Pennant Chain', 'Bulb Chain', 'Fireflys'];
traitValues[uint256(Keys.flags)] = ['null', 'Apes', 'Fomo', 'Lofi', 'Hodl', 'One Banana', 'Three Bananas', 'Doggo Red', 'Doggo Orange', 'Banana Pirates', 'Aped', 'Two Bananas'];
traitValues[uint256(Keys.cargos)] = ['null', 'Moneky Paw', 'Coconuts', 'Beer', 'Boxes of Oranges', 'Box of Oranges', 'Golden Banana', 'Whiskey Bottles', 'Banana Boxes', 'Banana Box', 'Coffee', 'Diamond Banana'];
}
function mint(address _ape, uint8 _amount)
public
payable
returns (uint256)
{
require(block.timestamp >= startMinting, 'Minting has not started');
require(_amount <= MAX_MINTABLE, "You can only mint up to 20 tokens at once");
require(msg.value >= PRICE * _amount, "Insufficient funds");
require(
_amount + totalSupply() <= MAX_SUPPLY,
"Request exeeds maximum supply"
);
if (block.timestamp < startMinting + 6 hours) {
require(bayc.balanceOf(msg.sender) > 0, "No ape, no yacht");
}
bool ownsDog = bakc.balanceOf(msg.sender) > 0;
bool ownsApe = bayc.balanceOf(msg.sender) > 0;
for (uint8 i = 0; i < _amount; i++) {
_tokenIds.increment();
uint256 newTokenId = _tokenIds.current();
_safeMint(_ape, newTokenId);
}
if (ownsApe && ownsDog && block.timestamp < startMinting + 12 hours) {
ahd.mint(_ape);
}
emit Mint(_ape, _amount);
return _tokenIds.current();
}
function setName(uint256 _tokenId, string memory _name)
public
returns (string memory)
{
require(ownerOf(_tokenId) == msg.sender, "Only boat owner can name it");
names[_tokenId] = _name;
emit NameChange(_tokenId, _name);
return _name;
}
function getName(uint256 _tokenId) public view returns (string memory) {
return names[_tokenId];
}
function withdraw() public onlyOwner {
uint256 balance = address(this).balance;
address payable receiver = payable(msg.sender);
receiver.transfer(balance);
}
function decodeTokenId(uint256 randomValue, uint256 _tokenId)
public
view
returns (uint256[] memory)
{
require(randomValue != 0, "Tokens have not been revealed yet");
uint256 tokenCode = uint256(
keccak256(abi.encode(randomValue, _tokenId))
);
uint8[15] memory shifts = [ 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112 ];
uint256[] memory tokenPart = new uint256[](shifts.length);
for (uint256 i = 0; i < shifts.length; i++) {
tokenPart[i] = (tokenCode >> shifts[i]) & BITMASK;
}
for (uint256 i = 0; i < tokenPart.length - 2; i++) {
uint256 currentIdx = 0;
for (uint256 j = 0; j < cutoffs[i].length; j++) {
if (tokenPart[i] < cutoffs[i][j]) {
currentIdx = j;
break;
}
}
tokenPart[i] = currentIdx;
}
bool noMast = (tokenPart[uint256(Keys.masts)] == 0);
if (noMast) {
tokenPart[uint256(Keys.sails)] = 0;
tokenPart[uint256(Keys.chains)] = 0;
tokenPart[uint256(Keys.flags)] = 0;
}
tokenPart[uint256(Keys.range)] =
(tokenPart[uint256(Keys.range)] % MAX_RANGE) +
1;
tokenPart[uint256(Keys.speed)] =
(tokenPart[uint256(Keys.speed)] % MAX_SPEED) +
1;
return tokenPart;
}
function reveal() public onlyOwner {
require(
LINK.balanceOf(address(this)) >= chainLinkFee,
"Not enough LINK - fill contract with faucet"
);
require(randomSeed == 0, 'randomSeed has already been set');
requestId = requestRandomness(keyHash, chainLinkFee);
}
function fulfillRandomness(bytes32 _requestId, uint256 _randomness)
internal
override
{
require(requestId == _requestId, "Wrong request Id");
require(randomSeed == 0, 'randomSeed has already been set');
randomSeed = _randomness;
emit Reveal(_randomness);
}
function getAttributeBytes(uint256 key, uint256 value)
private
view
returns (bytes memory, bool attributePresent)
{
if (
keccak256(abi.encodePacked(traitValues[key][value])) ==
keccak256(abi.encodePacked("null"))
) {
return ("", false);
}
return (
abi.encodePacked(
'{"trait_type": "',
traits[key],
'", "value": "',
traitValues[key][value],
'"}'
),
true
);
}
function getNumericAttributeBytes(uint256 _key, uint256 _value)
private
view
returns (bytes memory)
{
return (
abi.encodePacked(
'{"trait_type": "',
traits[_key],
'", "value": ',
Strings.toString(_value),
"}"
)
);
}
function getAttributes(uint256[] memory tokenPart)
private
view
returns (string memory) {
bytes memory attributes = '"attributes": [';
bytes memory singleAtt;
bool attPresent;
(singleAtt, attPresent) = getAttributeBytes(0, tokenPart[0]);
attributes = abi.encodePacked(attributes, singleAtt);
for (uint256 i = 1; i < traits.length - 2; i++) {
(singleAtt, attPresent) = getAttributeBytes(i, tokenPart[i]);
if (attPresent) {
attributes = abi.encodePacked(attributes, ", ", singleAtt);
}
}
attributes = abi.encodePacked(
attributes,
", ",
getNumericAttributeBytes(
uint256(Keys.speed),
tokenPart[uint256(Keys.speed)]
),
", ",
getNumericAttributeBytes(
uint256(Keys.range),
tokenPart[uint256(Keys.range)]
),
"]"
);
return string(attributes);
}
function setRevealedCollectionBaseURL(string memory _ipfsHash) onlyOwner public {
require(!frozen, 'Metadata has been frozen');
revealedCollectionBaseURL = string(abi.encodePacked('ipfs://', _ipfsHash, '/'));
emit SetCollectionHash(_ipfsHash);
}
function freezeMetadata() onlyOwner public {
frozen = true;
}
function tokenURI(uint256 _tokenId)
public
view
override
returns (string memory)
{
string memory tokenName = names[_tokenId];
if (keccak256(abi.encodePacked(tokenName)) == keccak256(abi.encodePacked(''))) {
tokenName = string(abi.encodePacked('Yacht ', Strings.toString(_tokenId)));
}
bytes memory content = abi.encodePacked('{"name":"', tokenName, '"');
if (keccak256(abi.encodePacked(revealedCollectionBaseURL)) == keccak256(abi.encodePacked(''))) {
content = abi.encodePacked(content,
', ',
'"description": "An unrevealed Ape Harbour Yacht"',
', ',
'"image": "', preRevealImageUrl, '"',
'}');
} else {
uint256[] memory tokenParts = decodeTokenId(randomSeed, _tokenId);
content = abi.encodePacked(content,
', ',
getAttributes(tokenParts),
', ',
'"image": "', revealedCollectionBaseURL, Strings.toString(_tokenId), '.png"',
'}');
}
string memory result = string(
abi.encodePacked(
"data:application/json;base64,",
Base64.encode(content)
)
);
return result;
}
}
文件 4 的 19: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;
}
}
文件 5 的 19:Counters.sol
pragma solidity ^0.8.0;
library Counters {
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
文件 6 的 19:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 7 的 19:ERC721.sol
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
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) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), 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 {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_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 {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
文件 8 的 19:ERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "./IERC721Enumerable.sol";
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
mapping(uint256 => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 => uint256) private _allTokensIndex;
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId;
_ownedTokensIndex[lastTokenId] = tokenIndex;
}
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
function _removeTokenFromAllTokensEnumeration(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();
}
}
文件 9 的 19:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 10 的 19:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
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
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
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 safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 11 的 19:IERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Enumerable is IERC721 {
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);
}
文件 12 的 19:IERC721Metadata.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 13 的 19:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 14 的 19:LinkTokenInterface.sol
pragma solidity ^0.8.0;
interface LinkTokenInterface {
function allowance(
address owner,
address spender
)
external
view
returns (
uint256 remaining
);
function approve(
address spender,
uint256 value
)
external
returns (
bool success
);
function balanceOf(
address owner
)
external
view
returns (
uint256 balance
);
function decimals()
external
view
returns (
uint8 decimalPlaces
);
function decreaseApproval(
address spender,
uint256 addedValue
)
external
returns (
bool success
);
function increaseApproval(
address spender,
uint256 subtractedValue
) external;
function name()
external
view
returns (
string memory tokenName
);
function symbol()
external
view
returns (
string memory tokenSymbol
);
function totalSupply()
external
view
returns (
uint256 totalTokensIssued
);
function transfer(
address to,
uint256 value
)
external
returns (
bool success
);
function transferAndCall(
address to,
uint256 value,
bytes calldata data
)
external
returns (
bool success
);
function transferFrom(
address from,
address to,
uint256 value
)
external
returns (
bool success
);
}
文件 15 的 19: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() {
_setOwner(_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 {
_setOwner(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 16 的 19:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
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);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
文件 17 的 19:VRFConsumerBase.sol
pragma solidity ^0.8.0;
import "./interfaces/LinkTokenInterface.sol";
import "./VRFRequestIDBase.sol";
abstract contract VRFConsumerBase is VRFRequestIDBase {
function fulfillRandomness(
bytes32 requestId,
uint256 randomness
)
internal
virtual;
uint256 constant private USER_SEED_PLACEHOLDER = 0;
function requestRandomness(
bytes32 _keyHash,
uint256 _fee
)
internal
returns (
bytes32 requestId
)
{
LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER));
uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]);
nonces[_keyHash] = nonces[_keyHash] + 1;
return makeRequestId(_keyHash, vRFSeed);
}
LinkTokenInterface immutable internal LINK;
address immutable private vrfCoordinator;
mapping(bytes32 => uint256 ) private nonces;
constructor(
address _vrfCoordinator,
address _link
) {
vrfCoordinator = _vrfCoordinator;
LINK = LinkTokenInterface(_link);
}
function rawFulfillRandomness(
bytes32 requestId,
uint256 randomness
)
external
{
require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill");
fulfillRandomness(requestId, randomness);
}
}
文件 18 的 19:VRFRequestIDBase.sol
pragma solidity ^0.8.0;
contract VRFRequestIDBase {
function makeVRFInputSeed(
bytes32 _keyHash,
uint256 _userSeed,
address _requester,
uint256 _nonce
)
internal
pure
returns (
uint256
)
{
return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce)));
}
function makeRequestId(
bytes32 _keyHash,
uint256 _vRFInputSeed
)
internal
pure
returns (
bytes32
)
{
return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed));
}
}
文件 19 的 19:base64.sol
pragma solidity ^0.8.0;
library Base64 {
string internal constant TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function encode(bytes memory data) internal pure returns (string memory) {
if (data.length == 0) return '';
string memory table = TABLE;
uint256 encodedLen = 4 * ((data.length + 2) / 3);
string memory result = new string(encodedLen + 32);
assembly {
mstore(result, encodedLen)
let tablePtr := add(table, 1)
let dataPtr := data
let endPtr := add(dataPtr, mload(data))
let resultPtr := add(result, 32)
for {} lt(dataPtr, endPtr) {}
{
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
resultPtr := add(resultPtr, 1)
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
resultPtr := add(resultPtr, 1)
mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F)))))
resultPtr := add(resultPtr, 1)
mstore(resultPtr, shl(248, mload(add(tablePtr, and( input, 0x3F)))))
resultPtr := add(resultPtr, 1)
}
switch mod(mload(data), 3)
case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
}
return result;
}
}
{
"compilationTarget": {
"contracts/ApeHarbourYachts.sol": "ApeHarbourYachts"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_baycAddress","type":"address"},{"internalType":"address","name":"_bakcAddress","type":"address"},{"internalType":"address","name":"_ahdAddress","type":"address"},{"internalType":"address","name":"_linkAddress","type":"address"},{"internalType":"address","name":"_vrfCoordinatorAddress","type":"address"},{"internalType":"bytes32","name":"_keyHash","type":"bytes32"},{"internalType":"uint256","name":"_chainLinkFee","type":"uint256"},{"internalType":"uint256","name":"_startMinting","type":"uint256"}],"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":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"_name","type":"string"}],"name":"NameChange","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":"uint256","name":"randomness","type":"uint256"}],"name":"Reveal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"ipfsHash","type":"string"}],"name":"SetCollectionHash","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":[],"name":"PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[{"internalType":"uint256","name":"randomValue","type":"uint256"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"decodeTokenId","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freezeMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"frozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"uint256","name":"_tokenId","type":"uint256"}],"name":"getName","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[{"internalType":"address","name":"_ape","type":"address"},{"internalType":"uint8","name":"_amount","type":"uint8"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","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":[],"name":"randomSeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealedCollectionBaseURL","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"string","name":"_name","type":"string"}],"name":"setName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_ipfsHash","type":"string"}],"name":"setRevealedCollectionBaseURL","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":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]