ETH Price: $2,667.98 (+1.47%)

Transaction Decoder

Block:
15514531 at Sep-11-2022 11:16:09 AM +UTC
Transaction Fee:
0.000208596094284808 ETH $0.56
Gas Used:
46,031 Gas / 4.531643768 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
0x5c0b862b...8fC50E227
0.2911166023930511 Eth
Nonce: 281
0.290908006298766292 Eth
Nonce: 282
0.000208596094284808
(F2Pool Old)
1,681.870104280705098502 Eth1,681.870173327205098502 Eth0.0000690465
0xADaE0Dda...041D13220

Execution Trace

EvolutionSerum.setApprovalForAll( operator=0x1E0049783F008A0085193E00003D00cd54003c71, approved=True )
{"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"},"ERC1155.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity \u003e=0.8.0;\n\n/// @notice Minimalist and gas efficient standard ERC1155 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)\nabstract contract ERC1155 {\n    /*///////////////////////////////////////////////////////////////\n                                EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event TransferSingle(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256 id,\n        uint256 amount\n    );\n\n    event TransferBatch(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256[] ids,\n        uint256[] amounts\n    );\n\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    event URI(string value, uint256 indexed id);\n\n    /*///////////////////////////////////////////////////////////////\n                            ERC1155 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    mapping(address =\u003e mapping(uint256 =\u003e uint256)) public balanceOf;\n\n    mapping(address =\u003e mapping(address =\u003e bool)) public isApprovedForAll;\n\n    /*///////////////////////////////////////////////////////////////\n                             METADATA LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function uri(uint256 id) public view virtual returns (string memory);\n\n    /*///////////////////////////////////////////////////////////////\n                             ERC1155 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function setApprovalForAll(address operator, bool approved) public virtual {\n        isApprovedForAll[msg.sender][operator] = approved;\n\n        emit ApprovalForAll(msg.sender, operator, approved);\n    }\n\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) public virtual {\n        require(msg.sender == from || isApprovedForAll[from][msg.sender], \"NOT_AUTHORIZED\");\n\n        balanceOf[from][id] -= amount;\n        balanceOf[to][id] += amount;\n\n        emit TransferSingle(msg.sender, from, to, id, amount);\n\n        require(\n            to.code.length == 0\n                ? to != address(0)\n                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==\n                    ERC1155TokenReceiver.onERC1155Received.selector,\n            \"UNSAFE_RECIPIENT\"\n        );\n    }\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 {\n        uint256 idsLength = ids.length; // Saves MLOADs.\n\n        require(idsLength == amounts.length, \"LENGTH_MISMATCH\");\n\n        require(msg.sender == from || isApprovedForAll[from][msg.sender], \"NOT_AUTHORIZED\");\n\n        for (uint256 i = 0; i \u003c idsLength; ) {\n            uint256 id = ids[i];\n            uint256 amount = amounts[i];\n\n            balanceOf[from][id] -= amount;\n            balanceOf[to][id] += amount;\n\n            // An array can\u0027t have a total length\n            // larger than the max uint256 value.\n            unchecked {\n                i++;\n            }\n        }\n\n        emit TransferBatch(msg.sender, from, to, ids, amounts);\n\n        require(\n            to.code.length == 0\n                ? to != address(0)\n                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==\n                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,\n            \"UNSAFE_RECIPIENT\"\n        );\n    }\n\n    function balanceOfBatch(address[] memory owners, uint256[] memory ids)\n        public\n        view\n        virtual\n        returns (uint256[] memory balances)\n    {\n        uint256 ownersLength = owners.length; // Saves MLOADs.\n\n        require(ownersLength == ids.length, \"LENGTH_MISMATCH\");\n\n        balances = new uint256[](owners.length);\n\n        // Unchecked because the only math done is incrementing\n        // the array index counter which cannot possibly overflow.\n        unchecked {\n            for (uint256 i = 0; i \u003c ownersLength; i++) {\n                balances[i] = balanceOf[owners[i]][ids[i]];\n            }\n        }\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                              ERC165 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {\n        return\n            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165\n            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155\n            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        INTERNAL MINT/BURN LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _mint(\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) internal {\n        balanceOf[to][id] += amount;\n\n        emit TransferSingle(msg.sender, address(0), to, id, amount);\n\n        require(\n            to.code.length == 0\n                ? to != address(0)\n                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==\n                    ERC1155TokenReceiver.onERC1155Received.selector,\n            \"UNSAFE_RECIPIENT\"\n        );\n    }\n\n    function _batchMint(\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal {\n        uint256 idsLength = ids.length; // Saves MLOADs.\n\n        require(idsLength == amounts.length, \"LENGTH_MISMATCH\");\n\n        for (uint256 i = 0; i \u003c idsLength; ) {\n            balanceOf[to][ids[i]] += amounts[i];\n\n            // An array can\u0027t have a total length\n            // larger than the max uint256 value.\n            unchecked {\n                i++;\n            }\n        }\n\n        emit TransferBatch(msg.sender, address(0), to, ids, amounts);\n\n        require(\n            to.code.length == 0\n                ? to != address(0)\n                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==\n                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,\n            \"UNSAFE_RECIPIENT\"\n        );\n    }\n\n    function _batchBurn(\n        address from,\n        uint256[] memory ids,\n        uint256[] memory amounts\n    ) internal {\n        uint256 idsLength = ids.length; // Saves MLOADs.\n\n        require(idsLength == amounts.length, \"LENGTH_MISMATCH\");\n\n        for (uint256 i = 0; i \u003c idsLength; ) {\n            balanceOf[from][ids[i]] -= amounts[i];\n\n            // An array can\u0027t have a total length\n            // larger than the max uint256 value.\n            unchecked {\n                i++;\n            }\n        }\n\n        emit TransferBatch(msg.sender, from, address(0), ids, amounts);\n    }\n\n    function _burn(\n        address from,\n        uint256 id,\n        uint256 amount\n    ) internal {\n        balanceOf[from][id] -= amount;\n\n        emit TransferSingle(msg.sender, from, address(0), id, amount);\n    }\n}\n\n/// @notice A generic interface for a contract which properly accepts ERC1155 tokens.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)\ninterface ERC1155TokenReceiver {\n    function onERC1155Received(\n        address operator,\n        address from,\n        uint256 id,\n        uint256 amount,\n        bytes calldata data\n    ) external returns (bytes4);\n\n    function onERC1155BatchReceived(\n        address operator,\n        address from,\n        uint256[] calldata ids,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"},"ERC721.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity \u003e=0.8.0;\n\n/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\n/// @dev Note that balanceOf does not revert if passed the zero address, in defiance of the ERC.\nabstract contract ERC721 {\n    /*///////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event Transfer(address indexed from, address indexed to, uint256 indexed id);\n\n    event Approval(address indexed owner, address indexed spender, uint256 indexed id);\n\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /*///////////////////////////////////////////////////////////////\n                          METADATA STORAGE/LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    string public name;\n\n    string public symbol;\n\n    function tokenURI(uint256 id) public view virtual returns (string memory);\n\n    /*///////////////////////////////////////////////////////////////\n                            ERC721 STORAGE                        \n    //////////////////////////////////////////////////////////////*/\n\n    uint256 public totalSupply;\n\n    mapping(address =\u003e uint256) public balanceOf;\n\n    mapping(uint256 =\u003e address) public ownerOf;\n\n    mapping(uint256 =\u003e address) public getApproved;\n\n    mapping(address =\u003e mapping(address =\u003e bool)) public isApprovedForAll;\n\n    /*///////////////////////////////////////////////////////////////\n                              CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(string memory _name, string memory _symbol) {\n        name = _name;\n        symbol = _symbol;\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                              ERC721 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function approve(address spender, uint256 id) public virtual {\n        address owner = ownerOf[id];\n\n        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], \"NOT_AUTHORIZED\");\n\n        getApproved[id] = spender;\n\n        emit Approval(owner, spender, id);\n    }\n\n    function setApprovalForAll(address operator, bool approved) public virtual {\n        isApprovedForAll[msg.sender][operator] = approved;\n\n        emit ApprovalForAll(msg.sender, operator, approved);\n    }\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 id\n    ) public virtual {\n        require(from == ownerOf[id], \"WRONG_FROM\");\n\n        require(to != address(0), \"INVALID_RECIPIENT\");\n\n        require(\n            msg.sender == from || msg.sender == getApproved[id] || isApprovedForAll[from][msg.sender],\n            \"NOT_AUTHORIZED\"\n        );\n\n        // Underflow of the sender\u0027s balance is impossible because we check for\n        // ownership above and the recipient\u0027s balance can\u0027t realistically overflow.\n        unchecked {\n            balanceOf[from]--;\n\n            balanceOf[to]++;\n        }\n\n        ownerOf[id] = to;\n\n        delete getApproved[id];\n\n        emit Transfer(from, to, id);\n    }\n\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id\n    ) public virtual {\n        transferFrom(from, to, id);\n\n        require(\n            to.code.length == 0 ||\n                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, \"\") ==\n                ERC721TokenReceiver.onERC721Received.selector,\n            \"UNSAFE_RECIPIENT\"\n        );\n    }\n\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        bytes memory data\n    ) public virtual {\n        transferFrom(from, to, id);\n\n        require(\n            to.code.length == 0 ||\n                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==\n                ERC721TokenReceiver.onERC721Received.selector,\n            \"UNSAFE_RECIPIENT\"\n        );\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                              ERC165 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {\n        return\n            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165\n            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721\n            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                       INTERNAL MINT/BURN LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _mint(address to, uint256 id) internal virtual {\n        require(to != address(0), \"INVALID_RECIPIENT\");\n\n        require(ownerOf[id] == address(0), \"ALREADY_MINTED\");\n\n        // Counter overflow is incredibly unrealistic.\n        unchecked {\n            totalSupply++;\n\n            balanceOf[to]++;\n        }\n\n        ownerOf[id] = to;\n\n        emit Transfer(address(0), to, id);\n    }\n\n    function _burn(uint256 id) internal virtual {\n        address owner = ownerOf[id];\n\n        require(ownerOf[id] != address(0), \"NOT_MINTED\");\n\n        // Ownership check above ensures no underflow.\n        unchecked {\n            totalSupply--;\n\n            balanceOf[owner]--;\n        }\n\n        delete ownerOf[id];\n\n        delete getApproved[id];\n\n        emit Transfer(owner, address(0), id);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                       INTERNAL SAFE MINT LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _safeMint(address to, uint256 id) internal virtual {\n        _mint(to, id);\n\n        require(\n            to.code.length == 0 ||\n                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, \"\") ==\n                ERC721TokenReceiver.onERC721Received.selector,\n            \"UNSAFE_RECIPIENT\"\n        );\n    }\n\n    function _safeMint(\n        address to,\n        uint256 id,\n        bytes memory data\n    ) internal virtual {\n        _mint(to, id);\n\n        require(\n            to.code.length == 0 ||\n                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==\n                ERC721TokenReceiver.onERC721Received.selector,\n            \"UNSAFE_RECIPIENT\"\n        );\n    }\n}\n\n/// @notice A generic interface for a contract which properly accepts ERC721 tokens.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\ninterface ERC721TokenReceiver {\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 id,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"},"EvolutionSerum.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.14;\n\nimport \"./Pixelmon.sol\";\nimport \"./ERC721.sol\";\nimport \"./ERC1155.sol\";\nimport \"./Ownable.sol\";\nimport \"./Strings.sol\";\n\nerror InvalidNonce();\nerror InvalidOwner();\nerror InvalidEvolution();\nerror InvalidVoucher();\nerror NotEnoughEther();\n\ncontract EvolutionSerum is ERC1155, Ownable, ERC1155TokenReceiver {\n    using Strings for uint256;\n\n    /*///////////////////////////////////////////////////////////////\n                               EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event Evolution(uint indexed tokenId, uint evolutionStage);\n\n    /*///////////////////////////////////////////////////////////////\n                               CONSTANTS\n    //////////////////////////////////////////////////////////////*/\n    \n    address constant public evolutionSigner = 0x00000001DEA29D000f2e99100C503bf1544Da95d;\n    address constant public gnosisSafeAddress = 0x813F10aBA9624D2f4b3130a1EcD26da2BB2d09D4;\n\n    string constant public name = \"Evolution Serum\";\n    string constant public symbol = \"ES\";\n\n    /*///////////////////////////////////////////////////////////////\n                               STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    Pixelmon creatures;\n\n    mapping(uint =\u003e uint) public serumPrices;\n    mapping(address =\u003e uint) public nonces;\n    mapping(bytes32 =\u003e bool) public usedVouchers;\n\n    string baseURI;\n\n    /*///////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(address creatureAddress, string memory _baseURI) {\n        creatures = Pixelmon(creatureAddress);\n        baseURI = _baseURI;\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                               MODIFIERS\n    //////////////////////////////////////////////////////////////*/\n\n    modifier correctNonce(uint nonce) {\n        if(nonce != nonces[msg.sender]) revert InvalidNonce();\n        nonces[msg.sender]++;\n        _;\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            METADATA LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function setBaseURI(string memory _baseURI) public onlyOwner {\n        baseURI = _baseURI;\n    }\n\n    function setSerumPrice(uint serumId, uint price) public onlyOwner {\n        serumPrices[serumId] = price;\n    }\n\n    function uri(uint256 id) public view override returns (string memory) {\n        return string(abi.encodePacked(baseURI, id.toString()));\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            MINTING LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function claim(uint serumId, uint count, bytes memory signature) public payable {\n        if(msg.value \u003c count * serumPrices[serumId]) revert NotEnoughEther();\n        if(!validMint(msg.sender, serumId, count, signature)) revert InvalidVoucher();\n        _mint(msg.sender, serumId, count, \"\");\n    }\n\n    function airdrop(uint serumId, address[] calldata users) public onlyOwner {\n        for (uint256 i = 0; i \u003c users.length; i++) {\n           _mint(users[i], serumId, 1, \"\"); \n        }\n    }\n\n    function ownerMint(uint id, uint amount, address receiver) public onlyOwner {\n        _mint(receiver, id, amount, \"\");\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            EVOLUTION LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function evolve(uint tokenId, uint serumId, uint nonce, uint evolutionStage, bytes memory signature) public correctNonce(nonce) {\n        if(creatures.ownerOf(tokenId) != msg.sender) revert InvalidOwner();\n        if(!validEvolution(msg.sender, serumId, tokenId, evolutionStage, nonce, signature)) revert InvalidEvolution();\n        _burn(msg.sender, serumId, 1);\n        creatures.mintEvolvedPixelmon(msg.sender, evolutionStage);\n        emit Evolution(tokenId, evolutionStage);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                                UTILS\n    //////////////////////////////////////////////////////////////*/\n\n    function validMint(address user, uint serumId, uint count, bytes memory signature) public returns (bool) {\n        bytes32 messageHash = keccak256(abi.encodePacked(user, serumId, count));\n        if(usedVouchers[messageHash]) return false;\n\n        usedVouchers[messageHash] = true;\n        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);\n        return recoverSigner(ethSignedMessageHash, signature) == evolutionSigner;\n    }\n\n    function validEvolution(address user, uint serumId, uint creatureId, uint evolutionStage, uint nonce, bytes memory signature)\n        public\n        pure\n        returns (bool)\n    {\n        bytes32 messageHash = keccak256(abi.encodePacked(user, serumId, creatureId, evolutionStage, nonce));\n        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);\n\n        return recoverSigner(ethSignedMessageHash, signature) == evolutionSigner;\n    }\n\n    function getEthSignedMessageHash(bytes32 _messageHash)\n        private\n        pure\n        returns (bytes32)\n    {\n        /*\n        Signature is produced by signing a keccak256 hash with the following format:\n        \"\\x19Ethereum Signed Message\\n\" + len(msg) + msg\n        */\n        return\n            keccak256(\n                abi.encodePacked(\n                    \"\\x19Ethereum Signed Message:\\n32\",\n                    _messageHash\n                )\n            );\n    }\n\n    function recoverSigner(\n        bytes32 _ethSignedMessageHash,\n        bytes memory _signature\n    ) private pure returns (address) {\n        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);\n        return ecrecover(_ethSignedMessageHash, v, r, s);\n    }\n\n    function splitSignature(bytes memory sig)\n        private\n        pure\n        returns (\n            bytes32 r,\n            bytes32 s,\n            uint8 v\n        )\n    {\n        require(sig.length == 65, \"sig invalid\");\n\n        assembly {\n            /*\n        First 32 bytes stores the length of the signature\n\n        add(sig, 32) = pointer of sig + 32\n        effectively, skips first 32 bytes of signature\n\n        mload(p) loads next 32 bytes starting at the memory address p into memory\n        */\n\n            // first 32 bytes, after the length prefix\n            r := mload(add(sig, 32))\n            // second 32 bytes\n            s := mload(add(sig, 64))\n            // final byte (first byte of the next 32 bytes)\n            v := byte(0, mload(add(sig, 96)))\n        }\n\n        // implicitly return (r, s, v)\n    }\n\n    /// @notice Withdraws collected funds to the Gnosis Safe address\n    function withdraw() public onlyOwner {\n        (bool success, ) = gnosisSafeAddress.call{value: address(this).balance}(\"\");\n        require(success);\n    }\n\n    function onERC1155Received(\n        address operator,\n        address from,\n        uint256 id,\n        uint256 amount,\n        bytes calldata data\n    ) external returns (bytes4) {\n        return ERC1155TokenReceiver.onERC1155Received.selector;\n    }\n\n    function onERC1155BatchReceived(\n        address operator,\n        address from,\n        uint256[] calldata ids,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external returns (bytes4) {\n        return ERC1155TokenReceiver.onERC1155BatchReceived.selector;\n    }\n}\n"},"Ownable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./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"},"Pixelmon.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.14;\n\nimport \"./ERC721.sol\";\nimport \"./Ownable.sol\";\nimport \"./Strings.sol\";\n\n/// @notice Thrown when completing the transaction results in overallocation of Pixelmon.\nerror MintedOut();\n/// @notice Thrown when the dutch auction phase has not yet started, or has already ended.\nerror AuctionNotStarted();\n/// @notice Thrown when the user has already minted two Pixelmon in the dutch auction.\nerror MintingTooMany();\n/// @notice Thrown when the value of the transaction is not enough for the current dutch auction or mintlist price.\nerror ValueTooLow();\n/// @notice Thrown when the user is not on the mintlist.\nerror NotMintlisted();\n/// @notice Thrown when the caller is not the EvolutionSerum contract, and is trying to evolve a Pixelmon.\nerror UnauthorizedEvolution();\n/// @notice Thrown when an invalid evolution is given by the EvolutionSerum contract.\nerror UnknownEvolution();\n\n\n//  ______   __     __  __     ______     __         __    __     ______     __   __    \n// /\\  == \\ /\\ \\   /\\_\\_\\_\\   /\\  ___\\   /\\ \\       /\\ \"-./  \\   /\\  __ \\   /\\ \"-.\\ \\   \n// \\ \\  _-/ \\ \\ \\  \\/_/\\_\\/_  \\ \\  __\\   \\ \\ \\____  \\ \\ \\-./\\ \\  \\ \\ \\/\\ \\  \\ \\ \\-.  \\  \n//  \\ \\_\\    \\ \\_\\   /\\_\\/\\_\\  \\ \\_____\\  \\ \\_____\\  \\ \\_\\ \\ \\_\\  \\ \\_____\\  \\ \\_\\\\\"\\_\\ \n//   \\/_/     \\/_/   \\/_/\\/_/   \\/_____/   \\/_____/   \\/_/  \\/_/   \\/_____/   \\/_/ \\/_/ \n//\n/// @title Generation 1 Pixelmon NFTs\n/// @author delta devs (https://www.twitter.com/deltadevelopers)\ncontract Pixelmon is ERC721, Ownable {\n    using Strings for uint256;\n\n    /*///////////////////////////////////////////////////////////////\n                               CONSTANTS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @dev Determines the order of the species for each tokenId, mechanism for choosing starting index explained post mint, explanation hash: acb427e920bde46de95103f14b8e57798a603abcf87ff9d4163e5f61c6a56881.\n    uint constant public provenanceHash = 0x9912e067bd3802c3b007ce40b6c125160d2ccb5352d199e20c092fdc17af8057;\n\n    /// @dev Sole receiver of collected contract funds, and receiver of 330 Pixelmon in the constructor.\n    address constant gnosisSafeAddress = 0xF6BD9Fc094F7aB74a846E5d82a822540EE6c6971;\n\n    /// @dev 7750, plus 330 for the Pixelmon Gnosis Safe\n    uint constant auctionSupply = 7750 + 330;\n\n    /// @dev The offsets are the tokenIds that the corresponding evolution stage will begin minting at.\n    uint constant secondEvolutionOffset = 10005;\n    uint constant thirdEvolutionOffset = secondEvolutionOffset + 4013;\n    uint constant fourthEvolutionOffset = thirdEvolutionOffset + 1206;\n\n    /*///////////////////////////////////////////////////////////////\n                        EVOLUTIONARY STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    /// @dev The next tokenID to be minted for each of the evolution stages\n    uint secondEvolutionSupply = 0;\n    uint thirdEvolutionSupply = 0;\n    uint fourthEvolutionSupply = 0;\n\n    /// @notice The address of the contract permitted to mint evolved Pixelmon.\n    address public serumContract;\n\n    /// @notice Returns true if the user is on the mintlist, if they have not already minted.\n    mapping(address =\u003e bool) public mintlisted;\n\n    /*///////////////////////////////////////////////////////////////\n                            AUCTION STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Starting price of the auction.\n    uint256 constant public auctionStartPrice = 3 ether;\n\n    /// @notice Unix Timestamp of the start of the auction.\n    /// @dev Monday, February 7th 2022, 13:00:00 converted to 1644256800 (GMT -5)\n    uint256 constant public auctionStartTime = 1644256800;\n\n    /// @notice Current mintlist price, which will be updated after the end of the auction phase.\n    /// @dev We started with signatures, then merkle tree, but landed on mapping to reduce USER gas fees.\n    uint256 public mintlistPrice = 0.75 ether;\n\n    /*///////////////////////////////////////////////////////////////\n                            METADATA STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    string public baseURI;\n\n    /*///////////////////////////////////////////////////////////////\n                            CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Deploys the contract, minting 330 Pixelmon to the Gnosis Safe and setting the initial metadata URI.\n    constructor(string memory _baseURI) ERC721(\"Pixelmon\", \"PXLMN\") {\n        baseURI = _baseURI;\n        unchecked {\n            balanceOf[gnosisSafeAddress] += 330;\n            totalSupply += 330;\n            for (uint256 i = 0; i \u003c 330; i++) {\n                ownerOf[i] = gnosisSafeAddress;\n                emit Transfer(address(0), gnosisSafeAddress, i);\n            }\n        }\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            METADATA LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Allows the contract deployer to set the metadata URI.\n    /// @param _baseURI The new metadata URI.\n    function setBaseURI(string memory _baseURI) public onlyOwner {\n        baseURI = _baseURI;\n    }\n\n    function tokenURI(uint256 id) public view override returns (string memory) {\n        return string(abi.encodePacked(baseURI, id.toString()));\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        DUTCH AUCTION LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Calculates the auction price with the accumulated rate deduction since the auction\u0027s begin\n    /// @return The auction price at the current time, or 0 if the deductions are greater than the auction\u0027s start price.\n    function validCalculatedTokenPrice() private view returns (uint) {\n        uint priceReduction = ((block.timestamp - auctionStartTime) / 10 minutes) * 0.1 ether;\n        return auctionStartPrice \u003e= priceReduction ? (auctionStartPrice - priceReduction) : 0;\n    }\n\n    /// @notice Calculates the current dutch auction price, given accumulated rate deductions and a minimum price.\n    /// @return The current dutch auction price\n    function getCurrentTokenPrice() public view returns (uint256) {\n        return max(validCalculatedTokenPrice(), 0.2 ether);\n    }\n\n    /// @notice Purchases a Pixelmon NFT in the dutch auction\n    /// @param mintingTwo True if the user is minting two Pixelmon, otherwise false.\n    /// @dev balanceOf is fine, team is aware and accepts that transferring out and repurchasing can be done, even by contracts. \n    function auction(bool mintingTwo) public payable {\n        if(block.timestamp \u003c auctionStartTime || block.timestamp \u003e auctionStartTime + 1 days) revert AuctionNotStarted();\n\n        uint count = mintingTwo ? 2 : 1;\n        uint price = getCurrentTokenPrice();\n\n        if(totalSupply + count \u003e auctionSupply) revert MintedOut();\n        if(balanceOf[msg.sender] + count \u003e 2) revert MintingTooMany();\n        if(msg.value \u003c price * count) revert ValueTooLow();\n\n        mintingTwo ? _mintTwo(msg.sender) : _mint(msg.sender, totalSupply);\n    }\n    \n    /// @notice Mints two Pixelmons to an address\n    /// @param to Receiver of the two newly minted NFTs\n    /// @dev errors taken from super._mint\n    function _mintTwo(address to) internal {\n        require(to != address(0), \"INVALID_RECIPIENT\");\n        require(ownerOf[totalSupply] == address(0), \"ALREADY_MINTED\");\n        uint currentId = totalSupply;\n\n        /// @dev unchecked because no arithmetic can overflow\n        unchecked {\n            totalSupply += 2;\n            balanceOf[to] += 2;\n            ownerOf[currentId] = to;\n            ownerOf[currentId + 1] = to;\n            emit Transfer(address(0), to, currentId);\n            emit Transfer(address(0), to, currentId + 1);\n        }\n    }\n\n\n    /*///////////////////////////////////////////////////////////////\n                        MINTLIST MINT LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Allows the contract deployer to set the price of the mintlist. To be called before uploading the mintlist.\n    /// @param price The price in wei of a Pixelmon NFT to be purchased from the mintlist supply.\n    function setMintlistPrice(uint256 price) public onlyOwner {\n        mintlistPrice = price;\n    }\n\n    /// @notice Allows the contract deployer to add a single address to the mintlist.\n    /// @param user Address to be added to the mintlist.\n    function mintlistUser(address user) public onlyOwner {\n        mintlisted[user] = true;\n    }\n\n    /// @notice Allows the contract deployer to add a list of addresses to the mintlist.\n    /// @param users Addresses to be added to the mintlist.\n    function mintlistUsers(address[] calldata users) public onlyOwner {\n        for (uint256 i = 0; i \u003c users.length; i++) {\n           mintlisted[users[i]] = true; \n        }\n    }\n\n    /// @notice Purchases a Pixelmon NFT from the mintlist supply\n    /// @dev We do not check if auction is over because the mintlist will be uploaded after the auction. \n    function mintlistMint() public payable {\n        if(totalSupply \u003e= secondEvolutionOffset) revert MintedOut();\n        if(!mintlisted[msg.sender]) revert NotMintlisted();\n        if(msg.value \u003c mintlistPrice) revert ValueTooLow();\n\n        mintlisted[msg.sender] = false;\n        _mint(msg.sender, totalSupply);\n    }\n\n    /// @notice Withdraws collected funds to the Gnosis Safe address\n    function withdraw() public onlyOwner {\n        (bool success, ) = gnosisSafeAddress.call{value: address(this).balance}(\"\");\n        require(success);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            ROLL OVER LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Allows the contract deployer to airdrop Pixelmon to a list of addresses, in case the auction doesn\u0027t mint out\n    /// @param addresses Array of addresses to receive Pixelmon\n    function rollOverPixelmons(address[] calldata addresses) public onlyOwner {\n        if(totalSupply + addresses.length \u003e secondEvolutionOffset) revert MintedOut();\n\n        for (uint256 i = 0; i \u003c addresses.length; i++) {\n            _mint(msg.sender, totalSupply);\n        }\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        EVOLUTIONARY LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Sets the address of the contract permitted to call mintEvolvedPixelmon\n    /// @param _serumContract The address of the EvolutionSerum contract\n    function setSerumContract(address _serumContract) public onlyOwner {\n        serumContract = _serumContract; \n    }\n\n    /// @notice Mints an evolved Pixelmon\n    /// @param receiver Receiver of the evolved Pixelmon\n    /// @param evolutionStage The evolution (2-4) that the Pixelmon is undergoing\n    function mintEvolvedPixelmon(address receiver, uint evolutionStage) public payable {\n        if(msg.sender != serumContract) revert UnauthorizedEvolution();\n\n        if (evolutionStage == 2) {\n            if(secondEvolutionSupply \u003e= 4013) revert MintedOut();\n            _mint(receiver, secondEvolutionOffset + secondEvolutionSupply);\n            unchecked {\n                secondEvolutionSupply++;\n            }\n        } else if (evolutionStage == 3) {\n            if(thirdEvolutionSupply \u003e= 1206) revert MintedOut();\n            _mint(receiver, thirdEvolutionOffset + thirdEvolutionSupply);\n            unchecked {\n                thirdEvolutionSupply++;\n            }\n        } else if (evolutionStage == 4) {\n            if(fourthEvolutionSupply \u003e= 33) revert MintedOut();\n            _mint(receiver, fourthEvolutionOffset + fourthEvolutionSupply);\n            unchecked {\n                fourthEvolutionSupply++;\n            }\n        } else  {\n            revert UnknownEvolution();\n        }\n    }\n\n\n    /*///////////////////////////////////////////////////////////////\n                                UTILS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Returns the greater of two numbers.\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a \u003e= b ? a : b;\n    }\n\n}\n"},"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    uint8 private constant _ADDRESS_LENGTH = 20;\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\u0027s 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 \u003e\u003e= 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 \u003e 1; --i) {\n            buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n            value \u003e\u003e= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n}\n"}}