// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^0.8.0;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 2 of 7: ERC1155.sol
// SPDX-License-Identifier: AGPL-3.0-onlypragmasolidity >=0.8.0;/// @notice Minimalist and gas efficient standard ERC1155 implementation./// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)abstractcontractERC1155{
/*///////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/eventTransferSingle(addressindexed operator,
addressindexedfrom,
addressindexed to,
uint256 id,
uint256 amount
);
eventTransferBatch(addressindexed operator,
addressindexedfrom,
addressindexed to,
uint256[] ids,
uint256[] amounts
);
eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
eventURI(string value, uint256indexed id);
/*///////////////////////////////////////////////////////////////
ERC1155 STORAGE
//////////////////////////////////////////////////////////////*/mapping(address=>mapping(uint256=>uint256)) public balanceOf;
mapping(address=>mapping(address=>bool)) public isApprovedForAll;
/*///////////////////////////////////////////////////////////////
METADATA LOGIC
//////////////////////////////////////////////////////////////*/functionuri(uint256 id) publicviewvirtualreturns (stringmemory);
/*///////////////////////////////////////////////////////////////
ERC1155 LOGIC
//////////////////////////////////////////////////////////////*/functionsetApprovalForAll(address operator, bool approved) publicvirtual{
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
functionsafeTransferFrom(addressfrom,
address to,
uint256 id,
uint256 amount,
bytesmemory data
) publicvirtual{
require(msg.sender==from|| isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, from, to, id, amount);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
functionsafeBatchTransferFrom(addressfrom,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) publicvirtual{
uint256 idsLength = ids.length; // Saves MLOADs.require(idsLength == amounts.length, "LENGTH_MISMATCH");
require(msg.sender==from|| isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
for (uint256 i =0; i < idsLength; ) {
uint256 id = ids[i];
uint256 amount = amounts[i];
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
// An array can't have a total length// larger than the max uint256 value.unchecked {
i++;
}
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
functionbalanceOfBatch(address[] memory owners, uint256[] memory ids)
publicviewvirtualreturns (uint256[] memory balances)
{
uint256 ownersLength = owners.length; // Saves MLOADs.require(ownersLength == ids.length, "LENGTH_MISMATCH");
balances =newuint256[](owners.length);
// Unchecked because the only math done is incrementing// the array index counter which cannot possibly overflow.unchecked {
for (uint256 i =0; i < ownersLength; i++) {
balances[i] = balanceOf[owners[i]][ids[i]];
}
}
}
/*///////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/functionsupportsInterface(bytes4 interfaceId) publicpurevirtualreturns (bool) {
return
interfaceId ==0x01ffc9a7||// ERC165 Interface ID for ERC165
interfaceId ==0xd9b67a26||// ERC165 Interface ID for ERC1155
interfaceId ==0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
}
/*///////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/function_mint(address to,
uint256 id,
uint256 amount,
bytesmemory data
) internal{
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, address(0), to, id, amount);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
function_batchMint(address to,
uint256[] memory ids,
uint256[] memory amounts,
bytesmemory data
) internal{
uint256 idsLength = ids.length; // Saves MLOADs.require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i =0; i < idsLength; ) {
balanceOf[to][ids[i]] += amounts[i];
// An array can't have a total length// larger than the max uint256 value.unchecked {
i++;
}
}
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
require(
to.code.length==0
? to !=address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
function_batchBurn(addressfrom,
uint256[] memory ids,
uint256[] memory amounts
) internal{
uint256 idsLength = ids.length; // Saves MLOADs.require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i =0; i < idsLength; ) {
balanceOf[from][ids[i]] -= amounts[i];
// An array can't have a total length// larger than the max uint256 value.unchecked {
i++;
}
}
emit TransferBatch(msg.sender, from, address(0), ids, amounts);
}
function_burn(addressfrom,
uint256 id,
uint256 amount
) internal{
balanceOf[from][id] -= amount;
emit TransferSingle(msg.sender, from, address(0), id, amount);
}
}
/// @notice A generic interface for a contract which properly accepts ERC1155 tokens./// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)interfaceERC1155TokenReceiver{
functiononERC1155Received(address operator,
addressfrom,
uint256 id,
uint256 amount,
bytescalldata data
) externalreturns (bytes4);
functiononERC1155BatchReceived(address operator,
addressfrom,
uint256[] calldata ids,
uint256[] calldata amounts,
bytescalldata data
) externalreturns (bytes4);
}
Contract Source Code
File 3 of 7: ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-onlypragmasolidity >=0.8.0;/// @notice Modern, minimalist, and gas efficient ERC-721 implementation./// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)/// @dev Note that balanceOf does not revert if passed the zero address, in defiance of the ERC.abstractcontractERC721{
/*///////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed id);
eventApproval(addressindexed owner, addressindexed spender, uint256indexed id);
eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/*///////////////////////////////////////////////////////////////
METADATA STORAGE/LOGIC
//////////////////////////////////////////////////////////////*/stringpublic name;
stringpublic symbol;
functiontokenURI(uint256 id) publicviewvirtualreturns (stringmemory);
/*///////////////////////////////////////////////////////////////
ERC721 STORAGE
//////////////////////////////////////////////////////////////*/uint256public totalSupply;
mapping(address=>uint256) public balanceOf;
mapping(uint256=>address) public ownerOf;
mapping(uint256=>address) public getApproved;
mapping(address=>mapping(address=>bool)) public isApprovedForAll;
/*///////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/constructor(stringmemory _name, stringmemory _symbol) {
name = _name;
symbol = _symbol;
}
/*///////////////////////////////////////////////////////////////
ERC721 LOGIC
//////////////////////////////////////////////////////////////*/functionapprove(address spender, uint256 id) publicvirtual{
address owner = ownerOf[id];
require(msg.sender== owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
getApproved[id] = spender;
emit Approval(owner, spender, id);
}
functionsetApprovalForAll(address operator, bool approved) publicvirtual{
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
functiontransferFrom(addressfrom,
address to,
uint256 id
) publicvirtual{
require(from== ownerOf[id], "WRONG_FROM");
require(to !=address(0), "INVALID_RECIPIENT");
require(
msg.sender==from||msg.sender== getApproved[id] || isApprovedForAll[from][msg.sender],
"NOT_AUTHORIZED"
);
// Underflow of the sender's balance is impossible because we check for// ownership above and the recipient's balance can't realistically overflow.unchecked {
balanceOf[from]--;
balanceOf[to]++;
}
ownerOf[id] = to;
delete getApproved[id];
emit Transfer(from, to, id);
}
functionsafeTransferFrom(addressfrom,
address to,
uint256 id
) publicvirtual{
transferFrom(from, to, id);
require(
to.code.length==0||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
functionsafeTransferFrom(addressfrom,
address to,
uint256 id,
bytesmemory data
) publicvirtual{
transferFrom(from, to, id);
require(
to.code.length==0||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
/*///////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/functionsupportsInterface(bytes4 interfaceId) publicpurevirtualreturns (bool) {
return
interfaceId ==0x01ffc9a7||// ERC165 Interface ID for ERC165
interfaceId ==0x80ac58cd||// ERC165 Interface ID for ERC721
interfaceId ==0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
}
/*///////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/function_mint(address to, uint256 id) internalvirtual{
require(to !=address(0), "INVALID_RECIPIENT");
require(ownerOf[id] ==address(0), "ALREADY_MINTED");
// Counter overflow is incredibly unrealistic.unchecked {
totalSupply++;
balanceOf[to]++;
}
ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function_burn(uint256 id) internalvirtual{
address owner = ownerOf[id];
require(ownerOf[id] !=address(0), "NOT_MINTED");
// Ownership check above ensures no underflow.unchecked {
totalSupply--;
balanceOf[owner]--;
}
delete ownerOf[id];
delete getApproved[id];
emit Transfer(owner, address(0), id);
}
/*///////////////////////////////////////////////////////////////
INTERNAL SAFE MINT LOGIC
//////////////////////////////////////////////////////////////*/function_safeMint(address to, uint256 id) internalvirtual{
_mint(to, id);
require(
to.code.length==0||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function_safeMint(address to,
uint256 id,
bytesmemory data
) internalvirtual{
_mint(to, id);
require(
to.code.length==0||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
}
/// @notice A generic interface for a contract which properly accepts ERC721 tokens./// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)interfaceERC721TokenReceiver{
functiononERC721Received(address operator,
addressfrom,
uint256 id,
bytescalldata data
) externalreturns (bytes4);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)pragmasolidity ^0.8.0;import"./Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 6 of 7: Pixelmon.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.14;import"./ERC721.sol";
import"./Ownable.sol";
import"./Strings.sol";
/// @notice Thrown when completing the transaction results in overallocation of Pixelmon.errorMintedOut();
/// @notice Thrown when the dutch auction phase has not yet started, or has already ended.errorAuctionNotStarted();
/// @notice Thrown when the user has already minted two Pixelmon in the dutch auction.errorMintingTooMany();
/// @notice Thrown when the value of the transaction is not enough for the current dutch auction or mintlist price.errorValueTooLow();
/// @notice Thrown when the user is not on the mintlist.errorNotMintlisted();
/// @notice Thrown when the caller is not the EvolutionSerum contract, and is trying to evolve a Pixelmon.errorUnauthorizedEvolution();
/// @notice Thrown when an invalid evolution is given by the EvolutionSerum contract.errorUnknownEvolution();
// ______ __ __ __ ______ __ __ __ ______ __ __ // /\ == \ /\ \ /\_\_\_\ /\ ___\ /\ \ /\ "-./ \ /\ __ \ /\ "-.\ \ // \ \ _-/ \ \ \ \/_/\_\/_ \ \ __\ \ \ \____ \ \ \-./\ \ \ \ \/\ \ \ \ \-. \ // \ \_\ \ \_\ /\_\/\_\ \ \_____\ \ \_____\ \ \_\ \ \_\ \ \_____\ \ \_\\"\_\ // \/_/ \/_/ \/_/\/_/ \/_____/ \/_____/ \/_/ \/_/ \/_____/ \/_/ \/_/ ///// @title Generation 1 Pixelmon NFTs/// @author delta devs (https://www.twitter.com/deltadevelopers)contractPixelmonisERC721, Ownable{
usingStringsforuint256;
/*///////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*//// @dev Determines the order of the species for each tokenId, mechanism for choosing starting index explained post mint, explanation hash: acb427e920bde46de95103f14b8e57798a603abcf87ff9d4163e5f61c6a56881.uintconstantpublic provenanceHash =0x9912e067bd3802c3b007ce40b6c125160d2ccb5352d199e20c092fdc17af8057;
/// @dev Sole receiver of collected contract funds, and receiver of 330 Pixelmon in the constructor.addressconstant gnosisSafeAddress =0xF6BD9Fc094F7aB74a846E5d82a822540EE6c6971;
/// @dev 7750, plus 330 for the Pixelmon Gnosis Safeuintconstant auctionSupply =7750+330;
/// @dev The offsets are the tokenIds that the corresponding evolution stage will begin minting at.uintconstant secondEvolutionOffset =10005;
uintconstant thirdEvolutionOffset = secondEvolutionOffset +4013;
uintconstant fourthEvolutionOffset = thirdEvolutionOffset +1206;
/*///////////////////////////////////////////////////////////////
EVOLUTIONARY STORAGE
//////////////////////////////////////////////////////////////*//// @dev The next tokenID to be minted for each of the evolution stagesuint secondEvolutionSupply =0;
uint thirdEvolutionSupply =0;
uint fourthEvolutionSupply =0;
/// @notice The address of the contract permitted to mint evolved Pixelmon.addresspublic serumContract;
/// @notice Returns true if the user is on the mintlist, if they have not already minted.mapping(address=>bool) public mintlisted;
/*///////////////////////////////////////////////////////////////
AUCTION STORAGE
//////////////////////////////////////////////////////////////*//// @notice Starting price of the auction.uint256constantpublic auctionStartPrice =3ether;
/// @notice Unix Timestamp of the start of the auction./// @dev Monday, February 7th 2022, 13:00:00 converted to 1644256800 (GMT -5)uint256constantpublic auctionStartTime =1644256800;
/// @notice Current mintlist price, which will be updated after the end of the auction phase./// @dev We started with signatures, then merkle tree, but landed on mapping to reduce USER gas fees.uint256public mintlistPrice =0.75ether;
/*///////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/stringpublic baseURI;
/*///////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*//// @notice Deploys the contract, minting 330 Pixelmon to the Gnosis Safe and setting the initial metadata URI.constructor(stringmemory _baseURI) ERC721("Pixelmon", "PXLMN") {
baseURI = _baseURI;
unchecked {
balanceOf[gnosisSafeAddress] +=330;
totalSupply +=330;
for (uint256 i =0; i <330; i++) {
ownerOf[i] = gnosisSafeAddress;
emit Transfer(address(0), gnosisSafeAddress, i);
}
}
}
/*///////////////////////////////////////////////////////////////
METADATA LOGIC
//////////////////////////////////////////////////////////////*//// @notice Allows the contract deployer to set the metadata URI./// @param _baseURI The new metadata URI.functionsetBaseURI(stringmemory _baseURI) publiconlyOwner{
baseURI = _baseURI;
}
functiontokenURI(uint256 id) publicviewoverridereturns (stringmemory) {
returnstring(abi.encodePacked(baseURI, id.toString()));
}
/*///////////////////////////////////////////////////////////////
DUTCH AUCTION LOGIC
//////////////////////////////////////////////////////////////*//// @notice Calculates the auction price with the accumulated rate deduction since the auction's begin/// @return The auction price at the current time, or 0 if the deductions are greater than the auction's start price.functionvalidCalculatedTokenPrice() privateviewreturns (uint) {
uint priceReduction = ((block.timestamp- auctionStartTime) /10minutes) *0.1ether;
return auctionStartPrice >= priceReduction ? (auctionStartPrice - priceReduction) : 0;
}
/// @notice Calculates the current dutch auction price, given accumulated rate deductions and a minimum price./// @return The current dutch auction pricefunctiongetCurrentTokenPrice() publicviewreturns (uint256) {
return max(validCalculatedTokenPrice(), 0.2ether);
}
/// @notice Purchases a Pixelmon NFT in the dutch auction/// @param mintingTwo True if the user is minting two Pixelmon, otherwise false./// @dev balanceOf is fine, team is aware and accepts that transferring out and repurchasing can be done, even by contracts. functionauction(bool mintingTwo) publicpayable{
if(block.timestamp< auctionStartTime ||block.timestamp> auctionStartTime +1days) revert AuctionNotStarted();
uint count = mintingTwo ? 2 : 1;
uint price = getCurrentTokenPrice();
if(totalSupply + count > auctionSupply) revert MintedOut();
if(balanceOf[msg.sender] + count >2) revert MintingTooMany();
if(msg.value< price * count) revert ValueTooLow();
mintingTwo ? _mintTwo(msg.sender) : _mint(msg.sender, totalSupply);
}
/// @notice Mints two Pixelmons to an address/// @param to Receiver of the two newly minted NFTs/// @dev errors taken from super._mintfunction_mintTwo(address to) internal{
require(to !=address(0), "INVALID_RECIPIENT");
require(ownerOf[totalSupply] ==address(0), "ALREADY_MINTED");
uint currentId = totalSupply;
/// @dev unchecked because no arithmetic can overflowunchecked {
totalSupply +=2;
balanceOf[to] +=2;
ownerOf[currentId] = to;
ownerOf[currentId +1] = to;
emit Transfer(address(0), to, currentId);
emit Transfer(address(0), to, currentId +1);
}
}
/*///////////////////////////////////////////////////////////////
MINTLIST MINT LOGIC
//////////////////////////////////////////////////////////////*//// @notice Allows the contract deployer to set the price of the mintlist. To be called before uploading the mintlist./// @param price The price in wei of a Pixelmon NFT to be purchased from the mintlist supply.functionsetMintlistPrice(uint256 price) publiconlyOwner{
mintlistPrice = price;
}
/// @notice Allows the contract deployer to add a single address to the mintlist./// @param user Address to be added to the mintlist.functionmintlistUser(address user) publiconlyOwner{
mintlisted[user] =true;
}
/// @notice Allows the contract deployer to add a list of addresses to the mintlist./// @param users Addresses to be added to the mintlist.functionmintlistUsers(address[] calldata users) publiconlyOwner{
for (uint256 i =0; i < users.length; i++) {
mintlisted[users[i]] =true;
}
}
/// @notice Purchases a Pixelmon NFT from the mintlist supply/// @dev We do not check if auction is over because the mintlist will be uploaded after the auction. functionmintlistMint() publicpayable{
if(totalSupply >= secondEvolutionOffset) revert MintedOut();
if(!mintlisted[msg.sender]) revert NotMintlisted();
if(msg.value< mintlistPrice) revert ValueTooLow();
mintlisted[msg.sender] =false;
_mint(msg.sender, totalSupply);
}
/// @notice Withdraws collected funds to the Gnosis Safe addressfunctionwithdraw() publiconlyOwner{
(bool success, ) = gnosisSafeAddress.call{value: address(this).balance}("");
require(success);
}
/*///////////////////////////////////////////////////////////////
ROLL OVER LOGIC
//////////////////////////////////////////////////////////////*//// @notice Allows the contract deployer to airdrop Pixelmon to a list of addresses, in case the auction doesn't mint out/// @param addresses Array of addresses to receive PixelmonfunctionrollOverPixelmons(address[] calldata addresses) publiconlyOwner{
if(totalSupply + addresses.length> secondEvolutionOffset) revert MintedOut();
for (uint256 i =0; i < addresses.length; i++) {
_mint(msg.sender, totalSupply);
}
}
/*///////////////////////////////////////////////////////////////
EVOLUTIONARY LOGIC
//////////////////////////////////////////////////////////////*//// @notice Sets the address of the contract permitted to call mintEvolvedPixelmon/// @param _serumContract The address of the EvolutionSerum contractfunctionsetSerumContract(address _serumContract) publiconlyOwner{
serumContract = _serumContract;
}
/// @notice Mints an evolved Pixelmon/// @param receiver Receiver of the evolved Pixelmon/// @param evolutionStage The evolution (2-4) that the Pixelmon is undergoingfunctionmintEvolvedPixelmon(address receiver, uint evolutionStage) publicpayable{
if(msg.sender!= serumContract) revert UnauthorizedEvolution();
if (evolutionStage ==2) {
if(secondEvolutionSupply >=4013) revert MintedOut();
_mint(receiver, secondEvolutionOffset + secondEvolutionSupply);
unchecked {
secondEvolutionSupply++;
}
} elseif (evolutionStage ==3) {
if(thirdEvolutionSupply >=1206) revert MintedOut();
_mint(receiver, thirdEvolutionOffset + thirdEvolutionSupply);
unchecked {
thirdEvolutionSupply++;
}
} elseif (evolutionStage ==4) {
if(fourthEvolutionSupply >=33) revert MintedOut();
_mint(receiver, fourthEvolutionOffset + fourthEvolutionSupply);
unchecked {
fourthEvolutionSupply++;
}
} else {
revert UnknownEvolution();
}
}
/*///////////////////////////////////////////////////////////////
UTILS
//////////////////////////////////////////////////////////////*//// @notice Returns the greater of two numbers.functionmax(uint256 a, uint256 b) internalpurereturns (uint256) {
return a >= b ? a : b;
}
}
Contract Source Code
File 7 of 7: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)pragmasolidity ^0.8.0;/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant _HEX_SYMBOLS ="0123456789abcdef";
uint8privateconstant _ADDRESS_LENGTH =20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
// Inspired by OraclizeAPI's implementation - MIT licence// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.solif (value ==0) {
return"0";
}
uint256 temp = value;
uint256 digits;
while (temp !=0) {
digits++;
temp /=10;
}
bytesmemory buffer =newbytes(digits);
while (value !=0) {
digits -=1;
buffer[digits] =bytes1(uint8(48+uint256(value %10)));
value /=10;
}
returnstring(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
if (value ==0) {
return"0x00";
}
uint256 temp = value;
uint256 length =0;
while (temp !=0) {
length++;
temp >>=8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = _HEX_SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/functiontoHexString(address addr) internalpurereturns (stringmemory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}