Source Code
Overview
MON Balance
MON Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 51322047 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON | |||||
| 51322009 | 8 mins ago | 0 MON |
Loading...
Loading
Contract Name:
UniswapV4Connector
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {
IPositionManager
} from "contracts/interfaces/external/uniswap/v4/IPositionManager.sol";
import { IHooks } from "contracts/interfaces/external/uniswap/v4/IHooks.sol";
import {
IStateView
} from "contracts/interfaces/external/uniswap/v4/IStateView.sol";
import {
PoolId
} from "contracts/interfaces/external/uniswap/v4/types/PoolId.sol";
import {
PoolKey
} from "contracts/interfaces/external/uniswap/v4/types/PoolKey.sol";
import {
PositionInfo
} from "contracts/interfaces/external/uniswap/v4/libraries/PositionInfoLibrary.sol";
import {
Actions
} from "contracts/interfaces/external/uniswap/v4/libraries/Actions.sol";
import {
Currency
} from "contracts/interfaces/external/uniswap/v4/types/Currency.sol";
import {
IAllowanceTransfer
} from "contracts/interfaces/external/IAllowanceTransfer.sol";
import { INftFarmConnector } from "contracts/interfaces/INftFarmConnector.sol";
import {
INftLiquidityConnector,
NftPoolInfo,
NftPoolKey,
NftPositionInfo
} from "contracts/interfaces/INftLiquidityConnector.sol";
import {
NftAddLiquidity,
NftRemoveLiquidity
} from "contracts/structs/NftLiquidityStructs.sol";
import { NftPosition } from "contracts/structs/NftFarmStrategyStructs.sol";
import {
FullMath
} from "contracts/interfaces/external/uniswap/v4/libraries/FullMath.sol";
import {
FixedPoint128
} from "contracts/interfaces/external/uniswap/v4/libraries/FixedPoint128.sol";
import {
Position
} from "contracts/interfaces/external/uniswap/v4/libraries/Position.sol";
struct UniswapV4MintExtraData {
uint24 tickSpacing;
IHooks hooks;
bytes hookData;
uint128 liquidity;
}
struct UniswapV4RemoveExtraData {
Currency currency0;
Currency currency1;
bytes hookData;
}
address constant UNISWAP_ETH = 0x0000000000000000000000000000000000000000;
address constant PERMIT_2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
contract UniswapV4Connector is INftLiquidityConnector, INftFarmConnector {
error InvalidParameters();
error InvalidDesiredAmount();
error InvalidTokenOwner();
IPositionManager public immutable positionManager;
IStateView public immutable stateView;
constructor(
IPositionManager positionManager_,
IStateView stateView_
) {
positionManager = positionManager_;
stateView = stateView_;
}
function addLiquidity(
NftAddLiquidity memory addLiquidityParams
)
external
virtual
override
checkAmountsForOverflow(
addLiquidityParams.amount0Desired, addLiquidityParams.amount1Desired
)
{
_addLiquidityInternal(addLiquidityParams);
}
function _addLiquidityInternal(
NftAddLiquidity memory addLiquidityParams
) internal virtual {
if (addLiquidityParams.pool.token0 != UNISWAP_ETH) {
IERC20(addLiquidityParams.pool.token0)
.approve(address(PERMIT_2), addLiquidityParams.amount0Desired);
IAllowanceTransfer(PERMIT_2)
.approve(
addLiquidityParams.pool.token0,
address(addLiquidityParams.nft),
uint160(addLiquidityParams.amount0Desired),
uint48(block.timestamp)
);
}
IERC20(addLiquidityParams.pool.token1)
.approve(address(PERMIT_2), addLiquidityParams.amount1Desired);
IAllowanceTransfer(PERMIT_2)
.approve(
addLiquidityParams.pool.token1,
address(addLiquidityParams.nft),
uint160(addLiquidityParams.amount1Desired),
uint48(block.timestamp)
);
if (addLiquidityParams.tokenId == 0) {
_mint(addLiquidityParams);
} else {
_increaseLiquidity(addLiquidityParams);
}
// Revoke approvals
if (addLiquidityParams.pool.token0 != UNISWAP_ETH) {
IERC20(addLiquidityParams.pool.token0).approve(address(PERMIT_2), 0);
}
IERC20(addLiquidityParams.pool.token1).approve(address(PERMIT_2), 0);
}
function _getCurrentLiquidity(
NftRemoveLiquidity memory removeLiquidityParams
) internal view virtual returns (uint128 currentLiquidity) {
return IPositionManager(address(removeLiquidityParams.nft))
.getPositionLiquidity(removeLiquidityParams.tokenId);
}
function removeLiquidity(
NftRemoveLiquidity memory removeLiquidityParams
)
external
override
checkAmountsForOverflow(
removeLiquidityParams.amount0Min, removeLiquidityParams.amount1Min
)
{
uint128 currentLiquidity = _getCurrentLiquidity(removeLiquidityParams);
if (removeLiquidityParams.liquidity == type(uint128).max) {
removeLiquidityParams.liquidity = currentLiquidity;
}
if (removeLiquidityParams.liquidity == 0) {
revert InvalidParameters();
}
if (removeLiquidityParams.liquidity == currentLiquidity) {
_burnNft(removeLiquidityParams);
} else {
_decreaseLiquidity(removeLiquidityParams);
}
}
function depositExistingNft(
NftPosition calldata, // position,
bytes calldata // extraData
) external virtual override { }
function withdrawNft(
NftPosition calldata, // position,
bytes calldata // extraData
) external virtual override { }
function claim(
NftPosition calldata position,
address[] memory, // rewardTokens
uint128, // amount0Max
uint128, // amount1Max
bytes calldata extraData
) external virtual override {
_collect(
IPositionManager(address(position.nft)), position.tokenId, extraData
);
}
function fee(
address, // pool
uint256 tokenId
) external view virtual override returns (uint24) {
(PoolKey memory poolKey,) =
positionManager.getPoolAndPositionInfo(tokenId);
(,,, uint24 lpFee) = stateView.getSlot0(poolKey.toId());
return lpFee;
}
function poolInfo(
address, // pool
bytes32 poolId
) external view virtual override returns (NftPoolInfo memory) {
(uint160 sqrtPriceX96, int24 tick_,, uint24 lpFee) =
stateView.getSlot0(PoolId.wrap(poolId));
(uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) =
stateView.getFeeGrowthGlobals(PoolId.wrap(poolId));
uint128 liquidity = stateView.getLiquidity(PoolId.wrap(poolId));
PoolKey memory poolKey = positionManager.poolKeys(bytes25(poolId));
return NftPoolInfo({
token0: Currency.unwrap(poolKey.currency0),
token1: Currency.unwrap(poolKey.currency1),
fee: lpFee,
tickSpacing: uint24(poolKey.tickSpacing),
sqrtPriceX96: sqrtPriceX96,
tick: tick_,
liquidity: liquidity,
feeGrowthGlobal0X128: feeGrowthGlobal0X128,
feeGrowthGlobal1X128: feeGrowthGlobal1X128
});
}
function positionLiquidity(
address, // nftManager
uint256 tokenId
)
public
view
virtual
override
returns (int24 tickLower, int24 tickUpper, uint128 liquidity)
{
PositionInfo positionInfo_ = positionManager.positionInfo(tokenId);
tickLower = positionInfo_.tickLower();
tickUpper = positionInfo_.tickUpper();
liquidity = positionManager.getPositionLiquidity(tokenId);
}
function positionPoolKey(
address, // poolFactory
address, // nftManager
uint256 tokenId
) external view virtual override returns (NftPoolKey memory) {
(PoolKey memory poolKey,) =
positionManager.getPoolAndPositionInfo(tokenId);
return NftPoolKey({
poolAddress: address(0), // not used by Uniswap V4
poolId: PoolId.unwrap(poolKey.toId())
});
}
function getTokenId(
address, // nftManager
address owner
) external view virtual override returns (uint256 tokenId) {
tokenId = positionManager.nextTokenId() - 1;
if (positionManager.ownerOf(tokenId) != owner) {
revert InvalidTokenOwner();
}
return tokenId;
}
function totalSupply(
address // nftManager
) external view virtual override returns (uint256) {
return positionManager.nextTokenId() - 1;
}
function _mint(
NftAddLiquidity memory addLiquidityParams
) internal virtual {
UniswapV4MintExtraData memory extraData =
abi.decode(addLiquidityParams.extraData, (UniswapV4MintExtraData));
bytes memory actions = abi.encodePacked(
uint8(Actions.MINT_POSITION),
uint8(Actions.SETTLE_PAIR),
uint8(Actions.SWEEP)
);
bytes[] memory params = new bytes[](3);
Currency currency0 = Currency.wrap(addLiquidityParams.pool.token0);
Currency currency1 = Currency.wrap(addLiquidityParams.pool.token1);
PoolKey memory poolKey = PoolKey({
currency0: currency0,
currency1: currency1,
fee: addLiquidityParams.pool.fee,
tickSpacing: int24(extraData.tickSpacing),
hooks: IHooks(extraData.hooks)
});
params[0] = abi.encode(
poolKey,
addLiquidityParams.tickLower,
addLiquidityParams.tickUpper,
extraData.liquidity,
addLiquidityParams.amount0Desired,
addLiquidityParams.amount1Desired,
address(this),
extraData.hookData
);
params[1] = abi.encode(currency0, currency1);
params[2] = abi.encode(UNISWAP_ETH, address(this));
uint256 valueToPass =
currency0.isAddressZero() ? addLiquidityParams.amount0Desired : 0;
IPositionManager(address(addLiquidityParams.nft))
.modifyLiquidities{ value: valueToPass }(
abi.encode(actions, params), block.timestamp
);
}
function _increaseLiquidity(
NftAddLiquidity memory addLiquidityParams
) internal {
UniswapV4MintExtraData memory extraData =
abi.decode(addLiquidityParams.extraData, (UniswapV4MintExtraData));
Currency currency0 = Currency.wrap(addLiquidityParams.pool.token0);
Currency currency1 = Currency.wrap(addLiquidityParams.pool.token1);
bytes memory actions;
bytes[] memory params;
// Check if position is out of range (only one token needed)
bool isOutOfRange = addLiquidityParams.amount0Desired == 0
|| addLiquidityParams.amount1Desired == 0;
if (isOutOfRange) {
// Out of range: use SETTLE for token being deposited,
// CLOSE_CURRENCY for the other. CLOSE_CURRENCY handles any fee
// deltas (positive or
// negative) which SETTLE_PAIR cannot handle when fees are owed.
bool needsToken0 = addLiquidityParams.amount0Desired > 0;
Currency currencyToSettle = needsToken0 ? currency0 : currency1;
Currency currencyToClose = needsToken0 ? currency1 : currency0;
// For SETTLE: payerIsUser=true uses Permit2 to pull from caller,
// payerIsUser=false uses sync()+transfer() from position manager.
// For non-native currencies, we need payerIsUser=true since tokens
// are held by the sickle (caller), not the position manager.
bool payerIsUser = !currencyToSettle.isAddressZero();
actions = abi.encodePacked(
uint8(Actions.INCREASE_LIQUIDITY),
uint8(Actions.SETTLE),
uint8(Actions.CLOSE_CURRENCY),
uint8(Actions.SWEEP)
);
params = new bytes[](4);
params[0] = abi.encode(
addLiquidityParams.tokenId,
extraData.liquidity,
addLiquidityParams.amount0Desired,
addLiquidityParams.amount1Desired,
extraData.hookData
);
params[1] = abi.encode(currencyToSettle, uint256(0), payerIsUser);
params[2] = abi.encode(currencyToClose);
params[3] = abi.encode(UNISWAP_ETH, address(this));
} else {
actions = abi.encodePacked(
uint8(Actions.INCREASE_LIQUIDITY),
uint8(Actions.SETTLE_PAIR),
uint8(Actions.SWEEP)
);
params = new bytes[](3);
params[0] = abi.encode(
addLiquidityParams.tokenId,
extraData.liquidity,
addLiquidityParams.amount0Desired,
addLiquidityParams.amount1Desired,
extraData.hookData
);
params[1] = abi.encode(currency0, currency1);
params[2] = abi.encode(UNISWAP_ETH, address(this));
}
uint256 valueToPass =
currency0.isAddressZero() ? addLiquidityParams.amount0Desired : 0;
IPositionManager(address(addLiquidityParams.nft))
.modifyLiquidities{ value: valueToPass }(
abi.encode(actions, params), block.timestamp
);
}
function _burnNft(
NftRemoveLiquidity memory removeLiquidityParams
) internal {
UniswapV4RemoveExtraData memory extraData = abi.decode(
removeLiquidityParams.extraData, (UniswapV4RemoveExtraData)
);
bytes memory actions = abi.encodePacked(
uint8(Actions.BURN_POSITION), uint8(Actions.TAKE_PAIR)
);
bytes[] memory params = new bytes[](2);
params[0] = abi.encode(
removeLiquidityParams.tokenId,
uint128(0),
uint128(0),
extraData.hookData
);
params[1] =
abi.encode(extraData.currency0, extraData.currency1, address(this));
IPositionManager(address(removeLiquidityParams.nft))
.modifyLiquidities(abi.encode(actions, params), block.timestamp);
}
function _decreaseLiquidity(
NftRemoveLiquidity memory removeLiquidityParams
) internal {
UniswapV4RemoveExtraData memory extraData = abi.decode(
removeLiquidityParams.extraData, (UniswapV4RemoveExtraData)
);
bytes memory actions = abi.encodePacked(
uint8(Actions.DECREASE_LIQUIDITY), uint8(Actions.TAKE_PAIR)
);
bytes[] memory params = new bytes[](2);
params[0] = abi.encode(
removeLiquidityParams.tokenId,
removeLiquidityParams.liquidity,
removeLiquidityParams.amount0Min,
removeLiquidityParams.amount1Min,
extraData.hookData
);
params[1] =
abi.encode(extraData.currency0, extraData.currency1, address(this));
IPositionManager(address(removeLiquidityParams.nft))
.modifyLiquidities(abi.encode(actions, params), block.timestamp);
}
function _collect(
IPositionManager nft,
uint256 tokenId,
bytes memory extraData
) internal {
UniswapV4RemoveExtraData memory removeExtraData =
abi.decode(extraData, (UniswapV4RemoveExtraData));
bytes memory actions = abi.encodePacked(
uint8(Actions.DECREASE_LIQUIDITY), uint8(Actions.TAKE_PAIR)
);
bytes[] memory params = new bytes[](2);
params[0] = abi.encode(tokenId, 0, 0, 0, removeExtraData.hookData);
params[1] = abi.encode(
removeExtraData.currency0, removeExtraData.currency1, address(this)
);
nft.modifyLiquidities(abi.encode(actions, params), block.timestamp);
}
function isStaked(
address, // user
NftPosition calldata
) external view virtual override returns (bool) {
return false; // Uniswap V4 does not support staking
}
function earned(
address, // user
NftPosition calldata, // position
address[] memory rewardTokens
) external view virtual override returns (uint256[] memory) {
// Uniswap V4 does not support token incentives
return new uint256[](rewardTokens.length);
}
modifier checkAmountsForOverflow(
uint256 amount0,
uint256 amount1
) {
if (amount0 > type(uint128).max) {
revert InvalidDesiredAmount();
}
if (amount1 > type(uint128).max) {
revert InvalidDesiredAmount();
}
_;
}
function earnedFees(
address, // nftManager
address, // pool
uint256 tokenId
) external view override returns (uint256 fees0, uint256 fees1) {
(PoolKey memory poolKey,) =
positionManager.getPoolAndPositionInfo(tokenId);
(int24 tickLower, int24 tickUpper, uint128 liquidity) =
positionLiquidity(address(0), tokenId);
PoolId poolId = PoolId.wrap(PoolId.unwrap(poolKey.toId()));
(
uint256 poolFeeGrowthInside0LastX128,
uint256 poolFeeGrowthInside1LastX128
) = stateView.getFeeGrowthInside(poolId, tickLower, tickUpper);
bytes32 positionKey = Position.calculatePositionKey(
address(positionManager), tickLower, tickUpper, bytes32(tokenId)
);
(
,
uint256 positionFeeGrowthInside0LastX128,
uint256 positionFeeGrowthInside1LastX128
) = stateView.getPositionInfo(poolId, positionKey);
unchecked {
fees0 = FullMath.mulDiv(
poolFeeGrowthInside0LastX128 - positionFeeGrowthInside0LastX128,
liquidity,
FixedPoint128.Q128
);
fees1 = FullMath.mulDiv(
poolFeeGrowthInside1LastX128 - positionFeeGrowthInside1LastX128,
liquidity,
FixedPoint128.Q128
);
}
}
function positionInfo(
address nftManager,
uint256 tokenId
) external view virtual override returns (NftPositionInfo memory) {
(int24 tickLower, int24 tickUpper, uint128 liquidity) =
positionLiquidity(nftManager, tokenId);
return NftPositionInfo({
liquidity: liquidity, tickLower: tickLower, tickUpper: tickUpper
});
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { PoolKey } from "./types/PoolKey.sol";
import { PositionInfo } from "./libraries/PositionInfoLibrary.sol";
import { IPoolManager } from "./IPoolManager.sol";
interface IImmutableState {
/// @notice The Uniswap v4 PoolManager contract
function poolManager() external view returns (IPoolManager);
}
/// @title IPositionManager
/// @notice Interface for the PositionManager contract
interface IPositionManager is IImmutableState {
/// @notice Thrown when the caller is not approved to modify a position
error NotApproved(address caller);
/// @notice Thrown when the block.timestamp exceeds the user-provided
/// deadline
error DeadlinePassed(uint256 deadline);
/// @notice Thrown when calling transfer, subscribe, or unsubscribe when the
/// PoolManager is unlocked.
/// @dev This is to prevent hooks from being able to trigger notifications
/// at the same time the position is being modified.
error PoolManagerMustBeLocked();
/// @notice Unlocks Uniswap v4 PoolManager and batches actions for modifying
/// liquidity
/// @dev This is the standard entrypoint for the PositionManager
/// @param unlockData is an encoding of actions, and parameters for those
/// actions
/// @param deadline is the deadline for the batched actions to be executed
function modifyLiquidities(
bytes calldata unlockData,
uint256 deadline
) external payable;
/// @notice Batches actions for modifying liquidity without unlocking v4
/// PoolManager
/// @dev This must be called by a contract that has already unlocked the v4
/// PoolManager
/// @param actions the actions to perform
/// @param params the parameters to provide for the actions
function modifyLiquiditiesWithoutUnlock(
bytes calldata actions,
bytes[] calldata params
) external payable;
/// @notice Used to get the ID that will be used for the next minted
/// liquidity position
/// @return uint256 The next token ID
function nextTokenId() external view returns (uint256);
/// @notice Returns the liquidity of a position
/// @param tokenId the ERC721 tokenId
/// @return liquidity the position's liquidity, as a liquidityAmount
/// @dev this value can be processed as an amount0 and amount1 by using the
/// LiquidityAmounts library
function getPositionLiquidity(
uint256 tokenId
) external view returns (uint128 liquidity);
/// @notice Returns the pool key and position info of a position
/// @param tokenId the ERC721 tokenId
/// @return poolKey the pool key of the position
/// @return PositionInfo a uint256 packed value holding information about
/// the position including the range (tickLower, tickUpper)
function getPoolAndPositionInfo(
uint256 tokenId
) external view returns (PoolKey memory, PositionInfo);
/// @notice Returns the position info of a position
/// @param tokenId the ERC721 tokenId
/// @return a uint256 packed value holding information about the position
/// including the range (tickLower, tickUpper)
function positionInfo(
uint256 tokenId
) external view returns (PositionInfo);
/// @notice Returns the pool key of a pool
/// @param poolId the pool ID
/// @return poolKey the pool key of the pool
function poolKeys(
bytes25 poolId
) external view returns (PoolKey memory);
/// @notice Returns the owner of a token
/// @param tokenId the ERC721 tokenId
/// @return owner the owner of the token
function ownerOf(
uint256 tokenId
) external view returns (address);
/// @notice Subscribe a position to a subscriber contract for notifications
/// @param tokenId the ERC721 tokenId
/// @param subscriber the subscriber contract address
/// @param data optional data to pass to the subscriber
function subscribe(
uint256 tokenId,
address subscriber,
bytes calldata data
) external;
/// @notice Check if a position has a subscriber
/// @param tokenId the ERC721 tokenId
/// @return hasSubscriber true if the position has a subscriber
function hasSubscriber(
uint256 tokenId
) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { PoolKey } from "./types/PoolKey.sol";
import { BalanceDelta } from "./types/BalanceDelta.sol";
import { IPoolManager } from "./IPoolManager.sol";
import { BeforeSwapDelta } from "./types/BeforeSwapDelta.sol";
/// @notice V4 decides whether to invoke specific hooks by inspecting the least
/// significant bits
/// of the address that the hooks contract is deployed to.
/// For example, a hooks contract deployed to address:
/// 0x0000000000000000000000000000000000002400
/// has the lowest bits '10 0100 0000 0000' which would cause the 'before
/// initialize' and 'after add liquidity' hooks to be used.
/// See the Hooks library for the full spec.
/// @dev Should only be callable by the v4 PoolManager.
interface IHooks {
/// @notice The hook called before the state of a pool is initialized
/// @param sender The initial msg.sender for the initialize call
/// @param key The key for the pool being initialized
/// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96
/// @return bytes4 The function selector for the hook
function beforeInitialize(
address sender,
PoolKey calldata key,
uint160 sqrtPriceX96
) external returns (bytes4);
/// @notice The hook called after the state of a pool is initialized
/// @param sender The initial msg.sender for the initialize call
/// @param key The key for the pool being initialized
/// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96
/// @param tick The current tick after the state of a pool is initialized
/// @return bytes4 The function selector for the hook
function afterInitialize(
address sender,
PoolKey calldata key,
uint160 sqrtPriceX96,
int24 tick
) external returns (bytes4);
/// @notice The hook called before liquidity is added
/// @param sender The initial msg.sender for the add liquidity call
/// @param key The key for the pool
/// @param params The parameters for adding liquidity
/// @param hookData Arbitrary data handed into the PoolManager by the
/// liquidity provider to be passed on to the hook
/// @return bytes4 The function selector for the hook
function beforeAddLiquidity(
address sender,
PoolKey calldata key,
IPoolManager.ModifyLiquidityParams calldata params,
bytes calldata hookData
) external returns (bytes4);
/// @notice The hook called after liquidity is added
/// @param sender The initial msg.sender for the add liquidity call
/// @param key The key for the pool
/// @param params The parameters for adding liquidity
/// @param delta The caller's balance delta after adding liquidity; the sum
/// of principal delta, fees accrued, and hook delta
/// @param feesAccrued The fees accrued since the last time fees were
/// collected from this position
/// @param hookData Arbitrary data handed into the PoolManager by the
/// liquidity provider to be passed on to the hook
/// @return bytes4 The function selector for the hook
/// @return BalanceDelta The hook's delta in token0 and token1. Positive:
/// the hook is owed/took currency, negative: the hook owes/sent currency
function afterAddLiquidity(
address sender,
PoolKey calldata key,
IPoolManager.ModifyLiquidityParams calldata params,
BalanceDelta delta,
BalanceDelta feesAccrued,
bytes calldata hookData
) external returns (bytes4, BalanceDelta);
/// @notice The hook called before liquidity is removed
/// @param sender The initial msg.sender for the remove liquidity call
/// @param key The key for the pool
/// @param params The parameters for removing liquidity
/// @param hookData Arbitrary data handed into the PoolManager by the
/// liquidity provider to be be passed on to the hook
/// @return bytes4 The function selector for the hook
function beforeRemoveLiquidity(
address sender,
PoolKey calldata key,
IPoolManager.ModifyLiquidityParams calldata params,
bytes calldata hookData
) external returns (bytes4);
/// @notice The hook called after liquidity is removed
/// @param sender The initial msg.sender for the remove liquidity call
/// @param key The key for the pool
/// @param params The parameters for removing liquidity
/// @param delta The caller's balance delta after removing liquidity; the
/// sum of principal delta, fees accrued, and hook delta
/// @param feesAccrued The fees accrued since the last time fees were
/// collected from this position
/// @param hookData Arbitrary data handed into the PoolManager by the
/// liquidity provider to be be passed on to the hook
/// @return bytes4 The function selector for the hook
/// @return BalanceDelta The hook's delta in token0 and token1. Positive:
/// the hook is owed/took currency, negative: the hook owes/sent currency
function afterRemoveLiquidity(
address sender,
PoolKey calldata key,
IPoolManager.ModifyLiquidityParams calldata params,
BalanceDelta delta,
BalanceDelta feesAccrued,
bytes calldata hookData
) external returns (bytes4, BalanceDelta);
/// @notice The hook called before a swap
/// @param sender The initial msg.sender for the swap call
/// @param key The key for the pool
/// @param params The parameters for the swap
/// @param hookData Arbitrary data handed into the PoolManager by the
/// swapper to be be passed on to the hook
/// @return bytes4 The function selector for the hook
/// @return BeforeSwapDelta The hook's delta in specified and unspecified
/// currencies. Positive: the hook is owed/took currency, negative: the hook
/// owes/sent currency
/// @return uint24 Optionally override the lp fee, only used if three
/// conditions are met: 1. the Pool has a dynamic fee, 2. the value's 2nd
/// highest bit is set (23rd bit, 0x400000), and 3. the value is less than
/// or equal to the maximum fee (1 million)
function beforeSwap(
address sender,
PoolKey calldata key,
IPoolManager.SwapParams calldata params,
bytes calldata hookData
) external returns (bytes4, BeforeSwapDelta, uint24);
/// @notice The hook called after a swap
/// @param sender The initial msg.sender for the swap call
/// @param key The key for the pool
/// @param params The parameters for the swap
/// @param delta The amount owed to the caller (positive) or owed to the
/// pool (negative)
/// @param hookData Arbitrary data handed into the PoolManager by the
/// swapper to be be passed on to the hook
/// @return bytes4 The function selector for the hook
/// @return int128 The hook's delta in unspecified currency. Positive: the
/// hook is owed/took currency, negative: the hook owes/sent currency
function afterSwap(
address sender,
PoolKey calldata key,
IPoolManager.SwapParams calldata params,
BalanceDelta delta,
bytes calldata hookData
) external returns (bytes4, int128);
/// @notice The hook called before donate
/// @param sender The initial msg.sender for the donate call
/// @param key The key for the pool
/// @param amount0 The amount of token0 being donated
/// @param amount1 The amount of token1 being donated
/// @param hookData Arbitrary data handed into the PoolManager by the donor
/// to be be passed on to the hook
/// @return bytes4 The function selector for the hook
function beforeDonate(
address sender,
PoolKey calldata key,
uint256 amount0,
uint256 amount1,
bytes calldata hookData
) external returns (bytes4);
/// @notice The hook called after donate
/// @param sender The initial msg.sender for the donate call
/// @param key The key for the pool
/// @param amount0 The amount of token0 being donated
/// @param amount1 The amount of token1 being donated
/// @param hookData Arbitrary data handed into the PoolManager by the donor
/// to be be passed on to the hook
/// @return bytes4 The function selector for the hook
function afterDonate(
address sender,
PoolKey calldata key,
uint256 amount0,
uint256 amount1,
bytes calldata hookData
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { PoolId } from
"contracts/interfaces/external/uniswap/v4/types/PoolId.sol";
import { IPoolManager } from
"contracts/interfaces/external/uniswap/v4/IPoolManager.sol";
/// @title IImmutableState
/// @notice Interface for the ImmutableState contract
interface IImmutableState {
/// @notice The Uniswap v4 PoolManager contract
function poolManager() external view returns (IPoolManager);
}
/// @title IStateView
/// @notice Interface for the StateView contract
interface IStateView is IImmutableState {
/// @notice Get Slot0 of the pool: sqrtPriceX96, tick, protocolFee, lpFee
/// @dev Corresponds to pools[poolId].slot0
/// @param poolId The ID of the pool.
/// @return sqrtPriceX96 The square root of the price of the pool, in Q96
/// precision.
/// @return tick The current tick of the pool.
/// @return protocolFee The protocol fee of the pool.
/// @return lpFee The swap fee of the pool.
function getSlot0(
PoolId poolId
)
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint24 protocolFee,
uint24 lpFee
);
/// @notice Retrieves the tick information of a pool at a specific tick.
/// @dev Corresponds to pools[poolId].ticks[tick]
/// @param poolId The ID of the pool.
/// @param tick The tick to retrieve information for.
/// @return liquidityGross The total position liquidity that references this
/// tick
/// @return liquidityNet The amount of net liquidity added (subtracted) when
/// tick is crossed from left to right (right to left)
/// @return feeGrowthOutside0X128 fee growth per unit of liquidity on the
/// _other_ side of this tick (relative to the current tick)
/// @return feeGrowthOutside1X128 fee growth per unit of liquidity on the
/// _other_ side of this tick (relative to the current tick)
function getTickInfo(
PoolId poolId,
int24 tick
)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128
);
/// @notice Retrieves the liquidity information of a pool at a specific
/// tick.
/// @dev Corresponds to pools[poolId].ticks[tick].liquidityGross and
/// pools[poolId].ticks[tick].liquidityNet. A more gas efficient version of
/// getTickInfo
/// @param poolId The ID of the pool.
/// @param tick The tick to retrieve liquidity for.
/// @return liquidityGross The total position liquidity that references this
/// tick
/// @return liquidityNet The amount of net liquidity added (subtracted) when
/// tick is crossed from left to right (right to left)
function getTickLiquidity(
PoolId poolId,
int24 tick
) external view returns (uint128 liquidityGross, int128 liquidityNet);
/// @notice Retrieves the fee growth outside a tick range of a pool
/// @dev Corresponds to pools[poolId].ticks[tick].feeGrowthOutside0X128 and
/// pools[poolId].ticks[tick].feeGrowthOutside1X128. A more gas efficient
/// version of getTickInfo
/// @param poolId The ID of the pool.
/// @param tick The tick to retrieve fee growth for.
/// @return feeGrowthOutside0X128 fee growth per unit of liquidity on the
/// _other_ side of this tick (relative to the current tick)
/// @return feeGrowthOutside1X128 fee growth per unit of liquidity on the
/// _other_ side of this tick (relative to the current tick)
function getTickFeeGrowthOutside(
PoolId poolId,
int24 tick
)
external
view
returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128);
/// @notice Retrieves the global fee growth of a pool.
/// @dev Corresponds to pools[poolId].feeGrowthGlobal0X128 and
/// pools[poolId].feeGrowthGlobal1X128
/// @param poolId The ID of the pool.
/// @return feeGrowthGlobal0 The global fee growth for token0.
/// @return feeGrowthGlobal1 The global fee growth for token1.
function getFeeGrowthGlobals(
PoolId poolId
)
external
view
returns (uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1);
/// @notice Retrieves the total liquidity of a pool.
/// @dev Corresponds to pools[poolId].liquidity
/// @param poolId The ID of the pool.
/// @return liquidity The liquidity of the pool.
function getLiquidity(
PoolId poolId
) external view returns (uint128 liquidity);
/// @notice Retrieves the tick bitmap of a pool at a specific tick.
/// @dev Corresponds to pools[poolId].tickBitmap[tick]
/// @param poolId The ID of the pool.
/// @param tick The tick to retrieve the bitmap for.
/// @return tickBitmap The bitmap of the tick.
function getTickBitmap(
PoolId poolId,
int16 tick
) external view returns (uint256 tickBitmap);
/// @notice Retrieves the position info without needing to calculate the
/// `positionId`.
/// @dev Corresponds to pools[poolId].positions[positionId]
/// @param poolId The ID of the pool.
/// @param owner The owner of the liquidity position.
/// @param tickLower The lower tick of the liquidity range.
/// @param tickUpper The upper tick of the liquidity range.
/// @param salt The bytes32 randomness to further distinguish position
/// state.
/// @return liquidity The liquidity of the position.
/// @return feeGrowthInside0LastX128 The fee growth inside the position for
/// token0.
/// @return feeGrowthInside1LastX128 The fee growth inside the position for
/// token1.
function getPositionInfo(
PoolId poolId,
address owner,
int24 tickLower,
int24 tickUpper,
bytes32 salt
)
external
view
returns (
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128
);
/// @notice Retrieves the position information of a pool at a specific
/// position ID.
/// @dev Corresponds to pools[poolId].positions[positionId]
/// @param poolId The ID of the pool.
/// @param positionId The ID of the position.
/// @return liquidity The liquidity of the position.
/// @return feeGrowthInside0LastX128 The fee growth inside the position for
/// token0.
/// @return feeGrowthInside1LastX128 The fee growth inside the position for
/// token1.
function getPositionInfo(
PoolId poolId,
bytes32 positionId
)
external
view
returns (
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128
);
/// @notice Retrieves the liquidity of a position.
/// @dev Corresponds to pools[poolId].positions[positionId].liquidity. More
/// gas efficient for just retrieving liquidity as compared to
/// getPositionInfo
/// @param poolId The ID of the pool.
/// @param positionId The ID of the position.
/// @return liquidity The liquidity of the position.
function getPositionLiquidity(
PoolId poolId,
bytes32 positionId
) external view returns (uint128 liquidity);
/// @notice Calculate the fee growth inside a tick range of a pool
/// @dev pools[poolId].feeGrowthInside0LastX128 in Position.Info is cached
/// and can become stale. This function will calculate the up to date
/// feeGrowthInside
/// @param poolId The ID of the pool.
/// @param tickLower The lower tick of the range.
/// @param tickUpper The upper tick of the range.
/// @return feeGrowthInside0X128 The fee growth inside the tick range for
/// token0.
/// @return feeGrowthInside1X128 The fee growth inside the tick range for
/// token1.
function getFeeGrowthInside(
PoolId poolId,
int24 tickLower,
int24 tickUpper
)
external
view
returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { PoolKey } from "./PoolKey.sol";
type PoolId is bytes32;
/// @notice Library for computing the ID of a pool
library PoolIdLibrary {
/// @notice Returns value equal to keccak256(abi.encode(poolKey))
function toId(
PoolKey memory poolKey
) internal pure returns (PoolId poolId) {
assembly ("memory-safe") {
// 0xa0 represents the total size of the poolKey struct (5 slots of
// 32 bytes)
poolId := keccak256(poolKey, 0xa0)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Currency } from "./Currency.sol";
import { IHooks } from "../IHooks.sol";
import { PoolIdLibrary } from "./PoolId.sol";
using PoolIdLibrary for PoolKey global;
/// @notice Returns the key for identifying a pool
struct PoolKey {
/// @notice The lower currency of the pool, sorted numerically
Currency currency0;
/// @notice The higher currency of the pool, sorted numerically
Currency currency1;
/// @notice The pool LP fee, capped at 1_000_000. If the highest bit is 1,
/// the pool has a dynamic fee and must be exactly equal to 0x800000
uint24 fee;
/// @notice Ticks that involve positions must be a multiple of tick spacing
int24 tickSpacing;
/// @notice The hooks of the pool
IHooks hooks;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import { PoolKey } from "../types/PoolKey.sol";
import { PoolId } from "../types/PoolId.sol";
/**
* @dev PositionInfo is a packed version of solidity structure.
* Using the packaged version saves gas and memory by not storing the structure
* fields in memory slots.
*
* Layout:
* 200 bits poolId | 24 bits tickUpper | 24 bits tickLower | 8 bits
* hasSubscriber
*
* Fields in the direction from the least significant bit:
*
* A flag to know if the tokenId is subscribed to an address
* uint8 hasSubscriber;
*
* The tickUpper of the position
* int24 tickUpper;
*
* The tickLower of the position
* int24 tickLower;
*
* The truncated poolId. Truncates a bytes32 value so the most signifcant
* (highest) 200 bits are used.
* bytes25 poolId;
*
* Note: If more bits are needed, hasSubscriber can be a single bit.
*
*/
type PositionInfo is uint256;
using PositionInfoLibrary for PositionInfo global;
library PositionInfoLibrary {
PositionInfo internal constant EMPTY_POSITION_INFO = PositionInfo.wrap(0);
uint256 internal constant MASK_UPPER_200_BITS =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000;
uint256 internal constant MASK_8_BITS = 0xFF;
uint24 internal constant MASK_24_BITS = 0xFFFFFF;
uint256 internal constant SET_UNSUBSCRIBE =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00;
uint256 internal constant SET_SUBSCRIBE = 0x01;
uint8 internal constant TICK_LOWER_OFFSET = 8;
uint8 internal constant TICK_UPPER_OFFSET = 32;
/// @dev This poolId is NOT compatible with the poolId used in UniswapV4
/// core. It is truncated to 25 bytes, and just used to lookup PoolKey in
/// the poolKeys mapping.
function poolId(
PositionInfo info
) internal pure returns (bytes25 _poolId) {
assembly ("memory-safe") {
_poolId := and(MASK_UPPER_200_BITS, info)
}
}
function tickLower(
PositionInfo info
) internal pure returns (int24 _tickLower) {
assembly ("memory-safe") {
_tickLower := signextend(2, shr(TICK_LOWER_OFFSET, info))
}
}
function tickUpper(
PositionInfo info
) internal pure returns (int24 _tickUpper) {
assembly ("memory-safe") {
_tickUpper := signextend(2, shr(TICK_UPPER_OFFSET, info))
}
}
function hasSubscriber(
PositionInfo info
) internal pure returns (bool _hasSubscriber) {
assembly ("memory-safe") {
_hasSubscriber := and(MASK_8_BITS, info)
}
}
/// @dev this does not actually set any storage
function setSubscribe(
PositionInfo info
) internal pure returns (PositionInfo _info) {
assembly ("memory-safe") {
_info := or(info, SET_SUBSCRIBE)
}
}
/// @dev this does not actually set any storage
function setUnsubscribe(
PositionInfo info
) internal pure returns (PositionInfo _info) {
assembly ("memory-safe") {
_info := and(info, SET_UNSUBSCRIBE)
}
}
/// @notice Creates the default PositionInfo struct
/// @dev Called when minting a new position
/// @param _poolKey the pool key of the position
/// @param _tickLower the lower tick of the position
/// @param _tickUpper the upper tick of the position
/// @return info packed position info, with the truncated poolId and the
/// hasSubscriber flag set to false
function initialize(
PoolKey memory _poolKey,
int24 _tickLower,
int24 _tickUpper
) internal pure returns (PositionInfo info) {
bytes25 _poolId = bytes25(PoolId.unwrap(_poolKey.toId()));
assembly {
info :=
or(
or(
and(MASK_UPPER_200_BITS, _poolId),
shl(TICK_UPPER_OFFSET, and(MASK_24_BITS, _tickUpper))
),
shl(TICK_LOWER_OFFSET, and(MASK_24_BITS, _tickLower))
)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Library to define different pool actions.
/// @dev These are suggested common commands, however additional commands should
/// be defined as required
/// Some of these actions are not supported in the Router contracts or Position
/// Manager contracts, but are left as they may be helpful commands for other
/// peripheral contracts.
library Actions {
// pool actions
// liquidity actions
uint256 internal constant INCREASE_LIQUIDITY = 0x00;
uint256 internal constant DECREASE_LIQUIDITY = 0x01;
uint256 internal constant MINT_POSITION = 0x02;
uint256 internal constant BURN_POSITION = 0x03;
uint256 internal constant INCREASE_LIQUIDITY_FROM_DELTAS = 0x04;
uint256 internal constant MINT_POSITION_FROM_DELTAS = 0x05;
// swapping
uint256 internal constant SWAP_EXACT_IN_SINGLE = 0x06;
uint256 internal constant SWAP_EXACT_IN = 0x07;
uint256 internal constant SWAP_EXACT_OUT_SINGLE = 0x08;
uint256 internal constant SWAP_EXACT_OUT = 0x09;
// donate
// note this is not supported in the position manager or router
uint256 internal constant DONATE = 0x0a;
// closing deltas on the pool manager
// settling
uint256 internal constant SETTLE = 0x0b;
uint256 internal constant SETTLE_ALL = 0x0c;
uint256 internal constant SETTLE_PAIR = 0x0d;
// taking
uint256 internal constant TAKE = 0x0e;
uint256 internal constant TAKE_ALL = 0x0f;
uint256 internal constant TAKE_PORTION = 0x10;
uint256 internal constant TAKE_PAIR = 0x11;
uint256 internal constant CLOSE_CURRENCY = 0x12;
uint256 internal constant CLEAR_OR_TAKE = 0x13;
uint256 internal constant SWEEP = 0x14;
uint256 internal constant WRAP = 0x15;
uint256 internal constant UNWRAP = 0x16;
// minting/burning 6909s to close deltas
// note this is not supported in the position manager or router
uint256 internal constant MINT_6909 = 0x17;
uint256 internal constant BURN_6909 = 0x18;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC20Minimal } from "../IERC20Minimal.sol";
import { CustomRevert } from "../libraries/CustomRevert.sol";
type Currency is address;
using {
greaterThan as >,
lessThan as <,
greaterThanOrEqualTo as >=,
equals as ==
} for Currency global;
using CurrencyLibrary for Currency global;
function equals(Currency currency, Currency other) pure returns (bool) {
return Currency.unwrap(currency) == Currency.unwrap(other);
}
function greaterThan(Currency currency, Currency other) pure returns (bool) {
return Currency.unwrap(currency) > Currency.unwrap(other);
}
function lessThan(Currency currency, Currency other) pure returns (bool) {
return Currency.unwrap(currency) < Currency.unwrap(other);
}
function greaterThanOrEqualTo(
Currency currency,
Currency other
) pure returns (bool) {
return Currency.unwrap(currency) >= Currency.unwrap(other);
}
/// @title CurrencyLibrary
/// @dev This library allows for transferring and holding native tokens and
/// ERC20 tokens
library CurrencyLibrary {
/// @notice Additional context for ERC-7751 wrapped error when a native
/// transfer fails
error NativeTransferFailed();
/// @notice Additional context for ERC-7751 wrapped error when an ERC20
/// transfer fails
error ERC20TransferFailed();
/// @notice A constant to represent the native currency
Currency public constant ADDRESS_ZERO = Currency.wrap(address(0));
function transfer(Currency currency, address to, uint256 amount) internal {
// altered from
// https://github.com/transmissions11/solmate/blob/44a9963d4c78111f77caa0e65d677b8b46d6f2e6/src/utils/SafeTransferLib.sol
// modified custom error selectors
bool success;
if (currency.isAddressZero()) {
assembly ("memory-safe") {
// Transfer the ETH and revert if it fails.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
// revert with NativeTransferFailed, containing the bubbled up error
// as an argument
if (!success) {
CustomRevert.bubbleUpAndRevertWith(
to, bytes4(0), NativeTransferFailed.selector
);
}
} else {
assembly ("memory-safe") {
// Get a pointer to some free memory.
let fmp := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with
// the function selector.
mstore(
fmp,
0xa9059cbb00000000000000000000000000000000000000000000000000000000
)
mstore(
add(fmp, 4),
and(to, 0xffffffffffffffffffffffffffffffffffffffff)
) // Append and mask the "to" argument.
mstore(add(fmp, 36), amount) // Append the "amount" argument.
// Masking not required as it's a full 32 byte type.
success :=
and(
// Set success to whether the call reverted, if not we check
// it either
// returned exactly 1 (can't just be non-zero data), or had
// no return data.
or(
and(eq(mload(0), 1), gt(returndatasize(), 31)),
iszero(returndatasize())
),
// We use 68 because the length of our calldata totals up
// like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data
// into the scratch space.
// Counterintuitively, this call must be positioned second
// to the or() call in the
// surrounding and() call or else returndatasize() will be
// zero during the computation.
call(gas(), currency, 0, fmp, 68, 0, 32)
)
// Now clean the memory we used
mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were
// stored here
mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of
// `amount` were stored here
mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored
// here
}
// revert with ERC20TransferFailed, containing the bubbled up error
// as an argument
if (!success) {
CustomRevert.bubbleUpAndRevertWith(
Currency.unwrap(currency),
IERC20Minimal.transfer.selector,
ERC20TransferFailed.selector
);
}
}
}
function balanceOfSelf(
Currency currency
) internal view returns (uint256) {
if (currency.isAddressZero()) {
return address(this).balance;
} else {
return IERC20Minimal(Currency.unwrap(currency)).balanceOf(
address(this)
);
}
}
function balanceOf(
Currency currency,
address owner
) internal view returns (uint256) {
if (currency.isAddressZero()) {
return owner.balance;
} else {
return IERC20Minimal(Currency.unwrap(currency)).balanceOf(owner);
}
}
function isAddressZero(
Currency currency
) internal pure returns (bool) {
return Currency.unwrap(currency) == Currency.unwrap(ADDRESS_ZERO);
}
function toId(
Currency currency
) internal pure returns (uint256) {
return uint160(Currency.unwrap(currency));
}
// If the upper 12 bytes are non-zero, they will be zero-ed out
// Therefore, fromId() and toId() are not inverses of each other
function fromId(
uint256 id
) internal pure returns (Currency) {
return Currency.wrap(address(uint160(id)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// import {IEIP712} from "./IEIP712.sol";
/// @title AllowanceTransfer
/// @notice Handles ERC20 token permissions through signature based allowance
/// setting and ERC20 token transfers by checking allowed amounts
/// @dev Requires user's token approval on the Permit2 contract
interface IAllowanceTransfer {
//is IEIP712
/// @notice Thrown when an allowance on a token has expired.
/// @param deadline The timestamp at which the allowed amount is no longer
/// valid
error AllowanceExpired(uint256 deadline);
/// @notice Thrown when an allowance on a token has been depleted.
/// @param amount The maximum amount allowed
error InsufficientAllowance(uint256 amount);
/// @notice Thrown when too many nonces are invalidated.
error ExcessiveInvalidation();
/// @notice Emits an event when the owner successfully invalidates an
/// ordered nonce.
event NonceInvalidation(
address indexed owner,
address indexed token,
address indexed spender,
uint48 newNonce,
uint48 oldNonce
);
/// @notice Emits an event when the owner successfully sets permissions on a
/// token for the spender.
event Approval(
address indexed owner,
address indexed token,
address indexed spender,
uint160 amount,
uint48 expiration
);
/// @notice Emits an event when the owner successfully sets permissions
/// using a permit signature on a token for the spender.
event Permit(
address indexed owner,
address indexed token,
address indexed spender,
uint160 amount,
uint48 expiration,
uint48 nonce
);
/// @notice Emits an event when the owner sets the allowance back to 0 with
/// the lockdown function.
event Lockdown(address indexed owner, address token, address spender);
/// @notice The permit data for a token
struct PermitDetails {
// ERC20 token address
address token;
// the maximum amount allowed to spend
uint160 amount;
// timestamp at which a spender's token allowances become invalid
uint48 expiration;
// an incrementing value indexed per owner,token,and spender for each
// signature
uint48 nonce;
}
/// @notice The permit message signed for a single token allowance
struct PermitSingle {
// the permit data for a single token alownce
PermitDetails details;
// address permissioned on the allowed tokens
address spender;
// deadline on the permit signature
uint256 sigDeadline;
}
/// @notice The permit message signed for multiple token allowances
struct PermitBatch {
// the permit data for multiple token allowances
PermitDetails[] details;
// address permissioned on the allowed tokens
address spender;
// deadline on the permit signature
uint256 sigDeadline;
}
/// @notice The saved permissions
/// @dev This info is saved per owner, per token, per spender and all signed
/// over in the permit message
/// @dev Setting amount to type(uint160).max sets an unlimited approval
struct PackedAllowance {
// amount allowed
uint160 amount;
// permission expiry
uint48 expiration;
// an incrementing value indexed per owner,token,and spender for each
// signature
uint48 nonce;
}
/// @notice A token spender pair.
struct TokenSpenderPair {
// the token the spender is approved
address token;
// the spender address
address spender;
}
/// @notice Details for a token transfer.
struct AllowanceTransferDetails {
// the owner of the token
address from;
// the recipient of the token
address to;
// the amount of the token
uint160 amount;
// the token to be transferred
address token;
}
/// @notice A mapping from owner address to token address to spender address
/// to PackedAllowance struct, which contains details and conditions of the
/// approval.
/// @notice The mapping is indexed in the above order see:
/// allowance[ownerAddress][tokenAddress][spenderAddress]
/// @dev The packed slot holds the allowed amount, expiration at which the
/// allowed amount is no longer valid, and current nonce thats updated on
/// any signature based approvals.
function allowance(
address user,
address token,
address spender
) external view returns (uint160 amount, uint48 expiration, uint48 nonce);
/// @notice Approves the spender to use up to amount of the specified token
/// up until the expiration
/// @param token The token to approve
/// @param spender The spender address to approve
/// @param amount The approved amount of the token
/// @param expiration The timestamp at which the approval is no longer valid
/// @dev The packed allowance also holds a nonce, which will stay unchanged
/// in approve
/// @dev Setting amount to type(uint160).max sets an unlimited approval
function approve(
address token,
address spender,
uint160 amount,
uint48 expiration
) external;
/// @notice Permit a spender to a given amount of the owners token via the
/// owner's EIP-712 signature
/// @dev May fail if the owner's nonce was invalidated in-flight by
/// invalidateNonce
/// @param owner The owner of the tokens being approved
/// @param permitSingle Data signed over by the owner specifying the terms
/// of approval
/// @param signature The owner's signature over the permit data
function permit(
address owner,
PermitSingle memory permitSingle,
bytes calldata signature
) external;
/// @notice Permit a spender to the signed amounts of the owners tokens via
/// the owner's EIP-712 signature
/// @dev May fail if the owner's nonce was invalidated in-flight by
/// invalidateNonce
/// @param owner The owner of the tokens being approved
/// @param permitBatch Data signed over by the owner specifying the terms of
/// approval
/// @param signature The owner's signature over the permit data
function permit(
address owner,
PermitBatch memory permitBatch,
bytes calldata signature
) external;
/// @notice Transfer approved tokens from one address to another
/// @param from The address to transfer from
/// @param to The address of the recipient
/// @param amount The amount of the token to transfer
/// @param token The token address to transfer
/// @dev Requires the from address to have approved at least the desired
/// amount
/// of tokens to msg.sender.
function transferFrom(
address from,
address to,
uint160 amount,
address token
) external;
/// @notice Transfer approved tokens in a batch
/// @param transferDetails Array of owners, recipients, amounts, and tokens
/// for the transfers
/// @dev Requires the from addresses to have approved at least the desired
/// amount
/// of tokens to msg.sender.
function transferFrom(
AllowanceTransferDetails[] calldata transferDetails
) external;
/// @notice Enables performing a "lockdown" of the sender's Permit2 identity
/// by batch revoking approvals
/// @param approvals Array of approvals to revoke.
function lockdown(
TokenSpenderPair[] calldata approvals
) external;
/// @notice Invalidate nonces for a given (token, spender) pair
/// @param token The token to invalidate nonces for
/// @param spender The spender to invalidate nonces for
/// @param newNonce The new nonce to set. Invalidates all nonces less than
/// it.
/// @dev Can't invalidate more than 2**16 nonces per transaction.
function invalidateNonces(
address token,
address spender,
uint48 newNonce
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { NftPosition } from "contracts/structs/NftFarmStrategyStructs.sol";
interface INftFarmConnector {
function depositExistingNft(
NftPosition calldata position,
bytes calldata extraData
) external;
function withdrawNft(
NftPosition calldata position,
bytes calldata extraData
) external;
function claim(
NftPosition calldata position,
address[] memory rewardTokens,
uint128 maxAmount0, // For collecting
uint128 maxAmount1,
bytes calldata extraData
) external;
function earned(
address user,
NftPosition calldata position,
address[] memory rewardTokens
) external view returns (uint256[] memory);
function isStaked(
address user,
NftPosition calldata position
) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {
NftAddLiquidity,
NftRemoveLiquidity,
NftPoolKey,
NftPoolInfo,
NftPositionInfo
} from "contracts/structs/NftLiquidityStructs.sol";
interface INftLiquidityConnector {
function addLiquidity(
NftAddLiquidity memory addLiquidityParams
) external;
function removeLiquidity(
NftRemoveLiquidity memory removeLiquidityParams
) external;
function fee(
address pool,
uint256 tokenId // Used by UniswapV4
) external view returns (uint24);
function totalSupply(
address nftManager
) external view returns (uint256);
function getTokenId(
address nftManager,
address owner
) external view returns (uint256);
function earnedFees(
address nftManager,
address pool,
uint256 tokenId
) external view returns (uint256 fees0, uint256 fees1);
function positionLiquidity(
address nftManager,
uint256 tokenId
)
external
view
returns (int24 tickLower, int24 tickUpper, uint128 liquidity);
function positionPoolKey(
address poolFactory,
address nftManager,
uint256 tokenId
) external view returns (NftPoolKey memory);
function poolInfo(
address pool,
bytes32 poolId
) external view returns (NftPoolInfo memory);
// Maintained for backwards compatibility with NftSettingsRegistry
function positionInfo(
address nftManager,
uint256 tokenId
) external view returns (NftPositionInfo memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
struct Pool {
address token0;
address token1;
uint24 fee;
}
struct NftPoolKey {
address poolAddress;
bytes32 poolId;
}
struct NftPoolInfo {
address token0;
address token1;
uint24 fee;
uint24 tickSpacing;
uint160 sqrtPriceX96;
int24 tick;
uint128 liquidity;
uint256 feeGrowthGlobal0X128;
uint256 feeGrowthGlobal1X128;
}
// Maintained for backwards compatibility with NftSettingsRegistry
struct NftPositionInfo {
uint128 liquidity;
int24 tickLower;
int24 tickUpper;
}
struct NftAddLiquidity {
INonfungiblePositionManager nft;
uint256 tokenId;
Pool pool;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
bytes extraData;
}
struct NftRemoveLiquidity {
INonfungiblePositionManager nft;
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min; // For decreasing
uint256 amount1Min;
uint128 amount0Max; // For collecting
uint128 amount1Max;
bytes extraData;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { IUniswapV3Pool } from
"contracts/interfaces/external/uniswap/IUniswapV3Pool.sol";
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
import { NftZapIn, NftZapOut } from "contracts/structs/NftZapStructs.sol";
import { SwapParams } from "contracts/structs/SwapStructs.sol";
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
struct NftPosition {
Farm farm;
INonfungiblePositionManager nft;
uint256 tokenId;
}
struct NftIncrease {
address[] tokensIn;
uint256[] amountsIn;
NftZapIn zap;
bytes extraData;
}
struct NftDeposit {
Farm farm;
INonfungiblePositionManager nft;
NftIncrease increase;
}
struct NftWithdraw {
NftZapOut zap;
address[] tokensOut;
bytes extraData;
}
struct SimpleNftHarvest {
address[] rewardTokens;
uint128 amount0Max;
uint128 amount1Max;
bytes extraData;
}
struct NftHarvest {
SimpleNftHarvest harvest;
SwapParams[] swaps;
address[] outputTokens;
address[] sweepTokens;
}
struct NftCompound {
SimpleNftHarvest harvest;
NftZapIn zap;
}
struct NftRebalance {
IUniswapV3Pool pool;
NftPosition position;
NftHarvest harvest;
NftWithdraw withdraw;
NftIncrease increase;
}
struct NftMove {
IUniswapV3Pool pool;
NftPosition position;
NftHarvest harvest;
NftWithdraw withdraw;
NftDeposit deposit;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an
/// intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division
/// where an intermediate value overflows 256 bits
library FullMath {
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws
/// if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license
/// https://xn--2-umb.com/21/muldiv
function mulDiv(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
uint256 prod0 = a * b; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
assembly ("memory-safe") {
result := div(prod0, denominator)
}
return result;
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1
// prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly ("memory-safe") {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly ("memory-safe") {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (0 - denominator) & denominator;
// Divide denominator by power of two
assembly ("memory-safe") {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly ("memory-safe") {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly ("memory-safe") {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256
// Now that denominator is an odd number, it has an inverse
// modulo 2**256 such that denominator * inv = 1 mod 2**256.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // inverse mod 2**256
// Because the division is now exact we can divide by multiplying
// with the modular inverse of denominator. This will give us the
// correct result modulo 2**256. Since the preconditions guarantee
// that the outcome is less than 2**256, this is the final result.
// We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws
/// if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
function mulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) != 0) {
require(++result > 0);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title FixedPoint128
/// @notice A library for handling binary fixed point numbers, see
/// https://en.wikipedia.org/wiki/Q_(number_format)
library FixedPoint128 {
uint256 internal constant Q128 = 0x100000000000000000000000000000000;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import { FullMath } from "./FullMath.sol";
import { FixedPoint128 } from "./FixedPoint128.sol";
import { LiquidityMath } from "./LiquidityMath.sol";
import { CustomRevert } from "./CustomRevert.sol";
/// @title Position
/// @notice Positions represent an owner address' liquidity between a lower and
/// upper tick boundary
/// @dev Positions store additional state for tracking fees owed to the position
library Position {
using CustomRevert for bytes4;
/// @notice Cannot update a position with no liquidity
error CannotUpdateEmptyPosition();
// info stored for each user's position
struct State {
// the amount of liquidity owned by this position
uint128 liquidity;
// fee growth per unit of liquidity as of the last update to liquidity
// or fees owed
uint256 feeGrowthInside0LastX128;
uint256 feeGrowthInside1LastX128;
}
/// @notice Returns the State struct of a position, given an owner and
/// position boundaries
/// @param self The mapping containing all user positions
/// @param owner The address of the position owner
/// @param tickLower The lower tick boundary of the position
/// @param tickUpper The upper tick boundary of the position
/// @param salt A unique value to differentiate between multiple positions
/// in the same range
/// @return position The position info struct of the given owners' position
function get(
mapping(bytes32 => State) storage self,
address owner,
int24 tickLower,
int24 tickUpper,
bytes32 salt
) internal view returns (State storage position) {
bytes32 positionKey =
calculatePositionKey(owner, tickLower, tickUpper, salt);
position = self[positionKey];
}
/// @notice A helper function to calculate the position key
/// @param owner The address of the position owner
/// @param tickLower the lower tick boundary of the position
/// @param tickUpper the upper tick boundary of the position
/// @param salt A unique value to differentiate between multiple positions
/// in the same range, by the same owner. Passed in by the caller.
function calculatePositionKey(
address owner,
int24 tickLower,
int24 tickUpper,
bytes32 salt
) internal pure returns (bytes32 positionKey) {
// positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper,
// salt))
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(add(fmp, 0x26), salt) // [0x26, 0x46)
mstore(add(fmp, 0x06), tickUpper) // [0x23, 0x26)
mstore(add(fmp, 0x03), tickLower) // [0x20, 0x23)
mstore(fmp, owner) // [0x0c, 0x20)
positionKey := keccak256(add(fmp, 0x0c), 0x3a) // len is 58 bytes
// now clean the memory we used
mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt
mstore(add(fmp, 0x20), 0) // fmp+0x20 held tickLower, tickUpper,
// salt
mstore(fmp, 0) // fmp held owner
}
}
/// @notice Credits accumulated fees to a user's position
/// @param self The individual position to update
/// @param liquidityDelta The change in pool liquidity as a result of the
/// position update
/// @param feeGrowthInside0X128 The all-time fee growth in currency0, per
/// unit of liquidity, inside the position's tick boundaries
/// @param feeGrowthInside1X128 The all-time fee growth in currency1, per
/// unit of liquidity, inside the position's tick boundaries
/// @return feesOwed0 The amount of currency0 owed to the position owner
/// @return feesOwed1 The amount of currency1 owed to the position owner
function update(
State storage self,
int128 liquidityDelta,
uint256 feeGrowthInside0X128,
uint256 feeGrowthInside1X128
) internal returns (uint256 feesOwed0, uint256 feesOwed1) {
uint128 liquidity = self.liquidity;
if (liquidityDelta == 0) {
// disallow pokes for 0 liquidity positions
if (liquidity == 0) CannotUpdateEmptyPosition.selector.revertWith();
} else {
self.liquidity = LiquidityMath.addDelta(liquidity, liquidityDelta);
}
// calculate accumulated fees. overflow in the subtraction of fee growth
// is expected
unchecked {
feesOwed0 = FullMath.mulDiv(
feeGrowthInside0X128 - self.feeGrowthInside0LastX128,
liquidity,
FixedPoint128.Q128
);
feesOwed1 = FullMath.mulDiv(
feeGrowthInside1X128 - self.feeGrowthInside1LastX128,
liquidity,
FixedPoint128.Q128
);
}
// update the position
self.feeGrowthInside0LastX128 = feeGrowthInside0X128;
self.feeGrowthInside1LastX128 = feeGrowthInside1X128;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import { Currency } from "./types/Currency.sol";
import { PoolKey } from "./types/PoolKey.sol";
import { PoolId } from "./types/PoolId.sol";
import { BalanceDelta } from "./types/BalanceDelta.sol";
import { IHooks } from "./IHooks.sol";
import { IExtsload } from "./IExtsload.sol";
import { IExttload } from "./IExttload.sol";
/// @notice Interface for the PoolManager
interface IPoolManager is IExtsload, IExttload {
/// @notice Thrown when a currency is not netted out after the contract is
/// unlocked
error CurrencyNotSettled();
/// @notice Thrown when trying to interact with a non-initialized pool
error PoolNotInitialized();
/// @notice Thrown when unlock is called, but the contract is already
/// unlocked
error AlreadyUnlocked();
/// @notice Thrown when a function is called that requires the contract to
/// be unlocked, but it is not
error ManagerLocked();
/// @notice Pools are limited to type(int16).max tickSpacing in #initialize,
/// to prevent overflow
error TickSpacingTooLarge(int24 tickSpacing);
/// @notice Pools must have a positive non-zero tickSpacing passed to
/// #initialize
error TickSpacingTooSmall(int24 tickSpacing);
/// @notice PoolKey must have currencies where address(currency0) <
/// address(currency1)
error CurrenciesOutOfOrderOrEqual(address currency0, address currency1);
/// @notice Thrown when a call to updateDynamicLPFee is made by an address
/// that is not the hook,
/// or on a pool that does not have a dynamic swap fee.
error UnauthorizedDynamicLPFeeUpdate();
/// @notice Thrown when trying to swap amount of 0
error SwapAmountCannotBeZero();
///@notice Thrown when native currency is passed to a non native settlement
error NonzeroNativeValue();
/// @notice Thrown when `clear` is called with an amount that is not exactly
/// equal to the open currency delta.
error MustClearExactPositiveDelta();
/// @notice Emitted when a new pool is initialized
/// @param id The abi encoded hash of the pool key struct for the new pool
/// @param currency0 The first currency of the pool by address sort order
/// @param currency1 The second currency of the pool by address sort order
/// @param fee The fee collected upon every swap in the pool, denominated in
/// hundredths of a bip
/// @param tickSpacing The minimum number of ticks between initialized ticks
/// @param hooks The hooks contract address for the pool, or address(0) if
/// none
/// @param sqrtPriceX96 The price of the pool on initialization
/// @param tick The initial tick of the pool corresponding to the
/// initialized price
event Initialize(
PoolId indexed id,
Currency indexed currency0,
Currency indexed currency1,
uint24 fee,
int24 tickSpacing,
IHooks hooks,
uint160 sqrtPriceX96,
int24 tick
);
/// @notice Emitted when a liquidity position is modified
/// @param id The abi encoded hash of the pool key struct for the pool that
/// was modified
/// @param sender The address that modified the pool
/// @param tickLower The lower tick of the position
/// @param tickUpper The upper tick of the position
/// @param liquidityDelta The amount of liquidity that was added or removed
/// @param salt The extra data to make positions unique
event ModifyLiquidity(
PoolId indexed id,
address indexed sender,
int24 tickLower,
int24 tickUpper,
int256 liquidityDelta,
bytes32 salt
);
/// @notice Emitted for swaps between currency0 and currency1
/// @param id The abi encoded hash of the pool key struct for the pool that
/// was modified
/// @param sender The address that initiated the swap call, and that
/// received the callback
/// @param amount0 The delta of the currency0 balance of the pool
/// @param amount1 The delta of the currency1 balance of the pool
/// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a
/// Q64.96
/// @param liquidity The liquidity of the pool after the swap
/// @param tick The log base 1.0001 of the price of the pool after the swap
/// @param fee The swap fee in hundredths of a bip
event Swap(
PoolId indexed id,
address indexed sender,
int128 amount0,
int128 amount1,
uint160 sqrtPriceX96,
uint128 liquidity,
int24 tick,
uint24 fee
);
/// @notice Emitted for donations
/// @param id The abi encoded hash of the pool key struct for the pool that
/// was donated to
/// @param sender The address that initiated the donate call
/// @param amount0 The amount donated in currency0
/// @param amount1 The amount donated in currency1
event Donate(
PoolId indexed id,
address indexed sender,
uint256 amount0,
uint256 amount1
);
/// @notice All interactions on the contract that account deltas require
/// unlocking. A caller that calls `unlock` must implement
/// `IUnlockCallback(msg.sender).unlockCallback(data)`, where they interact
/// with the remaining functions on this contract.
/// @dev The only functions callable without an unlocking are `initialize`
/// and `updateDynamicLPFee`
/// @param data Any data to pass to the callback, via
/// `IUnlockCallback(msg.sender).unlockCallback(data)`
/// @return The data returned by the call to
/// `IUnlockCallback(msg.sender).unlockCallback(data)`
function unlock(
bytes calldata data
) external returns (bytes memory);
/// @notice Initialize the state for a given pool ID
/// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps
/// impossible since the input is entirely consumed by the fee
/// @param key The pool key for the pool to initialize
/// @param sqrtPriceX96 The initial square root price
/// @return tick The initial tick of the pool
function initialize(
PoolKey memory key,
uint160 sqrtPriceX96
) external returns (int24 tick);
struct ModifyLiquidityParams {
// the lower and upper tick of the position
int24 tickLower;
int24 tickUpper;
// how to modify the liquidity
int256 liquidityDelta;
// a value to set if you want unique liquidity positions at the same
// range
bytes32 salt;
}
/// @notice Modify the liquidity for the given pool
/// @dev Poke by calling with a zero liquidityDelta
/// @param key The pool to modify liquidity in
/// @param params The parameters for modifying the liquidity
/// @param hookData The data to pass through to the add/removeLiquidity
/// hooks
/// @return callerDelta The balance delta of the caller of modifyLiquidity.
/// This is the total of both principal, fee deltas, and hook deltas if
/// applicable
/// @return feesAccrued The balance delta of the fees generated in the
/// liquidity range. Returned for informational purposes
/// @dev Note that feesAccrued can be artificially inflated by a malicious
/// actor and integrators should be careful using the value
/// For pools with a single liquidity position, actors can donate to
/// themselves to inflate feeGrowthGlobal (and consequently feesAccrued)
/// atomically donating and collecting fees in the same unlockCallback may
/// make the inflated value more extreme
function modifyLiquidity(
PoolKey memory key,
ModifyLiquidityParams memory params,
bytes calldata hookData
) external returns (BalanceDelta callerDelta, BalanceDelta feesAccrued);
struct SwapParams {
/// Whether to swap token0 for token1 or vice versa
bool zeroForOne;
/// The desired input amount if negative (exactIn), or the desired
/// output amount if positive (exactOut)
int256 amountSpecified;
/// The sqrt price at which, if reached, the swap will stop executing
uint160 sqrtPriceLimitX96;
}
/// @notice Swap against the given pool
/// @param key The pool to swap in
/// @param params The parameters for swapping
/// @param hookData The data to pass through to the swap hooks
/// @return swapDelta The balance delta of the address swapping
/// @dev Swapping on low liquidity pools may cause unexpected swap amounts
/// when liquidity available is less than amountSpecified.
/// Additionally note that if interacting with hooks that have the
/// BEFORE_SWAP_RETURNS_DELTA_FLAG or AFTER_SWAP_RETURNS_DELTA_FLAG
/// the hook may alter the swap input/output. Integrators should perform
/// checks on the returned swapDelta.
function swap(
PoolKey memory key,
SwapParams memory params,
bytes calldata hookData
) external returns (BalanceDelta swapDelta);
/// @notice Donate the given currency amounts to the in-range liquidity
/// providers of a pool
/// @dev Calls to donate can be frontrun adding just-in-time liquidity, with
/// the aim of receiving a portion donated funds.
/// Donors should keep this in mind when designing donation mechanisms.
/// @dev This function donates to in-range LPs at slot0.tick. In certain
/// edge-cases of the swap algorithm, the `sqrtPrice` of
/// a pool can be at the lower boundary of tick `n`, but the `slot0.tick` of
/// the pool is already `n - 1`. In this case a call to
/// `donate` would donate to tick `n - 1` (slot0.tick) not tick `n`
/// (getTickAtSqrtPrice(slot0.sqrtPriceX96)).
/// Read the comments in `Pool.swap()` for more information about this.
/// @param key The key of the pool to donate to
/// @param amount0 The amount of currency0 to donate
/// @param amount1 The amount of currency1 to donate
/// @param hookData The data to pass through to the donate hooks
/// @return BalanceDelta The delta of the caller after the donate
function donate(
PoolKey memory key,
uint256 amount0,
uint256 amount1,
bytes calldata hookData
) external returns (BalanceDelta);
/// @notice Writes the current ERC20 balance of the specified currency to
/// transient storage
/// This is used to checkpoint balances for the manager and derive deltas
/// for the caller.
/// @dev This MUST be called before any ERC20 tokens are sent into the
/// contract, but can be skipped
/// for native tokens because the amount to settle is determined by the sent
/// value.
/// However, if an ERC20 token has been synced and not settled, and the
/// caller instead wants to settle
/// native funds, this function can be called with the native currency to
/// then be able to settle the native currency
function sync(
Currency currency
) external;
/// @notice Called by the user to net out some value owed to the user
/// @dev Will revert if the requested amount is not available, consider
/// using `mint` instead
/// @dev Can also be used as a mechanism for free flash loans
/// @param currency The currency to withdraw from the pool manager
/// @param to The address to withdraw to
/// @param amount The amount of currency to withdraw
function take(Currency currency, address to, uint256 amount) external;
/// @notice Called by the user to pay what is owed
/// @return paid The amount of currency settled
function settle() external payable returns (uint256 paid);
/// @notice Called by the user to pay on behalf of another address
/// @param recipient The address to credit for the payment
/// @return paid The amount of currency settled
function settleFor(
address recipient
) external payable returns (uint256 paid);
/// @notice WARNING - Any currency that is cleared, will be non-retrievable,
/// and locked in the contract permanently.
/// A call to clear will zero out a positive balance WITHOUT a corresponding
/// transfer.
/// @dev This could be used to clear a balance that is considered dust.
/// Additionally, the amount must be the exact positive balance. This is to
/// enforce that the caller is aware of the amount being cleared.
function clear(Currency currency, uint256 amount) external;
/// @notice Called by the user to move value into ERC6909 balance
/// @param to The address to mint the tokens to
/// @param id The currency address to mint to ERC6909s, as a uint256
/// @param amount The amount of currency to mint
/// @dev The id is converted to a uint160 to correspond to a currency
/// address
/// If the upper 12 bytes are not 0, they will be 0-ed out
function mint(address to, uint256 id, uint256 amount) external;
/// @notice Called by the user to move value from ERC6909 balance
/// @param from The address to burn the tokens from
/// @param id The currency address to burn from ERC6909s, as a uint256
/// @param amount The amount of currency to burn
/// @dev The id is converted to a uint160 to correspond to a currency
/// address
/// If the upper 12 bytes are not 0, they will be 0-ed out
function burn(address from, uint256 id, uint256 amount) external;
/// @notice Updates the pools lp fees for the a pool that has enabled
/// dynamic lp fees.
/// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps
/// impossible since the input is entirely consumed by the fee
/// @param key The key of the pool to update dynamic LP fees for
/// @param newDynamicLPFee The new dynamic pool LP fee
function updateDynamicLPFee(
PoolKey memory key,
uint24 newDynamicLPFee
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SafeCast } from "../libraries/SafeCast.sol";
/// @dev Two `int128` values packed into a single `int256` where the upper 128
/// bits represent the amount0
/// and the lower 128 bits represent the amount1.
type BalanceDelta is int256;
using { add as +, sub as -, eq as ==, neq as != } for BalanceDelta global;
using BalanceDeltaLibrary for BalanceDelta global;
using SafeCast for int256;
function toBalanceDelta(
int128 _amount0,
int128 _amount1
) pure returns (BalanceDelta balanceDelta) {
assembly ("memory-safe") {
balanceDelta :=
or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1))
}
}
function add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
int256 res0;
int256 res1;
assembly ("memory-safe") {
let a0 := sar(128, a)
let a1 := signextend(15, a)
let b0 := sar(128, b)
let b1 := signextend(15, b)
res0 := add(a0, b0)
res1 := add(a1, b1)
}
return toBalanceDelta(res0.toInt128(), res1.toInt128());
}
function sub(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
int256 res0;
int256 res1;
assembly ("memory-safe") {
let a0 := sar(128, a)
let a1 := signextend(15, a)
let b0 := sar(128, b)
let b1 := signextend(15, b)
res0 := sub(a0, b0)
res1 := sub(a1, b1)
}
return toBalanceDelta(res0.toInt128(), res1.toInt128());
}
function eq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b);
}
function neq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b);
}
/// @notice Library for getting the amount0 and amount1 deltas from the
/// BalanceDelta type
library BalanceDeltaLibrary {
/// @notice A BalanceDelta of 0
BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0);
function amount0(
BalanceDelta balanceDelta
) internal pure returns (int128 _amount0) {
assembly ("memory-safe") {
_amount0 := sar(128, balanceDelta)
}
}
function amount1(
BalanceDelta balanceDelta
) internal pure returns (int128 _amount1) {
assembly ("memory-safe") {
_amount1 := signextend(15, balanceDelta)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Return type of the beforeSwap hook.
// Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in
// unspecified tokens (to match the afterSwap hook)
type BeforeSwapDelta is int256;
// Creates a BeforeSwapDelta from specified and unspecified
function toBeforeSwapDelta(
int128 deltaSpecified,
int128 deltaUnspecified
) pure returns (BeforeSwapDelta beforeSwapDelta) {
assembly ("memory-safe") {
beforeSwapDelta :=
or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified))
}
}
/// @notice Library for getting the specified and unspecified deltas from the
/// BeforeSwapDelta type
library BeforeSwapDeltaLibrary {
/// @notice A BeforeSwapDelta of 0
BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0);
/// extracts int128 from the upper 128 bits of the BeforeSwapDelta
/// returned by beforeSwap
function getSpecifiedDelta(
BeforeSwapDelta delta
) internal pure returns (int128 deltaSpecified) {
assembly ("memory-safe") {
deltaSpecified := sar(128, delta)
}
}
/// extracts int128 from the lower 128 bits of the BeforeSwapDelta
/// returned by beforeSwap and afterSwap
function getUnspecifiedDelta(
BeforeSwapDelta delta
) internal pure returns (int128 deltaUnspecified) {
assembly ("memory-safe") {
deltaUnspecified := signextend(15, delta)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Minimal ERC20 interface for Uniswap
/// @notice Contains a subset of the full ERC20 interface that is used in
/// Uniswap V3
interface IERC20Minimal {
/// @notice Returns an account's balance in the token
/// @param account The account for which to look up the number of tokens it
/// has, i.e. its balance
/// @return The number of tokens held by the account
function balanceOf(
address account
) external view returns (uint256);
/// @notice Transfers the amount of token from the `msg.sender` to the
/// recipient
/// @param recipient The account that will receive the amount transferred
/// @param amount The number of tokens to send from the sender to the
/// recipient
/// @return Returns true for a successful transfer, false for an
/// unsuccessful transfer
function transfer(
address recipient,
uint256 amount
) external returns (bool);
/// @notice Returns the current allowance given to a spender by an owner
/// @param owner The account of the token owner
/// @param spender The account of the token spender
/// @return The current allowance granted by `owner` to `spender`
function allowance(
address owner,
address spender
) external view returns (uint256);
/// @notice Sets the allowance of a spender from the `msg.sender` to the
/// value `amount`
/// @param spender The account which will be allowed to spend a given amount
/// of the owners tokens
/// @param amount The amount of tokens allowed to be used by `spender`
/// @return Returns true for a successful approval, false for unsuccessful
function approve(address spender, uint256 amount) external returns (bool);
/// @notice Transfers `amount` tokens from `sender` to `recipient` up to the
/// allowance given to the `msg.sender`
/// @param sender The account from which the transfer will be initiated
/// @param recipient The recipient of the transfer
/// @param amount The amount of the transfer
/// @return Returns true for a successful transfer, false for unsuccessful
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/// @notice Event emitted when tokens are transferred from one address to
/// another, either via `#transfer` or `#transferFrom`.
/// @param from The account from which the tokens were sent, i.e. the
/// balance decreased
/// @param to The account to which the tokens were sent, i.e. the balance
/// increased
/// @param value The amount of tokens that were transferred
event Transfer(address indexed from, address indexed to, uint256 value);
/// @notice Event emitted when the approval amount for the spender of a
/// given owner's tokens changes.
/// @param owner The account that approved spending of its tokens
/// @param spender The account for which the spending allowance was modified
/// @param value The new allowance from the owner to the spender
event Approval(
address indexed owner, address indexed spender, uint256 value
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Library for reverting with custom errors efficiently
/// @notice Contains functions for reverting with custom errors with different
/// argument types efficiently
/// @dev To use this library, declare `using CustomRevert for bytes4;` and
/// replace `revert CustomError()` with
/// `CustomError.selector.revertWith()`
/// @dev The functions may tamper with the free memory pointer but it is fine
/// since the call context is exited immediately
library CustomRevert {
/// @dev ERC-7751 error for wrapping bubbled up reverts
error WrappedError(
address target, bytes4 selector, bytes reason, bytes details
);
/// @dev Reverts with the selector of a custom error in the scratch space
function revertWith(
bytes4 selector
) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
revert(0, 0x04)
}
}
/// @dev Reverts with a custom error with an address argument in the scratch
/// space
function revertWith(bytes4 selector, address addr) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff))
revert(0, 0x24)
}
}
/// @dev Reverts with a custom error with an int24 argument in the scratch
/// space
function revertWith(bytes4 selector, int24 value) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, signextend(2, value))
revert(0, 0x24)
}
}
/// @dev Reverts with a custom error with a uint160 argument in the scratch
/// space
function revertWith(bytes4 selector, uint160 value) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff))
revert(0, 0x24)
}
}
/// @dev Reverts with a custom error with two int24 arguments
function revertWith(
bytes4 selector,
int24 value1,
int24 value2
) internal pure {
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(fmp, selector)
mstore(add(fmp, 0x04), signextend(2, value1))
mstore(add(fmp, 0x24), signextend(2, value2))
revert(fmp, 0x44)
}
}
/// @dev Reverts with a custom error with two uint160 arguments
function revertWith(
bytes4 selector,
uint160 value1,
uint160 value2
) internal pure {
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(fmp, selector)
mstore(
add(fmp, 0x04),
and(value1, 0xffffffffffffffffffffffffffffffffffffffff)
)
mstore(
add(fmp, 0x24),
and(value2, 0xffffffffffffffffffffffffffffffffffffffff)
)
revert(fmp, 0x44)
}
}
/// @dev Reverts with a custom error with two address arguments
function revertWith(
bytes4 selector,
address value1,
address value2
) internal pure {
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(fmp, selector)
mstore(
add(fmp, 0x04),
and(value1, 0xffffffffffffffffffffffffffffffffffffffff)
)
mstore(
add(fmp, 0x24),
and(value2, 0xffffffffffffffffffffffffffffffffffffffff)
)
revert(fmp, 0x44)
}
}
/// @notice bubble up the revert message returned by a call and revert with
/// a wrapped ERC-7751 error
/// @dev this method can be vulnerable to revert data bombs
function bubbleUpAndRevertWith(
address revertingContract,
bytes4 revertingFunctionSelector,
bytes4 additionalContext
) internal pure {
bytes4 wrappedErrorSelector = WrappedError.selector;
assembly ("memory-safe") {
// Ensure the size of the revert data is a multiple of 32 bytes
let encodedDataSize := mul(div(add(returndatasize(), 31), 32), 32)
let fmp := mload(0x40)
// Encode wrapped error selector, address, function selector,
// offset, additional context, size, revert reason
mstore(fmp, wrappedErrorSelector)
mstore(
add(fmp, 0x04),
and(
revertingContract,
0xffffffffffffffffffffffffffffffffffffffff
)
)
mstore(
add(fmp, 0x24),
and(
revertingFunctionSelector,
0xffffffff00000000000000000000000000000000000000000000000000000000
)
)
// offset revert reason
mstore(add(fmp, 0x44), 0x80)
// offset additional context
mstore(add(fmp, 0x64), add(0xa0, encodedDataSize))
// size revert reason
mstore(add(fmp, 0x84), returndatasize())
// revert reason
returndatacopy(add(fmp, 0xa4), 0, returndatasize())
// size additional context
mstore(add(fmp, add(0xa4, encodedDataSize)), 0x04)
// additional context
mstore(
add(fmp, add(0xc4, encodedDataSize)),
and(
additionalContext,
0xffffffff00000000000000000000000000000000000000000000000000000000
)
)
revert(fmp, add(0xe4, encodedDataSize))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC721Enumerable } from
"openzeppelin-contracts/contracts/interfaces/IERC721Enumerable.sol";
interface INonfungiblePositionManager is IERC721Enumerable {
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
function increaseLiquidity(
IncreaseLiquidityParams memory params
)
external
payable
returns (uint256 amount0, uint256 amount1, uint256 liquidity);
function decreaseLiquidity(
DecreaseLiquidityParams calldata params
) external payable returns (uint256 amount0, uint256 amount1);
function mint(
MintParams memory params
)
external
payable
returns (uint256 tokenId, uint256 amount0, uint256 amount1);
function collect(
CollectParams calldata params
) external payable returns (uint256 amount0, uint256 amount1);
function burn(
uint256 tokenId
) external payable;
function positions(
uint256 tokenId
)
external
view
returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
function factory() external view returns (address);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Pool state that never changes
/// @notice These parameters are fixed for a pool forever, i.e., the methods
/// will always return the same values
interface IUniswapV3PoolImmutables {
/// @notice The contract that deployed the pool, which must adhere to the
/// IUniswapV3Factory interface
/// @return The contract address
function factory() external view returns (address);
/// @notice The first of the two tokens of the pool, sorted by address
/// @return The token contract address
function token0() external view returns (address);
/// @notice The second of the two tokens of the pool, sorted by address
/// @return The token contract address
function token1() external view returns (address);
/// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
/// @return The fee
function fee() external view returns (uint24);
/// @notice The pool tick spacing
/// @dev Ticks can only be used at multiples of this value, minimum of 1 and
/// always positive
/// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick,
/// i.e., ..., -6, -3, 0, 3, 6, ...
/// This value is an int24 to avoid casting even though it is always
/// positive.
/// @return The tick spacing
function tickSpacing() external view returns (int24);
/// @notice The maximum amount of position liquidity that can use any tick
/// in the range
/// @dev This parameter is enforced per tick to prevent liquidity from
/// overflowing a uint128 at any point, and
/// also prevents out-of-range liquidity from being used to prevent adding
/// in-range liquidity to a pool
/// @return The max amount of liquidity per tick
function maxLiquidityPerTick() external view returns (uint128);
}
/// @title Pool state that can change
/// @notice These methods compose the pool's state, and can change with any
/// frequency including multiple times
/// per transaction
interface IUniswapV3PoolState {
/// @notice The 0th storage slot in the pool stores many values, and is
/// exposed as a single method to save gas
/// when accessed externally.
/// @return sqrtPriceX96 The current price of the pool as a
/// sqrt(token1/token0) Q64.96 value
/// @return tick The current tick of the pool, i.e. according to the last
/// tick transition that was run.
/// This value may not always be equal to
/// SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
/// boundary.
/// @return observationIndex The index of the last oracle observation that
/// was written,
/// @return observationCardinality The current maximum number of
/// observations stored in the pool,
/// @return observationCardinalityNext The next maximum number of
/// observations, to be updated when the observation.
/// @return feeProtocol The protocol fee for both tokens of the pool.
/// Encoded as two 4 bit values, where the protocol fee of token1 is shifted
/// 4 bits and the protocol fee of token0
/// is the lower 4 bits. Used as the denominator of a fraction of the swap
/// fee, e.g. 4 means 1/4th of the swap fee.
/// unlocked Whether the pool is currently locked to reentrancy
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
/// @notice The fee growth as a Q128.128 fees of token0 collected per unit
/// of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal0X128() external view returns (uint256);
/// @notice The fee growth as a Q128.128 fees of token1 collected per unit
/// of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal1X128() external view returns (uint256);
/// @notice The amounts of token0 and token1 that are owed to the protocol
/// @dev Protocol fees will never exceed uint128 max in either token
function protocolFees()
external
view
returns (uint128 token0, uint128 token1);
/// @notice The currently in range liquidity available to the pool
/// @dev This value has no relationship to the total liquidity across all
/// ticks
/// @return The liquidity at the current price of the pool
function liquidity() external view returns (uint128);
/// @notice Look up information about a specific tick in the pool
/// @param tick The tick to look up
/// @return liquidityGross the total amount of position liquidity that uses
/// the pool either as tick lower or
/// tick upper
/// @return liquidityNet how much liquidity changes when the pool price
/// crosses the tick,
/// @return feeGrowthOutside0X128 the fee growth on the other side of the
/// tick from the current tick in token0,
/// @return feeGrowthOutside1X128 the fee growth on the other side of the
/// tick from the current tick in token1,
/// @return tickCumulativeOutside the cumulative tick value on the other
/// side of the tick from the current tick
/// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity
/// on the other side of the tick from the current tick,
/// @return secondsOutside the seconds spent on the other side of the tick
/// from the current tick,
/// @return initialized Set to true if the tick is initialized, i.e.
/// liquidityGross is greater than 0, otherwise equal to false.
/// Outside values can only be used if the tick is initialized, i.e. if
/// liquidityGross is greater than 0.
/// In addition, these values are only relative and must be used only in
/// comparison to previous snapshots for
/// a specific position.
function ticks(
int24 tick
)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128,
int56 tickCumulativeOutside,
uint160 secondsPerLiquidityOutsideX128,
uint32 secondsOutside,
bool initialized
);
/// @notice Returns 256 packed tick initialized boolean values. See
/// TickBitmap for more information
function tickBitmap(
int16 wordPosition
) external view returns (uint256);
/// @notice Returns the information about a position by the position's key
/// @param key The position's key is a hash of a preimage composed by the
/// owner, tickLower and tickUpper
/// @return liquidity The amount of liquidity in the position,
/// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick
/// range as of the last mint/burn/poke,
/// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick
/// range as of the last mint/burn/poke,
/// @return tokensOwed0 the computed amount of token0 owed to the position
/// as of the last mint/burn/poke,
/// @return tokensOwed1 the computed amount of token1 owed to the position
/// as of the last mint/burn/poke
function positions(
bytes32 key
)
external
view
returns (
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
/// @notice Returns data about a specific observation index
/// @param index The element of the observations array to fetch
/// @dev You most likely want to use #observe() instead of this method to
/// get an observation as of some amount of time
/// ago, rather than at a specific index in the array.
/// @return blockTimestamp The timestamp of the observation,
/// @return tickCumulative the tick multiplied by seconds elapsed for the
/// life of the pool as of the observation timestamp,
/// @return secondsPerLiquidityCumulativeX128 the seconds per in range
/// liquidity for the life of the pool as of the observation timestamp,
/// @return initialized whether the observation has been initialized and the
/// values are safe to use
function observations(
uint256 index
)
external
view
returns (
uint32 blockTimestamp,
int56 tickCumulative,
uint160 secondsPerLiquidityCumulativeX128,
bool initialized
);
}
interface IUniswapV3Pool is IUniswapV3PoolImmutables, IUniswapV3PoolState {
function flash(
address recipient,
uint256 amount0,
uint256 amount1,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { SwapParams } from "contracts/structs/SwapStructs.sol";
import {
NftAddLiquidity,
NftRemoveLiquidity
} from "contracts/structs/NftLiquidityStructs.sol";
struct NftZapIn {
SwapParams[] swaps;
NftAddLiquidity addLiquidityParams;
}
struct NftZapOut {
NftRemoveLiquidity removeLiquidityParams;
SwapParams[] swaps;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct SwapParams {
address tokenApproval;
address router;
uint256 amountIn;
uint256 desiredAmountOut;
uint256 minAmountOut;
address tokenIn;
address tokenOut;
bytes extraData;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol";
import { SwapParams } from "contracts/structs/SwapStructs.sol";
struct Farm {
address stakingContract;
uint256 poolIndex;
}
struct DepositParams {
Farm farm;
address[] tokensIn;
uint256[] amountsIn;
ZapIn zap;
bytes extraData;
}
struct WithdrawParams {
bytes extraData;
ZapOut zap;
address[] tokensOut;
}
struct HarvestParams {
SwapParams[] swaps;
bytes extraData;
address[] tokensOut;
}
struct CompoundParams {
Farm claimFarm;
bytes claimExtraData;
address[] rewardTokens;
ZapIn zap;
Farm depositFarm;
bytes depositExtraData;
}
struct SimpleDepositParams {
Farm farm;
address lpToken;
uint256 amountIn;
bytes extraData;
}
struct SimpleHarvestParams {
address[] rewardTokens;
bytes extraData;
}
struct SimpleWithdrawParams {
address lpToken;
uint256 amountOut;
bytes extraData;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Math library for liquidity
library LiquidityMath {
/// @notice Add a signed liquidity delta to liquidity and revert if it
/// overflows or underflows
/// @param x The liquidity before change
/// @param y The delta by which liquidity should be changed
/// @return z The liquidity delta
function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) {
assembly ("memory-safe") {
z :=
add(and(x, 0xffffffffffffffffffffffffffffffff), signextend(15, y))
if shr(128, z) {
// revert SafeCastOverflow()
mstore(0, 0x93dafdf1)
revert(0x1c, 0x04)
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Interface for functions to access any storage slot in a contract
interface IExtsload {
/// @notice Called by external contracts to access granular pool state
/// @param slot Key of slot to sload
/// @return value The value of the slot as bytes32
function extsload(
bytes32 slot
) external view returns (bytes32 value);
/// @notice Called by external contracts to access granular pool state
/// @param startSlot Key of slot to start sloading from
/// @param nSlots Number of slots to load into return value
/// @return values List of loaded values.
function extsload(
bytes32 startSlot,
uint256 nSlots
) external view returns (bytes32[] memory values);
/// @notice Called by external contracts to access sparse pool state
/// @param slots List of slots to SLOAD from.
/// @return values List of loaded values.
function extsload(
bytes32[] calldata slots
) external view returns (bytes32[] memory values);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
/// @notice Interface for functions to access any transient storage slot in a
/// contract
interface IExttload {
/// @notice Called by external contracts to access transient storage of the
/// contract
/// @param slot Key of slot to tload
/// @return value The value of the slot as bytes32
function exttload(
bytes32 slot
) external view returns (bytes32 value);
/// @notice Called by external contracts to access sparse transient pool
/// state
/// @param slots List of slots to tload
/// @return values List of loaded values
function exttload(
bytes32[] calldata slots
) external view returns (bytes32[] memory values);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { CustomRevert } from "./CustomRevert.sol";
/// @title Safe casting methods
/// @notice Contains methods for safely casting between types
library SafeCast {
using CustomRevert for bytes4;
error SafeCastOverflow();
/// @notice Cast a uint256 to a uint160, revert on overflow
/// @param x The uint256 to be downcasted
/// @return y The downcasted integer, now type uint160
function toUint160(
uint256 x
) internal pure returns (uint160 y) {
y = uint160(x);
if (y != x) SafeCastOverflow.selector.revertWith();
}
/// @notice Cast a uint256 to a uint128, revert on overflow
/// @param x The uint256 to be downcasted
/// @return y The downcasted integer, now type uint128
function toUint128(
uint256 x
) internal pure returns (uint128 y) {
y = uint128(x);
if (x != y) SafeCastOverflow.selector.revertWith();
}
/// @notice Cast a int128 to a uint128, revert on overflow or underflow
/// @param x The int128 to be casted
/// @return y The casted integer, now type uint128
function toUint128(
int128 x
) internal pure returns (uint128 y) {
if (x < 0) SafeCastOverflow.selector.revertWith();
y = uint128(x);
}
/// @notice Cast a int256 to a int128, revert on overflow or underflow
/// @param x The int256 to be downcasted
/// @return y The downcasted integer, now type int128
function toInt128(
int256 x
) internal pure returns (int128 y) {
y = int128(x);
if (y != x) SafeCastOverflow.selector.revertWith();
}
/// @notice Cast a uint256 to a int256, revert on overflow
/// @param x The uint256 to be casted
/// @return y The casted integer, now type int256
function toInt256(
uint256 x
) internal pure returns (int256 y) {
y = int256(x);
if (y < 0) SafeCastOverflow.selector.revertWith();
}
/// @notice Cast a uint256 to a int128, revert on overflow
/// @param x The uint256 to be downcasted
/// @return The downcasted integer, now type int128
function toInt128(
uint256 x
) internal pure returns (int128) {
if (x >= 1 << 127) SafeCastOverflow.selector.revertWith();
return int128(int256(x));
}
}// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../token/ERC721/extensions/IERC721Enumerable.sol";
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SwapParams } from "contracts/structs/SwapStructs.sol";
import {
AddLiquidityParams,
RemoveLiquidityParams
} from "contracts/structs/LiquidityStructs.sol";
struct ZapIn {
SwapParams[] swaps;
AddLiquidityParams addLiquidityParams;
}
struct ZapOut {
RemoveLiquidityParams removeLiquidityParams;
SwapParams[] swaps;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct AddLiquidityParams {
address router;
address lpToken;
address[] tokens;
uint256[] desiredAmounts;
uint256[] minAmounts;
bytes extraData;
}
struct RemoveLiquidityParams {
address router;
address lpToken;
address[] tokens;
uint256 lpAmountIn;
uint256[] minAmountsOut;
bytes extraData;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"solmate/=lib/solmate/src/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"@morpho-blue/=lib/morpho-blue/src/",
"ds-test/=lib/solmate/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"morpho-blue/=lib/morpho-blue/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IPositionManager","name":"positionManager_","type":"address"},{"internalType":"contract IStateView","name":"stateView_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidDesiredAmount","type":"error"},{"inputs":[],"name":"InvalidParameters","type":"error"},{"inputs":[],"name":"InvalidTokenOwner","type":"error"},{"inputs":[{"components":[{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"}],"internalType":"struct Pool","name":"pool","type":"tuple"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint256","name":"amount0Desired","type":"uint256"},{"internalType":"uint256","name":"amount1Desired","type":"uint256"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct NftAddLiquidity","name":"addLiquidityParams","type":"tuple"}],"name":"addLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NftPosition","name":"position","type":"tuple"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NftPosition","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"depositExistingNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"components":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NftPosition","name":"","type":"tuple"},{"internalType":"address[]","name":"rewardTokens","type":"address[]"}],"name":"earned","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"earnedFees","outputs":[{"internalType":"uint256","name":"fees0","type":"uint256"},{"internalType":"uint256","name":"fees1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"fee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"getTokenId","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"components":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NftPosition","name":"","type":"tuple"}],"name":"isStaked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"poolId","type":"bytes32"}],"name":"poolInfo","outputs":[{"components":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint24","name":"tickSpacing","type":"uint24"},{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"feeGrowthGlobal0X128","type":"uint256"},{"internalType":"uint256","name":"feeGrowthGlobal1X128","type":"uint256"}],"internalType":"struct NftPoolInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftManager","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"positionInfo","outputs":[{"components":[{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"}],"internalType":"struct NftPositionInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"positionLiquidity","outputs":[{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"liquidity","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionManager","outputs":[{"internalType":"contract IPositionManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"positionPoolKey","outputs":[{"components":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"bytes32","name":"poolId","type":"bytes32"}],"internalType":"struct NftPoolKey","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"uint128","name":"amount0Max","type":"uint128"},{"internalType":"uint128","name":"amount1Max","type":"uint128"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct NftRemoveLiquidity","name":"removeLiquidityParams","type":"tuple"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stateView","outputs":[{"internalType":"contract IStateView","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NftPosition","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"withdrawNft","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c06040523480156200001157600080fd5b5060405162002f7d38038062002f7d833981016040819052620000349162000065565b6001600160a01b039182166080521660a052620000a4565b6001600160a01b03811681146200006257600080fd5b50565b600080604083850312156200007957600080fd5b825162000086816200004c565b602084015190925062000099816200004c565b809150509250929050565b60805160a051612e436200013a600039600081816101850152818161051a01528181610abe01528181610bb201528181610e0501528181610e9e0152610f500152600081816101d7015281816104a8015281816105c30152818161065b0152818161089501528181610942015281816109d301528181610b4301528181610c7401528181610d380152610fe80152612e436000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c8063b943855e116100a2578063e4dc2aa411610071578063e4dc2aa4146102d4578063e734583a146102e7578063e759c4651461030f578063e85505e11461034e578063ff7b92661461014d57600080fd5b8063b943855e14610220578063cce9480114610241578063de91a5e514610254578063dfe8addd1461029d57600080fd5b80634c4a3c25116100de5780634c4a3c25146101805780636f4621e3146101bf578063791b98bc146101d25780639e6eda18146101f957600080fd5b806304caab47146101105780631ae75562146101255780632847ccf21461014d5780633f40c7fa14610160575b600080fd5b61012361011e3660046121bc565b61036e565b005b6101386101333660046122be565b6103d1565b60405190151581526020015b60405180910390f35b61012361015b36600461233c565b505050565b61017361016e366004612417565b6103da565b604051610144919061246d565b6101a77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610144565b6101236101cd3660046124d1565b610429565b6101a77f000000000000000000000000000000000000000000000000000000000000000081565b61020c610207366004612576565b610485565b60405162ffffff9091168152602001610144565b61023361022e3660046125a2565b6105bd565b604051908152602001610144565b61012361024f3660046125db565b61070f565b610267610262366004612576565b61080b565b6040805182516001600160801b03168152602080840151600290810b918301919091529282015190920b90820152606001610144565b6102b06102ab3660046126aa565b610868565b6040805182516001600160a01b031681526020928301519281019290925201610144565b6102336102e23660046126eb565b61093c565b6102fa6102f53660046126aa565b6109cc565b60408051928352602083019190915201610144565b61032261031d366004612576565b610c6c565b60408051600294850b81529290930b60208301526001600160801b031691810191909152606001610144565b61036161035c366004612576565b610db5565b6040516101449190612708565b60a081015160c08201516001600160801b038211156103a0576040516363f6942760e11b815260040160405180910390fd5b6001600160801b038111156103c8576040516363f6942760e11b815260040160405180910390fd5b61015b836110e1565b60005b92915050565b606081516001600160401b038111156103f5576103f5611fe3565b60405190808252806020026020018201604052801561041e578160200160208202803683370190505b5090505b9392505050565b61047d61043c60608801604089016126eb565b876060013584848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061148892505050565b505050505050565b604051637ba03aad60e01b81526004810182905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637ba03aad9060240160c060405180830381865afa1580156104ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610513919061285c565b50905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c815641c6105528460a0902090565b6040518263ffffffff1660e01b815260040161057091815260200190565b608060405180830381865afa15801561058d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b19190612889565b98975050505050505050565b600060017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166375794a3c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906128e8565b61064d9190612901565b9050816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e836040518263ffffffff1660e01b81526004016106a791815260200190565b602060405180830381865afa1580156106c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e89190612922565b6001600160a01b0316146103d45760405163153e35b760e11b815260040160405180910390fd5b606081015160808201516001600160801b03821115610741576040516363f6942760e11b815260040160405180910390fd5b6001600160801b03811115610769576040516363f6942760e11b815260040160405180910390fd5b600061077484611623565b90506001600160801b03801684604001516001600160801b0316036107a3576001600160801b03811660408501525b83604001516001600160801b03166000036107d157604051630e52390960e41b815260040160405180910390fd5b806001600160801b031684604001516001600160801b0316036107fc576107f784611696565b610805565b61080584611838565b50505050565b604080516060810182526000808252602082018190529181018290529080806108348686610c6c565b604080516060810182526001600160801b039092168252600293840b60208301529190920b90820152935050505092915050565b6040805180820190915260008082526020820152604051637ba03aad60e01b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690637ba03aad9060240160c060405180830381865afa1580156108e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610908919061285c565b509050604051806040016040528060006001600160a01b031681526020016109318360a0902090565b905295945050505050565b600060017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166375794a3c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561099e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c291906128e8565b6103d49190612901565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637ba03aad856040518263ffffffff1660e01b8152600401610a1f91815260200190565b60c060405180830381865afa158015610a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a60919061285c565b5090506000806000610a73600088610c6c565b9250925092506000610a868560a0902090565b6040516353e9c1fb60e01b815260048101829052600286810b602483015285900b604482015290915060009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906353e9c1fb906064016040805180830381865afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b28919061293f565b60408051602681018e905260068101899052600381018a90527f00000000000000000000000000000000000000000000000000000000000000008152603a600c8201206000928201839052602082018390529082905292945090925090604051634bfebda160e11b8152600481018690526024810182905290915060009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906397fd7b4290604401606060405180830381865afa158015610bf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1d9190612963565b9250925050610c3c828603886001600160801b0316600160801b6118d3565b9b50610c58818503886001600160801b0316600160801b6118d3565b9a5050505050505050505050935093915050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389097a6a866040518263ffffffff1660e01b8152600401610cc091815260200190565b602060405180830381865afa158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0191906128e8565b9050610d108160081c60020b90565b9350610d1f8160201c60020b90565b604051631efeed3360e01b8152600481018790529093507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631efeed3390602401602060405180830381865afa158015610d87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dab919061299a565b9150509250925092565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915260008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c815641c866040518263ffffffff1660e01b8152600401610e5191815260200190565b608060405180830381865afa158015610e6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e929190612889565b935050925092506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639ec538c8886040518263ffffffff1660e01b8152600401610eea91815260200190565b6040805180830381865afa158015610f06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2a919061293f565b60405163fa6793d560e01b8152600481018a905291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fa6793d590602401602060405180830381865afa158015610f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbb919061299a565b6040516386b6be7d60e01b815266ffffffffffffff198a1660048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906386b6be7d9060240160a060405180830381865afa15801561102f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105391906129b7565b905060405180610120016040528082600001516001600160a01b0316815260200182602001516001600160a01b031681526020018662ffffff168152602001826060015162ffffff168152602001886001600160a01b031681526020018760020b8152602001836001600160801b031681526020018581526020018481525097505050505050505092915050565b6040810151516001600160a01b031615611215576040818101515160a0830151915163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba3600482015260248101929092526001600160a01b03169063095ea7b3906044016020604051808303816000875af115801561115c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118091906129d3565b5060408181015151825160a084015192516387517c4560e01b81526001600160a01b03928316600482015290821660248201529116604482015265ffffffffffff421660648201526e22d473030f116ddee9f6b43ac78ba3906387517c4590608401600060405180830381600087803b1580156111fc57600080fd5b505af1158015611210573d6000803e3d6000fd5b505050505b6040808201516020015160c0830151915163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba3600482015260248101929092526001600160a01b03169063095ea7b3906044016020604051808303816000875af115801561127f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a391906129d3565b5060408181015160200151825160c084015192516387517c4560e01b81526001600160a01b03928316600482015290821660248201529116604482015265ffffffffffff421660648201526e22d473030f116ddee9f6b43ac78ba3906387517c4590608401600060405180830381600087803b15801561132257600080fd5b505af1158015611336573d6000803e3d6000fd5b5050505080602001516000036113545761134f81611975565b61135d565b61135d81611c15565b6040810151516001600160a01b0316156113fa5760408181015151905163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba36004820152600060248201526001600160a01b039091169063095ea7b3906044016020604051808303816000875af11580156113d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f891906129d3565b505b60408082015160200151905163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba36004820152600060248201526001600160a01b039091169063095ea7b3906044016020604051808303816000875af1158015611460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148491906129d3565b5050565b60008180602001905181019061149e9190612a66565b90506000600160116040516020016114b7929190612af8565b60408051808303601f19018152600280845260608401909252925060009190816020015b60608152602001906001900390816114db5790505090508460008060008660400151604051602001611511959493929190612b46565b6040516020818303038152906040528160008151811061153357611533612b7a565b602090810291909101810191909152835184820151604080516001600160a01b03938416948101949094529116908201523060608201526080016040516020818303038152906040528160018151811061158f5761158f612b7a565b6020026020010181905250856001600160a01b031663dd46508f83836040516020016115bc929190612b90565b604051602081830303815290604052426040518363ffffffff1660e01b81526004016115e9929190612c02565b600060405180830381600087803b15801561160357600080fd5b505af1158015611617573d6000803e3d6000fd5b50505050505050505050565b80516020820151604051631efeed3360e01b815260048101919091526000916001600160a01b031690631efeed3390602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d4919061299a565b60008160e001518060200190518101906116b09190612a66565b90506000600360116040516020016116c9929190612af8565b60408051808303601f19018152600280845260608401909252925060009190816020015b60608152602001906001900390816116ed579050509050836020015160008085604001516040516020016117249493929190612c24565b6040516020818303038152906040528160008151811061174657611746612b7a565b602090810291909101810191909152835184820151604080516001600160a01b0393841694810194909452911690820152306060820152608001604051602081830303815290604052816001815181106117a2576117a2612b7a565b602002602001018190525083600001516001600160a01b031663dd46508f83836040516020016117d3929190612b90565b604051602081830303815290604052426040518363ffffffff1660e01b8152600401611800929190612c02565b600060405180830381600087803b15801561181a57600080fd5b505af115801561182e573d6000803e3d6000fd5b5050505050505050565b60008160e001518060200190518101906118529190612a66565b905060006001601160405160200161186b929190612af8565b60408051808303601f19018152600280845260608401909252925060009190816020015b606081526020019060019003908161188f57905050905083602001518460400151856060015186608001518660400151604051602001611724959493929190612c60565b600083830281600019858709828110838203039150508084116118f557600080fd5b8060000361190857508290049050610422565b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b60008161012001518060200190518101906119909190612c94565b60408051600160f91b6020820152600d60f81b6021820152600560fa1b602282015281516003818303810182526023830181815260a3840190945293945092600092916043015b60608152602001906001900390816119d7579050509050600084604001516000015190506000856040015160200151905060006040518060a00160405280846001600160a01b03168152602001836001600160a01b0316815260200188604001516040015162ffffff168152602001876000015160020b815260200187602001516001600160a01b03168152509050808760600151886080015188606001518a60a001518b60c00151308c60400151604051602001611a9d989796959493929190612d53565b60405160208183030381529060405284600081518110611abf57611abf612b7a565b60200260200101819052508282604051602001611af29291906001600160a01b0392831681529116602082015260400190565b60405160208183030381529060405284600181518110611b1457611b14612b7a565b60209081029190910181019190915260408051600092810192909252309082015260600160405160208183030381529060405284600281518110611b5a57611b5a612b7a565b602090810291909101015260006001600160a01b03841615611b7d576000611b83565b8760a001515b905087600001516001600160a01b031663dd46508f828888604051602001611bac929190612b90565b604051602081830303815290604052426040518463ffffffff1660e01b8152600401611bd9929190612c02565b6000604051808303818588803b158015611bf257600080fd5b505af1158015611c06573d6000803e3d6000fd5b50505050505050505050505050565b6000816101200151806020019051810190611c309190612c94565b6040830151805160209091015160a0850151929350909160609081906000901580611c5d575060c0870151155b90508015611e4e5760a08701511515600081611c795785611c7b565b865b9050600082611c8a5787611c8c565b865b905060006001600160a01b0383161560405160006020820152600b60f81b6021820152600960f91b6022820152600560fa1b60238201529015915060240160408051808303601f19018152600480845260a084019092529850816020015b6060815260200190600190039081611cea5790505095508a602001518a606001518c60a001518d60c001518d60400151604051602001611d2e959493929190612c60565b60405160208183030381529060405286600081518110611d5057611d50612b7a565b602090810291909101810191909152604080516001600160a01b03861692810192909252600090820152811515606082015260800160405160208183030381529060405286600181518110611da757611da7612b7a565b602002602001018190525081604051602001611dd291906001600160a01b0391909116815260200190565b60405160208183030381529060405286600281518110611df457611df4612b7a565b60209081029190910181019190915260408051600092810192909252309082015260600160405160208183030381529060405286600381518110611e3a57611e3a612b7a565b602002602001018190525050505050611f9c565b60405160006020820152600d60f81b6021820152600560fa1b602282015260230160408051808303601f190181526003808452608084019092529450816020015b6060815260200190600190039081611e8f579050509150866020015186606001518860a001518960c001518960400151604051602001611ed3959493929190612c60565b60405160208183030381529060405282600081518110611ef557611ef5612b7a565b60200260200101819052508484604051602001611f289291906001600160a01b0392831681529116602082015260400190565b60405160208183030381529060405282600181518110611f4a57611f4a612b7a565b60209081029190910181019190915260408051600092810192909252309082015260600160405160208183030381529060405282600281518110611f9057611f90612b7a565b60200260200101819052505b60006001600160a01b03861615611fb4576000611fba565b8760a001515b905087600001516001600160a01b031663dd46508f828686604051602001611bac929190612b90565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561201b5761201b611fe3565b60405290565b60405161014081016001600160401b038111828210171561201b5761201b611fe3565b60405161010081016001600160401b038111828210171561201b5761201b611fe3565b604051601f8201601f191681016001600160401b038111828210171561208f5761208f611fe3565b604052919050565b6001600160a01b03811681146120ac57600080fd5b50565b80356120ba81612097565b919050565b62ffffff811681146120ac57600080fd5b6000606082840312156120e257600080fd5b6120ea611ff9565b905081356120f781612097565b8152602082013561210781612097565b6020820152604082013561211a816120bf565b604082015292915050565b8060020b81146120ac57600080fd5b80356120ba81612125565b60006001600160401b0382111561215857612158611fe3565b50601f01601f191660200190565b600082601f83011261217757600080fd5b813561218a6121858261213f565b612067565b81815284602083860101111561219f57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156121ce57600080fd5b81356001600160401b03808211156121e557600080fd5b9083019061018082860312156121fa57600080fd5b612202612021565b61220b836120af565b81526020830135602082015261222486604085016120d0565b604082015261223560a08401612134565b606082015261224660c08401612134565b608082015260e083013560a08201526101008084013560c08301526101208085013560e08401526101408501358284015261016085013591508382111561228c57600080fd5b61229888838701612166565b908301525095945050505050565b6000608082840312156122b857600080fd5b50919050565b60008060a083850312156122d157600080fd5b82356122dc81612097565b91506122eb84602085016122a6565b90509250929050565b60008083601f84011261230657600080fd5b5081356001600160401b0381111561231d57600080fd5b60208301915083602082850101111561233557600080fd5b9250929050565b600080600060a0848603121561235157600080fd5b61235b85856122a6565b925060808401356001600160401b0381111561237657600080fd5b612382868287016122f4565b9497909650939450505050565b600082601f8301126123a057600080fd5b813560206001600160401b038211156123bb576123bb611fe3565b8160051b6123ca828201612067565b92835284810182019282810190878511156123e457600080fd5b83870192505b8483101561240c5782356123fd81612097565b825291830191908301906123ea565b979650505050505050565b600080600060c0848603121561242c57600080fd5b833561243781612097565b925061244685602086016122a6565b915060a08401356001600160401b0381111561246157600080fd5b610dab8682870161238f565b6020808252825182820181905260009190848201906040850190845b818110156124a557835183529284019291840191600101612489565b50909695505050505050565b6001600160801b03811681146120ac57600080fd5b80356120ba816124b1565b60008060008060008061010087890312156124eb57600080fd5b6124f588886122a6565b955060808701356001600160401b038082111561251157600080fd5b61251d8a838b0161238f565b965060a0890135915061252f826124b1565b90945060c088013590612541826124b1565b90935060e0880135908082111561255757600080fd5b5061256489828a016122f4565b979a9699509497509295939492505050565b6000806040838503121561258957600080fd5b823561259481612097565b946020939093013593505050565b600080604083850312156125b557600080fd5b82356125c081612097565b915060208301356125d081612097565b809150509250929050565b6000602082840312156125ed57600080fd5b81356001600160401b038082111561260457600080fd5b90830190610100828603121561261957600080fd5b612621612044565b61262a836120af565b815260208301356020820152612642604084016124c6565b6040820152606083013560608201526080830135608082015261266760a084016124c6565b60a082015261267860c084016124c6565b60c082015260e08301358281111561268f57600080fd5b61269b87828601612166565b60e08301525095945050505050565b6000806000606084860312156126bf57600080fd5b83356126ca81612097565b925060208401356126da81612097565b929592945050506040919091013590565b6000602082840312156126fd57600080fd5b813561042281612097565b81516001600160a01b039081168252602080840151909116908201526040808301516101208301916127409084018262ffffff169052565b506060830151612757606084018262ffffff169052565b50608083015161277260808401826001600160a01b03169052565b5060a083015161278760a084018260020b9052565b5060c08301516127a260c08401826001600160801b03169052565b5060e083015160e083015261010080840151818401525092915050565b600060a082840312156127d157600080fd5b60405160a081018181106001600160401b03821117156127f3576127f3611fe3565b8060405250809150825161280681612097565b8152602083015161281681612097565b60208201526040830151612829816120bf565b6040820152606083015161283c81612125565b6060820152608083015161284f81612097565b6080919091015292915050565b60008060c0838503121561286f57600080fd5b61287984846127bf565b915060a083015190509250929050565b6000806000806080858703121561289f57600080fd5b84516128aa81612097565b60208601519094506128bb81612125565b60408601519093506128cc816120bf565b60608601519092506128dd816120bf565b939692955090935050565b6000602082840312156128fa57600080fd5b5051919050565b818103818111156103d457634e487b7160e01b600052601160045260246000fd5b60006020828403121561293457600080fd5b815161042281612097565b6000806040838503121561295257600080fd5b505080516020909101519092909150565b60008060006060848603121561297857600080fd5b8351612983816124b1565b602085015160409095015190969495509392505050565b6000602082840312156129ac57600080fd5b8151610422816124b1565b600060a082840312156129c957600080fd5b61042283836127bf565b6000602082840312156129e557600080fd5b8151801515811461042257600080fd5b60005b83811015612a105781810151838201526020016129f8565b50506000910152565b600082601f830112612a2a57600080fd5b8151612a386121858261213f565b818152846020838601011115612a4d57600080fd5b612a5e8260208301602087016129f5565b949350505050565b600060208284031215612a7857600080fd5b81516001600160401b0380821115612a8f57600080fd5b9083019060608286031215612aa357600080fd5b612aab611ff9565b8251612ab681612097565b81526020830151612ac681612097565b6020820152604083015182811115612add57600080fd5b612ae987828601612a19565b60408301525095945050505050565b6001600160f81b031960f893841b811682529190921b16600182015260020190565b60008151808452612b328160208601602086016129f5565b601f01601f19169290920160200192915050565b85815260ff8516602082015260ff8416604082015260ff8316606082015260a06080820152600061240c60a0830184612b1a565b634e487b7160e01b600052603260045260246000fd5b604081526000612ba36040830185612b1a565b6020838203818501528185518084528284019150828160051b85010183880160005b83811015612bf357601f19878403018552612be1838351612b1a565b94860194925090850190600101612bc5565b50909998505050505050505050565b604081526000612c156040830185612b1a565b90508260208301529392505050565b84815260006001600160801b03808616602084015280851660408401525060806060830152612c566080830184612b1a565b9695505050505050565b8581526001600160801b038516602082015283604082015282606082015260a06080820152600061240c60a0830184612b1a565b600060208284031215612ca657600080fd5b81516001600160401b0380821115612cbd57600080fd5b9083019060808286031215612cd157600080fd5b604051608081018181108382111715612cec57612cec611fe3565b6040528251612cfa816120bf565b81526020830151612d0a81612097565b6020820152604083015182811115612d2157600080fd5b612d2d87828601612a19565b60408301525060608301519250612d43836124b1565b6060810192909252509392505050565b600061018060018060a01b03808c511684528060208d015116602085015262ffffff60408d015116604085015260608c015160020b60608501528060808d015116608085015250612da960a084018b60020b9052565b612db860c084018a60020b9052565b6001600160801b03881660e08401528661010084015285610120840152612deb6101408401866001600160a01b03169052565b80610160840152612dfe81840185612b1a565b9b9a505050505050505050505056fea2646970667358221220d4bd8fa33bacc9f60fe1ed7f7a2c339200d188496895f1519243e65cc6b5792864736f6c634300081300330000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f401600000000000000000000000077395f3b2e73ae90843717371294fa97cc419d64
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061010b5760003560e01c8063b943855e116100a2578063e4dc2aa411610071578063e4dc2aa4146102d4578063e734583a146102e7578063e759c4651461030f578063e85505e11461034e578063ff7b92661461014d57600080fd5b8063b943855e14610220578063cce9480114610241578063de91a5e514610254578063dfe8addd1461029d57600080fd5b80634c4a3c25116100de5780634c4a3c25146101805780636f4621e3146101bf578063791b98bc146101d25780639e6eda18146101f957600080fd5b806304caab47146101105780631ae75562146101255780632847ccf21461014d5780633f40c7fa14610160575b600080fd5b61012361011e3660046121bc565b61036e565b005b6101386101333660046122be565b6103d1565b60405190151581526020015b60405180910390f35b61012361015b36600461233c565b505050565b61017361016e366004612417565b6103da565b604051610144919061246d565b6101a77f00000000000000000000000077395f3b2e73ae90843717371294fa97cc419d6481565b6040516001600160a01b039091168152602001610144565b6101236101cd3660046124d1565b610429565b6101a77f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f401681565b61020c610207366004612576565b610485565b60405162ffffff9091168152602001610144565b61023361022e3660046125a2565b6105bd565b604051908152602001610144565b61012361024f3660046125db565b61070f565b610267610262366004612576565b61080b565b6040805182516001600160801b03168152602080840151600290810b918301919091529282015190920b90820152606001610144565b6102b06102ab3660046126aa565b610868565b6040805182516001600160a01b031681526020928301519281019290925201610144565b6102336102e23660046126eb565b61093c565b6102fa6102f53660046126aa565b6109cc565b60408051928352602083019190915201610144565b61032261031d366004612576565b610c6c565b60408051600294850b81529290930b60208301526001600160801b031691810191909152606001610144565b61036161035c366004612576565b610db5565b6040516101449190612708565b60a081015160c08201516001600160801b038211156103a0576040516363f6942760e11b815260040160405180910390fd5b6001600160801b038111156103c8576040516363f6942760e11b815260040160405180910390fd5b61015b836110e1565b60005b92915050565b606081516001600160401b038111156103f5576103f5611fe3565b60405190808252806020026020018201604052801561041e578160200160208202803683370190505b5090505b9392505050565b61047d61043c60608801604089016126eb565b876060013584848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061148892505050565b505050505050565b604051637ba03aad60e01b81526004810182905260009081906001600160a01b037f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40161690637ba03aad9060240160c060405180830381865afa1580156104ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610513919061285c565b50905060007f00000000000000000000000077395f3b2e73ae90843717371294fa97cc419d646001600160a01b031663c815641c6105528460a0902090565b6040518263ffffffff1660e01b815260040161057091815260200190565b608060405180830381865afa15801561058d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b19190612889565b98975050505050505050565b600060017f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40166001600160a01b03166375794a3c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906128e8565b61064d9190612901565b9050816001600160a01b03167f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40166001600160a01b0316636352211e836040518263ffffffff1660e01b81526004016106a791815260200190565b602060405180830381865afa1580156106c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e89190612922565b6001600160a01b0316146103d45760405163153e35b760e11b815260040160405180910390fd5b606081015160808201516001600160801b03821115610741576040516363f6942760e11b815260040160405180910390fd5b6001600160801b03811115610769576040516363f6942760e11b815260040160405180910390fd5b600061077484611623565b90506001600160801b03801684604001516001600160801b0316036107a3576001600160801b03811660408501525b83604001516001600160801b03166000036107d157604051630e52390960e41b815260040160405180910390fd5b806001600160801b031684604001516001600160801b0316036107fc576107f784611696565b610805565b61080584611838565b50505050565b604080516060810182526000808252602082018190529181018290529080806108348686610c6c565b604080516060810182526001600160801b039092168252600293840b60208301529190920b90820152935050505092915050565b6040805180820190915260008082526020820152604051637ba03aad60e01b8152600481018390526000907f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40166001600160a01b031690637ba03aad9060240160c060405180830381865afa1580156108e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610908919061285c565b509050604051806040016040528060006001600160a01b031681526020016109318360a0902090565b905295945050505050565b600060017f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40166001600160a01b03166375794a3c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561099e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c291906128e8565b6103d49190612901565b60008060007f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40166001600160a01b0316637ba03aad856040518263ffffffff1660e01b8152600401610a1f91815260200190565b60c060405180830381865afa158015610a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a60919061285c565b5090506000806000610a73600088610c6c565b9250925092506000610a868560a0902090565b6040516353e9c1fb60e01b815260048101829052600286810b602483015285900b604482015290915060009081906001600160a01b037f00000000000000000000000077395f3b2e73ae90843717371294fa97cc419d6416906353e9c1fb906064016040805180830381865afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b28919061293f565b60408051602681018e905260068101899052600381018a90527f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40168152603a600c8201206000928201839052602082018390529082905292945090925090604051634bfebda160e11b8152600481018690526024810182905290915060009081906001600160a01b037f00000000000000000000000077395f3b2e73ae90843717371294fa97cc419d6416906397fd7b4290604401606060405180830381865afa158015610bf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1d9190612963565b9250925050610c3c828603886001600160801b0316600160801b6118d3565b9b50610c58818503886001600160801b0316600160801b6118d3565b9a5050505050505050505050935093915050565b6000806000807f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40166001600160a01b03166389097a6a866040518263ffffffff1660e01b8152600401610cc091815260200190565b602060405180830381865afa158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0191906128e8565b9050610d108160081c60020b90565b9350610d1f8160201c60020b90565b604051631efeed3360e01b8152600481018790529093507f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f40166001600160a01b031690631efeed3390602401602060405180830381865afa158015610d87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dab919061299a565b9150509250925092565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915260008060007f00000000000000000000000077395f3b2e73ae90843717371294fa97cc419d646001600160a01b031663c815641c866040518263ffffffff1660e01b8152600401610e5191815260200190565b608060405180830381865afa158015610e6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e929190612889565b935050925092506000807f00000000000000000000000077395f3b2e73ae90843717371294fa97cc419d646001600160a01b0316639ec538c8886040518263ffffffff1660e01b8152600401610eea91815260200190565b6040805180830381865afa158015610f06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2a919061293f565b60405163fa6793d560e01b8152600481018a905291935091506000906001600160a01b037f00000000000000000000000077395f3b2e73ae90843717371294fa97cc419d64169063fa6793d590602401602060405180830381865afa158015610f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbb919061299a565b6040516386b6be7d60e01b815266ffffffffffffff198a1660048201529091506000906001600160a01b037f0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f401616906386b6be7d9060240160a060405180830381865afa15801561102f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105391906129b7565b905060405180610120016040528082600001516001600160a01b0316815260200182602001516001600160a01b031681526020018662ffffff168152602001826060015162ffffff168152602001886001600160a01b031681526020018760020b8152602001836001600160801b031681526020018581526020018481525097505050505050505092915050565b6040810151516001600160a01b031615611215576040818101515160a0830151915163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba3600482015260248101929092526001600160a01b03169063095ea7b3906044016020604051808303816000875af115801561115c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118091906129d3565b5060408181015151825160a084015192516387517c4560e01b81526001600160a01b03928316600482015290821660248201529116604482015265ffffffffffff421660648201526e22d473030f116ddee9f6b43ac78ba3906387517c4590608401600060405180830381600087803b1580156111fc57600080fd5b505af1158015611210573d6000803e3d6000fd5b505050505b6040808201516020015160c0830151915163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba3600482015260248101929092526001600160a01b03169063095ea7b3906044016020604051808303816000875af115801561127f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a391906129d3565b5060408181015160200151825160c084015192516387517c4560e01b81526001600160a01b03928316600482015290821660248201529116604482015265ffffffffffff421660648201526e22d473030f116ddee9f6b43ac78ba3906387517c4590608401600060405180830381600087803b15801561132257600080fd5b505af1158015611336573d6000803e3d6000fd5b5050505080602001516000036113545761134f81611975565b61135d565b61135d81611c15565b6040810151516001600160a01b0316156113fa5760408181015151905163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba36004820152600060248201526001600160a01b039091169063095ea7b3906044016020604051808303816000875af11580156113d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f891906129d3565b505b60408082015160200151905163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba36004820152600060248201526001600160a01b039091169063095ea7b3906044016020604051808303816000875af1158015611460573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148491906129d3565b5050565b60008180602001905181019061149e9190612a66565b90506000600160116040516020016114b7929190612af8565b60408051808303601f19018152600280845260608401909252925060009190816020015b60608152602001906001900390816114db5790505090508460008060008660400151604051602001611511959493929190612b46565b6040516020818303038152906040528160008151811061153357611533612b7a565b602090810291909101810191909152835184820151604080516001600160a01b03938416948101949094529116908201523060608201526080016040516020818303038152906040528160018151811061158f5761158f612b7a565b6020026020010181905250856001600160a01b031663dd46508f83836040516020016115bc929190612b90565b604051602081830303815290604052426040518363ffffffff1660e01b81526004016115e9929190612c02565b600060405180830381600087803b15801561160357600080fd5b505af1158015611617573d6000803e3d6000fd5b50505050505050505050565b80516020820151604051631efeed3360e01b815260048101919091526000916001600160a01b031690631efeed3390602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d4919061299a565b60008160e001518060200190518101906116b09190612a66565b90506000600360116040516020016116c9929190612af8565b60408051808303601f19018152600280845260608401909252925060009190816020015b60608152602001906001900390816116ed579050509050836020015160008085604001516040516020016117249493929190612c24565b6040516020818303038152906040528160008151811061174657611746612b7a565b602090810291909101810191909152835184820151604080516001600160a01b0393841694810194909452911690820152306060820152608001604051602081830303815290604052816001815181106117a2576117a2612b7a565b602002602001018190525083600001516001600160a01b031663dd46508f83836040516020016117d3929190612b90565b604051602081830303815290604052426040518363ffffffff1660e01b8152600401611800929190612c02565b600060405180830381600087803b15801561181a57600080fd5b505af115801561182e573d6000803e3d6000fd5b5050505050505050565b60008160e001518060200190518101906118529190612a66565b905060006001601160405160200161186b929190612af8565b60408051808303601f19018152600280845260608401909252925060009190816020015b606081526020019060019003908161188f57905050905083602001518460400151856060015186608001518660400151604051602001611724959493929190612c60565b600083830281600019858709828110838203039150508084116118f557600080fd5b8060000361190857508290049050610422565b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b60008161012001518060200190518101906119909190612c94565b60408051600160f91b6020820152600d60f81b6021820152600560fa1b602282015281516003818303810182526023830181815260a3840190945293945092600092916043015b60608152602001906001900390816119d7579050509050600084604001516000015190506000856040015160200151905060006040518060a00160405280846001600160a01b03168152602001836001600160a01b0316815260200188604001516040015162ffffff168152602001876000015160020b815260200187602001516001600160a01b03168152509050808760600151886080015188606001518a60a001518b60c00151308c60400151604051602001611a9d989796959493929190612d53565b60405160208183030381529060405284600081518110611abf57611abf612b7a565b60200260200101819052508282604051602001611af29291906001600160a01b0392831681529116602082015260400190565b60405160208183030381529060405284600181518110611b1457611b14612b7a565b60209081029190910181019190915260408051600092810192909252309082015260600160405160208183030381529060405284600281518110611b5a57611b5a612b7a565b602090810291909101015260006001600160a01b03841615611b7d576000611b83565b8760a001515b905087600001516001600160a01b031663dd46508f828888604051602001611bac929190612b90565b604051602081830303815290604052426040518463ffffffff1660e01b8152600401611bd9929190612c02565b6000604051808303818588803b158015611bf257600080fd5b505af1158015611c06573d6000803e3d6000fd5b50505050505050505050505050565b6000816101200151806020019051810190611c309190612c94565b6040830151805160209091015160a0850151929350909160609081906000901580611c5d575060c0870151155b90508015611e4e5760a08701511515600081611c795785611c7b565b865b9050600082611c8a5787611c8c565b865b905060006001600160a01b0383161560405160006020820152600b60f81b6021820152600960f91b6022820152600560fa1b60238201529015915060240160408051808303601f19018152600480845260a084019092529850816020015b6060815260200190600190039081611cea5790505095508a602001518a606001518c60a001518d60c001518d60400151604051602001611d2e959493929190612c60565b60405160208183030381529060405286600081518110611d5057611d50612b7a565b602090810291909101810191909152604080516001600160a01b03861692810192909252600090820152811515606082015260800160405160208183030381529060405286600181518110611da757611da7612b7a565b602002602001018190525081604051602001611dd291906001600160a01b0391909116815260200190565b60405160208183030381529060405286600281518110611df457611df4612b7a565b60209081029190910181019190915260408051600092810192909252309082015260600160405160208183030381529060405286600381518110611e3a57611e3a612b7a565b602002602001018190525050505050611f9c565b60405160006020820152600d60f81b6021820152600560fa1b602282015260230160408051808303601f190181526003808452608084019092529450816020015b6060815260200190600190039081611e8f579050509150866020015186606001518860a001518960c001518960400151604051602001611ed3959493929190612c60565b60405160208183030381529060405282600081518110611ef557611ef5612b7a565b60200260200101819052508484604051602001611f289291906001600160a01b0392831681529116602082015260400190565b60405160208183030381529060405282600181518110611f4a57611f4a612b7a565b60209081029190910181019190915260408051600092810192909252309082015260600160405160208183030381529060405282600281518110611f9057611f90612b7a565b60200260200101819052505b60006001600160a01b03861615611fb4576000611fba565b8760a001515b905087600001516001600160a01b031663dd46508f828686604051602001611bac929190612b90565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561201b5761201b611fe3565b60405290565b60405161014081016001600160401b038111828210171561201b5761201b611fe3565b60405161010081016001600160401b038111828210171561201b5761201b611fe3565b604051601f8201601f191681016001600160401b038111828210171561208f5761208f611fe3565b604052919050565b6001600160a01b03811681146120ac57600080fd5b50565b80356120ba81612097565b919050565b62ffffff811681146120ac57600080fd5b6000606082840312156120e257600080fd5b6120ea611ff9565b905081356120f781612097565b8152602082013561210781612097565b6020820152604082013561211a816120bf565b604082015292915050565b8060020b81146120ac57600080fd5b80356120ba81612125565b60006001600160401b0382111561215857612158611fe3565b50601f01601f191660200190565b600082601f83011261217757600080fd5b813561218a6121858261213f565b612067565b81815284602083860101111561219f57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156121ce57600080fd5b81356001600160401b03808211156121e557600080fd5b9083019061018082860312156121fa57600080fd5b612202612021565b61220b836120af565b81526020830135602082015261222486604085016120d0565b604082015261223560a08401612134565b606082015261224660c08401612134565b608082015260e083013560a08201526101008084013560c08301526101208085013560e08401526101408501358284015261016085013591508382111561228c57600080fd5b61229888838701612166565b908301525095945050505050565b6000608082840312156122b857600080fd5b50919050565b60008060a083850312156122d157600080fd5b82356122dc81612097565b91506122eb84602085016122a6565b90509250929050565b60008083601f84011261230657600080fd5b5081356001600160401b0381111561231d57600080fd5b60208301915083602082850101111561233557600080fd5b9250929050565b600080600060a0848603121561235157600080fd5b61235b85856122a6565b925060808401356001600160401b0381111561237657600080fd5b612382868287016122f4565b9497909650939450505050565b600082601f8301126123a057600080fd5b813560206001600160401b038211156123bb576123bb611fe3565b8160051b6123ca828201612067565b92835284810182019282810190878511156123e457600080fd5b83870192505b8483101561240c5782356123fd81612097565b825291830191908301906123ea565b979650505050505050565b600080600060c0848603121561242c57600080fd5b833561243781612097565b925061244685602086016122a6565b915060a08401356001600160401b0381111561246157600080fd5b610dab8682870161238f565b6020808252825182820181905260009190848201906040850190845b818110156124a557835183529284019291840191600101612489565b50909695505050505050565b6001600160801b03811681146120ac57600080fd5b80356120ba816124b1565b60008060008060008061010087890312156124eb57600080fd5b6124f588886122a6565b955060808701356001600160401b038082111561251157600080fd5b61251d8a838b0161238f565b965060a0890135915061252f826124b1565b90945060c088013590612541826124b1565b90935060e0880135908082111561255757600080fd5b5061256489828a016122f4565b979a9699509497509295939492505050565b6000806040838503121561258957600080fd5b823561259481612097565b946020939093013593505050565b600080604083850312156125b557600080fd5b82356125c081612097565b915060208301356125d081612097565b809150509250929050565b6000602082840312156125ed57600080fd5b81356001600160401b038082111561260457600080fd5b90830190610100828603121561261957600080fd5b612621612044565b61262a836120af565b815260208301356020820152612642604084016124c6565b6040820152606083013560608201526080830135608082015261266760a084016124c6565b60a082015261267860c084016124c6565b60c082015260e08301358281111561268f57600080fd5b61269b87828601612166565b60e08301525095945050505050565b6000806000606084860312156126bf57600080fd5b83356126ca81612097565b925060208401356126da81612097565b929592945050506040919091013590565b6000602082840312156126fd57600080fd5b813561042281612097565b81516001600160a01b039081168252602080840151909116908201526040808301516101208301916127409084018262ffffff169052565b506060830151612757606084018262ffffff169052565b50608083015161277260808401826001600160a01b03169052565b5060a083015161278760a084018260020b9052565b5060c08301516127a260c08401826001600160801b03169052565b5060e083015160e083015261010080840151818401525092915050565b600060a082840312156127d157600080fd5b60405160a081018181106001600160401b03821117156127f3576127f3611fe3565b8060405250809150825161280681612097565b8152602083015161281681612097565b60208201526040830151612829816120bf565b6040820152606083015161283c81612125565b6060820152608083015161284f81612097565b6080919091015292915050565b60008060c0838503121561286f57600080fd5b61287984846127bf565b915060a083015190509250929050565b6000806000806080858703121561289f57600080fd5b84516128aa81612097565b60208601519094506128bb81612125565b60408601519093506128cc816120bf565b60608601519092506128dd816120bf565b939692955090935050565b6000602082840312156128fa57600080fd5b5051919050565b818103818111156103d457634e487b7160e01b600052601160045260246000fd5b60006020828403121561293457600080fd5b815161042281612097565b6000806040838503121561295257600080fd5b505080516020909101519092909150565b60008060006060848603121561297857600080fd5b8351612983816124b1565b602085015160409095015190969495509392505050565b6000602082840312156129ac57600080fd5b8151610422816124b1565b600060a082840312156129c957600080fd5b61042283836127bf565b6000602082840312156129e557600080fd5b8151801515811461042257600080fd5b60005b83811015612a105781810151838201526020016129f8565b50506000910152565b600082601f830112612a2a57600080fd5b8151612a386121858261213f565b818152846020838601011115612a4d57600080fd5b612a5e8260208301602087016129f5565b949350505050565b600060208284031215612a7857600080fd5b81516001600160401b0380821115612a8f57600080fd5b9083019060608286031215612aa357600080fd5b612aab611ff9565b8251612ab681612097565b81526020830151612ac681612097565b6020820152604083015182811115612add57600080fd5b612ae987828601612a19565b60408301525095945050505050565b6001600160f81b031960f893841b811682529190921b16600182015260020190565b60008151808452612b328160208601602086016129f5565b601f01601f19169290920160200192915050565b85815260ff8516602082015260ff8416604082015260ff8316606082015260a06080820152600061240c60a0830184612b1a565b634e487b7160e01b600052603260045260246000fd5b604081526000612ba36040830185612b1a565b6020838203818501528185518084528284019150828160051b85010183880160005b83811015612bf357601f19878403018552612be1838351612b1a565b94860194925090850190600101612bc5565b50909998505050505050505050565b604081526000612c156040830185612b1a565b90508260208301529392505050565b84815260006001600160801b03808616602084015280851660408401525060806060830152612c566080830184612b1a565b9695505050505050565b8581526001600160801b038516602082015283604082015282606082015260a06080820152600061240c60a0830184612b1a565b600060208284031215612ca657600080fd5b81516001600160401b0380821115612cbd57600080fd5b9083019060808286031215612cd157600080fd5b604051608081018181108382111715612cec57612cec611fe3565b6040528251612cfa816120bf565b81526020830151612d0a81612097565b6020820152604083015182811115612d2157600080fd5b612d2d87828601612a19565b60408301525060608301519250612d43836124b1565b6060810192909252509392505050565b600061018060018060a01b03808c511684528060208d015116602085015262ffffff60408d015116604085015260608c015160020b60608501528060808d015116608085015250612da960a084018b60020b9052565b612db860c084018a60020b9052565b6001600160801b03881660e08401528661010084015285610120840152612deb6101408401866001600160a01b03169052565b80610160840152612dfe81840185612b1a565b9b9a505050505050505050505056fea2646970667358221220d4bd8fa33bacc9f60fe1ed7f7a2c339200d188496895f1519243e65cc6b5792864736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f401600000000000000000000000077395f3b2e73ae90843717371294fa97cc419d64
-----Decoded View---------------
Arg [0] : positionManager_ (address): 0x5b7eC4a94fF9beDb700fb82aB09d5846972F4016
Arg [1] : stateView_ (address): 0x77395F3b2E73aE90843717371294fa97cC419D64
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005b7ec4a94ff9bedb700fb82ab09d5846972f4016
Arg [1] : 00000000000000000000000077395f3b2e73ae90843717371294fa97cc419d64
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MON
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.