becrypto/contracts/logic/MinterFactory.sol
2022-08-10 16:35:50 +08:00

260 lines
7.4 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 "../interfaces/IBEERC721.sol";
import "../interfaces/IBEERC1155.sol";
import "../core/HasSignature.sol";
contract MinterFactory is Ownable, Initializable, HasSignature {
address public executor;
// NFT contract
IBEERC721 public hero;
IBEERC721 public equip;
IBEERC1155 public chip;
IBEERC1155 public shard;
event TokenMinted(
address contractAddress,
address to,
uint256 indexed tokenId
);
event TokenMintedBatch(
address contractAddress,
address indexed to,
uint256[] ids,
uint256[] amounts
);
mapping(bytes => bool) public usedSignatures;
constructor() HasSignature("MinterFactory", "1") {}
function init(address[4] calldata _erc721s) external initializer onlyOwner {
hero = IBEERC721(_erc721s[0]);
equip = IBEERC721(_erc721s[1]);
chip = IBEERC1155(_erc721s[2]);
shard = IBEERC1155(_erc721s[3]);
}
/**
* @dev update executor
*/
function updateExecutor(address account) external onlyOwner {
require(account != address(0), "address can not be zero");
executor = account;
}
/**
* @dev mint function to distribute Hero NFT to user
*/
function mintHeroTo(address to, uint256 tokenId) external onlyOwner {
mint721NFT(to, tokenId, hero);
}
/**
* @dev mint function to distribute Equipment NFT to user
*/
function mintEquipTo(address to, uint256 tokenId) external onlyOwner {
mint721NFT(to, tokenId, equip);
}
/**
* @dev mint function to distribute Chip NFT to user
*/
function mintChipTo(address to, uint256 tokenId) external onlyOwner {
mint1155NFT(to, tokenId, 1, chip);
}
/**
* @dev mint function to distribute Shard NFT to user
*/
function mintShardTo(address to, uint256 tokenId) external onlyOwner {
mint1155NFT(to, tokenId, 1, shard);
}
/**
* @dev batch mint 1155 Chip to user
*/
function mintChipBatch(address to, uint256[] memory ids)
external
onlyOwner
{
require(
to != address(0),
"MinterFactory::mintChipBatch: to address can not be zero"
);
require(
ids.length > 0,
"MinterFactory::mintChipBatch: ids cannot be empty"
);
uint256[] memory amounts = new uint256[](ids.length);
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
amounts[i] = 1;
}
mint1155NFTBatch(to, ids, amounts, chip);
}
/**
* @dev batch mint 1155 Shard to user
*/
function mintShardBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts
) external onlyOwner {
require(to != address(0), "MinterFactory: to address can not be zero");
require(ids.length > 0, "MinterFactory: ids cannot be empty");
require(
ids.length == amounts.length,
"MinterFactory: ids and amounts length mismatch"
);
mint1155NFTBatch(to, ids, amounts, chip);
}
/**
* @dev user mint hero
*/
function mintHeroUser(
uint256 tokenId,
uint256 saltNonce,
bytes calldata signature
) external {
mint721NFTUser(tokenId, saltNonce, signature, hero);
}
/**
* @dev user mint equip
*/
function mintEquipUser(
uint256 tokenId,
uint256 saltNonce,
bytes calldata signature
) external {
mint721NFTUser(tokenId, saltNonce, signature, equip);
}
/**
* @dev user batch mint 1155 chip
*/
function mintChipBatchUser(
uint256[] memory ids,
uint256 saltNonce,
bytes calldata signature
) external {
uint256[] memory amounts = new uint256[](ids.length);
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
amounts[i] = 1;
}
mint1155NFTBatchUser(ids, amounts, saltNonce, signature, chip);
}
/**
* @dev user batch mint 1155 shard
*/
function mintShardBatchUser(
uint256[] memory ids,
uint256[] memory amounts,
uint256 saltNonce,
bytes calldata signature
) external {
mint1155NFTBatchUser(ids, amounts, saltNonce, signature, shard);
}
function mint721NFTUser(
uint256 id,
uint256 saltNonce,
bytes calldata signature,
IBEERC721 nft
) internal {
require(
!usedSignatures[signature],
"MinterFactory: signature used. please send another transaction with new signature"
);
address to = _msgSender();
uint256[] memory signArray = new uint256[](1);
signArray[0] = id;
bytes32 criteriaMessageHash = getMessageHash(to, saltNonce, signArray);
checkSigner(executor, criteriaMessageHash, signature);
mint721NFT(to, id, nft);
usedSignatures[signature] = true;
}
function mint1155NFTBatchUser(
uint256[] memory ids,
uint256[] memory amounts,
uint256 saltNonce,
bytes calldata signature,
IBEERC1155 nft
) internal {
uint256 len = ids.length;
require(len > 0, "MinterFactory: ids cannot be empty");
require(
len == amounts.length,
"MinterFactory: ids and amounts length mismatch"
);
require(
!usedSignatures[signature],
"MinterFactory: signature used. please send another transaction with new signature"
);
address to = _msgSender();
uint256[] memory signArray = new uint256[](len * 2);
for (uint256 i = 0; i < len; ++i) {
signArray[i * 2] = ids[i];
signArray[i * 2 + 1] = amounts[i];
}
bytes32 criteriaMessageHash = getMessageHash(to, saltNonce, signArray);
checkSigner(executor, criteriaMessageHash, signature);
mint1155NFTBatch(to, ids, amounts, nft);
usedSignatures[signature] = true;
}
function mint721NFT(
address to,
uint256 tokenId,
IBEERC721 nft
) internal {
require(to != address(0), "MinterFactory: to address can not be zero");
nft.mint(to, tokenId);
emit TokenMinted(address(nft), to, tokenId);
}
function mint1155NFT(
address to,
uint256 id,
uint256 amount,
IBEERC1155 nft
) internal {
require(to != address(0), "MinterFactory: to address can not be zero");
nft.mint(to, id, amount, "");
emit TokenMinted(address(chip), to, id);
}
function mint1155NFTBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
IBEERC1155 nft
) internal {
nft.mintBatch(to, ids, amounts, "");
emit TokenMintedBatch(address(nft), to, ids, amounts);
}
function getMessageHash(
address _to,
uint256 _saltNonce,
uint256[] memory _ids
) public pure returns (bytes32) {
bytes memory encoded = abi.encodePacked(_to, _saltNonce);
uint256 len = _ids.length;
for (uint256 i = 0; i < len; ++i) {
encoded = bytes.concat(encoded, abi.encodePacked(_ids[i]));
}
return keccak256(encoded);
}
}