becrypto/contracts/activate/NFTActivateProxy.sol
2022-04-25 15:23:57 +08:00

125 lines
3.6 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 = 9 * 1e15;
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: Game nftid must less than 9 * 1e15"
);
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 nft721 = getIMintableERC721ByType(nftType);
require(
nft721.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
nft721.burn(owner, nftOld);
usedSignatures[signature] = true;
nft721.mint(owner, nftNew);
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 getMessageHash(
address _owner,
uint256 _nftOld,
uint256 _nftNew,
uint256 _nftType,
uint256 _saltNonce
) public pure returns (bytes32) {
return
keccak256(
abi.encodePacked(_owner, _nftOld, _nftNew, _nftType, _saltNonce)
);
}
}