// 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/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../interfaces/IBEERC721.sol"; import "../interfaces/IBEERC1155.sol"; import "../utils/UInt.sol"; import "../utils/TimeChecker.sol"; import "../core/HasSignature.sol"; import "./FactoryBase.sol"; contract MinterFactory is Ownable, FactoryBase, TimeChecker, Initializable, HasSignature { using UInt for uint256; using SafeERC20 for IERC20; address public executor; // NFT contract IBEERC721 public hero; IBEERC721 public equip; IBEERC721 public chip; address public feeToAddress; event TokenMinted( address contractAddress, address indexed to, uint256 indexed nonce, uint256 indexed tokenId ); event TokenMintedBatch( address contractAddress, address indexed to, uint256 indexed nonce, uint256[] ids, uint256[] amounts ); constructor() HasSignature("MinterFactory", "1") {} function init(address[4] calldata _erc721s) external initializer onlyOwner { hero = IBEERC721(_erc721s[0]); equip = IBEERC721(_erc721s[1]); chip = IBEERC721(_erc721s[2]); } /** * @dev update executor */ function updateExecutor(address account) external onlyOwner { require(account != address(0), "address can not be zero"); executor = account; } function setFeeToAddress(address _feeToAddress) external onlyOwner { require( _feeToAddress != address(0), "fee received address can not be zero" ); feeToAddress = _feeToAddress; } /** * @dev mint function to distribute Hero NFT to user */ function mintHeroTo( address to, uint256 tokenId, uint256 nonce ) external onlyOwner { mint721NFT(to, tokenId, nonce, hero); } /** * @dev mint function to distribute Equipment NFT to user */ function mintEquipTo( address to, uint256 tokenId, uint256 nonce ) external onlyOwner { mint721NFT(to, tokenId, nonce, equip); } /** * @dev mint function to distribute Chip NFT to user */ function mintChipTo( address to, uint256 tokenId, uint256 nonce ) external onlyOwner { mint721NFT(to, tokenId, nonce, chip); } function mint721ByUser( address to, uint256 id, uint256 startTime, uint256 saltNonce, bytes calldata signature, IBEERC721 nft ) external signatureValid(signature) timeValid(startTime) { uint256[] memory signArray = new uint256[](1); signArray[0] = id; bytes32 criteriaMessageHash = getMessageHash( to, address(nft), startTime, saltNonce, signArray ); checkSigner(executor, criteriaMessageHash, signature); mint721NFT(to, id, saltNonce, nft); _useSignature(signature); } function mint721NFT( address to, uint256 tokenId, uint256 nonce, IBEERC721 nft ) internal { require(to != address(0), "MinterFactory: to address can not be zero"); nft.mint(to, tokenId); emit TokenMinted(address(nft), to, nonce, tokenId); } function mint1155NFT( address to, uint256 id, uint256 nonce, uint256 amount, IBEERC1155 nft ) internal { require(to != address(0), "MinterFactory: to address can not be zero"); nft.mintBatch(to, id.asSingletonArray(), amount.asSingletonArray(), ""); emit TokenMinted(address(chip), to, nonce, id); } function mint1155NFTBatch( address to, uint256 nonce, uint256[] memory ids, uint256[] memory amounts, IBEERC1155 nft ) internal { nft.mintBatch(to, ids, amounts, ""); emit TokenMintedBatch(address(nft), to, nonce, ids, amounts); } function getMessageHash( address _to, address _nftAddress, uint256 _startTime, uint256 _saltNonce, uint256[] memory _ids ) public pure returns (bytes32) { bytes memory encoded = abi.encodePacked( _to, _nftAddress, _startTime, _saltNonce ); uint256 len = _ids.length; for (uint256 i = 0; i < len; ++i) { encoded = bytes.concat(encoded, abi.encodePacked(_ids[i])); } return keccak256(encoded); } function getShardMixHash( ShardParam memory param, address nftAddress, uint256[] memory _ids ) internal pure returns (bytes32) { bytes memory encoded = abi.encodePacked( param.to, nftAddress, param.nftId, param.payToken, param.payAmount, param.startTime, param.saltNonce ); uint256 len = _ids.length; for (uint256 i = 0; i < len; ++i) { encoded = bytes.concat(encoded, abi.encodePacked(_ids[i])); } return keccak256(encoded); } }