90 lines
2.5 KiB
Solidity
90 lines
2.5 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity 0.8.10;
|
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
import "../core/HasSignature.sol";
|
|
import "../utils/TimeChecker.sol";
|
|
import "../utils/UInt.sol";
|
|
|
|
interface IBurnableERC721 is IERC721 {
|
|
function burn(uint256 tokenId) external;
|
|
|
|
function batchMint(address to, uint256[] memory tokenIds) external;
|
|
}
|
|
|
|
contract EvolveProxy is Ownable, TimeChecker, HasSignature {
|
|
using UInt for uint256;
|
|
|
|
IBurnableERC721 public nft;
|
|
|
|
address public executor;
|
|
|
|
event TokenEvolved(
|
|
uint256 indexed evolveEventId,
|
|
address indexed owner,
|
|
uint256[] tokenIds
|
|
);
|
|
|
|
constructor(address _address){
|
|
nft = IBurnableERC721(_address);
|
|
}
|
|
|
|
/**
|
|
* @dev update executor
|
|
*/
|
|
function updateExecutor(address account) external onlyOwner {
|
|
require(account != address(0), "address can not be zero");
|
|
executor = account;
|
|
}
|
|
|
|
/**
|
|
* @dev evolve function to Counter Fire nft NFT
|
|
* tokenIds: [nft_to_evolve, nft_for_burn, nft_for_burn...]
|
|
* nft_to_evolve: nft to evolve, auto mint if not exist
|
|
*/
|
|
function evolveNft(
|
|
uint256 evolveEventId,
|
|
uint256[] calldata tokenIds,
|
|
uint256 startTime,
|
|
uint256 saltNonce,
|
|
bytes calldata signature
|
|
) external signatureValid(signature) timeValid(startTime) {
|
|
require(tokenIds.length > 0, "EvolveProxy: tokenIds length must > 0");
|
|
require(tokenIds[0] > 0, "EvolveProxy: nft to evolve can not be 0");
|
|
address user = _msgSender();
|
|
|
|
bytes32 criteriaMessageHash = getMessageHash(
|
|
evolveEventId,
|
|
user,
|
|
startTime,
|
|
saltNonce,
|
|
tokenIds
|
|
);
|
|
checkSigner(executor, criteriaMessageHash, signature);
|
|
try nft.batchMint(user, tokenIds[0].asSingletonArray()) {} catch {}
|
|
require(nft.ownerOf(tokenIds[0]) == user,"EvolveProxy: not owner of this nft now");
|
|
if (tokenIds.length > 1) {
|
|
for (uint256 i = 1; i < tokenIds.length; ++i) {
|
|
nft.burn(tokenIds[i]);
|
|
}
|
|
}
|
|
_useSignature(signature);
|
|
emit TokenEvolved(evolveEventId,user,tokenIds);
|
|
}
|
|
|
|
function getMessageHash(
|
|
uint256 _eventId,
|
|
address _user,
|
|
uint256 _startTime,
|
|
uint256 _saltNonce,
|
|
uint256[] memory _tokenIds
|
|
) public pure returns (bytes32) {
|
|
bytes memory encoded = abi.encodePacked(_eventId, _user, _startTime, _saltNonce);
|
|
uint256 len = _tokenIds.length;
|
|
for (uint256 i = 0; i < len; ++i) {
|
|
encoded = bytes.concat(encoded, abi.encodePacked(_tokenIds[i]));
|
|
}
|
|
return keccak256(encoded);
|
|
}
|
|
}
|