cebgcontract a068fda5da 1
2022-04-20 15:01:54 +08:00

191 lines
5.9 KiB
Solidity

// 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;
}
}