165 lines
4.3 KiB
Solidity
165 lines
4.3 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 burn(address owner, uint256 tokenId, uint256 amount) external;
|
|
}
|
|
|
|
interface IMintableERC721 is IERC721 {
|
|
function mint(address to, uint256 tokenId) external;
|
|
}
|
|
|
|
contract LuckyBoxProxy is Ownable, Initializable, HasSignature {
|
|
IMintableERC1155 public box;
|
|
IMintableERC721 public hero;
|
|
IMintableERC721 public equip;
|
|
IMintableERC721 public chip;
|
|
|
|
address public executor;
|
|
|
|
mapping(bytes => bool) public usedSignatures;
|
|
|
|
event BoxMinted(
|
|
address contractAddress,
|
|
address indexed to,
|
|
uint256[] ids,
|
|
uint256[] amounts
|
|
);
|
|
|
|
event BoxOpened(
|
|
address indexed to,
|
|
uint256 indexed boxId,
|
|
uint256[] ids,
|
|
uint256[] types
|
|
);
|
|
|
|
constructor()
|
|
HasSignature("LuckyBoxProxy", "1"){
|
|
}
|
|
|
|
function init(address _erc1155, address[3] calldata _erc721s) external initializer onlyOwner {
|
|
box = IMintableERC1155(_erc1155);
|
|
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 mintBoxTo(address to, uint256[] memory ids, uint256[] memory amounts) external onlyOwner{
|
|
require(to != address(0), 'to address can not be zero');
|
|
box.mintBatch(to, ids, amounts, "");
|
|
emit BoxMinted(address(box), to, ids, amounts);
|
|
}
|
|
|
|
function openBox(
|
|
uint256 boxId,
|
|
uint256[3] memory ids,
|
|
uint256[3] memory types,
|
|
uint256 saltNonce,
|
|
bytes calldata signature
|
|
) external {
|
|
require(ids.length == types.length, "LuckyBoxProxy: ids and types length mismatch");
|
|
|
|
require(
|
|
!usedSignatures[signature],
|
|
"LuckyBoxProxy: signature used. please send another transaction with new signature"
|
|
);
|
|
bytes32 criteriaMessageHash = getMessageHash(
|
|
boxId,
|
|
ids[0],
|
|
ids[1],
|
|
ids[2],
|
|
types[0],
|
|
types[1],
|
|
types[2],
|
|
saltNonce
|
|
);
|
|
checkSigner(executor, criteriaMessageHash, signature);
|
|
usedSignatures[signature] = true;
|
|
address owner = msg.sender;
|
|
// open box
|
|
box.burn(owner, boxId, 1);
|
|
// random count
|
|
uint256 val = rand(owner, saltNonce, 100);
|
|
// mint nft
|
|
uint256[] memory results;
|
|
uint256[] memory resultTypes;
|
|
mint721WithType(owner, ids[0], types[0]);
|
|
results[0] = ids[0];
|
|
resultTypes[0] = types[0];
|
|
if (val > 80) {
|
|
mint721WithType(owner, ids[1], types[1]);
|
|
results[1] = ids[1];
|
|
resultTypes[1] = types[1];
|
|
}
|
|
if (val > 90) {
|
|
mint721WithType(owner, ids[2], types[2]);
|
|
results[2] = ids[2];
|
|
resultTypes[2] = types[2];
|
|
}
|
|
emit BoxOpened(
|
|
owner,
|
|
boxId,
|
|
results,
|
|
resultTypes
|
|
);
|
|
}
|
|
|
|
function mint721WithType(address to, uint256 tokenId, uint256 typeNum) private {
|
|
if (typeNum == 0) {
|
|
hero.mint(to, tokenId);
|
|
} else if (typeNum == 1) {
|
|
equip.mint(to, tokenId);
|
|
} else {
|
|
chip.mint(to, tokenId);
|
|
}
|
|
}
|
|
|
|
function rand(
|
|
address owner,
|
|
uint256 nonce,
|
|
uint256 _length
|
|
) internal view returns(uint256) {
|
|
uint256 random = uint256(keccak256(abi.encodePacked(owner, nonce, block.difficulty, block.timestamp)));
|
|
return random%_length;
|
|
}
|
|
|
|
function getMessageHash(
|
|
uint256 _boxId,
|
|
uint256 _firstToken,
|
|
uint256 _secondToken,
|
|
uint256 _thirdToken,
|
|
uint256 _type1,
|
|
uint256 _type2,
|
|
uint256 _type3,
|
|
uint256 _saltNonce
|
|
) public pure returns (bytes32) {
|
|
return
|
|
keccak256(
|
|
abi.encodePacked(
|
|
_boxId,
|
|
_firstToken,
|
|
_secondToken,
|
|
_thirdToken,
|
|
_type1,
|
|
_type2,
|
|
_type3,
|
|
_saltNonce
|
|
)
|
|
);
|
|
}
|
|
} |