// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; contract Pixel is ERC721, ERC721URIStorage, ERC721Enumerable, Pausable, Ownable { using Counters for Counters.Counter; using SafeERC20 for IERC20; Counters.Counter public _tokenIdCounter; mapping(uint256 => string) public nftData; uint256 public price = 5 ether; uint256 constant public MAX_MINT = 5000; string public baseURI; constructor() ERC721("Pixel", "Pixel NFT") { _tokenIdCounter.increment(); } function setPrice(uint256 newPrice) public onlyOwner { price = newPrice; } function pause() public onlyOwner { _pause(); } function unpause() public onlyOwner { _unpause(); } function _baseURI() internal view override returns (string memory) { return baseURI; } function setBaseURI(string memory _uri) public onlyOwner { baseURI = _uri; } function getCurrentCounter() public view returns (uint256) { return _tokenIdCounter.current(); } function getOwnerNFTData( address _owner, uint256 _offset, uint256 _limit ) public view returns (string[] memory) { uint256 balance = balanceOf(_owner); string[] memory res = new string[](_limit); uint256 counter = 0; for (uint256 i = _offset; i < _offset + _limit; i++) { if (i >= balance) return res; uint256 id = tokenOfOwnerByIndex(_owner, i); res[counter++] = nftData[id]; } return res; } function getNFTData( uint256 _offset, uint256 _limit ) public view returns (string[] memory) { uint256 balance = _tokenIdCounter.current(); string[] memory res = new string[](_limit); uint256 counter = 0; for (uint256 id = _offset; id < _offset + _limit; id++) { if (id >= balance) return res; res[counter++] = nftData[id]; } return res; } function setTokensUri(uint256[] memory _ids, string[] memory _tokensURI) public onlyOwner { require(_ids.length > 0, "ID arrays not empty"); require(_ids.length == _tokensURI.length, "Length of ID and Data arrays is not equal!"); for (uint256 i = 0; i < _ids.length; i++) { _setTokenURI(_ids[i], _tokensURI[i]); } } function safeMint(string memory data) public payable whenNotPaused { uint256 tokenId = _tokenIdCounter.current(); require(tokenId <= MAX_MINT, "No tokens left to be minted!"); require(msg.sender == owner() || price == msg.value, "Price not same!"); _tokenIdCounter.increment(); _safeMint(msg.sender, tokenId); nftData[tokenId] = data; } function withdraw() public virtual onlyOwner { uint256 amount = address(this).balance; payable(msg.sender).transfer(amount); } function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal whenNotPaused override(ERC721, ERC721Enumerable) { super._beforeTokenTransfer(from, to, tokenId); } function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) { super._burn(tokenId); } function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { return super.tokenURI(tokenId); } // The following functions are overrides required by Solidity. function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) { return super.supportsInterface(interfaceId); } event Received(address, uint); receive() external payable { emit Received(msg.sender, msg.value); } }