调整目录结构
This commit is contained in:
parent
40208a9e00
commit
77b2a1934e
@ -5,7 +5,7 @@ import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
|
||||
import "../interfaces/IBEERC1155.sol";
|
||||
import "../interfaces/IBEERC721.sol";
|
||||
import "../HasSignature.sol";
|
||||
import "../core/HasSignature.sol";
|
||||
|
||||
contract BEChipFactory is Ownable, Initializable, HasSignature {
|
||||
IBEERC1155 public chip;
|
@ -5,7 +5,7 @@ import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
|
||||
import "../interfaces/IBEERC1155.sol";
|
||||
import "../interfaces/IBEERC721.sol";
|
||||
import "../HasSignature.sol";
|
||||
import "../core/HasSignature.sol";
|
||||
|
||||
contract BEShardFactory is Ownable, Initializable, HasSignature {
|
||||
address public executor;
|
@ -3,7 +3,7 @@ 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 "./HasSignature.sol";
|
||||
import "../core/HasSignature.sol";
|
||||
|
||||
// this contract will transfer ownership to BETimelockController after deployed
|
||||
// all onlyowner method would add timelock
|
@ -4,7 +4,7 @@ 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 "../HasSignature.sol";
|
||||
import "../core/HasSignature.sol";
|
||||
|
||||
interface IMintableERC721 is IERC721 {
|
||||
function mint(address to, uint256 tokenId) external;
|
@ -4,7 +4,7 @@ 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 "../HasSignature.sol";
|
||||
import "../core/HasSignature.sol";
|
||||
|
||||
interface IMintableERC721 is IERC721 {
|
||||
function mint(address to, uint256 tokenId) external;
|
@ -6,7 +6,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/utils/Address.sol";
|
||||
import "@openzeppelin/contracts/governance/TimelockController.sol";
|
||||
import "./HasSignature.sol";
|
||||
import "../core/HasSignature.sol";
|
||||
|
||||
contract BEBoxMall is Ownable, HasSignature, TimelockController{
|
||||
using SafeERC20 for IERC20;
|
@ -8,7 +8,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
||||
import "./HasSignature.sol";
|
||||
import "../core/HasSignature.sol";
|
||||
|
||||
// this contract will transfer ownership to BETimelockController after deployed
|
||||
// all onlyowner method would add timelock
|
@ -1,190 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.10;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/access/AccessControl.sol";
|
||||
|
||||
contract BELuckyBox is ERC1155, AccessControl {
|
||||
bytes32 public constant URI_SETTER_ROLE = keccak256("URI_SETTER_ROLE");
|
||||
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
|
||||
bytes32 public constant BURN_ROLE = keccak256("BURN_ROLE");
|
||||
|
||||
struct TokenStruct {
|
||||
uint256 tokenId;
|
||||
uint256 amount;
|
||||
}
|
||||
|
||||
mapping(address => uint256[]) private _ownedTokens;
|
||||
mapping(address => mapping(uint256 => uint256)) private _ownedTokensIndex;
|
||||
|
||||
mapping(uint256 => uint256) private _totalSupply;
|
||||
|
||||
constructor() ERC1155("https://market.cebg.games/api/nft/info/{id}") {
|
||||
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
||||
_grantRole(URI_SETTER_ROLE, msg.sender);
|
||||
}
|
||||
|
||||
function setURI(string memory newuri) external onlyRole(URI_SETTER_ROLE) {
|
||||
_setURI(newuri);
|
||||
}
|
||||
|
||||
function mint(address account, uint256 id, uint256 amount, bytes memory data)
|
||||
external
|
||||
onlyRole(MINTER_ROLE)
|
||||
{
|
||||
_mint(account, id, amount, data);
|
||||
}
|
||||
|
||||
function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data)
|
||||
external
|
||||
onlyRole(MINTER_ROLE)
|
||||
{
|
||||
_mintBatch(to, ids, amounts, data);
|
||||
}
|
||||
|
||||
function burn(
|
||||
address account,
|
||||
uint256 id,
|
||||
uint256 value
|
||||
) external onlyRole(BURN_ROLE) {
|
||||
_burn(account, id, value);
|
||||
}
|
||||
|
||||
function burnBatch(
|
||||
address account,
|
||||
uint256[] memory ids,
|
||||
uint256[] memory values
|
||||
) external onlyRole(BURN_ROLE) {
|
||||
_burnBatch(account, ids, values);
|
||||
}
|
||||
|
||||
// The following functions are overrides required by Solidity.
|
||||
|
||||
function supportsInterface(bytes4 interfaceId)
|
||||
public
|
||||
view
|
||||
override(ERC1155, AccessControl)
|
||||
returns (bool)
|
||||
{
|
||||
return super.supportsInterface(interfaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Add factory to mint/burn item
|
||||
*/
|
||||
function setMintFactory(address factory) external onlyRole(DEFAULT_ADMIN_ROLE) {
|
||||
_grantRole(MINTER_ROLE, factory);
|
||||
_grantRole(BURN_ROLE, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Remove factory
|
||||
*/
|
||||
function removeMintFactory(address factory) external onlyRole(DEFAULT_ADMIN_ROLE) {
|
||||
_revokeRole(MINTER_ROLE, factory);
|
||||
_revokeRole(BURN_ROLE, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Total amount of tokens in with a given id.
|
||||
*/
|
||||
function totalSupply(uint256 id) public view virtual returns (uint256) {
|
||||
return _totalSupply[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Indicates whether any token exist with a given id, or not.
|
||||
*/
|
||||
function exists(uint256 id) public view virtual returns (bool) {
|
||||
return BELuckyBox.totalSupply(id) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {ERC1155-_beforeTokenTransfer}.
|
||||
*/
|
||||
function _beforeTokenTransfer(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint256[] memory ids,
|
||||
uint256[] memory amounts,
|
||||
bytes memory data
|
||||
) internal virtual override {
|
||||
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
|
||||
|
||||
if (from == address(0)) {
|
||||
// mint nft
|
||||
for (uint256 i = 0; i < ids.length; ++i) {
|
||||
_totalSupply[ids[i]] += amounts[i];
|
||||
}
|
||||
} else if (from != to){
|
||||
// transfer from -> to
|
||||
|
||||
for (uint256 i = 0; i < ids.length; ++i) {
|
||||
_removeTokenFromOwnerEnumeration(from, ids[i], amounts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (to == address(0)) {
|
||||
// burn nft
|
||||
for (uint256 i = 0; i < ids.length; ++i) {
|
||||
_totalSupply[ids[i]] -= amounts[i];
|
||||
}
|
||||
|
||||
} else if (to != from) {
|
||||
// mint or transfer from -> to
|
||||
for (uint256 i = 0; i < ids.length; ++i) {
|
||||
_addTokenToOwnerEnumeration(to, ids[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
|
||||
if (_ownedTokensIndex[to][tokenId] == 0 && balanceOf(to, tokenId) == 0) {
|
||||
_ownedTokensIndex[to][tokenId] = _ownedTokens[to].length;
|
||||
_ownedTokens[to].push(tokenId);
|
||||
}
|
||||
}
|
||||
|
||||
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId, uint256 amount) private {
|
||||
uint256 balance = balanceOf(from, tokenId);
|
||||
if (balance == amount) {
|
||||
uint256 lastTokenIndex = _ownedTokens[from].length - 1;
|
||||
uint256 tokenIndex = _ownedTokensIndex[from][tokenId];
|
||||
|
||||
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
|
||||
|
||||
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
|
||||
_ownedTokensIndex[from][lastTokenId] = tokenIndex; // Update the moved token's index
|
||||
|
||||
// This also deletes the contents at the last position of the array
|
||||
delete _ownedTokensIndex[from][tokenId];
|
||||
_ownedTokens[from].pop();
|
||||
}
|
||||
}
|
||||
|
||||
function userTokens(address user, uint256 start, uint256 page)
|
||||
external view returns (TokenStruct [] memory){
|
||||
uint256 size = _ownedTokens[user].length;
|
||||
TokenStruct[] memory results = new TokenStruct[](page);
|
||||
if (start < size) {
|
||||
uint256 max = size;
|
||||
if (start + page < size) {
|
||||
max = start + page;
|
||||
}
|
||||
for (uint256 i = start; i < max; ++i) {
|
||||
TokenStruct memory dataObj;
|
||||
uint256 tokenId = _ownedTokens[user][i];
|
||||
dataObj.tokenId = tokenId;
|
||||
dataObj.amount = balanceOf(user, tokenId);
|
||||
results[i-start] = dataObj;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
function tokenTypes(address user) external view returns (uint256) {
|
||||
return _ownedTokens[user].length;
|
||||
}
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
// 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;
|
||||
|
||||
uint8 public constant TYPE_NONE = 0;
|
||||
uint8 public constant TYPE_HERO = 1;
|
||||
uint8 public constant TYPE_EQUIP = 2;
|
||||
uint8 public constant TYPE_CHIP = 3;
|
||||
|
||||
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 val,
|
||||
uint256[3] ids,
|
||||
uint8[3] 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 saltNonce,
|
||||
bytes calldata signature
|
||||
) external {
|
||||
require(
|
||||
!usedSignatures[signature],
|
||||
"LuckyBoxProxy: signature used. please send another transaction with new signature"
|
||||
);
|
||||
address owner = msg.sender;
|
||||
bytes32 criteriaMessageHash = getMessageHash(
|
||||
boxId,
|
||||
ids[0],
|
||||
ids[1],
|
||||
ids[2],
|
||||
saltNonce
|
||||
);
|
||||
checkSigner(executor, criteriaMessageHash, signature);
|
||||
usedSignatures[signature] = true;
|
||||
// open box
|
||||
box.burn(owner, boxId, 1);
|
||||
|
||||
uint256[3] memory results = [ids[0], 0, 0];
|
||||
uint8[3] memory types = [TYPE_HERO, TYPE_NONE, TYPE_NONE];
|
||||
mint721WithType(owner, ids[0], types[0]);
|
||||
results[0] = ids[0];
|
||||
|
||||
uint256 val = rand(owner, saltNonce, 100);
|
||||
if (val >= 70 && val < 90) {
|
||||
types[1] = TYPE_CHIP;
|
||||
mint721WithType(owner, ids[1], types[1]);
|
||||
results[1] = ids[1];
|
||||
} else if (val >= 90 && val < 98) {
|
||||
types[1] = TYPE_EQUIP;
|
||||
mint721WithType(owner, ids[1], types[1]);
|
||||
results[1] = ids[1];
|
||||
} else if (val >= 98) {
|
||||
types[1] = TYPE_EQUIP;
|
||||
mint721WithType(owner, ids[1], types[1]);
|
||||
results[1] = ids[1];
|
||||
types[2] = TYPE_CHIP;
|
||||
mint721WithType(owner, ids[2], types[2]);
|
||||
results[2] = ids[2];
|
||||
}
|
||||
emit BoxOpened(owner, boxId, val, results, types);
|
||||
}
|
||||
|
||||
function mint721WithType(
|
||||
address to,
|
||||
uint256 tokenId,
|
||||
uint256 typeNum
|
||||
) private {
|
||||
if (typeNum == 1) {
|
||||
hero.mint(to, tokenId);
|
||||
} else if (typeNum == 2) {
|
||||
equip.mint(to, tokenId);
|
||||
} else if (typeNum == 3) {
|
||||
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 _saltNonce
|
||||
) public pure returns (bytes32) {
|
||||
return
|
||||
keccak256(
|
||||
abi.encodePacked(
|
||||
_boxId,
|
||||
_firstToken,
|
||||
_secondToken,
|
||||
_thirdToken,
|
||||
_saltNonce
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user