-
-
Save shobhitic/9c281505002a50d95e55b4c261e3d477 to your computer and use it in GitHub Desktop.
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>LazyMinting</title> | |
| <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ethers/5.6.9/ethers.umd.min.js"></script> | |
| </head> | |
| <body> | |
| <script type="text/javascript"> | |
| const SIGNING_DOMAIN_NAME = "Voucher-Domain" | |
| const SIGNING_DOMAIN_VERSION = "1" | |
| const chainId = 1 | |
| const contractAddress = "0xa131AD247055FD2e2aA8b156A11bdEc81b9eAD95" // Put the address here from remix | |
| const signer = new ethers.Wallet("503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb") // private key that I use for address 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 | |
| const domain = { | |
| name: SIGNING_DOMAIN_NAME, | |
| version: SIGNING_DOMAIN_VERSION, | |
| verifyingContract: contractAddress, | |
| chainId | |
| } | |
| async function createVoucher(tokenId, price, uri, buyer) { | |
| const voucher = { tokenId, price, uri, buyer } | |
| const types = { | |
| LazyNFTVoucher: [ | |
| {name: "tokenId", type: "uint256"}, | |
| {name: "price", type: "uint256"}, | |
| {name: "uri", type: "string"}, | |
| {name: "buyer", type: "address"} | |
| ] | |
| } | |
| const signature = await signer._signTypedData(domain, types, voucher) | |
| return { | |
| ...voucher, | |
| signature | |
| } | |
| } | |
| async function main() { | |
| const voucher = await createVoucher(5, 50, "uri", "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4") // the address is the address which receives the NFT | |
| console.log(`[${voucher.tokenId}, ${voucher.price}, "${voucher.uri}", "${voucher.buyer}", "${voucher.signature}"]`) | |
| } | |
| </script> | |
| </body> | |
| </html> |
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.4; | |
| import "@openzeppelin/contracts@4.7.3/token/ERC721/ERC721.sol"; | |
| import "@openzeppelin/contracts@4.7.3/token/ERC721/extensions/ERC721URIStorage.sol"; | |
| import "@openzeppelin/contracts@4.7.3/access/Ownable.sol"; | |
| import "@openzeppelin/contracts@4.7.3/utils/cryptography/draft-EIP712.sol"; | |
| contract LazyNFT is ERC721, ERC721URIStorage, Ownable, EIP712 { | |
| string private constant SIGNING_DOMAIN = "Voucher-Domain"; | |
| string private constant SIGNATURE_VERSION = "1"; | |
| address public minter; | |
| constructor(address _minter) ERC721("LazyNFT", "LNFT") EIP712(SIGNING_DOMAIN, SIGNATURE_VERSION) { | |
| minter = _minter; | |
| } | |
| struct LazyNFTVoucher { | |
| uint256 tokenId; | |
| uint256 price; | |
| string uri; | |
| address buyer; | |
| bytes signature; | |
| } | |
| function recover(LazyNFTVoucher calldata voucher) public view returns (address) { | |
| bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( | |
| keccak256("LazyNFTVoucher(uint256 tokenId,uint256 price,string uri,address buyer)"), | |
| voucher.tokenId, | |
| voucher.price, | |
| keccak256(bytes(voucher.uri)), | |
| voucher.buyer | |
| ))); | |
| address signer = ECDSA.recover(digest, voucher.signature); | |
| return signer; | |
| } | |
| function safeMint(LazyNFTVoucher calldata voucher) | |
| public | |
| payable | |
| { | |
| require(minter == recover(voucher), "Wrong signature."); | |
| require(msg.value >= voucher.price, "Not enough ether sent."); | |
| _safeMint(voucher.buyer, voucher.tokenId); | |
| _setTokenURI(voucher.tokenId, voucher.uri); | |
| } | |
| // The following functions are overrides required by Solidity. | |
| 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); | |
| } | |
| } |
@damianlluch so only allowed user can mint with the voucher (and not everyone). Also can't front run the transaction.
I keep getting this error when i try and run the contract:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
Returned error: {"jsonrpc":"2.0","error":"execution reverted","id":6426425325688160}
any thoughts?
When i force the transaction i get:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
Returned error: {"jsonrpc":"2.0","error":"err: max fee per gas less than block base fee: address 0x27fF22B4AFbF9b7b1de0D832c94142c9E0Edea22, maxFeePerGas: 154311703063 baseFee: 158976875280 (supplied gas 15025147)","id":6426425325688248}
Hi, I found your code very useful.
I have a question for you.
Why do you use the minter variable? What's the point?