Base
Smart contract base utilities and implementations
import "@openzeppelin/src/base/BaseAsyncSwap.sol";
Base implementation for async swaps, which skip the v3-like swap implementation of the PoolManager
by taking the full swap input amount and returning a delta that nets out the specified amount to 0.
This base hook allows developers to implement arbitrary logic to handle swaps, including use-cases like
asynchronous swaps and custom swap-ordering. However, given this flexibility, developers should ensure
that any logic implemented interacts safely with the PoolManager
and works correctly.
In order to handle async swaps, the hook mints ERC-6909 claim tokens for the specified currency and amount.
Inheriting contracts are free to handle these claim tokens as necessary, which can be redeemed for the
underlying currency by using the settle
function from the CurrencySettler
library.
If the hook is used for multiple pools, the ERC-6909 tokens must be separated and managed
independently for each pool in order to prevent draining of ERC-6909 tokens from one pool to another.
NOTE: The hook only supports async exact-input swaps. Exact-output swaps will be processed normally
by the PoolManager
.
This is experimental software and is provided on an "as is" and "as available" basis. We do
not give any warranties and will not be liable for any losses incurred through any use of this code base.
Available since v0.1.0
Functions
- constructor(_poolManager)
- _beforeSwap(sender, key, params, )
- _calculateSwapFee(key, specifiedAmount)
- getHookPermissions()
IHookEvents
BaseHook
- _validateHookAddress(hook)
- beforeInitialize(sender, key, sqrtPriceX96)
- _beforeInitialize(, , )
- afterInitialize(sender, key, sqrtPriceX96, tick)
- _afterInitialize(, , , )
- beforeAddLiquidity(sender, key, params, hookData)
- _beforeAddLiquidity(, , , )
- beforeRemoveLiquidity(sender, key, params, hookData)
- _beforeRemoveLiquidity(, , , )
- afterAddLiquidity(sender, key, params, delta0, delta1, hookData)
- _afterAddLiquidity(, , , , , )
- afterRemoveLiquidity(sender, key, params, delta0, delta1, hookData)
- _afterRemoveLiquidity(, , , , , )
- beforeSwap(sender, key, params, hookData)
- afterSwap(sender, key, params, delta, hookData)
- _afterSwap(, , , , )
- beforeDonate(sender, key, amount0, amount1, hookData)
- _beforeDonate(, , , , )
- afterDonate(sender, key, amount0, amount1, hookData)
- _afterDonate(, , , , )
- poolManager()
IHooks
Events
constructor(contract IPoolManager _poolManager)
internal
#Set the PoolManager
address.
_beforeSwap(address sender, struct PoolKey key, struct SwapParams params, bytes) → bytes4, BeforeSwapDelta, uint24
internal
#Skip the v3-like swap implementation of the PoolManager
by returning a delta that nets out the
specified amount to 0 to enable asynchronous swaps.
_calculateSwapFee(struct PoolKey key, uint256 specifiedAmount) → uint256 feeAmount
internal
#Calculate the fee amount for the swap.
getHookPermissions() → struct Hooks.Permissions permissions
public
#Set the hook permissions, specifically beforeSwap
and beforeSwapReturnDelta
.
import "@openzeppelin/src/base/BaseCustomAccounting.sol";
Base implementation for custom accounting and hook-owned liquidity.
To enable hook-owned liquidity, tokens must be deposited via the hook to allow control and flexibility over the liquidity. The implementation inheriting this hook must implement the respective functions to calculate the liquidity modification parameters and the amount of liquidity shares to mint or burn.
Additionally, the implementer must consider that the hook is the sole owner of the liquidity and manage fees over liquidity shares accordingly.
NOTE: This base hook is designed to work with a single pool key. If you want to use the same custom
accounting hook for multiple pools, you must have multiple storage instances of this contract and
initialize them via the PoolManager
with their respective pool keys.
This is experimental software and is provided on an "as is" and "as available" basis. We do
not give any warranties and will not be liable for any losses incurred through any use of this code base.
Available since v0.1.0
Modifiers
Functions
- constructor(_poolManager)
- poolKey()
- addLiquidity(params)
- removeLiquidity(params)
- _modifyLiquidity(params)
- unlockCallback(rawData)
- _handleAccruedFees(data, callerDelta, feesAccrued)
- _beforeInitialize(, key, )
- _beforeAddLiquidity(, , , )
- _beforeRemoveLiquidity(, , , )
- _getAddLiquidity(sqrtPriceX96, params)
- _getRemoveLiquidity(params)
- _mint(params, callerDelta, feesAccrued, shares)
- _burn(params, callerDelta, feesAccrued, shares)
- getHookPermissions()
IUnlockCallback
IHookEvents
BaseHook
- _validateHookAddress(hook)
- beforeInitialize(sender, key, sqrtPriceX96)
- afterInitialize(sender, key, sqrtPriceX96, tick)
- _afterInitialize(, , , )
- beforeAddLiquidity(sender, key, params, hookData)
- beforeRemoveLiquidity(sender, key, params, hookData)
- afterAddLiquidity(sender, key, params, delta0, delta1, hookData)
- _afterAddLiquidity(, , , , , )
- afterRemoveLiquidity(sender, key, params, delta0, delta1, hookData)
- _afterRemoveLiquidity(, , , , , )
- beforeSwap(sender, key, params, hookData)
- _beforeSwap(, , , )
- afterSwap(sender, key, params, delta, hookData)
- _afterSwap(, , , , )
- beforeDonate(sender, key, amount0, amount1, hookData)
- _beforeDonate(, , , , )
- afterDonate(sender, key, amount0, amount1, hookData)
- _afterDonate(, , , , )
- poolManager()
IHooks
Events
Errors
ensure(uint256 deadline)
internal
#Ensure the deadline of a liquidity modification request is not expired.
constructor(contract IPoolManager _poolManager)
internal
#Set the pool PoolManager
address.
poolKey() → struct PoolKey
public
#addLiquidity(struct BaseCustomAccounting.AddLiquidityParams params) → BalanceDelta delta
public
#To cover all possible scenarios, msg.sender
should have already given the hook an allowance
of at least amount0Desired/amount1Desired on token0/token1. Always adds assets at the ideal ratio,
according to the price when the transaction is executed.
NOTE: The amount0Min
and amount1Min
parameters are relative to the principal delta, which excludes
fees accrued from the liquidity modification delta.
removeLiquidity(struct BaseCustomAccounting.RemoveLiquidityParams params) → BalanceDelta delta
public
#_modifyLiquidity(bytes params) → BalanceDelta callerDelta, BalanceDelta feesAccrued
internal
#Calls the PoolManager
to unlock and call back the hook's unlockCallback
function.
unlockCallback(bytes rawData) → bytes returnData
public
#Callback from the PoolManager
when liquidity is modified, either adding or removing.
_handleAccruedFees(struct BaseCustomAccounting.CallbackData data, BalanceDelta callerDelta, BalanceDelta feesAccrued)
internal
#Handle any fees accrued in a liquidity position. By default, this function transfers the tokens to the owner of the liquidity position. However, this function can be overridden to take fees accrued in the position, or any other desired logic.
_beforeInitialize(address, struct PoolKey key, uint160) → bytes4
internal
#Initialize the hook's pool key. The stored key should act immutably so that it can safely be used across the hook's functions.
_beforeAddLiquidity(address, struct PoolKey, struct ModifyLiquidityParams, bytes) → bytes4
internal
#Revert when liquidity is attempted to be added via the PoolManager
.
_beforeRemoveLiquidity(address, struct PoolKey, struct ModifyLiquidityParams, bytes) → bytes4
internal
#Revert when liquidity is attempted to be removed via the PoolManager
.
_getAddLiquidity(uint160 sqrtPriceX96, struct BaseCustomAccounting.AddLiquidityParams params) → bytes modify, uint256 shares
internal
#Get the liquidity modification to apply for a given liquidity addition, and the amount of liquidity shares would be minted to the sender.
_getRemoveLiquidity(struct BaseCustomAccounting.RemoveLiquidityParams params) → bytes modify, uint256 shares
internal
#Get the liquidity modification to apply for a given liquidity removal, and the amount of liquidity shares would be burned from the sender.
_mint(struct BaseCustomAccounting.AddLiquidityParams params, BalanceDelta callerDelta, BalanceDelta feesAccrued, uint256 shares)
internal
#Mint liquidity shares to the sender.
_burn(struct BaseCustomAccounting.RemoveLiquidityParams params, BalanceDelta callerDelta, BalanceDelta feesAccrued, uint256 shares)
internal
#Burn liquidity shares from the sender.
getHookPermissions() → struct Hooks.Permissions permissions
public
#Set the hook permissions, specifically beforeInitialize
, beforeAddLiquidity
and beforeRemoveLiquidity
.
ExpiredPastDeadline()
error
#A liquidity modification order was attempted to be executed after the deadline.
PoolNotInitialized()
error
#Pool was not initialized.
TooMuchSlippage()
error
#Principal delta of liquidity modification resulted in too much slippage.
LiquidityOnlyViaHook()
error
#Liquidity was attempted to be added or removed via the PoolManager
instead of the hook.
InvalidNativeValue()
error
#Native currency was not sent with the correct amount.
AlreadyInitialized()
error
#Hook was already initialized.
import "@openzeppelin/src/base/BaseCustomCurve.sol";
Base implementation for custom curves, inheriting from BaseCustomAccounting
.
This hook allows to implement a custom curve (or any logic) for swaps, which overrides the default v3-like
concentrated liquidity implementation of the PoolManager
. During a swap, the hook calls the
BaseCustomCurve._getUnspecifiedAmount
function to get the amount of tokens to be sent to the receiver. The return delta
created from this calculation is then consumed and applied by the PoolManager
.
NOTE: This hook by default does not include fee or salt mechanisms, which can be implemented by inheriting contracts if needed.
This is experimental software and is provided on an "as is" and "as available" basis. We do
not give any warranties and will not be liable for any losses incurred through any use of this code base.
Available since v0.1.0
Functions
- constructor(_poolManager)
- _getAddLiquidity(, params)
- _getRemoveLiquidity(params)
- _beforeSwap(sender, key, params, )
- _modifyLiquidity(params)
- unlockCallback(rawData)
- _getUnspecifiedAmount(params)
- _getSwapFeeAmount(params, unspecifiedAmount)
- _getAmountOut(params)
- _getAmountIn(params)
- getHookPermissions()
BaseCustomAccounting
- poolKey()
- addLiquidity(params)
- removeLiquidity(params)
- _handleAccruedFees(data, callerDelta, feesAccrued)
- _beforeInitialize(, key, )
- _beforeAddLiquidity(, , , )
- _beforeRemoveLiquidity(, , , )
- _mint(params, callerDelta, feesAccrued, shares)
- _burn(params, callerDelta, feesAccrued, shares)
IUnlockCallback
IHookEvents
BaseHook
- _validateHookAddress(hook)
- beforeInitialize(sender, key, sqrtPriceX96)
- afterInitialize(sender, key, sqrtPriceX96, tick)
- _afterInitialize(, , , )
- beforeAddLiquidity(sender, key, params, hookData)
- beforeRemoveLiquidity(sender, key, params, hookData)
- afterAddLiquidity(sender, key, params, delta0, delta1, hookData)
- _afterAddLiquidity(, , , , , )
- afterRemoveLiquidity(sender, key, params, delta0, delta1, hookData)
- _afterRemoveLiquidity(, , , , , )
- beforeSwap(sender, key, params, hookData)
- afterSwap(sender, key, params, delta, hookData)
- _afterSwap(, , , , )
- beforeDonate(sender, key, amount0, amount1, hookData)
- _beforeDonate(, , , , )
- afterDonate(sender, key, amount0, amount1, hookData)
- _afterDonate(, , , , )
- poolManager()
IHooks
Events
Errors
constructor(contract IPoolManager _poolManager)
internal
#Set the pool PoolManager
address.
_getAddLiquidity(uint160, struct BaseCustomAccounting.AddLiquidityParams params) → bytes, uint256
internal
#Defines how the liquidity modification data is encoded and returned for an add liquidity request.
_getRemoveLiquidity(struct BaseCustomAccounting.RemoveLiquidityParams params) → bytes, uint256
internal
#Defines how the liquidity modification data is encoded and returned for a remove liquidity request.
_beforeSwap(address sender, struct PoolKey key, struct SwapParams params, bytes) → bytes4, BeforeSwapDelta, uint24
internal
#Overrides the default swap logic of the PoolManager
and calls the BaseCustomCurve._getUnspecifiedAmount
to get the amount of tokens to be sent to the receiver.
NOTE: In order to take and settle tokens from the pool, the hook must hold the liquidity added
via the BaseCustomAccounting.addLiquidity
function.
_modifyLiquidity(bytes params) → BalanceDelta callerDelta, BalanceDelta feesAccrued
internal
#Overrides the custom accounting logic to support the custom curve integer amounts.
unlockCallback(bytes rawData) → bytes returnData
public
#Decodes the callback data and applies the liquidity modifications, overriding the custom accounting logic to mint and burn ERC-6909 claim tokens which are used in swaps.
_getUnspecifiedAmount(struct SwapParams params) → uint256 unspecifiedAmount
internal
#Calculate the amount of the unspecified currency to be taken or settled from the swapper, depending on the swap direction and the fee amount to be paid to LPs.
_getSwapFeeAmount(struct SwapParams params, uint256 unspecifiedAmount) → uint256 swapFeeAmount
internal
#Calculate the amount of fees to be paid to LPs in a swap.
_getAmountOut(struct BaseCustomAccounting.RemoveLiquidityParams params) → uint256 amount0, uint256 amount1, uint256 shares
internal
#Calculate the amount of tokens to use and liquidity shares to burn for a remove liquidity request.
_getAmountIn(struct BaseCustomAccounting.AddLiquidityParams params) → uint256 amount0, uint256 amount1, uint256 shares
internal
#Calculate the amount of tokens to use and liquidity shares to mint for an add liquidity request.
getHookPermissions() → struct Hooks.Permissions permissions
public
#Set the hook permissions, specifically beforeInitialize
, beforeAddLiquidity
, beforeRemoveLiquidity
,
beforeSwap
, and beforeSwapReturnDelta
import "@openzeppelin/src/base/BaseHook.sol";
Base hook implementation.
This contract defines all hook entry points, as well as security and permission helpers. Based on the Uniswap v4 periphery implementation.
NOTE: Hook entry points must be overridden and implemented by the inheriting hook to be used. Their respective
flags must be set to true in the getHookPermissions
function as well.
This is experimental software and is provided on an "as is" and "as available" basis. We do
not give any warranties and will not be liable for any losses incurred through any use of this code base.
Available since v0.1.0
Modifiers
Functions
- constructor(_poolManager)
- getHookPermissions()
- _validateHookAddress(hook)
- beforeInitialize(sender, key, sqrtPriceX96)
- _beforeInitialize(, , )
- afterInitialize(sender, key, sqrtPriceX96, tick)
- _afterInitialize(, , , )
- beforeAddLiquidity(sender, key, params, hookData)
- _beforeAddLiquidity(, , , )
- beforeRemoveLiquidity(sender, key, params, hookData)
- _beforeRemoveLiquidity(, , , )
- afterAddLiquidity(sender, key, params, delta0, delta1, hookData)
- _afterAddLiquidity(, , , , , )
- afterRemoveLiquidity(sender, key, params, delta0, delta1, hookData)
- _afterRemoveLiquidity(, , , , , )
- beforeSwap(sender, key, params, hookData)
- _beforeSwap(, , , )
- afterSwap(sender, key, params, delta, hookData)
- _afterSwap(, , , , )
- beforeDonate(sender, key, amount0, amount1, hookData)
- _beforeDonate(, , , , )
- afterDonate(sender, key, amount0, amount1, hookData)
- _afterDonate(, , , , )
- poolManager()
IHooks
onlyPoolManager()
internal
#onlySelf()
internal
#Restrict the function to only be callable by the hook itself.
onlyValidPools(contract IHooks hooks)
internal
#Restrict the function to only be called for a valid pool.
constructor(contract IPoolManager _poolManager)
internal
#Set the pool manager and check that the hook address matches the expected permissions and flags.
getHookPermissions() → struct Hooks.Permissions permissions
public
#Get the hook permissions to signal which hook functions are to be implemented.
Used at deployment to validate the address correctly represents the expected permissions.
_validateHookAddress(contract BaseHook hook)
internal
#Validate the hook address against the expected permissions.
beforeInitialize(address sender, struct PoolKey key, uint160 sqrtPriceX96) → bytes4
external
#_beforeInitialize(address, struct PoolKey, uint160) → bytes4
internal
#Hook implementation for beforeInitialize
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
afterInitialize(address sender, struct PoolKey key, uint160 sqrtPriceX96, int24 tick) → bytes4
external
#_afterInitialize(address, struct PoolKey, uint160, int24) → bytes4
internal
#Hook implementation for afterInitialize
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
beforeAddLiquidity(address sender, struct PoolKey key, struct ModifyLiquidityParams params, bytes hookData) → bytes4
external
#_beforeAddLiquidity(address, struct PoolKey, struct ModifyLiquidityParams, bytes) → bytes4
internal
#Hook implementation for beforeAddLiquidity
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
beforeRemoveLiquidity(address sender, struct PoolKey key, struct ModifyLiquidityParams params, bytes hookData) → bytes4
external
#_beforeRemoveLiquidity(address, struct PoolKey, struct ModifyLiquidityParams, bytes) → bytes4
internal
#Hook implementation for beforeRemoveLiquidity
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
afterAddLiquidity(address sender, struct PoolKey key, struct ModifyLiquidityParams params, BalanceDelta delta0, BalanceDelta delta1, bytes hookData) → bytes4, BalanceDelta
external
#_afterAddLiquidity(address, struct PoolKey, struct ModifyLiquidityParams, BalanceDelta, BalanceDelta, bytes) → bytes4, BalanceDelta
internal
#Hook implementation for afterAddLiquidity
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
afterRemoveLiquidity(address sender, struct PoolKey key, struct ModifyLiquidityParams params, BalanceDelta delta0, BalanceDelta delta1, bytes hookData) → bytes4, BalanceDelta
external
#_afterRemoveLiquidity(address, struct PoolKey, struct ModifyLiquidityParams, BalanceDelta, BalanceDelta, bytes) → bytes4, BalanceDelta
internal
#Hook implementation for afterRemoveLiquidity
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
beforeSwap(address sender, struct PoolKey key, struct SwapParams params, bytes hookData) → bytes4, BeforeSwapDelta, uint24
external
#_beforeSwap(address, struct PoolKey, struct SwapParams, bytes) → bytes4, BeforeSwapDelta, uint24
internal
#Hook implementation for beforeSwap
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
afterSwap(address sender, struct PoolKey key, struct SwapParams params, BalanceDelta delta, bytes hookData) → bytes4, int128
external
#_afterSwap(address, struct PoolKey, struct SwapParams, BalanceDelta, bytes) → bytes4, int128
internal
#Hook implementation for afterSwap
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
beforeDonate(address sender, struct PoolKey key, uint256 amount0, uint256 amount1, bytes hookData) → bytes4
external
#_beforeDonate(address, struct PoolKey, uint256, uint256, bytes) → bytes4
internal
#Hook implementation for beforeDonate
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
afterDonate(address sender, struct PoolKey key, uint256 amount0, uint256 amount1, bytes hookData) → bytes4
external
#_afterDonate(address, struct PoolKey, uint256, uint256, bytes) → bytes4
internal
#Hook implementation for afterDonate
, to be overridden by the inheriting hook. The
flag must be set to true in the getHookPermissions
function.
poolManager() → contract IPoolManager
public
#NotSelf()
error
#The hook is not the caller.
InvalidPool()
error
#The pool is not authorized to use this hook.
HookNotImplemented()
error
#The hook function is not implemented.
NotPoolManager()
error
#