Pea
0xfe177128df8d336caf99f787b72183d1e68ff9c2
Verification
Verified
0.8.28+commit.7893614a
Type
Contract
8,465 bytes
ABI entries
70
28 read · 12 write
License
none
Contract information
- Address
- 0xfe177128df8d336caf99f787b72183d1e68ff9c2
- Chain
- Robinhood Chain (4663)
- Compiler
- 0.8.28+commit.7893614a
- Optimization
- Enabled
- Creator
- 0x837C94A716…22164d7c21
- Creation tx
- 0x7f98c6888e…0f98094cba
Token
- Name
- MinePea
- Symbol
- PEA
- Decimals
- 18
- Holders
- 356
- Market
- View token page →
Read contract (28)
DOMAIN_SEPARATOR() → bytes32
MAX_SUPPLY() → uint256
MIN_SNAPSHOT_INTERVAL() → uint256
_isExcluded(address) → bool
allowance(address, address) → uint256
balanceOf(address) → uint256
currentSnapshotIndex() → uint8
decimals() → uint8
eip712Domain() → bytes1, string, string, uint256, address, bytes32, uint256[]
getOracleTWAP() → int24
getPriceDeviation() → int24, int24, uint24
getTWAPAmountOut(uint256) → uint256
getTickHistory() → tuple[5]
isTWAPReady() → bool
limited() → bool
minter() → address
minterFrozen() → bool
name() → string
nonces(address) → uint256
owner() → address
peaIsToken0() → bool
poolId() → bytes32
poolIdSet() → bool
poolManager() → address
symbol() → string
tickHistory(uint256) → int24, uint32
totalMinted() → uint256
totalSupply() → uint256
Events (7)
ApprovalEIP712DomainChangedMinterFrozenMinterUpdatedOwnershipTransferredPoolIdUpdatedTransfer
ABI
[
{
"inputs": [
{
"internalType": "address[]",
"name": "_Peas",
"type": "address[]"
},
{
"internalType": "address",
"name": "_poolManager",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "ECDSAInvalidSignature",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "length",
"type": "uint256"
}
],
"name": "ECDSAInvalidSignatureLength",
"type": "error"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "s",
"type": "bytes32"
}
],
"name": "ECDSAInvalidSignatureS",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "allowance",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "needed",
"type": "uint256"
}
],
"name": "ERC20InsufficientAllowance",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "uint256",
"name": "balance",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "needed",
"type": "uint256"
}
],
"name": "ERC20InsufficientBalance",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "approver",
"type": "address"
}
],
"name": "ERC20InvalidApprover",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "receiver",
"type": "address"
}
],
"name": "ERC20InvalidReceiver",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "ERC20InvalidSender",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "ERC20InvalidSpender",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "deadline",
"type": "uint256"
}
],
"name": "ERC2612ExpiredSignature",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "signer",
"type": "address"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "ERC2612InvalidSigner",
"type": "error"
},
{
"inputs": [],
"name": "ExceedsMaxSupply",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "uint256",
"name": "currentNonce",
"type": "uint256"
}
],
"name": "InvalidAccountNonce",
"type": "error"
},
{
"inputs": [],
"name": "InvalidShortString",
"type": "error"
},
{
"inputs": [],
"name": "MinterAlreadyFrozen",
"type": "error"
},
{
"inputs": [],
"name": "NotMinter",
"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": "PoolIdAlreadySet",
"type": "error"
},
{
"inputs": [
{
"internalType": "string",
"name": "str",
"type": "string"
}
],
"name": "StringTooLong",
"type": "error"
},
{
"inputs": [],
"name": "TWAPNotReady",
"type": "error"
},
{
"inputs": [],
"name": "ZeroAddress",
"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": [],
"name": "EIP712DomainChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "minter",
"type": "address"
}
],
"name": "MinterFrozen",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "oldMinter",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newMinter",
"type": "address"
}
],
"name": "MinterUpdated",
"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": "PoolId",
"name": "poolId",
"type": "bytes32"
}
],
"name": "PoolIdUpdated",
"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": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [],
"name": "DOMAIN_SEPARATOR",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MIN_SNAPSHOT_INTERVAL",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "_isExcluded",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "burn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "currentSnapshotIndex",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "eip712Domain",
"outputs": [
{
"internalType": "bytes1",
"name": "fields",
"type": "bytes1"
},
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "version",
"type": "string"
},
{
"internalType": "uint256",
"name": "chainId",
"type": "uint256"
},
{
"internalType": "address",
"name": "verifyingContract",
"type": "address"
},
{
"internalType": "bytes32",
"name": "salt",
"type": "bytes32"
},
{
"internalType": "uint256[]",
"name": "extensions",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "freezeMinter",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getOracleTWAP",
"outputs": [
{
"internalType": "int24",
"name": "twapTick",
"type": "int24"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getPriceDeviation",
"outputs": [
{
"internalType": "int24",
"name": "spotTick",
"type": "int24"
},
{
"internalType": "int24",
"name": "twapTick",
"type": "int24"
},
{
"internalType": "uint24",
"name": "deviationTicks",
"type": "uint24"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "ethAmount",
"type": "uint256"
}
],
"name": "getTWAPAmountOut",
"outputs": [
{
"internalType": "uint256",
"name": "expectedPEA",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getTickHistory",
"outputs": [
{
"components": [
{
"internalType": "int24",
"name": "tick",
"type": "int24"
},
{
"internalType": "uint32",
"name": "timestamp",
"type": "uint32"
}
],
"internalType": "struct Pea.TickSnapshot[5]",
"name": "snapshots",
"type": "tuple[5]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isTWAPReady",
"outputs": [
{
"internalType": "bool",
"name": "ready",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "limited",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "minter",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "minterFrozen",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "nonces",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "peaIsToken0",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"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": "poolId",
"outputs": [
{
"internalType": "PoolId",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "poolIdSet",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "poolManager",
"outputs": [
{
"internalType": "contract IPoolManager",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "removeLimits",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_minter",
"type": "address"
}
],
"name": "setMinter",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "PoolId",
"name": "_poolId",
"type": "bytes32"
}
],
"name": "setPoolId",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "tickHistory",
"outputs": [
{
"internalType": "int24",
"name": "tick",
"type": "int24"
},
{
"internalType": "uint32",
"name": "timestamp",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalMinted",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"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": "value",
"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"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import "@uniswap/v4-core/src/types/PoolId.sol";
import "@uniswap/v4-core/src/libraries/StateLibrary.sol";
import "@uniswap/v4-core/src/libraries/TickMath.sol";
import "@uniswap/v4-core/src/libraries/FullMath.sol";
contract Pea is ERC20, ERC20Permit, Ownable {
using StateLibrary for IPoolManager;
using PoolIdLibrary for PoolKey;
// ============ Constants ============
uint256 public constant MAX_SUPPLY = 3_000_000 * 1e18;
// ============ State ============
uint256 public totalMinted;
address public minter;
bool public minterFrozen;
bool public limited = true;
// V4 Pool
IPoolManager public immutable poolManager;
PoolId public poolId;
bool public poolIdSet;
bool public peaIsToken0;
// TWAP State
struct TickSnapshot {
int24 tick;
uint32 timestamp;
}
uint256 public constant MIN_SNAPSHOT_INTERVAL = 12;
TickSnapshot[5] public tickHistory;
mapping(address => bool) private _isPea;
mapping(address => bool) public _isExcluded;
mapping(address => bool) private _isAMMPool;
uint8 public currentSnapshotIndex;
uint256 private lastTickUpdateTime;
// ============ Events ============
event MinterUpdated(address indexed oldMinter, address indexed newMinter);
event MinterFrozen(address indexed minter);
event PoolIdUpdated(PoolId indexed poolId);
// ============ Errors ============
error NotMinter();
error MinterAlreadyFrozen();
error ExceedsMaxSupply();
error TWAPNotReady();
error ZeroAddress();
error PoolIdAlreadySet();
// ============ Constructor ============
constructor(
address[] memory _Peas,
address _poolManager
) ERC20("MinePea", "PEA") ERC20Permit("MinePea") Ownable(msg.sender) {
if (_poolManager == address(0)) revert ZeroAddress();
poolManager = IPoolManager(_poolManager);
uint256 initialMint = 10_000 * 1e18;
_mint(msg.sender, initialMint);
totalMinted = initialMint;
_setPeas(_Peas, true);
_isExcluded[_msgSender()] = true;
_isExcluded[address(this)] = true;
_isAMMPool[address(poolManager)] = true;
}
// ============ Admin Functions ============
function setMinter(address _minter) external onlyOwner {
if (minterFrozen) revert MinterAlreadyFrozen();
if (_minter == address(0)) revert ZeroAddress();
address oldMinter = minter;
minter = _minter;
emit MinterUpdated(oldMinter, _minter);
}
function freezeMinter() external onlyOwner {
if (minterFrozen) revert MinterAlreadyFrozen();
minterFrozen = true;
emit MinterFrozen(minter);
}
function _setPeas(address[] memory _Peas, bool _status) internal {
for (uint i = 0; i < _Peas.length; i++) {
_isPea[_Peas[i]] = _status;
}
}
function removeLimits() external onlyOwner {
limited = false;
}
/// @notice Set the V4 pool ID after creating the pool via PoolManager.initialize()
/// @dev Can only be called once. Determines token ordering for price calculations.
function setPoolId(PoolId _poolId) external onlyOwner {
if (poolIdSet) revert PoolIdAlreadySet();
poolId = _poolId;
poolIdSet = true;
// Native ETH = address(0), always lower than any contract address
peaIsToken0 = false;
emit PoolIdUpdated(_poolId);
}
// ============ Minting ============
function mint(address to, uint256 amount) external {
if (msg.sender != minter) revert NotMinter();
if (totalMinted + amount > MAX_SUPPLY) revert ExceedsMaxSupply();
totalMinted += amount;
_mint(to, amount);
}
function burn(uint256 amount) external {
_burn(msg.sender, amount);
}
// ============ Transfer Override for TWAP ============
function _update(address from, address to, uint256 value) internal override {
if (_isAMMPool[from] || _isAMMPool[to]) {
if (!_isExcluded[to] && !_isExcluded[from] && limited) {
require(_isPea[to] || _isPea[from], "Not Allowed");
}
_updateTickSnapshot();
}
super._update(from, to, value);
}
// ============ TWAP Functions ============
/// @notice Update the tick snapshot from V4 pool (called on AMM interactions)
function _updateTickSnapshot() private {
if (block.timestamp < lastTickUpdateTime + MIN_SNAPSHOT_INTERVAL) return;
if (!poolIdSet) return;
lastTickUpdateTime = block.timestamp;
// Read current tick from V4 PoolManager via StateLibrary (extsload)
(, int24 tick,,) = poolManager.getSlot0(poolId);
currentSnapshotIndex = uint8((currentSnapshotIndex + 1) % 5);
tickHistory[currentSnapshotIndex] = TickSnapshot({
tick: tick,
timestamp: uint32(block.timestamp)
});
}
/// @notice Calculate TWAP tick from snapshots
/// @return twapTick Arithmetic mean of stored ticks (= geometric mean of prices)
function getOracleTWAP() public view returns (int24 twapTick) {
int256 tickSum;
uint256 count;
for (uint256 i = 0; i < 5; i++) {
if (tickHistory[i].timestamp == 0) continue;
tickSum += tickHistory[i].tick;
count++;
}
if (count < 5) revert TWAPNotReady();
twapTick = int24(tickSum / int256(count));
}
/// @notice Get expected PEA output for a given ETH input using TWAP
/// @param ethAmount Amount of ETH (in wei)
/// @return expectedPEA Expected PEA output based on TWAP price
function getTWAPAmountOut(uint256 ethAmount) external view returns (uint256 expectedPEA) {
int24 twapTick = getOracleTWAP();
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(twapTick);
// Overflow-safe price calc (mirrors Uniswap V3 OracleLibrary)
if (sqrtPriceX96 <= type(uint128).max) {
uint256 ratioX192 = uint256(sqrtPriceX96) * uint256(sqrtPriceX96);
expectedPEA = peaIsToken0
? FullMath.mulDiv(1 << 192, ethAmount, ratioX192)
: FullMath.mulDiv(ratioX192, ethAmount, 1 << 192);
} else {
uint256 ratioX128 = FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, 1 << 64);
expectedPEA = peaIsToken0
? FullMath.mulDiv(1 << 128, ethAmount, ratioX128)
: FullMath.mulDiv(ratioX128, ethAmount, 1 << 128);
}
}
/// @notice Check if TWAP is ready (has 5 snapshots)
function isTWAPReady() external view returns (bool ready) {
uint256 count;
for (uint256 i = 0; i < 5; i++) {
if (tickHistory[i].timestamp != 0) count++;
}
return count >= 5;
}
/// @notice Get current spot price vs TWAP price deviation
/// @return spotTick Current pool tick
/// @return twapTick Average tick from snapshots
/// @return deviationTicks Absolute difference in ticks
function getPriceDeviation() external view returns (
int24 spotTick,
int24 twapTick,
uint24 deviationTicks
) {
if (!poolIdSet) return (0, 0, 0);
(, spotTick,,) = poolManager.getSlot0(poolId);
twapTick = getOracleTWAP();
int24 diff = spotTick - twapTick;
deviationTicks = diff >= 0 ? uint24(diff) : uint24(-diff);
}
// ============ View Functions ============
/// @notice Get all tick snapshots
function getTickHistory() external view returns (TickSnapshot[5] memory snapshots) {
return tickHistory;
}
}
Chain explorer3783msChain node83ms