编译器
0.8.20+commit.a1b79de6
文件 1 的 15:Arrays.sol
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
import {Math} from "./math/Math.sol";
library Arrays {
using StorageSlot for bytes32;
function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
low = mid + 1;
}
}
if (low > 0 && unsafeAccess(array, low - 1).value == element) {
return low - 1;
} else {
return low;
}
}
function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
bytes32 slot;
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getAddressSlot();
}
function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
bytes32 slot;
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getBytes32Slot();
}
function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
bytes32 slot;
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getUint256Slot();
}
function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
}
文件 2 的 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;
}
}
文件 3 的 15:Controlled.sol
pragma solidity ^0.8.20;
import "solady/src/auth/Ownable.sol";
abstract contract Controlled is Ownable {
error NotController();
mapping(address => bool) internal isController;
event ControllerUpdated(address addr, bool value_);
constructor() {
_initializeOwner(msg.sender);
}
function setController(address addr_, bool value_) external {
_checkOwner();
isController[addr_] = true;
emit ControllerUpdated(addr_, value_);
}
function _checkController() internal view {
if (!isController[msg.sender]) revert NotController();
}
}
文件 4 的 15:ERC1155.sol
pragma solidity ^0.8.20;
import {IERC1155} from "./IERC1155.sol";
import {IERC1155Receiver} from "./IERC1155Receiver.sol";
import {IERC1155MetadataURI} from "./extensions/IERC1155MetadataURI.sol";
import {Context} from "../../utils/Context.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
import {Arrays} from "../../utils/Arrays.sol";
import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol";
abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors {
using Arrays for uint256[];
using Arrays for address[];
mapping(uint256 id => mapping(address account => uint256)) private _balances;
mapping(address account => mapping(address operator => bool)) private _operatorApprovals;
string private _uri;
constructor(string memory uri_) {
_setURI(uri_);
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC1155).interfaceId ||
interfaceId == type(IERC1155MetadataURI).interfaceId ||
super.supportsInterface(interfaceId);
}
function uri(uint256 ) public view virtual returns (string memory) {
return _uri;
}
function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
return _balances[id][account];
}
function balanceOfBatch(
address[] memory accounts,
uint256[] memory ids
) public view virtual returns (uint256[] memory) {
if (accounts.length != ids.length) {
revert ERC1155InvalidArrayLength(ids.length, accounts.length);
}
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));
}
return batchBalances;
}
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address account, address operator) public view virtual returns (bool) {
return _operatorApprovals[account][operator];
}
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {
address sender = _msgSender();
if (from != sender && !isApprovedForAll(from, sender)) {
revert ERC1155MissingApprovalForAll(sender, from);
}
_safeTransferFrom(from, to, id, value, data);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) public virtual {
address sender = _msgSender();
if (from != sender && !isApprovedForAll(from, sender)) {
revert ERC1155MissingApprovalForAll(sender, from);
}
_safeBatchTransferFrom(from, to, ids, values, data);
}
function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual {
if (ids.length != values.length) {
revert ERC1155InvalidArrayLength(ids.length, values.length);
}
address operator = _msgSender();
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids.unsafeMemoryAccess(i);
uint256 value = values.unsafeMemoryAccess(i);
if (from != address(0)) {
uint256 fromBalance = _balances[id][from];
if (fromBalance < value) {
revert ERC1155InsufficientBalance(from, fromBalance, value, id);
}
unchecked {
_balances[id][from] = fromBalance - value;
}
}
if (to != address(0)) {
_balances[id][to] += value;
}
}
if (ids.length == 1) {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
emit TransferSingle(operator, from, to, id, value);
} else {
emit TransferBatch(operator, from, to, ids, values);
}
}
function _updateWithAcceptanceCheck(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal virtual {
_update(from, to, ids, values);
if (to != address(0)) {
address operator = _msgSender();
if (ids.length == 1) {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
_doSafeTransferAcceptanceCheck(operator, from, to, id, value, data);
} else {
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, values, data);
}
}
}
function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(from, to, ids, values, data);
}
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
_updateWithAcceptanceCheck(from, to, ids, values, data);
}
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(address(0), to, ids, values, data);
}
function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
_updateWithAcceptanceCheck(address(0), to, ids, values, data);
}
function _burn(address from, uint256 id, uint256 value) internal {
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(from, address(0), ids, values, "");
}
function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal {
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
_updateWithAcceptanceCheck(from, address(0), ids, values, "");
}
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC1155InvalidOperator(address(0));
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 value,
bytes memory data
) private {
if (to.code.length > 0) {
try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
revert ERC1155InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert ERC1155InvalidReceiver(to);
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) private {
if (to.code.length > 0) {
try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (
bytes4 response
) {
if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
revert ERC1155InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert ERC1155InvalidReceiver(to);
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
function _asSingletonArrays(
uint256 element1,
uint256 element2
) private pure returns (uint256[] memory array1, uint256[] memory array2) {
assembly {
array1 := mload(0x40)
mstore(array1, 1)
mstore(add(array1, 0x20), element1)
array2 := add(array1, 0x40)
mstore(array2, 1)
mstore(add(array2, 0x20), element2)
mstore(0x40, add(array2, 0x40))
}
}
}
文件 5 的 15:ERC165.sol
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 6 的 15:IERC1155.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}
文件 7 的 15:IERC1155MetadataURI.sol
pragma solidity ^0.8.20;
import {IERC1155} from "../IERC1155.sol";
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
文件 8 的 15:IERC1155Receiver.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 9 的 15:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 10 的 15:LibUtils.sol
pragma solidity ^0.8.20;
library LibUtils {
address internal constant _ROUTER = 0x6BDED42c6DA8FBf0d2bA55B2fa120C5e0c8D7891;
function _keccakU256(uint256 input) internal pure returns (uint256 output) {
assembly {
mstore(0x0, input)
output := keccak256(0x0, 0x20)
}
}
function _safeTransferETH(address to_, uint256 amount_) internal {
assembly {
if iszero(call(gas(), to_, amount_, 0, 0, 0, 0)) {
mstore(0x0, 0x90b8ec18)
revert(0x0, 0x4)
}
}
}
function _revert(bytes4 code) internal pure {
assembly {
mstore(0x0, code)
revert(0x0, 0x4)
}
}
}
文件 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.4;
abstract contract Ownable {
error Unauthorized();
error NewOwnerIsZeroAddress();
error NoHandoverRequest();
error AlreadyInitialized();
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
event OwnershipHandoverRequested(address indexed pendingOwner);
event OwnershipHandoverCanceled(address indexed pendingOwner);
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
bytes32 internal constant _OWNER_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
function _initializeOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
assembly {
let ownerSlot := _OWNER_SLOT
if sload(ownerSlot) {
mstore(0x00, 0x0dc149f0)
revert(0x1c, 0x04)
}
newOwner := shr(96, shl(96, newOwner))
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
} else {
assembly {
newOwner := shr(96, shl(96, newOwner))
sstore(_OWNER_SLOT, newOwner)
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
}
function _setOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
assembly {
let ownerSlot := _OWNER_SLOT
newOwner := shr(96, shl(96, newOwner))
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
}
} else {
assembly {
let ownerSlot := _OWNER_SLOT
newOwner := shr(96, shl(96, newOwner))
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
sstore(ownerSlot, newOwner)
}
}
}
function _checkOwner() internal view virtual {
assembly {
if iszero(eq(caller(), sload(_OWNER_SLOT))) {
mstore(0x00, 0x82b42900)
revert(0x1c, 0x04)
}
}
}
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
function transferOwnership(address newOwner) public payable virtual onlyOwner {
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae)
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
assembly {
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
function cancelOwnershipHandover() public payable virtual {
assembly {
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
assembly {
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818)
revert(0x1c, 0x04)
}
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
function owner() public view virtual returns (address result) {
assembly {
result := sload(_OWNER_SLOT)
}
}
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
assembly {
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
result := sload(keccak256(0x0c, 0x20))
}
}
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}
文件 13 的 15:Pokebase.sol
pragma solidity ^0.8.20;
import "solady/src/auth/Ownable.sol";
import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import {Controlled} from "../lib/Controlled.sol";
import "../lib/LibUtils.sol";
interface IPoke {
function burn(address from, uint256 amount) external;
function mint(address to, uint256 amount) external;
}
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
}
interface IUniswapV2Pair {
function getReserves() external view returns (uint112, uint112, uint32);
function token0() external view returns (address);
}
contract Pokebase is ERC1155, Controlled {
error NonExistantTokenId();
error NoReserves();
error PlatformOffline();
error MaxSupplyReached();
error BondsNotStarted();
error InsufficientETH();
error AboveLimits();
error NotEnoughToCompound();
error NotEnoughToClaim();
error OnlyEOA();
struct PokebaseType {
uint248 interest;
uint8 chance;
}
struct MintData {
uint8 id;
uint8 offsetDraw;
uint240 amount;
}
IPoke public poke;
address private constant _USDC = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913;
IUniswapV2Pair private ethPokePair;
IUniswapV2Pair private ethUsdcPair;
uint8 public maxSupplyNodes = 49;
uint8 public bondDiscount = 25;
uint64 public bondNodeStartTime;
address public treasury;
bool public isLive = true;
uint64 public interestDuration = 86400;
uint256 public nodeCost = 100000000000000000000;
uint256 public nodeBase = 4000000000000000000;
uint256 public totalNodes = 0;
event Claimed(address indexed user, uint256 amount);
mapping(uint256 => PokebaseType) public pokebases;
mapping(address => uint256) public claimables;
mapping(address => mapping(uint256 => uint256)) public holdings;
constructor(
address poke_,
address ethPokePair_,
address treasury_
)
ERC1155(
"https://emerald-fat-toucan-494.mypinata.cloud/ipfs/QmR8pwc2RWJyrPJocLuYi1fCqfDmgBHpaWvS3ryCpUX2yW/"
)
{
poke = IPoke(poke_);
ethPokePair = IUniswapV2Pair(ethPokePair_);
ethUsdcPair = IUniswapV2Pair(0xcDAC0d6c6C59727a65F871236188350531885C43);
treasury = treasury_;
isController[msg.sender] = true;
_initpokebaseTypes();
}
function setURI(string memory newuri_) external {
_checkOwner();
_setURI(newuri_);
}
function addPokebaseTypes(PokebaseType[] calldata types_) external {
_checkOwner();
uint256 nextId = maxSupplyNodes;
uint256 len = types_.length;
if (nextId + len > 255) LibUtils._revert(MaxSupplyReached.selector);
unchecked {
for (uint256 i = 0; i < len; ++i) {
pokebases[nextId++] = types_[i];
}
maxSupplyNodes = uint8(nextId);
}
}
function setPokebaseType(
uint256 tokenId_,
uint248 interest_,
uint8 chance_
) external {
_checkOwner();
if (tokenId_ > maxSupplyNodes)
LibUtils._revert(NonExistantTokenId.selector);
pokebases[tokenId_] = PokebaseType({
interest: interest_,
chance: chance_
});
}
function setBondDiscount(uint8 discount_) external {
_checkOwner();
if (discount_ > 75) LibUtils._revert(AboveLimits.selector);
bondDiscount = discount_;
}
function setTreasuryAddr(address treasury_) external {
_checkOwner();
treasury = treasury_;
}
function setPoke(address addr_) external {
_checkOwner();
poke = IPoke(addr_);
}
function setInterestDuration(uint64 duration_) external {
_checkOwner();
interestDuration = duration_;
}
function setPlatformState(bool isLive_) external {
_checkOwner();
isLive = isLive_;
}
function setBondNodeStartTime(uint64 bondStartTime_) external {
_checkOwner();
bondNodeStartTime = bondStartTime_;
}
function setNodeCost(uint256 cost_) external {
_checkOwner();
nodeCost = cost_;
}
function setNodeBase(uint256 base_) external {
_checkOwner();
nodeBase = base_;
}
function awardNode(
address addr_,
uint256 tokenId_,
uint256 amount_
) external {
_checkController();
_updateClaims(addr_, tokenId_);
_mint(addr_, tokenId_, amount_, "");
totalNodes += amount_;
}
function currentDailyRewards(
uint256 tokenId_
) external view returns (uint256) {
if (tokenId_ > maxSupplyNodes)
LibUtils._revert(NonExistantTokenId.selector);
return nodeBase + pokebases[tokenId_].interest;
}
function interestsOnDuration(
address addr_,
uint256[] calldata tokenIds_
) external view returns (uint256) {
unchecked {
uint256 len = tokenIds_.length;
uint256 rewards;
for (uint256 i; i < len; ++i) {
uint256 id = tokenIds_[i];
uint256 balance = balanceOf(addr_, id);
uint256 interest = pokebases[id].interest;
if (interest > 0) rewards += (nodeBase + interest) * balance;
}
return rewards;
}
}
function getExistingNodes() public view returns (PokebaseType[] memory) {
PokebaseType[] memory allTypes = new PokebaseType[](maxSupplyNodes);
unchecked {
for (uint i = 0; i < maxSupplyNodes; ++i) {
allTypes[i] = pokebases[i];
}
}
return allTypes;
}
function getNodeIds(address owner_) public view returns (uint8[] memory) {
uint256[] memory allIds = new uint256[](maxSupplyNodes);
uint256 count;
unchecked {
for (uint256 i = 0; i < maxSupplyNodes; ++i) {
uint256 balance = balanceOf(owner_, i);
if (balance > 0) {
allIds[i] = 1;
++count;
}
}
uint8[] memory heldIds = new uint8[](count);
uint256 index;
for (uint i = 0; i < maxSupplyNodes; ++i) {
if (allIds[i] > 0) heldIds[index++] = uint8(i);
}
return heldIds;
}
}
function uri(
uint256 tokenId_
) public view override returns (string memory) {
if (tokenId_ > maxSupplyNodes)
LibUtils._revert(NonExistantTokenId.selector);
return
string(
abi.encodePacked(super.uri(0), _toString(tokenId_), ".json")
);
}
function safeTransferFrom(
address from_,
address to_,
uint256 id_,
uint256 value_,
bytes memory data_
) public override {
_updateClaims(from_, id_);
_updateClaims(to_, id_);
super.safeTransferFrom(from_, to_, id_, value_, data_);
}
function safeBatchTransferFrom(
address from_,
address to_,
uint256[] memory ids_,
uint256[] memory values_,
bytes memory data_
) public override {
uint256 len = ids_.length;
for (uint256 i; i < len; ) {
_updateClaims(from_, ids_[i]);
_updateClaims(to_, ids_[i]);
unchecked {
++i;
}
}
super.safeBatchTransferFrom(from_, to_, ids_, values_, data_);
}
function burn(address from_, uint256 id_, uint256 value_) external {
_checkController();
_updateClaims(from_, id_);
_burn(from_, id_, value_);
totalNodes -= value_;
}
function getPrice() public view returns (uint256) {
(uint112 reserve0, uint112 reserve1, ) = ethPokePair.getReserves();
if (reserve0 == 0 || reserve1 == 0)
LibUtils._revert(NoReserves.selector);
address token0 = ethPokePair.token0();
return (
token0 == address(poke)
? (uint256(reserve1) * 1e18) / reserve0
: (uint256(reserve0) * 1e18) / reserve1
);
}
function getBondCost() public view returns (uint256) {
uint256 tokenPrice = getPrice();
uint256 basePriceETH = (nodeCost * tokenPrice) / 1e18;
uint256 discount;
unchecked {
discount = 100 - bondDiscount;
}
uint256 bondPrice = (basePriceETH * discount) / 100;
return bondPrice;
}
function getEthPriceUsdc() public view returns (uint256) {
(uint112 reserve0, uint112 reserve1, ) = ethUsdcPair.getReserves();
if (reserve0 == 0 || reserve1 == 0) revert NoReserves();
address token0 = ethUsdcPair.token0();
uint256 ethReserve;
uint256 usdcReserve;
if (token0 == _USDC) {
usdcReserve = reserve0;
ethReserve = reserve1;
} else {
usdcReserve = reserve1;
ethReserve = reserve0;
}
return (usdcReserve * 1e18) / ethReserve;
}
function getPriceUsdc() public view returns (uint256) {
uint256 pokePriceInEth = getPrice();
uint256 ethPriceInUsdc = getEthPriceUsdc();
uint256 nodeCostInEth = (nodeCost * pokePriceInEth) / 1e18;
uint256 nodeCostInUsdc = (nodeCostInEth * ethPriceInUsdc) / 1e18;
return nodeCostInUsdc;
}
function getBondCostUSDC() public view returns (uint256) {
uint256 price = getPriceUsdc();
uint256 discount;
unchecked {
discount = 100 - bondDiscount;
}
uint256 bondPrice = (price * discount) / 100;
return bondPrice;
}
function getClaimable(
address _user,
uint256[] calldata tokenId_,
bool cumulative_
) public view returns (uint256) {
uint256 pending;
uint256 len = tokenId_.length;
for (uint256 i = 0; i < len; ) {
uint256 holdSince = holdings[_user][tokenId_[i]];
if (holdSince > 0) {
pending +=
(balanceOf(_user, tokenId_[i]) *
(nodeBase + pokebases[tokenId_[i]].interest) *
(block.timestamp - holdSince)) /
interestDuration;
}
unchecked {
++i;
}
}
if (!cumulative_) return pending;
return claimables[_user] + pending;
}
function buyNode(
uint256 amount_,
bool isBondETH_,
bool isBondUSDC_
) external payable {
if (!isLive) LibUtils._revert(PlatformOffline.selector);
if (msg.sender != tx.origin)
LibUtils._revert(OnlyEOA.selector);
if (
(isBondETH_ || isBondUSDC_) &&
(bondNodeStartTime == 0 || block.timestamp < bondNodeStartTime)
) revert BondsNotStarted();
if (isBondETH_) {
uint256 bondCostEth = getBondCost() * amount_;
if (msg.value < bondCostEth)
LibUtils._revert(InsufficientETH.selector);
LibUtils._safeTransferETH(treasury, bondCostEth);
} else if (isBondUSDC_) {
uint256 bondCostUsdc = getBondCostUSDC() * amount_;
_safeTransferTokenFrom(
_USDC,
msg.sender,
treasury,
bondCostUsdc
);
} else {
uint256 bondCostPoke = nodeCost * amount_;
poke.burn(
msg.sender,
bondCostPoke
);
}
uint256 randomNumber = block.prevrandao;
assembly {
randomNumber := sub(add(randomNumber, caller()), mul(gasprice(), number()))
}
_randomMint(msg.sender, amount_, randomNumber);
}
function compoundNode(
uint256[] calldata tokenIds_,
uint256 amount_
) public {
if (!isLive) LibUtils._revert(PlatformOffline.selector);
if (msg.sender != tx.origin)
LibUtils._revert(OnlyEOA.selector);
uint256 len = tokenIds_.length;
for (uint256 i; i < len; ) {
_updateClaims(msg.sender, tokenIds_[i]);
unchecked {
++i;
}
}
uint256 claimable = claimables[msg.sender];
uint256 maxAmount;
unchecked {
maxAmount = claimable / nodeCost;
}
if (maxAmount == 0) LibUtils._revert(NotEnoughToCompound.selector);
if (amount_ == 0) {
amount_ = maxAmount;
} else if (amount_ > maxAmount) {
LibUtils._revert(NotEnoughToCompound.selector);
}
unchecked {
claimables[msg.sender] = claimable - (amount_ * nodeCost);
}
uint256 randomNumber = block.prevrandao;
assembly {
randomNumber := sub(add(randomNumber, caller()), mul(gasprice(), number()))
}
_randomMint(msg.sender, amount_, randomNumber);
}
function claim(uint256 tokenId_) external payable {
_updateClaims(msg.sender, tokenId_);
uint256 claimable = claimables[msg.sender];
if (claimable == 0) LibUtils._revert(NotEnoughToClaim.selector);
delete claimables[msg.sender];
poke.mint(msg.sender, claimable);
}
function claimMultiple(uint256[] calldata tokenIds_) external payable {
uint256 len = tokenIds_.length;
for (uint256 i; i < len; ) {
uint256 tokenId = tokenIds_[i];
_updateClaims(msg.sender, tokenId);
unchecked {
++i;
}
}
uint256 claimable = claimables[msg.sender];
if (claimable == 0) LibUtils._revert(NotEnoughToClaim.selector);
delete claimables[msg.sender];
poke.mint(msg.sender, claimable);
}
function _randomMint(
address to_,
uint256 amount_,
uint256 randomNumber_
) internal {
uint8 cachedMaxSupply = maxSupplyNodes;
unchecked {
for (uint256 i; i < amount_; ++i) {
uint8 randomId;
assembly {
randomId := mod(randomNumber_, cachedMaxSupply)
}
uint256 PokebaseChance = pokebases[randomId].chance;
randomNumber_ = LibUtils._keccakU256(randomNumber_);
assembly {
let secRdm := add(mod(randomNumber_, 100), 1)
if gt(secRdm, PokebaseChance) {
randomId := mod(add(randomId, secRdm), cachedMaxSupply)
}
}
_updateClaims(to_, randomId);
_mint(to_, randomId, 1, "");
}
totalNodes += amount_;
}
}
function _updateClaims(address owner_, uint256 tokenId_) internal {
uint256 timerFrom = holdings[owner_][tokenId_];
if (timerFrom == block.timestamp) return;
holdings[owner_][tokenId_] = uint64(block.timestamp);
if (timerFrom > 0)
claimables[owner_] +=
(balanceOf(owner_, tokenId_) *
(nodeBase + pokebases[tokenId_].interest) *
(block.timestamp - timerFrom)) /
interestDuration;
}
function _toString(
uint256 value_
) internal pure returns (string memory str) {
assembly {
let m := add(mload(0x40), 0xa0)
mstore(0x40, m)
str := sub(m, 0x20)
mstore(str, 0)
let end := str
for { let temp := value_ } 1 {} {
str := sub(str, 1)
mstore8(str, add(48, mod(temp, 10)))
temp := div(temp, 10)
if iszero(temp) { break }
}
let length := sub(end, str)
str := sub(str, 0x20)
mstore(str, length)
}
}
function _safeTransferTokenFrom(
address token,
address from,
address to,
uint256 amount
) private {
assembly {
let m := mload(0x40)
mstore(0x60, amount)
mstore(0x40, to)
mstore(0x2c, shl(96, from))
mstore(0x0c, 0x23b872dd000000000000000000000000)
if iszero(
and(
or(eq(mload(0x00), 1), iszero(returndatasize())),
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18)
revert(0x1c, 0x04)
}
mstore(0x60, 0)
mstore(0x40, m)
}
}
function _initpokebaseTypes() private {
pokebases[0] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[1] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[2] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[3] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[4] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[5] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[6] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[7] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[8] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[9] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[10] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[11] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[12] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[13] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[14] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[15] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[16] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[17] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[18] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[19] = PokebaseType({interest: 1000000000000000000, chance: 100});
pokebases[20] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[21] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[22] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[23] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[24] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[25] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[26] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[27] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[28] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[29] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[30] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[31] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[32] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[33] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[34] = PokebaseType({interest: 2000000000000000000, chance: 70});
pokebases[35] = PokebaseType({interest: 6000000000000000000, chance: 40});
pokebases[36] = PokebaseType({interest: 6000000000000000000, chance: 40});
pokebases[37] = PokebaseType({interest: 6000000000000000000, chance: 40});
pokebases[38] = PokebaseType({interest: 6000000000000000000, chance: 40});
pokebases[39] = PokebaseType({interest: 6000000000000000000, chance: 40});
pokebases[40] = PokebaseType({interest: 6000000000000000000, chance: 40});
pokebases[41] = PokebaseType({interest: 6000000000000000000, chance: 40});
pokebases[42] = PokebaseType({interest: 16000000000000000000, chance: 20});
pokebases[43] = PokebaseType({interest: 16000000000000000000, chance: 20});
pokebases[44] = PokebaseType({interest: 16000000000000000000, chance: 20});
pokebases[45] = PokebaseType({interest: 16000000000000000000, chance: 20});
pokebases[46] = PokebaseType({interest: 16000000000000000000, chance: 20});
pokebases[47] = PokebaseType({interest: 36000000000000000000, chance: 5});
pokebases[48] = PokebaseType({interest: 36000000000000000000, chance: 5});
}
}
文件 14 的 15:StorageSlot.sol
pragma solidity ^0.8.20;
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly {
r.slot := slot
}
}
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly {
r.slot := store.slot
}
}
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly {
r.slot := slot
}
}
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly {
r.slot := store.slot
}
}
}
文件 15 的 15:draft-IERC6093.sol
pragma solidity ^0.8.20;
interface IERC20Errors {
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
error ERC20InvalidSender(address sender);
error ERC20InvalidReceiver(address receiver);
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
error ERC20InvalidApprover(address approver);
error ERC20InvalidSpender(address spender);
}
interface IERC721Errors {
error ERC721InvalidOwner(address owner);
error ERC721NonexistentToken(uint256 tokenId);
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
error ERC721InvalidSender(address sender);
error ERC721InvalidReceiver(address receiver);
error ERC721InsufficientApproval(address operator, uint256 tokenId);
error ERC721InvalidApprover(address approver);
error ERC721InvalidOperator(address operator);
}
interface IERC1155Errors {
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
error ERC1155InvalidSender(address sender);
error ERC1155InvalidReceiver(address receiver);
error ERC1155MissingApprovalForAll(address operator, address owner);
error ERC1155InvalidApprover(address approver);
error ERC1155InvalidOperator(address operator);
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
{
"compilationTarget": {
"contracts/poke/Pokebase.sol": "Pokebase"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"poke_","type":"address"},{"internalType":"address","name":"ethPokePair_","type":"address"},{"internalType":"address","name":"treasury_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AboveLimits","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BondsNotStarted","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[],"name":"InsufficientETH","type":"error"},{"inputs":[],"name":"MaxSupplyReached","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NoReserves","type":"error"},{"inputs":[],"name":"NonExistantTokenId","type":"error"},{"inputs":[],"name":"NotController","type":"error"},{"inputs":[],"name":"NotEnoughToClaim","type":"error"},{"inputs":[],"name":"NotEnoughToCompound","type":"error"},{"inputs":[],"name":"OnlyEOA","type":"error"},{"inputs":[],"name":"PlatformOffline","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"bool","name":"value_","type":"bool"}],"name":"ControllerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"components":[{"internalType":"uint248","name":"interest","type":"uint248"},{"internalType":"uint8","name":"chance","type":"uint8"}],"internalType":"struct Pokebase.PokebaseType[]","name":"types_","type":"tuple[]"}],"name":"addPokebaseTypes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"awardNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondDiscount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondNodeStartTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"bool","name":"isBondETH_","type":"bool"},{"internalType":"bool","name":"isBondUSDC_","type":"bool"}],"name":"buyNode","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds_","type":"uint256[]"}],"name":"claimMultiple","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimables","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds_","type":"uint256[]"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"compoundNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"currentDailyRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBondCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBondCostUSDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256[]","name":"tokenId_","type":"uint256[]"},{"internalType":"bool","name":"cumulative_","type":"bool"}],"name":"getClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEthPriceUsdc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExistingNodes","outputs":[{"components":[{"internalType":"uint248","name":"interest","type":"uint248"},{"internalType":"uint8","name":"chance","type":"uint8"}],"internalType":"struct Pokebase.PokebaseType[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"getNodeIds","outputs":[{"internalType":"uint8[]","name":"","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPriceUsdc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"holdings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestDuration","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"},{"internalType":"uint256[]","name":"tokenIds_","type":"uint256[]"}],"name":"interestsOnDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupplyNodes","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nodeBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nodeCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poke","outputs":[{"internalType":"contract IPoke","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pokebases","outputs":[{"internalType":"uint248","name":"interest","type":"uint248"},{"internalType":"uint8","name":"chance","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256[]","name":"ids_","type":"uint256[]"},{"internalType":"uint256[]","name":"values_","type":"uint256[]"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"value_","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":"discount_","type":"uint8"}],"name":"setBondDiscount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"bondStartTime_","type":"uint64"}],"name":"setBondNodeStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"},{"internalType":"bool","name":"value_","type":"bool"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"duration_","type":"uint64"}],"name":"setInterestDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"base_","type":"uint256"}],"name":"setNodeBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cost_","type":"uint256"}],"name":"setNodeCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isLive_","type":"bool"}],"name":"setPlatformState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"}],"name":"setPoke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint248","name":"interest_","type":"uint248"},{"internalType":"uint8","name":"chance_","type":"uint8"}],"name":"setPokebaseType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"treasury_","type":"address"}],"name":"setTreasuryAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newuri_","type":"string"}],"name":"setURI","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":"totalNodes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]