becrypto/contracts/chip1155/BEChipFactory.sol
2022-08-04 15:48:38 +08:00

169 lines
4.7 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/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "../HasSignature.sol";
interface IMintableERC1155 is IERC1155 {
function mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) external;
function mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) external;
function burn(
address owner,
uint256 tokenId,
uint256 amount
) external;
function exists(uint256 id) external view returns (bool);
}
interface IBurnableERC721 is IERC721 {
function burn(address owner, uint256 tokenId) external;
}
contract BEChipFactory is Ownable, Initializable, HasSignature {
IMintableERC1155 public chip;
IBurnableERC721 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 = IMintableERC1155(_erc1155);
chipOld = IBurnableERC721(_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]);
}
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);
}
}