// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "../interfaces/IBEERC1155.sol"; import "../interfaces/IBEERC721.sol"; import "../core/HasSignature.sol"; contract BEChipFactory is Ownable, Initializable, HasSignature { IBEERC1155 public chip; IBEERC721 public chipOld; address public executor; mapping(bytes => bool) public usedSignatures; event Chip1155Minted( address contractAddress, address indexed to, uint256[] ids ); event Chip1155Activate( address indexed to, uint256 indexed nftOld, uint256 nftNew ); constructor() HasSignature("BEChipFactory", "1") {} function init(address _erc1155, address _erc721) external initializer onlyOwner { chip = IBEERC1155(_erc1155); chipOld = IBEERC721(_erc721); } /** * @dev update executor */ function updateExecutor(address account) external onlyOwner { require(account != address(0), "address can not be zero"); executor = account; } function mintChipTo( address to, uint256[] memory ids ) external onlyOwner { require(to != address(0), "BEChipFactory: to address can not be zero"); require(ids.length > 0, "BEChipFactory: 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; } chip.mintBatch(to, ids, amounts, ""); emit Chip1155Minted(address(chip), to, ids); } function mintChipSelf( uint256[] memory ids, uint256 saltNonce, bytes calldata signature ) external{ require(ids.length > 0, "BEChipFactory: ids cannot be empty"); require( !usedSignatures[signature], "BEChipFactory:: mintChipSelf: signature used. please send another transaction with new signature" ); address to = _msgSender(); bytes32 criteriaMessageHash = getMessageHash( to, saltNonce, ids ); checkSigner(executor, criteriaMessageHash, signature); uint256[] memory amounts = new uint256[](ids.length); uint256 len = ids.length; for (uint256 i = 0; i < len; ++i) { amounts[i] = 1; } chip.mintBatch(to, ids, amounts, ""); usedSignatures[signature] = true; emit Chip1155Minted(address(chip), to, ids); } function activateOneChip( uint256[] memory ids, uint256 saltNonce, bytes calldata signature ) external{ require(ids.length == 2, "BEChipFactory: ids length mismatch"); require( !usedSignatures[signature], "BEChipFactory:: activateOneChip: signature used. please send another transaction with new signature" ); address to = _msgSender(); require( chipOld.ownerOf(ids[1]) == to, "BEChipFactory: only owner can activate this nft" ); require( !chip.exists(ids[0]), "BEChipFactory: 1155 nftid duplicated" ); bytes32 criteriaMessageHash = getMessageHash( to, saltNonce, ids ); checkSigner(executor, criteriaMessageHash, signature); usedSignatures[signature] = true; chip.mint(to, ids[0], 1, ""); chipOld.burn(to, ids[1]); emit Chip1155Activate(to, ids[1], ids[0]); } //TODO:: // function upgradeChip( // uint256[] memory ids, // uint256 saltNonce, // bytes calldata signature // ) external { // require(ids.length > 1, "BEChipFactory: ids length mismatch"); // require( // !usedSignatures[signature], // "BEChipFactory:: activateOneChip: signature used. please send another transaction with new signature" // ); // address to = _msgSender(); // } 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); } }