becrypto/contracts/activity/NFTClaimer.sol
2024-03-03 13:48:10 +08:00

106 lines
2.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../core/HasSignature.sol";
/**
* Contract for activity NFT claim.
*/
interface IClaimAbleNFT {
function safeMint(
address to
) external returns (uint256);
}
contract NFTClaimer is HasSignature, ReentrancyGuard{
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
address public immutable nftAddress;
address public signer;
uint256 public startTime;
uint256 public endTime;
mapping(address => uint256) public claimHistory;
event NFTClaimed(
address indexed nftAddress,
address indexed to,
uint256 tokenId,
uint256 nonce
);
event SignerUpdated(address indexed signer);
event StartTimeUpdated(uint256 indexed startTime);
event EndTimeUpdated(uint256 indexed endTime);
constructor(address _nftAddress) {
_CACHED_CHAIN_ID = block.chainid;
_CACHED_THIS = address(this);
nftAddress = _nftAddress;
}
function updateStartTime(uint256 _startTime) external onlyOwner {
startTime = _startTime;
emit StartTimeUpdated(_startTime);
}
function updateEndTime(uint256 _endTime) external onlyOwner {
endTime = _endTime;
emit EndTimeUpdated(_endTime);
}
/**
* @dev update signer
* @param _account new signer address
*/
function updateSigner(address _account) external onlyOwner {
require(_account != address(0), "NFTClaimer: address can not be zero");
signer = _account;
emit SignerUpdated(_account);
}
/**
* @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 {
require(block.timestamp >= startTime, "NFTClaimer: not started");
require(block.timestamp <= endTime, "NFTClaimer: already ended");
address to = _msgSender();
require(claimHistory[to] == 0, "NFTClaimer: already claimed");
bytes32 criteriaMessageHash = getMessageHash(
to,
nftAddress,
saltNonce
);
checkSigner(signer, 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);
}
}