文件 1 的 14: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 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 的 14: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 的 14: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)) private _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 {
_setApprovalForAll(_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 to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, _asSingletonArray(id), _asSingletonArray(amount), data);
_balances[id][to] += amount;
emit TransferSingle(operator, address(0), to, id, amount);
_doSafeTransferAcceptanceCheck(operator, address(0), to, 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 from,
uint256 id,
uint256 amount
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
emit TransferSingle(operator, from, address(0), id, amount);
}
function _burnBatch(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
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: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
}
emit TransferBatch(operator, from, address(0), ids, amounts);
}
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 _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 的 14: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 的 14:HelmsForLoot.sol
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "contracts/LootInterfaces.sol";
import "contracts/HelmsMetadata.sol";
pragma solidity ^0.8.0;
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
}
interface IERC2981 {
function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}
interface ProxyRegistry {
function proxies(address) external view returns (address);
}
contract HelmsForLoot is ERC1155, IERC2981, Ownable {
string public PROVENANCE = "";
enum SaleState {
Paused,
Phase1,
Phase2,
Phase3
}
SaleState public state = SaleState.Paused;
bool public lootOnly = true;
ILoot private ogLootContract;
ILmart private lmartContract;
IRiftData private riftDataContract;
IHelmsMetadata public metadataContract;
mapping(ILoot => bool) private lootContracts;
mapping(ILoot => mapping(uint256 => bool)) public lootClaimed;
mapping(uint256 => bool) public lootMinted;
string public name = "Helms for Loot";
string public symbol = "H4L";
bool private wyvernProxyWhitelist = true;
bytes[5] private under19legendaryIds;
bytes[5] private over19legendaryIds;
uint256 public lootOwnerPriceCommon = 0.02 ether;
uint256 public publicPriceCommon = 0.05 ether;
uint256 public lootOwnerPriceEpic = 0.04 ether;
uint256 public publicPriceEpic = 0.07 ether;
uint256 public lootOwnerPriceLegendary = 0.06 ether;
uint256 public publicPriceLegendary = 0.09 ether;
uint256 public lootOwnerPriceMythic = 0.08 ether;
uint256 public publicPriceMythic = 0.11 ether;
event Minted(uint256 lootId);
event Claimed(uint256 lootId);
constructor(
ILoot[] memory lootsList,
ILmart lmart,
IRiftData riftData
) ERC1155("") {
for (uint256 i = 0; i < lootsList.length; i++) {
if (i == 0) {
ogLootContract = lootsList[i];
}
lootContracts[lootsList[i]] = true;
}
lmartContract = lmart;
riftDataContract = riftData;
under19legendaryIds[1] = hex"01131028039119120f7b14d2";
under19legendaryIds[2] = hex"0200109b0f441b04";
under19legendaryIds[4] = hex"01400eea06fa1c29088616e60f7c12b5";
over19legendaryIds[1] = hex"00fd148101ee0c02030a0809037013d91d501d88";
over19legendaryIds[2] = hex"064d0a68094114340b611e45";
over19legendaryIds[4] = hex"01a81d870b141087";
}
function helmRarity(uint256 lootId) public view returns (uint256) {
uint256 rand = uint256(
keccak256(abi.encodePacked("HEAD", Strings.toString(lootId)))
);
uint256 greatness = rand % 21;
uint256 kind = rand % 15;
require(kind < 6, "HelmsForLoot: no helm in bag");
if (greatness <= 14) {
return (1);
} else if (greatness < 19) {
if (findHelmIndex(under19legendaryIds[kind], lootId)) {
return (3);
}
else if (lootId == 2304 || lootId == 4557) {
return (4);
} else {
return (2);
}
} else {
if (findHelmIndex(over19legendaryIds[kind], lootId)) {
return (3);
} else {
return (4);
}
}
}
function purchasePublic(uint256[] memory lootIds) public payable {
require(!lootOnly, "HelmsForLoot: Loot-only minting period is active");
require(lootIds.length > 0, "HelmsForLoot: buy at least one");
require(lootIds.length <= 26, "HelmsForLoot: too many at once");
uint256[] memory tokenIds = new uint256[](lootIds.length);
uint256 price = 0;
for (uint256 i = 0; i < lootIds.length; i++) {
require(!lootMinted[lootIds[i]], "HelmsForLoot: already claimed");
require(
lootIds[i] > 0 && lootIds[i] < 7778,
"HelmsForLoot: invalid Loot ID"
);
uint256 rarity = helmRarity(lootIds[i]);
if (rarity == 1) {
require(
state == SaleState.Phase1 ||
state == SaleState.Phase2 ||
state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
price += publicPriceCommon;
} else if (rarity == 2) {
require(
state == SaleState.Phase2 || state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
price += publicPriceEpic;
} else if (rarity == 3) {
require(
state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
price += publicPriceLegendary;
} else {
require(
state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
price += publicPriceMythic;
}
lootMinted[lootIds[i]] = true;
tokenIds[i] = lmartContract.headId(lootIds[i]);
}
require(msg.value == price, "HelmsForLoot: wrong price");
for (uint256 i = 0; i < tokenIds.length; i++) {
_mint(msg.sender, tokenIds[i], 1, "");
emit Minted(lootIds[i]);
}
}
function purchaseMatching(
ILoot claimLoot,
uint256[] memory claimIds,
uint256[] memory lootIds,
bool claimRiftXP
) public payable {
require(
state == SaleState.Phase1 ||
state == SaleState.Phase2 ||
state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
require(lootContracts[claimLoot], "HelmsForLoot: not compatible");
if (lootOnly == true) {
require(
claimLoot == ogLootContract,
"HelmsForLoot: loot-only minting period is active."
);
}
require(lootIds.length > 0, "HelmsForLoot: buy at least one");
require(lootIds.length <= 26, "HelmsForLoot: too many at once");
uint256[] memory tokenIds = new uint256[](lootIds.length);
uint256 price = 0;
for (uint256 i = 0; i < lootIds.length; i++) {
require(
(lootIds[i] > 0 && lootIds[i] < 7778),
"HelmsForLoot: invalid Loot ID"
);
require(
claimLoot.ownerOf(claimIds[i]) == msg.sender,
"HelmsForLoot: not owner"
);
require(
keccak256(abi.encodePacked(claimLoot.getHead(claimIds[i]))) ==
keccak256(
abi.encodePacked(ogLootContract.getHead(lootIds[i]))
),
"HelmsForLoot: wrong helm"
);
require(
!lootClaimed[claimLoot][claimIds[i]],
"HelmsForLoot: bag already used for claim"
);
require(
!lootMinted[lootIds[i]],
"HelmsForLoot: loot bag already minted"
);
uint256 rarity = helmRarity(lootIds[i]);
if (rarity == 1) {
require(
state == SaleState.Phase1 ||
state == SaleState.Phase2 ||
state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
price += lootOwnerPriceCommon;
} else if (rarity == 2) {
require(
state == SaleState.Phase2 || state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
price += lootOwnerPriceEpic;
} else if (rarity == 3) {
require(
state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
price += lootOwnerPriceLegendary;
} else {
require(
state == SaleState.Phase3,
"HelmsForLoot: sale not active"
);
price += lootOwnerPriceMythic;
}
lootMinted[lootIds[i]] = true;
lootClaimed[claimLoot][claimIds[i]] = true;
tokenIds[i] = lmartContract.headId(lootIds[i]);
}
require(msg.value == price, "HelmsForLoot: wrong price");
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 riftId;
if (claimRiftXP == true) {
if (claimLoot != ogLootContract && claimIds[i] < 8001) {
riftId = claimIds[i] + 9997460;
} else {
riftId = claimIds[i];
}
riftDataContract.addXP(200, riftId);
}
_mint(msg.sender, tokenIds[i], 1, "");
emit Claimed(lootIds[i]);
}
}
function uri(uint256 tokenId) public view override returns (string memory) {
require(
address(metadataContract) != address(0),
"HelmsForLoot: no metadata address"
);
return metadataContract.uri(tokenId);
}
function lootClaimedBatched(ILoot loot, uint256[] calldata ids)
public
view
returns (bool[] memory claimed)
{
claimed = new bool[](ids.length);
for (uint256 i = 0; i < ids.length; i++) {
claimed[i] = lootClaimed[loot][ids[i]];
}
}
function lootMintedBatched(uint256[] calldata ids)
public
view
returns (bool[] memory minted)
{
minted = new bool[](ids.length);
for (uint256 i = 0; i < ids.length; i++) {
minted[i] = lootMinted[ids[i]];
}
}
function findHelmIndex(bytes storage data, uint256 helmId)
internal
view
returns (bool found)
{
for (uint256 i = 0; i < data.length / 2; i++) {
if (
uint8(data[i * 2]) == ((helmId >> 8) & 0xFF) &&
uint8(data[i * 2 + 1]) == (helmId & 0xFF)
) {
return true;
}
}
return false;
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override
returns (bool)
{
return
interfaceId == type(IERC2981).interfaceId ||
super.supportsInterface(interfaceId);
}
function royaltyInfo(uint256, uint256 salePrice)
external
view
override
returns (address receiver, uint256 royaltyAmount)
{
receiver = owner();
royaltyAmount = (salePrice * 5) / 100;
}
function isApprovedForAll(address owner, address operator)
public
view
override
returns (bool)
{
if (wyvernProxyWhitelist == true) {
if (block.chainid == 4) {
if (
ProxyRegistry(0xF57B2c51dED3A29e6891aba85459d600256Cf317)
.proxies(owner) == operator
) {
return true;
}
} else if (block.chainid == 1) {
if (
ProxyRegistry(0xa5409ec958C83C3f309868babACA7c86DCB077c1)
.proxies(owner) == operator
) {
return true;
}
}
}
return ERC1155.isApprovedForAll(owner, operator);
}
function setProvenance(string calldata prov) public onlyOwner {
PROVENANCE = prov;
}
function setState(SaleState newState, bool newlootOnly) public onlyOwner {
state = newState;
lootOnly = newlootOnly;
}
function setMetadataContract(IHelmsMetadata addr) public onlyOwner {
metadataContract = addr;
}
function setWyvernProxyWhitelist(bool enabled) public onlyOwner {
wyvernProxyWhitelist = enabled;
}
function ownerClaim(uint256[] memory lootIds, address to)
public
payable
onlyOwner
{
for (uint256 i = 0; i < lootIds.length; i++) {
require(lootIds[i] > 7777 && lootIds[i] < 8001, "Token ID invalid");
lootMinted[lootIds[i]] = true;
uint256 tokenId = lmartContract.headId(lootIds[i]);
_mint(to, tokenId, 1, "");
emit Minted(lootIds[i]);
}
}
function id(uint256 lootId) public view returns (uint256 headId) {
return lmartContract.headId(lootId);
}
function setPricesCommon(uint256 newlootOwnerPrice, uint256 newPublicPrice)
public
onlyOwner
{
lootOwnerPriceCommon = newlootOwnerPrice;
publicPriceCommon = newPublicPrice;
}
function setPricesEpic(uint256 newlootOwnerPrice, uint256 newPublicPrice)
public
onlyOwner
{
lootOwnerPriceEpic = newlootOwnerPrice;
publicPriceEpic = newPublicPrice;
}
function setPricesLegendary(
uint256 newlootOwnerPrice,
uint256 newPublicPrice
) public onlyOwner {
lootOwnerPriceLegendary = newlootOwnerPrice;
publicPriceLegendary = newPublicPrice;
}
function setPricesMythic(uint256 newlootOwnerPrice, uint256 newPublicPrice)
public
onlyOwner
{
lootOwnerPriceMythic = newlootOwnerPrice;
publicPriceMythic = newPublicPrice;
}
function withdrawAll() public payable onlyOwner {
require(payable(msg.sender).send(address(this).balance));
}
function withdrawAllERC20(IERC20 erc20Token) public onlyOwner {
require(
erc20Token.transfer(msg.sender, erc20Token.balanceOf(address(this)))
);
}
}
文件 6 的 14:HelmsMetadata.sol
import "@openzeppelin/contracts/access/Ownable.sol";
import "base64-sol/base64.sol";
import "contracts/LootInterfaces.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
pragma solidity ^0.8.0;
interface IHelmsMetadata {
function uri(uint256 tokenId) external view returns (string memory);
}
contract HelmsMetadata is Ownable, IHelmsMetadata {
string public description;
string public baseUri;
string private imageUriSuffix = ".gif";
string private animationUriSuffix = ".glb";
ILmart private lmartContract;
constructor(ILmart lmart, string memory IpfsUri) Ownable() {
description = "Helms (for Loot) is the first 3D interpretation of the helms of Loot. Adventurers, builders, and artists are encouraged to reference Helms (for Loot) to further expand on the imagination of Loot.";
lmartContract = lmart;
baseUri = IpfsUri;
}
function setDescription(string memory desc) public onlyOwner {
description = desc;
}
function setbaseUri(string calldata newbaseUri) public onlyOwner {
baseUri = newbaseUri;
}
function setUriSuffix(
string calldata newImageUriSuffix,
string calldata newAnimationUriSuffix
) public onlyOwner {
imageUriSuffix = newImageUriSuffix;
animationUriSuffix = newAnimationUriSuffix;
}
function uri(uint256 tokenId) public view override returns (string memory) {
string memory name = lmartContract.tokenName(tokenId);
bytes memory tokenUri = abi.encodePacked(
baseUri,
"/",
Strings.toString(tokenId)
);
string memory json = Base64.encode(
bytes(
string(
abi.encodePacked(
'{ "name": "',
name,
'", ',
'"description": ',
'"Helms (for Loot) is the first 3D interpretation of the helms of Loot. Adventurers, builders, and artists are encouraged to reference Helms (for Loot) to further expand on the imagination of Loot.", ',
'"image": ',
'"',
tokenUri,
imageUriSuffix,
'", '
'"animation_url": ',
'"',
tokenUri,
animationUriSuffix,
'"'
"}"
)
)
)
);
return string(abi.encodePacked("data:application/json;base64,", json));
}
}
文件 7 的 14: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;
}
文件 8 的 14:IERC1155MetadataURI.sol
pragma solidity ^0.8.0;
import "../IERC1155.sol";
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
文件 9 的 14: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);
}
文件 10 的 14:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 11 的 14:LootInterfaces.sol
pragma solidity ^0.8.0;
interface ILoot {
function ownerOf(uint256 tokenId) external view returns (address owner);
function balanceOf(address owner) external view returns (uint256 balance);
function tokenOfOwnerByIndex(address owner, uint256 index)
external
view
returns (uint256 tokenId);
function tokenByIndex(uint256 index) external view returns (uint256);
function getHead(uint256 tokenId) external view returns (string memory);
}
interface ILmart {
function headId(uint256 tokenId) external pure returns (uint256);
function tokenName(uint256 id) external view returns (string memory);
}
interface IRiftData {
function addXP(uint256 xp, uint256 bagId) external;
}
文件 12 的 14: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());
}
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 {
_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);
}
}
文件 13 的 14:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
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);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
文件 14 的 14:base64.sol
pragma solidity >=0.6.0;
library Base64 {
string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
bytes internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000"
hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000"
hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000"
hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000";
function encode(bytes memory data) internal pure returns (string memory) {
if (data.length == 0) return '';
string memory table = TABLE_ENCODE;
uint256 encodedLen = 4 * ((data.length + 2) / 3);
string memory result = new string(encodedLen + 32);
assembly {
mstore(result, encodedLen)
let tablePtr := add(table, 1)
let dataPtr := data
let endPtr := add(dataPtr, mload(data))
let resultPtr := add(result, 32)
for {} lt(dataPtr, endPtr) {}
{
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and( input, 0x3F))))
resultPtr := add(resultPtr, 1)
}
switch mod(mload(data), 3)
case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
}
return result;
}
function decode(string memory _data) internal pure returns (bytes memory) {
bytes memory data = bytes(_data);
if (data.length == 0) return new bytes(0);
require(data.length % 4 == 0, "invalid base64 decoder input");
bytes memory table = TABLE_DECODE;
uint256 decodedLen = (data.length / 4) * 3;
bytes memory result = new bytes(decodedLen + 32);
assembly {
let lastBytes := mload(add(data, mload(data)))
if eq(and(lastBytes, 0xFF), 0x3d) {
decodedLen := sub(decodedLen, 1)
if eq(and(lastBytes, 0xFFFF), 0x3d3d) {
decodedLen := sub(decodedLen, 1)
}
}
mstore(result, decodedLen)
let tablePtr := add(table, 1)
let dataPtr := data
let endPtr := add(dataPtr, mload(data))
let resultPtr := add(result, 32)
for {} lt(dataPtr, endPtr) {}
{
dataPtr := add(dataPtr, 4)
let input := mload(dataPtr)
let output := add(
add(
shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)),
shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))),
add(
shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)),
and(mload(add(tablePtr, and( input , 0xFF))), 0xFF)
)
)
mstore(resultPtr, shl(232, output))
resultPtr := add(resultPtr, 3)
}
}
return result;
}
}
{
"compilationTarget": {
"contracts/HelmsForLoot.sol": "HelmsForLoot"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ILoot[]","name":"lootsList","type":"address[]"},{"internalType":"contract ILmart","name":"lmart","type":"address"},{"internalType":"contract IRiftData","name":"riftData","type":"address"}],"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":false,"internalType":"uint256","name":"lootId","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lootId","type":"uint256"}],"name":"Minted","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":[],"name":"PROVENANCE","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":[{"internalType":"uint256","name":"lootId","type":"uint256"}],"name":"helmRarity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lootId","type":"uint256"}],"name":"id","outputs":[{"internalType":"uint256","name":"headId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ILoot","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lootClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ILoot","name":"loot","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"lootClaimedBatched","outputs":[{"internalType":"bool[]","name":"claimed","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lootMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"lootMintedBatched","outputs":[{"internalType":"bool[]","name":"minted","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootOnly","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootOwnerPriceCommon","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootOwnerPriceEpic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootOwnerPriceLegendary","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootOwnerPriceMythic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataContract","outputs":[{"internalType":"contract IHelmsMetadata","name":"","type":"address"}],"stateMutability":"view","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":"lootIds","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"ownerClaim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"publicPriceCommon","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicPriceEpic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicPriceLegendary","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicPriceMythic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ILoot","name":"claimLoot","type":"address"},{"internalType":"uint256[]","name":"claimIds","type":"uint256[]"},{"internalType":"uint256[]","name":"lootIds","type":"uint256[]"},{"internalType":"bool","name":"claimRiftXP","type":"bool"}],"name":"purchaseMatching","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"lootIds","type":"uint256[]"}],"name":"purchasePublic","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","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":"contract IHelmsMetadata","name":"addr","type":"address"}],"name":"setMetadataContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newlootOwnerPrice","type":"uint256"},{"internalType":"uint256","name":"newPublicPrice","type":"uint256"}],"name":"setPricesCommon","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newlootOwnerPrice","type":"uint256"},{"internalType":"uint256","name":"newPublicPrice","type":"uint256"}],"name":"setPricesEpic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newlootOwnerPrice","type":"uint256"},{"internalType":"uint256","name":"newPublicPrice","type":"uint256"}],"name":"setPricesLegendary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newlootOwnerPrice","type":"uint256"},{"internalType":"uint256","name":"newPublicPrice","type":"uint256"}],"name":"setPricesMythic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"prov","type":"string"}],"name":"setProvenance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum HelmsForLoot.SaleState","name":"newState","type":"uint8"},{"internalType":"bool","name":"newlootOnly","type":"bool"}],"name":"setState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setWyvernProxyWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"enum HelmsForLoot.SaleState","name":"","type":"uint8"}],"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":"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":[],"name":"withdrawAll","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"erc20Token","type":"address"}],"name":"withdrawAllERC20","outputs":[],"stateMutability":"nonpayable","type":"function"}]