文件 1 的 18:Address.sol
pragma solidity ^0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(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) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 18: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 的 18:ERC1155.sol
pragma solidity ^0.8.0;
import "./IERC1155.sol";
import "./IERC1155Receiver.sol";
import "./extensions/IERC1155MetadataURI.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
using Address for address;
mapping(uint256 => mapping(address => uint256)) internal _balances;
mapping(address => mapping(address => bool)) private _operatorApprovals;
string private _uri;
constructor(string memory uri_) {
_setURI(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 uri(uint256) public view virtual override returns (string memory) {
return _uri;
}
function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
require(account != address(0), "ERC1155: balance query for the zero address");
return _balances[id][account];
}
function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
public
view
virtual
override
returns (uint256[] memory)
{
require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
return batchBalances;
}
function setApprovalForAll(address operator, bool approved) public virtual override {
require(_msgSender() != operator, "ERC1155: setting approval status for self");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
return _operatorApprovals[account][operator];
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not owner nor approved"
);
_safeTransferFrom(from, to, id, amount, data);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: transfer caller is not owner nor approved"
);
_safeBatchTransferFrom(from, to, ids, amounts, data);
}
function _safeTransferFrom(
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();
_beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
emit TransferSingle(operator, from, to, id, amount);
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
}
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
}
emit TransferBatch(operator, from, to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
}
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
function _mint(
address account,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(account != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);
_balances[id][account] += amount;
emit TransferSingle(operator, address(0), account, id, amount);
_doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
}
function _mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; i++) {
_balances[ids[i]][to] += amounts[i];
}
emit TransferBatch(operator, address(0), to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
}
function _burn(
address account,
uint256 id,
uint256 amount
) internal virtual {
require(account != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
uint256 accountBalance = _balances[id][account];
require(accountBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][account] = accountBalance - amount;
}
emit TransferSingle(operator, account, address(0), id, amount);
}
function _burnBatch(
address account,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
require(account != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, account, address(0), ids, amounts, "");
for (uint256 i = 0; i < ids.length; i++) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 accountBalance = _balances[id][account];
require(accountBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][account] = accountBalance - amount;
}
}
emit TransferBatch(operator, account, address(0), ids, amounts);
}
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) private {
if (to.isContract()) {
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 (to.isContract()) {
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 _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](1);
array[0] = element;
return array;
}
}
文件 4 的 18: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 的 18: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 的 18:IERC1155MetadataURI.sol
pragma solidity ^0.8.0;
import "../IERC1155.sol";
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
文件 7 的 18: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 的 18:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 18:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 10 的 18:IERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 11 的 18:ILootmart.sol
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
interface ILootmart {
function itemTypeFor(uint256 tokenId) external view returns (string memory);
function nameFor(uint256 tokenId) external view returns (string memory);
}
文件 12 的 18:LootComponents.sol
pragma solidity ^0.8.0;
contract LootComponents {
string[] internal weapons = [
"Warhammer",
"Quarterstaff",
"Maul",
"Mace",
"Club",
"Katana",
"Falchion",
"Scimitar",
"Long Sword",
"Short Sword",
"Ghost Wand",
"Grave Wand",
"Bone Wand",
"Wand",
"Grimoire",
"Chronicle",
"Tome",
"Book"
];
uint256 constant weaponsLength = 18;
string[] internal chestArmor = [
"Divine Robe",
"Silk Robe",
"Linen Robe",
"Robe",
"Shirt",
"Demon Husk",
"Dragonskin Armor",
"Studded Leather Armor",
"Hard Leather Armor",
"Leather Armor",
"Holy Chestplate",
"Ornate Chestplate",
"Plate Mail",
"Chain Mail",
"Ring Mail"
];
uint256 constant chestLength = 15;
string[] internal headArmor = [
"Ancient Helm",
"Ornate Helm",
"Great Helm",
"Full Helm",
"Helm",
"Demon Crown",
"Dragon's Crown",
"War Cap",
"Leather Cap",
"Cap",
"Crown",
"Divine Hood",
"Silk Hood",
"Linen Hood",
"Hood"
];
uint256 constant headLength = 15;
string[] internal waistArmor = [
"Ornate Belt",
"War Belt",
"Plated Belt",
"Mesh Belt",
"Heavy Belt",
"Demonhide Belt",
"Dragonskin Belt",
"Studded Leather Belt",
"Hard Leather Belt",
"Leather Belt",
"Brightsilk Sash",
"Silk Sash",
"Wool Sash",
"Linen Sash",
"Sash"
];
uint256 constant waistLength = 15;
string[] internal footArmor = [
"Holy Greaves",
"Ornate Greaves",
"Greaves",
"Chain Boots",
"Heavy Boots",
"Demonhide Boots",
"Dragonskin Boots",
"Studded Leather Boots",
"Hard Leather Boots",
"Leather Boots",
"Divine Slippers",
"Silk Slippers",
"Wool Shoes",
"Linen Shoes",
"Shoes"
];
uint256 constant footLength = 15;
string[] internal handArmor = [
"Holy Gauntlets",
"Ornate Gauntlets",
"Gauntlets",
"Chain Gloves",
"Heavy Gloves",
"Demon's Hands",
"Dragonskin Gloves",
"Studded Leather Gloves",
"Hard Leather Gloves",
"Leather Gloves",
"Divine Gloves",
"Silk Gloves",
"Wool Gloves",
"Linen Gloves",
"Gloves"
];
uint256 constant handLength = 15;
string[] internal necklaces = [
"Necklace",
"Amulet",
"Pendant"
];
uint256 constant necklacesLength = 3;
string[] internal rings = [
"Gold Ring",
"Silver Ring",
"Bronze Ring",
"Platinum Ring",
"Titanium Ring"
];
uint256 constant ringsLength = 5;
string[] internal suffixes = [
"of Power",
"of Giants",
"of Titans",
"of Skill",
"of Perfection",
"of Brilliance",
"of Enlightenment",
"of Protection",
"of Anger",
"of Rage",
"of Fury",
"of Vitriol",
"of the Fox",
"of Detection",
"of Reflection",
"of the Twins"
];
uint256 constant suffixesLength = 16;
string[] internal namePrefixes = [
"Agony",
"Apocalypse",
"Armageddon",
"Beast",
"Behemoth",
"Blight",
"Blood",
"Bramble",
"Brimstone",
"Brood",
"Carrion",
"Cataclysm",
"Chimeric",
"Corpse",
"Corruption",
"Damnation",
"Death",
"Demon",
"Dire",
"Dragon",
"Dread",
"Doom",
"Dusk",
"Eagle",
"Empyrean",
"Fate",
"Foe",
"Gale",
"Ghoul",
"Gloom",
"Glyph",
"Golem",
"Grim",
"Hate",
"Havoc",
"Honour",
"Horror",
"Hypnotic",
"Kraken",
"Loath",
"Maelstrom",
"Mind",
"Miracle",
"Morbid",
"Oblivion",
"Onslaught",
"Pain",
"Pandemonium",
"Phoenix",
"Plague",
"Rage",
"Rapture",
"Rune",
"Skull",
"Sol",
"Soul",
"Sorrow",
"Spirit",
"Storm",
"Tempest",
"Torment",
"Vengeance",
"Victory",
"Viper",
"Vortex",
"Woe",
"Wrath",
"Light's",
"Shimmering"
];
uint256 constant namePrefixesLength = 69;
string[] internal nameSuffixes = [
"Bane",
"Root",
"Bite",
"Song",
"Roar",
"Grasp",
"Instrument",
"Glow",
"Bender",
"Shadow",
"Whisper",
"Shout",
"Growl",
"Tear",
"Peak",
"Form",
"Sun",
"Moon"
];
uint256 constant nameSuffixesLength = 18;
function random(string memory input) internal pure returns (uint256) {
return uint256(keccak256(abi.encodePacked(input)));
}
function weaponComponents(uint256 tokenId)
internal
pure
returns (uint256[5] memory)
{
return pluck(tokenId, "WEAPON", weaponsLength);
}
function chestComponents(uint256 tokenId)
internal
pure
returns (uint256[5] memory)
{
return pluck(tokenId, "CHEST", chestLength);
}
function headComponents(uint256 tokenId)
internal
pure
returns (uint256[5] memory)
{
return pluck(tokenId, "HEAD", headLength);
}
function waistComponents(uint256 tokenId)
internal
pure
returns (uint256[5] memory)
{
return pluck(tokenId, "WAIST", waistLength);
}
function footComponents(uint256 tokenId)
internal
pure
returns (uint256[5] memory)
{
return pluck(tokenId, "FOOT", footLength);
}
function handComponents(uint256 tokenId)
internal
pure
returns (uint256[5] memory)
{
return pluck(tokenId, "HAND", handLength);
}
function neckComponents(uint256 tokenId)
internal
pure
returns (uint256[5] memory)
{
return pluck(tokenId, "NECK", necklacesLength);
}
function ringComponents(uint256 tokenId)
internal
pure
returns (uint256[5] memory)
{
return pluck(tokenId, "RING", ringsLength);
}
function pluck(
uint256 tokenId,
string memory keyPrefix,
uint256 sourceArrayLength
) internal pure returns (uint256[5] memory) {
uint256[5] memory components;
uint256 rand = random(
string(abi.encodePacked(keyPrefix, toString(tokenId)))
);
components[0] = rand % sourceArrayLength;
components[1] = 0;
components[2] = 0;
uint256 greatness = rand % 21;
if (greatness > 14) {
components[1] = (rand % suffixesLength) + 1;
}
if (greatness >= 19) {
components[2] = (rand % namePrefixesLength) + 1;
components[3] = (rand % nameSuffixesLength) + 1;
if (greatness == 19) {
} else {
components[4] = 1;
}
}
return components;
}
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
}
文件 13 的 18:LootTokensMetadata.sol
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
import "./LootComponents.sol";
import "./TokenId.sol";
import "./ILootmart.sol";
import {Base64, toString} from "./MetadataUtils.sol";
struct ItemIds {
uint256 weapon;
uint256 chest;
uint256 head;
uint256 waist;
uint256 foot;
uint256 hand;
uint256 neck;
uint256 ring;
}
struct ItemNames {
string weapon;
string chest;
string head;
string waist;
string foot;
string hand;
string neck;
string ring;
}
contract LootTokensMetadata is ILootmart, LootComponents {
uint256 internal constant WEAPON = 0x0;
uint256 internal constant CHEST = 0x1;
uint256 internal constant HEAD = 0x2;
uint256 internal constant WAIST = 0x3;
uint256 internal constant FOOT = 0x4;
uint256 internal constant HAND = 0x5;
uint256 internal constant NECK = 0x6;
uint256 internal constant RING = 0x7;
string[] internal itemTypes = [
"weapon",
"chest",
"head",
"waist",
"foot",
"hand",
"neck",
"ring"
];
string public baseURI;
constructor(string memory _baseURI) {
baseURI = _baseURI;
}
function name() external pure returns (string memory) {
return "Lootmart";
}
function symbol() external pure returns (string memory) {
return "MART";
}
function setBaseURI(string memory _newBaseURI) external {
baseURI = _newBaseURI;
}
function tokenURI(uint256 tokenId) public view returns (string memory) {
string memory json = Base64.encode(
bytes(
string(
abi.encodePacked(
'{',
'"name": "', nameFor(tokenId),'", ',
'"description": "', nameFor(tokenId), '\\n\\n', 'Lootmart items are individual Loot items that you can trade and use to upgrade your Adventurer. Different combinations of Loot items unlock special abilities and powers.", ',
'"image": ', '"', baseURI, '/', toString(tokenId), '.png", ',
'"attributes": ', attributes(tokenId),
'}'
)
)
)
);
return string(
abi.encodePacked("data:application/json;base64,", json)
);
}
function attributes(uint256 id) public view returns (string memory) {
(uint256[5] memory components, uint256 itemType) = TokenId.fromId(id);
string memory slot = itemTypes[itemType];
string memory res = string(abi.encodePacked('[', trait("Item Type", slot)));
string memory item = itemName(itemType, components[0]);
res = string(abi.encodePacked(res, ", ", trait("Name", item)));
if (components[1] > 0) {
string memory data = suffixes[components[1] - 1];
res = string(abi.encodePacked(res, ", ", trait("Suffix", data)));
}
if (components[2] > 0) {
string memory data = namePrefixes[components[2] - 1];
res = string(abi.encodePacked(res, ", ", trait("Name Prefix", data)));
}
if (components[3] > 0) {
string memory data = nameSuffixes[components[3] - 1];
res = string(abi.encodePacked(res, ", ", trait("Name Suffix", data)));
}
if (components[4] > 0) {
res = string(abi.encodePacked(res, ", ", trait("Augmentation", "Yes")));
}
res = string(abi.encodePacked(res, ']'));
return res;
}
function itemTypeFor(uint256 id) external pure override returns (string memory) {
(, uint256 _itemType) = TokenId.fromId(id);
return [
"weapon",
"chest",
"head",
"waist",
"foot",
"hand",
"neck",
"ring"
][_itemType];
}
function trait(string memory _traitType, string memory _value) internal pure returns (string memory) {
return string(abi.encodePacked('{',
'"trait_type": "', _traitType, '", ',
'"value": "', _value, '"',
'}'));
}
function nameFor(uint256 id) public override view returns (string memory) {
(uint256[5] memory components, uint256 itemType) = TokenId.fromId(id);
return componentsToString(components, itemType);
}
function itemName(uint256 itemType, uint256 idx) public view returns (string memory) {
string[] storage arr;
if (itemType == WEAPON) {
arr = weapons;
} else if (itemType == CHEST) {
arr = chestArmor;
} else if (itemType == HEAD) {
arr = headArmor;
} else if (itemType == WAIST) {
arr = waistArmor;
} else if (itemType == FOOT) {
arr = footArmor;
} else if (itemType == HAND) {
arr = handArmor;
} else if (itemType == NECK) {
arr = necklaces;
} else if (itemType == RING) {
arr = rings;
} else {
revert("Unexpected armor piece");
}
return arr[idx];
}
function componentsToString(uint256[5] memory components, uint256 itemType)
public
view
returns (string memory)
{
string memory item = itemName(itemType, components[0]);
if (components[1] > 0) {
item = string(
abi.encodePacked(item, " ", suffixes[components[1] - 1])
);
}
if (components[2] > 0) {
string memory namePrefixSuffix = string(
abi.encodePacked("'", namePrefixes[components[2] - 1])
);
if (components[3] > 0) {
namePrefixSuffix = string(
abi.encodePacked(namePrefixSuffix, " ", nameSuffixes[components[3] - 1])
);
}
namePrefixSuffix = string(abi.encodePacked(namePrefixSuffix, "' "));
item = string(abi.encodePacked(namePrefixSuffix, item));
}
if (components[4] > 0) {
item = string(abi.encodePacked(item, " +1"));
}
return item;
}
function weaponId(uint256 tokenId) public pure returns (uint256) {
return TokenId.toId(weaponComponents(tokenId), WEAPON);
}
function chestId(uint256 tokenId) public pure returns (uint256) {
return TokenId.toId(chestComponents(tokenId), CHEST);
}
function headId(uint256 tokenId) public pure returns (uint256) {
return TokenId.toId(headComponents(tokenId), HEAD);
}
function waistId(uint256 tokenId) public pure returns (uint256) {
return TokenId.toId(waistComponents(tokenId), WAIST);
}
function footId(uint256 tokenId) public pure returns (uint256) {
return TokenId.toId(footComponents(tokenId), FOOT);
}
function handId(uint256 tokenId) public pure returns (uint256) {
return TokenId.toId(handComponents(tokenId), HAND);
}
function neckId(uint256 tokenId) public pure returns (uint256) {
return TokenId.toId(neckComponents(tokenId), NECK);
}
function ringId(uint256 tokenId) public pure returns (uint256) {
return TokenId.toId(ringComponents(tokenId), RING);
}
function ids(uint256 tokenId) public pure returns (ItemIds memory) {
return
ItemIds({
weapon: weaponId(tokenId),
chest: chestId(tokenId),
head: headId(tokenId),
waist: waistId(tokenId),
foot: footId(tokenId),
hand: handId(tokenId),
neck: neckId(tokenId),
ring: ringId(tokenId)
});
}
function idsMany(uint256[] memory tokenIds) public pure returns (ItemIds[] memory) {
ItemIds[] memory itemids = new ItemIds[](tokenIds.length);
for (uint256 i = 0; i < tokenIds.length; i++) {
itemids[i] = ids(tokenIds[i]);
}
return itemids;
}
function names(uint256 tokenId) public view returns (ItemNames memory) {
ItemIds memory items = ids(tokenId);
return
ItemNames({
weapon: nameFor(items.weapon),
chest: nameFor(items.chest),
head: nameFor(items.head),
waist: nameFor(items.waist),
foot: nameFor(items.foot),
hand: nameFor(items.hand),
neck: nameFor(items.neck),
ring: nameFor(items.ring)
});
}
function namesMany(uint256[] memory tokenNames) public view returns (ItemNames[] memory) {
ItemNames[] memory itemNames = new ItemNames[](tokenNames.length);
for (uint256 i = 0; i < tokenNames.length; i++) {
itemNames[i] = names(tokenNames[i]);
}
return itemNames;
}
}
文件 14 的 18:Lootmart.sol
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./LootTokensMetadata.sol";
import "./LootmartId.sol";
interface ILootAirdrop {
function claimForLoot(uint256) external payable;
function safeTransferFrom(address, address, uint256) external payable;
}
interface IAdventurer {
function mint() external;
function mintToAccount(address _account) external;
function totalSupply() external returns (uint256);
function equipBulk(uint256 tokenId, address[] memory itemAddresses, uint256[] memory itemIds) external;
function equip(uint256 tokenId, address itemAddress, uint256 itemId) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
}
library Errors {
string constant DoesNotOwnLootbag = "you do not own the lootbag for this airdrop";
string constant IsNotLoot = "msg.sender is not the loot contract";
}
contract Lootmart is Ownable, ERC1155, LootTokensMetadata {
IERC721Enumerable immutable loot;
IAdventurer immutable adventurer;
mapping(uint256 => bool) public claimedByTokenId;
uint256 public tokenIdStart = 1;
uint256 public tokenIdEnd = 8000;
constructor(address _loot, address _adventurer, string memory _baseURI) ERC1155("") LootTokensMetadata(_baseURI) {
loot = IERC721Enumerable(_loot);
adventurer = IAdventurer(_adventurer);
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155) returns (bool) {
return
interfaceId == LootmartId.INTERFACE_ID ||
super.supportsInterface(interfaceId);
}
function claimForLoot(uint256 tokenId) external {
_claim(tokenId, _msgSender());
}
function claimAllForOwner() external {
uint256 tokenBalanceOwner = loot.balanceOf(_msgSender());
require(tokenBalanceOwner > 0, "NO_TOKENS_OWNED");
for (uint256 i = 0; i < tokenBalanceOwner; i++) {
_claim(loot.tokenOfOwnerByIndex(_msgSender(), i), _msgSender());
}
}
function claimForTokenIds(uint256[] memory tokenIds) external {
for (uint256 i = 0; i < tokenIds.length; i++) {
_claim(tokenIds[i], _msgSender());
}
}
function claimForLootWithAdventurer(uint256 tokenId) external {
_claim(tokenId, _msgSender());
adventurer.mintToAccount(_msgSender());
}
function claimAllForOwnerWithAdventurer() external {
uint256 tokenBalanceOwner = loot.balanceOf(_msgSender());
require(tokenBalanceOwner > 0, "NO_TOKENS_OWNED");
for (uint256 i = 0; i < tokenBalanceOwner; i++) {
_claim(loot.tokenOfOwnerByIndex(_msgSender(), i), _msgSender());
}
adventurer.mintToAccount(_msgSender());
}
function claimForTokenIdsWithAdventurer(uint256[] memory tokenIds) external {
for (uint256 i = 0; i < tokenIds.length; i++) {
_claim(tokenIds[i], _msgSender());
}
adventurer.mintToAccount(_msgSender());
}
function _claim(uint256 tokenId, address tokenOwner) internal {
require(tokenOwner == loot.ownerOf(tokenId), "MUST_OWN_TOKEN_ID");
require(tokenId >= tokenIdStart && tokenId <= tokenIdEnd, "TOKEN_ID_OUT_OF_RANGE");
require(!claimedByTokenId[tokenId], "ALREADY_CLAIMED");
claimedByTokenId[tokenId] = true;
uint256[] memory ids = new uint256[](8);
uint256[] memory amounts = new uint256[](8);
ids[0] = itemId(tokenId, weaponComponents, WEAPON);
ids[1] = itemId(tokenId, chestComponents, CHEST);
ids[2] = itemId(tokenId, headComponents, HEAD);
ids[3] = itemId(tokenId, waistComponents, WAIST);
ids[4] = itemId(tokenId, footComponents, FOOT);
ids[5] = itemId(tokenId, handComponents, HAND);
ids[6] = itemId(tokenId, neckComponents, NECK);
ids[7] = itemId(tokenId, ringComponents, RING);
for (uint256 i = 0; i < ids.length; i++) {
amounts[i] = 1;
_balances[ids[i]][tokenOwner] += 1;
}
emit TransferBatch(_msgSender(), address(0), tokenOwner, ids, amounts);
}
function itemId(
uint256 tokenId,
function(uint256) view returns (uint256[5] memory) componentsFn,
uint256 itemType
) private view returns (uint256) {
uint256[5] memory components = componentsFn(tokenId);
return TokenId.toId(components, itemType);
}
function uri(uint256 tokenId) public view override returns (string memory) {
return tokenURI(tokenId);
}
function toBytes(uint256 x) internal pure returns (bytes memory b) {
b = new bytes(32);
assembly { mstore(add(b, 32), x) }
}
}
文件 15 的 18:LootmartId.sol
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
library LootmartId {
bytes4 internal constant INTERFACE_ID = 0xf35e2fbc;
}
文件 16 的 18:MetadataUtils.sol
pragma solidity ^0.8.0;
function toString(uint256 value) pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
library Base64 {
bytes internal constant TABLE =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
function encode(bytes memory data) internal pure returns (string memory) {
uint256 len = data.length;
if (len == 0) return "";
uint256 encodedLen = 4 * ((len + 2) / 3);
bytes memory result = new bytes(encodedLen + 32);
bytes memory table = TABLE;
assembly {
let tablePtr := add(table, 1)
let resultPtr := add(result, 32)
for {
let i := 0
} lt(i, len) {
} {
i := add(i, 3)
let input := and(mload(add(data, i)), 0xffffff)
let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
out := shl(8, out)
out := add(
out,
and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF)
)
out := shl(8, out)
out := add(
out,
and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF)
)
out := shl(8, out)
out := add(
out,
and(mload(add(tablePtr, and(input, 0x3F))), 0xFF)
)
out := shl(224, out)
mstore(resultPtr, out)
resultPtr := add(resultPtr, 4)
}
switch mod(len, 3)
case 1 {
mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
}
case 2 {
mstore(sub(resultPtr, 1), shl(248, 0x3d))
}
mstore(result, encodedLen)
}
return string(result);
}
}
文件 17 的 18: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() {
_setOwner(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 18 的 18:TokenId.sol
pragma solidity ^0.8.0;
library TokenId {
uint256 constant SHIFT = 16;
function toId(uint256[5] memory components, uint256 itemType)
internal
pure
returns (uint256)
{
uint256 id = itemType;
id += encode(components[0], 1);
id += encode(components[1], 2);
id += encode(components[2], 3);
id += encode(components[3], 4);
id += encode(components[4], 5);
return id;
}
function fromId(uint256 id)
internal
pure
returns (uint256[5] memory components, uint256 itemType)
{
itemType = decode(id, 0);
components[0] = decode(id, 1);
components[1] = decode(id, 2);
components[2] = decode(id, 3);
components[3] = decode(id, 4);
components[4] = decode(id, 5);
}
function encode(uint256 component, uint256 idx)
private
pure
returns (uint256)
{
return (component & 0xff) << (SHIFT * idx);
}
function decode(uint256 id, uint256 idx) private pure returns (uint256) {
return (id >> (SHIFT * idx)) & 0xff;
}
}
{
"compilationTarget": {
"contracts/Lootmart.sol": "Lootmart"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 10
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_loot","type":"address"},{"internalType":"address","name":"_adventurer","type":"address"},{"internalType":"string","name":"_baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"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":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"attributes","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"chestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"claimAllForOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimAllForOwnerWithAdventurer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"claimForLoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"claimForLootWithAdventurer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"claimForTokenIds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"claimForTokenIdsWithAdventurer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimedByTokenId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"components","type":"uint256[5]"},{"internalType":"uint256","name":"itemType","type":"uint256"}],"name":"componentsToString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"footId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"handId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"headId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ids","outputs":[{"components":[{"internalType":"uint256","name":"weapon","type":"uint256"},{"internalType":"uint256","name":"chest","type":"uint256"},{"internalType":"uint256","name":"head","type":"uint256"},{"internalType":"uint256","name":"waist","type":"uint256"},{"internalType":"uint256","name":"foot","type":"uint256"},{"internalType":"uint256","name":"hand","type":"uint256"},{"internalType":"uint256","name":"neck","type":"uint256"},{"internalType":"uint256","name":"ring","type":"uint256"}],"internalType":"struct ItemIds","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"idsMany","outputs":[{"components":[{"internalType":"uint256","name":"weapon","type":"uint256"},{"internalType":"uint256","name":"chest","type":"uint256"},{"internalType":"uint256","name":"head","type":"uint256"},{"internalType":"uint256","name":"waist","type":"uint256"},{"internalType":"uint256","name":"foot","type":"uint256"},{"internalType":"uint256","name":"hand","type":"uint256"},{"internalType":"uint256","name":"neck","type":"uint256"},{"internalType":"uint256","name":"ring","type":"uint256"}],"internalType":"struct ItemIds[]","name":"","type":"tuple[]"}],"stateMutability":"pure","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":"uint256","name":"itemType","type":"uint256"},{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"itemName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"itemTypeFor","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"nameFor","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"names","outputs":[{"components":[{"internalType":"string","name":"weapon","type":"string"},{"internalType":"string","name":"chest","type":"string"},{"internalType":"string","name":"head","type":"string"},{"internalType":"string","name":"waist","type":"string"},{"internalType":"string","name":"foot","type":"string"},{"internalType":"string","name":"hand","type":"string"},{"internalType":"string","name":"neck","type":"string"},{"internalType":"string","name":"ring","type":"string"}],"internalType":"struct ItemNames","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenNames","type":"uint256[]"}],"name":"namesMany","outputs":[{"components":[{"internalType":"string","name":"weapon","type":"string"},{"internalType":"string","name":"chest","type":"string"},{"internalType":"string","name":"head","type":"string"},{"internalType":"string","name":"waist","type":"string"},{"internalType":"string","name":"foot","type":"string"},{"internalType":"string","name":"hand","type":"string"},{"internalType":"string","name":"neck","type":"string"},{"internalType":"string","name":"ring","type":"string"}],"internalType":"struct ItemNames[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"neckId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ringId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","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":"_newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","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":"pure","type":"function"},{"inputs":[],"name":"tokenIdEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenIdStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"waistId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"weaponId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]