-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
//SPDX-License-Identifier: Unlicense | ||
pragma solidity ^0.8.20; | ||
|
||
import {ERC721URIStorageUpgradeable} from | ||
"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"; | ||
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import {ERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; | ||
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; | ||
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; | ||
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; | ||
|
||
/// @title DemoNFT | ||
/// @notice | ||
/// @dev | ||
contract DemoNFT is OwnableUpgradeable, AccessControlUpgradeable, ERC721Upgradeable, UUPSUpgradeable { | ||
using Strings for uint256; | ||
|
||
uint256 public tokenIdCounter; | ||
string public baseTokenURI; | ||
IERC20 public paymentToken; | ||
uint256 public mintPrice; | ||
|
||
event PaymentTokenSet(address indexed paymentToken); | ||
event MintPriceSet(uint256 indexed mintPrice); | ||
event BaseURISet(string indexed baseURI); | ||
|
||
mapping(uint256 => string) public tokenURIs; | ||
// disable contract until initialization | ||
|
||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize(address _owner, string memory _baseTokenURI, address _paymentToken, uint256 _mintPrice) | ||
public | ||
initializer | ||
{ | ||
__ERC721_init("DemoNFT", "DMON"); | ||
__Ownable_init(_owner); | ||
__UUPSUpgradeable_init(); | ||
|
||
tokenIdCounter = 0; | ||
baseTokenURI = _baseTokenURI; | ||
|
||
paymentToken = IERC20(_paymentToken); | ||
mintPrice = _mintPrice; | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
/// Internal functions | ||
//////////////////////////////////////////////////////////////////////// | ||
|
||
function _authorizeUpgrade(address /* newImplementation */ ) internal view override onlyOwner {} | ||
|
||
function _baseURI() internal view override returns (string memory) { | ||
return baseTokenURI; | ||
} | ||
|
||
function tokenURI(uint256 tokenId) public view override returns (string memory) { | ||
_requireOwned(tokenId); | ||
string memory baseURI = _baseURI(); | ||
return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : ""; | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
/// Owner actions | ||
//////////////////////////////////////////////////////////////////////// | ||
|
||
function _transferOwnership(address newOwner) internal virtual override { | ||
super._transferOwnership(newOwner); | ||
_grantRole(DEFAULT_ADMIN_ROLE, newOwner); | ||
} | ||
|
||
/// @notice set a new baseTokenURI | ||
/// @param _baseTokenURI the new base token URI | ||
function setBaseURI(string memory _baseTokenURI) public onlyOwner { | ||
baseTokenURI = _baseTokenURI; | ||
emit BaseURISet(_baseTokenURI); | ||
} | ||
|
||
function setPaymentToken(address _paymentToken) public onlyOwner { | ||
paymentToken = IERC20(_paymentToken); | ||
emit PaymentTokenSet(_paymentToken); | ||
} | ||
|
||
function setMintPrice(uint256 _mintPrice) public onlyOwner { | ||
mintPrice = _mintPrice; | ||
emit MintPriceSet(_mintPrice); | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
/// Minter action | ||
//////////////////////////////////////////////////////////////////////// | ||
|
||
/// @notice mint a NFT | ||
|
||
function mint(string memory _tokenURI) public returns (uint256) { | ||
require(paymentToken.balanceOf(msg.sender) >= mintPrice, "Insufficient token balance"); | ||
require(paymentToken.allowance(msg.sender, address(this)) >= mintPrice, "Token allowance too low"); | ||
|
||
// Transfer ERC20 tokens to this contract | ||
paymentToken.transferFrom(msg.sender, address(this), mintPrice); | ||
|
||
unchecked { | ||
++tokenIdCounter; | ||
} | ||
uint256 newItemId = tokenIdCounter; | ||
_safeMint(msg.sender, newItemId); | ||
tokenURIs[newItemId] = _tokenURI; | ||
return newItemId; | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
/// Interface functions | ||
//////////////////////////////////////////////////////////////////////// | ||
|
||
function supportsInterface(bytes4 interfaceId) | ||
public | ||
view | ||
virtual | ||
override(ERC721Upgradeable, AccessControlUpgradeable) | ||
returns (bool) | ||
{ | ||
return | ||
ERC721Upgradeable.supportsInterface(interfaceId) || AccessControlUpgradeable.supportsInterface(interfaceId); | ||
} | ||
} |