编译器
0.8.17+commit.8df45f5f
文件 1 的 14:Bonfire.sol
pragma solidity ^0.8.0;
import "@thirdweb-dev/contracts/extension/Permissions.sol";
import "@thirdweb-dev/contracts/openzeppelin-presets/security/ReentrancyGuard.sol";
import "@thirdweb-dev/contracts/openzeppelin-presets/utils/cryptography/EIP712.sol";
import "./extensions/Pausable.sol";
import "./interfaces/IBonfire.sol";
import "./interfaces/original/IOldWorldPass.sol";
import "./interfaces/original/IOldDiceNFT.sol";
import "./interfaces/IDiceNFT.sol";
import "./interfaces/IWorldPassNFT.sol";
contract Bonfire is EIP712, ReentrancyGuard, Pausable, Permissions, IBonfire {
using ECDSA for bytes32;
bytes32 private constant TYPEHASH =
keccak256(
"BurnRequest(address to,uint128 wpBurnAmount,uint256[] diceIds,uint8[] diceResults,uint8[] wpHouses,uint128 validityStartTimestamp,uint128 validityEndTimestamp,bytes32 uid)"
);
mapping(bytes32 => bool) private requestIdProcessed;
address public allowedSigner;
address public immutable originalDice;
address public immutable originalWP;
address public immutable reforgedDice;
address public immutable reforgedWP;
IOldWorldPass internal immutable oldWP;
IOldDiceNFT internal immutable oldDice;
IDiceNFT internal immutable newDice;
IWorldPassNFT internal immutable newWP;
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor(
address _originalDice,
address _originalWP,
address _reforgedDice,
address _reforgedWP,
address _allowedSigner
) EIP712("Bonfire", "1") {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(PAUSER_ROLE, msg.sender);
allowedSigner = _allowedSigner;
originalDice = _originalDice;
originalWP = _originalWP;
reforgedDice = _reforgedDice;
reforgedWP = _reforgedWP;
oldWP = IOldWorldPass(originalWP);
oldDice = IOldDiceNFT(originalDice);
newDice = IDiceNFT(reforgedDice);
newWP = IWorldPassNFT(reforgedWP);
}
function bonfireBurn(BurnRequest calldata _req, bytes calldata _signature)
external
nonReentrant
whenNotPaused
returns (address signer)
{
require(
_req.wpBurnAmount == _req.wpHouses.length,
"Unequal wpBurnAmount & wpHouses"
);
require(
_req.wpBurnAmount > 0 || _req.diceIds.length > 0,
"Nothing to burn"
);
signer = _processRequest(_req, _signature);
if (_req.wpBurnAmount > 0) {
oldWP.burn(_req.to, 0, _req.wpBurnAmount);
}
uint256 diceBurnAmount = _req.diceIds.length;
for (uint256 i = 0; i < diceBurnAmount; ) {
if (oldDice.ownerOf(_req.diceIds[i]) != _req.to) {
revert("Only the owner of the dice can burn them");
}
oldDice.burn(_req.diceIds[i]);
unchecked {
++i;
}
}
for (uint256 i = 0; i < _req.wpHouses.length; ) {
newWP.mintWithHouseTo(_req.to, House(_req.wpHouses[i]));
unchecked {
++i;
}
}
if (diceBurnAmount > 0) {
if (diceBurnAmount == 1) {
newDice.mint(_req.to, _req.diceIds[0]);
} else {
newDice.batchMint(_req.to, _req.diceIds);
}
}
emit BonfireBurn(_req.to, _req);
}
function burnDiceOnly(uint256[] calldata diceIds)
external
nonReentrant
whenNotPaused
{
require(diceIds.length > 0, "Nothing to burn");
uint256 diceBurnAmount = diceIds.length;
for (uint256 i = 0; i < diceBurnAmount; ) {
if (oldDice.ownerOf(diceIds[i]) != msg.sender) {
revert("Only the owner of the dice can burn them");
}
oldDice.burn(diceIds[i]);
unchecked {
++i;
}
}
if (diceBurnAmount == 1) {
newDice.mint(msg.sender, diceIds[0]);
} else {
newDice.batchMint(msg.sender, diceIds);
}
emit BonfireBurnDiceOnly(msg.sender, diceIds);
}
function joinScarred(uint256 burnAmount)
external
nonReentrant
whenNotPaused
{
require(burnAmount > 0, "Cannot burn nothing");
oldWP.burn(msg.sender, 0, burnAmount);
if (burnAmount == 1) {
newWP.mintWithHouseTo(msg.sender, House.Scarred);
} else {
newWP.batchMintWithHouseTo(msg.sender, burnAmount, House.Scarred);
}
emit BonfireJoinScarred(msg.sender, burnAmount);
}
function setAllowedSigner(address _allowedSigner)
public
onlyRole(DEFAULT_ADMIN_ROLE)
{
require(_allowedSigner != address(0), "allowedSigner undefined");
allowedSigner = _allowedSigner;
}
function verify(BurnRequest calldata _req, bytes calldata _signature)
public
view
returns (bool success, address signer)
{
signer = _recoverAddress(_req, _signature);
success = !requestIdProcessed[_req.uid] && _canSignBurnRequest(signer);
}
function _canSignBurnRequest(address _signer) internal view returns (bool) {
return _signer == allowedSigner;
}
function _processRequest(
BurnRequest calldata _req,
bytes calldata _signature
) internal returns (address signer) {
bool success;
(success, signer) = verify(_req, _signature);
if (!success) {
revert("Invalid req");
}
if (
_req.validityStartTimestamp > block.timestamp ||
block.timestamp > _req.validityEndTimestamp
) {
revert("Req expired");
}
require(_req.to != address(0), "recipient undefined");
requestIdProcessed[_req.uid] = true;
}
function _recoverAddress(
BurnRequest calldata _req,
bytes calldata _signature
) internal view returns (address) {
return
_hashTypedDataV4(keccak256(_encodeRequest(_req))).recover(
_signature
);
}
function _encodeRequest(BurnRequest calldata _req)
internal
pure
returns (bytes memory)
{
return
abi.encode(
TYPEHASH,
_req.to,
_req.wpBurnAmount,
keccak256(abi.encodePacked(_req.diceIds)),
keccak256(abi.encodePacked(_req.diceResults)),
keccak256(abi.encodePacked(_req.wpHouses)),
_req.validityStartTimestamp,
_req.validityEndTimestamp,
_req.uid
);
}
function pause() external onlyRole(PAUSER_ROLE) whenNotPaused {
_pause();
}
function unpause() external onlyRole(PAUSER_ROLE) whenPaused {
_unpause();
}
}
文件 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:ECDSA.sol
pragma solidity ^0.8.0;
import "../../../lib/TWStrings.sol";
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", TWStrings.toString(s.length), s));
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
文件 4 的 14:EIP712.sol
pragma solidity ^0.8.0;
import "./ECDSA.sol";
abstract contract EIP712 {
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}
文件 5 的 14:IBonfire.sol
pragma solidity ^0.8.0;
import "./IWorldPassNFT.sol";
interface IBonfire {
struct BurnRequest {
address to;
uint128 wpBurnAmount;
uint256[] diceIds;
uint8[] diceResults;
uint8[] wpHouses;
uint128 validityStartTimestamp;
uint128 validityEndTimestamp;
bytes32 uid;
}
event BonfireBurn(address indexed mintedTo, BurnRequest burnRequest);
event BonfireBurnDiceOnly(
address indexed mintedTo,
uint256[] indexed burntDiceIDs
);
event BonfireJoinScarred(
address indexed mintedTo,
uint256 indexed burnAmount
);
function verify(BurnRequest calldata req, bytes calldata signature)
external
view
returns (bool success, address signer);
function bonfireBurn(BurnRequest calldata req, bytes calldata signature)
external
returns (address signer);
function burnDiceOnly(uint256[] calldata diceIds) external;
function joinScarred(uint256 burnAmount) external;
}
文件 6 的 14:IDiceNFT.sol
pragma solidity ^0.8.0;
enum Material {
Amber,
Amethyst,
Ruby,
Sapphire,
Spinel,
Topaz
}
enum DieType {
D4,
D6,
D8,
D10,
D12,
D20
}
enum ElementalType {
Dark,
Space,
Time,
Psychic,
Light
}
library MaterialUtil {
function toString(Material _material)
internal
pure
returns (string memory)
{
if (_material == Material.Amber) {
return "Amber";
} else if (_material == Material.Amethyst) {
return "Amethyst";
} else if (_material == Material.Ruby) {
return "Ruby";
} else if (_material == Material.Sapphire) {
return "Sapphire";
} else if (_material == Material.Spinel) {
return "Spinel";
} else {
return "Topaz";
}
}
}
library DiceTypeUtil {
function toString(DieType _type) internal pure returns (string memory) {
if (_type == DieType.D4) {
return "D4";
} else if (_type == DieType.D6) {
return "D6";
} else if (_type == DieType.D8) {
return "D8";
} else if (_type == DieType.D10) {
return "D10";
} else if (_type == DieType.D12) {
return "D12";
} else {
return "D20";
}
}
}
library ElementalTypeUtil {
function toString(ElementalType _el) internal pure returns (string memory) {
if (_el == ElementalType.Dark) {
return "Dark";
} else if (_el == ElementalType.Space) {
return "Space";
} else if (_el == ElementalType.Time) {
return "Time";
} else if (_el == ElementalType.Psychic) {
return "Psychic";
} else {
return "Light";
}
}
}
library DiceBitmapUtil {
function getDiceType(uint48 bitmap, uint8 diceIdx)
internal
pure
returns (DieType)
{
uint256 shiftAmount = diceIdx * 6;
uint8 typeBit = uint8((bitmap & (7 << shiftAmount)) >> shiftAmount);
return DieType(typeBit);
}
function getDiceMaterial(uint48 bitmap, uint8 diceIdx)
internal
pure
returns (Material)
{
uint256 shiftAmount = diceIdx * 6 + 3;
uint8 typeBit = uint8((bitmap & (7 << shiftAmount)) >> shiftAmount);
return Material(typeBit);
}
function getElementType(uint48 bitmap)
internal
pure
returns (ElementalType)
{
uint256 shiftAmount = 7 * 6;
uint8 typeBit = uint8((bitmap & (7 << shiftAmount)) >> shiftAmount);
return ElementalType(typeBit);
}
}
interface IDiceNFT {
struct DiceMetadata {
uint48 bitmap;
uint8 amount;
uint8 power;
}
event BoostUpdated(uint256 indexed tokenId, uint256 newBoostCount);
function setOriginalMetadata(
DiceMetadata[] calldata originalMetadata,
uint128 _startIndex,
uint128 _endIndex
) external;
function resetBoosts(uint256 _newDefaultBoostCount) external;
function useBoost(uint256 tokenId, uint256 count) external;
function setBoostCount(uint256 tokenId, uint16 boostCount) external;
function mint(address _to, uint256 _oldTokenId) external;
function batchMint(address _to, uint256[] calldata _oldTokenIds) external;
function getDiceBoosts(uint256 _tokenId) external view returns (uint256);
function getDiceMaterials(uint256 _tokenId)
external
view
returns (string[] memory);
function getDiceMetadata(uint256 _tokenId)
external
view
returns (DiceMetadata memory);
}
文件 7 的 14:IOldDiceNFT.sol
pragma solidity ^0.8.4;
interface IOldDiceNFT {
error ApprovalCallerNotOwnerNorApproved();
error ApprovalQueryForNonexistentToken();
error ApprovalToCurrentOwner();
error ApproveToCaller();
error BalanceQueryForZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error OwnerQueryForNonexistentToken();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TransferToNonERC721ReceiverImplementer();
error TransferToZeroAddress();
error URIQueryForNonexistentToken();
event Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
);
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
event ContractURIUpdated(string prevURI, string newURI);
event DefaultRoyalty(
address indexed newRoyaltyRecipient,
uint256 newRoyaltyBps
);
event OwnerUpdated(address indexed prevOwner, address indexed newOwner);
event RoyaltyForToken(
uint256 indexed tokenId,
address indexed royaltyRecipient,
uint256 royaltyBps
);
event Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
function airdrop(address[] memory _addresses, uint256[] memory _amounts)
external;
function approve(address to, uint256 tokenId) external;
function balanceOf(address owner) external view returns (uint256);
function burn(uint256 _tokenId) external;
function contractURI() external view returns (string memory);
function getApproved(uint256 tokenId) external view returns (address);
function getDefaultRoyaltyInfo() external view returns (address, uint16);
function getRoyaltyInfoForToken(uint256 _tokenId)
external
view
returns (address, uint16);
function isApprovedForAll(address owner, address operator)
external
view
returns (bool);
function multicall(bytes[] memory data)
external
returns (bytes[] memory results);
function name() external view returns (string memory);
function owner() external view returns (address);
function ownerOf(uint256 tokenId) external view returns (address);
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) external;
function setApprovalForAll(address operator, bool approved) external;
function setBaseURI(string memory _uri) external;
function setContractURI(string memory _uri) external;
function setDefaultRoyaltyInfo(
address _royaltyRecipient,
uint256 _royaltyBps
) external;
function setOwner(address _newOwner) external;
function setRoyaltyInfoForToken(
uint256 _tokenId,
address _recipient,
uint256 _bps
) external;
function supportsInterface(bytes4 interfaceId) external view returns (bool);
function symbol() external view returns (string memory);
function tokenURI(uint256 _tokenId) external view returns (string memory);
function totalSupply() external view returns (uint256);
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
}
文件 8 的 14:IOldWorldPass.sol
pragma solidity ^0.8.4;
interface IOldWorldPass {
error Ownable__NotAuthorized();
error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps);
error PlatformFee__NotAuthorized();
error PrimarySale__NotAuthorized();
error Royalty__ExceedsMaxBps(uint256 royaltyBps);
error Royalty__NotAuthorized();
event ApprovalForAll(
address indexed account,
address indexed operator,
bool approved
);
event ClaimConditionsUpdated(
uint256 indexed tokenId,
IDropClaimCondition.ClaimCondition[] claimConditions
);
event DefaultRoyalty(
address indexed newRoyaltyRecipient,
uint256 newRoyaltyBps
);
event MaxTotalSupplyUpdated(uint256 tokenId, uint256 maxTotalSupply);
event MaxWalletClaimCountUpdated(uint256 tokenId, uint256 count);
event OwnerUpdated(address indexed prevOwner, address indexed newOwner);
event PlatformFeeInfoUpdated(
address indexed platformFeeRecipient,
uint256 platformFeeBps
);
event PrimarySaleRecipientUpdated(address indexed recipient);
event RoleAdminChanged(
bytes32 indexed role,
bytes32 indexed previousAdminRole,
bytes32 indexed newAdminRole
);
event RoleGranted(
bytes32 indexed role,
address indexed account,
address indexed sender
);
event RoleRevoked(
bytes32 indexed role,
address indexed account,
address indexed sender
);
event RoyaltyForToken(
uint256 indexed tokenId,
address indexed royaltyRecipient,
uint256 royaltyBps
);
event SaleRecipientForTokenUpdated(
uint256 indexed tokenId,
address saleRecipient
);
event TokensClaimed(
uint256 indexed claimConditionIndex,
uint256 indexed tokenId,
address indexed claimer,
address receiver,
uint256 quantityClaimed
);
event TokensLazyMinted(
uint256 startTokenId,
uint256 endTokenId,
string baseURI
);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event TransferSingle(
address indexed operator,
address indexed from,
address indexed to,
uint256 id,
uint256 value
);
event URI(string value, uint256 indexed id);
event WalletClaimCountUpdated(
uint256 tokenId,
address indexed wallet,
uint256 count
);
function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
function balanceOf(address account, uint256 id)
external
view
returns (uint256);
function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
external
view
returns (uint256[] memory);
function burn(
address account,
uint256 id,
uint256 value
) external;
function burnBatch(
address account,
uint256[] memory ids,
uint256[] memory values
) external;
function claim(
address _receiver,
uint256 _tokenId,
uint256 _quantity,
address _currency,
uint256 _pricePerToken,
bytes32[] memory _proofs,
uint256 _proofMaxQuantityPerTransaction
) external payable;
function claimCondition(uint256)
external
view
returns (uint256 currentStartId, uint256 count);
function contractType() external pure returns (bytes32);
function contractURI() external view returns (string memory);
function contractVersion() external pure returns (uint8);
function getActiveClaimConditionId(uint256 _tokenId)
external
view
returns (uint256);
function getClaimConditionById(uint256 _tokenId, uint256 _conditionId)
external
view
returns (IDropClaimCondition.ClaimCondition memory condition);
function getClaimTimestamp(
uint256 _tokenId,
uint256 _conditionId,
address _claimer
)
external
view
returns (uint256 lastClaimTimestamp, uint256 nextValidClaimTimestamp);
function getDefaultRoyaltyInfo() external view returns (address, uint16);
function getPlatformFeeInfo() external view returns (address, uint16);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function getRoleMember(bytes32 role, uint256 index)
external
view
returns (address);
function getRoleMemberCount(bytes32 role) external view returns (uint256);
function getRoyaltyInfoForToken(uint256 _tokenId)
external
view
returns (address, uint16);
function grantRole(bytes32 role, address account) external;
function hasRole(bytes32 role, address account)
external
view
returns (bool);
function initialize(
address _defaultAdmin,
string memory _name,
string memory _symbol,
string memory _contractURI,
address[] memory _trustedForwarders,
address _saleRecipient,
address _royaltyRecipient,
uint128 _royaltyBps,
uint128 _platformFeeBps,
address _platformFeeRecipient
) external;
function isApprovedForAll(address account, address operator)
external
view
returns (bool);
function isTrustedForwarder(address forwarder) external view returns (bool);
function lazyMint(uint256 _amount, string memory _baseURIForTokens)
external;
function maxTotalSupply(uint256) external view returns (uint256);
function maxWalletClaimCount(uint256) external view returns (uint256);
function multicall(bytes[] memory data)
external
returns (bytes[] memory results);
function name() external view returns (string memory);
function nextTokenIdToMint() external view returns (uint256);
function owner() external view returns (address);
function primarySaleRecipient() external view returns (address);
function renounceRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) external;
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) external;
function saleRecipient(uint256) external view returns (address);
function setApprovalForAll(address operator, bool approved) external;
function setClaimConditions(
uint256 _tokenId,
IDropClaimCondition.ClaimCondition[] memory _phases,
bool _resetClaimEligibility
) external;
function setContractURI(string memory _uri) external;
function setDefaultRoyaltyInfo(
address _royaltyRecipient,
uint256 _royaltyBps
) external;
function setMaxTotalSupply(uint256 _tokenId, uint256 _maxTotalSupply)
external;
function setMaxWalletClaimCount(uint256 _tokenId, uint256 _count) external;
function setOwner(address _newOwner) external;
function setPlatformFeeInfo(
address _platformFeeRecipient,
uint256 _platformFeeBps
) external;
function setPrimarySaleRecipient(address _saleRecipient) external;
function setRoyaltyInfoForToken(
uint256 _tokenId,
address _recipient,
uint256 _bps
) external;
function setSaleRecipientForToken(uint256 _tokenId, address _saleRecipient)
external;
function setWalletClaimCount(
uint256 _tokenId,
address _claimer,
uint256 _count
) external;
function supportsInterface(bytes4 interfaceId) external view returns (bool);
function symbol() external view returns (string memory);
function totalSupply(uint256) external view returns (uint256);
function uri(uint256 _tokenId)
external
view
returns (string memory _tokenURI);
function verifyClaim(
uint256 _conditionId,
address _claimer,
uint256 _tokenId,
uint256 _quantity,
address _currency,
uint256 _pricePerToken,
bool verifyMaxQuantityPerTransaction
) external view;
function verifyClaimMerkleProof(
uint256 _conditionId,
address _claimer,
uint256 _tokenId,
uint256 _quantity,
bytes32[] memory _proofs,
uint256 _proofMaxQuantityPerTransaction
) external view returns (bool validMerkleProof, uint256 merkleProofIndex);
function walletClaimCount(uint256, address) external view returns (uint256);
}
interface IDropClaimCondition {
struct ClaimCondition {
uint256 startTimestamp;
uint256 maxClaimableSupply;
uint256 supplyClaimed;
uint256 quantityLimitPerTransaction;
uint256 waitTimeInSecondsBetweenClaims;
bytes32 merkleRoot;
uint256 pricePerToken;
address currency;
}
}
文件 9 的 14:IPermissions.sol
pragma solidity ^0.8.0;
interface IPermissions {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 10 的 14:IWorldPassNFT.sol
pragma solidity ^0.8.0;
enum House {
Scarred,
Arms,
Hearts,
Sight,
Hearing,
Shadows
}
library HouseUtil {
function toString(House _house) internal pure returns (string memory) {
if (_house == House.Arms) {
return "Arms";
} else if (_house == House.Hearts) {
return "Hearts";
} else if (_house == House.Sight) {
return "Sight";
} else if (_house == House.Hearing) {
return "Hearing";
} else if (_house == House.Shadows) {
return "Shadows";
} else {
return "Scarred";
}
}
}
interface IWorldPassNFT {
struct TokenData {
bool __exists;
House house;
}
function setTokenHouse(uint256 _tokenId, House _house) external;
function getTokenHouse(uint256 _tokenId) external view returns (House);
function getRemainingHouseSupply(House _house) external view returns (uint256);
function mintWithHouseTo(address _to, House _house) external;
function batchMintWithHouseTo(
address _to,
uint256 _quantity,
House _house
) external;
}
文件 11 的 14:Pausable.sol
pragma solidity ^0.8.0;
import "@thirdweb-dev/contracts/openzeppelin-presets/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());
}
}
文件 12 的 14:Permissions.sol
pragma solidity ^0.8.0;
import "./interface/IPermissions.sol";
import "../lib/TWStrings.sol";
contract Permissions is IPermissions {
mapping(bytes32 => mapping(address => bool)) private _hasRole;
mapping(bytes32 => bytes32) private _getRoleAdmin;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role, msg.sender);
_;
}
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _hasRole[role][account];
}
function hasRoleWithSwitch(bytes32 role, address account) public view returns (bool) {
if (!_hasRole[role][address(0)]) {
return _hasRole[role][account];
}
return true;
}
function getRoleAdmin(bytes32 role) external view override returns (bytes32) {
return _getRoleAdmin[role];
}
function grantRole(bytes32 role, address account) public virtual override {
_checkRole(_getRoleAdmin[role], msg.sender);
if (_hasRole[role][account]) {
revert("Can only grant to non holders");
}
_setupRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override {
_checkRole(_getRoleAdmin[role], msg.sender);
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
if (msg.sender != account) {
revert("Can only renounce for self");
}
_revokeRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = _getRoleAdmin[role];
_getRoleAdmin[role] = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _setupRole(bytes32 role, address account) internal virtual {
_hasRole[role][account] = true;
emit RoleGranted(role, account, msg.sender);
}
function _revokeRole(bytes32 role, address account) internal virtual {
_checkRole(role, account);
delete _hasRole[role][account];
emit RoleRevoked(role, account, msg.sender);
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!_hasRole[role][account]) {
revert(
string(
abi.encodePacked(
"Permissions: account ",
TWStrings.toHexString(uint160(account), 20),
" is missing role ",
TWStrings.toHexString(uint256(role), 32)
)
)
);
}
}
function _checkRoleWithSwitch(bytes32 role, address account) internal view virtual {
if (!hasRoleWithSwitch(role, account)) {
revert(
string(
abi.encodePacked(
"Permissions: account ",
TWStrings.toHexString(uint160(account), 20),
" is missing role ",
TWStrings.toHexString(uint256(role), 32)
)
)
);
}
}
}
文件 13 的 14:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 14 的 14:TWStrings.sol
pragma solidity ^0.8.0;
library TWStrings {
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);
}
}
{
"compilationTarget": {
"contracts/Bonfire.sol": "Bonfire"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_originalDice","type":"address"},{"internalType":"address","name":"_originalWP","type":"address"},{"internalType":"address","name":"_reforgedDice","type":"address"},{"internalType":"address","name":"_reforgedWP","type":"address"},{"internalType":"address","name":"_allowedSigner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"mintedTo","type":"address"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"wpBurnAmount","type":"uint128"},{"internalType":"uint256[]","name":"diceIds","type":"uint256[]"},{"internalType":"uint8[]","name":"diceResults","type":"uint8[]"},{"internalType":"uint8[]","name":"wpHouses","type":"uint8[]"},{"internalType":"uint128","name":"validityStartTimestamp","type":"uint128"},{"internalType":"uint128","name":"validityEndTimestamp","type":"uint128"},{"internalType":"bytes32","name":"uid","type":"bytes32"}],"indexed":false,"internalType":"struct IBonfire.BurnRequest","name":"burnRequest","type":"tuple"}],"name":"BonfireBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"mintedTo","type":"address"},{"indexed":true,"internalType":"uint256[]","name":"burntDiceIDs","type":"uint256[]"}],"name":"BonfireBurnDiceOnly","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"mintedTo","type":"address"},{"indexed":true,"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"BonfireJoinScarred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowedSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"wpBurnAmount","type":"uint128"},{"internalType":"uint256[]","name":"diceIds","type":"uint256[]"},{"internalType":"uint8[]","name":"diceResults","type":"uint8[]"},{"internalType":"uint8[]","name":"wpHouses","type":"uint8[]"},{"internalType":"uint128","name":"validityStartTimestamp","type":"uint128"},{"internalType":"uint128","name":"validityEndTimestamp","type":"uint128"},{"internalType":"bytes32","name":"uid","type":"bytes32"}],"internalType":"struct IBonfire.BurnRequest","name":"_req","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"bonfireBurn","outputs":[{"internalType":"address","name":"signer","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"diceIds","type":"uint256[]"}],"name":"burnDiceOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRoleWithSwitch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"joinScarred","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"originalDice","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"originalWP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reforgedDice","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reforgedWP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_allowedSigner","type":"address"}],"name":"setAllowedSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"wpBurnAmount","type":"uint128"},{"internalType":"uint256[]","name":"diceIds","type":"uint256[]"},{"internalType":"uint8[]","name":"diceResults","type":"uint8[]"},{"internalType":"uint8[]","name":"wpHouses","type":"uint8[]"},{"internalType":"uint128","name":"validityStartTimestamp","type":"uint128"},{"internalType":"uint128","name":"validityEndTimestamp","type":"uint128"},{"internalType":"bytes32","name":"uid","type":"bytes32"}],"internalType":"struct IBonfire.BurnRequest","name":"_req","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"verify","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"address","name":"signer","type":"address"}],"stateMutability":"view","type":"function"}]