// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
import {LPFeeLibrary} from "@uniswap/v4-core/src/libraries/LPFeeLibrary.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {
BeforeSwapDelta,
BeforeSwapDeltaLibrary,
toBeforeSwapDelta
} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {BaseHook} from "@uniswap/v4-periphery/src/utils/BaseHook.sol";
import {IDegenSpyBuybackVault} from "../interfaces/IDegenSpyBuybackVault.sol";
import {IDegenSpyV1FeeLocker} from "../interfaces/IDegenSpyV1FeeLocker.sol";
import {IDegenSpyV2Hook} from "../interfaces/IDegenSpyV2Hook.sol";
import {DegenFeeMath} from "../libraries/DegenFeeMath.sol";
import {DegenSpyV2LaunchConstants} from "../libraries/DegenSpyV2LaunchConstants.sol";
/// @title SPY V4 V2 hook
/// @notice Uses raw SPY units and isolates global protocol buckets from creator accounting.
contract DegenSpyV2Hook is BaseHook, IDegenSpyV2Hook, IUnlockCallback, ReentrancyGuard {
using PoolIdLibrary for PoolKey;
using SafeERC20 for IERC20;
uint24 public constant LP_FEE = uint24(DegenSpyV2LaunchConstants.LP_FEE_RATE);
int24 public constant TICK_SPACING = DegenSpyV2LaunchConstants.TICK_SPACING;
int24 public constant INITIAL_TICK = DegenSpyV2LaunchConstants.INITIAL_TICK;
uint256 private constant ROBINHOOD_CHAIN_ID = 4663;
address private constant LIVE_POOL_MANAGER = 0x8366a39CC670B4001A1121B8F6A443A643e40951;
address private constant LIVE_V3_FACTORY = 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA;
address private constant LIVE_DEGEN = 0x04d5D8a61DA0b6548B136412843aDBA55EbeaDE6;
address private constant LIVE_SPY = 0x117cc2133c37B721F49dE2A7a74833232B3B4C0C;
address public immutable module;
address public immutable spy;
address public immutable operatingTreasury;
address public immutable buybackVault;
IDegenSpyV1FeeLocker public immutable feeLocker;
mapping(PoolId => PoolConfig) private _poolConfigs;
mapping(address => PoolId) private _poolIdsByToken;
mapping(PoolId => uint256) public totalRawSpyFeesAccrued;
mapping(PoolId => uint256) public totalTreasuryRawSpyAccrued;
mapping(PoolId => uint256) public totalBuybackRawSpyAccrued;
uint256 public pendingTreasuryRawSpy;
uint256 public pendingBuybackRawSpy;
uint256 public totalTreasuryRawSpySwept;
uint256 public totalBuybackRawSpySwept;
mapping(PoolId => mapping(address => uint256)) public pendingBeneficiaryRawSpy;
mapping(PoolId => uint256) public pendingBeneficiaryTotalRawSpy;
bool private _unlocking;
uint256 private _unlockTreasury;
uint256 private _unlockBuyback;
uint256 private _unlockCreator;
modifier onlyModule() {
if (msg.sender != module) revert OnlyModule();
_;
}
constructor(
IPoolManager manager,
address module_,
address spy_,
address operatingTreasury_,
address buybackVault_,
address feeLocker_
) BaseHook(manager) {
if (
address(manager) == address(0) || module_ == address(0) || spy_ == address(0)
|| spy_.code.length == 0 || operatingTreasury_ == address(0)
|| buybackVault_ == address(0)
) revert InvalidAddress();
if (
feeLocker_.code.length == 0 || IDegenSpyV1FeeLocker(feeLocker_).SPY() != spy_
|| IDegenSpyV1FeeLocker(feeLocker_).HOOK() != address(this)
) revert InvalidFeeLocker();
if (buybackVault_.code.length == 0) revert InvalidBuybackVault();
IDegenSpyBuybackVault vault = IDegenSpyBuybackVault(buybackVault_);
address vaultFactory = address(vault.v3Factory());
if (
vaultFactory == address(0) || vaultFactory.code.length == 0 || vault.spy() != spy_
|| vault.degen() == address(0) || vault.poolFee() != 10_000
|| vault.tickSpacing() != 200
|| vault.burnSink() != 0x000000000000000000000000000000000000dEaD
|| (block.chainid == ROBINHOOD_CHAIN_ID
&& (address(manager) != LIVE_POOL_MANAGER
|| spy_ != LIVE_SPY
|| vaultFactory != LIVE_V3_FACTORY
|| vault.degen() != LIVE_DEGEN))
) revert InvalidBuybackVault();
module = module_;
spy = spy_;
operatingTreasury = operatingTreasury_;
buybackVault = buybackVault_;
feeLocker = IDegenSpyV1FeeLocker(feeLocker_);
}
function registerPool(address token, address beneficiary, address controller)
external
onlyModule
returns (PoolKey memory key)
{
if (token == address(0) || token == spy) revert InvalidToken();
if (beneficiary == address(0)) revert InvalidBeneficiary();
if (controller == address(0) || controller != feeLocker.LP_LOCKER()) {
revert InvalidBeneficiaryController();
}
if (token > spy) revert InvalidTokenOrder();
key = PoolKey({
currency0: Currency.wrap(token),
currency1: Currency.wrap(spy),
fee: LPFeeLibrary.DYNAMIC_FEE_FLAG,
tickSpacing: TICK_SPACING,
hooks: IHooks(address(this))
});
PoolId poolId = key.toId();
if (_poolConfigs[poolId].registered) revert PoolAlreadyRegistered();
_poolConfigs[poolId] = PoolConfig(token, beneficiary, controller, true, false, 0);
_poolIdsByToken[token] = poolId;
emit PoolRegistered(poolId, token, spy, controller);
}
function updateBeneficiary(address token, address newBeneficiary) external {
if (newBeneficiary == address(0)) revert InvalidBeneficiary();
PoolConfig storage config = _poolConfigs[_poolIdsByToken[token]];
if (!config.registered) revert PoolNotRegistered();
if (msg.sender != config.beneficiaryController) revert OnlyBeneficiaryController();
address previous = config.beneficiary;
config.beneficiary = newBeneficiary;
emit BeneficiaryUpdated(_poolIdsByToken[token], token, previous, newBeneficiary);
}
function getPoolConfig(PoolId poolId) external view returns (PoolConfig memory) {
return _poolConfigs[poolId];
}
function poolIdForToken(address token) external view returns (PoolId) {
return _poolIdsByToken[token];
}
function _beforeInitialize(address sender, PoolKey calldata key, uint160 price)
internal
view
override
returns (bytes4)
{
PoolConfig storage config = _poolConfigs[key.toId()];
if (!config.registered) revert PoolNotRegistered();
if (sender != module) revert OnlyModule();
if (config.initialized) revert PoolAlreadyInitialized();
if (price != TickMath.getSqrtPriceAtTick(INITIAL_TICK)) revert InvalidInitialPrice();
return BaseHook.beforeInitialize.selector;
}
function _afterInitialize(address sender, PoolKey calldata key, uint160 price, int24 tick)
internal
override
returns (bytes4)
{
PoolId poolId = key.toId();
PoolConfig storage config = _poolConfigs[poolId];
if (!config.registered) revert PoolNotRegistered();
if (sender != module) revert OnlyModule();
if (config.initialized) revert PoolAlreadyInitialized();
if (price != TickMath.getSqrtPriceAtTick(INITIAL_TICK) || tick != INITIAL_TICK) {
revert InvalidInitialPrice();
}
poolManager.updateDynamicLPFee(key, LP_FEE);
config.initialized = true;
config.initializedAt = uint64(block.timestamp);
emit PoolInitialized(poolId, config.initializedAt, LP_FEE);
return BaseHook.afterInitialize.selector;
}
function _beforeSwap(
address sender,
PoolKey calldata key,
IPoolManager.SwapParams calldata params,
bytes calldata
) internal override returns (bytes4, BeforeSwapDelta, uint24) {
PoolId poolId = key.toId();
_requireInitialized(poolId);
_attemptSweep(poolId, sender);
poolManager.updateDynamicLPFee(key, LP_FEE);
uint256 rate = _totalHookRate(poolId);
DegenFeeMath.FeeSplit memory split;
uint256 gross;
if (params.amountSpecified < 0 && !params.zeroForOne) {
gross = _absolute(params.amountSpecified);
split = DegenFeeMath.splitHookFee(gross, rate);
} else if (params.amountSpecified >= 0 && params.zeroForOne) {
uint256 net = uint256(params.amountSpecified);
gross = DegenFeeMath.grossFromNet(net, rate);
split = DegenFeeMath.splitRealizedHookFee(gross, rate, gross - net);
}
if (split.totalHookFee == 0) {
return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
}
_accrue(poolId, key, gross, rate, split);
return
(BaseHook.beforeSwap.selector, toBeforeSwapDelta(_toInt128(split.totalHookFee), 0), 0);
}
function _afterSwap(
address,
PoolKey calldata key,
IPoolManager.SwapParams calldata params,
BalanceDelta delta,
bytes calldata
) internal override returns (bytes4, int128) {
PoolId poolId = key.toId();
_requireInitialized(poolId);
uint256 rate = _totalHookRate(poolId);
DegenFeeMath.FeeSplit memory split;
uint256 gross;
int128 spyDelta = delta.amount1();
if (params.amountSpecified < 0 && params.zeroForOne && spyDelta > 0) {
gross = uint128(spyDelta);
split = DegenFeeMath.splitHookFee(gross, rate);
} else if (params.amountSpecified >= 0 && !params.zeroForOne && spyDelta < 0) {
uint256 poolSpy = _absolute(int256(spyDelta));
gross = DegenFeeMath.grossFromNet(poolSpy, rate);
split = DegenFeeMath.splitRealizedHookFee(gross, rate, gross - poolSpy);
}
if (split.totalHookFee == 0) return (BaseHook.afterSwap.selector, 0);
_accrue(poolId, key, gross, rate, split);
return (BaseHook.afterSwap.selector, _toInt128(split.totalHookFee));
}
function _accrue(
PoolId poolId,
PoolKey calldata key,
uint256 gross,
uint256 rate,
DegenFeeMath.FeeSplit memory split
) private {
PoolConfig storage config = _poolConfigs[poolId];
uint256 cumulative = totalRawSpyFeesAccrued[poolId] + split.totalHookFee;
totalRawSpyFeesAccrued[poolId] = cumulative;
totalTreasuryRawSpyAccrued[poolId] += split.treasuryCredit;
totalBuybackRawSpyAccrued[poolId] += split.buybackCredit;
pendingTreasuryRawSpy += split.treasuryCredit;
pendingBuybackRawSpy += split.buybackCredit;
pendingBeneficiaryRawSpy[poolId][config.beneficiary] += split.beneficiaryTemporary;
pendingBeneficiaryTotalRawSpy[poolId] += split.beneficiaryTemporary;
emit RawSpyHookFeeAccrued(
poolId,
config.beneficiary,
gross,
rate,
split.totalHookFee,
split.permanentFee,
split.temporaryFee,
split.beneficiaryTemporary,
split.treasuryCredit,
split.buybackCredit,
split.roundingDust,
cumulative
);
poolManager.mint(address(this), key.currency1.toId(), split.totalHookFee);
}
function sweepProtocolRawSpyDuringSwap(uint256 treasuryAmount, uint256 buybackAmount) external {
if (msg.sender != address(this)) revert OnlySelf();
uint256 expectedTreasury = pendingTreasuryRawSpy;
uint256 expectedBuyback = pendingBuybackRawSpy;
if (treasuryAmount != expectedTreasury || buybackAmount != expectedBuyback) {
revert ProtocolSweepAmountMismatch(
expectedTreasury, treasuryAmount, expectedBuyback, buybackAmount
);
}
pendingTreasuryRawSpy = 0;
pendingBuybackRawSpy = 0;
totalTreasuryRawSpySwept += treasuryAmount;
totalBuybackRawSpySwept += buybackAmount;
Currency quote = Currency.wrap(spy);
poolManager.burn(address(this), quote.toId(), treasuryAmount + buybackAmount);
if (treasuryAmount != 0) poolManager.take(quote, operatingTreasury, treasuryAmount);
if (buybackAmount != 0) poolManager.take(quote, buybackVault, buybackAmount);
}
function _attemptSweep(PoolId poolId, address caller) private {
uint256 treasuryAmount = pendingTreasuryRawSpy;
uint256 buybackAmount = pendingBuybackRawSpy;
if (treasuryAmount + buybackAmount == 0) return;
try this.sweepProtocolRawSpyDuringSwap(treasuryAmount, buybackAmount) {
emit ProtocolRawSpySwept(
poolId,
caller,
treasuryAmount,
buybackAmount,
totalTreasuryRawSpySwept,
totalBuybackRawSpySwept,
true
);
} catch (bytes memory reason) {
emit ProtocolRawSpySweepFailed(poolId, treasuryAmount, buybackAmount, reason);
}
}
function flushProtocolFees()
external
nonReentrant
returns (uint256 treasuryPaid, uint256 buybackPaid)
{
treasuryPaid = pendingTreasuryRawSpy;
buybackPaid = pendingBuybackRawSpy;
if (treasuryPaid + buybackPaid == 0) return (0, 0);
pendingTreasuryRawSpy = 0;
pendingBuybackRawSpy = 0;
totalTreasuryRawSpySwept += treasuryPaid;
totalBuybackRawSpySwept += buybackPaid;
_redeem(treasuryPaid, buybackPaid, 0);
emit ProtocolRawSpySwept(
PoolId.wrap(bytes32(0)),
msg.sender,
treasuryPaid,
buybackPaid,
totalTreasuryRawSpySwept,
totalBuybackRawSpySwept,
false
);
}
function flushPoolFees(PoolId poolId, address beneficiary)
external
nonReentrant
returns (uint256 treasuryPaid, uint256 buybackPaid, uint256 beneficiaryStored)
{
if (!_poolConfigs[poolId].registered) {
revert PoolNotRegistered();
}
beneficiaryStored = pendingBeneficiaryRawSpy[poolId][beneficiary];
if (beneficiaryStored == 0) return (0, 0, 0);
pendingBeneficiaryRawSpy[poolId][beneficiary] = 0;
pendingBeneficiaryTotalRawSpy[poolId] -= beneficiaryStored;
_redeem(0, 0, beneficiaryStored);
IERC20 quote = IERC20(spy);
quote.forceApprove(address(feeLocker), beneficiaryStored);
uint256 received = feeLocker.storeFees(beneficiary, beneficiaryStored);
quote.forceApprove(address(feeLocker), 0);
if (received != beneficiaryStored) {
revert UnexpectedLockerReceipt(beneficiaryStored, received);
}
emit PoolFeesFlushed(poolId, beneficiary, msg.sender, 0, 0, beneficiaryStored);
}
function _redeem(uint256 treasuryAmount, uint256 buybackAmount, uint256 creatorAmount) private {
_unlocking = true;
_unlockTreasury = treasuryAmount;
_unlockBuyback = buybackAmount;
_unlockCreator = creatorAmount;
poolManager.unlock(abi.encode(treasuryAmount, buybackAmount, creatorAmount));
_unlocking = false;
_unlockTreasury = 0;
_unlockBuyback = 0;
_unlockCreator = 0;
}
function unlockCallback(bytes calldata data) external returns (bytes memory) {
if (msg.sender != address(poolManager) || !_unlocking) revert UnauthorizedUnlock();
(uint256 treasuryAmount, uint256 buybackAmount, uint256 creatorAmount) =
abi.decode(data, (uint256, uint256, uint256));
if (
treasuryAmount != _unlockTreasury || buybackAmount != _unlockBuyback
|| creatorAmount != _unlockCreator
) revert UnauthorizedUnlock();
Currency quote = Currency.wrap(spy);
poolManager.burn(
address(this), quote.toId(), treasuryAmount + buybackAmount + creatorAmount
);
if (treasuryAmount != 0) poolManager.take(quote, operatingTreasury, treasuryAmount);
if (buybackAmount != 0) poolManager.take(quote, buybackVault, buybackAmount);
if (creatorAmount != 0) poolManager.take(quote, address(this), creatorAmount);
return bytes("");
}
function _absolute(int256 amount) private pure returns (uint256) {
unchecked {
return uint256(-(amount + 1)) + 1;
}
}
function _toInt128(uint256 amount) private pure returns (int128) {
if (amount > uint256(uint128(type(int128).max))) revert FeeAmountOverflow(amount);
return int128(int256(amount));
}
function _totalHookRate(PoolId poolId) private view returns (uint256) {
return DegenFeeMath.totalHookRate(_poolConfigs[poolId].initializedAt, block.timestamp);
}
function _requireInitialized(PoolId poolId) private view {
PoolConfig storage config = _poolConfigs[poolId];
if (!config.registered) revert PoolNotRegistered();
if (!config.initialized) revert PoolNotInitialized();
}
function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
return Hooks.Permissions({
beforeInitialize: true,
afterInitialize: true,
beforeAddLiquidity: false,
afterAddLiquidity: false,
beforeRemoveLiquidity: false,
afterRemoveLiquidity: false,
beforeSwap: true,
afterSwap: true,
beforeDonate: false,
afterDonate: false,
beforeSwapReturnDelta: true,
afterSwapReturnDelta: true,
afterAddLiquidityReturnDelta: false,
afterRemoveLiquidityReturnDelta: false
});
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "manager",
"type": "address",
"internalType": "contract IPoolManager"
},
{
"name": "module_",
"type": "address",
"internalType": "address"
},
{
"name": "spy_",
"type": "address",
"internalType": "address"
},
{
"name": "operatingTreasury_",
"type": "address",
"internalType": "address"
},
{
"name": "buybackVault_",
"type": "address",
"internalType": "address"
},
{
"name": "feeLocker_",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "nonpayable"
},
{
"name": "FeeAmountOverflow",
"type": "error",
"inputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "HookNotImplemented",
"type": "error",
"inputs": []
},
{
"name": "InvalidAddress",
"type": "error",
"inputs": []
},
{
"name": "InvalidBeneficiary",
"type": "error",
"inputs": []
},
{
"name": "InvalidBeneficiaryController",
"type": "error",
"inputs": []
},
{
"name": "InvalidBuybackVault",
"type": "error",
"inputs": []
},
{
"name": "InvalidFeeLocker",
"type": "error",
"inputs": []
},
{
"name": "InvalidHookRate",
"type": "error",
"inputs": [
{
"name": "rate",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "InvalidInitialPrice",
"type": "error",
"inputs": []
},
{
"name": "InvalidRate",
"type": "error",
"inputs": [
{
"name": "rate",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "InvalidRealizedFee",
"type": "error",
"inputs": [
{
"name": "realizedFee",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "minimumFee",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "maximumFee",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "InvalidTimestamp",
"type": "error",
"inputs": [
{
"name": "timestamp",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "initializedAt",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "InvalidToken",
"type": "error",
"inputs": []
},
{
"name": "InvalidTokenOrder",
"type": "error",
"inputs": []
},
{
"name": "NotPoolManager",
"type": "error",
"inputs": []
},
{
"name": "OnlyBeneficiaryController",
"type": "error",
"inputs": []
},
{
"name": "OnlyModule",
"type": "error",
"inputs": []
},
{
"name": "OnlySelf",
"type": "error",
"inputs": []
},
{
"name": "PoolAlreadyInitialized",
"type": "error",
"inputs": []
},
{
"name": "PoolAlreadyRegistered",
"type": "error",
"inputs": []
},
{
"name": "PoolNotInitialized",
"type": "error",
"inputs": []
},
{
"name": "PoolNotRegistered",
"type": "error",
"inputs": []
},
{
"name": "ProtocolSweepAmountMismatch",
"type": "error",
"inputs": [
{
"name": "expectedTreasury",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "actualTreasury",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "expectedBuyback",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "actualBuyback",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "ReentrancyGuardReentrantCall",
"type": "error",
"inputs": []
},
{
"name": "SafeERC20FailedOperation",
"type": "error",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "UnauthorizedUnlock",
"type": "error",
"inputs": []
},
{
"name": "UnexpectedLockerReceipt",
"type": "error",
"inputs": [
{
"name": "expected",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "received",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "BeneficiaryUpdated",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "previousBeneficiary",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newBeneficiary",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "PoolFeesFlushed",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "beneficiary",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "caller",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "treasuryPaid",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "buybackPaid",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "beneficiaryStored",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "PoolInitialized",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "initializedAt",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
},
{
"name": "lpFee",
"type": "uint24",
"indexed": false,
"internalType": "uint24"
}
],
"anonymous": false
},
{
"name": "PoolRegistered",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "spy",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "beneficiaryController",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "ProtocolRawSpySweepFailed",
"type": "event",
"inputs": [
{
"name": "triggeringPoolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "attemptedTreasuryAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "attemptedBuybackAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "reason",
"type": "bytes",
"indexed": false,
"internalType": "bytes"
}
],
"anonymous": false
},
{
"name": "ProtocolRawSpySwept",
"type": "event",
"inputs": [
{
"name": "triggeringPoolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "caller",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "treasuryAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "buybackAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "cumulativeTreasurySwept",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "cumulativeBuybackSwept",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "automatic",
"type": "bool",
"indexed": false,
"internalType": "bool"
}
],
"anonymous": false
},
{
"name": "RawSpyHookFeeAccrued",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "beneficiary",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "grossRawSpyBasis",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "totalRate",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "totalFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "permanentFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "temporaryFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "beneficiaryTemporary",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "treasuryCredit",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "buybackCredit",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "roundingDust",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "cumulativeAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "INITIAL_TICK",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "LP_FEE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint24",
"internalType": "uint24"
}
],
"stateMutability": "view"
},
{
"name": "TICK_SPACING",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "afterAddLiquidity",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "liquidityDelta",
"type": "int256",
"internalType": "int256"
},
{
"name": "salt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"internalType": "struct IPoolManager.ModifyLiquidityParams"
},
{
"name": "delta",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "feesAccrued",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BalanceDelta"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterDonate",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "amount0",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterInitialize",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "sqrtPriceX96",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "tick",
"type": "int24",
"internalType": "int24"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterRemoveLiquidity",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "liquidityDelta",
"type": "int256",
"internalType": "int256"
},
{
"name": "salt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"internalType": "struct IPoolManager.ModifyLiquidityParams"
},
{
"name": "delta",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "feesAccrued",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BalanceDelta"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterSwap",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "zeroForOne",
"type": "bool",
"internalType": "bool"
},
{
"name": "amountSpecified",
"type": "int256",
"internalType": "int256"
},
{
"name": "sqrtPriceLimitX96",
"type": "uint160",
"internalType": "uint160"
}
],
"internalType": "struct IPoolManager.SwapParams"
},
{
"name": "delta",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int128",
"internalType": "int128"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeAddLiquidity",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "liquidityDelta",
"type": "int256",
"internalType": "int256"
},
{
"name": "salt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"internalType": "struct IPoolManager.ModifyLiquidityParams"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeDonate",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "amount0",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeInitialize",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "sqrtPriceX96",
"type": "uint160",
"internalType": "uint160"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeRemoveLiquidity",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "liquidityDelta",
"type": "int256",
"internalType": "int256"
},
{
"name": "salt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"internalType": "struct IPoolManager.ModifyLiquidityParams"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeSwap",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "zeroForOne",
"type": "bool",
"internalType": "bool"
},
{
"name": "amountSpecified",
"type": "int256",
"internalType": "int256"
},
{
"name": "sqrtPriceLimitX96",
"type": "uint160",
"internalType": "uint160"
}
],
"internalType": "struct IPoolManager.SwapParams"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BeforeSwapDelta"
},
{
"name": "",
"type": "uint24",
"internalType": "uint24"
}
],
"stateMutability": "nonpayable"
},
{
"name": "buybackVault",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "feeLocker",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IDegenSpyV1FeeLocker"
}
],
"stateMutability": "view"
},
{
"name": "flushPoolFees",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
},
{
"name": "beneficiary",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "treasuryPaid",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "buybackPaid",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "beneficiaryStored",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "flushProtocolFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "treasuryPaid",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "buybackPaid",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "getHookPermissions",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "beforeInitialize",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterInitialize",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeAddLiquidity",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterAddLiquidity",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeRemoveLiquidity",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterRemoveLiquidity",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeSwap",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterSwap",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeDonate",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterDonate",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeSwapReturnDelta",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterSwapReturnDelta",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterAddLiquidityReturnDelta",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterRemoveLiquidityReturnDelta",
"type": "bool",
"internalType": "bool"
}
],
"internalType": "struct Hooks.Permissions"
}
],
"stateMutability": "pure"
},
{
"name": "getPoolConfig",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "beneficiary",
"type": "address",
"internalType": "address"
},
{
"name": "beneficiaryController",
"type": "address",
"internalType": "address"
},
{
"name": "registered",
"type": "bool",
"internalType": "bool"
},
{
"name": "initialized",
"type": "bool",
"internalType": "bool"
},
{
"name": "initializedAt",
"type": "uint64",
"internalType": "uint64"
}
],
"internalType": "struct IDegenSpyV2Hook.PoolConfig"
}
],
"stateMutability": "view"
},
{
"name": "module",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "operatingTreasury",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "pendingBeneficiaryRawSpy",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
},
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "pendingBeneficiaryTotalRawSpy",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "pendingBuybackRawSpy",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "pendingTreasuryRawSpy",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "poolIdForToken",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"stateMutability": "view"
},
{
"name": "poolManager",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IPoolManager"
}
],
"stateMutability": "view"
},
{
"name": "registerPool",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "beneficiary",
"type": "address",
"internalType": "address"
},
{
"name": "controller",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
}
],
"stateMutability": "nonpayable"
},
{
"name": "spy",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "sweepProtocolRawSpyDuringSwap",
"type": "function",
"inputs": [
{
"name": "treasuryAmount",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "buybackAmount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "totalBuybackRawSpyAccrued",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalBuybackRawSpySwept",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalRawSpyFeesAccrued",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalTreasuryRawSpyAccrued",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalTreasuryRawSpySwept",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "unlockCallback",
"type": "function",
"inputs": [
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "nonpayable"
},
{
"name": "updateBeneficiary",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "newBeneficiary",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
}
]0x6080806040526004361015610012575f80fd5b5f905f3560e01c908163037aadbe14611ff25750806307dbef7314611cc45780630e15a2be14611c9a57806312a70ae314611c7057806315424b0814611c355780631802f79414611c1757806321d0ee7014611b9e578063259982e514611b9e5780632a90c59114611b4d5780632c23003d146115c45780633ae6646c146115a657806346ca626b1461158a578063575e24b4146114725780635e3f2727146114555780636c2bbe7e146109b85780636f66681f146114375780636fe7e6eb1461106457806370e9d244146110135780637249d9d914610e81578063906913de14610e5757806391dd734614610a335780639f063efc146109b8578063a0e62eb914610973578063b3dbac771461093d578063b47b2fb114610806578063b6a8b0fa14610208578063b86d5298146107b5578063c4e833ce1461064a578063d012965b14610620578063d08f41dc146105cd578063d2ab69191461057e578063d361c80e14610560578063dc4c90d31461050f578063dc98354e146102f8578063dcde388f146102a7578063e1b4af69146102085763f1f5c993146101b5575f80fd5b34610205578060031936011261020557602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000910313c5303fecf33a2dbb1d945aad9c26a3a952168152f35b80fd5b50346102055760049061021a36612377565b50505050505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951163303610282577f0a85dc29000000000000000000000000000000000000000000000000000000008152fd5b7fae18210a000000000000000000000000000000000000000000000000000000008152fd5b5034610205578060031936011261020557602060405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000053f8a103f2c9451bfb7157ccae4461fba39d39a0168152f35b50346102055760e06003193601126102055761031261210e565b60a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261050b57610344612303565b9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511633036104e35760a061038d36612d17565b208352600160205260026040842001549060ff8260a01c16156104bb5773ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000c626856dfff1b9a68f3132ca1e872067cae6c569169116036104935760a81c60ff1661046b5773ffffffffffffffffffffffffffffffffffffffff8061041161388b565b169116036104435760206040517fdc98354e000000000000000000000000000000000000000000000000000000008152f35b807fb3cd5c660000000000000000000000000000000000000000000000000000000060049252fd5b6004827f7983c051000000000000000000000000000000000000000000000000000000008152fd5b6004837f139c9e32000000000000000000000000000000000000000000000000000000008152fd5b6004847f739f4185000000000000000000000000000000000000000000000000000000008152fd5b6004837fae18210a000000000000000000000000000000000000000000000000000000008152fd5b5080fd5b5034610205578060031936011261020557602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951168152f35b50346102055780600319360112610205576020600954604051908152f35b5034610205576040600319360112610205576001906105ae61059e612131565b6105a6613175565b60043561275c565b9390925560405192839260608401928452602084015260408301520390f35b50346102055760406003193601126102055773ffffffffffffffffffffffffffffffffffffffff60406105fe612131565b926004358152600a6020522091165f52602052602060405f2054604051908152f35b50346102055760206003193601126102055760406020916004358152600583522054604051908152f35b50346102055780600319360112610205576020816101c0926101a06040516106718161245f565b82815282858201528260408201528260608201528260808201528260a08201528260c08201528260e082015282610100820152826101208201528261014082015282610160820152826101808201520152806040516106cf8161245f565b600181528381016001815260408201838152606083018481526080840185815260a0850186815260c08601906001825260e0870192600184526101008801948986526101208901968a88526101408a019860018a526101a06101608c019b60018d5261018081019d8e52019c8d526040519d8e916001835251151591015251151560408d015251151560608c015251151560808b015251151560a08a015251151560c089015251151560e08801525115156101008701525115156101208601525115156101408501525115156101608401525115156101808301525115156101a0820152f35b5034610205578060031936011261020557602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c626856dfff1b9a68f3132ca1e872067cae6c569168152f35b5034610205576101606003193601126102055761082161210e565b5060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126102055760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c360112610205576101443567ffffffffffffffff811161050b57610897903690600401612175565b505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511633036109155760406108e4610124356131ac565b7fffffffff00000000000000000000000000000000000000000000000000000000835192168252600f0b6020820152f35b807fae18210a0000000000000000000000000000000000000000000000000000000060049252fd5b5034610205578060031936011261020557604090610959613175565b6001610963612531565b9190925582519182526020820152f35b503461020557602060031936011261020557604060209173ffffffffffffffffffffffffffffffffffffffff6109a761210e565b168152600283522054604051908152f35b5034610205576004906109ca36612250565b5050505050505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951163303610282577f0a85dc29000000000000000000000000000000000000000000000000000000008152fd5b50346102055760206003193601126102055760043567ffffffffffffffff811161050b57610a65903690600401612175565b9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511691823314801590610e4a575b610e22578160609181010312610c62578035916040602083013592013591600d548414801590610e16575b8015610e0a575b610de257849073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000117cc2133c37b721f49de2a7a74833232b3b4c0c1694610b2c85610b2784846124bd565b6124bd565b843b15610d08576040517ff5298aca000000000000000000000000000000000000000000000000000000008152306004820152602481018890526044810191909152838160648183895af1908115610dd7578491610dc2575b505080610d0c575b5080610c66575b505081610bc9575b610bc58460405190610baf60208361247c565b8152604051918291602083526020830190612334565b0390f35b908184923b15610c62576040517f0b0d9c0900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff94909416600485015230602485015260448401919091528290606490829084905af18015610c5757610c42575b8080610b9c565b610c4d82809261247c565b610205575f610c3b565b6040513d84823e3d90fd5b8280fd5b823b1561050b576040517f0b0d9c0900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301527f000000000000000000000000910313c5303fecf33a2dbb1d945aad9c26a3a9521660248201526044810191909152818160648183875af18015610c575715610b945781610cfd9161247c565b610d0857835f610b94565b8380fd5b833b15610c62576040517f0b0d9c0900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301527f00000000000000000000000053f8a103f2c9451bfb7157ccae4461fba39d39a01660248201526044810191909152828160648183885af1908115610db7578391610da2575b50610b8d565b81610dac9161247c565b61050b57815f610d9c565b6040513d85823e3d90fd5b81610dcc9161247c565b610c6257825f610b85565b6040513d86823e3d90fd5b6004857f975ce5bf000000000000000000000000000000000000000000000000000000008152fd5b50600f54831415610adb565b50600e54811415610ad4565b6004847f975ce5bf000000000000000000000000000000000000000000000000000000008152fd5b5060ff600c541615610aa9565b50346102055760206003193601126102055760406020916004358152600b83522054604051908152f35b503461020557604060031936011261020557610e9b61210e565b73ffffffffffffffffffffffffffffffffffffffff610eb8612131565b16908115610feb5773ffffffffffffffffffffffffffffffffffffffff16808352600260205260408320548352600160205260408320600281015460ff8160a01c1615610fc35773ffffffffffffffffffffffffffffffffffffffff163303610f9b576001019173ffffffffffffffffffffffffffffffffffffffff83541692817fffffffffffffffffffffffff000000000000000000000000000000000000000082541617905581845260026020527ffe6ca1addf5276d963a4b3a0d7cccc48f6a60f973cd85e8507e5c88f21d253b76020604086205492604051908152a480f35b6004847fd6b5c095000000000000000000000000000000000000000000000000000000008152fd5b6004857f739f4185000000000000000000000000000000000000000000000000000000008152fd5b6004837f5566df5c000000000000000000000000000000000000000000000000000000008152fd5b5034610205578060031936011261020557602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000aa5d42424673218a52778718caef57e0e4c0ba31168152f35b5034610205576101006003193601126102055761107f61210e565b60a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261050b576110b1612303565b9160e4358060020b80910361050b5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116908133036104e35760a061110a36612d17565b20948584526001602052600260408520019485549060ff8260a01c161561140f5773ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000c626856dfff1b9a68f3132ca1e872067cae6c569169116036113e75760a81c60ff166113bf5773ffffffffffffffffffffffffffffffffffffffff8061119261388b565b1691161490811591611394575b5061136c57803b1561050b57604051907f5275965100000000000000000000000000000000000000000000000000000000825260243573ffffffffffffffffffffffffffffffffffffffff8116809103610d0857600483015260443573ffffffffffffffffffffffffffffffffffffffff8116809103610d0857602483015260643562ffffff8116809103610d085760448301526084358060020b809103610d0857606483015260a43573ffffffffffffffffffffffffffffffffffffffff8116809103610d085760c4838580948294608484015261271060a48401525af18015610c5757611357575b82547fffff000000000000000000ffffffffffffffffffffffffffffffffffffffffff164260b01b7dffffffffffffffff0000000000000000000000000000000000000000000016177501000000000000000000000000000000000000000000178355837f21132787737e2e9ff0a61e3aa3c57c7f9c657413d432c8e6a3957182c24c2336604067ffffffffffffffff865460b01c1681519081526127106020820152a260206040517f6fe7e6eb000000000000000000000000000000000000000000000000000000008152f35b61136282809261247c565b6102055780611289565b6004827fb3cd5c66000000000000000000000000000000000000000000000000000000008152fd5b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca0b8915014155f61119f565b6004847f7983c051000000000000000000000000000000000000000000000000000000008152fd5b6004857f139c9e32000000000000000000000000000000000000000000000000000000008152fd5b6004867f739f4185000000000000000000000000000000000000000000000000000000008152fd5b50346102055780600319360112610205576020600654604051908152f35b503461020557806003193601126102055760206040516127108152f35b5034610205576101406003193601126102055761148d61210e565b9060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126102055760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c360112610205576101243567ffffffffffffffff811161050b57611503903690600401612175565b505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116330361091557606062ffffff61155184612ea1565b907fffffffff00000000000000000000000000000000000000000000000000000000604094939451941684526020840152166040820152f35b5034610205578060031936011261020557602060405160c88152f35b50346102055780600319360112610205576020600754604051908152f35b5034610205576060600319360112610205576115de61210e565b6115e6612131565b906044359073ffffffffffffffffffffffffffffffffffffffff8216809203610d085783608060405161161881612443565b828152826020820152826040820152826060820152015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c626856dfff1b9a68f3132ca1e872067cae6c569163303611b255773ffffffffffffffffffffffffffffffffffffffff169182158015611ae6575b611abe5773ffffffffffffffffffffffffffffffffffffffff168015611a965781158015611991575b6119695773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000117cc2133c37b721f49de2a7a74833232b3b4c0c1692838111611941576040519361170585612443565b81855260208501918183526040860193628000008552606087019560c887526080880198308a5260a0892092838252600160205260ff600260408420015460a01c166119195793837f01bf263a1db1652580721573296e1a1fa70b3d4c87f61d02a69c4e1109d2d573602073ffffffffffffffffffffffffffffffffffffffff9b99958360a09f9c99878f9a60409267ffffffffffffffff62ffffff9f9b6118e0938651936117b3856123fa565b8d85528a85019081528785018a81526001606087018181526080880186815260a0808a018881529688526020849052968c9020985189547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff928316178b559551938a01805490961693811693909317909455915160029790970180549251935194517fffff000000000000000000000000000000000000000000000000000000000000909316979091169690961791151590931b74ff0000000000000000000000000000000000000000161790151560a81b75ff0000000000000000000000000000000000000000001617911660b01b7dffffffffffffffff0000000000000000000000000000000000000000000016179055565b878152600285522055604051908152a481604051985116885251166020870152511660408501525160020b606084015251166080820152f35b6004827fb3e8301e000000000000000000000000000000000000000000000000000000008152fd5b6004857f3f06bf81000000000000000000000000000000000000000000000000000000008152fd5b6004847fbba5e2f2000000000000000000000000000000000000000000000000000000008152fd5b506040517fcdf05fbc00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000aa5d42424673218a52778718caef57e0e4c0ba31165afa8015611a8b578590611a24575b73ffffffffffffffffffffffffffffffffffffffff9150168214156116b5565b506020813d602011611a83575b81611a3e6020938361247c565b81010312611a7f575173ffffffffffffffffffffffffffffffffffffffff81168103611a7f5773ffffffffffffffffffffffffffffffffffffffff90611a04565b8480fd5b3d9150611a31565b6040513d87823e3d90fd5b6004847f5566df5c000000000000000000000000000000000000000000000000000000008152fd5b6004847fc1ab6dc1000000000000000000000000000000000000000000000000000000008152fd5b5073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000117cc2133c37b721f49de2a7a74833232b3b4c0c16831461168c565b6004847f139c9e32000000000000000000000000000000000000000000000000000000008152fd5b5034610205578060031936011261020557602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000117cc2133c37b721f49de2a7a74833232b3b4c0c168152f35b503461020557600490611bb0366121a3565b505050505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951163303610282577f0a85dc29000000000000000000000000000000000000000000000000000000008152fd5b50346102055780600319360112610205576020600854604051908152f35b503461020557806003193601126102055760206040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca0b88152f35b50346102055760206003193601126102055760406020916004358152600383522054604051908152f35b50346102055760206003193601126102055760406020916004358152600483522054604051908152f35b5034611f7a576040600319360112611f7a5760043590602435303303611fca57600654600754818514801590611fc0575b611f7e5750505f6006555f600755611d0f836008546124bd565b600855611d1e816009546124bd565b60095573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000117cc2133c37b721f49de2a7a74833232b3b4c0c1673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511691611d9a81866124bd565b94833b15611f7a576040517ff5298aca0000000000000000000000000000000000000000000000000000000081523060048201526024810184905260448101969096525f8660648183885af18015611f6f57611f59575b84955080611eae575b5080611e0557505050f35b823b15611ea9576040517f0b0d9c0900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201527f000000000000000000000000910313c5303fecf33a2dbb1d945aad9c26a3a952909216602483015260448201529082908290606490829084905af18015610c5757611e985750f35b81611ea29161247c565b6102055780f35b505050fd5b833b15611a7f576040517f0b0d9c0900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f00000000000000000000000053f8a103f2c9451bfb7157ccae4461fba39d39a01660248201526044810191909152848160648183885af1908115611a8b578591611f44575b50611dfa565b81611f4e9161247c565b611ea957835f611f3e565b9350935f611f669161247c565b5f928490611df1565b6040513d5f823e3d90fd5b5f80fd5b9160849285604051937f6e2873380000000000000000000000000000000000000000000000000000000085526004850152602484015260448301526064820152fd5b5080831415611cf5565b7f14d4a4e8000000000000000000000000000000000000000000000000000000005f5260045ffd5b34611f7a576020600319360112611f7a5760a0816120105f936123fa565b82815282602082015282604082015282606082015282608082015201526004355f52600160205260c060405f2067ffffffffffffffff60405191612053836123fa565b73ffffffffffffffffffffffffffffffffffffffff81541692838152600273ffffffffffffffffffffffffffffffffffffffff600184015416926020830193845201549173ffffffffffffffffffffffffffffffffffffffff60408301818516815281606085019360ff8760a01c16151585528760a0608088019760ff8a60a81c1615158952019760b01c168752604051988952511660208801525116604086015251151560608501525115156080840152511660a0820152f35b6004359073ffffffffffffffffffffffffffffffffffffffff82168203611f7a57565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203611f7a57565b359073ffffffffffffffffffffffffffffffffffffffff82168203611f7a57565b9181601f84011215611f7a5782359167ffffffffffffffff8311611f7a5760208381860195010111611f7a57565b90610160600319830112611f7a5760043573ffffffffffffffffffffffffffffffffffffffff81168103611f7a579160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc820112611f7a5760249160807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c830112611f7a5760c491610144359067ffffffffffffffff8211611f7a5761224c91600401612175565b9091565b906101a0600319830112611f7a5760043573ffffffffffffffffffffffffffffffffffffffff81168103611f7a579160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc820112611f7a5760249160807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c830112611f7a5760c49161014435916101643591610184359067ffffffffffffffff8211611f7a5761224c91600401612175565b60c4359073ffffffffffffffffffffffffffffffffffffffff82168203611f7a57565b35908160020b8203611f7a57565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b610120600319820112611f7a5760043573ffffffffffffffffffffffffffffffffffffffff81168103611f7a579160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc830112611f7a5760249160c4359160e43591610104359067ffffffffffffffff8211611f7a5761224c91600401612175565b60c0810190811067ffffffffffffffff82111761241657604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60a0810190811067ffffffffffffffff82111761241657604052565b6101c0810190811067ffffffffffffffff82111761241657604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761241657604052565b919082018092116124ca57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff811161241657601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600654906007549061254382846124bd565b15612747575f6006555f60075561255c836008546124bd565b60085561256b826009546124bd565b60095560017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600c541617600c5582600d5581600e555f600f556126085f604051856020820152846040820152816060820152606081526125cd60808261247c565b604051809381927f48c89491000000000000000000000000000000000000000000000000000000008352602060048401526024830190612334565b03818373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951165af18015611f6f576126d0575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600c5416600c555f600d555f600e555f600f5560085460095460405191858352846020840152604083015260608201525f60808201525f7fde26d600b1d346438899afa1ae112181457d7885484a906e9921287cc2f494fd60a03393a3565b3d805f833e6126df818361247c565b810190602081830312611f7a5780519067ffffffffffffffff8211611f7a570181601f82011215611f7a57805190612716826124f7565b92612724604051948561247c565b82845260208383010111611f7a57815f9260208093018386015e8301015261264f565b5f9250829150565b919082039182116124ca57565b5f925f92825f52600160205260ff600260405f20015460a01c1615612cdf57825f52600a60205260405f2073ffffffffffffffffffffffffffffffffffffffff82165f5260205260405f2054928315612cd257805f52600a60205260405f2073ffffffffffffffffffffffffffffffffffffffff83165f526020525f6040812055805f52600b60205260405f206127f485825461274f565b905560017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600c541617600c555f600d555f600e5583600f556128555f604051816020820152816040820152866060820152606081526125cd60808261247c565b03818373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951165af18015611f6f57612c5b575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600c5416600c555f600d555f600e555f600f5573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000117cc2133c37b721f49de2a7a74833232b3b4c0c1673ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000aa5d42424673218a52778718caef57e0e4c0ba311660405160205f8183017f095ea7b30000000000000000000000000000000000000000000000000000000081526129cc846129a08c88602484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810186528561247c565b83519082875af15f513d82612c3f575b505015612be2575b506040517f892f9e2f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260248101879052916020836044815f865af1928315611f6f575f93612bae575b506040519060205f8184017f095ea7b300000000000000000000000000000000000000000000000000000000815285602486015281604486015260448552612a9060648661247c565b84519082855af15f513d82612b92575b505015612b34575b505050848103612b055750604051905f82525f60208301528460408301527f404953b80a7b2776a588f33a47c62d57f3d60e2bcb12cd54b110072ee4158bc1606073ffffffffffffffffffffffffffffffffffffffff33951693a4565b847ff2491cf6000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b612b85612b8a93604051907f095ea7b300000000000000000000000000000000000000000000000000000000602083015260248201525f604482015260448152612b7f60648261247c565b82613c27565b613c27565b5f8080612aa8565b909150612ba65750803b15155b5f80612aa0565b600114612b9f565b9092506020813d602011612bda575b81612bca6020938361247c565b81010312611f7a5751915f612a47565b3d9150612bbd565b612c3990612c336040517f095ea7b30000000000000000000000000000000000000000000000000000000060208201528460248201525f604482015260448152612c2d60648261247c565b85613c27565b83613c27565b5f6129e4565b909150612c535750823b15155b5f806129dc565b600114612c4c565b3d805f833e612c6a818361247c565b810190602081830312611f7a5780519067ffffffffffffffff8211611f7a570181601f82011215611f7a57805190612ca1826124f7565b92612caf604051948561247c565b82845260208383010111611f7a57815f9260208093018386015e8301015261289c565b505f945084935083925050565b7f739f4185000000000000000000000000000000000000000000000000000000005f5260045ffd5b359062ffffff82168203611f7a57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc60a0910112611f7a5760405190612d4e82612443565b8160243573ffffffffffffffffffffffffffffffffffffffff81168103611f7a57815260443573ffffffffffffffffffffffffffffffffffffffff81168103611f7a57602082015260643562ffffff81168103611f7a5760408201526084358060020b8103611f7a57606082015260a4359073ffffffffffffffffffffffffffffffffffffffff82168203611f7a5760800152565b91908260a0910312611f7a57604051612dfb81612443565b6080612e47818395612e0c81612154565b8552612e1a60208201612154565b6020860152612e2b60408201612d07565b6040860152612e3c60608201612326565b606086015201612154565b910152565b60405190610120820182811067ffffffffffffffff821117612416576040525f610100838281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201520152565b5f90612ec460a0612eb3366024612de3565b2091612ebe8361330e565b8261335e565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116803b15611f7a57604051907f5275965100000000000000000000000000000000000000000000000000000000825260243573ffffffffffffffffffffffffffffffffffffffff81168103611f7a5773ffffffffffffffffffffffffffffffffffffffff16600483015260443573ffffffffffffffffffffffffffffffffffffffff81168103611f7a5773ffffffffffffffffffffffffffffffffffffffff16602483015260643562ffffff81168103611f7a5762ffffff1660448301526084358060020b8103611f7a5760020b606483015260a4359073ffffffffffffffffffffffffffffffffffffffff82168203611f7a5760c4835f819373ffffffffffffffffffffffffffffffffffffffff829616608484015261271060a48401525af18015611f6f57613160575b50613030816134c7565b90613039612e4c565b60e43590848083128080613147575b156130f557505050830361305a612e4c565b5061306483613ce7565b61306d83613cae565b61308161307a8483613e46565b8083613d32565b915b8251156130cb576130a19361309b926024859361360c565b51613843565b60801b917f575e24b400000000000000000000000000000000000000000000000000000000929190565b505050507f575e24b400000000000000000000000000000000000000000000000000000000918190565b9391939290921580613136575b61310d575b50613083565b9150915061312f61312861312185846134fd565b928361274f565b8483613570565b915f613107565b5060c4358015158114613102578680fd5b5060c4358015908115810361315c5750613048565b8880fd5b61316d9192505f9061247c565b5f905f613026565b60025f54146131845760025f55565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b60a06131b9366024612de3565b20906131c48261330e565b6131cd826134c7565b916131d6612e4c565b915f81600f0b5f60e435128080916132fd575b806132f4575b1561329c575050506fffffffffffffffffffffffffffffffff91925016613214612e4c565b5061321e83613ce7565b61322783613cae565b61323461307a8483613e46565b915b8251156132725761324e9361309b926024859361360c565b7fb47b2fb10000000000000000000000000000000000000000000000000000000091565b505050507fb47b2fb100000000000000000000000000000000000000000000000000000000905f90565b909193925015806132df575b806132d6575b6132b9575b50613236565b915091505f036132cf61312861312185846134fd565b915f6132b3565b505f81126132ae565b5060c43580159081158103611f7a57506132a8565b505f82136131ef565b5060c43580151581146131e9575f80fd5b5f526001602052600260405f20015460ff8160a01c1615612cdf5760a81c60ff161561333657565b7f486aa307000000000000000000000000000000000000000000000000000000005f5260045ffd5b600654915f926007549161337283836124bd565b156134c057303b15611f7a576040517f07dbef730000000000000000000000000000000000000000000000000000000081528260048201528360248201525f8160448183305af190816134ab575b50613446575091927f3b66871764441190d7871f7f477cb4567ee7c2ba11e92c28281f14b8b76377a692903d1561343b57613436903d6133ff816124f7565b9061340d604051928361247c565b8152809160203d92013e5b60405193849384526020840152606060408401526060830190612334565b0390a2565b506134366060613418565b73ffffffffffffffffffffffffffffffffffffffff9060a0927fde26d600b1d346438899afa1ae112181457d7885484a906e9921287cc2f494fd94600854906009549260405199508952602089015260408801526060870152600160808701521693a3565b6134b89196505f9061247c565b5f945f6133c0565b5050505050565b5f5260016020526134ed67ffffffffffffffff600260405f20015460b01c164290613dd0565b6127100180612710116124ca5790565b9061350781613cae565b80620f424003620f424081116124ca5761352581620f42408561409c565b91620f42401461354357620f424061354093091515906124bd565b90565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b91909161357b612e4c565b5061358583613ce7565b61358e83613cae565b6135b661359b8483613e46565b93620f42406135ab81838661409c565b9184091515906124bd565b8383108015613603575b6135d05750906135409291613d32565b83837fe4a552dc000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b508083116135c0565b909392916101407f9c4d94fa4bdae9e1d495b726de60bf7e5ee5f8e261ef8e75ff84b7775b77909791835f52600160205260405f2094845f52600360205261365a60405f20548851906124bd565b90855f5260036020528160405f20558761010081018051885f52600460205261368860405f209182546124bd565b905560c08201908151895f5260056020526136a860405f209182546124bd565b90556136b781516006546124bd565b6006556136c782516007546124bd565b60075573ffffffffffffffffffffffffffffffffffffffff606084019a8b518b5f52600a602052600160405f209201918380845416165f5260205261371160405f209182546124bd565b90558b518b5f52600b60205261372c60405f209182546124bd565b9055541699835160208501519060e0604087015193519451955196015196604051998a5260208a015260408901526060880152608087015260a086015260c085015260e0840152610100830152610120820152a3602073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951169201359073ffffffffffffffffffffffffffffffffffffffff8216809203611f7a5751823b15611f7a576040517f156e29f600000000000000000000000000000000000000000000000000000000815230600482015260248101929092526044820152905f908290606490829084905af18015611f6f576138375750565b5f6138419161247c565b565b6f7fffffffffffffffffffffffffffffff811161386057600f0b90565b7fb02ecae0000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca0b860ff1d7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca0b8810118620d89e88111613bdb5763ffffffff90600181167001fffcb933bd6fad37aa2d162d1a59400102700100000000000000000000000000000000189060028116613bbf575b60048116613ba3575b60088116613b87575b60108116613b6b575b60208116613b4f575b60408116613b33575b60808116613b17575b6101008116613afb575b6102008116613adf575b6104008116613ac3575b6108008116613aa7575b6110008116613a8b575b6120008116613a6f575b6140008116613a53575b6180008116613a37575b620100008116613a1b575b620200008116613a00575b6204000081166139e5575b62080000166139cf575b0160201c90565b6b048a170391f7dc42444e8fa20260801c6139c8565b6d2216e584f5fa1ea926041bedfe9890910260801c906139be565b906e5d6af8dedb81196699c329225ee6040260801c906139b3565b906f09aa508b5b7a84e1c677de54f3e99bc90260801c906139a8565b906f31be135f97d08fd981231505542fcfa60260801c9061399d565b906f70d869a156d2a1b890bb3df62baf32f70260801c90613993565b906fa9f746462d870fdf8a65dc1f90e061e50260801c90613989565b906fd097f3bdfd2022b8845ad8f792aa58250260801c9061397f565b906fe7159475a2c29b7443b29c7fa6e889d90260801c90613975565b906ff3392b0822b70005940c7a398e4b70f30260801c9061396b565b906ff987a7253ac413176f2b074cf7815e540260801c90613961565b906ffcbe86c7900a88aedcffc83b479aa3a40260801c90613957565b906ffe5dee046a99a2a811c461f1969c30530260801c9061394d565b906fff2ea16466c96a3843ec78b326b528610260801c90613944565b906fff973b41fa98c081472e6896dfb254c00260801c9061393b565b906fffcb9843d60f6159c9db58835c9266440260801c90613932565b906fffe5caca7e10e4e61c3624eaa0941cd00260801c90613929565b906ffff2e50f5f656932ef12357cf3c7fdcc0260801c90613920565b906ffff97272373d413259a46990580e213a0260801c90613917565b7f8b86327a000000000000000000000000000000000000000000000000000000005f527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca0b860045260245ffd5b905f602091828151910182855af115611f6f575f513d613ca5575073ffffffffffffffffffffffffffffffffffffffff81163b155b613c635750565b73ffffffffffffffffffffffffffffffffffffffff907f5274afe7000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b60011415613c5c565b620f4240811015613cbc5750565b7f6d10fa46000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b61271081108015613d25575b613cfa5750565b7fb8834b0f000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b50620f4240811015613cf3565b90613dc0613dc892949394613daf613d48612e4c565b968488958652613da5613d97613d8a6060613d736020613d678a613eec565b9b019a808c528761274f565b8d604081019180835260011c92839101525161274f565b9560808c01968752613f80565b60a08b01978189525161274f565b60c08a015261274f565b9260e08701938452519051906124bd565b9051906124bd565b610100830152565b90818110613e185790613de29161274f565b601e811015613e135780601e0390601e82116124ca57818002918083041490601e1417156124ca5761354090614008565b505f90565b7fcbda5f6b000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b9190915f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8482099084810292838084109303928084039314613ede5782620f42401115613ecc57507fde8f6cefed634549b62c77574f722e1ac57e23f24d8fd5cb790fb65668c261399394620f4240910990828211900360fa1b910360061c170290565b634e487b71905260116020526024601cfd5b505050620f42409192500490565b905f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6127108409612710840291828083109203918083039214613f745781620f42401115613ecc5750620f42406127107fde8f6cefed634549b62c77574f722e1ac57e23f24d8fd5cb790fb65668c2613994950990828211900360fa1b910360061c170290565b5050620f424090049150565b905f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6113888409611388840291828083109203918083039214613f745781620f42401115613ecc5750620f42406113887fde8f6cefed634549b62c77574f722e1ac57e23f24d8fd5cb790fb65668c2613994950990828211900360fa1b910360061c170290565b905f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83620c0df00983620c0df0029182808310920391808303921461409157816103841115613ecc57506103847f4320fedcba987654320fedcba987654320fedcba987654320fedcba9876543219394620c0df00990828211900360fe1b910360021c170290565b505061038490049150565b90917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff838309928083029283808610950394808603951461414c57848311156141345790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b50509150811561354357049056
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| no token holdings | ||||
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| no token transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x15eb5c…417021 | 24 days agoFri, 24 Jul 2026 19:12:29 UTC | 0x9c4d94…9097 | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…914fde78 data: 0x000000000000000000…fb015573 |
| 0x3bac73…0714fa | 24 days agoFri, 24 Jul 2026 14:45:57 UTC | 0xde26d6…94fd | [0] 0x000000000000…00000000 [1] 0x000000000000…914fde78 data: 0x000000000000000000…00000000 |
| 0xe22d43…a5057e | 24 days agoFri, 24 Jul 2026 14:32:59 UTC | 0x9c4d94…9097 | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…914fde78 data: 0x000000000000000000…83c90bc6 |
| 0xe22d43…a5057e | 24 days agoFri, 24 Jul 2026 14:32:59 UTC | 0xde26d6…94fd | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…94624eff data: 0x000000000000000000…00000001 |
| 0xd5749f…f8748f | 24 days agoFri, 24 Jul 2026 14:32:43 UTC | 0x9c4d94…9097 | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…914fde78 data: 0x000000000000000000…f51f9042 |
| 0xd5749f…f8748f | 24 days agoFri, 24 Jul 2026 14:32:43 UTC | 0xde26d6…94fd | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…94624eff data: 0x000000000000000000…00000001 |
| 0x12671e…324bc2 | 24 days agoFri, 24 Jul 2026 14:32:13 UTC | 0x9c4d94…9097 | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…914fde78 data: 0x000000000000000000…6aa04180 |
| 0x12671e…324bc2 | 24 days agoFri, 24 Jul 2026 14:32:13 UTC | 0xde26d6…94fd | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…94624eff data: 0x000000000000000000…00000001 |
| 0xdd2fcf…e1816d | 24 days agoFri, 24 Jul 2026 14:31:49 UTC | 0x9c4d94…9097 | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…914fde78 data: 0x000000000000000000…70df1ad2 |
| 0xdd2fcf…e1816d | 24 days agoFri, 24 Jul 2026 14:31:49 UTC | 0xde26d6…94fd | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…94624eff data: 0x000000000000000000…00000001 |
| 0x688579…3d2d0c | 24 days agoFri, 24 Jul 2026 14:31:35 UTC | 0x9c4d94…9097 | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…914fde78 data: 0x000000000000000000…72d4151e |
| 0x5f71d7…e3e355 | 24 days agoFri, 24 Jul 2026 14:20:27 UTC | 0x211327…2336 | [0] 0x8f041bcaf6ee…8d2809f4 data: 0x000000000000000000…00002710 |
| 0x5f71d7…e3e355 | 24 days agoFri, 24 Jul 2026 14:20:27 UTC | 0x01bf26…d573 | [0] 0x8f041bcaf6ee…8d2809f4 [1] 0x000000000000…26b05de6 [2] 0x000000000000…2b3b4c0c data: 0x000000000000000000…fa50aedd |
| 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 | |||||||||
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x3bac73…0714fa | flushProtocolFees | 18,231,024 | 24 days agoFri, 24 Jul 2026 14:45:57 UTC | 0x2e13…de78 | IN | DegenSpyV2Hook | $0.000 ETH | 0.00001969 |
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 18,137,064 | 24 days agoFri, 24 Jul 2026 12:08:58 UTC | 0xe6b37e…b387e9 | CREATE2 | optimized_routeFill921336808 | 0x4e59…956c | IN | 0xb3a0…f0cc | 0 ETH |