125 lines
3.6 KiB
Solidity
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)
|
|
);
|
|
}
|
|
}
|