100 lines
2.5 KiB
Solidity
100 lines
2.5 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity 0.8.23;
|
|
|
|
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
|
|
import {HasSignature} from "../core/HasSignature.sol";
|
|
|
|
/**
|
|
* Contract for the activity of NFT claim stage 2.
|
|
*/
|
|
interface IClaimAbleNFT {
|
|
function safeMint(
|
|
address to
|
|
) external returns (uint256);
|
|
}
|
|
|
|
contract NFTClaimStage2 is HasSignature, ReentrancyGuard{
|
|
uint256 private immutable _CACHED_CHAIN_ID;
|
|
address private immutable _CACHED_THIS;
|
|
address public immutable nftAddress;
|
|
address public verifier;
|
|
|
|
bool public isPaused = false;
|
|
|
|
mapping(address user => uint256 status) public claimHistory;
|
|
|
|
event NFTClaimed(
|
|
address indexed nftAddress,
|
|
address indexed to,
|
|
uint256 tokenId,
|
|
uint256 nonce
|
|
);
|
|
|
|
event StateUpdated(bool isPaused);
|
|
event VerifierUpdated(address indexed verifier);
|
|
|
|
constructor(address _nftAddress) {
|
|
_CACHED_CHAIN_ID = block.chainid;
|
|
_CACHED_THIS = address(this);
|
|
nftAddress = _nftAddress;
|
|
}
|
|
|
|
modifier whenNotPaused() {
|
|
require(!isPaused, "NFTClaimer: paused");
|
|
_;
|
|
}
|
|
|
|
function updatePaused(bool _isPaused) external onlyOwner {
|
|
isPaused = _isPaused;
|
|
emit StateUpdated(_isPaused);
|
|
}
|
|
|
|
/**
|
|
* @dev update verifier address
|
|
*/
|
|
function updateVerifier(address _verifier) external onlyOwner {
|
|
require(_verifier != address(0), "NFTClaimer: address can not be zero");
|
|
verifier = _verifier;
|
|
emit VerifierUpdated(_verifier);
|
|
}
|
|
|
|
/**
|
|
* @dev claim NFT
|
|
* Get whitelist signature from a third-party service, then call this method to claim NFT
|
|
* @param saltNonce nonce
|
|
* @param signature signature
|
|
*/
|
|
function claim(
|
|
uint256 saltNonce,
|
|
bytes calldata signature
|
|
) external nonReentrant whenNotPaused {
|
|
address to = _msgSender();
|
|
require(claimHistory[to] == 0, "NFTClaimer: already claimed");
|
|
bytes32 criteriaMessageHash = getMessageHash(
|
|
to,
|
|
nftAddress,
|
|
saltNonce
|
|
);
|
|
checkSigner(verifier, criteriaMessageHash, signature);
|
|
uint256 tokenId = IClaimAbleNFT(nftAddress).safeMint(to);
|
|
claimHistory[to] = tokenId;
|
|
_useSignature(signature);
|
|
emit NFTClaimed(nftAddress, to, tokenId, saltNonce);
|
|
}
|
|
|
|
function getMessageHash(
|
|
address _to,
|
|
address _address,
|
|
uint256 _saltNonce
|
|
) public view returns (bytes32) {
|
|
bytes memory encoded = abi.encodePacked(
|
|
_to,
|
|
_address,
|
|
_CACHED_CHAIN_ID,
|
|
_CACHED_THIS,
|
|
_saltNonce
|
|
);
|
|
return keccak256(encoded);
|
|
}
|
|
}
|