DeFi/AMM Uitbuiting: Uniswap v4 Hook Presisie/Afrondingsmisbruik
Reading time: 9 minutes
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Hierdie bladsy dokumenteer ân klas DeFi/AMMâuitbuitingstegnieke teen Uniswap v4âstyl DEXes wat kernâwiskunde uitbrei met custom hooks. ân Onlangse voorval in Bunni V2 het ân afronding/presisie fout in ân Liquidity Distribution Function (LDF) benut wat by elke swap uitgevoer is, wat die aanvaller in staat gestel het om positiewe krediete aan te bou en likiditeit te dreineer.
Sleutelidee: as ân hook addisionele rekeningkunde implementeer wat afhanklik is van fixedâpoint math, tick rounding, en drempelâlogika, kan ân aanvaller exactâinput swaps saamstel wat spesifieke drempels kruis sodat afrondingsverskille in hul guns ophoop. Deur die patroon te herhaal en dan die opgeblase balans terug te trek, word wins gerealiseer â dikwels gefinansier met ân flash loan.
Achtergrond: Uniswap v4 hooks en swap flow
- Hooks is kontrakte wat die PoolManager op spesifieke lewensikluspunte aanroep (bv. beforeSwap/afterSwap, beforeAddLiquidity/afterAddLiquidity, beforeRemoveLiquidity/afterRemoveLiquidity).
- Pools word geĂŻnitialiseer met ân PoolKey wat die hooks address insluit. As dit nieânul is, voer PoolManager callbacks uit by elke relevante operasie.
- Core math gebruik fixedâpoint formats soos Q64.96 vir sqrtPriceX96 en tick arithmetic met 1.0001^tick. Enige custom math wat daarbo geplaas word, moet die afrondingssemantiek noukeurig pas om invariant drift te vermy.
- Swaps kan exactInput of exactOutput wees. In v3/v4 beweeg die prys oor ticks; die oorskryding van ân tickâgrens kan range liquidity aktiveer/deaktiveer. Hooks kan addisionele logika implementeer op threshold/tick crossings.
Vulnerability archetype: thresholdâcrossing precision/rounding drift
ân Tipiese kwesbare patroon in custom hooks:
- Die hook bereken perâswap liquidity of balansdeltaâs met integer division, mulDiv, of fixedâpoint conversions (bv. token â liquidity gebruikende sqrtPrice en tick ranges).
- Thresholdâlogika (bv. rebalancing, stepwise redistribution, of perârange activation) word geaktiveer wanneer ân swapâgrootte of prysbeweging ân interne grens kruis.
- Afronding word onsystematies toegepas (bv. truncation toward zero, floor versus ceil) tussen die vooruitberekening en die settlementâpad. Klein verskille kanselleer nie en krediteer eerder die caller.
- Exactâinput swaps, presies gemeet om daardie grense te oorbrug, oes herhaaldelik die positiewe afrondingsreste. Die aanvaller onttrek later die opgehoopte krediet.
Aanvalsâvoorwaardes
- ân Pool wat ân custom v4 hook gebruik wat by elke swap addisionele wiskunde uitvoer (bv. ân LDF/rebalancer).
- Ten minste een uitvoeringspad waar afronding die swap initiator bevoordeel oor drempelâoorskrywings.
- Vermoë om baie swaps atomies te herhaal (flash loans is ideaal om tydelike float te verskaf en gas te amortiseer).
Praktiese aanvalsâmetodologie
- Identifiseer kandidaatpools met hooks
- Enumereer v4 pools en kontroleer PoolKey.hooks != address(0).
- Inspekteer hook bytecode/ABI vir callbacks: beforeSwap/afterSwap en enige custom rebalancing metodes.
- Soek na wiskunde wat: deel deur liquidity, omskakel tussen token amounts en liquidity, of BalanceDelta aggregasie met afronding uitvoer.
- Modelleer die hook se wiskunde en drempels
- Herbou die hook se liquidity/redistribution formule: inpute sluit gewoonlik sqrtPriceX96, tickLower/Upper, currentTick, fee tier, en net liquidity in.
- Kaart threshold/step funksies: ticks, bucket boundaries, of LDF breakpoints. Bepaal aan watter kant van elke grens die delta afgerond word.
- Identifiseer waar omskakelings tussen uint256/int256 plaasvind, SafeCast gebruik word, of mulDiv met implisiete floor staatmaak.
- Kalibreer exactâinput swaps om grense te kruis
- Gebruik Foundry/Hardhat simulatsies om die minimale Îin te bereken wat nodig is om die prys net oor ân grens te skuif en die hookâbranch te trigger.
- Verifieer dat afterSwap settlement die caller meer krediteer as die koste, wat ân positiewe BalanceDelta of krediet in die hookârekeninglaat agterlaat.
- Herhaal swaps om krediet op te bou; roep dan die hook se withdrawal/settlementâpad aan.
Example Foundryâstyle test harness (pseudocode)
function test_precision_rounding_abuse() public {
// 1) Arrange: set up pool with hook
PoolKey memory key = PoolKey({
currency0: USDC,
currency1: USDT,
fee: 500, // 0.05%
tickSpacing: 10,
hooks: address(bunniHook)
});
pm.initialize(key, initialSqrtPriceX96);
// 2) Determine a boundaryâcrossing exactInput
uint256 exactIn = calibrateToCrossThreshold(key, targetTickBoundary);
// 3) Loop swaps to accrue rounding credit
for (uint i; i < N; ++i) {
pm.swap(
key,
IPoolManager.SwapParams({
zeroForOne: true,
amountSpecified: int256(exactIn), // exactInput
sqrtPriceLimitX96: 0 // allow tick crossing
}),
""
);
}
// 4) Realize inflated credit via hookâexposed withdrawal
bunniHook.withdrawCredits(msg.sender);
}
Kalibrering van die exactInput
- Bereken ÎsqrtP vir 'n tick-stap: sqrtP_next = sqrtP_current Ă 1.0001^(Îtick).
- Benader Îin met behulp van v3/v4-formules: Îx â L Ă (ÎsqrtP / (sqrtP_next Ă sqrtP_current)). Sorg dat die afrondingsrigting ooreenstem met die kernwiskunde.
- Pas Îin met ±1 wei rondom die grens aan om die tak te vind waar die hook in jou guns afrond.
- Vergroot met flash loans
- Leen 'n groot notionele bedrag (bv. 3M USDT of 2000 WETH) om baie iterasies atomies uit te voer.
- Voer die gekalibreerde swap-lus uit, onttrek en betaal dan terug binne die flash loan callback.
Aave V3 flash loan skeleton
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external returns (bool) {
// run thresholdâcrossing swap loop here
for (uint i; i < N; ++i) {
_exactInBoundaryCrossingSwap();
}
// realize credits / withdraw inflated balances
bunniHook.withdrawCredits(address(this));
// repay
for (uint j; j < assets.length; ++j) {
IERC20(assets[j]).approve(address(POOL), amounts[j] + premiums[j]);
}
return true;
}
- Uitstap en oorkettingâreplikasie
- As hooks op verskeie kettings ontplooi is, herhaal dieselfde kalibrasie per ketting.
- Brug stuur opbrengste terug na die teikenketting en kan opsioneel via leningsprotokolle kringloop om vloei te verwring.
Algemene oorsake in hookâwiskunde
- Gemengde afrondingssemantiek: mulDiv voer floor uit terwyl later paaie effektief na bo afrond; of omskakelings tussen token/liquidity pas verskillende afronding toe.
- Tickâuitlijningsfoute: gebruik van onafgeronde ticks in een pad en tickâspasâafronding in 'n ander.
- BalanceDelta teken/overflowâkwessies wanneer omgeskakel word tussen int256 en uint256 tydens settlement.
- Presisieverlies in Q64.96 omskakelings (sqrtPriceX96) nie gespiegeld in die omgekeerde mapping nie.
- Akkumulatieâpaaie: perâswap watreste wat as krediete gevolg word en deur die caller onttrekbaar is in plaas daarvan om verbrand/zeroâsum te wees.
Verdedigende riglyne
- DifferensiĂ«le toetsing: spieĂ«l die hook se wiskunde teen 'n verwysingsimplementering met hoĂ«âpresisie rasionele rekenkunde en stel gelykheid of 'n begrensde fout wat altyd adversarieel is (nooit in die caller se guns nie).
- Invariant/eienskapstoetse:
- Som van deltas (tokens, liquidity) oor swapâpaaie en hookâaanpassings moet waarde conserveer modulo fooie.
- Geen pad mag 'n positiewe netto krediet vir die swapâinitiatior skep oor herhaalde exactInputâiterasies nie.
- Drempel/tickâgrens toetse rondom ±1 wei insette vir beide exactInput/exactOutput.
- Afrondingsbeleid: sentraliseer afrondingshelpers wat altyd teen die gebruiker afrond; verwyder inkonsekwente casts en implisiete floors.
- Settlement sinks: akkumuleer onvermydelike afrondingsresidu na die protokolâkassie of verbrand dit; ken dit nooit toe aan msg.sender nie.
- Rateâlimits/guardrails: minimum swapâgroottes vir rebalanseringsâtriggers; deaktiveer rebalanses as deltas subâwei is; sanityâcheck deltas teen verwagte reekse.
- Hersien hook callbacks holisties: beforeSwap/afterSwap en before/after liquidityâveranderings moet saamstem oor tickâuitlijning en deltaâafronding.
Gevallestudie: Bunni V2 (2025â09â02)
- Protokol: Bunni V2 (Uniswap v4 hook) met 'n LDF toegepas per swap om te rebalanseer.
- Oorsaak: afrondings/presisieâfout in LDF liquiditeitsrekeninghouding tydens drempelâoorsteek swaps; perâswap ongelykhede het opgeloop as positiewe krediete vir die caller.
- Ethereum poot: aanvaller het 'n ~3M USDT flash loan geneem, gekalibreerde exactâinput swaps op USDC/USDT uitgevoer om krediete op te bou, opgehewe opgeblase balances, terugbetaal, en fondse via Aave gerouteer.
- UniChain poot: het die exploit herhaal met 'n 2000 WETH flash loan, ongeveer 1366 WETH afgesyfer en na Ethereum gebridged.
- Impak: ~USD 8.3M leeggemaak oor kettings. Geen gebruikersinteraksie benodig; heeltemal onâchain.
Opsporingskontrolelys
- Gebruik die pool 'n nieânul hooksâadres? Watter callbacks is geaktiveer?
- Is daar perâswap herverdelings/rebalanses wat aangepaste wiskunde gebruik? Enige tick/drempel logika?
- Waar word divisions/mulDiv, Q64.96 omskakelings, of SafeCast gebruik? Is afrondingssemantiek globaal konsekwent?
- Kan jy Îin konstrueer wat skaars 'n grens oorsteek en 'n gunstige afrondingsâtak lewer? Toets beide rigtings en beide exactInput en exactOutput.
- Hou die hook perâcaller krediete of deltas by wat later onttrek kan word? Verseker dat residu geneutraliseer word.
References
- Bunni V2 Exploit: $8.3M Drained via Liquidity Flaw (summary)
- Bunni V2 Exploit: Full Hack Analysis
- Uniswap v4 background (QuillAudits research)
- Liquidity mechanics in Uniswap v4 core
- Swap mechanics in Uniswap v4 core
- Uniswap v4 Hooks and Security Considerations
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.