// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { FullMath } from "@uniswap/v4-core/src/libraries/FullMath.sol";
import { TickMath } from "@uniswap/v4-core/src/libraries/TickMath.sol";
import { IDerivedPoolFeed } from "./interfaces/IDerivedPoolFeed.sol";
interface IExtsload {
function extsload(bytes32 slot) external view returns (bytes32);
}
interface IChainlinkQuote {
function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
function decimals() external view returns (uint8);
}
/// @title RipV4UsdAggregator
/// @notice A Chainlink-shaped USD feed for a token that trades only on a Uniswap **v4** pool, carrying
/// its own price history because v4 does not.
///
/// @dev THE AVERAGE HOLDS ONLY WHILE THE RING IS FED. {poke} must be called more often than
/// {twapWindow}: once the newest observation is older than the window, the mean is computed
/// across that single observation and equals the current tick, while {twapAvailable} still
/// answers true. {UniV4SpotUsdAggregator} reports the pool price without a ring for consumers
/// that cannot guarantee the cadence.
///
/// THE FEED CARRIES ITS OWN PRICE HISTORY. Uniswap v4 core exposes no oracle: there are no
/// observations and no `observe`. Price lives in one packed `slot0` word reachable through
/// `extsload`, and it is the CURRENT price, movable inside a single block by anyone willing to
/// push the pool and push it back. RIP's pool hook keeps no history either.
///
/// {poke} is the accumulator that closes that gap — a permissionless tick-time integral held in
/// this contract's own ring, giving a time-weighted average over {twapWindow}.
///
/// WHAT THE ANSWER GOVERNS. This feed gates a vault card's minimum value on mint and on
/// withdrawal, both permanent state changes, so the answer is always the average and never the
/// spot price. The finish a card wears is read at view time and follows price back down; the
/// floors do not.
///
/// THE FAILURE MODE. With too little history to cover the window, the answer is zero, meaning
/// "no price": the renderer draws an em dash and the floor counts the asset as nothing, so a
/// card clears its minimum on assets that have a price. {spotUsd} remains available to an
/// operator as a diagnostic.
contract RipV4UsdAggregator is Ownable, IDerivedPoolFeed {
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
uint8 public constant DECIMALS = 8;
uint256 public constant VERSION = 4;
/// @dev v4 packs pool state under `POOLS_SLOT`; `slot0` is the first word of a pool's state.
bytes32 private constant POOLS_SLOT = bytes32(uint256(6));
uint32 public constant MIN_TWAP_WINDOW = 60;
uint32 public constant MAX_TWAP_WINDOW = 12 hours;
/// @notice Ceiling on {quoteMaxAge}, matching {StockFeedRegistry.MAX_AGE_LIMIT}. The window is
/// bounded above and required non-zero, so the freshness check on the reference leg stays
/// active under every configuration.
uint32 public constant MAX_QUOTE_AGE = 7 days;
/// @notice The exchange family the priced pool lives on, as reported by {describe}.
string public constant VENUE = "uniswap-v4";
/// @notice Ceiling on the reference feed's reported decimals. Beyond this the rescale exponent
/// overflows, so a reference reporting more than this yields no price and the read keeps
/// working. Matches {StockFeedRegistry}'s own bound.
uint8 public constant MAX_QUOTE_DECIMALS = 36;
/// @notice Ceiling on the reference feed's answer, for the same reason: an unbounded answer reaches
/// the fixed-point multiply in {_usd} and reverts instead of reporting no price.
uint256 public constant MAX_QUOTE_ANSWER = 1e36;
/// @dev Ring capacity. Each observation is one slot; 64 at a 5-minute cadence spans ~5 hours,
/// comfortably more than any window this feed will be configured with.
uint256 public constant CARDINALITY = 64;
/// @dev Gas ceiling on the quote call, so a hostile or broken feed cannot burn the caller's gas.
uint256 private constant QUOTE_GAS_LIMIT = 200_000;
/*//////////////////////////////////////////////////////////////
IMMUTABLE
//////////////////////////////////////////////////////////////*/
/// @notice The v4 singleton every pool lives in.
IExtsload public immutable poolManager;
/// @notice The pool this feed reads, as its v4 id.
bytes32 public immutable poolId;
/// @notice The token being priced.
address public immutable token;
/// @notice True when {token} is the pool's `currency1`, which decides whether the pool's price is
/// inverted before use. RIP/ETH pools put native ETH at `currency0`, so this is true.
bool public immutable tokenIsCurrency1;
/// @notice The pool's other leg — the asset the price is quoted against, and the one {quoteFeed}
/// prices in USD. Native ETH is `address(0)`, as v4 itself represents it.
/// @dev Supplied at construction, because a v4 pool id is the hash of a PoolKey and the
/// currencies cannot be recovered from it. The value is therefore a claim about the pool,
/// verified by recomputing the pool id from the key off chain.
address public immutable referenceAsset;
/*//////////////////////////////////////////////////////////////
STATE
//////////////////////////////////////////////////////////////*/
struct Observation {
uint32 timestamp;
int56 tickCumulative;
bool initialised;
}
Observation[CARDINALITY] private _ring;
uint256 public index; // slot of the most recent observation
uint256 public written; // observations ever written, capped for reads at CARDINALITY
/// @notice The averaging window. Longer resists manipulation harder and tracks the market slower.
uint32 public twapWindow;
/// @notice How stale the quote leg may be before this feed reports nothing.
uint32 public quoteMaxAge;
/// @notice The ETH/USD Chainlink feed the pool price is quoted through.
address public quoteFeed;
string public description;
/*//////////////////////////////////////////////////////////////
EVENTS / ERRORS
//////////////////////////////////////////////////////////////*/
event Poked(uint256 indexed slot, uint32 timestamp, int24 tick, int56 tickCumulative);
event TwapWindowSet(uint32 window);
event QuoteFeedSet(address feed, uint32 maxAge);
event DescriptionSet(string description);
error ZeroAddress();
error TwapWindowOutOfRange(uint32 window);
error QuoteMaxAgeOutOfRange(uint32 maxAge);
error QuoteFeedIsDerived(address quoteFeed);
error PoolNotInitialised();
constructor(
IExtsload poolManager_,
bytes32 poolId_,
address token_,
bool tokenIsCurrency1_,
address referenceAsset_,
address quoteFeed_,
uint32 twapWindow_,
uint32 quoteMaxAge_,
string memory description_,
address owner_
) Ownable(owner_) {
if (address(poolManager_) == address(0) || token_ == address(0) || quoteFeed_ == address(0)) {
revert ZeroAddress();
}
if (twapWindow_ < MIN_TWAP_WINDOW || twapWindow_ > MAX_TWAP_WINDOW) {
revert TwapWindowOutOfRange(twapWindow_);
}
if (quoteMaxAge_ == 0 || quoteMaxAge_ > MAX_QUOTE_AGE) revert QuoteMaxAgeOutOfRange(quoteMaxAge_);
if (_isDerived(quoteFeed_)) revert QuoteFeedIsDerived(quoteFeed_);
poolManager = poolManager_;
poolId = poolId_;
token = token_;
tokenIsCurrency1 = tokenIsCurrency1_;
referenceAsset = referenceAsset_;
quoteFeed = quoteFeed_;
twapWindow = twapWindow_;
quoteMaxAge = quoteMaxAge_;
description = description_;
// Refuse a pool that does not exist: a zero sqrt price means nothing was ever initialised, and
// every later read would silently answer about a pool that is not there.
(uint160 sqrtPriceX96,) = _slot0();
if (sqrtPriceX96 == 0) revert PoolNotInitialised();
_record(); // seed the ring so the first window can begin closing immediately
}
/*//////////////////////////////////////////////////////////////
POOL STATE
//////////////////////////////////////////////////////////////*/
/// @dev v4 exposes no getters. Pool state hangs off `keccak256(poolId, POOLS_SLOT)` and `slot0` is
/// its first word, packed `sqrtPriceX96 | tick | protocolFee | lpFee` from the low bits up.
function _slot0() private view returns (uint160 sqrtPriceX96, int24 tick) {
bytes32 stateSlot = keccak256(abi.encodePacked(poolId, POOLS_SLOT));
bytes32 word = poolManager.extsload(stateSlot);
sqrtPriceX96 = uint160(uint256(word));
tick = int24(uint24(uint256(word) >> 160));
}
/// @notice The pool's current tick and sqrt price, unaveraged. For inspection, never for pricing.
function spotSlot0() external view returns (uint160 sqrtPriceX96, int24 tick) {
return _slot0();
}
/*//////////////////////////////////////////////////////////////
THE ACCUMULATOR
//////////////////////////////////////////////////////////////*/
/// @notice Fold the current tick into the running time-integral. Permissionless and idempotent
/// within a block.
///
/// @dev This is the contract's whole reason to exist: v4 keeps no history, so somebody has to.
/// Calling it more often narrows the gap between the window asked for and the window
/// actually covered; calling it never leaves the feed reporting nothing, which is safe.
function poke() public {
Observation storage last = _ring[index];
if (last.initialised && last.timestamp == uint32(block.timestamp)) return; // one per second is enough
_record();
}
function _record() private {
(, int24 tick) = _slot0();
Observation storage last = _ring[index];
int56 cumulative;
uint256 slot;
if (!last.initialised) {
cumulative = 0;
slot = 0;
} else {
uint32 elapsed = uint32(block.timestamp) - last.timestamp;
cumulative = last.tickCumulative + int56(tick) * int56(uint56(elapsed));
slot = (index + 1) % CARDINALITY;
}
_ring[slot] = Observation({ timestamp: uint32(block.timestamp), tickCumulative: cumulative, initialised: true });
index = slot;
if (written < CARDINALITY) written++;
emit Poked(slot, uint32(block.timestamp), tick, cumulative);
}
/// @notice The oldest observation still in the ring, and whether the ring holds anything at all.
function oldestObservation() public view returns (uint32 timestamp, int56 tickCumulative, bool ok) {
if (written == 0) return (0, 0, false);
uint256 slot = written < CARDINALITY ? 0 : (index + 1) % CARDINALITY;
Observation storage o = _ring[slot];
if (!o.initialised) return (0, 0, false);
return (o.timestamp, o.tickCumulative, true);
}
/// @notice Whether the ring covers the configured window, i.e. whether this feed can answer.
/// @dev {StockFeedRegistry.setFeed} calls this before accepting the feed, so a pool can only be
/// named as a source once it already spans the window it will be read under. On this venue
/// the ring starts empty and fills through {poke}, so a freshly deployed feed answers false
/// until it has been poked across the window.
function twapAvailable() public view returns (bool) {
(uint32 oldest,, bool ok) = oldestObservation();
if (!ok || written < 2) return false;
return block.timestamp - oldest >= twapWindow;
}
/// @inheritdoc IDerivedPoolFeed
function isDerivedPoolFeed() external pure returns (bool) {
return true;
}
/// @inheritdoc IDerivedPoolFeed
function describe() external view returns (IDerivedPoolFeed.Source memory) {
return IDerivedPoolFeed.Source({
venue: VENUE,
pool: address(poolManager), // a v4 pool has no address of its own; the singleton holds it
poolId: poolId,
token: token,
referenceAsset: referenceAsset,
referenceFeed: quoteFeed,
averagingWindow: twapWindow,
referenceMaxAge: quoteMaxAge
});
}
/// @dev The mean tick over `twapWindow`, interpolating the current tick up to now so the average
/// always ends at the present rather than at the last poke.
function _meanTick() private view returns (int24 mean, bool ok) {
if (!twapAvailable()) return (0, false);
Observation storage newest = _ring[index];
(, int24 tick) = _slot0();
// Extend the newest observation to now, so a stale ring does not report a stale average.
uint32 sinceNewest = uint32(block.timestamp) - newest.timestamp;
int56 cumNow = newest.tickCumulative + int56(tick) * int56(uint56(sinceNewest));
// Walk back to the first observation at least `twapWindow` old.
uint32 target = uint32(block.timestamp) - twapWindow;
int56 cumThen;
uint32 tThen;
bool found;
uint256 count = written < CARDINALITY ? written : CARDINALITY;
for (uint256 i = 0; i < count; ++i) {
uint256 slot = (index + CARDINALITY - i) % CARDINALITY;
Observation storage o = _ring[slot];
if (!o.initialised) continue;
if (o.timestamp <= target) {
cumThen = o.tickCumulative;
tThen = o.timestamp;
found = true;
break;
}
}
if (!found) return (0, false);
uint32 span = uint32(block.timestamp) - tThen;
if (span == 0) return (0, false);
int56 delta = cumNow - cumThen;
int56 avg = delta / int56(uint56(span));
if (delta < 0 && delta % int56(uint56(span)) != 0) avg--; // floor toward negative infinity
if (avg < TickMath.MIN_TICK || avg > TickMath.MAX_TICK) return (0, false);
return (int24(avg), true);
}
/// @notice The averaged tick, and whether it could be computed.
function twapTick() external view returns (int24 tick, bool ok) {
return _meanTick();
}
/*//////////////////////////////////////////////////////////////
PRICING
//////////////////////////////////////////////////////////////*/
/// @dev The pool price of one whole {token} in the other currency, from a sqrt price.
function _quoteAtSqrt(uint160 sqrtPriceX96, uint256 baseAmount) private view returns (uint256) {
if (sqrtPriceX96 <= type(uint128).max) {
uint256 ratioX192 = uint256(sqrtPriceX96) * uint256(sqrtPriceX96);
return tokenIsCurrency1
? FullMath.mulDiv(1 << 192, baseAmount, ratioX192)
: FullMath.mulDiv(ratioX192, baseAmount, 1 << 192);
}
uint256 ratioX128 = FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, 1 << 64);
return tokenIsCurrency1
? FullMath.mulDiv(1 << 128, baseAmount, ratioX128)
: FullMath.mulDiv(ratioX128, baseAmount, 1 << 128);
}
/// @dev The quote leg, read defensively: a bounded staticcall with a return-bomb guard, because
/// this address is owner-settable and therefore the mutable half of the feed.
///
/// The guard is {_staticcallWords}, not `(bool, bytes memory)`. The high-level form copies the
/// callee's ENTIRE returndata into our memory and charges US for it, outside the gas cap —
/// which only bounds the callee. Copying a fixed five words makes the cost of a read constant
/// no matter what the feed returns, so a hostile quote aggregator cannot make every consumer
/// of this feed pay for its memory expansion. It is what lets an unusable source read as "no
/// price" at a bounded cost.
function _quote() private view returns (uint256 price, uint256 updatedAt, bool fresh) {
// 5 static words: roundId, answer, startedAt, updatedAt, answeredInRound.
(bool ok, bytes32[5] memory words) =
_staticcallWords(quoteFeed, abi.encodeCall(IChainlinkQuote.latestRoundData, ()), 5);
if (!ok) return (0, 0, false);
int256 answer = int256(uint256(words[1]));
uint256 ts = uint256(words[3]);
if (answer <= 0 || ts == 0) return (0, 0, false);
// A hostile reference could answer just under 2^255, which would reach the mulDiv in {_usd} and
// revert the whole read; the ceiling turns that into "no price". It is generous in economic
// terms - 1e36 is 10^28 dollars per whole unit at this feed's 1e8 scale - so it catches only a
// broken or hostile source.
if (uint256(answer) > MAX_QUOTE_ANSWER) return (0, ts, false);
if (block.timestamp > ts && block.timestamp - ts > quoteMaxAge) return (0, ts, false);
// forge-lint: disable-next-line(unsafe-typecast) — `answer <= 0` returned above, so this is positive
return (uint256(answer), ts, true);
}
/// @dev The reference feed's `decimals()`, read under the same gas cap and return-bomb guard as its
/// answer. A feed that reverts, is not a contract, or answers short reads as this feed's own
/// scale of 8 rather than reverting — the same fallback v3 and the registry use. Read as a raw
/// word rather than a narrow decode, because a value overflowing `uint8` must not make the call
/// revert either; {MAX_QUOTE_DECIMALS} catches anything absurd downstream.
function _quoteDecimals() private view returns (uint8) {
(bool ok, bytes32[5] memory words) =
_staticcallWords(quoteFeed, abi.encodeCall(IChainlinkQuote.decimals, ()), 1);
if (!ok) return DECIMALS;
uint256 dec = uint256(words[0]);
if (dec > type(uint8).max) return type(uint8).max; // refused by the MAX_QUOTE_DECIMALS guard
// forge-lint: disable-next-line(unsafe-typecast) — bounded by the check above
return uint8(dec);
}
/// @dev Whether `feed` identifies itself as pool-derived, which is what enforces the one-hop rule.
/// A call that reverts, has no code, or answers short reads as a direct feed — the permissive
/// direction, where every real Chainlink aggregator lands.
function _isDerived(address feed) private view returns (bool) {
(bool ok, bytes32[5] memory words) =
_staticcallWords(feed, abi.encodeCall(IDerivedPoolFeed.isDerivedPoolFeed, ()), 1);
return ok && words[0] != bytes32(0);
}
/// @dev Gas-capped `staticcall` copying AT MOST `wordCount` words of returndata, so the cost of one
/// outward read is constant regardless of what the callee returns.
/// @return ok false if the call reverted OR returned fewer than `wordCount` words.
/// @return words the first `wordCount` words of returndata; trailing entries are zero.
function _staticcallWords(address target, bytes memory payload, uint256 wordCount)
private
view
returns (bool ok, bytes32[5] memory words)
{
// The destination is a FIXED bytes32[5]. Every call site passes a literal 1 or 5, but a 6 would
// make `returndatacopy` write past the array and corrupt whatever memory followed. Guarding here
// costs a few gas and removes the whole class.
if (wordCount > 5) return (false, words);
uint256 gasLimit = QUOTE_GAS_LIMIT;
uint256 wanted = wordCount * 32;
assembly ("memory-safe") {
let success := staticcall(gasLimit, target, add(payload, 0x20), mload(payload), 0x00, 0x00)
if and(success, iszero(lt(returndatasize(), wanted))) {
returndatacopy(words, 0x00, wanted)
ok := 1
}
}
}
/// @notice The quote leg's own reading, for inspection.
function quoteUsd() external view returns (uint256 price, uint256 updatedAt, bool fresh) {
return _quote();
}
/// @dev USD per whole token, scaled to {DECIMALS}. Zero whenever the answer would be unsound.
function _usd() private view returns (uint256 usd, uint256 quoteUpdatedAt) {
(uint256 q, uint256 ts, bool fresh) = _quote();
if (!fresh || q == 0) return (0, 0);
(int24 tick, bool ok) = _meanTick();
if (!ok) return (0, 0); // NO SPOT FALLBACK — see the contract docblock
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(tick);
uint256 inQuoteCurrency = _quoteAtSqrt(sqrtPriceX96, 1e18); // wei of ETH per whole token
// The reference leg is owner-settable and therefore the mutable, least-trusted half of this feed.
// Its decimals are read under the same gas cap and return-bomb guard as its answer, and bounded
// before they are used as an exponent: `10 ** (qd - DECIMALS)` overflows above 77, and a feed
// reporting an absurd scale yields no price and leaves the read working.
uint8 qd = _quoteDecimals();
if (qd > MAX_QUOTE_DECIMALS) return (0, 0);
// usd = ethPerToken * ethUsd, renormalised from (1e18 * 10^qd) to 10^DECIMALS
uint256 scaled = FullMath.mulDiv(inQuoteCurrency, q, 1e18);
if (qd >= DECIMALS) return (scaled / (10 ** (qd - DECIMALS)), ts);
return (scaled * (10 ** (DECIMALS - qd)), ts);
}
/// @notice USD value of `amount` of the token, scaled to {DECIMALS}. Zero when unpriceable.
function usdValueOf(uint256 amount) external view returns (uint256) {
(uint256 usd,) = _usd();
if (usd == 0 || amount == 0) return 0;
return FullMath.mulDiv(usd, amount, 1e18);
}
/*//////////////////////////////////////////////////////////////
AGGREGATOR V3 SURFACE
//////////////////////////////////////////////////////////////*/
function decimals() external pure returns (uint8) {
return DECIMALS;
}
function version() external pure returns (uint256) {
return VERSION;
}
function latestRoundData()
public
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
{
(uint256 usd, uint256 ts) = _usd();
if (usd == 0) return (1, 0, 0, 0, 1);
return (1, int256(usd), ts, ts, 1);
}
/// @dev A derived feed has one reading; every round id reports it. No consumer walks history here.
function getRoundData(uint80) external view returns (uint80, int256, uint256, uint256, uint80) {
return latestRoundData();
}
function latestAnswer() external view returns (int256 answer) {
(, answer,,,) = latestRoundData();
}
function latestTimestamp() external view returns (uint256 ts) {
(,,, ts,) = latestRoundData();
}
function latestRound() external pure returns (uint256) {
return 1;
}
function getAnswer(uint256) external view returns (int256 answer) {
(, answer,,,) = latestRoundData();
}
function getTimestamp(uint256) external view returns (uint256 ts) {
(,,, ts,) = latestRoundData();
}
/*//////////////////////////////////////////////////////////////
CURATION
//////////////////////////////////////////////////////////////*/
function setTwapWindow(uint32 window) external onlyOwner {
if (window < MIN_TWAP_WINDOW || window > MAX_TWAP_WINDOW) revert TwapWindowOutOfRange(window);
twapWindow = window;
emit TwapWindowSet(window);
}
/// @dev EXACTLY ONE POOL HOP, and a staleness window that is bounded and never zero. The reference
/// leg is priced by a direct feed: a feed carrying the {IDerivedPoolFeed} marker is refused
/// here, and {UniV3UsdAggregator._setQuoteFeed} applies the same constraint on that venue.
function setQuoteFeed(address feed, uint32 maxAge) external onlyOwner {
if (feed == address(0)) revert ZeroAddress();
if (maxAge == 0 || maxAge > MAX_QUOTE_AGE) revert QuoteMaxAgeOutOfRange(maxAge);
if (_isDerived(feed)) revert QuoteFeedIsDerived(feed);
quoteFeed = feed;
quoteMaxAge = maxAge;
emit QuoteFeedSet(feed, maxAge);
}
function setDescription(string calldata description_) external onlyOwner {
description = description_;
emit DescriptionSet(description_);
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "poolManager_",
"type": "address",
"internalType": "contract IExtsload"
},
{
"name": "poolId_",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "token_",
"type": "address",
"internalType": "address"
},
{
"name": "tokenIsCurrency1_",
"type": "bool",
"internalType": "bool"
},
{
"name": "referenceAsset_",
"type": "address",
"internalType": "address"
},
{
"name": "quoteFeed_",
"type": "address",
"internalType": "address"
},
{
"name": "twapWindow_",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "quoteMaxAge_",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "description_",
"type": "string",
"internalType": "string"
},
{
"name": "owner_",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "nonpayable"
},
{
"name": "OwnableInvalidOwner",
"type": "error",
"inputs": [
{
"name": "owner",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "OwnableUnauthorizedAccount",
"type": "error",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "PoolNotInitialised",
"type": "error",
"inputs": []
},
{
"name": "QuoteFeedIsDerived",
"type": "error",
"inputs": [
{
"name": "quoteFeed",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "QuoteMaxAgeOutOfRange",
"type": "error",
"inputs": [
{
"name": "maxAge",
"type": "uint32",
"internalType": "uint32"
}
]
},
{
"name": "TwapWindowOutOfRange",
"type": "error",
"inputs": [
{
"name": "window",
"type": "uint32",
"internalType": "uint32"
}
]
},
{
"name": "ZeroAddress",
"type": "error",
"inputs": []
},
{
"name": "DescriptionSet",
"type": "event",
"inputs": [
{
"name": "description",
"type": "string",
"indexed": false,
"internalType": "string"
}
],
"anonymous": false
},
{
"name": "OwnershipTransferred",
"type": "event",
"inputs": [
{
"name": "previousOwner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newOwner",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "Poked",
"type": "event",
"inputs": [
{
"name": "slot",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "timestamp",
"type": "uint32",
"indexed": false,
"internalType": "uint32"
},
{
"name": "tick",
"type": "int24",
"indexed": false,
"internalType": "int24"
},
{
"name": "tickCumulative",
"type": "int56",
"indexed": false,
"internalType": "int56"
}
],
"anonymous": false
},
{
"name": "QuoteFeedSet",
"type": "event",
"inputs": [
{
"name": "feed",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "maxAge",
"type": "uint32",
"indexed": false,
"internalType": "uint32"
}
],
"anonymous": false
},
{
"name": "TwapWindowSet",
"type": "event",
"inputs": [
{
"name": "window",
"type": "uint32",
"indexed": false,
"internalType": "uint32"
}
],
"anonymous": false
},
{
"name": "CARDINALITY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "DECIMALS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "MAX_QUOTE_AGE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "MAX_QUOTE_ANSWER",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "MAX_QUOTE_DECIMALS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "MAX_TWAP_WINDOW",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "MIN_TWAP_WINDOW",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "VENUE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"name": "VERSION",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "decimals",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "pure"
},
{
"name": "describe",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "venue",
"type": "string",
"internalType": "string"
},
{
"name": "pool",
"type": "address",
"internalType": "address"
},
{
"name": "poolId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "referenceAsset",
"type": "address",
"internalType": "address"
},
{
"name": "referenceFeed",
"type": "address",
"internalType": "address"
},
{
"name": "averagingWindow",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "referenceMaxAge",
"type": "uint32",
"internalType": "uint32"
}
],
"internalType": "struct IDerivedPoolFeed.Source"
}
],
"stateMutability": "view"
},
{
"name": "description",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"name": "getAnswer",
"type": "function",
"inputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "answer",
"type": "int256",
"internalType": "int256"
}
],
"stateMutability": "view"
},
{
"name": "getRoundData",
"type": "function",
"inputs": [
{
"name": "",
"type": "uint80",
"internalType": "uint80"
}
],
"outputs": [
{
"name": "",
"type": "uint80",
"internalType": "uint80"
},
{
"name": "",
"type": "int256",
"internalType": "int256"
},
{
"name": "",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "",
"type": "uint80",
"internalType": "uint80"
}
],
"stateMutability": "view"
},
{
"name": "getTimestamp",
"type": "function",
"inputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "ts",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "index",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "isDerivedPoolFeed",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "pure"
},
{
"name": "latestAnswer",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "answer",
"type": "int256",
"internalType": "int256"
}
],
"stateMutability": "view"
},
{
"name": "latestRound",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "pure"
},
{
"name": "latestRoundData",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "roundId",
"type": "uint80",
"internalType": "uint80"
},
{
"name": "answer",
"type": "int256",
"internalType": "int256"
},
{
"name": "startedAt",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "updatedAt",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "answeredInRound",
"type": "uint80",
"internalType": "uint80"
}
],
"stateMutability": "view"
},
{
"name": "latestTimestamp",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "ts",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "oldestObservation",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "timestamp",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "tickCumulative",
"type": "int56",
"internalType": "int56"
},
{
"name": "ok",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "owner",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "poke",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "poolId",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "poolManager",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IExtsload"
}
],
"stateMutability": "view"
},
{
"name": "quoteFeed",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "quoteMaxAge",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "quoteUsd",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "price",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "updatedAt",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "fresh",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "referenceAsset",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "renounceOwnership",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setDescription",
"type": "function",
"inputs": [
{
"name": "description_",
"type": "string",
"internalType": "string"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setQuoteFeed",
"type": "function",
"inputs": [
{
"name": "feed",
"type": "address",
"internalType": "address"
},
{
"name": "maxAge",
"type": "uint32",
"internalType": "uint32"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setTwapWindow",
"type": "function",
"inputs": [
{
"name": "window",
"type": "uint32",
"internalType": "uint32"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "spotSlot0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "sqrtPriceX96",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "tick",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "token",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "tokenIsCurrency1",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "transferOwnership",
"type": "function",
"inputs": [
{
"name": "newOwner",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "twapAvailable",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "twapTick",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "tick",
"type": "int24",
"internalType": "int24"
},
{
"name": "ok",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "twapWindow",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "usdValueOf",
"type": "function",
"inputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "version",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "pure"
},
{
"name": "written",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
}
]0x61012080604052346106be5761269c803803809161001d82856106c2565b8339810190610140818303126106be5780516001600160a01b03811691908281036106be57602082015191610054604082016106e5565b606082015180151581036106be5761006e608084016106e5565b9161007b60a085016106e5565b9561008860c086016106f9565b61009460e087016106f9565b6101008701519096906001600160401b0381116106be5781019a80601f8d0112156106be578b519b6001600160401b038d1161048a576040519c91828e6100e5601f8301601f1916602001826106c2565b52602083830101116106be57815f928e60208080950191015e8d0101526001600160a01b039061011890610120016106e5565b169889156106ab575f80546001600160a01b031981168c1782556040519b916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a315801561069a575b8015610689575b61067a5763ffffffff1695603c8710801561066f575b61065c5763ffffffff861680158015610650575b61063e575063476615a360e11b60208a0190815260048a52986101c46024826106c2565b5f905f8060a09c8d93604051946101db81876106c2565b36863751908d62030d40fa60203d10151661062f575b81610624575b5061060657608052875260c05260e05261010052604380546001600160e01b03191660409490941b600160401b600160e01b0316939093179190911760209190911b67ffffffff000000001617905581516001600160401b03811161048a57604454600181811c911680156105fc575b60208210146105e857601f8111610585575b50602092601f821160011461052457928192935f92610519575b50508160011b915f199060031b1c1916176044555b6102b061070a565b506001600160a01b03161561050a576102c761070a565b6041549150604082101561047657816001015460ff8160581c16155f1461049e57505f9150815b6040514263ffffffff169190606081016001600160401b0381118282101761048a57604052828152602081019160060b9182815260408201906001825260408710156104765763ffffffff8760010193511663ffffffff1984541617835551906affffffffffffff000000006bff000000000000000000000084549251151560581b169260201b1690640100000000600160601b031916171790558360415560425460408110610447575b50906060917f4e18d86f11b46296fa0a4b8dba7976034805a0fbb256112d013836a4cf93939b9360405192835260020b60208301526040820152a2604051611edb91826107c1833960805182818161038101528181610b8e0152611cc5015251818181610a5e01528181610bb70152611c6d015260c0518181816102890152610be5015260e0518181816109ed01528181611dc50152611e190152610100518181816103c50152610c140152f35b91905f19831461046257600192909201604255906060610399565b634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b63ffffffff811663ffffffff42160363ffffffff81116104625763ffffffff1660060b8260020b02908160060b9182036104625760201c60060b01667fffffffffffff8113667fffffffffffff19821217610462579160018101811161046257600160409108916102ee565b630c20991b60e01b5f5260045ffd5b015190505f80610293565b601f1982169360445f52805f20915f5b86811061056d5750836001959610610555575b505050811b016044556102a8565b01515f1960f88460031b161c191690555f8080610547565b91926020600181928685015181550194019201610534565b60445f527f9b22d3d61959b4d3528b1d8ba932c96fbe302b36a1aad1d95cab54f9e0a135ea601f830160051c810191602084106105de575b601f0160051c01905b8181106105d35750610279565b5f81556001016105c6565b90915081906105bd565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610267565b632d5e8b0360e01b5f9081526001600160a01b038916600452602490fd5b90505115155f6101f7565b905060205f823e6001906101f1565b6312573f1f60e01b5f5260045260245ffd5b5062093a8081116101a0565b86630a21ce3360e01b5f5260045260245ffd5b5061a8c0871161018c565b63d92e233d60e01b5f5260045ffd5b506001600160a01b03881615610176565b506001600160a01b0383161561016f565b631e4fbdf760e01b5f525f60045260245ffd5b5f80fd5b601f909101601f19168101906001600160401b0382119082101761048a57604052565b51906001600160a01b03821682036106be57565b519063ffffffff821682036106be57565b60a05160405160208101918252600660408201526040815261072d6060826106c2565b51902090602060018060a01b036080511692602460405180958193631e2eaeaf60e01b835260048301525afa9182156107b5575f92610781575b506001600160a01b0382169160a01c62ffffff1660020b90565b9091506020813d6020116107ad575b8161079d602093836106c2565b810103126106be5751905f610767565b3d9150610790565b6040513d5f823e3d90fdfe60806040526004361015610011575f80fd5b5f3560e01c80630743a94f14610d475780630e87eecd14610d1e57806316c2d30f14610cf85780631817835814610cde5780631a65893b14610cc35780631ad184ff14610b155780631b1043c814610af85780631d60740414610ad45780632986c0e514610ab75780632e0f262514610a9c578063313ce56714610a9c5780633a871e7814610a815780633e0dc34e14610a4757806350d25bcd14610a2d57806352fe308714610a1257806354fd4d50146101fd5780635cc14051146109d65780635f55354514610944578063668a0f0214610726578063680a00131461090c578063715018a6146108b55780637284e416146107fe57806376d8eabb146107cf5780638107e133146107ac5780638205bf6a1461079257806389a71afe146107685780638da5cb5b146107415780638ecc2b461461072657806390c3f38f146105315780639a6fc8f5146105005780639f7b1ebc146104d5578063a47b3289146104b8578063b4ba3bd314610485578063b5ab58dc1461045d578063b633620c14610435578063b88a92b414610419578063d45690ed146103f4578063d5c05833146103b0578063dc4c90d31461036c578063e79f54661461033d578063f2fde38b146102b8578063fc0c546a14610274578063feaf968c1461021c5763ffa1ad74146101fd575f80fd5b34610218575f36600319011261021857602060405160048152f35b5f80fd5b34610218575f36600319011261021857610270610237611239565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015290819060a0820190565b0390f35b34610218575f366003190112610218576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610218576020366003190112610218576102d1610e84565b6102d9611263565b6001600160a01b0316801561032a575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b34610218575f36600319011261021857610270610358610f49565b604051918291602083526020830190610e9a565b34610218575f366003190112610218576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610218575f366003190112610218576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610218575f36600319011261021857602063ffffffff604354821c16604051908152f35b34610218575f36600319011261021857602060405161a8c08152f35b34610218576020366003190112610218576020610450611239565b5092505050604051908152f35b34610218576020366003190112610218576020610478611239565b5050509050604051908152f35b34610218575f36600319011261021857604061049f611c63565b82516001600160a01b03909216825260020b6020820152f35b34610218575f366003190112610218576020604254604051908152f35b34610218575f3660031901126102185760406104ef611a60565b82519160020b825215156020820152f35b346102185760203660031901126102185760043569ffffffffffffffffffff81160361021857610270610237611239565b346102185760203660031901126102185760043567ffffffffffffffff8111610218573660238201121561021857806004013567ffffffffffffffff811161021857366024828401011161021857610587611263565b610592604454610ebe565b601f81116106be575b505f601f8211600114610624577f3e901d580d416311e4d68918afffe82b58f06885f6fcf1b2d3b34b35b238ef5f92826024936040935f91610617575b508160011b905f198360031b1c1916176044555b8083519485936020855282602086015201848401375f828201840152601f01601f19168101030190a1005b85915083010135866105d8565b601f1982169060445f525f80516020611ebb833981519152915f5b8181106106a35750926040927f3e901d580d416311e4d68918afffe82b58f06885f6fcf1b2d3b34b35b238ef5f95928260249610610688575b5050600181811b016044556105ec565b83018501355f19600384901b60f8161c191690558580610678565b91926020600181926024878a0101358155019401920161063f565b60445f52601f820160051c5f80516020611ebb833981519152019060208310610711575b601f0160051c5f80516020611ebb83398151915201905b818110610706575061059b565b5f81556001016106f9565b5f80516020611ebb83398151915291506106e2565b34610218575f36600319011261021857602060405160018152f35b34610218575f366003190112610218575f546040516001600160a01b039091168152602090f35b34610218575f366003190112610218576043546040805191901c6001600160a01b03168152602090f35b34610218575f366003190112610218576020610450611239565b34610218575f36600319011261021857602063ffffffff60435416604051908152f35b34610218575f3660031901126102185760606107e9611960565b90604051928352602083015215156040820152f35b34610218575f366003190112610218576040515f60445461081e81610ebe565b80845290600181169081156108915750600114610846575b6102708361035881850382610f27565b91905060445f525f80516020611ebb833981519152915f905b80821061087757509091508101602001610358610836565b91926001816020925483858801015201910190929161085f565b60ff191660208086019190915291151560051b840190910191506103589050610836565b34610218575f366003190112610218576108cd611263565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610218575f3660031901126102185760606109266111ce565b9063ffffffff6040519316835260060b602083015215156040820152f35b346102185760203660031901126102185760043563ffffffff81168091036102185761096e611263565b603c811080156109cb575b6109b9576020817f50ad13511560ceaf2921a810deb090b81467b3aff0405f679c6dd07acee9131c9263ffffffff196043541617604355604051908152a1005b630a21ce3360e01b5f5260045260245ffd5b5061a8c08111610979565b34610218575f3660031901126102185760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b34610218575f36600319011261021857602060405160408152f35b34610218575f366003190112610218576020610478611239565b34610218575f3660031901126102185760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610218575f36600319011261021857602060405160248152f35b34610218575f36600319011261021857602060405160088152f35b34610218575f366003190112610218576020604154604051908152f35b34610218575f366003190112610218576020610aee611189565b6040519015158152f35b34610218575f36600319011261021857602060405162093a808152f35b34610218575f366003190112610218575f60e0604051610b3481610ef6565b606081528260208201528260408201528260608201528260808201528260a08201528260c08201520152610c7d610b69610f49565b60435460405191610b7983610ef6565b825263ffffffff602083019160018060a01b037f000000000000000000000000000000000000000000000000000000000000000016835281604085017f000000000000000000000000000000000000000000000000000000000000000081526060860160018060a01b037f00000000000000000000000000000000000000000000000000000000000000001681526080870160018060a01b037f000000000000000000000000000000000000000000000000000000000000000016815260a088019160018060a01b038660401c16835260c089019385871685528560e08b019760201c1687526040519a8b9a60208c525161010060208d01526101208c0190610e9a565b98516001600160a01b0390811660408c0152905160608b01529051811660808a01529051811660a089015290511660c0870152511660e085015251166101008301520390f35b34610218575f366003190112610218576020604051603c8152f35b34610218575f36600319011261021857610cf6610fb1565b005b34610218576020366003190112610218576020610d16600435610f80565b604051908152f35b34610218575f3660031901126102185760206040516ec097ce7bc90715b34b9f10000000008152f35b3461021857604036600319011261021857610d60610e84565b6024359063ffffffff82169081830361021857610d7b611263565b6001600160a01b038116928315610e755782158015610e69575b610e565760405163476615a360e11b602082015260048152610dc290610dbc602482610f27565b83611d56565b81610e4b575b50610e385760438054640100000000600160e01b031916604093841b68010000000000000000600160e01b031617602092831b67ffffffff000000001617905581519384528301919091527fff338b1add4c3ddf947a9c8fc00a3ddf31e5f9c6b55ffac69b4e074c439e617b91a1005b83632d5e8b0360e01b5f5260045260245ffd5b905051151585610dc8565b826312573f1f60e01b5f5260045260245ffd5b5062093a808311610d95565b63d92e233d60e01b5f5260045ffd5b600435906001600160a01b038216820361021857565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b90600182811c92168015610eec575b6020831014610ed857565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610ecd565b610100810190811067ffffffffffffffff821117610f1357604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff821117610f1357604052565b604051906040820182811067ffffffffffffffff821117610f1357604052600a8252691d5b9a5cddd85c0b5d8d60b21b6020830152565b610f886112ad565b509081158015610fa9575b610fa357610fa0916116a8565b90565b50505f90565b508015610f93565b60415460408110156111075780600101805460ff8160581c169081611169575b5061116557610fde611c63565b9190505460ff8160581c16155f1461111b57505f9150815b63ffffffff4216906040516060810181811067ffffffffffffffff821117610f1357604052828152602081019160060b9182815260408201906001825260408710156111075763ffffffff8760010193511663ffffffff1984541617835551906affffffffffffff0000000083549160ff60581b9051151560581b169260201b16906bffffffffffffffff0000000019161717905583604155604254604081106110d8575b50906060917f4e18d86f11b46296fa0a4b8dba7976034805a0fbb256112d013836a4cf93939b9360405192835260020b60208301526040820152a2565b91905f1983146110f35760019290920160425590606061109b565b634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b8061114263ffffffff6111358161114e9516824216611909565b1660060b8460020b611923565b9060201c60060b61193a565b916001810181116110f35760016040910891610ff6565b5050565b905063ffffffff8042169116145f610fd1565b919082039182116110f357565b6111916111ce565b90501580156111c2575b6111bd5763ffffffff6111af91164261117c565b63ffffffff60435416111590565b505f90565b5060026042541061119b565b60425480156112305760401115611218575f5b604081101561110757600101549060ff8260581c161561120f5763ffffffff82169160201c60060b90600190565b5f915081908190565b6041546001810181116110f3576001604091086111e1565b505f905f905f90565b6112416112ad565b8192911561125457600192918190600190565b50600191505f90819081908490565b5f546001600160a01b0316330361127657565b63118cdaa760e01b5f523360045260245ffd5b60ff16604d81116110f357600a0a90565b818102929181159184041417156110f357565b6112b5611960565b929190921580156116a0575b611698576112cd611a60565b1561168e5760020b8060ff1d8181011890620d89e8821161167c576113da9163ffffffff91600160801b7001fffcb933bd6fad37aa2d162d1a5940016001841602189160028116611660575b60048116611644575b60088116611628575b6010811661160c575b602081166115f0575b604081166115d4575b608081166115b8575b610100811661159c575b6102008116611580575b6104008116611564575b6108008116611548575b611000811661152c575b6120008116611510575b61400081166114f4575b61800081166114d8575b6201000081166114bc575b6202000081166114a1575b620400008116611486575b620800001661146d575b5f12611465575b0160201c611d98565b9060ff6113e5611e61565b16916024831161145a57906113f9916116a8565b906008811015611425576008039060ff82116110f35761141b61142192611289565b9061129a565b9190565b6007190160ff81116110f35761143a90611289565b90811561144657049190565b634e487b7160e01b5f52601260045260245ffd5b50505090505f905f90565b5f19046113d1565b6b048a170391f7dc42444e8fa290910260801c906113ca565b6d2216e584f5fa1ea926041bedfe9890920260801c916113c0565b916e5d6af8dedb81196699c329225ee6040260801c916113b5565b916f09aa508b5b7a84e1c677de54f3e99bc90260801c916113aa565b916f31be135f97d08fd981231505542fcfa60260801c9161139f565b916f70d869a156d2a1b890bb3df62baf32f70260801c91611395565b916fa9f746462d870fdf8a65dc1f90e061e50260801c9161138b565b916fd097f3bdfd2022b8845ad8f792aa58250260801c91611381565b916fe7159475a2c29b7443b29c7fa6e889d90260801c91611377565b916ff3392b0822b70005940c7a398e4b70f30260801c9161136d565b916ff987a7253ac413176f2b074cf7815e540260801c91611363565b916ffcbe86c7900a88aedcffc83b479aa3a40260801c91611359565b916ffe5dee046a99a2a811c461f1969c30530260801c9161134f565b916fff2ea16466c96a3843ec78b326b528610260801c91611346565b916fff973b41fa98c081472e6896dfb254c00260801c9161133d565b916fffcb9843d60f6159c9db58835c9266440260801c91611334565b916fffe5caca7e10e4e61c3624eaa0941cd00260801c9161132b565b916ffff2e50f5f656932ef12357cf3c7fdcc0260801c91611322565b916ffff97272373d413259a46990580e213a0260801c91611319565b6345c3193d60e11b5f5260045260245ffd5b505090505f905f90565b505f91508190565b5080156112c1565b808202905f1983820990828083109203918083039283670de0b6b3a764000011156102185714611712577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066993670de0b6b3a7640000910990828211900360ee1b910360121c170290565b5050670de0b6b3a764000091500490565b81810291905f1982820991838084109303928084039384600160c01b1115610218571461176357600160c01b910990828211900360401b910360c01c1790565b50505060c01c90565b9060c082901b905f1983600160c01b099282808510940393808503948584111561021857146117ee578190600160c01b0981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b5091500490565b81810291905f1982820991838084109303928084039384600160401b1115610218571461183557600160401b910990828211900360c01b910360401c1790565b50505060401c90565b81810291905f1982820991838084109303928084039384600160801b1115610218571461187e57600160801b910990828211900360801b910360801c1790565b50505060801c90565b90608082901b905f1983600160801b099282808510940393808503948584111561021857146117ee578190600160801b0981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b9063ffffffff8091169116039063ffffffff82116110f357565b9060060b9060060b02908160060b9182036110f357565b9060060b9060060b0190667fffffffffffff198212667fffffffffffff8313176110f357565b6043549060405160208101633fabe5a360e21b815260048252611984602483610f27565b5f905f8060a092604051956119998588610f27565b843688375190604089901c6001600160a01b031662030d40fa813d101516611a53575b5015611a495760606020820151910151925f8213801590611a41575b611a36576ec097ce7bc90715b34b9f10000000008211611a2d578342119081611a10575b50611a08579190600190565b505f91905f90565b905063ffffffff611a21854261117c565b9160201c16105f6119fc565b50505f91905f90565b505f92508291829150565b5083156119d8565b505f915081908190565b90505f823e60015f6119bc565b611a68611189565b15611c5d57604154604081101561110757611a81611c63565b9050611ab563ffffffff42169161114284600101549163ffffffff611aa881851687611909565b1660060b9060020b611923565b90611ac863ffffffff6043541682611909565b905f935f925f91604254604081105f14611c535791905b63ffffffff5f92169160408201809211905b848110611be4575b505050505015611bda5763ffffffff91611b1291611909565b16918215611bd15760060b9060060b0390667fffffffffffff8213667fffffffffffff198312176110f35760060b9060060b811561144657667fffffffffffff1981145f198314166110f357818105915f82129182611bc2575b5050611ba8575b8060060b620d89e7198112908115611b9b575b50611b945760020b90600190565b505f905f90565b620d89e89150135f611b86565b60060b667fffffffffffff1981146110f3575f1901611b73565b0760060b151590505f80611b6c565b5050505f905f90565b505050505f905f90565b816110f357603f611bf5828561117c565b166040811015611107576001015460ff8160581c1615611c4a5763ffffffff81169085821115611c2b5750506001905b01611af1565b979850995050505050505060201c60060b929060015f80808080611af9565b50600190611c25565b5060409190611adf565b5f905f90565b60405160208101907f000000000000000000000000000000000000000000000000000000000000000082526006604082015260408152611ca4606082610f27565b519020604051631e2eaeaf60e01b81526004810191909152906020826024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa918215611d4b575f92611d17575b506001600160a01b0382169160a01c62ffffff1660020b90565b9091506020813d602011611d43575b81611d3360209383610f27565b810103126102185751905f611cfd565b3d9150611d26565b6040513d5f823e3d90fd5b90915f925f8060405192611d6b60a085610f27565b60a036853783956020825192019062030d40fa60203d101516611d8b5750565b60209193505f903e600191565b6001600160a01b03166fffffffffffffffffffffffffffffffff811115611e0d5780611dc3916117f5565b7f000000000000000000000000000000000000000000000000000000000000000015611dfb57610fa090670de0b6b3a7640000611887565b670de0b6b3a7640000610fa09161183e565b80611e179161129a565b7f000000000000000000000000000000000000000000000000000000000000000015611e4f57610fa090670de0b6b3a764000061176c565b670de0b6b3a7640000610fa091611723565b6043546040805163313ce56760e01b602082015260048152611e999290911c6001600160a01b0316611e94602483610f27565b611d56565b9015611eb4575160ff8111611eae5760ff1690565b5060ff90565b5060089056fe9b22d3d61959b4d3528b1d8ba932c96fbe302b36a1aad1d95cab54f9e0a135ea0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516ad6aa41fed2528a76979a615e3c5f3e0ab494f5abc5e1c15362ad6151187a43000000000000000000000000e4b8723d202fdd0298b1d7496a86656b2986c5320000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078f3556b67e17df817d51ef5a990cdaf09e8d3a9000000000000000000000000000000000000000000000000000000000000012c00000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000000000000000140000000000000000000000000e5c73d368f0210131c48ad3ebb062b7011b4a9d60000000000000000000000000000000000000000000000000000000000000009524950202f205553440000000000000000000000000000000000000000000000
0x60806040526004361015610011575f80fd5b5f3560e01c80630743a94f14610d475780630e87eecd14610d1e57806316c2d30f14610cf85780631817835814610cde5780631a65893b14610cc35780631ad184ff14610b155780631b1043c814610af85780631d60740414610ad45780632986c0e514610ab75780632e0f262514610a9c578063313ce56714610a9c5780633a871e7814610a815780633e0dc34e14610a4757806350d25bcd14610a2d57806352fe308714610a1257806354fd4d50146101fd5780635cc14051146109d65780635f55354514610944578063668a0f0214610726578063680a00131461090c578063715018a6146108b55780637284e416146107fe57806376d8eabb146107cf5780638107e133146107ac5780638205bf6a1461079257806389a71afe146107685780638da5cb5b146107415780638ecc2b461461072657806390c3f38f146105315780639a6fc8f5146105005780639f7b1ebc146104d5578063a47b3289146104b8578063b4ba3bd314610485578063b5ab58dc1461045d578063b633620c14610435578063b88a92b414610419578063d45690ed146103f4578063d5c05833146103b0578063dc4c90d31461036c578063e79f54661461033d578063f2fde38b146102b8578063fc0c546a14610274578063feaf968c1461021c5763ffa1ad74146101fd575f80fd5b34610218575f36600319011261021857602060405160048152f35b5f80fd5b34610218575f36600319011261021857610270610237611239565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015290819060a0820190565b0390f35b34610218575f366003190112610218576040517f000000000000000000000000e4b8723d202fdd0298b1d7496a86656b2986c5326001600160a01b03168152602090f35b34610218576020366003190112610218576102d1610e84565b6102d9611263565b6001600160a01b0316801561032a575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b34610218575f36600319011261021857610270610358610f49565b604051918291602083526020830190610e9a565b34610218575f366003190112610218576040517f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03168152602090f35b34610218575f366003190112610218576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610218575f36600319011261021857602063ffffffff604354821c16604051908152f35b34610218575f36600319011261021857602060405161a8c08152f35b34610218576020366003190112610218576020610450611239565b5092505050604051908152f35b34610218576020366003190112610218576020610478611239565b5050509050604051908152f35b34610218575f36600319011261021857604061049f611c63565b82516001600160a01b03909216825260020b6020820152f35b34610218575f366003190112610218576020604254604051908152f35b34610218575f3660031901126102185760406104ef611a60565b82519160020b825215156020820152f35b346102185760203660031901126102185760043569ffffffffffffffffffff81160361021857610270610237611239565b346102185760203660031901126102185760043567ffffffffffffffff8111610218573660238201121561021857806004013567ffffffffffffffff811161021857366024828401011161021857610587611263565b610592604454610ebe565b601f81116106be575b505f601f8211600114610624577f3e901d580d416311e4d68918afffe82b58f06885f6fcf1b2d3b34b35b238ef5f92826024936040935f91610617575b508160011b905f198360031b1c1916176044555b8083519485936020855282602086015201848401375f828201840152601f01601f19168101030190a1005b85915083010135866105d8565b601f1982169060445f525f80516020611ebb833981519152915f5b8181106106a35750926040927f3e901d580d416311e4d68918afffe82b58f06885f6fcf1b2d3b34b35b238ef5f95928260249610610688575b5050600181811b016044556105ec565b83018501355f19600384901b60f8161c191690558580610678565b91926020600181926024878a0101358155019401920161063f565b60445f52601f820160051c5f80516020611ebb833981519152019060208310610711575b601f0160051c5f80516020611ebb83398151915201905b818110610706575061059b565b5f81556001016106f9565b5f80516020611ebb83398151915291506106e2565b34610218575f36600319011261021857602060405160018152f35b34610218575f366003190112610218575f546040516001600160a01b039091168152602090f35b34610218575f366003190112610218576043546040805191901c6001600160a01b03168152602090f35b34610218575f366003190112610218576020610450611239565b34610218575f36600319011261021857602063ffffffff60435416604051908152f35b34610218575f3660031901126102185760606107e9611960565b90604051928352602083015215156040820152f35b34610218575f366003190112610218576040515f60445461081e81610ebe565b80845290600181169081156108915750600114610846575b6102708361035881850382610f27565b91905060445f525f80516020611ebb833981519152915f905b80821061087757509091508101602001610358610836565b91926001816020925483858801015201910190929161085f565b60ff191660208086019190915291151560051b840190910191506103589050610836565b34610218575f366003190112610218576108cd611263565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610218575f3660031901126102185760606109266111ce565b9063ffffffff6040519316835260060b602083015215156040820152f35b346102185760203660031901126102185760043563ffffffff81168091036102185761096e611263565b603c811080156109cb575b6109b9576020817f50ad13511560ceaf2921a810deb090b81467b3aff0405f679c6dd07acee9131c9263ffffffff196043541617604355604051908152a1005b630a21ce3360e01b5f5260045260245ffd5b5061a8c08111610979565b34610218575f3660031901126102185760206040517f000000000000000000000000000000000000000000000000000000000000000115158152f35b34610218575f36600319011261021857602060405160408152f35b34610218575f366003190112610218576020610478611239565b34610218575f3660031901126102185760206040517f6ad6aa41fed2528a76979a615e3c5f3e0ab494f5abc5e1c15362ad6151187a438152f35b34610218575f36600319011261021857602060405160248152f35b34610218575f36600319011261021857602060405160088152f35b34610218575f366003190112610218576020604154604051908152f35b34610218575f366003190112610218576020610aee611189565b6040519015158152f35b34610218575f36600319011261021857602060405162093a808152f35b34610218575f366003190112610218575f60e0604051610b3481610ef6565b606081528260208201528260408201528260608201528260808201528260a08201528260c08201520152610c7d610b69610f49565b60435460405191610b7983610ef6565b825263ffffffff602083019160018060a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116835281604085017f6ad6aa41fed2528a76979a615e3c5f3e0ab494f5abc5e1c15362ad6151187a4381526060860160018060a01b037f000000000000000000000000e4b8723d202fdd0298b1d7496a86656b2986c5321681526080870160018060a01b037f000000000000000000000000000000000000000000000000000000000000000016815260a088019160018060a01b038660401c16835260c089019385871685528560e08b019760201c1687526040519a8b9a60208c525161010060208d01526101208c0190610e9a565b98516001600160a01b0390811660408c0152905160608b01529051811660808a01529051811660a089015290511660c0870152511660e085015251166101008301520390f35b34610218575f366003190112610218576020604051603c8152f35b34610218575f36600319011261021857610cf6610fb1565b005b34610218576020366003190112610218576020610d16600435610f80565b604051908152f35b34610218575f3660031901126102185760206040516ec097ce7bc90715b34b9f10000000008152f35b3461021857604036600319011261021857610d60610e84565b6024359063ffffffff82169081830361021857610d7b611263565b6001600160a01b038116928315610e755782158015610e69575b610e565760405163476615a360e11b602082015260048152610dc290610dbc602482610f27565b83611d56565b81610e4b575b50610e385760438054640100000000600160e01b031916604093841b68010000000000000000600160e01b031617602092831b67ffffffff000000001617905581519384528301919091527fff338b1add4c3ddf947a9c8fc00a3ddf31e5f9c6b55ffac69b4e074c439e617b91a1005b83632d5e8b0360e01b5f5260045260245ffd5b905051151585610dc8565b826312573f1f60e01b5f5260045260245ffd5b5062093a808311610d95565b63d92e233d60e01b5f5260045ffd5b600435906001600160a01b038216820361021857565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b90600182811c92168015610eec575b6020831014610ed857565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610ecd565b610100810190811067ffffffffffffffff821117610f1357604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff821117610f1357604052565b604051906040820182811067ffffffffffffffff821117610f1357604052600a8252691d5b9a5cddd85c0b5d8d60b21b6020830152565b610f886112ad565b509081158015610fa9575b610fa357610fa0916116a8565b90565b50505f90565b508015610f93565b60415460408110156111075780600101805460ff8160581c169081611169575b5061116557610fde611c63565b9190505460ff8160581c16155f1461111b57505f9150815b63ffffffff4216906040516060810181811067ffffffffffffffff821117610f1357604052828152602081019160060b9182815260408201906001825260408710156111075763ffffffff8760010193511663ffffffff1984541617835551906affffffffffffff0000000083549160ff60581b9051151560581b169260201b16906bffffffffffffffff0000000019161717905583604155604254604081106110d8575b50906060917f4e18d86f11b46296fa0a4b8dba7976034805a0fbb256112d013836a4cf93939b9360405192835260020b60208301526040820152a2565b91905f1983146110f35760019290920160425590606061109b565b634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b8061114263ffffffff6111358161114e9516824216611909565b1660060b8460020b611923565b9060201c60060b61193a565b916001810181116110f35760016040910891610ff6565b5050565b905063ffffffff8042169116145f610fd1565b919082039182116110f357565b6111916111ce565b90501580156111c2575b6111bd5763ffffffff6111af91164261117c565b63ffffffff60435416111590565b505f90565b5060026042541061119b565b60425480156112305760401115611218575f5b604081101561110757600101549060ff8260581c161561120f5763ffffffff82169160201c60060b90600190565b5f915081908190565b6041546001810181116110f3576001604091086111e1565b505f905f905f90565b6112416112ad565b8192911561125457600192918190600190565b50600191505f90819081908490565b5f546001600160a01b0316330361127657565b63118cdaa760e01b5f523360045260245ffd5b60ff16604d81116110f357600a0a90565b818102929181159184041417156110f357565b6112b5611960565b929190921580156116a0575b611698576112cd611a60565b1561168e5760020b8060ff1d8181011890620d89e8821161167c576113da9163ffffffff91600160801b7001fffcb933bd6fad37aa2d162d1a5940016001841602189160028116611660575b60048116611644575b60088116611628575b6010811661160c575b602081166115f0575b604081166115d4575b608081166115b8575b610100811661159c575b6102008116611580575b6104008116611564575b6108008116611548575b611000811661152c575b6120008116611510575b61400081166114f4575b61800081166114d8575b6201000081166114bc575b6202000081166114a1575b620400008116611486575b620800001661146d575b5f12611465575b0160201c611d98565b9060ff6113e5611e61565b16916024831161145a57906113f9916116a8565b906008811015611425576008039060ff82116110f35761141b61142192611289565b9061129a565b9190565b6007190160ff81116110f35761143a90611289565b90811561144657049190565b634e487b7160e01b5f52601260045260245ffd5b50505090505f905f90565b5f19046113d1565b6b048a170391f7dc42444e8fa290910260801c906113ca565b6d2216e584f5fa1ea926041bedfe9890920260801c916113c0565b916e5d6af8dedb81196699c329225ee6040260801c916113b5565b916f09aa508b5b7a84e1c677de54f3e99bc90260801c916113aa565b916f31be135f97d08fd981231505542fcfa60260801c9161139f565b916f70d869a156d2a1b890bb3df62baf32f70260801c91611395565b916fa9f746462d870fdf8a65dc1f90e061e50260801c9161138b565b916fd097f3bdfd2022b8845ad8f792aa58250260801c91611381565b916fe7159475a2c29b7443b29c7fa6e889d90260801c91611377565b916ff3392b0822b70005940c7a398e4b70f30260801c9161136d565b916ff987a7253ac413176f2b074cf7815e540260801c91611363565b916ffcbe86c7900a88aedcffc83b479aa3a40260801c91611359565b916ffe5dee046a99a2a811c461f1969c30530260801c9161134f565b916fff2ea16466c96a3843ec78b326b528610260801c91611346565b916fff973b41fa98c081472e6896dfb254c00260801c9161133d565b916fffcb9843d60f6159c9db58835c9266440260801c91611334565b916fffe5caca7e10e4e61c3624eaa0941cd00260801c9161132b565b916ffff2e50f5f656932ef12357cf3c7fdcc0260801c91611322565b916ffff97272373d413259a46990580e213a0260801c91611319565b6345c3193d60e11b5f5260045260245ffd5b505090505f905f90565b505f91508190565b5080156112c1565b808202905f1983820990828083109203918083039283670de0b6b3a764000011156102185714611712577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066993670de0b6b3a7640000910990828211900360ee1b910360121c170290565b5050670de0b6b3a764000091500490565b81810291905f1982820991838084109303928084039384600160c01b1115610218571461176357600160c01b910990828211900360401b910360c01c1790565b50505060c01c90565b9060c082901b905f1983600160c01b099282808510940393808503948584111561021857146117ee578190600160c01b0981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b5091500490565b81810291905f1982820991838084109303928084039384600160401b1115610218571461183557600160401b910990828211900360c01b910360401c1790565b50505060401c90565b81810291905f1982820991838084109303928084039384600160801b1115610218571461187e57600160801b910990828211900360801b910360801c1790565b50505060801c90565b90608082901b905f1983600160801b099282808510940393808503948584111561021857146117ee578190600160801b0981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b9063ffffffff8091169116039063ffffffff82116110f357565b9060060b9060060b02908160060b9182036110f357565b9060060b9060060b0190667fffffffffffff198212667fffffffffffff8313176110f357565b6043549060405160208101633fabe5a360e21b815260048252611984602483610f27565b5f905f8060a092604051956119998588610f27565b843688375190604089901c6001600160a01b031662030d40fa813d101516611a53575b5015611a495760606020820151910151925f8213801590611a41575b611a36576ec097ce7bc90715b34b9f10000000008211611a2d578342119081611a10575b50611a08579190600190565b505f91905f90565b905063ffffffff611a21854261117c565b9160201c16105f6119fc565b50505f91905f90565b505f92508291829150565b5083156119d8565b505f915081908190565b90505f823e60015f6119bc565b611a68611189565b15611c5d57604154604081101561110757611a81611c63565b9050611ab563ffffffff42169161114284600101549163ffffffff611aa881851687611909565b1660060b9060020b611923565b90611ac863ffffffff6043541682611909565b905f935f925f91604254604081105f14611c535791905b63ffffffff5f92169160408201809211905b848110611be4575b505050505015611bda5763ffffffff91611b1291611909565b16918215611bd15760060b9060060b0390667fffffffffffff8213667fffffffffffff198312176110f35760060b9060060b811561144657667fffffffffffff1981145f198314166110f357818105915f82129182611bc2575b5050611ba8575b8060060b620d89e7198112908115611b9b575b50611b945760020b90600190565b505f905f90565b620d89e89150135f611b86565b60060b667fffffffffffff1981146110f3575f1901611b73565b0760060b151590505f80611b6c565b5050505f905f90565b505050505f905f90565b816110f357603f611bf5828561117c565b166040811015611107576001015460ff8160581c1615611c4a5763ffffffff81169085821115611c2b5750506001905b01611af1565b979850995050505050505060201c60060b929060015f80808080611af9565b50600190611c25565b5060409190611adf565b5f905f90565b60405160208101907f6ad6aa41fed2528a76979a615e3c5f3e0ab494f5abc5e1c15362ad6151187a4382526006604082015260408152611ca4606082610f27565b519020604051631e2eaeaf60e01b81526004810191909152906020826024817f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03165afa918215611d4b575f92611d17575b506001600160a01b0382169160a01c62ffffff1660020b90565b9091506020813d602011611d43575b81611d3360209383610f27565b810103126102185751905f611cfd565b3d9150611d26565b6040513d5f823e3d90fd5b90915f925f8060405192611d6b60a085610f27565b60a036853783956020825192019062030d40fa60203d101516611d8b5750565b60209193505f903e600191565b6001600160a01b03166fffffffffffffffffffffffffffffffff811115611e0d5780611dc3916117f5565b7f000000000000000000000000000000000000000000000000000000000000000115611dfb57610fa090670de0b6b3a7640000611887565b670de0b6b3a7640000610fa09161183e565b80611e179161129a565b7f000000000000000000000000000000000000000000000000000000000000000115611e4f57610fa090670de0b6b3a764000061176c565b670de0b6b3a7640000610fa091611723565b6043546040805163313ce56760e01b602082015260048152611e999290911c6001600160a01b0316611e94602483610f27565b611d56565b9015611eb4575160ff8111611eae5760ff1690565b5060ff90565b5060089056fe9b22d3d61959b4d3528b1d8ba932c96fbe302b36a1aad1d95cab54f9e0a135ea
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| no token holdings | ||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x5402a1…e4b892 | 4 days agoThu, 13 Aug 2026 06:36:07 UTC | 0x4e18d8…939b | [0] 0x000000000000…00000001 data: 0x000000000000000000…04f220cc |
| 0x78eec0…6b29f0 | 4 days agoThu, 13 Aug 2026 06:27:23 UTC | 0x4e18d8…939b | [0] 0x000000000000…00000000 data: 0x000000000000000000…00000000 |
| 0x78eec0…6b29f0 | 4 days agoThu, 13 Aug 2026 06:27:23 UTC | 0x8be007…57e0 | [0] 0x000000000000…00000000 [1] 0x000000000000…11b4a9d6 |
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| no internal transactions found for this address yet (traced blocks + on-demand) | ||||||||
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x5402a1…e4b892 | poke | 35,179,889 | 4 days agoThu, 13 Aug 2026 06:36:07 UTC | 0xe5c7…a9d6 | IN | RipV4UsdAggregator | $0.000 ETH | 0.00000413 |
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| no token transfers for this address yet | |||||||||