编译器
0.8.17+commit.8df45f5f
文件 1 的 13:BaseAdminOperation.sol
pragma solidity ^0.8.4;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {TransferHelper} from "./util/TransferHelper.sol";
abstract contract BaseAdminOperation is Pausable, Ownable {
event AdminUpdated(address indexed addr, bool flag);
mapping(address => bool) public isAdmin;
modifier onlyAdmin() {
require(_msgSender() == owner() || isAdmin[_msgSender()], "BaseAdminOperation: !admin");
_;
}
function pause() public onlyAdmin {
_pause();
}
function unpause() public onlyAdmin {
_unpause();
}
function setAdmin(address addr, bool flag) public onlyAdmin {
isAdmin[addr] = flag;
emit AdminUpdated(addr, flag);
}
function inCaseTokenGotStuck(address stuckToken) external virtual onlyOwner {
if (stuckToken == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
TransferHelper.safeTransferETH(_msgSender(), address(this).balance);
} else {
uint256 amount = IERC20(stuckToken).balanceOf(address(this));
TransferHelper.safeTransfer(stuckToken, _msgSender(), amount);
}
}
}
文件 2 的 13:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 13:IERC1155.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
文件 4 的 13:IERC1155Receiver.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 5 的 13:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 6 的 13:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 7 的 13:INFTBoosterV2.sol
pragma solidity ^0.8.0;
interface INFTBoosterV2 {
event SetStakeTokenTTL(uint256 tokenId, uint256 newTTL, uint256 oldTTL);
struct StakeShortToken {
uint256 tokenId;
uint256 timestamp;
}
function base() external view returns (uint256);
function stakeAndBurn(uint256 _tokenId, uint256 _index) external;
function boostRatio(address _user) external view returns (uint256 compoundRatio, uint8[3] memory stakeTokenIds);
function getUserTier(address _user) external view returns (uint256 userTier);
}
文件 8 的 13:IRewardNFT.sol
pragma solidity ^0.8.0;
import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
interface IRewardNFT is IERC1155 {
function mint(address _user, uint256 _tokenId, uint256 _amount) external;
function burn(address _user, uint256 _tokenId, uint256 _amount) external;
function getAllTokenIds() external view returns (uint256[] memory allTokenIds);
}
文件 9 的 13:IWooStakingManager.sol
pragma solidity 0.8.17;
interface IWooStakingManager {
event StakeWooOnStakingManager(address indexed user, uint256 amount);
event UnstakeWooOnStakingManager(address indexed user, uint256 amount);
event AddMPOnStakingManager(address indexed user, uint256 amount);
event CompoundMPOnStakingManager(address indexed user);
event CompoundRewardsOnStakingManager(address indexed user, uint256 wooAmount);
event CompoundAllOnStakingManager(address indexed user);
event CompoundAllForUsersOnStakingManager(address[] users, uint256[] wooRewards);
event SetAutoCompoundOnStakingManager(address indexed user, bool flag);
event SetMPRewarderOnStakingManager(address indexed rewarder);
event SetWooPPOnStakingManager(address indexed wooPP);
event SetStakingLocalOnStakingManager(address indexed stakingProxy);
event SetCompounderOnStakingManager(address indexed compounder);
event AddRewarderOnStakingManager(address indexed rewarder);
event RemoveRewarderOnStakingManager(address indexed rewarder);
event ClaimRewardsOnStakingManager(address indexed user);
function stakeWoo(address _user, uint256 _amount) external;
function unstakeWoo(address _user, uint256 _amount) external;
function mpBalance(address _user) external view returns (uint256);
function wooBalance(address _user) external view returns (uint256);
function wooTotalBalance() external view returns (uint256);
function totalBalance(address _user) external view returns (uint256);
function totalBalance() external view returns (uint256);
function compoundMP(address _user) external;
function addMP(address _user, uint256 _amount) external;
function compoundRewards(address _user) external;
function compoundAll(address _user) external;
function compoundAllForUsers(address[] memory _users) external;
function setAutoCompound(address _user, bool _flag) external;
function pendingRewards(
address _user
) external view returns (uint256 mpRewardAmount, address[] memory rewardTokens, uint256[] memory amounts);
}
文件 10 的 13:NFTBoosterV2.sol
pragma solidity ^0.8.4;
import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import {BaseAdminOperation} from "../BaseAdminOperation.sol";
import {INFTBoosterV2} from "../interfaces/INFTBoosterV2.sol";
import {IRewardNFT} from "../interfaces/IRewardNFT.sol";
import {IWooStakingManager} from "../interfaces/IWooStakingManager.sol";
contract NFTBoosterV2 is INFTBoosterV2, IERC1155Receiver, BaseAdminOperation {
IRewardNFT public stakedNFT;
IWooStakingManager public stakingManager;
uint256 public base;
uint256 public tierCount = 10;
mapping(uint256 => uint256) public stakeTokenTTLs;
mapping(uint256 => uint256) public nftBoostRatios;
mapping(address => StakeShortToken[3]) public userStakeShortTokens;
mapping(uint256 => bool) public isActiveBucket;
mapping(uint256 => uint256) public tierThresholds;
mapping(uint256 => uint256) public tokenBoostDecayRatios;
constructor(address _stakedNFT, address _stakingManager) {
stakedNFT = IRewardNFT(_stakedNFT);
stakingManager = IWooStakingManager(_stakingManager);
base = 10000;
isActiveBucket[0] = true;
uint256[] memory tokenIds = stakedNFT.getAllTokenIds();
uint256 len = tokenIds.length;
for (uint256 i = 0; i < len; ++i) {
uint256 tokenId = tokenIds[i];
stakeTokenTTLs[tokenId] = 5 days;
}
tierThresholds[1] = 1_800e18;
tierThresholds[2] = 5_000e18;
tierThresholds[3] = 10_000e18;
tierThresholds[4] = 25_000e18;
tierThresholds[5] = 100_000e18;
tierThresholds[6] = 250_000e18;
tierThresholds[7] = 420_000e18;
tierThresholds[8] = 690_000e18;
tierThresholds[9] = 1_000_000e18;
tierThresholds[10] = 5_000_000e18;
}
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external override returns (bytes4) {
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
function stakeAndBurn(uint256 _tokenId, uint256 _index) external {
address user = msg.sender;
require(isActiveBucket[_index], "NFTBooster: !activeBucket");
require(_index < userStakeShortTokens[user].length, "NFTBooster: !largeBucket");
require(stakeTokenTTLs[_tokenId] > 0, "NFTBooster: !tokenId");
stakedNFT.burn(user, _tokenId, 1);
userStakeShortTokens[user][_index] = StakeShortToken(_tokenId, block.timestamp);
}
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId;
}
function boostRatio(address _user) external view returns (uint256 compoundRatio, uint8[3] memory stakeTokenIds) {
uint256 len = userStakeShortTokens[_user].length;
uint256 userTier = getUserTier(_user);
compoundRatio = base;
for (uint256 i = 0; i < len; ++i) {
if (!isActiveBucket[i]) continue;
uint256 tokenId = userStakeShortTokens[_user][i].tokenId;
uint256 timestamp = userStakeShortTokens[_user][i].timestamp;
if (tokenId == 0) continue;
if ((block.timestamp - timestamp) > stakeTokenTTLs[tokenId]) continue;
uint256 ratio = nftBoostRatios[tokenId] == 0 ? base : nftBoostRatios[tokenId];
uint256 accBoostDecayRatio = (base - tokenBoostDecayRatios[tokenId]) ** (userTier - 1);
uint256 ratioAfterDecay = (ratio * accBoostDecayRatio) / (base ** (userTier - 1));
compoundRatio = (compoundRatio * ratioAfterDecay) / base;
stakeTokenIds[i] = uint8(tokenId);
}
}
function getUserTier(address _user) public view returns (uint256 userTier) {
uint256 wooBal = stakingManager.wooBalance(_user);
for (uint256 i = tierCount; i > 0; --i) {
if (wooBal >= tierThresholds[i]) {
return i;
}
}
return 1;
}
function setStakedNFT(address _stakedNFT) external onlyOwner {
stakedNFT = IRewardNFT(_stakedNFT);
}
function setStakingManager(address _stakingManager) external onlyOwner {
stakingManager = IWooStakingManager(_stakingManager);
}
function setBase(uint256 _base) external onlyAdmin {
base = _base;
}
function setTierCount(uint256 _tierCount) external onlyOwner {
tierCount = _tierCount;
}
function setStakeTokenTTL(uint256 _tokenId, uint256 _ttl) external onlyAdmin {
uint256 oldTTL = stakeTokenTTLs[_tokenId];
stakeTokenTTLs[_tokenId] = _ttl;
emit SetStakeTokenTTL(_tokenId, _ttl, oldTTL);
}
function setNFTBoostRatios(uint256[] calldata _tokenIds, uint256[] calldata _ratios) external onlyOwner {
uint256 len = _tokenIds.length;
for (uint256 i = 0; i < len; ++i) {
require(_ratios[i] != 0, "NFTBooster: !_ratios");
nftBoostRatios[_tokenIds[i]] = _ratios[i];
}
}
function setActiveBucket(uint256 _bucket, bool _active) external onlyOwner {
isActiveBucket[_bucket] = _active;
}
function setTierThresholds(uint256[] calldata _tiers, uint256[] calldata _thresholds) external onlyOwner {
uint256 len = _tiers.length;
for (uint256 i = 0; i < len; ++i) {
tierThresholds[_tiers[i]] = _thresholds[i];
}
}
function setTokenBoostDecayRatios(
uint256[] calldata _tokenIds,
uint256[] calldata _boostDecayRatios
) external onlyOwner {
uint256 len = _tokenIds.length;
for (uint256 i = 0; i < len; ++i) {
tokenBoostDecayRatios[_tokenIds[i]] = _boostDecayRatios[i];
}
}
}
文件 11 的 13:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 12 的 13:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 13 的 13:TransferHelper.sol
pragma solidity ^0.8.0;
library TransferHelper {
function safeApprove(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper::safeApprove: approve failed"
);
}
function safeTransfer(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper::safeTransfer: transfer failed"
);
}
function safeTransferFrom(address token, address from, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper::transferFrom: transferFrom failed"
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "TransferHelper::safeTransferETH: ETH transfer failed");
}
}
{
"compilationTarget": {
"contracts/rewarders/NFTBoosterV2.sol": "NFTBoosterV2"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 20000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_stakedNFT","type":"address"},{"internalType":"address","name":"_stakingManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"bool","name":"flag","type":"bool"}],"name":"AdminUpdated","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTTL","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldTTL","type":"uint256"}],"name":"SetStakeTokenTTL","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"base","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"boostRatio","outputs":[{"internalType":"uint256","name":"compoundRatio","type":"uint256"},{"internalType":"uint8[3]","name":"stakeTokenIds","type":"uint8[3]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getUserTier","outputs":[{"internalType":"uint256","name":"userTier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stuckToken","type":"address"}],"name":"inCaseTokenGotStuck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isActiveBucket","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftBoostRatios","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bucket","type":"uint256"},{"internalType":"bool","name":"_active","type":"bool"}],"name":"setActiveBucket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"flag","type":"bool"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_base","type":"uint256"}],"name":"setBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_ratios","type":"uint256[]"}],"name":"setNFTBoostRatios","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_ttl","type":"uint256"}],"name":"setStakeTokenTTL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakedNFT","type":"address"}],"name":"setStakedNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakingManager","type":"address"}],"name":"setStakingManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tierCount","type":"uint256"}],"name":"setTierCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tiers","type":"uint256[]"},{"internalType":"uint256[]","name":"_thresholds","type":"uint256[]"}],"name":"setTierThresholds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_boostDecayRatios","type":"uint256[]"}],"name":"setTokenBoostDecayRatios","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"stakeAndBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakeTokenTTLs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakedNFT","outputs":[{"internalType":"contract IRewardNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingManager","outputs":[{"internalType":"contract IWooStakingManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tierCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tierThresholds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenBoostDecayRatios","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userStakeShortTokens","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"}]