编译器
0.8.13+commit.abaa5c0e
文件 1 的 16:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 16: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 的 16:ContractDataStorage.sol
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/access/Ownable.sol";
contract ContractDataStorage is Ownable {
struct ContractData {
address rawContract;
uint128 size;
uint128 offset;
}
struct ContractDataPages {
uint256 maxPageNumber;
bool exists;
mapping (uint256 => ContractData) pages;
}
mapping (string => ContractDataPages) internal _contractDataPages;
mapping (address => bool) internal _controllers;
constructor() {
updateController(_msgSender(), true);
}
function updateController(address _controller, bool _status) public onlyOwner {
_controllers[_controller] = _status;
}
modifier onlyController() {
require(_controllers[_msgSender()], "ContractDataStorage: caller is not a controller");
_;
}
function saveData(
string memory _key,
uint128 _pageNumber,
bytes memory _b
)
public
onlyController
{
require(_b.length < 24576, "SvgStorage: Exceeded 24,576 bytes max contract size");
bytes memory init = hex"610000_600e_6000_39_610000_6000_f3";
bytes1 size1 = bytes1(uint8(_b.length));
bytes1 size2 = bytes1(uint8(_b.length >> 8));
init[2] = size1;
init[1] = size2;
init[10] = size1;
init[9] = size2;
bytes memory code = abi.encodePacked(init, _b);
address dataContract;
assembly {
dataContract := create(0, add(code, 32), mload(code))
if eq(dataContract, 0) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
saveDataForDeployedContract(
_key,
_pageNumber,
dataContract,
uint128(_b.length),
0
);
}
function saveDataForDeployedContract(
string memory _key,
uint256 _pageNumber,
address dataContract,
uint128 _size,
uint128 _offset
)
public
onlyController
{
ContractDataPages storage _cdPages = _contractDataPages[_key];
if (_cdPages.maxPageNumber < _pageNumber) {
_cdPages.maxPageNumber = _pageNumber;
}
_cdPages.exists = true;
_cdPages.pages[_pageNumber] = ContractData(
dataContract,
_size,
_offset
);
}
function revokeContractData(
string memory _key
)
public
onlyController
{
delete _contractDataPages[_key];
}
function getSizeOfPages(
string memory _key
)
public
view
returns (uint256)
{
ContractDataPages storage _cdPages = _contractDataPages[_key];
uint256 totalSize;
for (uint256 idx; idx <= _cdPages.maxPageNumber; idx++) {
totalSize += _cdPages.pages[idx].size;
}
return totalSize;
}
function getData(
string memory _key
)
public
view
returns (bytes memory)
{
uint256 totalSize = getSizeOfPages(_key);
bytes memory _totalData = new bytes(totalSize);
ContractDataPages storage _cdPages = _contractDataPages[_key];
uint256 currentPointer = 32;
for (uint256 idx; idx <= _cdPages.maxPageNumber; idx++) {
ContractData storage dataPage = _cdPages.pages[idx];
address dataContract = dataPage.rawContract;
uint256 size = uint256(dataPage.size);
uint256 offset = uint256(dataPage.offset);
assembly {
extcodecopy(dataContract, add(_totalData, currentPointer), offset, size)
}
currentPointer += size;
}
return _totalData;
}
function getDataForAll(string[] memory _keys)
public
view
returns (bytes memory)
{
uint256 totalSize;
for (uint256 idx; idx < _keys.length; idx++) {
totalSize += getSizeOfPages(_keys[idx]);
}
bytes memory _totalData = new bytes(totalSize);
uint256 currentPointer = 32;
for (uint256 idx; idx < _keys.length; idx++) {
ContractDataPages storage _cdPages = _contractDataPages[_keys[idx]];
for (uint256 innerIdx; innerIdx <= _cdPages.maxPageNumber; innerIdx++) {
ContractData storage dataPage = _cdPages.pages[innerIdx];
address dataContract = dataPage.rawContract;
uint256 size = uint256(dataPage.size);
uint256 offset = uint256(dataPage.offset);
assembly {
extcodecopy(dataContract, add(_totalData, currentPointer), offset, size)
}
currentPointer += size;
}
}
return _totalData;
}
function hasKey(string memory _key)
public
view
returns (bool)
{
return _contractDataPages[_key].exists;
}
}
文件 4 的 16: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;
}
}
文件 5 的 16: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: address zero is not a valid owner");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0), "ERC721: invalid token ID");
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) {
_requireMinted(tokenId);
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 token owner or approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_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: caller is not token owner or 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: caller is not token owner or 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 _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == 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, 1);
require(!_exists(tokenId), "ERC721: token already minted");
unchecked {
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
owner = ERC721.ownerOf(tokenId);
delete _tokenApprovals[tokenId];
unchecked {
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
delete _tokenApprovals[tokenId];
unchecked {
_balances[from] -= 1;
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
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,
uint256 batchSize
) internal virtual {
if (batchSize > 1) {
if (from != address(0)) {
_balances[from] -= batchSize;
}
if (to != address(0)) {
_balances[to] += batchSize;
}
}
}
function _afterTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual {}
}
文件 6 的 16:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 7 的 16: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,
bytes calldata data
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 8 的 16: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);
}
文件 9 的 16:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 10 的 16:IOperatorFilterRegistry.sol
pragma solidity ^0.8.13;
interface IOperatorFilterRegistry {
function isOperatorAllowed(address registrant, address operator) external view returns (bool);
function register(address registrant) external;
function registerAndSubscribe(address registrant, address subscription) external;
function registerAndCopyEntries(address registrant, address registrantToCopy) external;
function unregister(address addr) external;
function updateOperator(address registrant, address operator, bool filtered) external;
function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
function subscribe(address registrant, address registrantToSubscribe) external;
function unsubscribe(address registrant, bool copyExistingEntries) external;
function subscriptionOf(address addr) external returns (address registrant);
function subscribers(address registrant) external returns (address[] memory);
function subscriberAt(address registrant, uint256 index) external returns (address);
function copyEntriesOf(address registrant, address registrantToCopy) external;
function isOperatorFiltered(address registrant, address operator) external returns (bool);
function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
function filteredOperators(address addr) external returns (address[] memory);
function filteredCodeHashes(address addr) external returns (bytes32[] memory);
function filteredOperatorAt(address registrant, uint256 index) external returns (address);
function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
function isRegistered(address addr) external returns (bool);
function codeHashOf(address addr) external returns (bytes32);
}
文件 11 的 16:JosieNftBox.sol
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./JosieNftBoxMetadata.sol";
import "./WithOperatorFilter.sol";
contract JosieNftBox is ERC721, Ownable, WithOperatorFilter {
JosieNftBoxMetadata public metadataContract;
uint256 public currentTokenSupply;
uint256 public START_TIMESTAMP;
uint256 constant public ROLLS_PER_DAY = 5;
uint256 constant SECONDS_BETWEEN_ROLLS = 86400;
uint256 public tokensRolled;
mapping(uint256 => uint256) public revealedTokenVariant;
uint256 constant NUM_REVEALED_VARIANTS = 12;
uint256 internal _leftToRoll;
mapping(uint256 => uint256) internal _idSwaps;
mapping(uint256 => uint256) internal _prizeDrawnSwaps;
uint256 internal _currentPrng;
address public royaltyRecipient;
uint256 public royaltyBps = 1000;
string[15] PRIZES = [
"Filter - #17/100",
"Looks like you've had a bit too much to think - #17/21",
"Looks like you've had a bit too much to think - #15/21",
"This is America - #57/70",
"This is America - #60/70",
"CyberBrokers - Phillip Whitlock #8128",
"CyberBrokers - Sonia of the Twilight #8018",
"CyberBrokers - Enya the Sickly #5513",
"CyberBrokers - Soppy Vader #3141",
"CyberBrokers - Everly of Uncouth #7612",
"CyberBrokers - Tainted Stoyer #6123",
"CyberBrokers - Zion Lackadaisical #423",
"CyberBrokers - Nolan from Pretty #2274",
"CyberBrokers - Macy Slurry #8905",
"CyberBrokers - Deja of Monroe #5876"
];
event RevealToken(uint256 tokenId, string variant, string prize);
constructor(
address _metadataContractAddress
)
ERC721("Don't Feed the Pigeons", 'PIGEONS')
{
setMetadataContract(_metadataContractAddress);
START_TIMESTAMP = block.timestamp;
royaltyRecipient = msg.sender;
}
function setIsOperatorFilterEnabled(bool _setting) external onlyOwner {
isOperatorFilterEnabled = _setting;
}
function setMetadataContract(address _metadataContractAddress) public onlyOwner {
metadataContract = JosieNftBoxMetadata(_metadataContractAddress);
}
function setRoyaltyRecipient(address _recipient) external onlyOwner {
royaltyRecipient = _recipient;
}
function setRoyaltyBps(uint256 _bps) external onlyOwner {
require(_bps < 10000, "Royalty basis points must be under 10,000 (100%)");
royaltyBps = _bps;
}
function airdrop(
address[] calldata addresses
)
external
onlyOwner
{
require(addresses.length > 0, "Invalid addresses lengths");
uint256 currentToken = totalSupply();
for (uint256 idx; idx < addresses.length; idx++) {
require(currentToken < 500, "At max supply.");
_safeMint(
addresses[idx],
currentToken + idx + 1
);
}
currentTokenSupply = currentToken + addresses.length;
}
function rollReveals()
external
onlyOwner
{
require(tokensRolled < totalSupply(), "Rolled all tokens");
uint256 tokensToRoll = numToRoll();
require(tokensToRoll > 0, "No tokens to roll yet");
tokensToRoll = tokensToRoll > 5 ? 5 : tokensToRoll;
uint256 leftToRoll = totalSupply() - tokensRolled;
uint256 currentPrng = _currentPrng;
uint256 _tokenId;
uint256 _prizeIndex;
for (uint256 idx; idx < tokensToRoll; idx++) {
currentPrng = _prng(currentPrng, leftToRoll, 1);
_tokenId = _pullRandomUniqueIndex(currentPrng, leftToRoll, _idSwaps);
revealedTokenVariant[_tokenId] = 1 + (_prng(currentPrng, leftToRoll, 42) % (NUM_REVEALED_VARIANTS));
_prizeIndex = (leftToRoll == 1) ? 500 : (_pullRandomUniqueIndex(_prng(currentPrng, leftToRoll, 69), leftToRoll - 1, _prizeDrawnSwaps) - 1);
leftToRoll--;
_revealToken(_tokenId, _prizeIndex);
}
_currentPrng = currentPrng;
tokensRolled += tokensToRoll;
}
function numToRoll()
public
view
returns (
uint256
)
{
uint256 tokensToRoll = ((((block.timestamp - START_TIMESTAMP) / SECONDS_BETWEEN_ROLLS) + 1) * ROLLS_PER_DAY) - tokensRolled;
if (tokensToRoll > totalSupply() - tokensRolled) {
tokensToRoll = totalSupply() - tokensRolled;
}
return tokensToRoll;
}
function _revealToken(
uint256 _tokenId,
uint256 _prizeIndex
)
private
{
string memory prize = "N/A";
if (_prizeIndex < PRIZES.length) {
prize = PRIZES[_prizeIndex];
} else if (_prizeIndex == 500) {
prize = 'CryptoPunk #9964';
}
emit RevealToken(_tokenId, metadataContract.VARIANT_NAMES(revealedTokenVariant[_tokenId]), prize);
}
function totalSupply() public view returns (uint256) {
return currentTokenSupply;
}
function tokenURI(
uint256 _tokenId
)
public
view
virtual
override
returns (
string memory
) {
require(address(metadataContract).code.length > 0, "Metadata contract not set");
return metadataContract.constructTokenURI(
_tokenId,
revealedTokenVariant[_tokenId]
);
}
function _pullRandomUniqueIndex(
uint256 currentPrng,
uint256 leftToRoll,
mapping(uint256 => uint256) storage _swaps
)
internal
returns (uint256)
{
require(leftToRoll > 0, "No more unique indexes to pull");
uint256 index = 1 + (currentPrng % leftToRoll);
uint256 chosenIndex = _swaps[index];
if (chosenIndex == 0) {
chosenIndex = index;
}
uint256 temp = _swaps[leftToRoll];
if (temp == 0) {
_swaps[index] = leftToRoll;
} else {
_swaps[index] = temp;
delete _swaps[leftToRoll];
}
return chosenIndex;
}
function _prng(
uint256 currentPrng,
uint256 leftToRoll,
uint256 blockOffset
)
internal
view
returns (uint256)
{
return uint256(
keccak256(
abi.encodePacked(
blockhash(block.number - blockOffset),
block.difficulty,
currentPrng,
leftToRoll
)
)
);
}
function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) {
super.setApprovalForAll(operator, approved);
}
function approve(address operator, uint256 tokenId) public override onlyAllowedOperatorApproval(operator) {
super.approve(operator, tokenId);
}
function transferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) {
super.transferFrom(from, to, tokenId);
}
function safeTransferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) {
super.safeTransferFrom(from, to, tokenId);
}
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data)
public
override
onlyAllowedOperator(from)
{
super.safeTransferFrom(from, to, tokenId, data);
}
function supportsInterface(bytes4 interfaceId)
public
view
override
returns (bool)
{
return interfaceId == this.royaltyInfo.selector || super.supportsInterface(interfaceId);
}
function royaltyInfo(uint256, uint256 amount)
public
view
returns (address, uint256)
{
return (royaltyRecipient, (amount * royaltyBps) / 10000);
}
}
文件 12 的 16:JosieNftBoxMetadata.sol
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/utils/Strings.sol";
import "./ContractDataStorage.sol";
contract JosieNftBoxMetadata {
using Strings for uint256;
ContractDataStorage public contractDataStorage;
mapping(uint256 => uint256) public revealedTokenVariant;
string[13] public VARIANT_NAMES = [
"Unrevealed",
"Brainwash Victim",
"Curb Valve",
"Detox",
"Galaxy Blaster",
"Hello, My Name Is",
"Holy Rosary",
"King Baby",
"Moose Sighting",
"Pay Me",
"Rest In Peace",
"Unfuck The World",
"Zoo York"
];
constructor(
address _contractDataStorageAddress
) {
contractDataStorage = ContractDataStorage(_contractDataStorageAddress);
}
function constructTokenURI(
uint256 _tokenId,
uint256 _variantIdx
)
public
view
returns (
string memory
) {
bool revealed = _variantIdx > 0;
string memory name = (revealed) ? "Don't Feed the Pigeons" : "UNREVEALED Don't Feed the Pigeons";
string memory desc = "Hustling down a New York City street, under a sea of towering skyscrapers and kaleidoscopes of light, a gust of night air rushes through your hair as a dozen pigeons take flight around you. Their silvery gray feathers glow blue, red, and purple from the hues above. Don't they look regal?\\n\\nPigeons have a bad rep. Sure, people see them as pests now, but starting even earlier than 4500 BCE (6,500 years ago), it was a different story. Once considered a beautiful companion, pigeons were highly respected creatures. Some kept as pets, some used as mail carriers with their intelligence and navigational skills, others decorated with medals of honor for saving thousands of lives in war or stranded boats out at sea. In fact, pigeons were brought to America on the first-ever expeditions from Europe because the voyage simply couldn't be done without their help. Over the years, like a true New Yorker, they have scrappily adapted to their new environment, thriving in a concrete jungle built for mankind. Despite their fall in status, they are still as intertwined with the city as Lady Liberty. As the many signs read \\\"Don't Feed the Pigeons\\\", or do, but at least stop to appreciate the beautiful life - big and small - that creates the beating pulse of New York City.\\n\\nThe color variants of \\\"Don't Feed the Pigeons\\\" are all named after graffiti, stickers, or signs found in New York. There is a special nod hidden in the SVG layers to a very special friend. R.I.P Alotta Money, sending you love from all of the beautiful creatures here missing you.";
string memory variant = VARIANT_NAMES[_variantIdx];
return string(
abi.encodePacked(
abi.encodePacked(
bytes('data:application/json;utf8,{"name":"'),
name,
bytes(' #'),
_tokenId.toString(),
bytes('","description":"'),
desc,
bytes('","image_data":"')
),
contractDataStorage.getData(variant),
contractDataStorage.getData('common-bottom.svg'),
abi.encodePacked(
bytes('","attributes":[{"trait_type":"Variant", "value":"'),
variant,
bytes('"}]}')
)
)
);
}
}
文件 13 的 16:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
文件 14 的 16:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 15 的 16:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
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] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
文件 16 的 16:WithOperatorFilter.sol
pragma solidity ^0.8.13;
import {IOperatorFilterRegistry} from "operator-filter-registry/src/IOperatorFilterRegistry.sol";
abstract contract WithOperatorFilter {
error OperatorNotAllowed(address operator);
address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);
IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY =
IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);
bool public isOperatorFilterEnabled = true;
constructor() {
if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), DEFAULT_SUBSCRIPTION);
}
}
modifier onlyAllowedOperator(address from) virtual {
if (from != msg.sender) {
_checkOperatorFilter(msg.sender);
}
_;
}
modifier onlyAllowedOperatorApproval(address operator) virtual {
_checkOperatorFilter(operator);
_;
}
function _checkOperatorFilter(address operator) internal view {
if (isOperatorFilterEnabled && address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {
revert OperatorNotAllowed(operator);
}
}
}
}
{
"compilationTarget": {
"contracts/JosieNftBox.sol": "JosieNftBox"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_metadataContractAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"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":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"variant","type":"string"},{"indexed":false,"internalType":"string","name":"prize","type":"string"}],"name":"RevealToken","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":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLLS_PER_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"START_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTokenSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"isOperatorFilterEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataContract","outputs":[{"internalType":"contract JosieNftBoxMetadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numToRoll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"revealedTokenVariant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rollReveals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"bool","name":"_setting","type":"bool"}],"name":"setIsOperatorFilterEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_metadataContractAddress","type":"address"}],"name":"setMetadataContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bps","type":"uint256"}],"name":"setRoyaltyBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"setRoyaltyRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensRolled","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"}]