编译器
0.8.24+commit.e11b9ed9
文件 1 的 15:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 2 的 15:DoubleEndedQueue.sol
pragma solidity ^0.8.20;
library DoubleEndedQueue {
error QueueEmpty();
error QueueFull();
error QueueOutOfBounds();
struct Uint256Deque {
uint128 _begin;
uint128 _end;
mapping(uint128 index => uint256) _data;
}
function pushBack(Uint256Deque storage deque, uint256 value) internal {
unchecked {
uint128 backIndex = deque._end;
if (backIndex + 1 == deque._begin) revert QueueFull();
deque._data[backIndex] = value;
deque._end = backIndex + 1;
}
}
function popBack(
Uint256Deque storage deque
) internal returns (uint256 value) {
unchecked {
uint128 backIndex = deque._end;
if (backIndex == deque._begin) revert QueueEmpty();
--backIndex;
value = deque._data[backIndex];
delete deque._data[backIndex];
deque._end = backIndex;
}
}
function pushFront(Uint256Deque storage deque, uint256 value) internal {
unchecked {
uint128 frontIndex = deque._begin - 1;
if (frontIndex == deque._end) revert QueueFull();
deque._data[frontIndex] = value;
deque._begin = frontIndex;
}
}
function popFront(
Uint256Deque storage deque
) internal returns (uint256 value) {
unchecked {
uint128 frontIndex = deque._begin;
if (frontIndex == deque._end) revert QueueEmpty();
value = deque._data[frontIndex];
delete deque._data[frontIndex];
deque._begin = frontIndex + 1;
}
}
function front(
Uint256Deque storage deque
) internal view returns (uint256 value) {
if (empty(deque)) revert QueueEmpty();
return deque._data[deque._begin];
}
function back(
Uint256Deque storage deque
) internal view returns (uint256 value) {
if (empty(deque)) revert QueueEmpty();
unchecked {
return deque._data[deque._end - 1];
}
}
function at(
Uint256Deque storage deque,
uint256 index
) internal view returns (uint256 value) {
if (index >= length(deque)) revert QueueOutOfBounds();
unchecked {
return deque._data[deque._begin + uint128(index)];
}
}
function clear(Uint256Deque storage deque) internal {
deque._begin = 0;
deque._end = 0;
}
function length(
Uint256Deque storage deque
) internal view returns (uint256) {
unchecked {
return uint256(deque._end - deque._begin);
}
}
function empty(Uint256Deque storage deque) internal view returns (bool) {
return deque._end == deque._begin;
}
}
文件 3 的 15:ERC20Events.sol
pragma solidity ^0.8.20;
library ERC20Events {
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Transfer(address indexed from, address indexed to, uint256 amount);
}
文件 4 的 15:ERC404.sol
pragma solidity ^0.8.20;
import {IERC721Receiver} from "@openzeppelin/contracts/interfaces/IERC721Receiver.sol";
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
import {IERC404} from "./interfaces/IERC404.sol";
import {DoubleEndedQueue} from "./lib/DoubleEndedQueue.sol";
import {ERC721Events} from "./lib/ERC721Events.sol";
import {ERC20Events} from "./lib/ERC20Events.sol";
abstract contract ERC404 is IERC404 {
using DoubleEndedQueue for DoubleEndedQueue.Uint256Deque;
DoubleEndedQueue.Uint256Deque private _storedERC721Ids;
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public immutable units;
uint256 public totalSupply;
uint256 public minted;
uint256 internal immutable _INITIAL_CHAIN_ID;
bytes32 internal immutable _INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
mapping(uint256 => address) public getApproved;
mapping(address => mapping(address => bool)) public isApprovedForAll;
mapping(uint256 => uint256) internal _ownedData;
mapping(address => uint256[]) internal _owned;
mapping(address => bool) internal _erc721TransferExempt;
mapping(address => uint256) public nonces;
uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;
uint256 private constant _BITMASK_OWNED_INDEX = ((1 << 96) - 1) << 160;
uint256 public constant ID_ENCODING_PREFIX = 1 << 255;
constructor(string memory name_, string memory symbol_, uint8 decimals_) {
name = name_;
symbol = symbol_;
if (decimals_ < 18) {
revert DecimalsTooLow();
}
decimals = decimals_;
units = 10 ** decimals;
_INITIAL_CHAIN_ID = block.chainid;
_INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator();
}
function ownerOf(
uint256 id_
) public view virtual returns (address erc721Owner) {
erc721Owner = _getOwnerOf(id_);
if (!_isValidTokenId(id_)) {
revert InvalidTokenId();
}
if (erc721Owner == address(0)) {
revert NotFound();
}
}
function owned(
address owner_
) public view virtual returns (uint256[] memory) {
return _owned[owner_];
}
function erc721BalanceOf(
address owner_
) public view virtual returns (uint256) {
return _owned[owner_].length;
}
function erc20BalanceOf(
address owner_
) public view virtual returns (uint256) {
return balanceOf[owner_];
}
function erc20TotalSupply() public view virtual returns (uint256) {
return totalSupply;
}
function erc721TotalSupply() public view virtual returns (uint256) {
return minted;
}
function getERC721QueueLength() public view virtual returns (uint256) {
return _storedERC721Ids.length();
}
function getERC721TokensInQueue(
uint256 start_,
uint256 count_
) public view virtual returns (uint256[] memory) {
uint256[] memory tokensInQueue = new uint256[](count_);
for (uint256 i = start_; i < start_ + count_; ) {
tokensInQueue[i - start_] = _storedERC721Ids.at(i);
unchecked {
++i;
}
}
return tokensInQueue;
}
function tokenURI(uint256 id_) public view virtual returns (string memory);
function approve(
address spender_,
uint256 valueOrId_
) public virtual returns (bool) {
if (_isValidTokenId(valueOrId_)) {
erc721Approve(spender_, valueOrId_);
} else {
return erc20Approve(spender_, valueOrId_);
}
return true;
}
function erc721Approve(address spender_, uint256 id_) public virtual {
address erc721Owner = _getOwnerOf(id_);
if (
msg.sender != erc721Owner &&
!isApprovedForAll[erc721Owner][msg.sender]
) {
revert Unauthorized();
}
getApproved[id_] = spender_;
emit ERC721Events.Approval(erc721Owner, spender_, id_);
}
function erc20Approve(
address spender_,
uint256 value_
) public virtual returns (bool) {
if (spender_ == address(0)) {
revert InvalidSpender();
}
allowance[msg.sender][spender_] = value_;
emit ERC20Events.Approval(msg.sender, spender_, value_);
return true;
}
function setApprovalForAll(
address operator_,
bool approved_
) public virtual {
if (operator_ == address(0)) {
revert InvalidOperator();
}
isApprovedForAll[msg.sender][operator_] = approved_;
emit ERC721Events.ApprovalForAll(msg.sender, operator_, approved_);
}
function transferFrom(
address from_,
address to_,
uint256 valueOrId_
) public virtual returns (bool) {
if (_isValidTokenId(valueOrId_)) {
erc721TransferFrom(from_, to_, valueOrId_);
} else {
return erc20TransferFrom(from_, to_, valueOrId_);
}
return true;
}
function erc721TransferFrom(
address from_,
address to_,
uint256 id_
) public virtual {
if (from_ == address(0)) {
revert InvalidSender();
}
if (to_ == address(0)) {
revert InvalidRecipient();
}
if (from_ != _getOwnerOf(id_)) {
revert Unauthorized();
}
if (
msg.sender != from_ &&
!isApprovedForAll[from_][msg.sender] &&
msg.sender != getApproved[id_]
) {
revert Unauthorized();
}
if (erc721TransferExempt(to_)) {
revert RecipientIsERC721TransferExempt();
}
_transferERC20(from_, to_, units);
_transferERC721(from_, to_, id_);
}
function erc20TransferFrom(
address from_,
address to_,
uint256 value_
) public virtual returns (bool) {
if (from_ == address(0)) {
revert InvalidSender();
}
if (to_ == address(0)) {
revert InvalidRecipient();
}
uint256 allowed = allowance[from_][msg.sender];
if (allowed != type(uint256).max) {
allowance[from_][msg.sender] = allowed - value_;
}
return _transferERC20WithERC721(from_, to_, value_);
}
function transfer(
address to_,
uint256 value_
) public virtual returns (bool) {
if (to_ == address(0)) {
revert InvalidRecipient();
}
return _transferERC20WithERC721(msg.sender, to_, value_);
}
function safeTransferFrom(
address from_,
address to_,
uint256 id_
) public virtual {
safeTransferFrom(from_, to_, id_, "");
}
function safeTransferFrom(
address from_,
address to_,
uint256 id_,
bytes memory data_
) public virtual {
if (!_isValidTokenId(id_)) {
revert InvalidTokenId();
}
transferFrom(from_, to_, id_);
if (
to_.code.length != 0 &&
IERC721Receiver(to_).onERC721Received(
msg.sender,
from_,
id_,
data_
) !=
IERC721Receiver.onERC721Received.selector
) {
revert UnsafeRecipient();
}
}
function permit(
address owner_,
address spender_,
uint256 value_,
uint256 deadline_,
uint8 v_,
bytes32 r_,
bytes32 s_
) public virtual {
if (deadline_ < block.timestamp) {
revert PermitDeadlineExpired();
}
if (_isValidTokenId(value_)) {
revert InvalidApproval();
}
if (spender_ == address(0)) {
revert InvalidSpender();
}
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner_,
spender_,
value_,
nonces[owner_]++,
deadline_
)
)
)
),
v_,
r_,
s_
);
if (recoveredAddress == address(0) || recoveredAddress != owner_) {
revert InvalidSigner();
}
allowance[recoveredAddress][spender_] = value_;
}
emit ERC20Events.Approval(owner_, spender_, value_);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return
block.chainid == _INITIAL_CHAIN_ID
? _INITIAL_DOMAIN_SEPARATOR
: _computeDomainSeparator();
}
function supportsInterface(
bytes4 interfaceId
) public view virtual returns (bool) {
return
interfaceId == type(IERC404).interfaceId ||
interfaceId == type(IERC165).interfaceId;
}
function setSelfERC721TransferExempt(bool state_) public virtual {
_setERC721TransferExempt(msg.sender, state_);
}
function erc721TransferExempt(
address target_
) public view virtual returns (bool) {
return target_ == address(0) || _erc721TransferExempt[target_];
}
function _isValidTokenId(uint256 id_) internal pure returns (bool) {
return id_ > ID_ENCODING_PREFIX && id_ != type(uint256).max;
}
function _computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _transferERC20(
address from_,
address to_,
uint256 value_
) internal virtual {
if (from_ == address(0)) {
totalSupply += value_;
} else {
balanceOf[from_] -= value_;
}
unchecked {
balanceOf[to_] += value_;
}
emit ERC20Events.Transfer(from_, to_, value_);
}
function _transferERC721(
address from_,
address to_,
uint256 id_
) internal virtual {
if (from_ != address(0)) {
delete getApproved[id_];
uint256 updatedId = _owned[from_][_owned[from_].length - 1];
if (updatedId != id_) {
uint256 updatedIndex = _getOwnedIndex(id_);
_owned[from_][updatedIndex] = updatedId;
_setOwnedIndex(updatedId, updatedIndex);
}
_owned[from_].pop();
}
if (to_ != address(0)) {
_setOwnerOf(id_, to_);
_owned[to_].push(id_);
_setOwnedIndex(id_, _owned[to_].length - 1);
} else {
delete _ownedData[id_];
}
emit ERC721Events.Transfer(from_, to_, id_);
}
function _transferERC20WithERC721(
address from_,
address to_,
uint256 value_
) internal virtual returns (bool) {
uint256 erc20BalanceOfSenderBefore = erc20BalanceOf(from_);
uint256 erc20BalanceOfReceiverBefore = erc20BalanceOf(to_);
_transferERC20(from_, to_, value_);
bool isFromERC721TransferExempt = erc721TransferExempt(from_);
bool isToERC721TransferExempt = erc721TransferExempt(to_);
if (isFromERC721TransferExempt && isToERC721TransferExempt) {
} else if (isFromERC721TransferExempt) {
uint256 tokensToRetrieveOrMint = (balanceOf[to_] / units) -
(erc20BalanceOfReceiverBefore / units);
for (uint256 i = 0; i < tokensToRetrieveOrMint; ) {
_retrieveOrMintERC721(to_);
unchecked {
++i;
}
}
} else if (isToERC721TransferExempt) {
uint256 tokensToWithdrawAndStore = (erc20BalanceOfSenderBefore /
units) - (balanceOf[from_] / units);
for (uint256 i = 0; i < tokensToWithdrawAndStore; ) {
_withdrawAndStoreERC721(from_);
unchecked {
++i;
}
}
} else {
uint256 nftsToTransfer = value_ / units;
for (uint256 i = 0; i < nftsToTransfer; ) {
uint256 indexOfLastToken = _owned[from_].length - 1;
uint256 tokenId = _owned[from_][indexOfLastToken];
_transferERC721(from_, to_, tokenId);
unchecked {
++i;
}
}
if (
erc20BalanceOfSenderBefore /
units -
erc20BalanceOf(from_) /
units >
nftsToTransfer
) {
_withdrawAndStoreERC721(from_);
}
if (
erc20BalanceOf(to_) /
units -
erc20BalanceOfReceiverBefore /
units >
nftsToTransfer
) {
_retrieveOrMintERC721(to_);
}
}
return true;
}
function _mintERC20(address to_, uint256 value_) internal virtual {
if (to_ == address(0)) {
revert InvalidRecipient();
}
if (totalSupply + value_ > ID_ENCODING_PREFIX) {
revert MintLimitReached();
}
_transferERC20WithERC721(address(0), to_, value_);
}
function _retrieveOrMintERC721(address to_) internal virtual {
if (to_ == address(0)) {
revert InvalidRecipient();
}
uint256 id;
if (!_storedERC721Ids.empty()) {
id = _storedERC721Ids.popBack();
} else {
++minted;
if (minted == type(uint256).max) {
revert MintLimitReached();
}
id = ID_ENCODING_PREFIX + minted;
}
address erc721Owner = _getOwnerOf(id);
if (erc721Owner != address(0)) {
revert AlreadyExists();
}
_transferERC721(erc721Owner, to_, id);
}
function _withdrawAndStoreERC721(address from_) internal virtual {
if (from_ == address(0)) {
revert InvalidSender();
}
uint256 id = _owned[from_][_owned[from_].length - 1];
_transferERC721(from_, address(0), id);
_storedERC721Ids.pushFront(id);
}
function _setERC721TransferExempt(
address target_,
bool state_
) internal virtual {
if (target_ == address(0)) {
revert InvalidExemption();
}
if (state_) {
_clearERC721Balance(target_);
} else {
_reinstateERC721Balance(target_);
}
_erc721TransferExempt[target_] = state_;
}
function _reinstateERC721Balance(address target_) private {
uint256 expectedERC721Balance = erc20BalanceOf(target_) / units;
uint256 actualERC721Balance = erc721BalanceOf(target_);
for (uint256 i = 0; i < expectedERC721Balance - actualERC721Balance; ) {
_retrieveOrMintERC721(target_);
unchecked {
++i;
}
}
}
function _clearERC721Balance(address target_) private {
uint256 erc721Balance = erc721BalanceOf(target_);
for (uint256 i = 0; i < erc721Balance; ) {
_withdrawAndStoreERC721(target_);
unchecked {
++i;
}
}
}
function _getOwnerOf(
uint256 id_
) internal view virtual returns (address ownerOf_) {
uint256 data = _ownedData[id_];
assembly {
ownerOf_ := and(data, _BITMASK_ADDRESS)
}
}
function _setOwnerOf(uint256 id_, address owner_) internal virtual {
uint256 data = _ownedData[id_];
assembly {
data := add(
and(data, _BITMASK_OWNED_INDEX),
and(owner_, _BITMASK_ADDRESS)
)
}
_ownedData[id_] = data;
}
function _getOwnedIndex(
uint256 id_
) internal view virtual returns (uint256 ownedIndex_) {
uint256 data = _ownedData[id_];
assembly {
ownedIndex_ := shr(160, data)
}
}
function _setOwnedIndex(uint256 id_, uint256 index_) internal virtual {
uint256 data = _ownedData[id_];
if (index_ > _BITMASK_OWNED_INDEX >> 160) {
revert OwnedIndexOverflow();
}
assembly {
data := add(
and(data, _BITMASK_ADDRESS),
and(shl(160, index_), _BITMASK_OWNED_INDEX)
)
}
_ownedData[id_] = data;
}
}
文件 5 的 15:ERC404UniswapV3Exempt.sol
pragma solidity ^0.8.20;
import {ERC404} from "../ERC404.sol";
import {IPeripheryImmutableState} from "@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol";
abstract contract ERC404UniswapV3Exempt is ERC404 {
error ERC404UniswapV3ExemptFactoryMismatch();
error ERC404UniswapV3ExemptWETH9Mismatch();
constructor(
address uniswapV3Router_,
address uniswapV3NonfungiblePositionManager_
) {
IPeripheryImmutableState uniswapV3Router = IPeripheryImmutableState(
uniswapV3Router_
);
_setERC721TransferExempt(uniswapV3Router_, true);
IPeripheryImmutableState uniswapV3NonfungiblePositionManager = IPeripheryImmutableState(
uniswapV3NonfungiblePositionManager_
);
_setERC721TransferExempt(uniswapV3NonfungiblePositionManager_, true);
if (
uniswapV3Router.factory() !=
uniswapV3NonfungiblePositionManager.factory()
) {
revert ERC404UniswapV3ExemptFactoryMismatch();
}
if (
uniswapV3Router.WETH9() !=
uniswapV3NonfungiblePositionManager.WETH9()
) {
revert ERC404UniswapV3ExemptWETH9Mismatch();
}
uint24[4] memory feeTiers = [
uint24(100),
uint24(500),
uint24(3_000),
uint24(10_000)
];
for (uint256 i = 0; i < feeTiers.length; ) {
address uniswapV3Pair = _getUniswapV3Pair(
uniswapV3Router.factory(),
uniswapV3Router.WETH9(),
feeTiers[i]
);
_setERC721TransferExempt(uniswapV3Pair, true);
unchecked {
++i;
}
}
}
function _getUniswapV3Pair(
address uniswapV3Factory_,
address weth_,
uint24 fee_
) private view returns (address) {
address thisAddress = address(this);
(address token0, address token1) = thisAddress < weth_
? (thisAddress, weth_)
: (weth_, thisAddress);
return
address(
uint160(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
uniswapV3Factory_,
keccak256(abi.encode(token0, token1, fee_)),
hex"e34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54"
)
)
)
)
);
}
}
文件 6 的 15:ERC721Events.sol
pragma solidity ^0.8.20;
library ERC721Events {
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
event Approval(
address indexed owner,
address indexed spender,
uint256 indexed id
);
event Transfer(
address indexed from,
address indexed to,
uint256 indexed id
);
}
文件 7 的 15:IERC165.sol
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";
文件 8 的 15:IERC404.sol
pragma solidity ^0.8.20;
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
interface IERC404 is IERC165 {
error NotFound();
error InvalidTokenId();
error AlreadyExists();
error InvalidRecipient();
error InvalidSender();
error InvalidSpender();
error InvalidOperator();
error UnsafeRecipient();
error RecipientIsERC721TransferExempt();
error Unauthorized();
error InsufficientAllowance();
error DecimalsTooLow();
error PermitDeadlineExpired();
error InvalidSigner();
error InvalidApproval();
error OwnedIndexOverflow();
error MintLimitReached();
error InvalidExemption();
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function erc20TotalSupply() external view returns (uint256);
function erc721TotalSupply() external view returns (uint256);
function balanceOf(address owner_) external view returns (uint256);
function erc721BalanceOf(address owner_) external view returns (uint256);
function erc20BalanceOf(address owner_) external view returns (uint256);
function erc721TransferExempt(address account_) external view returns (bool);
function isApprovedForAll(
address owner_,
address operator_
) external view returns (bool);
function allowance(
address owner_,
address spender_
) external view returns (uint256);
function owned(address owner_) external view returns (uint256[] memory);
function ownerOf(uint256 id_) external view returns (address erc721Owner);
function tokenURI(uint256 id_) external view returns (string memory);
function approve(
address spender_,
uint256 valueOrId_
) external returns (bool);
function erc20Approve(
address spender_,
uint256 value_
) external returns (bool);
function erc721Approve(address spender_, uint256 id_) external;
function setApprovalForAll(address operator_, bool approved_) external;
function transferFrom(
address from_,
address to_,
uint256 valueOrId_
) external returns (bool);
function erc20TransferFrom(
address from_,
address to_,
uint256 value_
) external returns (bool);
function erc721TransferFrom(address from_, address to_, uint256 id_) external;
function transfer(address to_, uint256 amount_) external returns (bool);
function getERC721QueueLength() external view returns (uint256);
function getERC721TokensInQueue(
uint256 start_,
uint256 count_
) external view returns (uint256[] memory);
function setSelfERC721TransferExempt(bool state_) external;
function safeTransferFrom(address from_, address to_, uint256 id_) external;
function safeTransferFrom(
address from_,
address to_,
uint256 id_,
bytes calldata data_
) external;
function DOMAIN_SEPARATOR() external view returns (bytes32);
function permit(
address owner_,
address spender_,
uint256 value_,
uint256 deadline_,
uint8 v_,
bytes32 r_,
bytes32 s_
) external;
}
文件 9 的 15:IERC721Receiver.sol
pragma solidity ^0.8.20;
import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol";
文件 10 的 15:IPeripheryImmutableState.sol
pragma solidity >=0.5.0;
interface IPeripheryImmutableState {
function factory() external view returns (address);
function WETH9() external view returns (address);
}
文件 11 的 15:Math.sol
pragma solidity ^0.8.20;
library Math {
error MathOverflowedMulDiv();
enum Rounding {
Floor,
Ceil,
Trunc,
Expand
}
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
return a / b;
}
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0 = x * y;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (0 - denominator);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}
文件 12 的 15:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 13 的 15:SignedMath.sol
pragma solidity ^0.8.20;
library SignedMath {
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
function average(int256 a, int256 b) internal pure returns (int256) {
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
function abs(int256 n) internal pure returns (uint256) {
unchecked {
return uint256(n >= 0 ? n : -n);
}
}
}
文件 14 的 15:Strings.sol
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
error StringsInsufficientHexLength(uint256 value, uint256 length);
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
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_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}
文件 15 的 15:VexAeterna.sol
pragma solidity ^0.8.20;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {ERC404} from "./ERC404/ERC404.sol";
import {ERC404UniswapV3Exempt} from "./ERC404/extensions/ERC404UniswapV3Exempt.sol";
contract VexAeterna is Ownable, ERC404, ERC404UniswapV3Exempt {
string public baseTokenURI;
string public imageURI;
enum Rarity {
COMMON,
UNCOMMON,
RARE,
EPIC,
LEGENDARY,
MYTHICAL
}
uint16[6] public atomicValues;
string[6] public colors;
string[6] public materials;
error InvalidRarity();
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
uint256 maxTotalSupplyERC721_,
address initialOwner_,
address initialMintRecipient_,
address uniswapSwapRouter_,
address uniswapV3NonfungiblePositionManager_
)
ERC404(name_, symbol_, decimals_)
Ownable(initialOwner_)
ERC404UniswapV3Exempt(
uniswapSwapRouter_,
uniswapV3NonfungiblePositionManager_
)
{
_setERC721TransferExempt(initialMintRecipient_, true);
_mintERC20(initialMintRecipient_, maxTotalSupplyERC721_ * units);
colors[uint(Rarity.COMMON)] = "Mystic Frost";
colors[uint(Rarity.UNCOMMON)] = "Verdant Pulse";
colors[uint(Rarity.RARE)] = "Skyrift Gleam";
colors[uint(Rarity.EPIC)] = "Orange Vex";
colors[uint(Rarity.LEGENDARY)] = "Nebula Pink";
colors[uint(Rarity.MYTHICAL)] = "Sunbeam Radiance";
materials[uint(Rarity.COMMON)] = "Vexodium";
materials[uint(Rarity.UNCOMMON)] = "Vexite";
materials[uint(Rarity.RARE)] = "Vexolite";
materials[uint(Rarity.EPIC)] = "Vexorium";
materials[uint(Rarity.LEGENDARY)] = "Vexillium";
materials[uint(Rarity.MYTHICAL)] = "Vexorite";
atomicValues[uint(Rarity.COMMON)] = 1;
atomicValues[uint(Rarity.UNCOMMON)] = 2;
atomicValues[uint(Rarity.RARE)] = 4;
atomicValues[uint(Rarity.EPIC)] = 7;
atomicValues[uint(Rarity.LEGENDARY)] = 25;
atomicValues[uint(Rarity.MYTHICAL)] = 625;
}
receive() external payable {}
function setERC721TransferExempt(
address account_,
bool value_
) external onlyOwner {
_setERC721TransferExempt(account_, value_);
}
function batchTransferERC721(
address from_,
address to_,
uint256[] calldata tokenIds
) external {
require(
to_ != address(0) || from_ != address(0),
"Cannot transfer to 0 address"
);
uint256 length = tokenIds.length;
for (uint i = 0; i < length; i++) {
erc721TransferFrom(from_, to_, tokenIds[i]);
}
}
function setTokenURI(string memory _tokenURI) external onlyOwner {
baseTokenURI = _tokenURI;
}
function setImageURI(string memory _imageURI) external onlyOwner {
imageURI = _imageURI;
}
function setAtomicValue(uint8 r, uint16 _newValue) external onlyOwner {
require(
uint8(getHighestRarity()) >= r && uint8(getLowestRarity()) <= r,
"Rarity does not exists"
);
atomicValues[r] = _newValue;
}
function withdraw() external onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, "No balance to withdraw");
(bool sent, ) = owner().call{value: balance}("");
require(sent, "Failed to send Ether");
}
function erc721TransferByRarity(
address _from,
address _to,
uint256 _amount,
uint8 _rarity
) external {
uint256 _fromBalance = balanceOfByRarity(_from, _rarity);
require(_fromBalance >= _amount, "Not enough of these energy stones");
uint256[] memory _fromTokenIds = owned(_from);
uint256 transferCount;
for (uint256 i = 0; i < _fromTokenIds.length; i++) {
uint256 tokenIdToTransfer = _fromTokenIds[i];
uint8 currentRarity = uint8(
getRarityByTokenId(decodedTokenId(tokenIdToTransfer))
);
if (currentRarity == _rarity) {
erc721TransferFrom(_from, _to, tokenIdToTransfer);
transferCount++;
if (transferCount == _amount) {
break;
}
}
}
}
function getHighestRarity() public pure returns (Rarity) {
return type(Rarity).max;
}
function getLowestRarity() public pure returns (Rarity) {
return type(Rarity).min;
}
function tokenURI(
uint256 id_
) public view override returns (string memory) {
uint256 tokenId = decodedTokenId(id_);
if (bytes(baseTokenURI).length > 0) {
return string.concat(baseTokenURI, Strings.toString(tokenId));
} else {
uint8 rarity = uint8(getRarityByTokenId(tokenId));
string memory uri = _generateJsonMetadata(rarity, tokenId);
return uri;
}
}
function balanceOfByRarity(
address _owner,
uint8 _rarity
) public view returns (uint256) {
if (
_rarity > uint8(getHighestRarity()) ||
_rarity < uint8(getLowestRarity())
) {
revert InvalidRarity();
}
uint256[] memory ownerTokenIds = owned(_owner);
uint256 totalOwned = ownerTokenIds.length;
if (totalOwned > 0) {
uint256 count = 0;
for (uint256 i = 0; i < totalOwned; i++) {
uint256 tokenId = decodedTokenId(ownerTokenIds[i]);
uint8 computedRarity = uint8(getRarityByTokenId(tokenId));
if (_rarity == computedRarity) {
count++;
}
}
return count;
} else {
return 0;
}
}
function balancesOfByRarity(
address _owner
) public view returns (uint256[6] memory balances) {
for (
uint8 i = uint8(getLowestRarity());
i <= uint8(getHighestRarity());
i++
) {
uint256 rarityCount = balanceOfByRarity(_owner, i);
balances[i] = rarityCount;
}
}
function decodedTokenId(uint256 _tokenId) public pure returns (uint256) {
if (_tokenId <= (1 << 255)) revert InvalidTokenId();
return _tokenId - (1 << 255);
}
function getRarityByTokenId(uint256 _tokenId) public pure returns (Rarity) {
uint256 hash = uint256(keccak256(abi.encodePacked(_tokenId)));
uint256 effectiveId = (hash % 100000) + 1;
if (effectiveId <= 50000) {
return Rarity.COMMON;
} else if (effectiveId <= 75000) {
return Rarity.UNCOMMON;
} else if (effectiveId <= 91000) {
return Rarity.RARE;
} else if (effectiveId <= 98000) {
return Rarity.EPIC;
} else if (effectiveId <= 99900) {
return Rarity.LEGENDARY;
} else {
return Rarity.MYTHICAL;
}
}
function _generateJsonAttributes(
uint8 _index
) internal view returns (string memory) {
string memory materialAttr = string.concat(
'"attributes": [{"trait_type": "Material", "value": "',
materials[_index]
);
string memory colorAttr = string.concat(
materialAttr,
string.concat(
'"}, {"trait_type": "Color", "value": "',
colors[_index]
)
);
string memory atomicValueAttr = string.concat(
colorAttr,
string.concat(
string.concat('"}, {"trait_type": "Atomic Value", "value": '),
Strings.toString(atomicValues[_index]),
"}]}"
)
);
return atomicValueAttr;
}
function _generateJsonDescription() internal view returns (string memory) {
return
string.concat(
string.concat(
'","description": "A collection of ',
Strings.toString(totalSupply / (10 ** decimals))
),
' digital collectible enabled by ERC404, an experimental token standard.", "external_url": "https://vexaeterna.com/'
);
}
function _generateJsonImage(
uint8 _index
) internal view returns (string memory) {
return
string.concat(
string.concat(
'", "image": "',
string.concat(
imageURI,
string.concat(materials[_index], '.png", ')
)
)
);
}
function _generateJsonNameAndCreator(
uint8 _index,
uint256 _tokenId
) internal view returns (string memory) {
string memory _name = string.concat(
'{"name": "',
string.concat(
materials[_index],
string.concat(" - ", Strings.toString(_tokenId))
)
);
return string.concat(_name, string.concat('", "created_by": "', name));
}
function _generateJsonMetadata(
uint8 _r,
uint256 _tokenId
) internal view returns (string memory uri) {
string memory _nameAndCreator = _generateJsonNameAndCreator(
_r,
_tokenId
);
string memory _description = _generateJsonDescription();
string memory _image = _generateJsonImage(_r);
string memory _attributes = _generateJsonAttributes(_r);
return
string.concat(
"data:application/json;utf8,",
string.concat(
_nameAndCreator,
string.concat(
_description,
string.concat(_image, _attributes)
)
)
);
}
}
{
"compilationTarget": {
"contracts/VexAeterna.sol": "VexAeterna"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"uint256","name":"maxTotalSupplyERC721_","type":"uint256"},{"internalType":"address","name":"initialOwner_","type":"address"},{"internalType":"address","name":"initialMintRecipient_","type":"address"},{"internalType":"address","name":"uniswapSwapRouter_","type":"address"},{"internalType":"address","name":"uniswapV3NonfungiblePositionManager_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyExists","type":"error"},{"inputs":[],"name":"DecimalsTooLow","type":"error"},{"inputs":[],"name":"ERC404UniswapV3ExemptFactoryMismatch","type":"error"},{"inputs":[],"name":"ERC404UniswapV3ExemptWETH9Mismatch","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InvalidApproval","type":"error"},{"inputs":[],"name":"InvalidExemption","type":"error"},{"inputs":[],"name":"InvalidOperator","type":"error"},{"inputs":[],"name":"InvalidRarity","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidSender","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidTokenId","type":"error"},{"inputs":[],"name":"MintLimitReached","type":"error"},{"inputs":[],"name":"NotFound","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnedIndexOverflow","type":"error"},{"inputs":[],"name":"PermitDeadlineExpired","type":"error"},{"inputs":[],"name":"QueueEmpty","type":"error"},{"inputs":[],"name":"QueueFull","type":"error"},{"inputs":[],"name":"QueueOutOfBounds","type":"error"},{"inputs":[],"name":"RecipientIsERC721TransferExempt","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsafeRecipient","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ID_ENCODING_PREFIX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"valueOrId_","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"atomicValues","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint8","name":"_rarity","type":"uint8"}],"name":"balanceOfByRarity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balancesOfByRarity","outputs":[{"internalType":"uint256[6]","name":"balances","type":"uint256[6]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"batchTransferERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"decodedTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"erc20Approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"erc20BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc20TotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"erc20TransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"erc721Approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"erc721BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc721TotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint8","name":"_rarity","type":"uint8"}],"name":"erc721TransferByRarity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target_","type":"address"}],"name":"erc721TransferExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"erc721TransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getERC721QueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start_","type":"uint256"},{"internalType":"uint256","name":"count_","type":"uint256"}],"name":"getERC721TokensInQueue","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHighestRarity","outputs":[{"internalType":"enum VexAeterna.Rarity","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getLowestRarity","outputs":[{"internalType":"enum VexAeterna.Rarity","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getRarityByTokenId","outputs":[{"internalType":"enum VexAeterna.Rarity","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"imageURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"materials","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"owned","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"erc721Owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"safeTransferFrom","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":"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":"uint8","name":"r","type":"uint8"},{"internalType":"uint16","name":"_newValue","type":"uint16"}],"name":"setAtomicValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"bool","name":"value_","type":"bool"}],"name":"setERC721TransferExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_imageURI","type":"string"}],"name":"setImageURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state_","type":"bool"}],"name":"setSelfERC721TransferExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"setTokenURI","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":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"valueOrId_","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"units","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]