增加1155的芯片

This commit is contained in:
cebgcontract 2022-08-03 19:04:40 +08:00
parent 082bfb9483
commit c756583f39
6 changed files with 72280 additions and 2 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,269 @@
// 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 BEChip1155 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");
bytes32 public constant LOCK_ROLE = keccak256("LOCK_ROLE");
mapping(uint256 => bool) public lockedTokens;
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) external view virtual returns (bool) {
return BEChip1155.totalSupply(id) > 0;
}
function grantLockRole(address account)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
_grantRole(LOCK_ROLE, account);
}
function revokeLockRole(address account)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
_revokeRole(LOCK_ROLE, account);
}
/**
* @dev Lock token to use in game or for rental
*/
function lock(uint256 id) external onlyRole(LOCK_ROLE) {
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(!lockedTokens[id], "Token has already locked");
lockedTokens[id] = true;
}
function lockBatch(uint256[] memory ids) external onlyRole(LOCK_ROLE) {
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
uint256 id = ids[i];
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(!lockedTokens[id], "Token has already locked");
lockedTokens[id] = true;
}
}
/**
* @dev Unlock token to use blockchain or sale on marketplace
*/
function unlock(uint256 id) external onlyRole(LOCK_ROLE) {
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(lockedTokens[id], "Token has already unlocked");
lockedTokens[id] = false;
}
function unlockBatch(uint256[] memory ids) external onlyRole(LOCK_ROLE) {
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
uint256 id = ids[i];
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(lockedTokens[id], "Token has already unlocked");
lockedTokens[id] = false;
}
}
/**
* @dev Get lock status
*/
function isLocked(uint256 id) external view returns (bool) {
return lockedTokens[id];
}
/**
* @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);
uint256 len = ids.length;
if (from == address(0)) {
// mint nft
for (uint256 i = 0; i < len; ++i) {
_totalSupply[ids[i]] += amounts[i];
}
} else if (from != to) {
// transfer from -> to
for (uint256 i = 0; i < len; ++i) {
_removeTokenFromOwnerEnumeration(from, ids[i], amounts[i]);
}
}
if (to == address(0)) {
// burn nft
for (uint256 i = 0; i < len; ++i) {
_totalSupply[ids[i]] -= amounts[i];
}
} else if (to != from) {
// mint or transfer from -> to
for (uint256 i = 0; i < len; ++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;
}
}

View File

@ -0,0 +1,110 @@
// 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;
}
contract BEChipFactory is Ownable, Initializable, HasSignature {
IMintableERC1155 public chip;
address public executor;
mapping(bytes => bool) public usedSignatures;
event Chip1155Minted(
address contractAddress,
address indexed to,
uint256[] ids
);
constructor() HasSignature("BEChipFactory", "1") {}
function init(address _erc1155)
external
initializer
onlyOwner
{
chip = IMintableERC1155(_erc1155);
}
/**
* @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), "to address can not be zero");
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{
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 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);
}
}

View File

@ -0,0 +1,23 @@
const Chip = artifacts.require('chip1155/BEChip1155');
const ChipFactory = artifacts.require('chip1155/BEChipFactory');
const config = require("../config/config");
module.exports = async function (deployer, network, accounts) {
await deployer.deploy(Chip);
const chipInstance = await Chip.deployed();
if(chipInstance) {
console.log("Chip 1155 successfully deployed.")
}
await deployer.deploy(ChipFactory);
const factoryInstance = await ChipFactory.deployed();
if(factoryInstance) {
console.log("Chip 1155 Factory successfully deployed.")
}
await factoryInstance.init(chipInstance.address);
await factoryInstance.updateExecutor(config.admins.admin);
console.log("Chip 1155 Factory successfully update setting.")
await chipInstance.setMintFactory(factoryInstance.address);
console.log("Chip 1155 successfully update factory.")
await chipInstance.grantLockRole(config.admins.admin);
console.log("Chip 1155 successfully grantLockRole.")
}

View File

@ -27,7 +27,7 @@ const fs = require('fs');
const mnemonic = fs.readFileSync(".secret").toString().trim();
// web3.eth.defaultAccount = '0x50A8e60041A206AcaA5F844a1104896224be6F39'
const kccTestnetKey = 'd9ed33809372932059c1ba7b336a33f406b4c55e7430daef8297134c67429d60';
module.exports = {
plugins: ['truffle-plugin-stdjsonin'],
api_keys: {
@ -81,7 +81,7 @@ module.exports = {
// production: true // Treats this network as if it was a public net. (default: false)
// }
kcc_testnet: {
provider: () => new HDWalletProvider(mnemonic, `https://rpc-testnet.kcc.network`),
provider: () => new HDWalletProvider(kccTestnetKey, `https://rpc-testnet.kcc.network`),
network_id: 322,
confirmations: 6,
timeoutBlocks: 5000,