编译器
0.8.17+commit.8df45f5f
文件 1 的 11:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 11:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 11:ERC1155Hybrid.sol
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
struct Owner {
address owner;
bool burned;
uint256 amount;
}
abstract contract ERC1155Hybrid is
Context,
ERC165,
IERC1155,
IERC1155MetadataURI
{
string internal _name;
string internal _symbol;
string internal _uri;
string internal _contractURI;
mapping(address => mapping(address => bool)) _operatorApprovals;
mapping(uint256 => mapping(address => uint256)) _fungibleBalances;
mapping(uint16 => mapping(uint256 => Owner)) _nftOwnership;
mapping(uint16 => uint256) _nftMintCounter;
mapping(uint16 => mapping(address => uint256)) _nftBalances;
constructor(
string memory name_,
string memory symbol_,
string memory contractURI_,
string memory uri_
) {
_name = name_;
_symbol = symbol_;
_contractURI = contractURI_;
_uri = uri_;
}
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC1155).interfaceId ||
interfaceId == type(IERC1155MetadataURI).interfaceId ||
super.supportsInterface(interfaceId);
}
function _setMetadata(
string memory name_,
string memory symbol_,
string memory contractURI_,
string memory uri_
) internal {
_name = name_;
_symbol = symbol_;
_contractURI = contractURI_;
_uri = uri_;
}
function ownerOf(uint256 id) public view returns (address) {
require(!_isFungible(id), "Token ID is fungible");
(uint16 tier, uint256 unpacked) = _unpackID(id);
(, uint256 idx, ) = _findNearestOwnershipRecord(tier, unpacked);
return _nftOwnership[tier][idx].owner;
}
function balanceOfTier(
address account,
uint16 tier
) public view returns (uint256) {
return _nftBalances[tier][account];
}
function balanceOf(
address account,
uint256 id
) public view returns (uint256) {
if (_isFungible(id)) {
return _balanceOfFungible(account, id);
}
if (ownerOf(id) == account) {
return 1;
}
return 0;
}
function _balanceOfFungible(
address account,
uint256 id
) private view returns (uint256) {
return _fungibleBalances[id][account];
}
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] calldata) {
require(accounts.length == ids.length, "Array mismatch");
uint256[] memory res = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; i++) {
res[i] = balanceOf(accounts[i], ids[i]);
}
return ids;
}
function setApprovalForAll(address operator, bool approved) external {
_setApprovalForAll(_msgSender(), operator, approved);
}
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC1155: setting approval status for self");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function isApprovedForAll(
address account,
address operator
) external view returns (bool) {
return _operatorApprovals[account][operator];
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external virtual {
_safeTransferFrom(from, to, id, amount, data);
}
function _safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) internal {
if (_isFungible(id)) {
return _safeTransferFromFungible(from, to, id, amount, data);
}
return _safeTransferFromNFT(from, to, id, amount, data);
}
function _safeTransferFromFungible(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
require(
from == operator || _operatorApprovals[from][operator],
"ERC1155: not approved"
);
uint256 fromBalance = _fungibleBalances[id][from];
require(
fromBalance >= amount,
"ERC1155: insufficient balance for transfer"
);
unchecked {
_fungibleBalances[id][from] = fromBalance - amount;
}
_fungibleBalances[id][to] += amount;
emit TransferSingle(operator, from, to, id, amount);
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
}
function _safeTransferFromNFT(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal {
address operator = _msgSender();
require(to != address(0), "ERC1155: transfer to the zero address");
require(amount == 1, "ERC1155: transfer of NFT must have amount of 1");
(uint16 tier, uint256 unpacked) = _unpackID(id);
(
address origOwner,
uint256 origStart,
uint256 origAmount
) = _findNearestOwnershipRecord(tier, unpacked);
require(origOwner == from, "ERC1155: not the owner of this token");
require(
from == operator || _operatorApprovals[from][operator],
"ERC1155: not approved"
);
uint256 rightAmount = origStart + origAmount - unpacked - 1;
uint256 leftAmount = unpacked - origStart;
if (leftAmount > 0) {
_nftOwnership[tier][origStart].amount = leftAmount;
}
_nftOwnership[tier][unpacked] = Owner({
owner: to,
burned: false,
amount: 1
});
if (rightAmount > 0) {
_nftOwnership[tier][unpacked + 1] = Owner({
owner: from,
burned: false,
amount: rightAmount
});
}
_nftBalances[tier][from] -= 1;
_nftBalances[tier][to] += 1;
emit TransferSingle(operator, from, to, id, amount);
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external {
require(ids.length == amounts.length, "Array mismatch");
for (uint256 i = 0; i < ids.length; i++) {
_safeTransferFrom(from, to, ids[i], amounts[i], data);
}
}
function _findNearestOwnershipRecord(
uint16 tier,
uint256 unpacked
) private view returns (address, uint256, uint256) {
if (unpacked > _nftMintCounter[tier]) {
revert("Token not minted");
}
for (uint256 i = unpacked; i >= 0; i--) {
if (
_nftOwnership[tier][i].owner != address(0) ||
_nftOwnership[tier][i].burned
) {
return (
_nftOwnership[tier][i].owner,
i,
_nftOwnership[tier][i].amount
);
}
}
revert("Ownership could not be determined");
}
function name() external view returns (string memory) {
return _name;
}
function symbol() external view returns (string memory) {
return _symbol;
}
function uri(uint256) external view returns (string memory) {
return _uri;
}
function contractURI() public view returns (string memory) {
return _contractURI;
}
function _tierOf(uint256 id) internal view virtual returns (uint16);
function _isFungible(uint256 id) internal view virtual returns (bool);
function _isFungibleTier(uint16 tier) internal view virtual returns (bool);
function _supplyLimit(uint256 id) internal view virtual returns (uint256);
function _tierBounds(
uint16 tier
) internal view virtual returns (uint256, uint256);
function _getNextID(uint16 tier) internal view virtual returns (uint256);
function _incrementNextID(
uint16 tier,
uint256 amount
) internal virtual returns (uint256);
function _mintFungible(address to, uint256 id, uint256 amount) internal {
require(to != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
_fungibleBalances[id][to] += amount;
emit TransferSingle(operator, address(0), to, id, amount);
_doSafeTransferAcceptanceCheck(
operator,
address(0),
to,
id,
amount,
"0x"
);
}
function _burnFungible(address from, uint256 id, uint256 amount) internal {
require(from != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
uint256 fromBalance = _fungibleBalances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_fungibleBalances[id][from] = fromBalance - amount;
}
emit TransferSingle(operator, from, address(0), id, amount);
}
function _mintNFT(address to, uint16 tier, uint256 amount) internal {
require(to != address(0), "ERC1155: mint to the zero address");
uint256 start = _incrementNextID(tier, amount);
address from = address(0);
_nftOwnership[tier][start] = Owner({
owner: to,
burned: false,
amount: amount
});
_nftBalances[tier][to] += amount;
_nftMintCounter[tier] = start + amount - 1;
emit TransferBatch(
_msgSender(),
from,
to,
_rangeWithTier(start, amount, tier),
_repeat(1, amount)
);
}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) private {
if (_isContract(to)) {
try
IERC1155Receiver(to).onERC1155Received(
operator,
from,
id,
amount,
data
)
returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non-ERC1155Receiver implementer");
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) private {
if (_isContract(to)) {
try
IERC1155Receiver(to).onERC1155BatchReceived(
operator,
from,
ids,
amounts,
data
)
returns (bytes4 response) {
if (
response != IERC1155Receiver.onERC1155BatchReceived.selector
) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non-ERC1155Receiver implementer");
}
}
}
function _repeat(
uint256 value,
uint256 length
) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](length);
for (uint256 i = 0; i < length; i++) {
array[i] = value;
}
return array;
}
function _range(
uint256 start,
uint256 length
) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](length);
for (uint256 i = 0; i < length; i++) {
array[i] = start + i;
}
return array;
}
function _rangeWithTier(
uint256 start,
uint256 length,
uint16 tier
) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](length);
for (uint256 i = 0; i < length; i++) {
array[i] = _packID(tier, start + i);
}
return array;
}
function _isContract(address account) private view returns (bool) {
return account.code.length > 0;
}
function _unpackID(uint256 id) internal pure returns (uint16, uint256) {
uint16 tier = uint16(id & (2 ** 16 - 1));
return (tier, id >> 16);
}
function _packID(uint16 tier, uint256 id) internal pure returns (uint256) {
require(id < 2 ** 240, "ID too big");
return (id << 16) + tier;
}
}
文件 4 的 11:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 5 的 11:IERC1155.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
文件 6 的 11:IERC1155MetadataURI.sol
pragma solidity ^0.8.0;
import "../IERC1155.sol";
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
文件 7 的 11:IERC1155Receiver.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 8 的 11:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 11:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 10 的 11:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 11 的 11:Token.sol
pragma solidity ^0.8.9;
import "./ERC1155Hybrid.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
struct TokenConfig {
bool added;
bool canMint;
bool canBurn;
uint256 supplyLimit;
}
contract Token is ERC1155Hybrid, Pausable, Ownable {
uint8 public constant ROLE_MINT_FT = 1 << 0;
uint8 public constant ROLE_MINT_NFT = 1 << 1;
uint8 public constant ROLE_BATCH_MINT_NFT = 1 << 2;
uint8 public constant ROLE_BURN_FT = 1 << 3;
uint256 public constant FUNGIBLE_TOKEN_UPPER_BOUND = 2 ** 16;
uint256 _tokenUpperBound = 0;
mapping(uint16 => uint256) _tierStarts;
uint256[] _tiers;
mapping(uint16 => uint256) private _nextID;
mapping(address => uint8) _roles;
error NotAuthorized(uint8 req, address sender);
event TierAdded(string name, uint16 id, uint256 size);
mapping(uint256 => uint256) private _minted;
mapping(uint256 => TokenConfig) private _added;
modifier requireRole(uint8 req) {
if (!hasRole(_msgSender(), req)) {
revert NotAuthorized(req, _msgSender());
}
_;
}
constructor(
string memory name_,
string memory symbol_,
string memory contractURI_,
string memory uri_
) ERC1155Hybrid(name_, symbol_, contractURI_, uri_) {
addTier("Fungible Tokens", FUNGIBLE_TOKEN_UPPER_BOUND);
}
function setMetadata(
string memory name_,
string memory symbol_,
string memory contractURI_,
string memory uri_
) public onlyOwner {
_setMetadata(name_, symbol_, contractURI_, uri_);
}
function setPaused(bool b) public onlyOwner {
if (b) {
require(b && !paused(), "Contract is already paused");
_pause();
return;
}
require(!b && paused(), "Contract is not paused");
_unpause();
}
function setRole(address operator, uint8 mask) public onlyOwner {
_roles[operator] = mask;
}
function hasRole(address operator, uint8 role) public view returns (bool) {
return _roles[operator] & role == role;
}
function addTier(
string memory name,
uint256 size
) public onlyOwner returns (uint16) {
uint newTier = _tiers.length;
require(newTier < 2 ** 16, "Tier is too high.");
require(
_tokenUpperBound + size < 2 ** 240,
"Token upper bound is too high."
);
_tiers.push(size);
_tierStarts[uint16(newTier)] = _tokenUpperBound;
_tokenUpperBound += size;
emit TierAdded(name, uint16(newTier), size);
return uint16(newTier);
}
function _tierOf(uint256 id) internal pure override returns (uint16) {
(uint16 tier, ) = _unpackID(id);
return tier;
}
function _tierBounds(
uint16 tier
) internal view override returns (uint256, uint256) {
require(tier < _tiers.length, "Tier not configured.");
return (_tierStarts[tier], _tierStarts[tier] + _tiers[tier]);
}
function _getNextID(uint16 tier) internal view override returns (uint256) {
require(tier < _tiers.length, "Tier not configured.");
return _nextID[tier];
}
function _incrementNextID(
uint16 tier,
uint256 amount
) internal override returns (uint256) {
(, uint256 end) = _tierBounds(tier);
require(
_nextID[tier] + amount < end,
"Requested IDs exceed bounds of tier"
);
uint256 start = _nextID[tier];
_nextID[tier] += amount;
return start;
}
function _isFungible(uint256 id) internal pure override returns (bool) {
return _isFungibleTier(_tierOf(id));
}
function _isFungibleTier(
uint16 tier
) internal pure override returns (bool) {
return tier == 0;
}
function _supplyLimit(uint256 id) internal view override returns (uint256) {
if (!_isFungible(id)) {
return 1;
}
return _added[id].supplyLimit;
}
function totalMinted(uint256 id) public view returns (uint256) {
if (!_isFungible(id)) {
if (ownerOf(id) != address(0)) {
return 1;
} else {
return 0;
}
}
return _minted[id];
}
function supplyLimit(uint256 id) public view returns (uint256) {
return _supplyLimit(id);
}
function addFT(
uint256 supplyLimit_,
bool canMint_,
bool canBurn_
) public onlyOwner returns (uint256) {
uint256 packed = _packID(0, _incrementNextID(0, 1));
_added[packed] = TokenConfig(true, canMint_, canBurn_, supplyLimit_);
return packed;
}
function modifyFT(
uint256 id,
uint256 supplyLimit_,
bool canMint_,
bool canBurn_
) public onlyOwner {
_added[id] = TokenConfig(true, canMint_, canBurn_, supplyLimit_);
}
function mintFT(
address to,
uint256 tokenID,
uint256 quantity
) public requireRole(ROLE_MINT_FT) {
require(_isFungible(tokenID), "Token is not fungible.");
require(_added[tokenID].added, "Token type not added.");
require(_added[tokenID].canMint, "Token cannot be minted.");
require(
supplyLimit(tokenID) == 0 ||
(totalMinted(tokenID) + quantity <= supplyLimit(tokenID)),
"Mint would exceed supply limit."
);
_minted[tokenID] += quantity;
_mintFungible(to, tokenID, quantity);
}
function adminMintFT(
address to,
uint256 tokenID,
uint256 quantity
) public onlyOwner {
require(_isFungible(tokenID), "Token is not fungible.");
require(_added[tokenID].added, "Token type not added.");
require(
supplyLimit(tokenID) == 0 ||
(totalMinted(tokenID) + quantity <= supplyLimit(tokenID)),
"Mint would exceed supply limit."
);
_minted[tokenID] += quantity;
_mintFungible(to, tokenID, quantity);
}
function mintNFT(
address to,
uint16 tier,
uint256 quantity
) public requireRole(ROLE_MINT_NFT) {
require(!_isFungibleTier(tier), "Tier is fungible.");
_mintNFT(to, tier, quantity);
}
function adminMintNFT(
address to,
uint16 tier,
uint256 quantity
) public onlyOwner {
require(!_isFungibleTier(tier), "Tier is fungible.");
_mintNFT(to, tier, quantity);
}
function batchMintNFT(
address to,
uint16[] calldata tiers,
uint256[] calldata quantities
) public requireRole(ROLE_BATCH_MINT_NFT) {
require(tiers.length == quantities.length, "Array mismatch");
for (uint256 i = 0; i < tiers.length; i++) {
mintNFT(to, tiers[i], quantities[i]);
}
}
function burnFT(
address owner,
uint256 tokenID,
uint256 quantity
) public requireRole(ROLE_BURN_FT) {
require(_isFungible(tokenID), "Token is not fungible.");
require(_added[tokenID].added, "Token type not added.");
require(_added[tokenID].canBurn, "Token cannot be burned.");
_burnFungible(owner, tokenID, quantity);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) public override(ERC1155Hybrid) {
if (paused()) revert("Token is paused");
return _safeTransferFrom(from, to, id, amount, data);
}
event MetadataUpdate(uint256 _tokenId);
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
function updateMetadata(uint256 id) public onlyOwner {
emit MetadataUpdate(id);
}
function updateAllMetadata() public onlyOwner {
emit BatchMetadataUpdate(0, type(uint256).max);
}
function packID(uint16 tier, uint256 id) external pure returns (uint256) {
return _packID(tier, id);
}
function unpackID(uint256 id) external pure returns (uint16, uint256) {
return _unpackID(id);
}
}
{
"compilationTarget": {
"contracts/Token.sol": "Token"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 20000
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"contractURI_","type":"string"},{"internalType":"string","name":"uri_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"req","type":"uint8"},{"internalType":"address","name":"sender","type":"address"}],"name":"NotAuthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint16","name":"id","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"}],"name":"TierAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"FUNGIBLE_TOKEN_UPPER_BOUND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_BATCH_MINT_NFT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_BURN_FT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_MINT_FT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_MINT_NFT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"supplyLimit_","type":"uint256"},{"internalType":"bool","name":"canMint_","type":"bool"},{"internalType":"bool","name":"canBurn_","type":"bool"}],"name":"addFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"addTier","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenID","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"adminMintFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"tier","type":"uint16"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"adminMintNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint16","name":"tier","type":"uint16"}],"name":"balanceOfTier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16[]","name":"tiers","type":"uint16[]"},{"internalType":"uint256[]","name":"quantities","type":"uint256[]"}],"name":"batchMintNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"tokenID","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"burnFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint8","name":"role","type":"uint8"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenID","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"tier","type":"uint16"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"supplyLimit_","type":"uint256"},{"internalType":"bool","name":"canMint_","type":"bool"},{"internalType":"bool","name":"canBurn_","type":"bool"}],"name":"modifyFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"tier","type":"uint16"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"packID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"contractURI_","type":"string"},{"internalType":"string","name":"uri_","type":"string"}],"name":"setMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"b","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint8","name":"mask","type":"uint8"}],"name":"setRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"supplyLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpackID","outputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"updateAllMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"updateMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]