This repository has been archived by the owner on Mar 2, 2024. It is now read-only.
forked from 0xMattCarter/grill-contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
input.json
96 lines (95 loc) · 119 KB
/
input.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{
"language": "Solidity",
"sources": {
"contracts/Grill2.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol\";\n\nerror CallerBlacklisted();\nerror CallerNotTokenOwner();\nerror CallerNotTokenStaker();\nerror StakingNotActive();\nerror ZeroEmissionRate();\n\n/**\n * Interfaces astrobull contract\n */\ninterface ISUPER1155 {\n function balanceOf(address _owner, uint256 _id)\n external\n view\n returns (uint256);\n\n function groupBalances(uint256 groupId, address from)\n external\n view\n returns (uint256);\n\n function safeTransferFrom(\n address _from,\n address _to,\n uint256 _id,\n uint256 _amount,\n bytes calldata _data\n ) external;\n\n function safeBatchTransferFrom(\n address _from,\n address _to,\n uint256[] memory _ids,\n uint256[] memory _amounts,\n bytes memory _data\n ) external;\n}\n\n/**\n * Interfaces old grill contract\n */\ninterface IGRILL {\n struct Stake {\n bool status;\n address staker;\n uint256 timestamp;\n }\n\n function getStake(uint256 _tokenId)\n external\n view\n returns (Stake memory _stake);\n\n function getIdsOfAddr(address _operator)\n external\n view\n returns (uint256[] memory _addrStakes);\n}\n\n/**\n * @title Grill2.0\n * @author Matt Carter, degendeveloper.eth\n * 6 June, 2022\n *\n * The purpose of this contract is to optimize gas consumption when adding new stakes and\n * removing previous stakes from the initial grill contract @ 0xE11AF478aF241FAb926f4c111d50139Ae003F7fd.\n *\n * Users will use this new grill contract when adding and removing stakes. This new contract\n * is also responsible for counting emission tokens and setting new emission rates.\n *\n * This contract is whitelisted to move the first grill's tokens via proxy registry in the super1155 contract.\n *\n * This contract should be set as the `proxyRegistryAddress` in the parent contract. This\n * allows the new grill to move tokens on behalf of the old grill.\n */\ncontract Grill2 is Ownable, ERC1155Holder {\n using Counters for Counters.Counter;\n uint256 internal constant MAX_INT = 2**256 - 1;\n /// contract instances ///\n ISUPER1155 public constant Parent =\n ISUPER1155(0x71B11Ac923C967CD5998F23F6dae0d779A6ac8Af);\n IGRILL public immutable OldGrill;\n /// the number of times the emission rate changes ///\n Counters.Counter internal emChanges;\n /// is adding stakes allowed ///\n bool public isStaking = true;\n /// the number of stakes added & removed by each account (this contract) ///\n mapping(address => Counters.Counter) internal stakesAddedPerAccount;\n mapping(address => Counters.Counter) internal stakesRemovedPerAccount;\n /// each Stake by tokenId (this contract) ///\n mapping(uint256 => Stake) public stakeStorage;\n /// each tokenId by index for an account (this contract) ///\n mapping(address => mapping(uint256 => uint256)) public accountStakes;\n /// each Emission by index (this contract) ///\n mapping(uint256 => Emission) public emissionStorage;\n /// the number of emission tokens earned be each account from removed stakes ///\n mapping(address => uint256) public unstakedClaims;\n /// accounts that can not add new stakes ///\n mapping(address => bool) public blacklist;\n /// list of new proxies for Parent tokens ///\n mapping(address => address) public proxies;\n\n /**\n * Stores information for an emission change\n * @param rate The number of seconds to earn 1 emission token\n * @param timestamp The block.timestamp this emission rate is set\n */\n struct Emission {\n uint256 rate;\n uint256 timestamp;\n }\n\n /**\n * Stores information for a stake\n * @param staker The address who creates this stake\n * @param timestamp The block.timestamp this stake is created\n * @param accountSlot The index for this stake in `accountStakes`\n */\n struct Stake {\n address staker;\n uint256 timestamp;\n uint256 accountSlot;\n }\n\n /// ============ CONSTRUCTOR ============ ///\n\n /**\n * Initializes contract instances and sets the initial emission rate\n * @param _grillAddr The address for the first grill contract\n * @notice `1652054400` is Mon, 09 May 2022 00:00:00 GMT\n * @notice '3600 * 24 * 45' is the number of seconds in 45 days\n */\n constructor(address _grillAddr) {\n OldGrill = IGRILL(_grillAddr);\n emissionStorage[emChanges.current()] = Emission(3600 * 24 * 45, 1652054400);\n }\n\n /// ============ OWNER ============ ///\n\n /**\n * Sets a proxy transferer for `account`s tokens\n * @param account The address whose tokens to move\n * @param operator The address being proxied as an approved operator for `account`\n * @notice The team will use this contract as a proxy for old grill tokens\n */\n function setProxyForAccount(address account, address operator)\n public\n onlyOwner\n {\n proxies[account] = operator;\n }\n\n /**\n * Removes a proxy transferer for `account`s tokens\n * @param account The address losing its proxy transferer\n */\n function removeProxyForAccount(address account) public onlyOwner {\n delete proxies[account];\n }\n\n /**\n * Allows/unallows the addition of new stakes\n */\n function toggleStaking() public onlyOwner {\n isStaking = !isStaking;\n }\n\n /**\n * Allows/unallows an account to add new stakes\n * @param account The address to set status for\n * @param status The status being set\n * @notice A staker is always able to remove their stakes regardless of blacklist status\n */\n function blacklistAccount(address account, bool status) public onlyOwner {\n blacklist[account] = status;\n }\n\n /**\n * Stops emission token counting by setting an emission rate of the max-int number of seconds\n * @notice No tokens can be earned with an emission rate this long\n * @notice To continue emissions counting, the owner must set a new emission rate\n */\n function pauseEmissions() public onlyOwner {\n _setEmissionRate(MAX_INT);\n }\n\n /**\n * Sets a new rate for earning emission tokens\n * @param _seconds The number of seconds a token must be staked for to earn 1 emission token\n */\n function setEmissionRate(uint256 _seconds) public onlyOwner {\n _setEmissionRate(_seconds);\n }\n\n /// ============ PUBLIC ============ ///\n\n /**\n * Stakes an array of tokenIds with this contract to earn emission tokens\n * @param tokenIds An array of tokenIds to stake\n * @param amounts An array of amounts of each tokenId to stake\n * @notice Caller must `setApprovalForAll()` to true in the parent contract using this contract's address\n * before it can move their tokens\n */\n function addStakes(uint256[] memory tokenIds, uint256[] memory amounts)\n public\n {\n if (!isStaking) {\n revert StakingNotActive();\n }\n if (blacklist[msg.sender]) {\n revert CallerBlacklisted();\n }\n /// @dev verifies caller owns each token ///\n for (uint256 i = 0; i < tokenIds.length; ++i) {\n uint256 _tokenId = tokenIds[i];\n if (Parent.balanceOf(msg.sender, _tokenId) == 0) {\n revert CallerNotTokenOwner();\n }\n /// @dev sets contract state ///\n _addStake(msg.sender, _tokenId);\n }\n /// @dev transfers tokens from caller to this contract ///\n Parent.safeBatchTransferFrom(\n msg.sender,\n address(this),\n tokenIds,\n amounts,\n \"0x00\"\n );\n }\n\n /**\n * Removes an array of tokenIds staked in this contract and/or the old one\n * @param oldTokenIds The tokenIds being unstaked from the old contract\n * @param oldAmounts The number of each token being unstaked\n * @param newTokenIds The tokenIds being unstaked from this contract\n * @param newAmounts The number of each token being unstaked\n */\n function removeStakes(\n uint256[] memory oldTokenIds,\n uint256[] memory oldAmounts,\n uint256[] memory newTokenIds,\n uint256[] memory newAmounts\n ) public {\n if (oldTokenIds.length > 0) {\n /// @dev verifies caller staked each token ///\n for (uint256 i = 0; i < oldTokenIds.length; ++i) {\n uint256 _tokenId = oldTokenIds[i];\n IGRILL.Stake memory _thisStake = OldGrill.getStake(_tokenId);\n if (_thisStake.staker != msg.sender) {\n revert CallerNotTokenStaker();\n }\n /// @dev increments emissions earned for caller ///\n unstakedClaims[msg.sender] += countEmissions(_thisStake.timestamp);\n }\n /// @dev transfers tokens from old contract to caller ///\n Parent.safeBatchTransferFrom(\n address(OldGrill),\n msg.sender,\n oldTokenIds,\n oldAmounts,\n \"0x00\"\n );\n }\n if (newTokenIds.length > 0) {\n /// @dev verifies caller staked each token ///\n for (uint256 i = 0; i < newTokenIds.length; ++i) {\n uint256 _tokenId = newTokenIds[i];\n if (stakeStorage[_tokenId].staker != msg.sender) {\n revert CallerNotTokenStaker();\n }\n /// @dev sets contract state ///\n _removeStake(_tokenId);\n }\n /// @dev transfers tokens from this contract to caller ///\n Parent.safeBatchTransferFrom(\n address(this),\n msg.sender,\n newTokenIds,\n newAmounts,\n \"0x00\"\n );\n }\n }\n\n /**\n * Counts the number of emission tokens a timestamp has earned\n * @param _timestamp The timestamp a token was staked\n * @return _c The number of emission tokens a stake has earned since `_timestamp`\n */\n function countEmissions(uint256 _timestamp) public view returns (uint256 _c) {\n /// @dev if timestamp is before contract creation or later than now return 0 ///\n if (\n _timestamp < emissionStorage[0].timestamp || _timestamp > block.timestamp\n ) {\n _c = 0;\n } else {\n /**\n * @dev finds the most recent emission rate _timestamp comes after\n * Example:\n * emChanges: *0...........1............2.....................3...........*\n * timeline: *(deploy)....x............x.....(timestamp).....x......(now)*\n */\n uint256 minT;\n for (uint256 i = 1; i <= emChanges.current(); ++i) {\n if (emissionStorage[i].timestamp < _timestamp) {\n minT += 1;\n }\n }\n /// @dev counts all emissions earned starting from minT -> now ///\n for (uint256 i = minT; i <= emChanges.current(); ++i) {\n uint256 tSmall = emissionStorage[i].timestamp;\n uint256 tBig = emissionStorage[i + 1].timestamp; // 0 if not set yet\n if (i == minT) {\n tSmall = _timestamp;\n }\n if (i == emChanges.current()) {\n tBig = block.timestamp;\n }\n _c += (tBig - tSmall) / emissionStorage[i].rate;\n }\n }\n }\n\n /// ============ INTERNAL ============ ///\n\n /**\n * Helper function that sets contract state when adding a stake to this contract\n * @param staker The address to make the stake for\n * @param tokenId The tokenId being staked\n */\n function _addStake(address staker, uint256 tokenId) internal {\n /// @dev increments slots filled by staker ///\n stakesAddedPerAccount[staker].increment();\n /// @dev fills new slot (account => index => tokenId) ///\n accountStakes[staker][stakesAddedPerAccount[staker].current()] = tokenId;\n /// @dev add new stake to storage ///\n stakeStorage[tokenId] = Stake(\n staker,\n block.timestamp,\n stakesAddedPerAccount[staker].current()\n );\n }\n\n /**\n * Helper function that sets contract state when removing a stake from this contract\n * @param tokenId The tokenId being un-staked\n * @notice This function is not called when removing stakes from the old contract\n */\n function _removeStake(uint256 tokenId) internal {\n /// @dev copies the stake being removed ///\n Stake memory _thisStake = stakeStorage[tokenId];\n /// @dev increments slots emptied by staker ///\n stakesRemovedPerAccount[_thisStake.staker].increment();\n /// @dev increments emissions earned for removing this stake ///\n unstakedClaims[_thisStake.staker] += countEmissions(_thisStake.timestamp);\n /// @dev empty staker's slot (account => index => 0) ///\n delete accountStakes[_thisStake.staker][_thisStake.accountSlot];\n /// @dev removes stake from storage ///\n delete stakeStorage[tokenId];\n }\n\n /**\n * Helper function that sets contract state when emission changes occur\n * @param _seconds The number of seconds a token must be staked for to earn 1 emission token\n * @notice The emission rate cannot be 0 seconds\n */\n function _setEmissionRate(uint256 _seconds) private {\n if (_seconds == 0) {\n revert ZeroEmissionRate();\n }\n emChanges.increment();\n emissionStorage[emChanges.current()] = Emission(_seconds, block.timestamp);\n }\n\n /**\n * Helper function that gets the number of stakes an account has active with this contract\n * @param account The address to lookup\n * @return _active The number stakes\n */\n function _activeStakesCountPerAccount(address account)\n internal\n view\n returns (uint256 _active)\n {\n _active =\n stakesAddedPerAccount[account].current() -\n stakesRemovedPerAccount[account].current();\n }\n\n /**\n * Helper function that gets the number of stakes an account has active with the old contract\n * @param account The address to lookup\n * @return _active The number of stakes not yet removed from the old contract\n */\n function _activeStakesCountPerAccountOld(address account)\n internal\n view\n returns (uint256 _active)\n {\n uint256[] memory oldStakes = OldGrill.getIdsOfAddr(account);\n for (uint256 i = 0; i < oldStakes.length; ++i) {\n if (Parent.balanceOf(address(OldGrill), oldStakes[i]) == 1) {\n _active += 1;\n }\n }\n }\n\n /// ============ READ-ONLY ============ ///\n\n /**\n * Gets tokenIds for `account`s active stakes in this contract\n * @param account The address to lookup\n * @return _ids Array of tokenIds\n */\n function stakedIdsPerAccount(address account)\n public\n view\n returns (uint256[] memory _ids)\n {\n _ids = new uint256[](_activeStakesCountPerAccount(account));\n /// @dev finds all slots still filled ///\n uint256 found;\n for (uint256 i = 1; i <= stakesAddedPerAccount[account].current(); ++i) {\n if (accountStakes[account][i] != 0) {\n _ids[found++] = accountStakes[account][i];\n }\n }\n }\n\n /**\n * Gets tokenIds for `account`s active stakes in the old contract\n * @param account The address to lookup\n * @return _ids Array of tokenIds\n */\n function stakedIdsPerAccountOld(address account)\n public\n view\n returns (uint256[] memory _ids)\n {\n /// @dev gets all tokenIds account had staked ///\n uint256[] memory oldStakes = OldGrill.getIdsOfAddr(account);\n /// @dev finds all tokenIds still active in old contract ///\n _ids = new uint256[](_activeStakesCountPerAccountOld(account));\n uint256 found;\n for (uint256 i = 0; i < oldStakes.length; ++i) {\n if (Parent.balanceOf(address(OldGrill), oldStakes[i]) == 1) {\n _ids[found++] = oldStakes[i];\n }\n }\n }\n\n /**\n * Gets the total number of emission changes to date\n * @return _changes The current number of changes to emission rates\n */\n function emissionChanges() external view returns (uint256 _changes) {\n _changes = emChanges.current();\n }\n\n /**\n * Gets the number of emission tokens `account` has earned from their active stakes\n * @param account The address to lookup\n * @return _earned The number of claims\n * @notice Uses stakes from new and old contract\n */\n function stakedClaims(address account) public view returns (uint256 _earned) {\n /// @dev counts emissions for each active stake in this contract ///\n uint256[] memory ownedIds = stakedIdsPerAccount(account);\n for (uint256 i; i < ownedIds.length; ++i) {\n _earned += countEmissions(stakeStorage[ownedIds[i]].timestamp);\n }\n /// @dev counts emissions for each active stake in old contract ///\n uint256[] memory ownedIdsOld = stakedIdsPerAccountOld(account);\n for (uint256 i; i < ownedIdsOld.length; ++i) {\n _earned += countEmissions(OldGrill.getStake(ownedIdsOld[i]).timestamp);\n }\n }\n\n /**\n * Gets the number of emission tokens `account` has earned from their active and removed stakes\n * @param account The address to lookup\n * @return _earned The number of emissions _operator has earned from all past and current stakes\n * @notice Uses stakes from new and old contract\n */\n function totalClaims(address account)\n external\n view\n returns (uint256 _earned)\n {\n _earned = unstakedClaims[account] + stakedClaims(account);\n }\n\n /**\n * Gets the Stake object from this grill contract\n * @param tokenId The tokenId to get stake for\n * @return _s The Stake object\n */\n function stakeStorageGetter(uint256 tokenId)\n public\n view\n returns (Stake memory _s)\n {\n _s = stakeStorage[tokenId];\n }\n\n /**\n * Gets the Stake object from the old grill contract\n * @param tokenId The tokenId to get stake for\n * @return _og The old Stake object\n */\n function stakeStorageOld(uint256 tokenId)\n public\n view\n returns (IGRILL.Stake memory _og)\n {\n _og = OldGrill.getStake(tokenId);\n }\n}\n"
},
"contracts/Burger.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"@openzeppelin/contracts/utils/Strings.sol\";\nimport \"./Grill2.sol\";\n\nerror BurningNotActive();\nerror ClaimingNotActive();\nerror CallerIsNotABurner();\nerror InsufficientClaimsRemaining();\n\n/**\n * @title Burgers\n * @author Matt Carter\n * June 6, 2022\n *\n * This contract is for accounts to claim emission tokens (burgers) from their grill stakes.\n * Burgers have a `tokenId` of 1 and are burnable by owner-set `burner` addresses.\n */\ncontract Burger is ERC1155, Ownable {\n using Strings for uint256;\n /// contract instances ///\n Grill2 public immutable TheGrill;\n Grill2 public SpecialGrill;\n /// is claiming/burning/special grill active ///\n bool public isClaiming = false;\n bool public isBurning = false;\n bool public isSpecial = false;\n /// the number of burgers minted/burned ///\n uint256 public totalMints;\n uint256 public totalBurns;\n /// addresses allowed to burn burgers ///\n mapping(address => bool) public burners;\n /// the number of claims used by each account ///\n mapping(address => uint256) public claimsUsed;\n /// the number of burgers burned by each account ///\n mapping(address => uint256) public accountBurns;\n /// the number of burgers burned by each burner ///\n mapping(address => uint256) public burnerBurns;\n\n /// ============ CONSTRUCTOR ============ ///\n\n /**\n * Sets the initial base URI and address for the grill\n * @param _URI The baseURI for each token\n * @param aGrill The address of the astro grill contract\n */\n constructor(string memory _URI, address aGrill) ERC1155(_URI) {\n TheGrill = Grill2(aGrill);\n }\n\n /// ============ INTERNAL ============ ///\n\n /**\n * Gets the total number of burgers `account` has earned from the grill(s)\n * @param account The address to lookup\n * @return quantity The number of claims\n */\n function _totalClaimsEarned(address account)\n internal\n view\n returns (uint256 quantity)\n {\n quantity += TheGrill.totalClaims(account);\n /// @dev additionally counts special grill stakes ///\n if (isSpecial) {\n quantity += SpecialGrill.totalClaims(account);\n }\n }\n\n /// ============ OWNER ============ ///\n\n /**\n * Sets the new base URI for tokens\n * @param _URI The new base URI\n * @notice Uses the format: baselink.com/{}.json\n */\n function setURI(string memory _URI) public onlyOwner {\n _setURI(_URI);\n }\n\n /**\n * Toggles if claiming tokens is allowed\n */\n function toggleClaiming() public onlyOwner {\n isClaiming = !isClaiming;\n }\n\n /**\n * Toggles if burning tokens is allowed\n */\n function toggleBurning() public onlyOwner {\n isBurning = !isBurning;\n }\n\n /**\n * Approve an address to burn burgers\n * @param account The burner address\n * @param status The status of the approval\n * @notice A burner should be a contract address that correctly handles the burning of an operators tokens\n */\n function setBurner(address account, bool status) public onlyOwner {\n burners[account] = status;\n }\n\n /**\n * Mints `quantity` burgers to `account` without restrictions\n * @param quantity The number of tokens to mint\n * @param account The address to mint the tokens to\n */\n function ownerMint(uint256 quantity, address account) public onlyOwner {\n _mint(account, 1, quantity, \"0x00\");\n totalMints += quantity;\n }\n\n /**\n * Toggles if the special grill is running\n */\n function toggleSpecial() public onlyOwner {\n isSpecial = !isSpecial;\n }\n\n /**\n * Sets the special grill interface\n * @param aGrill The address of the special grill\n */\n function setSpecial(address aGrill) public onlyOwner {\n SpecialGrill = Grill2(aGrill);\n }\n\n /// ============ PUBLIC ============ ///\n\n /**\n * Mints `quantity` burgers to caller\n * @param quantity The number of burgers caller is trying to mint\n */\n function claimBurgers(uint256 quantity) public {\n if (!isClaiming) {\n revert ClaimingNotActive();\n }\n if (claimsUsed[msg.sender] + quantity > _totalClaimsEarned(msg.sender)) {\n revert InsufficientClaimsRemaining();\n }\n /// @dev mints `quantity` tokens with `tokenId` 1 to caller ///\n _mint(msg.sender, 1, quantity, \"0x00\");\n /// @dev sets contract state ///\n claimsUsed[msg.sender] += quantity;\n totalMints += quantity;\n }\n\n /**\n * Burns burgers on behalf of `account`\n * @param account The address having it's burgers burned\n * @param quantity The number of burgers to burn\n * @notice Only burners may call this function\n */\n function burnBurger(address account, uint256 quantity) public {\n if (!isBurning) {\n revert BurningNotActive();\n }\n if (!burners[msg.sender]) {\n revert CallerIsNotABurner();\n }\n /// @dev burns `quantity` tokens of `tokenId` 1 for `account` ///\n _burn(account, 1, quantity);\n /// @dev sets contract state ///\n totalBurns += quantity;\n accountBurns[account] += quantity;\n burnerBurns[msg.sender] += quantity;\n }\n\n /// ============ READ-ONLY ============ ///\n\n /**\n * Gets the balance of burgers for `account`\n * @param account The address to lookup\n * @return _balance The number of burgers\n * @notice burgers have a `tokenId` of 1\n */\n function balanceOf(address account) public view returns (uint256 _balance) {\n _balance = balanceOf(account, 1);\n }\n\n /**\n * Gets the total number of burgers in circulation\n * @return _totalSupply The number of burgers\n */\n function totalSupply() public view returns (uint256 _totalSupply) {\n _totalSupply = totalMints - totalBurns;\n }\n\n /**\n * Gets the number of claims `account` has remaining\n * @param account The address to lookup\n * @return _remaining The number of claims\n */\n function tokenClaimsLeft(address account)\n public\n view\n returns (uint256 _remaining)\n {\n _remaining = _totalClaimsEarned(account) - claimsUsed[account];\n }\n}\n"
},
"contracts/MetaBull.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"erc721a/contracts/ERC721A.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"@openzeppelin/contracts/utils/Strings.sol\";\nimport \"./Burger.sol\";\n\nerror MintingNotActive();\nerror AstrobullAlreadyClaimed();\n\n/**\n * @title Metabulls\n * @author Matt Carter\n * June 6, 2022\n *\n * This contract is an implementation of chiru lab's erc721a contract and is used for minting\n * 3d metaverse bulls. To mint a metabull, an account will input tokenIds of astrobulls\n * they are using to claim; meaning the account must own each astrobull or be the staker of it,\n * and each astrobull can only be used once. The contract will store which astrobull traits to\n * give each metabull. Users will burn burgers for each metabull they mint.\n */\ncontract MetaBull is ERC721A, Ownable {\n using Strings for uint256;\n /// contract instances ///\n Burger public immutable BurgerContract;\n Grill2 public immutable GrillContract;\n ISUPER1155 public constant Astro =\n ISUPER1155(0x71B11Ac923C967CD5998F23F6dae0d779A6ac8Af);\n address public constant OldGrill = 0xE11AF478aF241FAb926f4c111d50139Ae003F7fd;\n /// if minting is active ///\n bool public isMinting;\n /// if tokens are revealed ///\n bool public isRevealed;\n /// the number of burgers to burn each mint ///\n uint256 public burnScalar = 2;\n /// the number of burgers burned by this contract ///\n uint256 public totalBurns;\n /// the base uri for all tokens ///\n string public URI;\n /// if an astrobull has been claimed for yet ///\n mapping(uint256 => bool) public portedIds;\n /// which astrobull traits to give each metabull ///\n mapping(uint256 => uint256) public portingMeta;\n /// the number of burgers each account has burned ///\n mapping(address => uint256) public accountBurns;\n\n /// ============ CONSTRUCTOR ============ ///\n\n /**\n * Sets the initial base uri and address for the burger contract\n * @param _URI The baseURI for each token\n * @param burgerAddr The address of the burger contract\n * @param grillAddr The address of the grill contract\n */\n constructor(\n string memory _URI,\n address burgerAddr,\n address grillAddr\n ) ERC721A(\"METABULLS\", \"MBULL\") {\n URI = _URI;\n BurgerContract = Burger(burgerAddr);\n GrillContract = Grill2(grillAddr);\n }\n\n /// ============ INTERNAL ============ ///\n\n /**\n * Overrides tokens to start at index 1 instead of 0\n * @return _id The tokenId of the first token\n */\n function _startTokenId() internal pure override returns (uint256 _id) {\n _id = 1;\n }\n\n /// ============ OWNER ============ ///\n\n /**\n * Sets a new base URI for tokens\n * @param _URI The new baseURI for each token\n */\n function setURI(string memory _URI) public onlyOwner {\n URI = _URI;\n }\n\n /**\n * Toggles if minting is allowed.\n */\n function toggleMinting() public onlyOwner {\n isMinting = !isMinting;\n }\n\n /**\n * Toggles if tokens are revealed.\n */\n function toggleReveal() public onlyOwner {\n isRevealed = !isRevealed;\n }\n\n /**\n * Sets the quantity of burgers an account must burn to mint each metabull\n * @param _burnScalar The number of burgers to burn\n */\n function setBurnScalar(uint256 _burnScalar) public onlyOwner {\n burnScalar = _burnScalar;\n }\n\n /**\n * Mints `quantity` tokens to `account`\n * @param quantity The number of tokens to mint\n * @param account The address to mint the tokens to\n * @notice Each token an owner mints will point to a 0 in the portingMeta mapping\n * since it does not share traits with a minted astrobull\n */\n function ownerMint(uint256 quantity, address account) public onlyOwner {\n _safeMint(account, quantity);\n }\n\n /// ============ PUBLIC ============ ///\n\n /**\n * Mints a metabull for each astrobull input\n * @param astrobullIds An array of astrobull IDs caller is claiming metabulls for\n * @notice The caller must own each astrobull ID they are claiming for; meaning it must\n * be removed from the grill before use\n */\n function claimBull(uint256[] memory astrobullIds) public {\n if (!isMinting) {\n revert MintingNotActive();\n }\n /// @dev gets the first tokenId being minted ///\n uint256 currentIndex = _currentIndex;\n for (uint256 i = 0; i < astrobullIds.length; ++i) {\n if (!_checkOwnerShip(msg.sender, astrobullIds[i])) {\n revert CallerNotTokenOwner();\n }\n if (portedIds[astrobullIds[i]]) {\n revert AstrobullAlreadyClaimed();\n }\n /// @dev sets the astrobull traits to give each metabull being minted ///\n portingMeta[currentIndex] = astrobullIds[i];\n /// @dev sets contract state ///\n portedIds[astrobullIds[i]] = true;\n /// @dev sets the next tokenId being minted ///\n currentIndex += 1;\n }\n /// burn caller's burgers ///\n uint256 toBurn = burnScalar * astrobullIds.length;\n BurgerContract.burnBurger(msg.sender, toBurn);\n /// sets contract state ///\n totalBurns += toBurn;\n accountBurns[msg.sender] += toBurn;\n /// mint metabulls to caller ///\n _safeMint(msg.sender, astrobullIds.length);\n }\n\n /// ============ INTERNAL ============ ///\n\n /**\n * Checks if `account` is the owner or staker of `tokenId`\n * @param account The address to check ownership for\n * @param tokenId The tokenId to check ownership of\n * @return _b If `account` is the owner or staker of `tokenId`\n */\n function _checkOwnerShip(address account, uint256 tokenId)\n internal\n view\n returns (bool _b)\n {\n _b = false;\n /// @dev first checks if account owns token ///\n if (Astro.balanceOf(account, tokenId) == 1) {\n _b = true;\n }\n /// @dev next, checks if token is staked in the old grill and caller is staker ///\n else if (Astro.balanceOf(address(OldGrill), tokenId) == 1) {\n if (GrillContract.stakeStorageOld(tokenId).staker == account) {\n _b = true;\n }\n }\n /// @dev last, checks if token is staked in current grill and caller is staker ///\n else if (GrillContract.stakeStorageGetter(tokenId).staker == account) {\n _b = true;\n }\n }\n\n /// ============ READ-ONLY ============ ///\n\n /**\n * Gets a token's URI\n * @param _tokenId The tokenId to lookup\n * @return _URI The token's uri\n */\n function tokenURI(uint256 _tokenId)\n public\n view\n override\n returns (string memory _URI)\n {\n if (isRevealed) {\n _URI = string(abi.encodePacked(URI, _tokenId.toString(), \".json\"));\n } else {\n _URI = URI;\n }\n }\n}\n"
},
"contracts/PhysicalBull.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Strings.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./Burger.sol\";\n\nerror ExceedsMaxClaims();\nerror InvalidTokenAmount();\nerror CallerIsNotTokenOwner();\nerror CallerNotInCommunity();\n\n/**\n * @title Physical Bulls\n * @author Matt Carter\n * June 6, 2022\n *\n * This contract handles the payment and verification for pre-ordering physical bulls. Users\n * will pre-order physical bulls by exchanging erc20 tokens and burning burgers.\n */\ncontract PhysicalBull is Ownable {\n using Strings for uint256;\n using SafeERC20 for IERC20;\n /// contract instances ///\n IERC20 public erc20;\n Burger public immutable BurgerContract;\n Grill2 public immutable GrillContract;\n ISUPER1155 public constant Astro =\n ISUPER1155(0x71B11Ac923C967CD5998F23F6dae0d779A6ac8Af);\n /// if claiming is active ///\n bool public isClaiming = false;\n /// the current erc20 payment receiver ///\n address public vault;\n /// the number of physical bulls claimed ///\n uint256 public totalClaims;\n /// the max number of claims an account can make ///\n uint256 public maxClaims = 3;\n /// the number of burgers burned by this contract ///\n uint256 public totalBurns;\n /// the number of burgers to burn for 1 physical bull ///\n uint256 public burnScalar = 1;\n /// the amount of erc20 tokens to claim 1 physical bull ///\n uint256 public erc20Cost = 100000000; // 100.000000 $USDC\n /// the number of burgers each account has burned ///\n mapping(address => uint256) public accountBurns;\n /// the number of physcal bulls each account has claimed ///\n mapping(address => uint256) public accountClaims;\n\n /**\n * @param _vault The address to receive erc20 tokens\n * @param _erc20 The contract address of the erc20 contract to use for payments\n * @param _burger The address of the burger contract\n * @param _grill The address of the new grill contract\n */\n constructor(\n address _vault,\n address _erc20,\n address _burger,\n address _grill\n ) {\n vault = _vault;\n erc20 = IERC20(_erc20);\n BurgerContract = Burger(_burger);\n GrillContract = Grill2(_grill);\n }\n\n /// ============ OWNER ============ ///\n\n /**\n * Toggles if claiming is active\n */\n function toggleClaiming() public onlyOwner {\n isClaiming = !isClaiming;\n }\n\n /**\n * Sets the cost for each bull claim\n * @param _erc20Cost The number of erc20 tokens to transfer\n */\n function setERC20Cost(uint256 _erc20Cost) public onlyOwner {\n erc20Cost = _erc20Cost;\n }\n\n /**\n * Sets the erc20 contract address to use for payments\n * @param _erc20 The erc20 contract address\n */\n function setERC20Address(address _erc20) public onlyOwner {\n erc20 = IERC20(_erc20);\n }\n\n /**\n * Sets the number of burgers to burn for each bull claim\n * @param _burnScalar The number of burgers to burn\n */\n function setBurnScalar(uint256 _burnScalar) public onlyOwner {\n burnScalar = _burnScalar;\n }\n\n /**\n * Sets the limit for the max number of claims per account\n * @param _maxClaims The max number of claims per account\n */\n function setMaxClaims(uint256 _maxClaims) public onlyOwner {\n maxClaims = _maxClaims;\n }\n\n /**\n * Sets the address for receiving erc20 payments\n * @param _vault The address to receive payments\n */\n function setVault(address _vault) public onlyOwner {\n vault = _vault;\n }\n\n /// ============ INTERNAL ============ ///\n\n /**\n * Checks if `account` owns any astrobulls or has any active stakes\n * @param account The address to lookup\n * @return _b If `account` owns or is the staker of > 0 astrobulls\n * @notice Checks both old and new grill contracts for active stakes\n */\n function _checkCommunityStatus(address account)\n internal\n view\n returns (bool _b)\n {\n _b = false;\n /// @dev first check if caller owns > 0 astrobulls ///\n if (Astro.groupBalances(1, account) > 0) {\n _b = true;\n }\n /// @dev next, check if caller has any active stakes in the old grill ///\n else if (GrillContract.stakedIdsPerAccountOld(account).length > 0) {\n _b = true;\n }\n /// @dev lastly, check if caller has any active stakes in the new grill ///\n else if (GrillContract.stakedIdsPerAccount(account).length > 0) {\n _b = true;\n }\n }\n\n /// ============ PUBLIC ============ ///\n\n /**\n * Claims `quantity` number of physical bulls if caller owns > 0 astrobulls\n * @param quantity The number of bulls to claim\n * @notice Caller will send `erc20Cost` * `quantity` tokens to `vault`\n * @notice Caller must give this contract a sufficient allowance to send their erc20 tokens\n */\n function claimBulls(uint256 quantity) public {\n if (!isClaiming) {\n revert ClaimingNotActive();\n }\n if (!_checkCommunityStatus(msg.sender)) {\n revert CallerNotInCommunity();\n }\n if (accountClaims[msg.sender] + quantity > maxClaims) {\n revert ExceedsMaxClaims();\n }\n if (quantity == 0) {\n revert InvalidTokenAmount();\n }\n /// @dev sends erc20 tokens from caller to vault ///\n erc20.safeTransferFrom(msg.sender, vault, quantity * erc20Cost);\n /// @dev burns caller's burgers ///\n uint256 toBurn = burnScalar * quantity;\n BurgerContract.burnBurger(msg.sender, burnScalar * quantity);\n /// @dev sets contract state ///\n totalBurns += toBurn;\n accountBurns[msg.sender] += toBurn;\n totalClaims += quantity;\n accountClaims[msg.sender] += quantity;\n }\n}\n"
},
"@openzeppelin/contracts/token/ERC1155/ERC1155.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: balance query for the zero address\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not owner nor approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: transfer caller is not owner nor approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _balances[id][to] += amount;\n emit TransferSingle(operator, address(0), to, id, amount);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `from`\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `from` must have at least `amount` tokens of token type `id`.\n */\n function _burn(\n address from,\n uint256 id,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n\n emit TransferSingle(operator, from, address(0), id, amount);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(\n address from,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n }\n\n emit TransferBatch(operator, from, address(0), ids, amounts);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits a {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC1155: setting approval status for self\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver.onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n"
},
"@openzeppelin/contracts/access/Ownable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n"
},
"@openzeppelin/contracts/utils/Counters.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n"
},
"@openzeppelin/contracts/utils/Strings.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n"
},
"@openzeppelin/contracts/token/ERC1155/IERC1155.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n"
},
"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n"
},
"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n"
},
"@openzeppelin/contracts/utils/Address.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n"
},
"@openzeppelin/contracts/utils/Context.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n"
},
"@openzeppelin/contracts/utils/introspection/ERC165.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n"
},
"@openzeppelin/contracts/utils/introspection/IERC165.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
},
"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ERC1155Receiver.sol\";\n\n/**\n * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens.\n *\n * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be\n * stuck.\n *\n * @dev _Available since v3.1._\n */\ncontract ERC1155Holder is ERC1155Receiver {\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n"
},
"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Receiver.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155Receiver.sol\";\nimport \"../../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\nabstract contract ERC1155Receiver is ERC165, IERC1155Receiver {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\n }\n}\n"
},
"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n"
},
"@openzeppelin/contracts/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n"
},
"erc721a/contracts/ERC721A.sol": {
"content": "// SPDX-License-Identifier: MIT\n// ERC721A Contracts v3.3.0\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\nimport './IERC721A.sol';\nimport '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@openzeppelin/contracts/utils/Context.sol';\nimport '@openzeppelin/contracts/utils/Strings.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension. Built to optimize for lower gas during batch mints.\n *\n * Assumes serials are sequentially minted starting at _startTokenId() (defaults to 0, e.g. 0, 1, 2, 3..).\n *\n * Assumes that an owner cannot have more than 2**64 - 1 (max value of uint64) of supply.\n *\n * Assumes that the maximum token id cannot exceed 2**256 - 1 (max value of uint256).\n */\ncontract ERC721A is Context, ERC165, IERC721A {\n using Address for address;\n using Strings for uint256;\n\n // The tokenId of the next token to be minted.\n uint256 internal _currentIndex;\n\n // The number of tokens burned.\n uint256 internal _burnCounter;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to ownership details\n // An empty struct value does not necessarily mean the token is unowned. See _ownershipOf implementation for details.\n mapping(uint256 => TokenOwnership) internal _ownerships;\n\n // Mapping owner address to address data\n mapping(address => AddressData) private _addressData;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n _currentIndex = _startTokenId();\n }\n\n /**\n * To change the starting tokenId, please override this function.\n */\n function _startTokenId() internal view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev Burned tokens are calculated here, use _totalMinted() if you want to count just minted tokens.\n */\n function totalSupply() public view override returns (uint256) {\n // Counter underflow is impossible as _burnCounter cannot be incremented\n // more than _currentIndex - _startTokenId() times\n unchecked {\n return _currentIndex - _burnCounter - _startTokenId();\n }\n }\n\n /**\n * Returns the total amount of tokens minted in the contract.\n */\n function _totalMinted() internal view returns (uint256) {\n // Counter underflow is impossible as _currentIndex does not decrement,\n // and it is initialized to _startTokenId()\n unchecked {\n return _currentIndex - _startTokenId();\n }\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view override returns (uint256) {\n if (owner == address(0)) revert BalanceQueryForZeroAddress();\n return uint256(_addressData[owner].balance);\n }\n\n /**\n * Returns the number of tokens minted by `owner`.\n */\n function _numberMinted(address owner) internal view returns (uint256) {\n return uint256(_addressData[owner].numberMinted);\n }\n\n /**\n * Returns the number of tokens burned by or on behalf of `owner`.\n */\n function _numberBurned(address owner) internal view returns (uint256) {\n return uint256(_addressData[owner].numberBurned);\n }\n\n /**\n * Returns the auxillary data for `owner`. (e.g. number of whitelist mint slots used).\n */\n function _getAux(address owner) internal view returns (uint64) {\n return _addressData[owner].aux;\n }\n\n /**\n * Sets the auxillary data for `owner`. (e.g. number of whitelist mint slots used).\n * If there are multiple variables, please pack them into a uint64.\n */\n function _setAux(address owner, uint64 aux) internal {\n _addressData[owner].aux = aux;\n }\n\n /**\n * Gas spent here starts off proportional to the maximum mint batch size.\n * It gradually moves to O(1) as tokens get transferred around in the collection over time.\n */\n function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) {\n uint256 curr = tokenId;\n\n unchecked {\n if (_startTokenId() <= curr) if (curr < _currentIndex) {\n TokenOwnership memory ownership = _ownerships[curr];\n if (!ownership.burned) {\n if (ownership.addr != address(0)) {\n return ownership;\n }\n // Invariant:\n // There will always be an ownership that has an address and is not burned\n // before an ownership that does not have an address and is not burned.\n // Hence, curr will not underflow.\n while (true) {\n curr--;\n ownership = _ownerships[curr];\n if (ownership.addr != address(0)) {\n return ownership;\n }\n }\n }\n }\n }\n revert OwnerQueryForNonexistentToken();\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view override returns (address) {\n return _ownershipOf(tokenId).addr;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n if (!_exists(tokenId)) revert URIQueryForNonexistentToken();\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : '';\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overriden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return '';\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public override {\n address owner = ERC721A.ownerOf(tokenId);\n if (to == owner) revert ApprovalToCurrentOwner();\n\n if (_msgSender() != owner) if(!isApprovedForAll(owner, _msgSender())) {\n revert ApprovalCallerNotOwnerNorApproved();\n }\n\n _approve(to, tokenId, owner);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view override returns (address) {\n if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n if (operator == _msgSender()) revert ApproveToCaller();\n\n _operatorApprovals[_msgSender()][operator] = approved;\n emit ApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, '');\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) public virtual override {\n _transfer(from, to, tokenId);\n if (to.isContract()) if(!_checkContractOnERC721Received(from, to, tokenId, _data)) {\n revert TransferToNonERC721ReceiverImplementer();\n }\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n */\n function _exists(uint256 tokenId) internal view returns (bool) {\n return _startTokenId() <= tokenId && tokenId < _currentIndex && !_ownerships[tokenId].burned;\n }\n\n /**\n * @dev Equivalent to `_safeMint(to, quantity, '')`.\n */\n function _safeMint(address to, uint256 quantity) internal {\n _safeMint(to, quantity, '');\n }\n\n /**\n * @dev Safely mints `quantity` tokens and transfers them to `to`.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement\n * {IERC721Receiver-onERC721Received}, which is called for each safe transfer.\n * - `quantity` must be greater than 0.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(\n address to,\n uint256 quantity,\n bytes memory _data\n ) internal {\n uint256 startTokenId = _currentIndex;\n if (to == address(0)) revert MintToZeroAddress();\n if (quantity == 0) revert MintZeroQuantity();\n\n _beforeTokenTransfers(address(0), to, startTokenId, quantity);\n\n // Overflows are incredibly unrealistic.\n // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1\n // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1\n unchecked {\n _addressData[to].balance += uint64(quantity);\n _addressData[to].numberMinted += uint64(quantity);\n\n _ownerships[startTokenId].addr = to;\n _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);\n\n uint256 updatedIndex = startTokenId;\n uint256 end = updatedIndex + quantity;\n\n if (to.isContract()) {\n do {\n emit Transfer(address(0), to, updatedIndex);\n if (!_checkContractOnERC721Received(address(0), to, updatedIndex++, _data)) {\n revert TransferToNonERC721ReceiverImplementer();\n }\n } while (updatedIndex < end);\n // Reentrancy protection\n if (_currentIndex != startTokenId) revert();\n } else {\n do {\n emit Transfer(address(0), to, updatedIndex++);\n } while (updatedIndex < end);\n }\n _currentIndex = updatedIndex;\n }\n _afterTokenTransfers(address(0), to, startTokenId, quantity);\n }\n\n /**\n * @dev Mints `quantity` tokens and transfers them to `to`.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `quantity` must be greater than 0.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 quantity) internal {\n uint256 startTokenId = _currentIndex;\n if (to == address(0)) revert MintToZeroAddress();\n if (quantity == 0) revert MintZeroQuantity();\n\n _beforeTokenTransfers(address(0), to, startTokenId, quantity);\n\n // Overflows are incredibly unrealistic.\n // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1\n // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1\n unchecked {\n _addressData[to].balance += uint64(quantity);\n _addressData[to].numberMinted += uint64(quantity);\n\n _ownerships[startTokenId].addr = to;\n _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);\n\n uint256 updatedIndex = startTokenId;\n uint256 end = updatedIndex + quantity;\n\n do {\n emit Transfer(address(0), to, updatedIndex++);\n } while (updatedIndex < end);\n\n _currentIndex = updatedIndex;\n }\n _afterTokenTransfers(address(0), to, startTokenId, quantity);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) private {\n TokenOwnership memory prevOwnership = _ownershipOf(tokenId);\n\n if (prevOwnership.addr != from) revert TransferFromIncorrectOwner();\n\n bool isApprovedOrOwner = (_msgSender() == from ||\n isApprovedForAll(from, _msgSender()) ||\n getApproved(tokenId) == _msgSender());\n\n if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();\n if (to == address(0)) revert TransferToZeroAddress();\n\n _beforeTokenTransfers(from, to, tokenId, 1);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId, from);\n\n // Underflow of the sender's balance is impossible because we check for\n // ownership above and the recipient's balance can't realistically overflow.\n // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.\n unchecked {\n _addressData[from].balance -= 1;\n _addressData[to].balance += 1;\n\n TokenOwnership storage currSlot = _ownerships[tokenId];\n currSlot.addr = to;\n currSlot.startTimestamp = uint64(block.timestamp);\n\n // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.\n // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.\n uint256 nextTokenId = tokenId + 1;\n TokenOwnership storage nextSlot = _ownerships[nextTokenId];\n if (nextSlot.addr == address(0)) {\n // This will suffice for checking _exists(nextTokenId),\n // as a burned slot cannot contain the zero address.\n if (nextTokenId != _currentIndex) {\n nextSlot.addr = from;\n nextSlot.startTimestamp = prevOwnership.startTimestamp;\n }\n }\n }\n\n emit Transfer(from, to, tokenId);\n _afterTokenTransfers(from, to, tokenId, 1);\n }\n\n /**\n * @dev Equivalent to `_burn(tokenId, false)`.\n */\n function _burn(uint256 tokenId) internal virtual {\n _burn(tokenId, false);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId, bool approvalCheck) internal virtual {\n TokenOwnership memory prevOwnership = _ownershipOf(tokenId);\n\n address from = prevOwnership.addr;\n\n if (approvalCheck) {\n bool isApprovedOrOwner = (_msgSender() == from ||\n isApprovedForAll(from, _msgSender()) ||\n getApproved(tokenId) == _msgSender());\n\n if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();\n }\n\n _beforeTokenTransfers(from, address(0), tokenId, 1);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId, from);\n\n // Underflow of the sender's balance is impossible because we check for\n // ownership above and the recipient's balance can't realistically overflow.\n // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.\n unchecked {\n AddressData storage addressData = _addressData[from];\n addressData.balance -= 1;\n addressData.numberBurned += 1;\n\n // Keep track of who burned the token, and the timestamp of burning.\n TokenOwnership storage currSlot = _ownerships[tokenId];\n currSlot.addr = from;\n currSlot.startTimestamp = uint64(block.timestamp);\n currSlot.burned = true;\n\n // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it.\n // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.\n uint256 nextTokenId = tokenId + 1;\n TokenOwnership storage nextSlot = _ownerships[nextTokenId];\n if (nextSlot.addr == address(0)) {\n // This will suffice for checking _exists(nextTokenId),\n // as a burned slot cannot contain the zero address.\n if (nextTokenId != _currentIndex) {\n nextSlot.addr = from;\n nextSlot.startTimestamp = prevOwnership.startTimestamp;\n }\n }\n }\n\n emit Transfer(from, address(0), tokenId);\n _afterTokenTransfers(from, address(0), tokenId, 1);\n\n // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.\n unchecked {\n _burnCounter++;\n }\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */\n function _approve(\n address to,\n uint256 tokenId,\n address owner\n ) private {\n _tokenApprovals[tokenId] = to;\n emit Approval(owner, to, tokenId);\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkContractOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) private returns (bool) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n return retval == IERC721Receiver(to).onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert TransferToNonERC721ReceiverImplementer();\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n }\n\n /**\n * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting.\n * And also called before burning one token.\n *\n * startTokenId - the first token id to be transferred\n * quantity - the amount to be transferred\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, `tokenId` will be burned by `from`.\n * - `from` and `to` are never both zero.\n */\n function _beforeTokenTransfers(\n address from,\n address to,\n uint256 startTokenId,\n uint256 quantity\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes\n * minting.\n * And also called after one token has been burned.\n *\n * startTokenId - the first token id to be transferred\n * quantity - the amount to be transferred\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been\n * transferred to `to`.\n * - When `from` is zero, `tokenId` has been minted for `to`.\n * - When `to` is zero, `tokenId` has been burned by `from`.\n * - `from` and `to` are never both zero.\n */\n function _afterTokenTransfers(\n address from,\n address to,\n uint256 startTokenId,\n uint256 quantity\n ) internal virtual {}\n}\n"
},
"erc721a/contracts/IERC721A.sol": {
"content": "// SPDX-License-Identifier: MIT\n// ERC721A Contracts v3.3.0\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\nimport '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol';\n\n/**\n * @dev Interface of an ERC721A compliant contract.\n */\ninterface IERC721A is IERC721, IERC721Metadata {\n /**\n * The caller must own the token or be an approved operator.\n */\n error ApprovalCallerNotOwnerNorApproved();\n\n /**\n * The token does not exist.\n */\n error ApprovalQueryForNonexistentToken();\n\n /**\n * The caller cannot approve to their own address.\n */\n error ApproveToCaller();\n\n /**\n * The caller cannot approve to the current owner.\n */\n error ApprovalToCurrentOwner();\n\n /**\n * Cannot query the balance for the zero address.\n */\n error BalanceQueryForZeroAddress();\n\n /**\n * Cannot mint to the zero address.\n */\n error MintToZeroAddress();\n\n /**\n * The quantity of tokens minted must be more than zero.\n */\n error MintZeroQuantity();\n\n /**\n * The token does not exist.\n */\n error OwnerQueryForNonexistentToken();\n\n /**\n * The caller must own the token or be an approved operator.\n */\n error TransferCallerNotOwnerNorApproved();\n\n /**\n * The token must be owned by `from`.\n */\n error TransferFromIncorrectOwner();\n\n /**\n * Cannot safely transfer to a contract that does not implement the ERC721Receiver interface.\n */\n error TransferToNonERC721ReceiverImplementer();\n\n /**\n * Cannot transfer to the zero address.\n */\n error TransferToZeroAddress();\n\n /**\n * The token does not exist.\n */\n error URIQueryForNonexistentToken();\n\n // Compiler will pack this into a single 256bit word.\n struct TokenOwnership {\n // The address of the owner.\n address addr;\n // Keeps track of the start time of ownership with minimal overhead for tokenomics.\n uint64 startTimestamp;\n // Whether the token has been burned.\n bool burned;\n }\n\n // Compiler will pack this into a single 256bit word.\n struct AddressData {\n // Realistically, 2**64-1 is more than enough.\n uint64 balance;\n // Keeps track of mint count with minimal overhead for tokenomics.\n uint64 numberMinted;\n // Keeps track of burn count with minimal overhead for tokenomics.\n uint64 numberBurned;\n // For miscellaneous variable(s) pertaining to the address\n // (e.g. number of whitelist mint slots used).\n // If there are multiple variables, please pack them into a uint64.\n uint64 aux;\n }\n\n /**\n * @dev Returns the total amount of tokens stored by the contract.\n * \n * Burned tokens are calculated here, use `_totalMinted()` if you want to count just minted tokens.\n */\n function totalSupply() external view returns (uint256);\n}\n"
},
"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n"
},
"@openzeppelin/contracts/token/ERC721/IERC721.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
},
"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": ["ast"]
}
}
}
}