becrypto/contracts/logic/EvolveProxy.sol
2023-11-28 11:14:31 +08:00

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);
}
}