// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.7.6;
import "./interfaces/ICLPool.sol";
import "./libraries/cl/LowGasSafeMath.sol";
import "./libraries/cl/SafeCast.sol";
import "./libraries/cl/Tick.sol";
import "./libraries/cl/TickBitmap.sol";
import "./libraries/cl/Position.sol";
import "./libraries/cl/Oracle.sol";
import "./libraries/cl/FullMath.sol";
import "./libraries/cl/FixedPoint128.sol";
import "./libraries/cl/TransferHelper.sol";
import "./libraries/cl/TickMath.sol";
import "./libraries/cl/LiquidityMath.sol";
import "./libraries/cl/SqrtPriceMath.sol";
import "./libraries/cl/SwapMath.sol";
import "./interfaces/ICLPoolDeployer.sol";
import "./interfaces/ICLFactory.sol";
import "./interfaces/IERC20Minimal.sol";
import "./interfaces/callback/IPancakeV3MintCallback.sol";
import "./interfaces/callback/IPancakeV3SwapCallback.sol";
import "./interfaces/callback/IPancakeV3FlashCallback.sol";
import "./interfaces/ILmPool.sol";
contract CLPool is ICLPool {
using LowGasSafeMath for uint256;
using LowGasSafeMath for int256;
using SafeCast for uint256;
using SafeCast for int256;
using Tick for mapping(int24 => Tick.Info);
using TickBitmap for mapping(int16 => uint256);
using Position for mapping(bytes32 => Position.Info);
using Position for Position.Info;
using Oracle for Oracle.Observation[65535];
/// @inheritdoc ICLPoolImmutables
address public immutable override factory;
/// @inheritdoc ICLPoolImmutables
address public immutable override token0;
/// @inheritdoc ICLPoolImmutables
address public immutable override token1;
/// @inheritdoc ICLPoolImmutables
uint24 public immutable override fee;
/// @inheritdoc ICLPoolImmutables
int24 public immutable override tickSpacing;
/// @inheritdoc ICLPoolImmutables
uint128 public immutable override maxLiquidityPerTick;
uint32 internal constant PROTOCOL_FEE_SP = 65_536;
// The deployed CL factory's pool creation bytecode is immutable. New CL pools are normalized
// to the controller's ungauged policy with applyCLUngaugedProtocolFee after creation.
uint32 internal constant DEFAULT_PROTOCOL_FEE = 1_000; // 10% initialization fallback
uint32 internal constant DEFAULT_PROTOCOL_FEE_PACKED = DEFAULT_PROTOCOL_FEE + (DEFAULT_PROTOCOL_FEE << 16);
uint256 internal constant PROTOCOL_FEE_DENOMINATOR = 10_000;
struct Slot0 {
// the current price
uint160 sqrtPriceX96;
// the current tick
int24 tick;
// the most-recently updated index of the observations array
uint16 observationIndex;
// the current maximum number of observations that are being stored
uint16 observationCardinality;
// the next maximum number of observations to store, triggered in observations.write
uint16 observationCardinalityNext;
// the current protocol fee for token0 and token1,
// 2 uint16 values stored in one uint32 variable (fee/PROTOCOL_FEE_DENOMINATOR)
uint32 feeProtocol;
// whether the pool is locked
bool unlocked;
}
/// @inheritdoc ICLPoolState
Slot0 public override slot0;
/// @inheritdoc ICLPoolState
uint256 public override feeGrowthGlobal0X128;
/// @inheritdoc ICLPoolState
uint256 public override feeGrowthGlobal1X128;
// accumulated protocol fees in token0/token1 units
struct ProtocolFees {
uint128 token0;
uint128 token1;
}
/// @inheritdoc ICLPoolState
ProtocolFees public override protocolFees;
/// @inheritdoc ICLPoolState
uint128 public override liquidity;
/// @inheritdoc ICLPoolState
mapping(int24 => Tick.Info) public override ticks;
/// @inheritdoc ICLPoolState
mapping(int16 => uint256) public override tickBitmap;
/// @inheritdoc ICLPoolState
mapping(bytes32 => Position.Info) public override positions;
/// @inheritdoc ICLPoolState
Oracle.Observation[65535] public override observations;
// CL LM pool accounting for staked NFT liquidity.
ILmPool public override lmPool;
event SetLmPoolEvent(address addr);
/// @dev Mutually exclusive reentrancy protection into the pool to/from a method. This method also prevents entrance
/// to a function before the pool is initialized. The reentrancy guard is required throughout the contract because
/// we use balance checks to determine the payment status of interactions such as mint, swap and flash.
modifier lock() {
require(slot0.unlocked, "LOK");
slot0.unlocked = false;
_;
slot0.unlocked = true;
}
/// @dev Prevents calling a function from anyone except the factory or its
/// owner
modifier onlyFactoryOrFactoryOwner() {
require(msg.sender == factory || msg.sender == ICLFactory(factory).owner());
_;
}
constructor() {
int24 _tickSpacing;
(factory, token0, token1, fee, _tickSpacing) = ICLPoolDeployer(msg.sender).parameters();
tickSpacing = _tickSpacing;
maxLiquidityPerTick = Tick.tickSpacingToMaxLiquidityPerTick(_tickSpacing);
}
/// @dev Common checks for valid tick inputs.
function checkTicks(int24 tickLower, int24 tickUpper) private pure {
require(tickLower < tickUpper, "TLU");
require(tickLower >= TickMath.MIN_TICK, "TLM");
require(tickUpper <= TickMath.MAX_TICK, "TUM");
}
/// @dev Returns the block timestamp truncated to 32 bits, i.e. mod 2**32. This method is overridden in tests.
function _blockTimestamp() internal view virtual returns (uint32) {
return uint32(block.timestamp); // truncation is desired
}
/// @dev Get the pool's balance of token0
/// @dev This function is gas optimized to avoid a redundant extcodesize check in addition to the returndatasize
/// check
function balance0() private view returns (uint256) {
(bool success, bytes memory data) =
token0.staticcall(abi.encodeWithSelector(IERC20Minimal.balanceOf.selector, address(this)));
require(success && data.length >= 32);
return abi.decode(data, (uint256));
}
/// @dev Get the pool's balance of token1
/// @dev This function is gas optimized to avoid a redundant extcodesize check in addition to the returndatasize
/// check
function balance1() private view returns (uint256) {
(bool success, bytes memory data) =
token1.staticcall(abi.encodeWithSelector(IERC20Minimal.balanceOf.selector, address(this)));
require(success && data.length >= 32);
return abi.decode(data, (uint256));
}
/// @inheritdoc ICLPoolDerivedState
function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)
external
view
override
returns (int56 tickCumulativeInside, uint160 secondsPerLiquidityInsideX128, uint32 secondsInside)
{
checkTicks(tickLower, tickUpper);
int56 tickCumulativeLower;
int56 tickCumulativeUpper;
uint160 secondsPerLiquidityOutsideLowerX128;
uint160 secondsPerLiquidityOutsideUpperX128;
uint32 secondsOutsideLower;
uint32 secondsOutsideUpper;
{
Tick.Info storage lower = ticks[tickLower];
Tick.Info storage upper = ticks[tickUpper];
bool initializedLower;
(tickCumulativeLower, secondsPerLiquidityOutsideLowerX128, secondsOutsideLower, initializedLower) =
(lower.tickCumulativeOutside, lower.secondsPerLiquidityOutsideX128, lower.secondsOutside, lower.initialized);
require(initializedLower);
bool initializedUpper;
(tickCumulativeUpper, secondsPerLiquidityOutsideUpperX128, secondsOutsideUpper, initializedUpper) =
(upper.tickCumulativeOutside, upper.secondsPerLiquidityOutsideX128, upper.secondsOutside, upper.initialized);
require(initializedUpper);
}
Slot0 memory _slot0 = slot0;
if (_slot0.tick < tickLower) {
return (
tickCumulativeLower - tickCumulativeUpper,
secondsPerLiquidityOutsideLowerX128 - secondsPerLiquidityOutsideUpperX128,
secondsOutsideLower - secondsOutsideUpper
);
} else if (_slot0.tick < tickUpper) {
uint32 time = _blockTimestamp();
(int56 tickCumulative, uint160 secondsPerLiquidityCumulativeX128) = observations.observeSingle(
time, 0, _slot0.tick, _slot0.observationIndex, liquidity, _slot0.observationCardinality
);
return (
tickCumulative - tickCumulativeLower - tickCumulativeUpper,
secondsPerLiquidityCumulativeX128 - secondsPerLiquidityOutsideLowerX128
- secondsPerLiquidityOutsideUpperX128,
time - secondsOutsideLower - secondsOutsideUpper
);
} else {
return (
tickCumulativeUpper - tickCumulativeLower,
secondsPerLiquidityOutsideUpperX128 - secondsPerLiquidityOutsideLowerX128,
secondsOutsideUpper - secondsOutsideLower
);
}
}
/// @inheritdoc ICLPoolDerivedState
function observe(uint32[] calldata secondsAgos)
external
view
override
returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s)
{
return observations.observe(
_blockTimestamp(), secondsAgos, slot0.tick, slot0.observationIndex, liquidity, slot0.observationCardinality
);
}
/// @inheritdoc ICLPoolActions
function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external override lock {
uint16 observationCardinalityNextOld = slot0.observationCardinalityNext; // for the event
uint16 observationCardinalityNextNew =
observations.grow(observationCardinalityNextOld, observationCardinalityNext);
slot0.observationCardinalityNext = observationCardinalityNextNew;
if (observationCardinalityNextOld != observationCardinalityNextNew) {
emit IncreaseObservationCardinalityNext(observationCardinalityNextOld, observationCardinalityNextNew);
}
}
/// @inheritdoc ICLPoolActions
/// @dev not locked because it initializes unlocked
function initialize(uint160 sqrtPriceX96) external override {
require(slot0.sqrtPriceX96 == 0, "AI");
int24 tick = TickMath.getTickAtSqrtRatio(sqrtPriceX96);
(uint16 cardinality, uint16 cardinalityNext) = observations.initialize(_blockTimestamp());
slot0 = Slot0({
sqrtPriceX96: sqrtPriceX96,
tick: tick,
observationIndex: 0,
observationCardinality: cardinality,
observationCardinalityNext: cardinalityNext,
feeProtocol: DEFAULT_PROTOCOL_FEE_PACKED,
unlocked: true
});
emit Initialize(sqrtPriceX96, tick);
}
struct ModifyPositionParams {
// the address that owns the position
address owner;
// the lower and upper tick of the position
int24 tickLower;
int24 tickUpper;
// any change in liquidity
int128 liquidityDelta;
}
/// @dev Effect some changes to a position
/// @param params the position details and the change to the position's liquidity to effect
/// @return position a storage pointer referencing the position with the given owner and tick range
/// @return amount0 the amount of token0 owed to the pool, negative if the pool should pay the recipient
/// @return amount1 the amount of token1 owed to the pool, negative if the pool should pay the recipient
function _modifyPosition(ModifyPositionParams memory params)
private
returns (Position.Info storage position, int256 amount0, int256 amount1)
{
checkTicks(params.tickLower, params.tickUpper);
Slot0 memory _slot0 = slot0; // SLOAD for gas optimization
position = _updatePosition(params.owner, params.tickLower, params.tickUpper, params.liquidityDelta, _slot0.tick);
if (params.liquidityDelta != 0) {
if (_slot0.tick < params.tickLower) {
// current tick is below the passed range; liquidity can only become in range by crossing from left to
// right, when we'll need _more_ token0 (it's becoming more valuable) so user must provide it
amount0 = SqrtPriceMath.getAmount0Delta(
TickMath.getSqrtRatioAtTick(params.tickLower),
TickMath.getSqrtRatioAtTick(params.tickUpper),
params.liquidityDelta
);
} else if (_slot0.tick < params.tickUpper) {
// current tick is inside the passed range
uint128 liquidityBefore = liquidity; // SLOAD for gas optimization
// write an oracle entry
(slot0.observationIndex, slot0.observationCardinality) = observations.write(
_slot0.observationIndex,
_blockTimestamp(),
_slot0.tick,
liquidityBefore,
_slot0.observationCardinality,
_slot0.observationCardinalityNext
);
amount0 = SqrtPriceMath.getAmount0Delta(
_slot0.sqrtPriceX96, TickMath.getSqrtRatioAtTick(params.tickUpper), params.liquidityDelta
);
amount1 = SqrtPriceMath.getAmount1Delta(
TickMath.getSqrtRatioAtTick(params.tickLower), _slot0.sqrtPriceX96, params.liquidityDelta
);
liquidity = LiquidityMath.addDelta(liquidityBefore, params.liquidityDelta);
} else {
// current tick is above the passed range; liquidity can only become in range by crossing from right to
// left, when we'll need _more_ token1 (it's becoming more valuable) so user must provide it
amount1 = SqrtPriceMath.getAmount1Delta(
TickMath.getSqrtRatioAtTick(params.tickLower),
TickMath.getSqrtRatioAtTick(params.tickUpper),
params.liquidityDelta
);
}
}
}
/// @dev Gets and updates a position with the given liquidity delta
/// @param owner the owner of the position
/// @param tickLower the lower tick of the position's tick range
/// @param tickUpper the upper tick of the position's tick range
/// @param tick the current tick, passed to avoid sloads
function _updatePosition(address owner, int24 tickLower, int24 tickUpper, int128 liquidityDelta, int24 tick)
private
returns (Position.Info storage position)
{
position = positions.get(owner, tickLower, tickUpper);
uint256 _feeGrowthGlobal0X128 = feeGrowthGlobal0X128; // SLOAD for gas optimization
uint256 _feeGrowthGlobal1X128 = feeGrowthGlobal1X128; // SLOAD for gas optimization
// if we need to update the ticks, do it
bool flippedLower;
bool flippedUpper;
if (liquidityDelta != 0) {
uint32 time = _blockTimestamp();
(int56 tickCumulative, uint160 secondsPerLiquidityCumulativeX128) = observations.observeSingle(
time, 0, slot0.tick, slot0.observationIndex, liquidity, slot0.observationCardinality
);
flippedLower = ticks.update(
tickLower,
tick,
liquidityDelta,
_feeGrowthGlobal0X128,
_feeGrowthGlobal1X128,
secondsPerLiquidityCumulativeX128,
tickCumulative,
time,
false,
maxLiquidityPerTick
);
flippedUpper = ticks.update(
tickUpper,
tick,
liquidityDelta,
_feeGrowthGlobal0X128,
_feeGrowthGlobal1X128,
secondsPerLiquidityCumulativeX128,
tickCumulative,
time,
true,
maxLiquidityPerTick
);
if (flippedLower) {
tickBitmap.flipTick(tickLower, tickSpacing);
}
if (flippedUpper) {
tickBitmap.flipTick(tickUpper, tickSpacing);
}
}
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) =
ticks.getFeeGrowthInside(tickLower, tickUpper, tick, _feeGrowthGlobal0X128, _feeGrowthGlobal1X128);
position.update(liquidityDelta, feeGrowthInside0X128, feeGrowthInside1X128);
// clear any tick data that is no longer needed
if (liquidityDelta < 0) {
if (flippedLower) {
ticks.clear(tickLower);
}
if (flippedUpper) {
ticks.clear(tickUpper);
}
}
}
/// @inheritdoc ICLPoolActions
/// @dev noDelegateCall is applied indirectly via _modifyPosition
function mint(address recipient, int24 tickLower, int24 tickUpper, uint128 amount, bytes calldata data)
external
override
lock
returns (uint256 amount0, uint256 amount1)
{
require(amount > 0);
(, int256 amount0Int, int256 amount1Int) = _modifyPosition(
ModifyPositionParams({
owner: recipient, tickLower: tickLower, tickUpper: tickUpper, liquidityDelta: int256(amount).toInt128()
})
);
amount0 = uint256(amount0Int);
amount1 = uint256(amount1Int);
uint256 balance0Before;
uint256 balance1Before;
if (amount0 > 0) balance0Before = balance0();
if (amount1 > 0) balance1Before = balance1();
IPancakeV3MintCallback(msg.sender).pancakeV3MintCallback(amount0, amount1, data);
if (amount0 > 0) require(balance0Before.add(amount0) <= balance0(), "M0");
if (amount1 > 0) require(balance1Before.add(amount1) <= balance1(), "M1");
emit Mint(msg.sender, recipient, tickLower, tickUpper, amount, amount0, amount1);
}
/// @inheritdoc ICLPoolActions
function collect(
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount0Requested,
uint128 amount1Requested
) external override lock returns (uint128 amount0, uint128 amount1) {
// we don't need to checkTicks here, because invalid positions will never have non-zero tokensOwed{0,1}
Position.Info storage position = positions.get(msg.sender, tickLower, tickUpper);
amount0 = amount0Requested > position.tokensOwed0 ? position.tokensOwed0 : amount0Requested;
amount1 = amount1Requested > position.tokensOwed1 ? position.tokensOwed1 : amount1Requested;
if (amount0 > 0) {
position.tokensOwed0 -= amount0;
TransferHelper.safeTransfer(token0, recipient, amount0);
}
if (amount1 > 0) {
position.tokensOwed1 -= amount1;
TransferHelper.safeTransfer(token1, recipient, amount1);
}
emit Collect(msg.sender, recipient, tickLower, tickUpper, amount0, amount1);
}
/// @inheritdoc ICLPoolActions
/// @dev noDelegateCall is applied indirectly via _modifyPosition
function burn(int24 tickLower, int24 tickUpper, uint128 amount)
external
override
lock
returns (uint256 amount0, uint256 amount1)
{
(Position.Info storage position, int256 amount0Int, int256 amount1Int) = _modifyPosition(
ModifyPositionParams({
owner: msg.sender,
tickLower: tickLower,
tickUpper: tickUpper,
liquidityDelta: -int256(amount).toInt128()
})
);
amount0 = uint256(-amount0Int);
amount1 = uint256(-amount1Int);
if (amount0 > 0 || amount1 > 0) {
(position.tokensOwed0, position.tokensOwed1) =
(position.tokensOwed0 + uint128(amount0), position.tokensOwed1 + uint128(amount1));
}
emit Burn(msg.sender, tickLower, tickUpper, amount, amount0, amount1);
}
struct SwapCache {
// the protocol fee for the input token
uint32 feeProtocol;
// liquidity at the beginning of the swap
uint128 liquidityStart;
// the timestamp of the current block
uint32 blockTimestamp;
// the current value of the tick accumulator, computed only if we cross an initialized tick
int56 tickCumulative;
// the current value of seconds per liquidity accumulator, computed only if we cross an initialized tick
uint160 secondsPerLiquidityCumulativeX128;
// whether we've computed and cached the above two accumulators
bool computedLatestObservation;
}
// the top level state of the swap, the results of which are recorded in storage at the end
struct SwapState {
// the amount remaining to be swapped in/out of the input/output asset
int256 amountSpecifiedRemaining;
// the amount already swapped out/in of the output/input asset
int256 amountCalculated;
// current sqrt(price)
uint160 sqrtPriceX96;
// the tick associated with the current price
int24 tick;
// the global fee growth of the input token
uint256 feeGrowthGlobalX128;
// amount of input token paid as protocol fee
uint128 protocolFee;
// the current liquidity in range
uint128 liquidity;
}
struct StepComputations {
// the price at the beginning of the step
uint160 sqrtPriceStartX96;
// the next tick to swap to from the current tick in the swap direction
int24 tickNext;
// whether tickNext is initialized or not
bool initialized;
// sqrt(price) for the next tick (1/0)
uint160 sqrtPriceNextX96;
// how much is being swapped in in this step
uint256 amountIn;
// how much is being swapped out
uint256 amountOut;
// how much fee is being paid in
uint256 feeAmount;
}
/// @inheritdoc ICLPoolActions
function swap(
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes calldata data
) external override returns (int256 amount0, int256 amount1) {
require(amountSpecified != 0, "AS");
Slot0 memory slot0Start = slot0;
require(slot0Start.unlocked, "LOK");
require(
zeroForOne
? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO
: sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO,
"SPL"
);
slot0.unlocked = false;
SwapCache memory cache = SwapCache({
liquidityStart: liquidity,
blockTimestamp: _blockTimestamp(),
feeProtocol: zeroForOne ? (slot0Start.feeProtocol % PROTOCOL_FEE_SP) : (slot0Start.feeProtocol >> 16),
secondsPerLiquidityCumulativeX128: 0,
tickCumulative: 0,
computedLatestObservation: false
});
if (address(lmPool) != address(0)) {
lmPool.accumulateReward(cache.blockTimestamp);
}
bool exactInput = amountSpecified > 0;
SwapState memory state = SwapState({
amountSpecifiedRemaining: amountSpecified,
amountCalculated: 0,
sqrtPriceX96: slot0Start.sqrtPriceX96,
tick: slot0Start.tick,
feeGrowthGlobalX128: zeroForOne ? feeGrowthGlobal0X128 : feeGrowthGlobal1X128,
protocolFee: 0,
liquidity: cache.liquidityStart
});
// continue swapping as long as we haven't used the entire input/output and haven't reached the price limit
while (state.amountSpecifiedRemaining != 0 && state.sqrtPriceX96 != sqrtPriceLimitX96) {
StepComputations memory step;
step.sqrtPriceStartX96 = state.sqrtPriceX96;
(step.tickNext, step.initialized) =
tickBitmap.nextInitializedTickWithinOneWord(state.tick, tickSpacing, zeroForOne);
// ensure that we do not overshoot the min/max tick, as the tick bitmap is not aware of these bounds
if (step.tickNext < TickMath.MIN_TICK) {
step.tickNext = TickMath.MIN_TICK;
} else if (step.tickNext > TickMath.MAX_TICK) {
step.tickNext = TickMath.MAX_TICK;
}
// get the price for the next tick
step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext);
// compute values to swap to the target tick, price limit, or point where input/output amount is exhausted
(state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep(
state.sqrtPriceX96,
(zeroForOne ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 : step.sqrtPriceNextX96 > sqrtPriceLimitX96)
? sqrtPriceLimitX96
: step.sqrtPriceNextX96,
state.liquidity,
state.amountSpecifiedRemaining,
fee
);
if (exactInput) {
state.amountSpecifiedRemaining -= (step.amountIn + step.feeAmount).toInt256();
state.amountCalculated = state.amountCalculated.sub(step.amountOut.toInt256());
} else {
state.amountSpecifiedRemaining += step.amountOut.toInt256();
state.amountCalculated = state.amountCalculated.add((step.amountIn + step.feeAmount).toInt256());
}
// if the protocol fee is on, calculate how much is owed, decrement feeAmount, and increment protocolFee
if (cache.feeProtocol > 0) {
uint256 delta = (step.feeAmount.mul(cache.feeProtocol)) / PROTOCOL_FEE_DENOMINATOR;
step.feeAmount -= delta;
state.protocolFee += uint128(delta);
}
// update global fee tracker
if (state.liquidity > 0) {
state.feeGrowthGlobalX128 += FullMath.mulDiv(step.feeAmount, FixedPoint128.Q128, state.liquidity);
}
// shift tick if we reached the next price
if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {
// if the tick is initialized, run the tick transition
if (step.initialized) {
// check for the placeholder value, which we replace with the actual value the first time the swap
// crosses an initialized tick
if (!cache.computedLatestObservation) {
(cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128) = observations.observeSingle(
cache.blockTimestamp,
0,
slot0Start.tick,
slot0Start.observationIndex,
cache.liquidityStart,
slot0Start.observationCardinality
);
cache.computedLatestObservation = true;
}
if (address(lmPool) != address(0)) {
lmPool.crossLmTick(step.tickNext, zeroForOne);
}
int128 liquidityNet = ticks.cross(
step.tickNext,
(zeroForOne ? state.feeGrowthGlobalX128 : feeGrowthGlobal0X128),
(zeroForOne ? feeGrowthGlobal1X128 : state.feeGrowthGlobalX128),
cache.secondsPerLiquidityCumulativeX128,
cache.tickCumulative,
cache.blockTimestamp
);
// if we're moving leftward, we interpret liquidityNet as the opposite sign
// safe because liquidityNet cannot be type(int128).min
if (zeroForOne) liquidityNet = -liquidityNet;
state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet);
}
state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;
} else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) {
// recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved
state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96);
}
}
// update tick and write an oracle entry if the tick change
if (state.tick != slot0Start.tick) {
(uint16 observationIndex, uint16 observationCardinality) = observations.write(
slot0Start.observationIndex,
cache.blockTimestamp,
slot0Start.tick,
cache.liquidityStart,
slot0Start.observationCardinality,
slot0Start.observationCardinalityNext
);
(slot0.sqrtPriceX96, slot0.tick, slot0.observationIndex, slot0.observationCardinality) =
(state.sqrtPriceX96, state.tick, observationIndex, observationCardinality);
} else {
// otherwise just update the price
slot0.sqrtPriceX96 = state.sqrtPriceX96;
}
// update liquidity if it changed
if (cache.liquidityStart != state.liquidity) liquidity = state.liquidity;
uint128 protocolFeesToken0 = 0;
uint128 protocolFeesToken1 = 0;
// update fee growth global and, if necessary, protocol fees
// overflow is acceptable, protocol has to withdraw before it hits type(uint128).max fees
if (zeroForOne) {
feeGrowthGlobal0X128 = state.feeGrowthGlobalX128;
if (state.protocolFee > 0) protocolFees.token0 += state.protocolFee;
protocolFeesToken0 = state.protocolFee;
} else {
feeGrowthGlobal1X128 = state.feeGrowthGlobalX128;
if (state.protocolFee > 0) protocolFees.token1 += state.protocolFee;
protocolFeesToken1 = state.protocolFee;
}
(amount0, amount1) = zeroForOne == exactInput
? (amountSpecified - state.amountSpecifiedRemaining, state.amountCalculated)
: (state.amountCalculated, amountSpecified - state.amountSpecifiedRemaining);
// do the transfers and collect payment
if (zeroForOne) {
if (amount1 < 0) TransferHelper.safeTransfer(token1, recipient, uint256(-amount1));
uint256 balance0Before = balance0();
IPancakeV3SwapCallback(msg.sender).pancakeV3SwapCallback(amount0, amount1, data);
require(balance0Before.add(uint256(amount0)) <= balance0(), "IIA");
} else {
if (amount0 < 0) TransferHelper.safeTransfer(token0, recipient, uint256(-amount0));
uint256 balance1Before = balance1();
IPancakeV3SwapCallback(msg.sender).pancakeV3SwapCallback(amount0, amount1, data);
require(balance1Before.add(uint256(amount1)) <= balance1(), "IIA");
}
emit Swap(
msg.sender,
recipient,
amount0,
amount1,
state.sqrtPriceX96,
state.liquidity,
state.tick,
protocolFeesToken0,
protocolFeesToken1
);
slot0.unlocked = true;
}
/// @inheritdoc ICLPoolActions
function flash(address recipient, uint256 amount0, uint256 amount1, bytes calldata data) external override lock {
uint128 _liquidity = liquidity;
require(_liquidity > 0, "L");
uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);
uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);
uint256 balance0Before = balance0();
uint256 balance1Before = balance1();
if (amount0 > 0) TransferHelper.safeTransfer(token0, recipient, amount0);
if (amount1 > 0) TransferHelper.safeTransfer(token1, recipient, amount1);
IPancakeV3FlashCallback(msg.sender).pancakeV3FlashCallback(fee0, fee1, data);
uint256 balance0After = balance0();
uint256 balance1After = balance1();
require(balance0Before.add(fee0) <= balance0After, "F0");
require(balance1Before.add(fee1) <= balance1After, "F1");
// sub is safe because we know balanceAfter is gt balanceBefore by at least fee
uint256 paid0 = balance0After - balance0Before;
uint256 paid1 = balance1After - balance1Before;
if (paid0 > 0) {
uint32 feeProtocol0 = slot0.feeProtocol % PROTOCOL_FEE_SP;
uint256 fees0 = feeProtocol0 == 0 ? 0 : (paid0 * feeProtocol0) / PROTOCOL_FEE_DENOMINATOR;
if (uint128(fees0) > 0) protocolFees.token0 += uint128(fees0);
feeGrowthGlobal0X128 += FullMath.mulDiv(paid0 - fees0, FixedPoint128.Q128, _liquidity);
}
if (paid1 > 0) {
uint32 feeProtocol1 = slot0.feeProtocol >> 16;
uint256 fees1 = feeProtocol1 == 0 ? 0 : (paid1 * feeProtocol1) / PROTOCOL_FEE_DENOMINATOR;
if (uint128(fees1) > 0) protocolFees.token1 += uint128(fees1);
feeGrowthGlobal1X128 += FullMath.mulDiv(paid1 - fees1, FixedPoint128.Q128, _liquidity);
}
emit Flash(msg.sender, recipient, amount0, amount1, paid0, paid1);
}
/// @inheritdoc ICLPoolOwnerActions
function setFeeProtocol(uint32 feeProtocol0, uint32 feeProtocol1) external override lock onlyFactoryOrFactoryOwner {
require(feeProtocol0 <= PROTOCOL_FEE_DENOMINATOR && feeProtocol1 <= PROTOCOL_FEE_DENOMINATOR);
uint32 feeProtocolOld = slot0.feeProtocol;
slot0.feeProtocol = feeProtocol0 + (feeProtocol1 << 16);
emit SetFeeProtocol(feeProtocolOld % PROTOCOL_FEE_SP, feeProtocolOld >> 16, feeProtocol0, feeProtocol1);
}
/// @inheritdoc ICLPoolOwnerActions
function collectProtocol(address recipient, uint128 amount0Requested, uint128 amount1Requested)
external
override
lock
onlyFactoryOrFactoryOwner
returns (uint128 amount0, uint128 amount1)
{
amount0 = amount0Requested > protocolFees.token0 ? protocolFees.token0 : amount0Requested;
amount1 = amount1Requested > protocolFees.token1 ? protocolFees.token1 : amount1Requested;
if (amount0 > 0) {
if (amount0 == protocolFees.token0) amount0--; // ensure that the slot is not cleared, for gas savings
protocolFees.token0 -= amount0;
TransferHelper.safeTransfer(token0, recipient, amount0);
}
if (amount1 > 0) {
if (amount1 == protocolFees.token1) amount1--; // ensure that the slot is not cleared, for gas savings
protocolFees.token1 -= amount1;
TransferHelper.safeTransfer(token1, recipient, amount1);
}
emit CollectProtocol(msg.sender, recipient, amount0, amount1);
}
function setLmPool(address _lmPool) external override onlyFactoryOrFactoryOwner {
lmPool = ILmPool(_lmPool);
emit SetLmPoolEvent(address(_lmPool));
}
}[
{
"type": "constructor",
"inputs": [],
"stateMutability": "nonpayable"
},
{
"name": "Burn",
"type": "event",
"inputs": [
{
"name": "owner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "tickLower",
"type": "int24",
"indexed": true,
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"indexed": true,
"internalType": "int24"
},
{
"name": "amount",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "amount0",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "Collect",
"type": "event",
"inputs": [
{
"name": "owner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "recipient",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "tickLower",
"type": "int24",
"indexed": true,
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"indexed": true,
"internalType": "int24"
},
{
"name": "amount0",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "amount1",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
}
],
"anonymous": false
},
{
"name": "CollectProtocol",
"type": "event",
"inputs": [
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount0",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "amount1",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
}
],
"anonymous": false
},
{
"name": "Flash",
"type": "event",
"inputs": [
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount0",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "paid0",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "paid1",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "IncreaseObservationCardinalityNext",
"type": "event",
"inputs": [
{
"name": "observationCardinalityNextOld",
"type": "uint16",
"indexed": false,
"internalType": "uint16"
},
{
"name": "observationCardinalityNextNew",
"type": "uint16",
"indexed": false,
"internalType": "uint16"
}
],
"anonymous": false
},
{
"name": "Initialize",
"type": "event",
"inputs": [
{
"name": "sqrtPriceX96",
"type": "uint160",
"indexed": false,
"internalType": "uint160"
},
{
"name": "tick",
"type": "int24",
"indexed": false,
"internalType": "int24"
}
],
"anonymous": false
},
{
"name": "Mint",
"type": "event",
"inputs": [
{
"name": "sender",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "owner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "tickLower",
"type": "int24",
"indexed": true,
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"indexed": true,
"internalType": "int24"
},
{
"name": "amount",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "amount0",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "SetFeeProtocol",
"type": "event",
"inputs": [
{
"name": "feeProtocol0Old",
"type": "uint32",
"indexed": false,
"internalType": "uint32"
},
{
"name": "feeProtocol1Old",
"type": "uint32",
"indexed": false,
"internalType": "uint32"
},
{
"name": "feeProtocol0New",
"type": "uint32",
"indexed": false,
"internalType": "uint32"
},
{
"name": "feeProtocol1New",
"type": "uint32",
"indexed": false,
"internalType": "uint32"
}
],
"anonymous": false
},
{
"name": "SetLmPoolEvent",
"type": "event",
"inputs": [
{
"name": "addr",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "Swap",
"type": "event",
"inputs": [
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount0",
"type": "int256",
"indexed": false,
"internalType": "int256"
},
{
"name": "amount1",
"type": "int256",
"indexed": false,
"internalType": "int256"
},
{
"name": "sqrtPriceX96",
"type": "uint160",
"indexed": false,
"internalType": "uint160"
},
{
"name": "liquidity",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "tick",
"type": "int24",
"indexed": false,
"internalType": "int24"
},
{
"name": "protocolFeesToken0",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "protocolFeesToken1",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
}
],
"anonymous": false
},
{
"name": "burn",
"type": "function",
"inputs": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "amount",
"type": "uint128",
"internalType": "uint128"
}
],
"outputs": [
{
"name": "amount0",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "collect",
"type": "function",
"inputs": [
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "amount0Requested",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "amount1Requested",
"type": "uint128",
"internalType": "uint128"
}
],
"outputs": [
{
"name": "amount0",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "amount1",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "nonpayable"
},
{
"name": "collectProtocol",
"type": "function",
"inputs": [
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "amount0Requested",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "amount1Requested",
"type": "uint128",
"internalType": "uint128"
}
],
"outputs": [
{
"name": "amount0",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "amount1",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "nonpayable"
},
{
"name": "factory",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "fee",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint24",
"internalType": "uint24"
}
],
"stateMutability": "view"
},
{
"name": "feeGrowthGlobal0X128",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "feeGrowthGlobal1X128",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "flash",
"type": "function",
"inputs": [
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "amount0",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "increaseObservationCardinalityNext",
"type": "function",
"inputs": [
{
"name": "observationCardinalityNext",
"type": "uint16",
"internalType": "uint16"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "initialize",
"type": "function",
"inputs": [
{
"name": "sqrtPriceX96",
"type": "uint160",
"internalType": "uint160"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "liquidity",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "lmPool",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract ILmPool"
}
],
"stateMutability": "view"
},
{
"name": "maxLiquidityPerTick",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "mint",
"type": "function",
"inputs": [
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "amount",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "amount0",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "observations",
"type": "function",
"inputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "blockTimestamp",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "tickCumulative",
"type": "int56",
"internalType": "int56"
},
{
"name": "secondsPerLiquidityCumulativeX128",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "initialized",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "observe",
"type": "function",
"inputs": [
{
"name": "secondsAgos",
"type": "uint32[]",
"internalType": "uint32[]"
}
],
"outputs": [
{
"name": "tickCumulatives",
"type": "int56[]",
"internalType": "int56[]"
},
{
"name": "secondsPerLiquidityCumulativeX128s",
"type": "uint160[]",
"internalType": "uint160[]"
}
],
"stateMutability": "view"
},
{
"name": "positions",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "liquidity",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "feeGrowthInside0LastX128",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feeGrowthInside1LastX128",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "tokensOwed0",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "tokensOwed1",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "protocolFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "token0",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "token1",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "setFeeProtocol",
"type": "function",
"inputs": [
{
"name": "feeProtocol0",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "feeProtocol1",
"type": "uint32",
"internalType": "uint32"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setLmPool",
"type": "function",
"inputs": [
{
"name": "_lmPool",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "slot0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "sqrtPriceX96",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "tick",
"type": "int24",
"internalType": "int24"
},
{
"name": "observationIndex",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "observationCardinality",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "observationCardinalityNext",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "feeProtocol",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "unlocked",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "snapshotCumulativesInside",
"type": "function",
"inputs": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
}
],
"outputs": [
{
"name": "tickCumulativeInside",
"type": "int56",
"internalType": "int56"
},
{
"name": "secondsPerLiquidityInsideX128",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "secondsInside",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "swap",
"type": "function",
"inputs": [
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "zeroForOne",
"type": "bool",
"internalType": "bool"
},
{
"name": "amountSpecified",
"type": "int256",
"internalType": "int256"
},
{
"name": "sqrtPriceLimitX96",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "amount0",
"type": "int256",
"internalType": "int256"
},
{
"name": "amount1",
"type": "int256",
"internalType": "int256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "tickBitmap",
"type": "function",
"inputs": [
{
"name": "",
"type": "int16",
"internalType": "int16"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "tickSpacing",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "ticks",
"type": "function",
"inputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"outputs": [
{
"name": "liquidityGross",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "liquidityNet",
"type": "int128",
"internalType": "int128"
},
{
"name": "feeGrowthOutside0X128",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feeGrowthOutside1X128",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "tickCumulativeOutside",
"type": "int56",
"internalType": "int56"
},
{
"name": "secondsPerLiquidityOutsideX128",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "secondsOutside",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "initialized",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "token0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "token1",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
}
]0x608060405234801561001057600080fd5b50600436106101845760003560e01c806370cf754a116100d9578063cc7e7fa211610087578063cc7e7fa2146107b5578063d0c93a7c146107db578063d21220a7146107fa578063ddca3f4314610802578063f305839914610822578063f30dba931461082a578063f637731d146108ac57610184565b806370cf754a146105a157806385b66729146105a9578063883bdbfd146105e6578063a34123a7146106ed578063a38807f214610727578063b0d0d21114610782578063c45a0155146107ad57610184565b80633c8a7d8d116101365780633c8a7d8d1461038b578063461413191461042b578063490e6cbc146104455780634f1eb3d8146104cf578063514ea4bf146105205780635339c29614610579578063540d49181461059957610184565b80630dfe168114610189578063128acb08146101ad5780631a6865021461025a5780631ad8b03b1461027e578063252c09d7146102b557806332148f671461030c5780633850c7bd1461032f575b600080fd5b6101916108d2565b604080516001600160a01b039092168252519081900360200190f35b610241600480360360a08110156101c357600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a081016080820135600160201b81111561020357600080fd5b82018360208201111561021557600080fd5b803590602001918460018302840111600160201b8311171561023657600080fd5b5090925090506108f6565b6040805192835260208301919091528051918290030190f35b6102626115f3565b604080516001600160801b039092168252519081900360200190f35b610286611602565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102d2600480360360208110156102cb57600080fd5b503561161c565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b61032d6004803603602081101561032257600080fd5b503561ffff16611661565b005b610337611753565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015263ffffffff90911660a0840152151560c0830152519081900360e00190f35b610241600480360360a08110156103a157600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a081016080820135600160201b8111156103ed57600080fd5b8201836020820111156103ff57600080fd5b803590602001918460018302840111600160201b8311171561042057600080fd5b5090925090506117a8565b610433611a66565b60408051918252519081900360200190f35b61032d6004803603608081101561045b57600080fd5b6001600160a01b038235169160208101359160408201359190810190608081016060820135600160201b81111561049157600080fd5b8201836020820111156104a357600080fd5b803590602001918460018302840111600160201b831117156104c457600080fd5b509092509050611a6c565b610286600480360360a08110156104e557600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611eb3565b61053d6004803603602081101561053657600080fd5b50356120d1565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b6104336004803603602081101561058f57600080fd5b503560010b61210e565b610191612120565b610262612131565b610286600480360360608110156105bf57600080fd5b506001600160a01b03813516906001600160801b0360208201358116916040013516612155565b610654600480360360208110156105fc57600080fd5b810190602081018135600160201b81111561061657600080fd5b82018360208201111561062857600080fd5b803590602001918460208302840111600160201b8311171561064957600080fd5b509092509050612450565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610698578181015183820152602001610680565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156106d75781810151838201526020016106bf565b5050505090500194505050505060405180910390f35b6102416004803603606081101561070357600080fd5b508035600290810b91602081013590910b90604001356001600160801b03166124d5565b6107516004803603604081101561073d57600080fd5b508035600290810b9160200135900b612651565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b61032d6004803603604081101561079857600080fd5b5063ffffffff81358116916020013516612839565b610191612a1e565b61032d600480360360208110156107cb57600080fd5b50356001600160a01b0316612a42565b6107e3612b64565b6040805160029290920b8252519081900360200190f35b610191612b88565b61080a612bac565b6040805162ffffff9092168252519081900360200190f35b610433612bd0565b61084a6004803603602081101561084057600080fd5b503560020b612bd6565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b61032d600480360360208110156108c257600080fd5b50356001600160a01b0316612c42565b7f0000000000000000000000000ab8d01664d4bb625705f9f3c595a8a19b3dcfb081565b60008085610930576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b9004909116608082015260015463ffffffff811660a083015260ff600160201b90910416151560c082018190526109e8576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a335780600001516001600160a01b0316866001600160a01b0316118015610a2e575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a65565b80600001516001600160a01b0316866001600160a01b0316108015610a6557506401000276a36001600160a01b038716115b610a9c576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6001805460ff60201b191690556040805160c08101909152600090808a610ad15760108460a0015163ffffffff16901c610adb565b60a084015161ffff165b63ffffffff1681526005546001600160801b03166020820152604001610aff612e29565b63ffffffff1681526000602082018190526040820181905260609091015262010008549091506001600160a01b031615610ba557620100085460408083015181516310a537f160e11b815263ffffffff909116600482015290516001600160a01b039092169163214a6fe29160248082019260009290919082900301818387803b158015610b8c57600080fd5b505af1158015610ba0573d6000803e3d6000fd5b505050505b6000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610bf357600354610bf7565b6002545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610c465750886001600160a01b031681604001516001600160a01b031614155b156110b557610c5361573a565b60408201516001600160a01b031681526060820151610c96906007907f000000000000000000000000000000000000000000000000000000000000000a8f612e2d565b15156040830152600290810b810b60208301819052620d89e719910b1215610cc757620d89e7196020820152610ce6565b6020810151620d89e860029190910b1315610ce657620d89e860208201525b610cf38160200151612f6f565b6001600160a01b031660608201526040820151610d84908d610d2d578b6001600160a01b031683606001516001600160a01b031611610d47565b8b6001600160a01b031683606001516001600160a01b0316105b610d55578260600151610d57565b8b5b60c085015185517f00000000000000000000000000000000000000000000000000000000000001f4613296565b60c085015260a084015260808301526001600160a01b031660408301528215610de657610dba8160c00151826080015101613488565b825103825260a0810151610ddc90610dd190613488565b60208401519061349e565b6020830152610e21565b610df38160a00151613488565b825101825260c08101516080820151610e1b91610e109101613488565b6020840151906134ba565b60208301525b835163ffffffff1615610e81576000612710610e54866000015163ffffffff168460c001516134d090919063ffffffff16565b81610e5b57fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610ec057610eb48160c00151600160801b8460c001516001600160801b03166134f4565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b031614156110745780604001511561104b578360a00151610f4a57610f28846040015160008760200151886040015188602001518a6060015160096135a4909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b62010008546001600160a01b031615610fd557620100085460208201516040805163a498463360e01b815260029290920b60048301528e15156024830152516001600160a01b039092169163a49846339160448082019260009290919082900301818387803b158015610fbc57600080fd5b505af1158015610fd0573d6000803e3d6000fd5b505050505b600061102182602001518e610fec57600254610ff2565b84608001515b8f611001578560800151611005565b6003545b608089015160608a015160408b01516006959493929190613736565b90508c1561102d576000035b61103b8360c00151826137f0565b6001600160801b031660c0840152505b8b61105a578060200151611063565b60018160200151035b600290810b900b60608301526110af565b80600001516001600160a01b031682604001516001600160a01b0316146110af576110a282604001516138a6565b600290810b900b60608301525b50610c20565b836020015160020b816060015160020b146111835760008061110386604001518660400151886020015188602001518a606001518b608001516009613ba5909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b9390931692909202919091176001600160a01b0319166001600160a01b03909116179055506111a89050565b6040810151600080546001600160a01b0319166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146111ee5760c0810151600580546001600160801b0319166001600160801b039092169190911790555b6000808c1561124857608083015160025560a08301516001600160801b03161561123c5760a0830151600480546001600160801b031981166001600160801b03918216909301169190911790555b8260a001519150611295565b608083015160035560a08301516001600160801b03161561128e5760a0830151600480546001600160801b03808216600160801b92839004821690940116029190911790555b5060a08201515b8315158d1515146112ae57602083015183518d036112bb565b82600001518c0383602001515b90985096508c156113f45760008712156112fd576112fd7f0000000000000000000000005fc5360d0400a0fd4f2af552add042d716f1d1688f89600003613d2b565b6000611307613e79565b9050336001600160a01b03166323a69e758a8a8e8e6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561138b57600080fd5b505af115801561139f573d6000803e3d6000fd5b505050506113ab613e79565b6113b5828b613fb2565b11156113ee576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b5061151e565b600088121561142b5761142b7f0000000000000000000000000ab8d01664d4bb625705f9f3c595a8a19b3dcfb08f8a600003613d2b565b6000611435613fc2565b9050336001600160a01b03166323a69e758a8a8e8e6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156114b957600080fd5b505af11580156114cd573d6000803e3d6000fd5b505050506114d9613fc2565b6114e3828a613fb2565b111561151c576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b8d6001600160a01b0316336001600160a01b03167f19b47279256b2a23a1665c810c8d55a1758940ee09377d4f8d26497a3577dc838a8a87604001518860c001518960600151898960405180888152602001878152602001866001600160a01b03168152602001856001600160801b031681526020018460020b8152602001836001600160801b03168152602001826001600160801b0316815260200197505050505050505060405180910390a350506001805460ff60201b1916600160201b17905550939a92995091975050505050505050565b6005546001600160801b031681565b6004546001600160801b0380821691600160801b90041682565b60098161ffff811061162d57600080fd5b015463ffffffff81169150600160201b810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600154600160201b900460ff166116a5576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6001805460ff60201b1916905560008054600160d81b900461ffff16906116ce6009838561405a565b6000805461ffff808416600160d81b810261ffff60d81b199093169290921790925591925083161461173b576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506001805460ff60201b1916600160201b17905550565b6000546001546001600160a01b03821691600160a01b810460020b9161ffff600160b81b8304811692600160c81b8104821692600160d81b9091049091169063ffffffff81169060ff600160201b9091041687565b6001546000908190600160201b900460ff166117f1576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6001805460ff60201b191690556001600160801b03851661181157600080fd5b60008061185f60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016118558a6001600160801b03166140fd565b600f0b905261410e565b925092505081935080925060008060008611156118815761187e613e79565b91505b84156118925761188f613fc2565b90505b336001600160a01b03166399eee9d087878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561191457600080fd5b505af1158015611928573d6000803e3d6000fd5b50505050600086111561197f5761193d613e79565b6119478388613fb2565b111561197f576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b84156119cf5761198d613fc2565b6119978287613fb2565b11156119cf576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506001805460ff60201b1916600160201b17905550919890975095505050505050565b60035481565b600154600160201b900460ff16611ab0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6001805460ff60201b191690556005546001600160801b031680611aff576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b6000611b34867f00000000000000000000000000000000000000000000000000000000000001f462ffffff16620f4240614344565b90506000611b6b867f00000000000000000000000000000000000000000000000000000000000001f462ffffff16620f4240614344565b90506000611b77613e79565b90506000611b83613fc2565b90508815611bb657611bb67f0000000000000000000000000ab8d01664d4bb625705f9f3c595a8a19b3dcfb08b8b613d2b565b8715611be757611be77f0000000000000000000000005fc5360d0400a0fd4f2af552add042d716f1d1688b8a613d2b565b336001600160a01b031663a1d4833685858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611c6957600080fd5b505af1158015611c7d573d6000803e3d6000fd5b505050506000611c8b613e79565b90506000611c97613fc2565b905081611ca48588613fb2565b1115611cdc576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611ce78487613fb2565b1115611d1f576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611da85760015461ffff1660008115611d4c5761271063ffffffff8316850204611d4f565b60005b90506001600160801b03811615611d8257600480546001600160801b038082168401166001600160801b03199091161790555b611d9c818503600160801b8d6001600160801b03166134f4565b60028054909101905550505b8015611e2d5760015460101c61ffff1660008115611dd25761271063ffffffff8316840204611dd5565b60005b90506001600160801b03811615611e0757600480546001600160801b03600160801b8083048216850182160291161790555b611e21818403600160801b8d6001600160801b03166134f4565b60038054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506001805460ff60201b1916600160201b179055505050505050505050505050565b6001546000908190600160201b900460ff16611efc576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6001805460ff60201b191690556000611f18600833898961437e565b60038101549091506001600160801b0390811690861611611f395784611f48565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611f705783611f86565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611feb576003810180546001600160801b031981166001600160801b03918216869003821617909155611feb907f0000000000000000000000000ab8d01664d4bb625705f9f3c595a8a19b3dcfb0908a908616613d2b565b6001600160801b03821615612051576003810180546001600160801b03600160801b808304821686900382160291811691909117909155612051907f0000000000000000000000005fc5360d0400a0fd4f2af552add042d716f1d168908a908516613d2b565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506001805460ff60201b1916600160201b17905590969095509350505050565b60086020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60076020526000908152604090205481565b62010008546001600160a01b031681565b7f0000000000000000000000000000000000005e8b2285f864419ac400be90719681565b6001546000908190600160201b900460ff1661219e576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6001805460ff60201b19169055336001600160a01b037f000000000000000000000000ece6ecd61177336ea6fb9b17937ac439d85ee20b16148061226e57507f000000000000000000000000ece6ecd61177336ea6fb9b17937ac439d85ee20b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561223657600080fd5b505afa15801561224a573d6000803e3d6000fd5b505050506040513d602081101561226057600080fd5b50516001600160a01b031633145b61227757600080fd5b6004546001600160801b039081169085161161229357836122a0565b6004546001600160801b03165b6004549092506001600160801b03600160801b9091048116908416116122c657826122da565b600454600160801b90046001600160801b03165b90506001600160801b0382161561235b576004546001600160801b038381169116141561230957600019909101905b600480546001600160801b031981166001600160801b0391821685900382161790915561235b907f0000000000000000000000000ab8d01664d4bb625705f9f3c595a8a19b3dcfb09087908516613d2b565b6001600160801b038116156123e1576004546001600160801b03828116600160801b90920416141561238c57600019015b600480546001600160801b03600160801b8083048216859003821602918116919091179091556123e1907f0000000000000000000000005fc5360d0400a0fd4f2af552add042d716f1d1689087908416613d2b565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36001805460ff60201b1916600160201b1790559094909350915050565b6060806124ca61245e612e29565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600554600996959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b9004166143e2565b915091509250929050565b6001546000908190600160201b900460ff1661251e576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6001805460ff60201b1916905560408051608081018252338152600287810b602083015286900b918101919091526000908190819061257a906060810161256d6001600160801b038a166140fd565b600003600f0b905261410e565b925092509250816000039450806000039350600085118061259b5750600084115b156125da576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506001805460ff60201b1916600160201b179055509094909350915050565b6000806000612660858561453c565b600285810b810b600090815260066020819052604080832088850b90940b8352822060038401549182900b93600160381b83046001600160a01b0316928492600160d81b820463ffffffff16928492909190600160f81b900460ff16806126c657600080fd5b6003820154600681900b9850600160381b81046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff168061270757600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b909204909316608083015260015463ffffffff811660a084015260ff600160201b90910416151560c08301529093508e820b910b121590506127af57509390940396509003935090039050612832565b8a60020b816020015160020b12156128235760006127cb612e29565b6020830151604084015160055460608601519394506000938493612801936009938893879392916001600160801b0316906135a4565b9a9003989098039b505094909603929092039650909103039250612832915050565b50949093039650039350900390505b9250925092565b600154600160201b900460ff1661287d576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6001805460ff60201b19169055336001600160a01b037f000000000000000000000000ece6ecd61177336ea6fb9b17937ac439d85ee20b16148061294d57507f000000000000000000000000ece6ecd61177336ea6fb9b17937ac439d85ee20b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561291557600080fd5b505afa158015612929573d6000803e3d6000fd5b505050506040513d602081101561293f57600080fd5b50516001600160a01b031633145b61295657600080fd5b6127108263ffffffff161115801561297657506127108163ffffffff1611155b61297f57600080fd5b6001805465ffffffff0000601084901b16840163ffffffff90811663ffffffff19831617909255167fb3159fed3ddfba67bae294599eafe2d0ec98c08bb38e0e5fb87d33154b6e05aa62010000826040805163ffffffff939092068316825261ffff601086901c16602083015286831682820152918516606082015290519081900360800190a150506001805460ff60201b1916600160201b17905550565b7f000000000000000000000000ece6ecd61177336ea6fb9b17937ac439d85ee20b81565b336001600160a01b037f000000000000000000000000ece6ecd61177336ea6fb9b17937ac439d85ee20b161480612b0557507f000000000000000000000000ece6ecd61177336ea6fb9b17937ac439d85ee20b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612acd57600080fd5b505afa158015612ae1573d6000803e3d6000fd5b505050506040513d6020811015612af757600080fd5b50516001600160a01b031633145b612b0e57600080fd5b6201000880546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f29983690a85a11696ce8a357993744f8d5a74fde14653e517cc2f8608a7235e99181900360200190a150565b7f000000000000000000000000000000000000000000000000000000000000000a81565b7f0000000000000000000000005fc5360d0400a0fd4f2af552add042d716f1d16881565b7f00000000000000000000000000000000000000000000000000000000000001f481565b60025481565b60066020819052600091825260409091208054600182015460028301546003909301546001600160801b03831694600160801b909304600f0b93919281900b90600160381b81046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612c85576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612c90826138a6565b9050600080612ca8612ca0612e29565b600990614605565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff89811660608801819052908916608088018190526303e803e860a08901819052600160c090990189905283546001600160a01b031916881762ffffff60a01b1916600160a01b62ffffff9888900b98909816979097029690961763ffffffff60b81b1916600160c81b9092029190911761ffff60d81b1916600160d81b9091021790558454600160201b63ffffffff1990911690931760ff60201b191692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612dd257fe5b05029050600083600281900b620d89e881612de957fe5b0502905060008460020b83830360020b81612e0057fe5b0560010190508062ffffff166001600160801b03801681612e1d57fe5b0493505050505b919050565b4290565b60008060008460020b8660020b81612e4157fe5b05905060008660020b128015612e6857508460020b8660020b81612e6157fe5b0760020b15155b15612e7257600019015b8315612ee757600080612e8483614651565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612ec957888360ff16860302612edc565b88612ed382614663565b840360ff168603025b965050505050612f65565b600080612ef683600101614651565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612f4857888360ff0360ff16866001010102612f5e565b8883612f53836146fd565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612f86578260020b612f8e565b8260020b6000035b9050620d89e8811115612fcc576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612fe057600160801b612ff2565b6ffffcb933bd6fad37aa2d162d1a5940015b6001600160881b03169050600282161561301c576ffff97272373d413259a46990580e213a0260801c5b600482161561303b576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b600882161561305a576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615613079576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615613098576fff973b41fa98c081472e6896dfb254c00260801c5b60408216156130b7576fff2ea16466c96a3843ec78b326b528610260801c5b60808216156130d6576ffe5dee046a99a2a811c461f1969c30530260801c5b6101008216156130f6576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615613116576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615613136576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615613156576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615613176576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615613196576fa9f746462d870fdf8a65dc1f90e061e50260801c5b6140008216156131b6576f70d869a156d2a1b890bb3df62baf32f70260801c5b6180008216156131d6576f31be135f97d08fd981231505542fcfa60260801c5b620100008216156131f7576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615613217576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615613236576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615613253576b048a170391f7dc42444e8fa20260801c5b60008460020b131561326e57806000198161326a57fe5b0490505b600160201b810615613281576001613284565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a16101581871280159061331b5760006132cf8989620f42400362ffffff16620f42406134f4565b9050826132e8576132e38c8c8c60016147e7565b6132f5565b6132f58b8d8c6001614862565b9550858110613306578a9650613315565b6133128c8b838661490d565b96505b50613365565b816133325761332d8b8b8b6000614862565b61333f565b61333f8a8c8b60006147e7565b935083886000031061335357899550613365565b6133628b8a8a60000385614959565b95505b6001600160a01b038a81169087161482156133c8578080156133845750815b61339a57613395878d8c6001614862565b61339c565b855b95508080156133a9575081155b6133bf576133ba878d8c60006147e7565b6133c1565b845b9450613412565b8080156133d25750815b6133e8576133e38c888c60016147e7565b6133ea565b855b95508080156133f7575081155b61340d576134088c888c6000614862565b61340f565b845b94505b8115801561342257508860000385115b1561342e578860000394505b81801561344d57508a6001600160a01b0316876001600160a01b031614155b1561345c578589039350613479565b613476868962ffffff168a620f42400362ffffff16614344565b93505b50505095509550955095915050565b6000600160ff1b821061349a57600080fd5b5090565b808203828113156000831215146134b457600080fd5b92915050565b818101828112156000831215146134b457600080fd5b60008215806134eb575050818102818382816134e857fe5b04145b6134b457600080fd5b600080806000198587098686029250828110908390030390508061352a576000841161351f57600080fd5b50829004905061359d565b80841161353657600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff871661364a576000898661ffff1661ffff81106135c557fe5b60408051608081018252919092015463ffffffff808216808452600160201b8304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461363657613633818a89886149a5565b90505b80602001518160400151925092505061372a565b86880360008061365f8c8c858c8c8c8c614a48565b91509150816000015163ffffffff168363ffffffff16141561369157816020015182604001519450945050505061372a565b805163ffffffff848116911614156136b957806020015181604001519450945050505061372a565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816136e757fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b0316028161371957fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b03600160381b808504821690960316909402600160381b600160d81b031990921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561385557826001600160801b03168260000384039150816001600160801b031610613850576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6134b4565b826001600160801b03168284019150816001600160801b031610156134b4576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906138e2575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613917576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b640100000000600160c01b03602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106139ab57607f810383901c91506139b5565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c6001603f1b161760c19b909b1c6001603e1b169a909a1760c29990991c6001603d1b169890981760c39790971c6001603c1b169690961760c49590951c6001603b1b169490941760c59390931c6001603a1b169290921760c69190911c600160391b161760c79190911c600160381b161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b14613b9657886001600160a01b0316613b7a82612f6f565b6001600160a01b03161115613b8f5781613b91565b805b613b98565b815b9998505050505050505050565b6000806000898961ffff1661ffff8110613bbb57fe5b60408051608081018252919092015463ffffffff808216808452600160201b8304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613c2a578885925092505061372a565b8461ffff168461ffff16118015613c4b57506001850361ffff168961ffff16145b15613c5857839150613c5c565b8491505b8161ffff168960010161ffff1681613c7057fe5b069250613c7f818989896149a5565b8a8461ffff1661ffff8110613c9057fe5b825191018054602084015160408501516060909501511515600160f81b026001600160f81b036001600160a01b03909616600160581b02600160581b600160f81b031960069390930b66ffffffffffffff16600160201b026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613da75780518252601f199092019160209182019101613d88565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613e09576040519150601f19603f3d011682016040523d82523d6000602084013e613e0e565b606091505b5091509150818015613e3c575080511580613e3c5750808060200190516020811015613e3957600080fd5b50515b613e72576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f0000000000000000000000000ab8d01664d4bb625705f9f3c595a8a19b3dcfb01693919290918291908083835b60208310613f125780518252601f199092019160209182019101613ef3565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613f72576040519150601f19603f3d011682016040523d82523d6000602084013e613f77565b606091505b5091509150818015613f8b57506020815110155b613f9457600080fd5b808060200190516020811015613fa957600080fd5b50519250505090565b808201828110156134b457600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f0000000000000000000000005fc5360d0400a0fd4f2af552add042d716f1d16816939192909182919080838360208310613f125780518252601f199092019160209182019101613ef3565b6000808361ffff1611614098576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff16116140ae57508161359d565b825b8261ffff168161ffff1610156140f4576001858261ffff1661ffff81106140d357fe5b01805463ffffffff191663ffffffff929092169190911790556001016140b0565b50909392505050565b80600f81900b8114612e2457600080fd5b60008060006141258460200151856040015161453c565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b90940416608085015260015463ffffffff811660a086015260ff600160201b90910416151560c0850152885190890151948901519289015193946141c79491939092909190614c42565b93508460600151600f0b60001461433c57846020015160020b816020015160020b121561421c576142156141fe8660200151612f6f565b61420b8760400151612f6f565b8760600151614df7565b925061433c565b846040015160020b816020015160020b12156143125760055460408201516001600160801b039091169061426e90614252612e29565b6020850151606086015160808701516009949392918791613ba5565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b9390921692909202179055815160408701516142be91906142b490612f6f565b8860600151614df7565b93506142dc6142d08760200151612f6f565b83516060890151614e3b565b92506142ec8187606001516137f0565b600580546001600160801b0319166001600160801b03929092169190911790555061433c565b6143396143228660200151612f6f565b61432f8760400151612f6f565b8760600151614e3b565b91505b509193909250565b60006143518484846134f4565b90506000828061435d57fe5b848609111561359d57600019811061437457600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614422576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561443a57600080fd5b50604051908082528060200260200182016040528015614464578160200160208202803683370190505b509150865167ffffffffffffffff8111801561447f57600080fd5b506040519080825280602002602001820160405280156144a9578160200160208202803683370190505b50905060005b875181101561452f576144da8a8a8a84815181106144c957fe5b60200260200101518a8a8a8a6135a4565b8483815181106144e657fe5b602002602001018484815181106144f957fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b815250505080806001019150506144af565b5097509795505050505050565b8060020b8260020b1261457c576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b12156145bf576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614601576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b600080821161467157600080fd5b600160801b821061468457608091821c91015b600160401b821061469757604091821c91015b600160201b82106146aa57602091821c91015b6201000082106146bc57601091821c91015b61010082106146cd57600891821c91015b601082106146dd57600491821c91015b600482106146ed57600291821c91015b60028210612e2457600101919050565b600080821161470b57600080fd5b5060ff6001600160801b0382161561472657607f190161472e565b608082901c91505b67ffffffffffffffff82161561474757603f190161474f565b604082901c91505b63ffffffff82161561476457601f190161476c565b602082901c91505b61ffff82161561477f57600f1901614787565b601082901c91505b60ff82161561479957600719016147a1565b600882901c91505b600f8216156147b357600319016147bb565b600482901c91505b60038216156147cd57600119016147d5565b600282901c91505b6001821615612e245760001901919050565b6000836001600160a01b0316856001600160a01b03161115614807579293925b816148345761482f836001600160801b03168686036001600160a01b0316600160601b6134f4565b614857565b614857836001600160801b03168686036001600160a01b0316600160601b614344565b90505b949350505050565b6000836001600160a01b0316856001600160a01b03161115614882579293925b600160601b600160e01b03606084901b166001600160a01b0386860381169087166148ac57600080fd5b836148dc57866001600160a01b03166148cf8383896001600160a01b03166134f4565b816148d657fe5b04614902565b6149026148f38383896001600160a01b0316614344565b886001600160a01b0316614e6a565b979650505050505050565b600080856001600160a01b03161161492457600080fd5b6000846001600160801b03161161493a57600080fd5b8161494c5761482f8585856001614e75565b6148578585856001614f56565b600080856001600160a01b03161161497057600080fd5b6000846001600160801b03161161498657600080fd5b816149985761482f8585856000614f56565b6148578585856000614e75565b6149ad615776565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b031611614a01576001614a03565b845b6001600160801b031663ffffffff60801b608085901b1681614a2157fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b614a50615776565b614a58615776565b888561ffff1661ffff8110614a6957fe5b60408051608081018252919092015463ffffffff8116808352600160201b8204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff16151560608201529250614acd90899089615039565b15614b05578663ffffffff16826000015163ffffffff161415614aef5761372a565b81614afc838989886149a5565b9150915061372a565b888361ffff168660010161ffff1681614b1a57fe5b0661ffff1661ffff8110614b2a57fe5b60408051608081018252929091015463ffffffff81168352600160201b8104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614bdf57604080516080810182528a5463ffffffff81168252600160201b8104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614bee88836000015189615039565b614c25576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614c3289898988876150fa565b9150915097509795505050505050565b6000614c51600887878761437e565b60025460035491925090600080600f87900b15614d97576000614c72612e29565b6000805460055492935090918291614cbc9160099186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b9004166135a4565b9092509050614cf660068d8b8d8b8b87898b60007f0000000000000000000000000000000000005e8b2285f864419ac400be907196615298565b9450614d2d60068c8b8d8b8b87898b60017f0000000000000000000000000000000000005e8b2285f864419ac400be907196615298565b93508415614d6157614d6160078d7f000000000000000000000000000000000000000000000000000000000000000a615451565b8315614d9357614d9360078c7f000000000000000000000000000000000000000000000000000000000000000a615451565b5050505b600080614da960068c8c8b8a8a6154b7565b9092509050614dba878a8484615563565b600089600f0b1215614de8578315614dd757614dd760068c6156f8565b8215614de857614de860068b6156f8565b50505050505095945050505050565b60008082600f0b12614e1d57614e18614e138585856001614862565b613488565b61485a565b614e30614e138585856000036000614862565b600003949350505050565b60008082600f0b12614e5757614e18614e1385858560016147e7565b614e30614e1385858560000360006147e7565b808204910615150190565b60008115614ee85760006001600160a01b03841115614eab57614ea684600160601b876001600160801b03166134f4565b614ec3565b6001600160801b038516606085901b81614ec157fe5b045b9050614ee0614edb6001600160a01b03881683613fb2565b615724565b91505061485a565b60006001600160a01b03841115614f1657614f1184600160601b876001600160801b0316614344565b614f2d565b614f2d606085901b6001600160801b038716614e6a565b905080866001600160a01b031611614f4457600080fd5b6001600160a01b03861603905061485a565b600082614f6457508361485a565b600160601b600160e01b03606085901b168215614ff2576001600160a01b03861684810290858281614f9257fe5b041415614fc357818101828110614fc157614fb783896001600160a01b031683614344565b935050505061485a565b505b614fe982614fe4878a6001600160a01b03168681614fdd57fe5b0490613fb2565b614e6a565b9250505061485a565b6001600160a01b0386168481029085828161500957fe5b0414801561501657508082115b61501f57600080fd5b808203614fb7614edb846001600160a01b038b1684614344565b60008363ffffffff168363ffffffff161115801561506357508363ffffffff168263ffffffff1611155b1561507f578163ffffffff168363ffffffff161115905061359d565b60008463ffffffff168463ffffffff16116150a6578363ffffffff16600160201b016150ae565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff16116150de578363ffffffff16600160201b016150e6565b8363ffffffff165b64ffffffffff169091111595945050505050565b615102615776565b61510a615776565b60008361ffff168560010161ffff168161512057fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff8716828161514d57fe5b0661ffff811061515957fe5b60408051608081018252929091015463ffffffff81168352600160201b8104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082018190529095506151c357806001019250615138565b898661ffff1682600101816151d457fe5b0661ffff81106151e057fe5b60408051608081018252929091015463ffffffff81168352600160201b8104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820152855190945060009061524a908b908b615039565b905080801561526357506152638a8a8760000151615039565b1561526e575061528b565b8061527e57600182039250615285565b8160010193505b50615138565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b0316826152c3828d6137f0565b9050846001600160801b0316816001600160801b03161115615311576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b0382811615908216158114159450156153b6578c60020b8e60020b1361539e57600183018b9055600283018a9055600383018054600160381b600160d81b031916600160381b6001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180546001600160f81b0316600160f81b1790555b82546001600160801b0319166001600160801b038216178355856153ff5782546153fa906153f590600160801b9004600f90810b810b908f900b6134ba565b6140fd565b615420565b8254615420906153f590600160801b9004600f90810b810b908f900b61349e565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161546057fe5b0760020b1561546e57600080fd5b6000806154898360020b8560020b8161548357fe5b05614651565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126154fd57505060018201546002830154615510565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561553257505060018301546002840154615545565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6156025781516001600160801b03166155fa576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b508051615611565b815161560e90866137f0565b90505b60006156358360200151860384600001516001600160801b0316600160801b6134f4565b9050600061565b8460400151860385600001516001600160801b0316600160801b6134f4565b905086600f0b6000146156825787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b0382161515806156b057506000816001600160801b0316115b156156ee576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612e2457600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000a
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| Globals Dollars (USDG) | USDG | 29 | $1 | $29 |
| Global Dollar (USDG) | USDG | 14 | $1 | $14 |
| Universal Stable Digital Coin (USDC) | USDC | 6 | $1 | $6 |
| Global Dollar (USDG) | USDG | 5 | $1 | $5 |
| global dollar (USDG) | USDG | 5 | $1 | $5 |
Global Dollar (USDG) | USDG | 0.000081 | $0.994 | $0 |
| Sushidog (Sushidog) | Sushidog | 30 | — | — |
| Cash Cat (CASHCAT) | CASHCAT | 16 | — | — |
| World Usdg (WORLD) | WORLD | 10 | — | — |
| sushicat | 0.000000 | — | — |
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x793544…778abf | 2 days agoThu, 13 Aug 2026 11:26:44 UTC | 0x596b57…b151 | [0] 0x000000000000…d85ee20b [1] 0x000000000000…54657024 data: 0x000000000000000000…0000586e |
| 0x02f0d2…4727c7 | 3 days agoWed, 12 Aug 2026 01:20:10 UTC | 0x709353…a9c0 | [0] 0x000000000000…aa96f641 [1] 0xffffffffffff…fffa9a8e [2] 0xffffffffffff…fffab2c6 data: 0x000000000000000000…0570663a |
| 0x02f0d2…4727c7 | 3 days agoWed, 12 Aug 2026 01:20:10 UTC | 0x0c396c…982c | [0] 0x000000000000…aa96f641 [1] 0xffffffffffff…fffa9a8e [2] 0xffffffffffff…fffab2c6 data: 0x000000000000000000…056d6374 |
| 0x0581d3…83dda1 | 3 days agoWed, 12 Aug 2026 01:19:43 UTC | 0x709353…a9c0 | [0] 0x000000000000…aa96f641 [1] 0xffffffffffff…fffaa150 [2] 0xffffffffffff…fffaa696 data: 0x000000000000000000…0099a2ba |
| 0x0581d3…83dda1 | 3 days agoWed, 12 Aug 2026 01:19:43 UTC | 0x0c396c…982c | [0] 0x000000000000…aa96f641 [1] 0xffffffffffff…fffaa150 [2] 0xffffffffffff…fffaa696 data: 0x000000000000000000…00998751 |
| 0x8f3b38…066891 | 4 days agoTue, 11 Aug 2026 21:48:36 UTC | 0x19b472…dc83 | [0] 0x000000000000…165d125f [1] 0x000000000000…7846e13f data: 0xffffffffffffffffff…00000007 |
| 0x91d310…3080c9 | 4 days agoTue, 11 Aug 2026 21:44:15 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0xffffffffffffffffff…0000004a |
| 0x1fa8aa…c5554a | 4 days agoTue, 11 Aug 2026 21:42:32 UTC | 0x19b472…dc83 | [0] 0x000000000000…2fc7bb89 [1] 0x000000000000…2fc7bb89 data: 0xffffffffffffffffff…000000f0 |
| 0xec527b…90d6bd | 4 days agoTue, 11 Aug 2026 21:42:20 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0xffffffffffffffffff…00000062 |
| 0x7a8061…0b351d | 4 days agoTue, 11 Aug 2026 21:41:55 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0x000000000000000000…00000000 |
| 0x2f937d…65cea6 | 4 days agoTue, 11 Aug 2026 21:41:48 UTC | 0x19b472…dc83 | [0] 0x000000000000…8cec1331 [1] 0x000000000000…8cec1331 data: 0xffffffffffffffffff…00000085 |
| 0x7a857d…ceea82 | 4 days agoTue, 11 Aug 2026 21:38:28 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…ec4fff4f data: 0xffffffffffffffffff…0000005f |
| 0xdb0c49…9be81b | 4 days agoTue, 11 Aug 2026 21:37:49 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0x000000000000000000…00000000 |
| 0xba062f…db0f69 | 4 days agoTue, 11 Aug 2026 21:37:41 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0xffffffffffffffffff…0000007c |
| 0xce66de…918fde | 4 days agoTue, 11 Aug 2026 21:36:43 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0x000000000000000000…00000000 |
| 0xd6f5cd…bfb502 | 4 days agoTue, 11 Aug 2026 21:35:15 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…ec4fff4f data: 0xffffffffffffffffff…0000005f |
| 0xcb2efb…4a8222 | 4 days agoTue, 11 Aug 2026 21:34:31 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0x000000000000000000…00000000 |
| 0x9d6ad4…a7ea22 | 4 days agoTue, 11 Aug 2026 21:34:16 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0xffffffffffffffffff…00000071 |
| 0x76bfb7…ebc34c | 4 days agoTue, 11 Aug 2026 21:32:05 UTC | 0x19b472…dc83 | [0] 0x000000000000…8376dd7b [1] 0x000000000000…8376dd7b data: 0x000000000000000000…00000000 |
| 0x7b3cdf…3a2918 | 4 days agoTue, 11 Aug 2026 21:31:59 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0xffffffffffffffffff…00000094 |
| 0xb9b5bb…f06ab7 | 4 days agoTue, 11 Aug 2026 21:31:27 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0x000000000000000000…00000000 |
| 0x49f7bd…a0cbf9 | 4 days agoTue, 11 Aug 2026 21:30:04 UTC | 0x19b472…dc83 | [0] 0x000000000000…8376dd7b [1] 0x000000000000…8376dd7b data: 0x000000000000000000…00000000 |
| 0x6e7102…68365f | 4 days agoTue, 11 Aug 2026 21:09:16 UTC | 0x19b472…dc83 | [0] 0x000000000000…20cbbe5f [1] 0x000000000000…20cbbe5f data: 0xffffffffffffffffff…0000001a |
| 0x8a4292…194b35 | 4 days agoTue, 11 Aug 2026 21:05:58 UTC | 0x19b472…dc83 | [0] 0x000000000000…8376dd7b [1] 0x000000000000…8376dd7b data: 0xffffffffffffffffff…000001b8 |
| 0x1b3513…3a0b3b | 4 days agoTue, 11 Aug 2026 21:05:30 UTC | 0x19b472…dc83 | [0] 0x000000000000…8376dd7b [1] 0x000000000000…8376dd7b data: 0x000000000000000000…00000000 |
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| No direct transactions — this address is only ever reached via internal calls (common for a contract only invoked through a router or proxy). View Internal Transactions → | |||||||||
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x79354479…778abf | Transfer | 35,353,527 | 2 days agoThu, 13 Aug 2026 11:26:44 UTC | 0x6ade…a044 | OUT | 0x35a3…7024 | $0.020.022638 USDG | Global Dollar (USDG) | |
| 0x79354479…778abf | Transfer | 35,353,527 | 2 days agoThu, 13 Aug 2026 11:26:44 UTC | 0x6ade…a044 | OUT | 0x35a3…7024 | 27.761263 sushicat | ||
| 0x8b5a0d0d…45e8fd | Transfer | 34,694,209 | 3 days agoWed, 12 Aug 2026 17:05:05 UTC | 0x3d2b…6bfc | IN | 0x6ade…a044 | 5 USDG | global dollar (USDG) | |
| 0x344e12af…a9b709 | Transfer | 34,663,579 | 3 days agoWed, 12 Aug 2026 16:13:57 UTC | 0x602e…7bd0 | IN | 0x6ade…a044 | 3 USDG | Global Dollar (USDG) | |
| 0x572cd28d…1fd6b9 | Transfer | 34,352,341 | 3 days agoWed, 12 Aug 2026 07:36:14 UTC | 0x602e…7bd0 | IN | 0x6ade…a044 | 2 USDG | Global Dollar (USDG) | |
| 0x02f0d25a…4727c7 | Transfer | 34,125,972 | 3 days agoWed, 12 Aug 2026 01:20:10 UTC | 0x6ade…a044 | OUT | 0xf8af…5029 | $90.7191.252282 USDG | Global Dollar (USDG) | |
| 0x02f0d25a…4727c7 | Transfer | 34,125,972 | 3 days agoWed, 12 Aug 2026 01:20:10 UTC | 0x6ade…a044 | OUT | 0xf8af…5029 | 237.852811 sushicat | ||
| 0x0581d395…83dda1 | Transfer | 34,125,712 | 3 days agoWed, 12 Aug 2026 01:19:43 UTC | 0x6ade…a044 | OUT | 0xf8af…5029 | $10.0110.068666 USDG | Global Dollar (USDG) | |
| 0x0581d395…83dda1 | Transfer | 34,125,712 | 3 days agoWed, 12 Aug 2026 01:19:43 UTC | 0x6ade…a044 | OUT | 0xf8af…5029 | 12.114894 sushicat | ||
| 0x97934def…fcc76a | Transfer | 34,085,145 | 3 days agoWed, 12 Aug 2026 00:12:34 UTC | 0x8c94…ec08 | IN | 0x6ade…a044 | 14 USDG | Global Dollar (USDG) | |
| 0xac1db970…ec518b | Transfer | 34,012,419 | 4 days agoTue, 11 Aug 2026 22:12:14 UTC | 0x8cc7…53bb | IN | 0x6ade…a044 | 16 CASHCAT | Cash Cat (CASHCAT) | |
| 0x8f3b38cc…066891 | Transfer | 33,998,186 | 4 days agoTue, 11 Aug 2026 21:48:36 UTC | 0x2ca3…125f | IN | 0x6ade…a044 | $0.140.143494 USDG | Global Dollar (USDG) | |
| 0x8f3b38cc…066891 | Transfer | 33,998,186 | 4 days agoTue, 11 Aug 2026 21:48:36 UTC | 0x6ade…a044 | OUT | 0x48a0…e13f | 176.037718 sushicat | ||
| 0x91d3108f…3080c9 | Transfer | 33,995,589 | 4 days agoTue, 11 Aug 2026 21:44:15 UTC | 0x39b3…be5f | IN | 0x6ade…a044 | $1.471.483446 USDG | Global Dollar (USDG) | |
| 0x91d3108f…3080c9 | Transfer | 33,995,589 | 4 days agoTue, 11 Aug 2026 21:44:15 UTC | 0x6ade…a044 | OUT | 0x39b3…be5f | 1,828.591233 sushicat | ||
| 0x1fa8aa74…c5554a | Transfer | 33,994,536 | 4 days agoTue, 11 Aug 2026 21:42:32 UTC | 0x0000…bb89 | IN | 0x6ade…a044 | $4.784.810822 USDG | Global Dollar (USDG) | |
| 0x1fa8aa74…c5554a | Transfer | 33,994,536 | 4 days agoTue, 11 Aug 2026 21:42:32 UTC | 0x6ade…a044 | OUT | 0x0000…bb89 | 6,041.434113 sushicat | ||
| 0xec527b20…90d6bd | Transfer | 33,994,418 | 4 days agoTue, 11 Aug 2026 21:42:20 UTC | 0x39b3…be5f | IN | 0x6ade…a044 | $1.961.974583 USDG | Global Dollar (USDG) | |
| 0xec527b20…90d6bd | Transfer | 33,994,418 | 4 days agoTue, 11 Aug 2026 21:42:20 UTC | 0x6ade…a044 | OUT | 0x39b3…be5f | 2,530.152943 sushicat | ||
| 0x7a80616f…0b351d | Transfer | 33,994,170 | 4 days agoTue, 11 Aug 2026 21:41:55 UTC | 0x39b3…be5f | IN | 0x6ade…a044 | 3,818.935154 sushicat | ||
| 0x7a80616f…0b351d | Transfer | 33,994,170 | 4 days agoTue, 11 Aug 2026 21:41:55 UTC | 0x6ade…a044 | OUT | 0x39b3…be5f | $2.972.98639 USDG | Global Dollar (USDG) | |
| 0x2f937dcc…65cea6 | Transfer | 33,994,094 | 4 days agoTue, 11 Aug 2026 21:41:48 UTC | 0x2387…1331 | IN | 0x6ade…a044 | $2.662.671911 USDG | Global Dollar (USDG) | |
| 0x2f937dcc…65cea6 | Transfer | 33,994,094 | 4 days agoTue, 11 Aug 2026 21:41:48 UTC | 0x6ade…a044 | OUT | 0x2387…1331 | 3,410.136696 sushicat | ||
| 0x7a857d90…ceea82 | Transfer | 33,992,110 | 4 days agoTue, 11 Aug 2026 21:38:28 UTC | 0xb92f…ff4f | IN | 0x6ade…a044 | $1.901.910538 USDG | Global Dollar (USDG) | |
| 0x7a857d90…ceea82 | Transfer | 33,992,110 | 4 days agoTue, 11 Aug 2026 21:38:28 UTC | 0x6ade…a044 | OUT | 0xb92f…ff4f | 2,472.080533 sushicat |
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 33,733,875 | 4 days agoTue, 11 Aug 2026 14:28:47 UTC | 0x866e1f…92af47 | CREATE2 | createAndInitializePoolIfNecessary | 0x5952…a57b | IN | 0x6ade…a044 | 0 ETH |