文件 1 的 27: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
) internal 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 的 27: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;
}
}
文件 3 的 27: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;
}
}
文件 4 的 27:ERC1155.sol
pragma solidity ^0.8.0;
import "./IERC1155.sol";
import "./IERC1155Receiver.sol";
import "./extensions/IERC1155MetadataURI.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
using Address for address;
mapping(uint256 => mapping(address => uint256)) private _balances;
mapping(address => mapping(address => bool)) private _operatorApprovals;
string private _uri;
constructor(string memory uri_) {
_setURI(uri_);
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC1155).interfaceId ||
interfaceId == type(IERC1155MetadataURI).interfaceId ||
super.supportsInterface(interfaceId);
}
function uri(uint256) public view virtual override returns (string memory) {
return _uri;
}
function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
require(account != address(0), "ERC1155: balance query for the zero address");
return _balances[id][account];
}
function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
public
view
virtual
override
returns (uint256[] memory)
{
require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
return batchBalances;
}
function setApprovalForAll(address operator, bool approved) public virtual override {
require(_msgSender() != operator, "ERC1155: setting approval status for self");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
return _operatorApprovals[account][operator];
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not owner nor approved"
);
_safeTransferFrom(from, to, id, amount, data);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: transfer caller is not owner nor approved"
);
_safeBatchTransferFrom(from, to, ids, amounts, data);
}
function _safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
emit TransferSingle(operator, from, to, id, amount);
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
}
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
}
emit TransferBatch(operator, from, to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
}
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
function _mint(
address account,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(account != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);
_balances[id][account] += amount;
emit TransferSingle(operator, address(0), account, id, amount);
_doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
}
function _mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; i++) {
_balances[ids[i]][to] += amounts[i];
}
emit TransferBatch(operator, address(0), to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
}
function _burn(
address account,
uint256 id,
uint256 amount
) internal virtual {
require(account != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
uint256 accountBalance = _balances[id][account];
require(accountBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][account] = accountBalance - amount;
}
emit TransferSingle(operator, account, address(0), id, amount);
}
function _burnBatch(
address account,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
require(account != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, account, address(0), ids, amounts, "");
for (uint256 i = 0; i < ids.length; i++) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 accountBalance = _balances[id][account];
require(accountBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][account] = accountBalance - amount;
}
}
emit TransferBatch(operator, account, address(0), ids, amounts);
}
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) private {
if (to.isContract()) {
try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) private {
if (to.isContract()) {
try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
bytes4 response
) {
if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](1);
array[0] = element;
return array;
}
}
文件 5 的 27:ERC1155Burnable.sol
pragma solidity ^0.8.0;
import "../ERC1155.sol";
abstract contract ERC1155Burnable is ERC1155 {
function burn(
address account,
uint256 id,
uint256 value
) public virtual {
require(
account == _msgSender() || isApprovedForAll(account, _msgSender()),
"ERC1155: caller is not owner nor approved"
);
_burn(account, id, value);
}
function burnBatch(
address account,
uint256[] memory ids,
uint256[] memory values
) public virtual {
require(
account == _msgSender() || isApprovedForAll(account, _msgSender()),
"ERC1155: caller is not owner nor approved"
);
_burnBatch(account, ids, values);
}
}
文件 6 的 27: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 的 27: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.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 的 27: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 的 27:ERC721Pausable.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "../../../security/Pausable.sol";
abstract contract ERC721Pausable is ERC721, Pausable {
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
require(!paused(), "ERC721Pausable: token transfer while paused");
}
}
文件 10 的 27:ERC721URIStorage.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
abstract contract ERC721URIStorage is ERC721 {
using Strings for uint256;
mapping(uint256 => string) private _tokenURIs;
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
if (bytes(base).length == 0) {
return _tokenURI;
}
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
return super.tokenURI(tokenId);
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}
文件 11 的 27:FluffyCore.sol
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract FluffyCore is VRFConsumerBase, Ownable {
using Counters for Counters.Counter;
Counters.Counter public _tokenIdCounter;
bytes32 internal keyHash;
uint256 internal fee;
uint256 public randomResult;
struct Token {
uint256 tokenId;
uint8 bg;
uint8 costume;
uint8 eyes;
uint8 head;
uint8 nose;
uint8 legendaryId;
bool isExists;
bool isLegendary;
}
event TokenInfoChanged(
Token token
);
mapping(uint256 => Token) tokens;
uint256[] tokenIds;
uint8 BGS = 9;
uint8 COSTUMES = 83;
uint8 EYES = 46;
uint8 HEADS = 87;
uint8 NOSES = 32;
constructor()
VRFConsumerBase(
0xf0d54349aDdcf704F77AE15b96510dEA15cb7952,
0x514910771AF9Ca656af840dff83E8264EcF986CA
)
{
keyHash = 0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445;
fee = 2 * 10 ** 18;
}
function getRandomNumber() onlyOwner public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
return requestRandomness(keyHash, fee);
}
function getToken(uint256 _id) public view returns (Token memory token) {
return tokens[_id];
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
randomResult = randomness;
}
function convert8 (uint256 _a) internal pure returns (uint8) {
return uint8(_a);
}
function setMetadata(uint256 tokenId) internal {
uint256 random = uint256(keccak256(abi.encode(tokenId,
randomResult,
msg.sender,
block.number,
block.timestamp,
blockhash(block.number - 1))));
uint8 bg = convert8(random % BGS) + 1;
uint8 costume = convert8(random % COSTUMES) + 1;
uint8 eye = convert8(random % EYES) + 1;
uint8 head = convert8(random % HEADS) + 1;
uint8 nose = convert8(random % NOSES) + 1;
Token memory _token = Token(tokenId, bg, costume, eye, head, nose, 0, true, false);
tokens[tokenId] = _token;
emit TokenInfoChanged(_token);
}
}
文件 12 的 27:FluffyPolarBears.sol
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./FluffyCore.sol";
import "./Library.sol";
contract FluffyPolarBears is ERC721, ERC721Enumerable, ERC721URIStorage, Pausable, Ownable, FluffyCore, IERC721Receiver {
using Counters for Counters.Counter;
address public constant CONTRACT_DEVELOPER_ADDRESS = 0x16eFE37c0c557D4B1D8EB76d11E13616d2b52eAF;
address public constant ARTIST_ADDRESS = 0xAD4dcA5A70b4b2467301879B83484dFB550698c6;
address public constant POOL_ADDRESS = 0x084C29a614e0F40a01dD028E1eE2Fb5046585316;
address public constant WEB_DEVELOPER_ADDRESS = 0x09D5b72677F42caa0Caa68519CdFC679cc6c24C0;
address public constant COMMUNITY_MANAGER_ADDRESS = 0xc1b17d7Cb355FE015E29C3575B12DF722D764959;
address public constant SHAREHOLDER_ADDRESS = 0x9E650ef13d0893A8729B3685285Fbc918b4850C6;
address public constant CHARITY_ADDRESS = 0x336353B2BfeFeB6d4241bC3E2009eC4D18cBdD74;
uint public CONTRACT_DEVELOPER_FEE = 3;
uint public ARTIST_FEE = 25;
uint public POOL_FEE = 12;
uint public WEB_DEVELOPER_FEE = 7;
uint public COMMUNITY_MANAGER_FEE = 24;
uint public SHAREHOLDER_FEE = 24;
uint public CHARITY_FEE = 5;
uint constant SHARE_SUM = 100;
uint constant TOTAL_SUPPLY = 9999;
uint256 public REROLL_PRICE = 0.033 ether;
address private _ERC1155BURNADDRESS;
bool public isMintingActive = false;
bool public isRerollActive = false;
string IMAGE_URL;
string[][100] attributeIdsToNames;
string[] attributeCategoryIdToName = ["Background", "Costume", "Eye", "Head", "Nose"];
string[] legendaryIdToName = ["Vanilla Bear", "Golden Bear", "Puzzled Bear", "3D Bear", "Polar Lisa", "The Scream", "Vincent Polar Gogh", "Great Wave", "Bearida Kahlo", "Pablo Polarsco", "Bearet Mondriaan", "Salvador Fluffy", "Gm Bear", "Shakespeare", "Amabearus Mozart", "Crossword Fluffy", "Frankicetein", "Crazy Wizard", "Count Bearacula", "Fluffy Witch", "Zombear", "Evil Fluffy Robot", "Mummy Bear", "Cave Bear", "Fluffy Unicorn", "Fluffy Cowboy", "Astronaut Bear", "Desert Bear", "Bipolar", "Super Fluffy", "Fluffy Punk", "Purple Punk", "Ninja Bear", "Fluffy Pilot", "Pirate Captain", "Exhausted Bear", "Fluffy Painter", "Left Looking Bear", "Pink Bear", "Fluffy Bandit", "Ducky", "Chick", "Office Bear", "Fluffy Warrior", "Mcbear's", "Ethbeary", "Hodl Bear", "Frozen Fluffy", "Beauty Bear", "Intern Viking", "Shiny", "Tattooed Bear", "Silhouette Bear", "Ski Bear", "Fluffy Neo", "Robear Hood", "Bearlie Chaplin", "Obear Wan", "Bearlock Holmes", "Sad Sailor", "Fluffy Captain", "Miss Fluffy Sunshine", "Chief Redbird", "Diver Bear", "Rainbow Bear", "Albear Icetein", "Galileo Fluffio", "Iceac Newton", "Niclaw Tesla", "Fluffy Marie Curie", "Fluffy Santa", "Fluffy Holiday", "Stormy", "Narcissist Bear", "Seally Bear", "Fluffy Knight", "Princess Aurora", "Karate Bear", "Fluffy Lighthouse", "Party Bear", "Rainy", "Igloo Bear", "Fluffy Panda", "Fluffy Fall", "Pizza Chef", "Stoned Bear", "Sharky", "The Goat", "Fluffy Pharaoh", "Art Bear", "Manga Bear", "Fluffy Hipster", "Lucky", "Bearly Bear", "The Ice King", "Yeti", "Coder Bear", "Fluffy Arctic Wolf", "Baby Bear"];
string public metadataProvenance;
constructor(address SketchAddress) ERC721("Fluffy Polar Bears", "FPB") {
_ERC1155BURNADDRESS = SketchAddress;
attributeIdsToNames[0] = ["Pink", "Orange", "Blue", "Purple", "Yellow", "Fuchsia", "Green", "Rose", "Electric Pink", "Light Green"];
attributeIdsToNames[1] = ["Yellow T-shirt", "Casual T-shirt", "Red Shirt", "Purple Polo", "Party Dress", "Purple Hoodie", "Purple Waistcoat", "Blue Scarf", "Pirate", "Blue Shirt&Tie", "White Shirt&Tie", "Suit", "Yellow Puffer", "Pink Scarf", "Pink Dress", "Caveman", "Karate", "Rock T-shirt", "Punk Jacket", "Explorer", "Trenchcoat", "Hawaiian Shirt", "Fur Coat", "Viking", "Yellow Sweater", "Red Sweater", "Warrior", "Wizard", "Sailor", "Cowboy", "Pilot", "Pink Blouse", "Painter", "Princess", "Craftsman", "Chef", "Aristocrat", "King", "Clown", "Pharaoh", "Red Hoodie", "Hodl Hoodie", "Captain", "Aviator", "Admiral", "Blue Bathrobe", "Pink Towel", "Denim Jacket", "Black Suit", "Plaid Shirt", "Poncho", "Prisoner", "Bikini", "Yellow Raincoat", "Hawaaian", "ETH Sweater", "ETH Hoodie", "Gold Chain", "Straitjacket", "FPB Chain", "Ski Coat", "Snow", "FPB T-shirt", "Santa", "Life Jacket", "Knight", "Legionnaire", "Roman", "Gold Medal", "Robin", "Tribal", "Gardener", "Vampire", "Super Bear", "Astronaut", "Hipster", "Tattoo", "Xmas Lights", "Jersey", "Snow Sweatshirt", "Jedi", "Detective", "Polka Dot Bikini", "Witch"];
attributeIdsToNames[2] = ["Straight", "Left", "Calm", "Thinker", "Angry", "Wobbly", "Embarassed", "Sad", "Tired", "Innocent", "Heart Glasses", "Cool", "Dizzy", "Sunglasses", "Blue Glasses", "Retro Glasses", "Pirate", "In Love", "3D", "Sneaky", "Triple", "Confused", "Winky", "Cunning", "Flower Glasses", "Crossed", "Crying", "Punk", "Starry", "Thug Life", "Ski Goggles", "Condescending", "Super Hero", "Cute", "Furious", "Cucumber", "Purple Glasses", "Manga Eyes", "Steampunk", "Red Glasses", "Hipster Glasses", "Green Laser", "Red Laser", "Dreamer", "Fragile", "Lol", "Shiny", "Masquerade"];
attributeIdsToNames[3] = ["Santa", "Fish", "Purple Beanie", "Frog Beanie", "Wizard", "Crab", "Pirate", "Viking", "Pink Hat", "Fedora Hat", "Punk", "Purple Hair", "Blue Cap", "Navy Cap", "Admiral", "Paper Boat", "Bandana", "Party Hat", "Lighthouse", "Reverse Cap", "Graduated", "Top Hat", "Emo", "Blonde", "Karate Bandana", "Punk Cap", "Explorer", "Rice Hat", "Sailor", "Seagull", "Cowboy", "Devil", "Frog", "Motorbike Helmet", "Pilot", "Mushroom", "Manga Hair", "Painter", "Princess", "Safety Helmet", "Chef", "Wig", "Gold Crown", "Clown", "Polar Bear Beanie", "Red Bow", "Pharaoh", "Igloo", "Captain", "Aviator", "Towel", "Duck", "Hodl Cap", "Ice Crown", "Caveman", "Sombrero", "Prisoner", "Ice-Cream", "Unicorn", "Coffee", "Straw Hat", "Rain Hat", "Bowler Hat", "Flowers", "Toilet Paper", "Funnel", "FPB Cap", "Pompom", "Propeller Hat", "Knight", "Legionnaire", "Civic Crown", "Cooking Pot", "Shark", "Robin", "Feather Headband", "Vampire", "Hero", "Hipster", "Basketball", "Chicken", "Traffic Cone", "Curly", "Witch", "Detective", "Pony Tail", "McBear", "Headphones"];
attributeIdsToNames[4] = ["Neutral", "Smiling", "Laughing", "Sweet", "Sad", "Tongue Out", "Teeth", "Crooked Teeth", "Smirky", "Playful", "Doubt", "Cool", "Fickle", "Bucktoothed", "Two Teeth", "Mmm", "Puzzled", "Lipstick", "Exhausted", "Whistling", "Goofy", "Frozen", "Romantic", "Vampire", "Content", "Manga Mouth", "Disco", "Moustache", "Runny Nose", "Crazy", "Satisfied", "Hodl"];
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) {
return interfaceId == type(IERC721Receiver).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
}
function safeMint() public onlyOwner {
uint256 current = _tokenIdCounter.current();
require(current < TOTAL_SUPPLY, "Purchase would exceed max tokens");
_safeMint(msg.sender, current);
super.setMetadata(current);
tokenIds.push(current);
_tokenIdCounter.increment();
}
function updateERC1155BurnAddress(address erc1155BurnAddress) external onlyOwner {
_ERC1155BURNADDRESS = erc1155BurnAddress;
}
function startMintingProcess() public onlyOwner {
isMintingActive = true;
}
function pauseMintingProcess() public onlyOwner {
isMintingActive = false;
}
function startRerollProcess() public onlyOwner {
isRerollActive = true;
}
function pauseRerollProcess() public onlyOwner {
isRerollActive = false;
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function reroll(uint256 tokenId) external payable {
require(isRerollActive, "Reroll not active");
require(msg.sender == ownerOf(tokenId), "Only owner can reroll.");
require(REROLL_PRICE <= msg.value, "Ether value sent is not correct");
super.setMetadata(tokenId);
}
function setImageUrl(string memory _imageUrl) onlyOwner public {
IMAGE_URL = _imageUrl;
}
function generateMetadata(uint256 _tokenId) public view returns (string memory) {
string memory metadataString;
Token memory token = tokens[_tokenId];
if (token.isLegendary) {
metadataString = string(
abi.encodePacked(
metadataString,
'{"trait_type":"Legendary","value":"',
legendaryIdToName[token.legendaryId],
'"}'
)
);
} else {
uint8[5] memory attributes = [token.bg, token.costume, token.eyes, token.head, token.nose];
for (uint8 i = 0; i < attributes.length; i++) {
uint256 value = attributes[i];
metadataString = string(
abi.encodePacked(
metadataString,
'{"trait_type":"',
attributeCategoryIdToName[i],
'","value":"',
attributeIdsToNames[i][value - 1],
'"}'
)
);
if (i != attributes.length - 1) metadataString = string(abi.encodePacked(metadataString, ","));
}
}
return string(abi.encodePacked("[", metadataString, "]"));
}
function tokenURI(uint256 _tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
require(tokens[_tokenId].isExists);
return
string(
abi.encodePacked(
"data:application/json;base64,",
Library.encode(
bytes(
string(
abi.encodePacked(
'{"name": "Fluffy Polar Bears #',
Library.toString(_tokenId),
'", "description": "After a very harsh ice age, polar bears were the only species that survived. Now, they need to explore the world, create inventions and a world of polar bears - cold, funky and definitely interesting! Fluffy Polar Bears are a collection of 9,999 randomly and fully On-Chain generated NFTs that exist on the Ethereum Blockchain.", "image": "',
IMAGE_URL,
Library.toString(_tokenId),
'","external_url":"https://polarbearsnft.com/token/',
Library.toString(_tokenId),
'","attributes":',
generateMetadata(_tokenId),
"}"
)
)
)
)
)
);
}
function tokensOfOwner(address _owner) external view returns(uint256[] memory ) {
uint256 tokenCount = balanceOf(_owner);
if (tokenCount == 0) {
return new uint256[](0);
} else {
uint256[] memory result = new uint256[](tokenCount);
uint256 index;
for (index = 0; index < tokenCount; index++) {
result[index] = tokenOfOwnerByIndex(_owner, index);
}
return result;
}
}
function onERC721Received(address, address from, uint256 id, bytes calldata data) public virtual override returns (bytes4) {
require(msg.sender == _ERC1155BURNADDRESS && id == 1, "Invalid NFT");
require(isMintingActive, "Minting is not active yet.");
uint256 current = _tokenIdCounter.current();
require(current + 1 <= TOTAL_SUPPLY, "Purchase would exceed max tokens");
try ERC1155Burnable(msg.sender).burn(address(this), id, 1) {
} catch Error(string memory reason) {
emit ErrorHandled(reason);
revert("Burn failure");
} catch (bytes memory lowLevelData) {
emit ErrorNotHandled(lowLevelData);
revert("Burn failure");
}
for (uint i = 0; i < 1; i++) {
uint256 current = _tokenIdCounter.current();
require(current < TOTAL_SUPPLY, "Purchase would exceed max tokens");
_safeMint(from, current);
super.setMetadata(current);
tokenIds.push(current);
_tokenIdCounter.increment();
}
return this.onERC721Received.selector;
}
function onERC1155Received(
address,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns(bytes4) {
_onERC1155Received(from, id, value, data);
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns(bytes4) {
require(ids.length == values.length, "Invalid input");
for (uint i = 0; i < ids.length; i++) {
_onERC1155Received(from, ids[i], values[i], data);
}
return this.onERC1155BatchReceived.selector;
}
event ErrorHandled(string reason);
event ErrorNotHandled(bytes reason);
function _onERC1155Received(address from, uint256 id, uint256 value, bytes calldata data) private {
require(msg.sender == _ERC1155BURNADDRESS && id == 1, "Invalid NFT");
require(isMintingActive, "Minting is not active yet.");
uint256 current = _tokenIdCounter.current();
require(current + value <= TOTAL_SUPPLY, "Purchase would exceed max tokens");
try ERC1155Burnable(msg.sender).burn(address(this), id, value) {
} catch Error(string memory reason) {
emit ErrorHandled(reason);
revert("Burn failure");
} catch (bytes memory lowLevelData) {
emit ErrorNotHandled(lowLevelData);
revert("Burn failure");
}
for (uint i = 0; i < value; i++) {
uint256 current = _tokenIdCounter.current();
require(current < TOTAL_SUPPLY, "Purchase would exceed max tokens");
_safeMint(from, current);
super.setMetadata(current);
tokenIds.push(current);
_tokenIdCounter.increment();
}
}
mapping (address => bool) isBlacklisted;
function addToBlacklist(address[] memory _addresses, bool _value) onlyOwner public {
for (uint i = 0; i < _addresses.length; i++) {
isBlacklisted[_addresses[i]] = _value;
}
}
function setTokenAsLegendary (uint256 tokenId, uint8 id, uint16[] memory tokenIdMap, uint16 tokenCount) private {
tokenId = tokenIdMap[tokenId];
if (tokens[tokenId].isLegendary) {
uint256 random = uint256(keccak256(abi.encode(tokenId, randomResult))) % tokenCount;
setTokenAsLegendary(random, id, tokenIdMap, tokenCount);
} else {
Token memory _token = tokens[tokenId];
_token.isLegendary = true;
_token.legendaryId = id;
tokens[tokenId] = _token;
emit TokenInfoChanged(_token);
}
}
function _setLegendaries(uint256[] memory _legendaries, uint16[] memory tokenIdMap, uint16 tokenCount) private {
uint256 len = _legendaries.length;
for (uint8 i = 0; i < len; i++) {
uint256 token = _legendaries[i];
setTokenAsLegendary(token, i, tokenIdMap, tokenCount);
}
}
function setLegendaries() public onlyOwner {
uint currentSupply = _tokenIdCounter.current();
uint16 cleanedTokenIdCounter = 0;
uint16[] memory cleanedTokensToActualTokenIds = new uint16[](currentSupply);
for (uint16 tokenId = 0; tokenId < currentSupply; tokenId++) {
address owner = this.ownerOf(tokenId);
if(isBlacklisted[owner] != true) {
cleanedTokensToActualTokenIds[cleanedTokenIdCounter] = tokenId;
cleanedTokenIdCounter += 1;
}
}
uint256[] memory luckyTokens = expand(randomResult, 99, cleanedTokenIdCounter);
_setLegendaries(luckyTokens, cleanedTokensToActualTokenIds, cleanedTokenIdCounter);
}
function expand(uint256 randomValue, uint256 n, uint256 tokenCount) private pure returns (uint256[] memory expandedValues) {
expandedValues = new uint256[](n);
for (uint256 i = 0; i < n; i++) {
expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i))) % tokenCount;
}
return expandedValues;
}
function setMetadataProvenance(string memory _hash) onlyOwner public {
metadataProvenance = _hash;
}
function withdrawAll() public payable onlyOwner {
uint256 balance = address(this).balance;
uint toContractDeveloper = (balance * CONTRACT_DEVELOPER_FEE) / SHARE_SUM;
uint toArtist = (balance * ARTIST_FEE) / SHARE_SUM;
uint toWebDeveloper = (balance * WEB_DEVELOPER_FEE) / SHARE_SUM;
uint toCommmunityManager = (balance * COMMUNITY_MANAGER_FEE) / SHARE_SUM;
uint toShareholder = (balance * SHAREHOLDER_FEE) / SHARE_SUM;
uint toCharity = (balance * CHARITY_FEE) / SHARE_SUM;
uint toPool = (balance * POOL_FEE) / SHARE_SUM;
payable(CONTRACT_DEVELOPER_ADDRESS).transfer(toContractDeveloper);
payable(ARTIST_ADDRESS).transfer(toArtist);
payable(WEB_DEVELOPER_ADDRESS).transfer(toWebDeveloper);
payable(COMMUNITY_MANAGER_ADDRESS).transfer(toCommmunityManager);
payable(SHAREHOLDER_ADDRESS).transfer(toShareholder);
payable(CHARITY_ADDRESS).transfer(toCharity);
payable(POOL_ADDRESS).transfer(toPool);
uint toOwner = balance - (toContractDeveloper + toArtist + toWebDeveloper + toCommmunityManager + toShareholder + toCharity + toPool);
payable(msg.sender).transfer(toOwner);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal whenNotPaused override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
}
文件 13 的 27:IERC1155.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
文件 14 的 27:IERC1155MetadataURI.sol
pragma solidity ^0.8.0;
import "../IERC1155.sol";
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
文件 15 的 27:IERC1155Receiver.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 16 的 27:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 17 的 27: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;
}
文件 18 的 27: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);
}
文件 19 的 27: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);
}
文件 20 的 27:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 21 的 27:Library.sol
pragma solidity ^0.8.2;
library Library {
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;
}
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 parseInt(string memory _a)
internal
pure
returns (uint8 _parsedInt)
{
bytes memory bresult = bytes(_a);
uint8 mint = 0;
for (uint8 i = 0; i < bresult.length; i++) {
if (
(uint8(uint8(bresult[i])) >= 48) &&
(uint8(uint8(bresult[i])) <= 57)
) {
mint *= 10;
mint += uint8(bresult[i]) - 48;
}
}
return mint;
}
function substring(
string memory str,
uint256 startIndex,
uint256 endIndex
) internal pure returns (string memory) {
bytes memory strBytes = bytes(str);
bytes memory result = new bytes(endIndex - startIndex);
for (uint256 i = startIndex; i < endIndex; i++) {
result[i - startIndex] = strBytes[i];
}
return string(result);
}
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
}
文件 22 的 27: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
);
}
文件 23 的 27: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);
}
}
文件 24 的 27: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());
}
}
文件 25 的 27: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);
}
}
文件 26 的 27: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);
}
}
文件 27 的 27: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));
}
}
{
"compilationTarget": {
"FluffyPolarBears.sol": "FluffyPolarBears"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"SketchAddress","type":"address"}],"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":"reason","type":"string"}],"name":"ErrorHandled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"reason","type":"bytes"}],"name":"ErrorNotHandled","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":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"bg","type":"uint8"},{"internalType":"uint8","name":"costume","type":"uint8"},{"internalType":"uint8","name":"eyes","type":"uint8"},{"internalType":"uint8","name":"head","type":"uint8"},{"internalType":"uint8","name":"nose","type":"uint8"},{"internalType":"uint8","name":"legendaryId","type":"uint8"},{"internalType":"bool","name":"isExists","type":"bool"},{"internalType":"bool","name":"isLegendary","type":"bool"}],"indexed":false,"internalType":"struct FluffyCore.Token","name":"token","type":"tuple"}],"name":"TokenInfoChanged","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"},{"inputs":[],"name":"ARTIST_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ARTIST_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHARITY_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHARITY_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COMMUNITY_MANAGER_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COMMUNITY_MANAGER_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTRACT_DEVELOPER_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTRACT_DEVELOPER_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REROLL_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHAREHOLDER_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHAREHOLDER_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEB_DEVELOPER_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEB_DEVELOPER_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_tokenIdCounter","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"addToBlacklist","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":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"generateMetadata","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":[],"name":"getRandomNumber","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getToken","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"bg","type":"uint8"},{"internalType":"uint8","name":"costume","type":"uint8"},{"internalType":"uint8","name":"eyes","type":"uint8"},{"internalType":"uint8","name":"head","type":"uint8"},{"internalType":"uint8","name":"nose","type":"uint8"},{"internalType":"uint8","name":"legendaryId","type":"uint8"},{"internalType":"bool","name":"isExists","type":"bool"},{"internalType":"bool","name":"isLegendary","type":"bool"}],"internalType":"struct FluffyCore.Token","name":"token","type":"tuple"}],"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":"isMintingActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRerollActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataProvenance","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"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":"pauseMintingProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseRerollProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"randomResult","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":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"reroll","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"safeMint","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":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_imageUrl","type":"string"}],"name":"setImageUrl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setLegendaries","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_hash","type":"string"}],"name":"setMetadataProvenance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startMintingProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startRerollProcess","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":[{"internalType":"address","name":"_owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"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":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc1155BurnAddress","type":"address"}],"name":"updateERC1155BurnAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"payable","type":"function"}]