-
-
Save AndonMitev/5e32904eafde2f3c7839b1e5e7b67fbf to your computer and use it in GitHub Desktop.
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
//SPDX-License-Identifier: Unlicense | |
pragma solidity 0.8.10; | |
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "@openzeppelin/contracts/utils/Strings.sol"; | |
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; | |
import "@openzeppelin/contracts/finance/PaymentSplitter.sol"; | |
contract Collection is ERC1155, Ownable, PaymentSplitter, EIP712 { | |
string private constant SIGNING_DOMAIN = "LazyNFT-Voucher"; | |
string private constant SIGNATURE_VERSION = "1"; | |
string public name; | |
string public symbol; | |
uint256 public maxSupply; | |
uint256 public totalSupply; | |
uint256 private startingAt; | |
uint256 private initialPrice; | |
// Mapping from token ID to copies | |
mapping(uint256 => uint256) private copiesOf; | |
// Mapping from token ID to initial price | |
mapping(uint256 => uint256) private price; | |
struct NFTVoucher { | |
uint256 tokenId; | |
uint256 maxSupply; | |
string uri; | |
bytes signature; | |
} | |
event NFTMinted(address, address, uint256, string); | |
event NFTTransfered(address, address, uint256); | |
constructor( | |
uint256 _startingAt, | |
uint256 _maxSupply, | |
uint256 _initialPrice, | |
string memory _uri, | |
string memory _name, | |
string memory _symbol, | |
address _artist, | |
address[] memory _payees, | |
uint256[] memory _shares | |
) payable ERC1155(_uri) PaymentSplitter(_payees, _shares) EIP712(SIGNING_DOMAIN, SIGNATURE_VERSION) { | |
name = _name; | |
symbol = _symbol; | |
maxSupply = _maxSupply; | |
startingAt = _startingAt; | |
initialPrice = _initialPrice; | |
transferOwnership(_artist); | |
} | |
function mint(address _redeemer, NFTVoucher calldata _voucher) public payable { | |
require(startingAt < block.timestamp, "Not started"); | |
require(copiesOf[_voucher.tokenId] < 1, "Already minted"); | |
// make sure signature is valid and get the address of the signer | |
address signer = _verify(_voucher); | |
// make sure that the signer is authorized to mint NFTs | |
require(signer == owner(), "Signature invalid or unauthorized"); | |
// make sure that the redeemer is paying enough to cover the buyer's cost | |
require(msg.value >= initialPrice, "Insufficient funds to mint"); | |
copiesOf[_voucher.tokenId] = 1; | |
totalSupply = totalSupply + 1; | |
// first assign the token to the signer, to establish provenance on-chain | |
_mint(signer, _voucher.tokenId, 0, ""); | |
// transfer the token to the redeemer | |
_mint(_redeemer, _voucher.tokenId, 1, ""); | |
emit NFTMinted(signer, _redeemer, _voucher.tokenId, _voucher.uri); | |
} | |
function safeTransferFrom( | |
address from, | |
address to, | |
uint256 id, | |
uint256 amount, | |
bytes memory data | |
) public override { | |
_safeTransferFrom(from, to, id, amount, data); | |
emit NFTTransfered(from, to, id); | |
} | |
function _verify(NFTVoucher calldata voucher) private view returns (address) { | |
bytes32 digest = _hash(voucher); | |
return ECDSA.recover(digest, voucher.signature); | |
} | |
function _hash(NFTVoucher calldata voucher) private view returns (bytes32) { | |
return | |
_hashTypedDataV4( | |
keccak256( | |
abi.encode( | |
keccak256("NFTVoucher(uint256 tokenId,uint256 maxSupply,string uri)"), | |
voucher.tokenId, | |
voucher.maxSupply, | |
keccak256(bytes(voucher.uri)) | |
) | |
) | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment