becrypto/contracts/activate/NFTActivateProxy.sol
2022-04-24 20:04:09 +08:00

143 lines
4.0 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "../HasSignature.sol";
interface IMintableERC721 is IERC721 {
function mint(address to, uint256 tokenId) external;
function burn(address owner, uint256 tokenId) external;
}
contract NFTActivateProxy is Ownable, Initializable, HasSignature {
uint256 private constant MINI_GEN_NFT_ID = 1e17;
uint256 private constant MAX_GAME_NFT_ID = 1e16;
IMintableERC721 public hero;
IMintableERC721 public equip;
IMintableERC721 public chip;
uint256 public constant TYPE_NONE = 0;
uint256 public constant TYPE_HERO = 1;
uint256 public constant TYPE_EQUIP = 2;
uint256 public constant TYPE_CHIP = 3;
address public executor;
mapping(bytes => bool) public usedSignatures;
event LogNFTActivate(
address indexed to,
uint256 indexed nftOld,
uint256 nftNew,
uint256 nftType
);
constructor() HasSignature("NFTActivateProxy", "1") {}
function init(address[3] calldata _erc721s)
external
initializer
onlyOwner
{
hero = IMintableERC721(_erc721s[0]);
equip = IMintableERC721(_erc721s[1]);
chip = IMintableERC721(_erc721s[2]);
}
/**
* @dev update executor
*/
function updateExecutor(address account) external onlyOwner {
require(account != address(0), "address can not be zero");
executor = account;
}
function activateOne(
uint256 nftOld,
uint256 nftNew,
uint256 nftType,
uint256 saltNonce,
bytes calldata signature
) external {
require(nftOld >= MINI_GEN_NFT_ID, "NFTActivateProxy: GEN nftid must greater than 1e18");
require(nftNew < MAX_GAME_NFT_ID, "NFTActivateProxy: GEN nftid must less than 1e17");
require(nftType > 0, "NFTActivateProxy: nft type must greater than 0");
require(nftType < 4, "NFTActivateProxy: nft type must less than 4");
require(
!usedSignatures[signature],
"NFTActivateProxy: signature used. please send another transaction with new signature"
);
address owner = msg.sender;
IMintableERC721 tokenOld = getIMintableERC721ByType(nftType);
require(
tokenOld.ownerOf(nftOld) == owner,
"NFTActivateProxy: only owner can activate this nft"
);
bytes32 criteriaMessageHash = getMessageHash(
owner,
nftOld,
nftNew,
nftType,
saltNonce
);
checkSigner(executor, criteriaMessageHash, signature);
// activate the old nft
tokenOld.burn(owner, nftOld);
usedSignatures[signature] = true;
mint721WithType(owner, nftNew, nftType);
emit LogNFTActivate(owner, nftOld, nftNew, nftType);
}
function getIMintableERC721ByType(uint256 nftType)
private view returns(IMintableERC721){
if (nftType == TYPE_HERO) {
return hero;
} else if (nftType == TYPE_EQUIP) {
return equip;
} else {
return chip;
}
}
function mint721WithType(
address to,
uint256 tokenId,
uint256 typeNum
) private {
if (typeNum == TYPE_HERO) {
hero.mint(to, tokenId);
} else if (typeNum == TYPE_EQUIP) {
equip.mint(to, tokenId);
} else {
chip.mint(to, tokenId);
}
}
function getMessageHash(
address _owner,
uint256 _nftOld,
uint256 _nftNew,
uint256 _nftType,
uint256 _saltNonce
) public pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
_owner,
_nftOld,
_nftNew,
_nftType,
_saltNonce
)
);
}
}