Created
May 28, 2023 07:19
-
-
Save ChristianOConnor/d51d7b5867cf586d98daffeb57837b7b to your computer and use it in GitHub Desktop.
mints nfts with second EIP712 sugnature and should be run locally on hardhat node
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: UNLICENSED | |
pragma solidity ^0.8.18; | |
import "hardhat/console.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; | |
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; | |
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; | |
import "@openzeppelin/contracts/utils/Counters.sol"; | |
contract RandomReachDebug5Local is ERC721URIStorage, Ownable, EIP712 { | |
using Counters for Counters.Counter; | |
struct Request { | |
address minter; | |
uint256 nonce; | |
uint256 deadline; | |
} | |
// This is the keccak256 hash of the Request schema | |
bytes32 internal constant REQUEST_TYPEHASH = keccak256(bytes("Request(address minter,uint256 nonce,uint256 deadline)")); | |
// Initialize _DOMAIN_SEPARATOR directly with static values | |
bytes32 private immutable _DOMAIN_SEPARATOR = keccak256( | |
abi.encode( | |
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), | |
keccak256(bytes("RandomReachDebug5Local")), // static name | |
keccak256(bytes("1")), // static version | |
31337, // static chainId | |
0x8464135c8F25Da09e49BC8782676a84730C318bC // static verifyingContract | |
) | |
); | |
event RequestedRandom(bytes32 indexed requestId); | |
event MintedRandomNFT(bytes32 indexed requestId, uint256 response); | |
event MintCostChanged(uint256 newCost); | |
event Withdrawn(address indexed to, uint256 amount); | |
event Verified(address indexed signer, uint256 nonce, address from, bytes32 sigR, bytes32 sigS, uint8 sigV, address recovered); | |
address public authorizedAccount; | |
uint256 public mintCost = 0.01 ether; | |
uint256 public constant MAX_MINTS_PER_ADDRESS = 3; | |
Counters.Counter private _tokenIdTracker; | |
mapping(address => Counters.Counter) private _nonces; | |
mapping(uint256 => Classifier) public tokenIdToClassifier; | |
mapping(bytes32 => bool) public awaitingFulfillment; | |
mapping(bytes32 => address) public requestToMinter; | |
mapping(address => uint256) public minterToMintCount; | |
enum Classifier {FIRST, SECOND, THIRD} | |
string public firstUri; | |
string public secondUri; | |
string public thirdUri; | |
string private constant ERR_INVALID_SIGNER = "INVALID_SIGNER"; | |
string private constant ERR_REQUEST_ID_UNKNOWN = "Request ID not known"; | |
string private constant ERR_MINT_COST_NOT_MET = "Minting cost not met"; | |
string private constant ERR_MINT_LIMIT_REACHED = "Mint limit reached"; | |
string private constant ERR_VERIFICATION_FAILED = "Verification failed"; | |
constructor(string memory name, string memory symbol) | |
ERC721(name, symbol) | |
EIP712(name, "1") {} | |
function setAuthorizedAccount(address _authorizedAccount) external onlyOwner() { | |
authorizedAccount = _authorizedAccount; | |
} | |
function setURIs( | |
string calldata _firstUri, | |
string calldata _secondUri, | |
string calldata _thirdUri | |
) external onlyOwner() { | |
firstUri = _firstUri; | |
secondUri = _secondUri; | |
thirdUri = _thirdUri; | |
} | |
function setMintCost(uint256 _newCost) public onlyOwner() { | |
mintCost = _newCost; | |
emit MintCostChanged(_newCost); | |
} | |
function requestRandomNFT( | |
address minter, | |
uint256 nonce, | |
uint256 deadline, | |
uint8 v, | |
bytes32 r, | |
bytes32 s, | |
uint256 randomUint256 | |
) external payable { | |
require(msg.value >= mintCost, ERR_MINT_COST_NOT_MET); | |
require(minterToMintCount[minter] < MAX_MINTS_PER_ADDRESS, ERR_MINT_LIMIT_REACHED); | |
bytes32 requestId = _hashTypedDataV4( | |
keccak256( | |
abi.encode( | |
REQUEST_TYPEHASH, | |
minter, | |
nonce, | |
deadline | |
) | |
) | |
); | |
// Compute the digest | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
_DOMAIN_SEPARATOR, | |
keccak256( | |
abi.encode( | |
REQUEST_TYPEHASH, | |
minter, | |
nonce, | |
deadline | |
) | |
) | |
) | |
); | |
address signer = ECDSA.recover(digest, v, r, s); | |
console.log("below this is signer"); | |
console.log(signer); | |
console.log("below this is aithorizedAccount"); | |
console.log(authorizedAccount); | |
require(signer == authorizedAccount, ERR_INVALID_SIGNER); | |
require(!awaitingFulfillment[requestId], ERR_REQUEST_ID_UNKNOWN); | |
awaitingFulfillment[requestId] = true; | |
requestToMinter[requestId] = minter; | |
_nonces[minter].increment(); | |
emit RequestedRandom(requestId); | |
// Mint the NFT | |
mintNFT(requestId, randomUint256); | |
} | |
function withdraw(address to, uint256 amount) external onlyOwner() { | |
require(amount <= address(this).balance, "Insufficient balance"); | |
(bool sent, ) = to.call{value: amount}(""); | |
require(sent, "Failed to send Ether"); | |
emit Withdrawn(to, amount); | |
} | |
function mintNFT(bytes32 requestId, uint256 randomUint256) internal { | |
require(awaitingFulfillment[requestId], ERR_REQUEST_ID_UNKNOWN); | |
uint256 tokenId = _tokenIdTracker.current(); | |
_tokenIdTracker.increment(); | |
string memory tokenURI; | |
Classifier classifier; | |
if (randomUint256 < type(uint256).max / 3) { | |
classifier = Classifier.FIRST; | |
tokenURI = firstUri; | |
} else if (randomUint256 < type(uint256).max / 3 * 2) { | |
classifier = Classifier.SECOND; | |
tokenURI = secondUri; | |
} else { | |
classifier = Classifier.THIRD; | |
tokenURI = thirdUri; | |
} | |
tokenIdToClassifier[tokenId] = classifier; | |
_mint(requestToMinter[requestId], tokenId); | |
_setTokenURI(tokenId, tokenURI); | |
minterToMintCount[requestToMinter[requestId]]++; | |
awaitingFulfillment[requestId] = false; | |
emit MintedRandomNFT(requestId, randomUint256); | |
} | |
function nonces(address minter) public view returns (uint256) { | |
return _nonces[minter].current(); | |
} | |
function withdraw() external onlyOwner() { | |
uint balance = address(this).balance; | |
payable(owner()).transfer(balance); | |
emit Withdrawn(owner(), balance); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment