// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {BaseHook} from "@openzeppelin/uniswap-hooks/src/base/BaseHook.sol";
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
import {BalanceDelta, BalanceDeltaLibrary} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary, toBeforeSwapDelta} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol";
import {ModifyLiquidityParams, SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol";
import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol";
interface IPNGStrategyFeeSink {
function addFees() external payable;
function loadingLiquidity() external view returns (bool);
}
interface IERC20Like {
function transfer(address to, uint256 amount) external returns (bool);
}
contract PNGStrategyHook is BaseHook, Ownable, ReentrancyGuard {
using BalanceDeltaLibrary for BalanceDelta;
using CurrencyLibrary for Currency;
using PoolIdLibrary for PoolKey;
using SafeCast for uint256;
error NotStrategy();
error InvalidFeeBips();
error InvalidFeeShares();
error AddressZero();
error UnsupportedExactOut();
error TransferFailed();
error InvalidHookPool();
event FeeBipsUpdated(uint128 buyFeeBips, uint128 sellFeeBips, uint128 preAccumulationSellFeeBips);
event FeeRecipientsUpdated(address indexed ownerFeeRecipient, address indexed holderRewardsRecipient);
event FeeSharesUpdated(uint16 strategyShareBips, uint16 ownerShareBips, uint16 holderShareBips);
event ManualFeesUpdated(bool manualFees);
event HookFee(PoolId indexed poolId, address indexed sender, Currency indexed currency, uint256 amount);
event FeesCollected(Currency indexed currency, uint256 amount);
event FeesForwarded(uint256 strategyAmount, uint256 ownerAmount, uint256 holderRewardsAmount);
event TokensRecovered(address indexed token, address indexed to, uint256 amount);
event NftsAccumulationStarted();
uint256 public constant BPS = 10_000;
uint160 public constant REQUIRED_HOOK_FLAGS = uint160(
Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG | Hooks.BEFORE_SWAP_FLAG
| Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG | Hooks.AFTER_SWAP_FLAG
| Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG
);
IPNGStrategyFeeSink public immutable strategy;
Currency public immutable strategyToken;
address public ownerFeeRecipient;
address public holderRewardsRecipient;
uint128 public buyFeeBips;
uint128 public sellFeeBips;
uint128 public preAccumulationSellFeeBips;
uint16 public strategyShareBips;
uint16 public ownerShareBips;
uint16 public holderShareBips;
bool public manualFees;
bool public nftsAccumulating;
uint256 public accumulatedEthFees;
uint256 public accumulatedStrategyTokenFees;
uint256 public accumulatedOwnerTokenFees;
uint256 public accumulatedHolderTokenFees;
modifier onlyStrategy() {
if (msg.sender != address(strategy)) revert NotStrategy();
_;
}
constructor(
address owner_,
IPoolManager poolManager_,
address strategy_,
address strategyToken_,
address ownerFeeRecipient_,
address holderRewardsRecipient_,
uint128 buyFeeBips_,
uint128 sellFeeBips_,
uint128 preAccumulationSellFeeBips_,
uint16 strategyShareBips_,
uint16 ownerShareBips_,
uint16 holderShareBips_
) BaseHook(poolManager_) Ownable(owner_) {
if (
owner_ == address(0) || address(poolManager_) == address(0) || strategy_ == address(0)
|| strategyToken_ == address(0)
) {
revert AddressZero();
}
strategy = IPNGStrategyFeeSink(strategy_);
strategyToken = Currency.wrap(strategyToken_);
ownerFeeRecipient = ownerFeeRecipient_;
holderRewardsRecipient = holderRewardsRecipient_;
_setFeeBips(buyFeeBips_, sellFeeBips_, preAccumulationSellFeeBips_);
_setFeeShares(strategyShareBips_, ownerShareBips_, holderShareBips_);
}
receive() external payable {
if (msg.sender == address(poolManager)) return;
accumulatedEthFees += msg.value;
emit FeesCollected(CurrencyLibrary.ADDRESS_ZERO, msg.value);
}
function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
return Hooks.Permissions({
beforeInitialize: true,
afterInitialize: false,
beforeAddLiquidity: false,
afterAddLiquidity: true,
beforeRemoveLiquidity: false,
afterRemoveLiquidity: false,
beforeSwap: true,
afterSwap: true,
beforeDonate: false,
afterDonate: false,
beforeSwapReturnDelta: true,
afterSwapReturnDelta: true,
afterAddLiquidityReturnDelta: false,
afterRemoveLiquidityReturnDelta: false
});
}
function hasRequiredHookPermissions() external view returns (bool) {
return (uint160(address(this)) & Hooks.ALL_HOOK_MASK) == REQUIRED_HOOK_FLAGS;
}
function calculateFee(bool isBuying) public view returns (uint128) {
if (isBuying) return buyFeeBips;
return nftsAccumulating ? sellFeeBips : preAccumulationSellFeeBips;
}
function calculateFee(Currency inputCurrency) public view returns (uint128) {
if (inputCurrency.isAddressZero()) return calculateFee(true);
if (inputCurrency == strategyToken) return calculateFee(false);
return 0;
}
function processAccumulatedFees() external nonReentrant {
_forwardEthFees();
}
function nftsAreAccumulating() external onlyStrategy {
nftsAccumulating = true;
emit NftsAccumulationStarted();
}
function updateFeeBips(
uint128 buyFeeBips_,
uint128 sellFeeBips_,
uint128 preAccumulationSellFeeBips_
) external onlyOwner {
_setFeeBips(buyFeeBips_, sellFeeBips_, preAccumulationSellFeeBips_);
}
function updateFeeRecipients(address ownerFeeRecipient_, address holderRewardsRecipient_) external onlyOwner {
ownerFeeRecipient = ownerFeeRecipient_;
holderRewardsRecipient = holderRewardsRecipient_;
emit FeeRecipientsUpdated(ownerFeeRecipient_, holderRewardsRecipient_);
}
function updateFeeShares(uint16 strategyShareBips_, uint16 ownerShareBips_, uint16 holderShareBips_)
external
onlyOwner
{
_setFeeShares(strategyShareBips_, ownerShareBips_, holderShareBips_);
}
function updateManualFees(bool manualFees_) external onlyOwner {
manualFees = manualFees_;
emit ManualFeesUpdated(manualFees_);
}
function recoverToken(address token, address to, uint256 amount) external onlyOwner {
if (token == address(0) || to == address(0)) revert AddressZero();
if (!IERC20Like(token).transfer(to, amount)) revert TransferFailed();
emit TokensRecovered(token, to, amount);
}
function _beforeInitialize(address, PoolKey calldata key, uint160) internal view override returns (bytes4) {
_validatePoolKey(key);
if (!_isStrategyLoadingLiquidity()) revert InvalidHookPool();
return BaseHook.beforeInitialize.selector;
}
function _afterAddLiquidity(
address,
PoolKey calldata key,
ModifyLiquidityParams calldata,
BalanceDelta,
BalanceDelta,
bytes calldata
) internal view override returns (bytes4, BalanceDelta) {
_validatePoolKey(key);
if (!_isStrategyLoadingLiquidity()) revert InvalidHookPool();
return (BaseHook.afterAddLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA);
}
function _beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata)
internal
override
returns (bytes4, BeforeSwapDelta, uint24)
{
if (params.amountSpecified > 0) revert UnsupportedExactOut();
_validatePoolKey(key);
if (params.amountSpecified == 0 || !params.zeroForOne || _isStrategyLoadingLiquidity()) {
return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
}
uint128 feeBips = calculateFee(true);
if (feeBips == 0) return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
uint256 inputAmount = uint256(-params.amountSpecified);
uint256 feeAmount = inputAmount * feeBips / BPS;
if (feeAmount == 0) return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
poolManager.take(CurrencyLibrary.ADDRESS_ZERO, address(this), feeAmount);
_recordEthFee(feeAmount);
emit HookFee(key.toId(), sender, CurrencyLibrary.ADDRESS_ZERO, feeAmount);
return (BaseHook.beforeSwap.selector, toBeforeSwapDelta(feeAmount.toInt128(), 0), 0);
}
function _afterSwap(
address sender,
PoolKey calldata key,
SwapParams calldata params,
BalanceDelta delta,
bytes calldata
) internal override returns (bytes4, int128) {
if (params.amountSpecified > 0) revert UnsupportedExactOut();
_validatePoolKey(key);
if (params.amountSpecified == 0 || params.zeroForOne || _isStrategyLoadingLiquidity()) {
return (BaseHook.afterSwap.selector, 0);
}
uint128 feeBips = calculateFee(false);
if (feeBips == 0) return (BaseHook.afterSwap.selector, 0);
uint256 feeBaseAmount = _absoluteAmount(delta.amount0());
uint256 feeAmount = feeBaseAmount * feeBips / BPS;
if (feeAmount == 0) return (BaseHook.afterSwap.selector, 0);
poolManager.take(CurrencyLibrary.ADDRESS_ZERO, address(this), feeAmount);
_recordEthFee(feeAmount);
emit HookFee(key.toId(), sender, CurrencyLibrary.ADDRESS_ZERO, feeAmount);
return (BaseHook.afterSwap.selector, feeAmount.toInt128());
}
function _setFeeBips(
uint128 buyFeeBips_,
uint128 sellFeeBips_,
uint128 preAccumulationSellFeeBips_
) private {
if (buyFeeBips_ > BPS || sellFeeBips_ > BPS || preAccumulationSellFeeBips_ > BPS) {
revert InvalidFeeBips();
}
buyFeeBips = buyFeeBips_;
sellFeeBips = sellFeeBips_;
preAccumulationSellFeeBips = preAccumulationSellFeeBips_;
emit FeeBipsUpdated(buyFeeBips_, sellFeeBips_, preAccumulationSellFeeBips_);
}
function _setFeeShares(uint16 strategyShareBips_, uint16 ownerShareBips_, uint16 holderShareBips_) private {
if (uint256(strategyShareBips_) + ownerShareBips_ + holderShareBips_ != BPS) revert InvalidFeeShares();
strategyShareBips = strategyShareBips_;
ownerShareBips = ownerShareBips_;
holderShareBips = holderShareBips_;
emit FeeSharesUpdated(strategyShareBips_, ownerShareBips_, holderShareBips_);
}
function _recordEthFee(uint256 amount) private {
emit FeesCollected(CurrencyLibrary.ADDRESS_ZERO, amount);
accumulatedEthFees += amount;
if (!manualFees) _forwardEthFees();
}
function _absoluteAmount(int128 amount) private pure returns (uint256) {
return uint128(amount < 0 ? -amount : amount);
}
function _forwardEthFees() private {
uint256 amount = accumulatedEthFees;
if (amount == 0) return;
accumulatedEthFees = 0;
(uint256 strategyAmount, uint256 ownerAmount, uint256 holderAmount) = _splitFee(amount);
uint256 ownerPaid;
uint256 holderPaid;
if (ownerAmount > 0) {
if (ownerFeeRecipient == address(0)) {
strategyAmount += ownerAmount;
} else {
ownerPaid = ownerAmount;
_sendEth(ownerFeeRecipient, ownerPaid);
}
}
if (holderAmount > 0) {
if (holderRewardsRecipient == address(0)) {
strategyAmount += holderAmount;
} else {
holderPaid = holderAmount;
_sendEth(holderRewardsRecipient, holderPaid);
}
}
strategy.addFees{value: strategyAmount}();
emit FeesForwarded(strategyAmount, ownerPaid, holderPaid);
}
function _splitFee(uint256 amount)
private
view
returns (uint256 strategyAmount, uint256 ownerAmount, uint256 holderAmount)
{
ownerAmount = amount * ownerShareBips / BPS;
holderAmount = amount * holderShareBips / BPS;
strategyAmount = amount - ownerAmount - holderAmount;
}
function _sendEth(address to, uint256 amount) private {
(bool paid,) = payable(to).call{value: amount}("");
if (!paid) revert TransferFailed();
}
function _validatePoolKey(PoolKey calldata key) private view {
if (!key.currency0.isAddressZero() || !(key.currency1 == strategyToken) || address(key.hooks) != address(this))
{
revert InvalidHookPool();
}
}
function _isStrategyLoadingLiquidity() private view returns (bool) {
try strategy.loadingLiquidity() returns (bool loading) {
return loading;
} catch {
return false;
}
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "owner_",
"type": "address",
"internalType": "address"
},
{
"name": "poolManager_",
"type": "address",
"internalType": "contract IPoolManager"
},
{
"name": "strategy_",
"type": "address",
"internalType": "address"
},
{
"name": "strategyToken_",
"type": "address",
"internalType": "address"
},
{
"name": "ownerFeeRecipient_",
"type": "address",
"internalType": "address"
},
{
"name": "holderRewardsRecipient_",
"type": "address",
"internalType": "address"
},
{
"name": "buyFeeBips_",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "sellFeeBips_",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "preAccumulationSellFeeBips_",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "strategyShareBips_",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "ownerShareBips_",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "holderShareBips_",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "nonpayable"
},
{
"name": "AddressZero",
"type": "error",
"inputs": []
},
{
"name": "HookNotImplemented",
"type": "error",
"inputs": []
},
{
"name": "InvalidFeeBips",
"type": "error",
"inputs": []
},
{
"name": "InvalidFeeShares",
"type": "error",
"inputs": []
},
{
"name": "InvalidHookPool",
"type": "error",
"inputs": []
},
{
"name": "InvalidPool",
"type": "error",
"inputs": []
},
{
"name": "NotPoolManager",
"type": "error",
"inputs": []
},
{
"name": "NotSelf",
"type": "error",
"inputs": []
},
{
"name": "NotStrategy",
"type": "error",
"inputs": []
},
{
"name": "OwnableInvalidOwner",
"type": "error",
"inputs": [
{
"name": "owner",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "OwnableUnauthorizedAccount",
"type": "error",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ReentrancyGuardReentrantCall",
"type": "error",
"inputs": []
},
{
"name": "TransferFailed",
"type": "error",
"inputs": []
},
{
"name": "UnsupportedExactOut",
"type": "error",
"inputs": []
},
{
"name": "FeeBipsUpdated",
"type": "event",
"inputs": [
{
"name": "buyFeeBips",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "sellFeeBips",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "preAccumulationSellFeeBips",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
}
],
"anonymous": false
},
{
"name": "FeeRecipientsUpdated",
"type": "event",
"inputs": [
{
"name": "ownerFeeRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "holderRewardsRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "FeeSharesUpdated",
"type": "event",
"inputs": [
{
"name": "strategyShareBips",
"type": "uint16",
"indexed": false,
"internalType": "uint16"
},
{
"name": "ownerShareBips",
"type": "uint16",
"indexed": false,
"internalType": "uint16"
},
{
"name": "holderShareBips",
"type": "uint16",
"indexed": false,
"internalType": "uint16"
}
],
"anonymous": false
},
{
"name": "FeesCollected",
"type": "event",
"inputs": [
{
"name": "currency",
"type": "address",
"indexed": true,
"internalType": "Currency"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "FeesForwarded",
"type": "event",
"inputs": [
{
"name": "strategyAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "ownerAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "holderRewardsAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "HookFee",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "currency",
"type": "address",
"indexed": true,
"internalType": "Currency"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "ManualFeesUpdated",
"type": "event",
"inputs": [
{
"name": "manualFees",
"type": "bool",
"indexed": false,
"internalType": "bool"
}
],
"anonymous": false
},
{
"name": "NftsAccumulationStarted",
"type": "event",
"inputs": [],
"anonymous": false
},
{
"name": "OwnershipTransferred",
"type": "event",
"inputs": [
{
"name": "previousOwner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newOwner",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "TokensRecovered",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "REQUIRED_HOOK_FLAGS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint160",
"internalType": "uint160"
}
],
"stateMutability": "view"
},
{
"name": "accumulatedEthFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "accumulatedHolderTokenFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "accumulatedOwnerTokenFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "accumulatedStrategyTokenFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"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 ModifyLiquidityParams"
},
{
"name": "delta0",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "delta1",
"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 ModifyLiquidityParams"
},
{
"name": "delta0",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "delta1",
"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 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 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 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 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": "buyFeeBips",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "calculateFee",
"type": "function",
"inputs": [
{
"name": "inputCurrency",
"type": "address",
"internalType": "Currency"
}
],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "calculateFee",
"type": "function",
"inputs": [
{
"name": "isBuying",
"type": "bool",
"internalType": "bool"
}
],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"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": "hasRequiredHookPermissions",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "holderRewardsRecipient",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "holderShareBips",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "manualFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "nftsAccumulating",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "nftsAreAccumulating",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "owner",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "ownerFeeRecipient",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "ownerShareBips",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "poolManager",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IPoolManager"
}
],
"stateMutability": "view"
},
{
"name": "preAccumulationSellFeeBips",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "processAccumulatedFees",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "recoverToken",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "to",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "renounceOwnership",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "sellFeeBips",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "strategy",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IPNGStrategyFeeSink"
}
],
"stateMutability": "view"
},
{
"name": "strategyShareBips",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "strategyToken",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "Currency"
}
],
"stateMutability": "view"
},
{
"name": "transferOwnership",
"type": "function",
"inputs": [
{
"name": "newOwner",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "updateFeeBips",
"type": "function",
"inputs": [
{
"name": "buyFeeBips_",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "sellFeeBips_",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "preAccumulationSellFeeBips_",
"type": "uint128",
"internalType": "uint128"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "updateFeeRecipients",
"type": "function",
"inputs": [
{
"name": "ownerFeeRecipient_",
"type": "address",
"internalType": "address"
},
{
"name": "holderRewardsRecipient_",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "updateFeeShares",
"type": "function",
"inputs": [
{
"name": "strategyShareBips_",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "ownerShareBips_",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "holderShareBips_",
"type": "uint16",
"internalType": "uint16"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "updateManualFees",
"type": "function",
"inputs": [
{
"name": "manualFees_",
"type": "bool",
"internalType": "bool"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "receive",
"stateMutability": "payable"
}
]0x6080806040526004361015610024575b50361561001a575f80fd5b610022611453565b005b5f3560e01c908163012a73881461113a57508063093d0fb4146111125780630ff383fc146110ec578063199bff2c146110c757806321d0ee7014611057578063249d39e9146110ab578063259982e514611057578063439d81471461103a578063465f5eb814611017578063575e24b414610f635780635d3d6ff014610e7c57806361913acb14610e5c57806362735f4514610e3f57806368723f2b14610e1b57806368e4110014610d815780636c2bbe7e14610d2b5780636fe7e6eb14610cb3578063715018a614610c5c578063747efea114610c185780638da5cb5b14610bf157806390ef556314610bd45780639e783a5e14610bb15780639f063efc14610b3d578063a4aa021914610b17578063a7229fd9146109f7578063a8c62e76146109b3578063ac4e405414610996578063b14e93451461095d578063b47b2fb1146108ae578063b6a8b0fa146103b6578063babd639314610889578063bdc9614c1461081d578063c4e833ce146106b2578063c8318b511461068e578063d2ee924a1461066a578063d3993ab11461057b578063dc4c90d314610537578063dc98354e1461041a578063e1b4af69146103b6578063f1c5d4211461032e578063f1f73620146102af578063f2fde38b1461022a5763fb9e2ad914610209575f61000f565b34610226575f366003190112610226576020600654604051908152f35b5f80fd5b346102265760203660031901126102265761024361115d565b61024b611715565b6001600160a01b0316801561029c575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b34610226576040366003190112610226576102c861115d565b6102d0611173565b906102d9611715565b600180546001600160a01b039283166001600160a01b031991821681179092556002805494909316931683179091557f4182300636c495eb36cba32ee090bd595eedf4221699a0481083758fa17293c25f80a3005b34610226575f366003190112610226577f00000000000000000000000095b02e975fcfd1c1cf637659e80b0de68b16775e6001600160a01b031633036103a7576004805460ff60b81b1916600160b81b1790557fe503742e7f7c1f5afcf60125f6b874dc6ad22f12e9c7dd06578a9aad5e4c7d845f80a1005b6359935c8f60e11b5f5260045ffd5b34610226576103c4366112bf565b5050507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03163303925061040b91505057630a85dc2960e01b5f5260045ffd5b63570c108560e11b5f5260045ffd5b346102265760e03660031901126102265761043361115d565b5060a036602319011261022657610448611299565b507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316330361040b576024356001600160a01b038116908181036102265750158015906104ef575b80156104d1575b6104c2576104ab611ad6565b156104c257604051636e4c1aa760e11b8152602090f35b633286d5a560e21b5f5260045ffd5b5060a4356001600160a01b038116908190036102265730141561049f565b506044356001600160a01b0381169081810361022657507f00000000000000000000000095b02e975fcfd1c1cf637659e80b0de68b16775e6001600160a01b03161415610498565b34610226575f366003190112610226576040517f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03168152602090f35b34610226576060366003190112610226576004356001600160801b038116809103610226576024356001600160801b03811691828203610226576044356001600160801b038116809103610226576105d1611715565b6127108211801561065f575b8015610654575b610645577f426b7d65a197e385ff2bff3da28ea42698821441d6e0b8a036b44f73427609f7936060936001600160801b03199060801b168317600355816001600160801b0319600454161760045560405192835260208301526040820152a1005b634164b1c160e11b5f5260045ffd5b5061271081116105e4565b5061271084116105dd565b34610226575f36600319011261022657602061ffff60045460a01c16604051908152f35b34610226575f36600319011261022657602061ffff60045460801c16604051908152f35b34610226575f366003190112610226575f6101a06040516106d281611374565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e0820152826101008201528261012082015282610140820152826101608201528261018082015201526101c0602060405161073581611374565b60018152818101905f8252604081015f81526060820160018152608083015f815260a084015f815260c085016001815260e0860190600182526101008701925f84526101208801945f8652610140890196600188526101608a019860018a526101a06101808c019b5f8d52019b5f8d526040519d8e916001835251151591015251151560408d015251151560608c015251151560808b015251151560a08a015251151560c089015251151560e08801525115156101008701525115156101208601525115156101408501525115156101608401525115156101808301525115156101a0820152f35b34610226576020366003190112610226576004358015158091036102265760207f9b38a2b8fdba0fd51cfc4d550921f90857eb2d6e7bae4ffbcf8bfc424a659ec491610867611715565b6004805460ff60b01b191660b083901b60ff60b01b16179055604051908152a1005b34610226575f36600319011261022657602060ff60045460b81c166040519015158152f35b3461022657610160366003190112610226576108c861115d565b60a03660231901126102265760603660c3190112610226576101443567ffffffffffffffff81116102265761090190369060040161119d565b50507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316330361040b5761094360409161012435906118b4565b82516001600160e01b03199092168252600f0b6020820152f35b3461022657602036600319011261022657600435801515810361022657610985602091611405565b6001600160801b0360405191168152f35b34610226575f3660031901126102265760206124cc604051908152f35b34610226575f366003190112610226576040517f00000000000000000000000095b02e975fcfd1c1cf637659e80b0de68b16775e6001600160a01b03168152602090f35b3461022657606036600319011261022657610a1061115d565b610a18611173565b9060443590610a25611715565b6001600160a01b03169081158015610b06575b610af75760405163a9059cbb60e01b81526001600160a01b039093166004840181905260248401829052926020816044815f875af1908115610aec575f91610abd575b5015610aae5760207f401f439d865a766757ec78675925bd67198d5e78805aa41691b34b5d6a6cbbe691604051908152a3005b6312171d8360e31b5f5260045ffd5b610adf915060203d602011610ae5575b610ad781836113a5565b8101906113c7565b84610a7b565b503d610acd565b6040513d5f823e3d90fd5b639fabe1c160e01b5f5260045ffd5b506001600160a01b03831615610a38565b34610226575f3660031901126102265760206001600160801b0360045416604051908152f35b3461022657610b4b3661122f565b5093945050507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03163303915061040b905057610b8e90611a49565b610b96611ad6565b156104c257604080516327c18fbf60e21b81525f6020820152f35b34610226575f3660031901126102265760206124cc60405190613fff3016148152f35b34610226575f366003190112610226576020600854604051908152f35b34610226575f366003190112610226575f546040516001600160a01b039091168152602090f35b34610226575f366003190112610226576040517f00000000000000000000000095b02e975fcfd1c1cf637659e80b0de68b16775e6001600160a01b03168152602090f35b34610226575f36600319011261022657610c74611715565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346102265761010036600319011261022657610ccd61115d565b5060a036602319011261022657610ce2611299565b50610ceb6112af565b507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316330361040b57630a85dc2960e01b5f5260045ffd5b3461022657610d393661122f565b5050507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03163303935061040b9250505057630a85dc2960e01b5f5260045ffd5b34610226575f3660031901126102265760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005414610e0c5760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055610de661173b565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055005b633ee5aeb560e01b5f5260045ffd5b34610226575f36600319011261022657602061ffff60045460901c16604051908152f35b34610226575f366003190112610226576020600754604051908152f35b34610226575f36600319011261022657602060035460801c604051908152f35b346102265760603660031901126102265760043561ffff811690818103610226576024359161ffff831691828403610226576044359261ffff84169182850361022657610ec7611715565b612710610edd84610ed88588611432565b611432565b03610f54577f9003211b2b1521204f5050485a93c7cd6d95cd7de48fffd5111524a34cb22019956060956004549061ffff60a01b9060a01b169261ffff60801b9060801b169065ffffffffffff60801b1916179061ffff60901b9060901b16171760045560405192835260208301526040820152a1005b631938445560e21b5f5260045ffd5b346102265761014036600319011261022657610f7d61115d565b60a03660231901126102265760603660c3190112610226576101243567ffffffffffffffff811161022657610fb690369060040161119d565b50507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316330361040b5762ffffff610ff7606092611564565b906040939293519363ffffffff60e01b1684526020840152166040820152f35b3461022657602036600319011261022657602061098561103561115d565b611317565b34610226575f366003190112610226576020600554604051908152f35b3461022657611065366111cb565b5050507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03163303915061040b905057630a85dc2960e01b5f5260045ffd5b34610226575f3660031901126102265760206040516127108152f35b34610226575f36600319011261022657602060ff60045460b01c166040519015158152f35b34610226575f3660031901126102265760206001600160801b0360035416604051908152f35b34610226575f366003190112610226576002546040516001600160a01b039091168152602090f35b34610226575f366003190112610226576001546001600160a01b03168152602090f35b600435906001600160a01b038216820361022657565b602435906001600160a01b038216820361022657565b35906001600160a01b038216820361022657565b9181601f840112156102265782359167ffffffffffffffff8311610226576020838186019501011161022657565b90610160600319830112610226576004356001600160a01b0381168103610226579160a060231982011261022657602491608060c3198301126102265760c491610144359067ffffffffffffffff82116102265761122b9160040161119d565b9091565b906101a0600319830112610226576004356001600160a01b0381168103610226579160a060231982011261022657602491608060c3198301126102265760c49161014435916101643591610184359067ffffffffffffffff82116102265761122b9160040161119d565b60c435906001600160a01b038216820361022657565b60e435908160020b820361022657565b610120600319820112610226576004356001600160a01b0381168103610226579160a06023198301126102265760249160c4359160e43591610104359067ffffffffffffffff82116102265761122b9160040161119d565b6001600160a01b03168015611364577f00000000000000000000000095b02e975fcfd1c1cf637659e80b0de68b16775e6001600160a01b031614611359575f90565b6113616113df565b90565b506003546001600160801b031690565b6101c0810190811067ffffffffffffffff82111761139157604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff82111761139157604052565b90816020910312610226575180151581036102265790565b60045460ff8160b81c165f146113f9575060035460801c90565b6001600160801b031690565b6114235760045460ff8160b81c165f146113f9575060035460801c90565b6001600160801b036003541690565b9190820180921161143f57565b634e487b7160e01b5f52601160045260245ffd5b337f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316146114bf5761148f34600554611432565b6005555f7f9dc46f23cfb5ddcad0ae7ea2be38d47fec07bb9382ec7e564efc69e036dd66ce6020604051348152a2565b565b8181029291811591840414171561143f57565b91908260a09103126102265760405160a0810181811067ffffffffffffffff82111761139157604052809261150881611189565b825261151660208201611189565b6020830152604081013562ffffff811681036102265760408301526060810135908160020b820361022657606083019190915260800135906001600160a01b03821682036102265760800152565b5f60e4355f8113611706576115796024611a49565b801580156116f1575b80156116e3575b6116bd576001600160801b036115a76001600160801b036003541690565b169081156116cf57600160ff1b811461143f57612710916115c9915f036114c1565b0480156116bd577f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316803b1561022657604051630b0d9c0960e01b81525f600482018190523060248301526044820184905290918290606490829084905af18015610aec576116a7575b5081611696929361164b83611b48565b60a06116583660246114d4565b206040518481526001600160a01b03909216917f26b5f3ec2562e84dcc09cb8002a0426ddf2ede3bff12e20519a5a048ca48e76a90602090a4611b9a565b60801b916315d7892d60e21b929190565b61169692505f6116b6916113a5565b5f9161163b565b506315d7892d60e21b925f9250829150565b506315d7892d60e21b935f93508392509050565b506116ec611ad6565b611589565b5060c435801590811581036102265750611582565b635b3acf8160e11b5f5260045ffd5b5f546001600160a01b0316330361172857565b63118cdaa760e01b5f523360045260245ffd5b60055480156118b15761ffff905f6005556117886004549161178361271061177a8161176c888860901c16866114c1565b0496879660a01c16846114c1565b04938492611bbb565b611bbb565b915f915f9180611875575b508061183a575b507f00000000000000000000000095b02e975fcfd1c1cf637659e80b0de68b16775e6001600160a01b031690813b15610226575f84926004604051809781936319d6150d60e01b83525af1928315610aec577fe052930777d2b6e303996d5ce89a775b83694899239d3e185612f4239b34f9509460609461182a575b5060405192835260208301526040820152a1565b5f611834916113a5565b5f611816565b600254919390916001600160a01b03168061186257509061185a91611432565b915b5f61179a565b916118709194508092611bc8565b61185c565b600154919490916001600160a01b03168061189d57509061189591611432565b925b5f611793565b93509390806118ac9194611bc8565b611897565b50565b905f9060e4355f8113611706576118cb6024611a49565b158015611a24575b8015611a16575b6119dc576001600160801b036118ee6113df565b16908115611a045760801d80600f0b905f82125f146119ed57506f7fffffffffffffffffffffffffffffff19811461143f57612710916001600160801b03611939925f035b166114c1565b049081156119dc577f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b031692833b1561022657604051630b0d9c0960e01b81525f600482018190523060248301526044820185905290948590606490829084905af1938415610aec576119bc946119c7575b5061164b83611b48565b63b47b2fb160e01b91565b6119d49192505f906113a5565b5f905f6119b2565b5063b47b2fb160e01b925f92509050565b6119399150916001600160801b0361271093611933565b5063b47b2fb160e01b935f9350915050565b50611a1f611ad6565b6118da565b5060c43580151581146118d3575f80fd5b356001600160a01b03811681036102265790565b611a5281611a35565b6001600160a01b03161580159190611a92575b8115611a73575b506104c257565b60809150013560018060a01b038116809103610226573014155f611a6c565b9050611aa060208201611a35565b7f00000000000000000000000095b02e975fcfd1c1cf637659e80b0de68b16775e6001600160a01b039081169116141590611a65565b604051635289bcb160e01b81526020816004817f00000000000000000000000095b02e975fcfd1c1cf637659e80b0de68b16775e6001600160a01b03165afa5f9181611b27575b5061136157505f90565b611b4191925060203d602011610ae557610ad781836113a5565b905f611b1d565b611b7f905f7f9dc46f23cfb5ddcad0ae7ea2be38d47fec07bb9382ec7e564efc69e036dd66ce6020604051848152a2600554611432565b60055560ff60045460b01c1615611b9257565b6114bf61173b565b6001607f1b811015611bac57600f0b90565b6393dafdf160e01b5f5260045ffd5b9190820391821161143f57565b5f918291829182916001600160a01b03165af13d15611c1a573d67ffffffffffffffff81116113915760405190611c09601f8201601f1916602001836113a5565b81525f60203d92013e5b15610aae57565b611c1356fea264697066735822122013fe844015b2d755d80928a2d0327baf3be18d4c45337fc4ca5cf803c9ad0f5b64736f6c634300081a0033
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| no token holdings | ||||
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x5390bd…ea3b67 | 14 days agoMon, 03 Aug 2026 00:04:46 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…e9b05d31 [2] 0x000000000000…00000000 data: 0x000000000000000000…7fd02319 |
| 0x5390bd…ea3b67 | 14 days agoMon, 03 Aug 2026 00:04:46 UTC | 0xe05293…f950 | data: 0x000000000000000000…8cbe70ed |
| 0x5390bd…ea3b67 | 14 days agoMon, 03 Aug 2026 00:04:46 UTC | 0x9dc46f…66ce | [0] 0x000000000000…00000000 data: 0x000000000000000000…7fd02319 |
| 0xf4d3d4…10dbed | 14 days agoSun, 02 Aug 2026 20:33:47 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…e9b05d31 [2] 0x000000000000…00000000 data: 0x000000000000000000…078569c4 |
| 0xf4d3d4…10dbed | 14 days agoSun, 02 Aug 2026 20:33:47 UTC | 0xe05293…f950 | data: 0x000000000000000000…82419fba |
| 0xf4d3d4…10dbed | 14 days agoSun, 02 Aug 2026 20:33:47 UTC | 0x9dc46f…66ce | [0] 0x000000000000…00000000 data: 0x000000000000000000…078569c4 |
| 0xd13e98…280646 | 16 days agoFri, 31 Jul 2026 23:46:00 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…e9b05d31 [2] 0x000000000000…00000000 data: 0x000000000000000000…fd4b0800 |
| 0xd13e98…280646 | 16 days agoFri, 31 Jul 2026 23:46:00 UTC | 0xe05293…f950 | data: 0x000000000000000000…ff301c00 |
| 0xd13e98…280646 | 16 days agoFri, 31 Jul 2026 23:46:00 UTC | 0x9dc46f…66ce | [0] 0x000000000000…00000000 data: 0x000000000000000000…fd4b0800 |
| 0x0bfc5a…4876ea | 25 days agoThu, 23 Jul 2026 00:27:35 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…e9b05d31 [2] 0x000000000000…00000000 data: 0x000000000000000000…f2772800 |
| 0x0bfc5a…4876ea | 25 days agoThu, 23 Jul 2026 00:27:35 UTC | 0xe05293…f950 | data: 0x000000000000000000…fbf08c00 |
| 0x0bfc5a…4876ea | 25 days agoThu, 23 Jul 2026 00:27:35 UTC | 0x9dc46f…66ce | [0] 0x000000000000…00000000 data: 0x000000000000000000…f2772800 |
| 0x80b3e9…1e7b5f | 25 days agoWed, 22 Jul 2026 21:37:46 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…e9b05d31 [2] 0x000000000000…00000000 data: 0x000000000000000000…e4ee5000 |
| 0x80b3e9…1e7b5f | 25 days agoWed, 22 Jul 2026 21:37:46 UTC | 0xe05293…f950 | data: 0x000000000000000000…f7e11800 |
| 0x80b3e9…1e7b5f | 25 days agoWed, 22 Jul 2026 21:37:46 UTC | 0x9dc46f…66ce | [0] 0x000000000000…00000000 data: 0x000000000000000000…e4ee5000 |
| 0x8fc5d2…0a50ac | 26 days agoWed, 22 Jul 2026 19:46:31 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…e9b05d31 [2] 0x000000000000…00000000 data: 0x000000000000000000…fd4b0800 |
| 0x8fc5d2…0a50ac | 26 days agoWed, 22 Jul 2026 19:46:31 UTC | 0xe05293…f950 | data: 0x000000000000000000…ff301c00 |
| 0x8fc5d2…0a50ac | 26 days agoWed, 22 Jul 2026 19:46:31 UTC | 0x9dc46f…66ce | [0] 0x000000000000…00000000 data: 0x000000000000000000…fd4b0800 |
| 0x470906…e19ca8 | 26 days agoWed, 22 Jul 2026 17:59:14 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…e9b05d31 [2] 0x000000000000…00000000 data: 0x000000000000000000…fd4b0800 |
| 0x470906…e19ca8 | 26 days agoWed, 22 Jul 2026 17:59:14 UTC | 0xe05293…f950 | data: 0x000000000000000000…ff301c00 |
| 0x470906…e19ca8 | 26 days agoWed, 22 Jul 2026 17:59:14 UTC | 0x9dc46f…66ce | [0] 0x000000000000…00000000 data: 0x000000000000000000…fd4b0800 |
| 0x116471…318ab6 | 26 days agoWed, 22 Jul 2026 17:58:33 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…e9b05d31 [2] 0x000000000000…00000000 data: 0x000000000000000000…fea58400 |
| 0x116471…318ab6 | 26 days agoWed, 22 Jul 2026 17:58:33 UTC | 0xe05293…f950 | data: 0x000000000000000000…ff980e00 |
| 0x116471…318ab6 | 26 days agoWed, 22 Jul 2026 17:58:33 UTC | 0x9dc46f…66ce | [0] 0x000000000000…00000000 data: 0x000000000000000000…fea58400 |
| 0x6fac18…602605 | 26 days agoWed, 22 Jul 2026 16:55:32 UTC | 0x26b5f3…e76a | [0] 0x5089bc508c03…13a27ae6 [1] 0x000000000000…db8c0904 [2] 0x000000000000…00000000 data: 0x000000000000000000…d6afc000 |
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| no token transfers for this address yet | |||||||||
| 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 ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 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 → | |||||||||
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 26,317,378 | 14 days agoMon, 03 Aug 2026 00:04:46 UTC | 0x5390bd…ea3b67 | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0x95b0…775e | 0.00028 ETH |
| 26,317,378 | 14 days agoMon, 03 Aug 2026 00:04:46 UTC | 0x5390bd…ea3b67 | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0x2a1b…3f05 | 0.00014 ETH |
| 26,317,378 | 14 days agoMon, 03 Aug 2026 00:04:46 UTC | 0x5390bd…ea3b67 | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0xb711…bb2c | 0.00004 ETH |
| 26,317,378 | 14 days agoMon, 03 Aug 2026 00:04:46 UTC | 0x5390bd…ea3b67 | CALL | dagSwapTo | 0x8366…0951 | IN | 0x3ef7…24cc | 0.00047 ETH |
| 26,190,937 | 14 days agoSun, 02 Aug 2026 20:33:47 UTC | 0xf4d3d4…10dbed | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0x95b0…775e | 0.00308 ETH |
| 26,190,937 | 14 days agoSun, 02 Aug 2026 20:33:47 UTC | 0xf4d3d4…10dbed | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0x2a1b…3f05 | 0.00154 ETH |
| 26,190,937 | 14 days agoSun, 02 Aug 2026 20:33:47 UTC | 0xf4d3d4…10dbed | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0xb711…bb2c | 0.00051 ETH |
| 26,190,937 | 14 days agoSun, 02 Aug 2026 20:33:47 UTC | 0xf4d3d4…10dbed | CALL | dagSwapTo | 0x8366…0951 | IN | 0x3ef7…24cc | 0.00514 ETH |
| 24,583,189 | 16 days agoFri, 31 Jul 2026 23:46:00 UTC | 0xd13e98…280646 | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0x95b0…775e | 0.00003 ETH |
| 24,583,189 | 16 days agoFri, 31 Jul 2026 23:46:00 UTC | 0xd13e98…280646 | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0x2a1b…3f05 | 0.00001 ETH |
| 24,583,189 | 16 days agoFri, 31 Jul 2026 23:46:00 UTC | 0xd13e98…280646 | CALL | dagSwapTo | 0x3ef7…24cc | OUT | 0xb711…bb2c | 0.00000 ETH |
| 24,583,189 | 16 days agoFri, 31 Jul 2026 23:46:00 UTC | 0xd13e98…280646 | CALL | dagSwapTo | 0x8366…0951 | IN | 0x3ef7…24cc | 0.00005 ETH |
| 16,856,072 | 25 days agoThu, 23 Jul 2026 00:27:35 UTC | 0x0bfc5a…4876ea | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0x95b0…775e | 0.00017 ETH |
| 16,856,072 | 25 days agoThu, 23 Jul 2026 00:27:35 UTC | 0x0bfc5a…4876ea | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0x2a1b…3f05 | 0.00008 ETH |
| 16,856,072 | 25 days agoThu, 23 Jul 2026 00:27:35 UTC | 0x0bfc5a…4876ea | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0xb711…bb2c | 0.00002 ETH |
| 16,856,072 | 25 days agoThu, 23 Jul 2026 00:27:35 UTC | 0x0bfc5a…4876ea | CALL | dagSwapByOrderId | 0x8366…0951 | IN | 0x3ef7…24cc | 0.00029 ETH |
| 16,754,482 | 25 days agoWed, 22 Jul 2026 21:37:46 UTC | 0x80b3e9…1e7b5f | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0x95b0…775e | 0.00035 ETH |
| 16,754,482 | 25 days agoWed, 22 Jul 2026 21:37:46 UTC | 0x80b3e9…1e7b5f | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0x2a1b…3f05 | 0.00017 ETH |
| 16,754,482 | 25 days agoWed, 22 Jul 2026 21:37:46 UTC | 0x80b3e9…1e7b5f | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0xb711…bb2c | 0.00005 ETH |
| 16,754,482 | 25 days agoWed, 22 Jul 2026 21:37:46 UTC | 0x80b3e9…1e7b5f | CALL | dagSwapByOrderId | 0x8366…0951 | IN | 0x3ef7…24cc | 0.00059 ETH |
| 16,687,853 | 26 days agoWed, 22 Jul 2026 19:46:31 UTC | 0x8fc5d2…0a50ac | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0x95b0…775e | 0.00003 ETH |
| 16,687,853 | 26 days agoWed, 22 Jul 2026 19:46:31 UTC | 0x8fc5d2…0a50ac | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0x2a1b…3f05 | 0.00001 ETH |
| 16,687,853 | 26 days agoWed, 22 Jul 2026 19:46:31 UTC | 0x8fc5d2…0a50ac | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0xb711…bb2c | 0.00000 ETH |
| 16,687,853 | 26 days agoWed, 22 Jul 2026 19:46:31 UTC | 0x8fc5d2…0a50ac | CALL | dagSwapByOrderId | 0x8366…0951 | IN | 0x3ef7…24cc | 0.00005 ETH |
| 16,623,610 | 26 days agoWed, 22 Jul 2026 17:59:14 UTC | 0x470906…e19ca8 | CALL | dagSwapByOrderId | 0x3ef7…24cc | OUT | 0x95b0…775e | 0.00003 ETH |