Introduction
to UniSwap v4 Hooks. Creating your first UniSwap v4 hook deep dive--Veee
This is a deep dive into creating a UniSwap v4 Hook, focusing on
building a simple on-chain points program.
The main objective is to incentivize users to purchase a new token
(e.g., "Meme") with ETH and add liquidity to the ETH/Meme pool.
Incentive Mechanism: The program issues a new ERC-20 token, called
"Point," as a reward.
Scoring Rules (Simple Example):
When swapping ETH for Meme, the user receives Points equivalent to 20%
of the ETH spent.
When adding liquidity, the user receives Points equivalent to 100% of
the ETH added. Technical Implementation (UniSwap v4 Hooks):
The developer must inherit the BaseHook base contract and configure the
Foundry environment (Solidity >= 0.8.25 and EVM Cancun).
It is essential to define the Hook's permissions, indicating which
functions it will implement.
Critical Function Choice:
The Hook must use the afterSwap and afterAddLiquidity functions.
Using "before" functions (before execution) is impossible, as the exact
amount of ETH spent by the user is only known after the core
Swap/Liquidity logic is executed (due to slippage limits or partial
filling).
User Identification:
The sender address received by the Hook is the Swap router (e.g.,
Universal Router), not the user's final address (Alice).
To resolve this, the end user must include their wallet address in the
hookData (arbitrary info) parameter, which the Hook decodes to know who
to mint the Points for. Value Calculation: The balanceDelta parameter
is used to determine the amount of tokens transferred. Negative values
indicate tokens that left the user's wallet (payment), and positive
values indicate tokens received.
Security Checks: The code includes checks to ensure that the pool
contains the native token (ETH as token0) and that points are issued
only when the user is buying the Meme token (and not selling it for
ETH).
Needed Improvements (Not for Production):
Prevent Multi-Pool Farming: It is crucial to use a different ERC-20 (or
ERC-1155/6909) for each pool so that an attacker cannot create a fake
token and farm infinite points.
Prevent Liquidity Add/Remove Attacks: A time lock should be implemented
to reward LPs (Liquidity Providers) proportionally to the time they
held liquidity in the pool, preventing them from earning points by
repeatedly removing and adding liquidity instantly.
Certainly, here is the English
translation of the summary about the Sign Protocol workshop:
The ETHOnline 2024 workshop, presented by Jack and Jordan from Sign
Protocol, focused on "Supercharging Attestations with Schema
Hooks." The main goal was to introduce the concept of Schema Hooks
and demonstrate how developers can use them to add custom validation
logic and access control to their attestations on the protocol,
encouraging participation in the hackathon.
Sign Protocol is introduced as a solution for "everything to be
signed on-chain." The essential workflow on the protocol consists of
three steps: first, the creation of a schema to define the data
structure format that will be attested; second, the making of the
attestation itself, which can be managed by a controlled backend (for
example, to pay gas fees) or done directly by the users; and third, the
consumption of the attested data through queries or direct
interactions with the protocol's smart contract.
Architecturally, the Sign Protocol Registry is composed of the main
smart contract (responsible for storing schemas, attestations, and hook
references) and a decentralized storage component for off-chain
attestations, such as those made on Arweave. The central focus of
the workshop, however, was the on-chain logic of the hooks on the EVM.
The Schema Hook itself is an external smart contract that is
invoked by the main Sign Protocol contract whenever there is an attempt
at attestation or revocation for a schema that defines it. This
mechanism grants the schema creator significant control over the
process, allowing the hook to act as a verifier (validation), a
processor (payments), or a notifier (interaction with other
contracts). If the hook contract reverts the transaction due to a
failure in its validation logic, the attestation is not recorded on the
blockchain, providing a powerful way to enforce business rules.
As a practical example, a simple "Whitelist Hook"was demonstrated.
This hook implements the necessary interface (`didReceiveAttestation`)
and connects to a separate contract, the `WhitelistManager, which
contains the logic for managing and verifying whether the attester's
address is authorized. The owner of the `WhitelistManager` can add or
remove addresses from the list, and the hook function simply calls this
verification, reverting the transaction if the attester's address is
not on the whitelist.
To activate the functionality, the deployed hook smart contract address
is provided during schema creation, either through the Sign Protocol
web interface or programmatically via the SDK. From that moment on, the
custom logic defined in the hook becomes a mandatory prerequisite for
any attestation under that schema.
The presenters also encouraged more ambitious ideas, such as using
Schema Hooks as ZK Verifier contracts for zero-knowledge proofs.
This application would pave the way for creating ZK-based private
attestations, where the cryptographic proof of compliance with a data
criterion is reliably recorded and verified on-chain without exposing
the underlying data.
The Sign Protocol is present on several EVM chains and stands out for
its native support for Arweave, which is ideal for storing large,
permanent, and public data that does not require smart contract
validation. They reaffirmed the open and non-curated nature of the
schemas on the platform and provided resources such as official
documentation and support channels (Discord and Telegram) to assist
developers during the hackathon.
Certainly, here is the English
translation of the podcast summary about Uniswap V4 Hooks and the Cork
Protocol exploit:
The podcast discussed Uniswap V4 Hooks from a security perspective,
focusing on how this revolutionary new feature in DeFi also introduces
significant risks. V4 Hooks allow pool creators to add custom
logic—such as dynamic fees, whitelisting, blacklisting, or custom swap
functionality—directly to the pools, which now reside within a single
contract called the Pool Manager (singleton contract). This capability
opens up a vast range of possibilities but comes with great
responsibility.
The central case study was the $12 million Cork Protocol exploit, an
insurance protocol that integrated V4 pools and placed critical
infrastructure code—specifically the logic for minting tokens—inside
its hook contract. The vulnerability arose in the Cork hook's
beforeSwap function, which was missing a crucial modifier check.
Hook contracts are generally only supposed to be called by the Pool
Manager. The lack of an msg.sender check in the beforeSwap function
allowed an attacker to call the hook contract directly, bypassing
interaction with the pool (e.g., without depositing tokens).
The exploit was facilitated by the use of hookData, which is
user-supplied data. By calling the function directly, the attacker was
able to craft a custom hookData value and execute arbitrary logic to
mint tokens for free. This case demonstrated the critical importance of:
Verifying msg.sender: Ensuring that only the Pool Manager can call the
hook functions.
Not Trusting User Input: Treating hookData securely, decoding it, and
understanding the risks of malicious manipulation.
Lessons and Security Checklist for Developers
To implement Uniswap V4 Hooks securely, the top security priorities are:
Immutability and Permissions: The hook is immutable after the pool's
deployment. Ensure the hook address has all the correct permissions
(both current and future) that the Uniswap V4 interface expects.
Delta Management: This is a critical V4 concept. The hook can return an
arbitrary delta value that affects the pool's internal accounting
state. Non-zero delta returns can "brick" the pool if they are not
resolved by the end of the transaction. Auditing the logic that
calculates the delta is essential.
External Interactions: If the hook interacts with external contracts
(like oracles or other protocols), there are added risks of reentrancy
or cascading failures (reverts). These interactions add complexity and
must be carefully audited.
Audit Scope Completeness: The fact that Cork passed multiple audits
without the flaw being noticed suggests that the hook code, being a new
piece of critical infrastructure, may not have been fully included or
focused on in all audit scopes.
The future of DeFi will continue to explore composability through
hooks, despite the security risks. The increased complexity
necessitates improved security tools. A live demonstration used the
Glider tool to identify the Cork vulnerability by tracing hook
functions that lacked authentication modifiers, showing how static code
analysis can mitigate such risks.
uniswapv4 Auto Rebalancing
Hook
The
video introduces the Auto Rebalancing Hook for Uniswap V4, a project
designed to create smarter and more efficient liquidity pools that
automatically adapt to market conditions. The main goal is to solve
challenges faced by Liquidity Providers (LPs), such as capital
inefficiency and impermanent loss.
The auto-rebalancing hook has three core capabilities: real-time market
monitoring, automatic liquidity rebalancing, and dynamic rate
adjustment.
Market monitoring is implemented through the updateMarket function,
which tracks metrics such as price volatility, trading volume, and
liquidity depth whenever market activity occurs. The current tick price
is retrieved from the pool, and trading volume is tracked over a
sliding time window. Price volatility is crucial and is calculated
using an Exponential Moving Average (EMA), which weights both
historical and the most recent absolute price change (in ticks).
The liquidity rebalancing engine determines the optimal price range
width based on market conditions. The calculateRangeWidth function uses
volatility and liquidity depth to return the range width in ticks. In
high volatility or low liquidity situations, the hook sets a maximum
range width (60 ticks) as a defensive strategy to protect LPs.
Conversely, in low volatility scenarios (below 200), it sets a narrow
range (5 ticks) to maximize capital efficiency. The final calculation
adjusts the range boundaries (lower and upper ticks) to ensure they
align with the pool's tick spacing.
Dynamic fee adjustment adapts pool fees based on multiple factors to
optimize LP returns. If volatility is too high, the hook returns a
maximum fee (1%) to protect LPs against impermanent loss. In scenarios
of high trading volume combined with low liquidity, fees are adjusted
upward (base fee + 0.2%) to capture more value. In cases of restricted
liquidity (below 200), there is a slight increase in the fee (base fee
+ 0.05%). If no extreme conditions are met, the hook returns the base
fee of 0.3%.
These functions work together to create a self-adjusting liquidity
pool, optimizing capital efficiency and returns for liquidity providers
by incentivizing the provision of small amounts of liquidity. The
developer concluded the presentation by demonstrating that testing for
all functionalities (dynamic fee adjustment, rebalancing, monitoring,
and end-to-end workflow) was running successfully.
The
video, presented by Luis from OpenZeppelin, focuses on security when
building Uniswap V4 Hooks using the OpenZeppelin library. Hooks are
smart contracts that add custom logic at critical points in a swap or
liquidity addition/removal process in Uniswap V4. Due to their position
in the critical path of each transaction, they interact with user
assets and the Pool Manager, making security crucial to prevent asset
drains or trading freezes.
The speaker listed five points developers should consider when creating
hooks:
Pool Count: By default, a hook can be used by multiple pools. If the
hook holds assets or tracks critical variables, it is essential to
ensure that the variables are mapped by Pool Key to prevent
mismanagement of assets between different pools. One solution to
restrict usage is to revert in the beforeInitialize function if the
Pool Key has already been used.
Pool Manager Calls: The hook is called by the Pool Manager. For the
hook to interact with the Pool Manager (e.g., to liquidate tokens), it
must use the lock/callback mechanism. It is vital that the
unlockCallback function includes a modifier (onlyPoolManager) to ensure
that only the Pool Manager can call it.
Liquidity Ownership: Hooks can hold Pool Manager tokens or change
balance deltas. If a hook owns assets, it is necessary to track the
origin of those assets (which pool key) to prevent token mixing between
different pools. The complexity of the EIP-6909 standard (credit
system) and Flash Accounting was mentioned, which means that the actual
transfer of ERC20 tokens to the hook only occurs after the swap,
preventing the hook from transferring these tokens externally during
function execution.
Swap Symmetry: There are four possible variations in a swap (0-to-1,
1-to-0, with exact input or exact output). The developer must be aware
of whether the hook is altering the logic in a non-symmetrical way,
which is crucial for hooks like anti-sandwich.
Native ETH Handling: EIP-6909 abstracts the handling of native ETH and
ERC20 tokens under the concept of "currency." The developer must handle
msg.value in functions called directly by users and be aware that
native ETH will always be zero currency if in use.
OpenZeppelin offers a library of modules to facilitate secure hook
development, including:
Base Modules: For abstracting patterns, such as BaseHook and
BaseCustomAccounting.
Fee Modules: To handle dynamic fees (BaseDynamicFee), with examples of
overriding or fees applied after the swap (dynamic after fee).
General Hooks: Ready-made defensive examples, such as the Anti-Sandwich
Hook (to prevent front-running MEV attacks), the Liquidity Penalty Hook
(to penalize Just-in-Time liquidity attacks, incentivizing long-term
LPs), and the Limit Order Hook (to enable limit orders by adding
liquidity outside the range).
The importance of issuing events (iHook Events) in a standardized
manner (swap, hook fees, liquidity modification, bonuses) was
highlighted so that the Uniswap Foundation and the community can track
hook revenue and performance consistently.
The
seminar, presented by Damian Rusinek of Composable Security, takes a
deep dive into the architecture and security threats of Uniswap V4
Hooks, highlighting that V4's high level of customization introduces
new attack vectors.
V4 migrates from V3's multi-contract architecture to a Singleton
Pattern, where a single Pool Manager stores all pools and liquidity.
The Pool Manager interacts with the Pool Operator (the router), which
uses a lock/callback mechanism (similar to a flash loan) to execute
transactions and ensure balances are finally settled.
The key focus is on Hooks, contracts that the Pool Manager calls at
eight execution points (before/after swap, liquidity addition/removal,
initialization, etc.). The hook can be the Pool Operator itself,
allowing complete control over the liquidity logic.
Composable Security identified six major threats:
Lack of Access Control (beforeInitialize): If the hook's
beforeInitialize doesn't have a modifier like onlyPoolManager, an
attacker can call it directly. This can overwrite critical variables
(such as the LP ERC20 token associated with the pool), rendering the
old token useless and locking up all previously added liquidity. The
solution is the poolManagerOnly modifier.
Unauthorized Callback Calls: The unlockCallback function in the Pool
Operator should also be protected with onlyPoolManager to prevent
malicious users from injecting arbitrary data and manipulating the
liquidity logic.
Pool Key Mismanagement: Hooks designed to function as Pool Operators
may use a unique storage variable for the Pool Key. If a second pool
initializes the same hook, it can overwrite this key. This causes the
hook to attempt to modify positions in the wrong pool, locking up the
original liquidity. The solution is to use Pool Key mappings or ensure
that the hook is used by only one pool.
Sender Impersonation: The sender parameter provided by the Pool Manager
to the hook is actually the address of the Pool Operator (the router),
not the end user's. A malicious operator can use hookData (arbitrary
user data) to inject a victim's address, simulating a withdrawal and
stealing approved liquidity. Developers must extract the user's real
address from the hookData.
Dynamic Rate Theft: Hooks with the Dynamic Rate flag can update the
swap rate in real time, capped at 100%. An attacker can set the rate to
100%, stealing the entire swap output without reversing. Furthermore,
if the rate calculation results in a value greater than 100%, the
transaction is reverted, which can permanently block the hook and the
pool if the rate remains stuck at that value.
Upgradability: For some, this is a safeguard; for others, a
vulnerability. If a hook is upgradable, its logic can be changed at any
time, introducing risks to users and other protocols that integrate
with it. OpenZeppelin and the community provide security checklists to
mitigate these attack vectors, highlighting the complexity of
integration in Uniswap V4.