Uniswap v4, Hook ile programlanabilir likidite sağlar ancak izin kodlaması ve erişim kontrolü gibi eksiklikler nedeniyle saldırıların odak noktası haline gelmiştir; Async Hook ve muhasebe mantığının yanlış kullanımı riskine dikkat edilmelidir.Yazı yazarı, kaynak: Beosin
Uniswap v4'ün ana ağda başlatılmasından sonra, Hook mekanizması DeFi'nin en çok dikkat çeken yeniliklerinden biri haline geldi. Base zincirindeki memecoin fırlatma platformu Flaunch, Hook'u sabit ön satış fiyatı ve otomatik likidite açılış mekanizması oluşturmak için kullandı; likidite protokolü Bunni v2, Hook'u programlanabilir likidite ve yeniden çapraz temin modeli inşa etmek için kullandı; bu yıl SATO, uPEG (Unipeg), Slonks gibi Hook oyunlarına dayalı tokenlar kısa sürede onlarca kat artış kaydetti.
Hook ekosisteminin gelişiminin bir diğer yüzünde, Hook implementasyon hatalarına yönelik saldırılar belirgin bir şekilde artıyor. Bu makale, Uniswap v4 Hook mekanizmasından başlayarak temel çağrı yığınını adım adım analiz ederek projelerin olası açıkları anlamasına yardımcı olacak.
Uniswap v4 Hook Güvenliği
1. Giriş
Uniswap v4'ün v3'e göre en önemli mimari değişikliği, Hook (bağlantı) mekanizmasının eklenmesidir: Geliştiricilerin, özelleştirilmiş sözleşmeleri likidite havuzlarının yaşam döngüsü olaylarına bağlamasını ve swap, likidite ekleme/çıkarma, başlatma gibi noktalarda herhangi bir mantık eklemesini sağlar.
v4'ün birkaç ana değişikliği şunlardır:
Tekil desen: Tüm havuzların durumu, her havuz için ayrı ayrı sözleşme dağıtmak yerine, tek bir PoolManager sözleşmesi tarafından merkezi olarak yönetilmektedir.
- Anlık muhasebe: İşlem sırasında ortaya çıkan geçici bakiye değişiklikleri yalnızca geçici depolamada kaydedilir ve işlem sonunda tek seferde hesaplanır.
- Hook mekanizması: Her havuz, bir Hook sözleşmesiyle bağlanabilir; PoolManager, kritik noktalarda (beforeInitialize, beforeSwap, afterAddLiquidity vb.) bu sözleşmeyi geri çağırır.
- Bağlantı noktası değiştirilemez: Havuz başlatıldığında, ilişkilendirilen bağlantı noktası adresi kalıcı olarak sabitlenir (havuzla ilişkilendirilen bağlantı noktası adresi değiştirilemez, ancak bağlantı noktası sözleşmesinin kendisinin yükseltilebilir olup olmadığı, uygulama şekline bağlıdır).
v3 döneminde geliştiriciler yalnızca Uniswap protokolüne güvenmelidir; ancak v4 döneminde her havuzun güvenliği, bağlı olduğu Hook'a bağlıdır. Hook, AMM'yi sabit bir finansal primitive'den programlanabilir bir finansal altyapıya dönüştürür, ancak güvenlik modeli "protokol seviyesinden" "havuz seviyesine" parçalanır.
2. Bağlama Yapısı 2.1 PoolManager ve unlock/callback modeli
v4'nin temel sözleşmesi, tekil bir PoolManager'dır. Havuzun durumunda yapılan herhangi bir değişiklik (swap, likidite ekleme/çıkarma) önce PoolManager.unlock() çağrılmalı ve tek seferlik geri çağırma izni alınmalıdır; ardından unlockCallback() içinde ilgili işlem tamamlanmalıdır. Tüm işlem tamamlandığında, PoolManager defterin dengede olup olmadığını doğrular:
NonzeroDeltaCount != 0 olduğunda doğrudan revert edilir; bu, v4 flash muhasebenin temel kısıtlamasıdır. Herhangi bir Hook, işlem sırasında hesap dengesizliğini geçici olarak oluşturabilir, ancak işlem bitmeden önce kendi kendine settle etmelidir; aksi takdirde tüm işlem geri alınır.
Her havuz, hooks alanını içeren bir PoolKey yapısıyla benzersiz şekilde tanımlanır:
PoolId, keccak256(PoolKey) ile hesaplanır, bu nedenle farklı hooks adresleri farklı havuzlar oluşturur. Bu aynı zamanda, PoolManager'ın bir hook adresinin daha önce başka bir havuzda kullanılıp kullanılmadığını doğrulamadığı anlamına gelir; aynı hook sözleşmesi birden fazla havuz tarafından aynı anda bağlanabilir.
2.2 Bağlantı izni kodlaması adres içinde
v4'ün bir doğruluk dışı tasarımı şudur: Hook'un izinleri, sözleşmenin içindeki bir değişken tarafından değil, Hook sözleşmesinin dağıtım adresi tarafından belirlenir.
PoolManager, Hook adresinin alt 14 bitini kontrol ederek bu Hook'un belirli bir yaşam döngüsü noktasında çağrılması gerekip gerekmediğini belirler:
Örneğin, BEFORE_SWAP_FLAG = 1 << 7. Hook adresinin 7. biti 1 ise, PoolManager swap işleminden önce bu Hook'un beforeSwap() fonksiyonunu çağırır; aksi halde, Hook sözleşmesi beforeSwap() uygulasa bile, PoolManager tarafından asla çağrılmaz.
Bu, Hook'un dağıtım sırasında CREATE2 + salt ile adres hesaplanmasını ve hedef izne tamamen uygun bir düşük adres oluşturulmasını gerektirir. Uniswap, bu amaç için HookMiner aracını sunar:
Yetki bitleri ile fonksiyon uygulamaları uyumsuz olduğunda iki tür sorun oluşur:
(1) Bir hook fonksiyonu uygulandı, ancak adres ilgili izin bitleri için kodlanmadı — PoolManager bu fonksiyonu asla çağırmaz, mantık boşuna yapılmıştır.
(2) Adres, belirli bir izin bitini kodlamıştır, ancak hook ilgili işlevi uygulamamıştır—PoolManager, geri çağırma sırasında revert yaşanmasına neden olabilir, bu da DOS gerçekleştirme veya dönüş değeri doğrulama hatasına yol açar ve ilgili işlemlerin yürütülmesini engeller.
Bu aynı zamanda Hook'un yükseltilmesi için doğal bir engeldir: Hook, bir aracılık yoluyla yükseltilebilirse, dağıtım adresi yükseltme sırasında değişmez; bu nedenle yükseltmeden sonra yalnızca mevcut Hook işlevlerinin uygulamaları değiştirilebilir, yeni Hook türleri eklenemez. Gelecekteki genişletilebilirlik için, tüm olası izin bitleri ilk dağıtım sırasında önceden hazırlanmalıdır.
2.3 BaseHook ve Genellikle Gözden Kaçırılan Bir Erişim Kontrol Tuzağı
Uniswap v4 periphery, eski sürümde sağlanan BaseHook soyut sözleşmesini, geliştiricilerin özelleştirilmiş Hook uygulamak için miras almasına izin verir. BaseHook'un önemli bir işlevi, unlockCallback() fonksiyonuna onlyPoolManager dekoratörünü sağlamaktır:
Ancak — burada çok kolayca gözden kaçırılan bir tasarım tuzağı var — BaseHook'un erken sürümleri yalnızca unlockCallback için onlyPoolManager ekledi, diğer hook geri çağrıları (beforeSwap, afterSwap, beforeAddLiquidity vb.) için hiçbir koruma sağlamadı. Bu fonksiyonların erişim kontrolleri, hook geliştiricileri tarafından açıkça eklenmelidir.
3. Hook Yaşam Döngüsü Kod İncelemesi
Bir exact-input swap örneğiyle, kullanıcı tarafından işlem başlatılmasından sonuçlanana kadar olan tam çağrı yığını analiz edilmiştir.
3.1 Havuz başlatma ve Hook bağlama
Herkes PoolManager.initialize() yöntemini çağırarak yeni bir havuz oluşturabilir:
isValidHookAddress, adres yetki bitini ve fee alanının uyumluluğunu yalnızca doğrular; Hook'un başka bir havuzda zaten kullanılıp kullanılmadığını veya Hook'un bu PoolKey'yi kabul etmek isteyip istemediğini doğrulamaz. Hook, beforeInitialize içinde beyaz liste veya tek havuz bağlantısı mantığı eklenmeden tasarlanırsa, herhangi biri aynı Hook'u kullanan ancak token çifti herhangi bir şey olan yeni bir havuz oluşturabilir ve Hook'un sonraki tüm geri çağrılarını tetikleyebilir.
3.2 beforeSwap ve BeforeSwapDelta
Swap işlem giriş noktası PoolManager.swap() fonksiyonudur ve temel swap mantığını çalıştırmadan önce Hooks.beforeSwap() çağırır:
beforeSwap'in dönüş değeri bir üçlüdür (bytes4, BeforeSwapDelta, uint24):
- bytes4: IHooks.beforeSwap.selector ile eşit olmalıdır, aksi halde PoolManager doğrudan revert eder
- BeforeSwapDelta: Hook, bu takas sırasında belirtilen token ve belirtilmeyen token için delta ayarlamalarını yapar
- uint24: Dinamik LP ücret oranı kapsam değeri (havuz dinamik ücret özelliği etkinleştirildiğinde geçerlidir)
BeforeSwapDelta, int256'in bir takma adıdır; üst 128 bit, belirtilen token'ın delta'sını (kullanıcının belirttiği miktardaki token) temsil eder, alt 128 bit ise belirtilmeyen token'ın delta'sını temsil eder:
Önemli bir not: BeforeSwapDelta'nın anlamı, Hook'un ücreti alırken pozitif değer döndürmesi, Hook'un token iade ederken negatif değer döndürmesidir. Geliştiriciler işaretleri kolayca ters çevirebilir; aynı zamanda, specified ve unspecified arasındaki ilişki, params.zeroForOne ve amountSpecified'nin işaretlerine bağlıdır; küçük bir yazım hatası token karışıklığına neden olabilir.
PoolManager, beforeSwap tarafından döndürülen specifiedDelta değerini doğrudan amountToSwap üzerine ekler:
Bu satır, Hook'un swap miktarını tutabileceğini ima eder. HookDeltaSpecified, -params.amountSpecified'e eşit olduğunda, amountToSwap doğrudan sıfırlanır; bu da Hook'un bu swap işlemini tamamen ele aldığını gösterir—buna Async Hook veya Custom Curve Hook denir.
Async Hook, v4'teki en yüksek riskli tasarım desenidir: Temel olarak, Hook'un kendi mantığı ile Uniswap'in swap mantığını değiştirir. Hook'ta bir zafiyet varsa veya kendi başına kötü niyetliyse, kullanıcı fonları Uniswap'in yerel fiyatlandırma mantığından değil, Hook'un kendi implementasyonunun doğruluğuna bağlı kalır.
3.3 Delta Settlemesi ve NonzeroDeltaCount
beforeSwap ve afterSwap tarafından döndürülen delta, hemen bir transfer tetiklemeyecek, bunun yerine PoolManager'ın dahili defterine kaydedilecektir:
Bir token'in birikmiş delta'sı sıfırdan sıfır olmayan bir değere değiştiğinde NonzeroDeltaCount artırılır; sıfıra döndüğünde azaltılır. 2.1'de belirtildiği gibi, unlock() işlevi sonlandığında NonzeroDeltaCount != 0 ise, tüm işlem geri alınır.
Hook, delta'sini dengelemek için settle() (PoolManager'e transfer) ve take() (PoolManager'dan çekme) işlemlerini gerçekleştirir:
Bu mekanizma tarafından sağlanan güvenlik anlamları nettir: herkes sonunda hesaplarını kapatmak zorundadır. Ancak bu yalnızca “hesapların korunmasını” garanti eder, “hesapların doğru olmasını” garanti etmez. Eğer Hook, beforeSwap sırasında kötü niyetli bir delta döndürürse, PoolManager bu delta'yi sadık bir şekilde kaydeder ve hesap sonunda kapatılırsa işlem başarılı sayılır—bu, Hook’un sahte bir iş durumu yaratarak sistemin, saldırganın bazı varlık haklarına sahip olduğunu yanlışlıkla düşündürmesine rağmen, PoolManager’ın bu iş düzeyindeki hatayı tanımlayamaması anlamına gelir.
Daha önce Cork Protocol güvenlik olayı, Hook'unda bir güvenlik açığı nedeniyle gerçekleşti ve saldırıdan önce dört adet denetim firması tarafından denetlendi. Olayın ardından yapılan incelemede şunu tespit ettik:
Dört denetimden üçünün kapsamı CorkHook sözleşmesini içermiyor.
CorkHook'ün tek denetimini yapan kuruluş, bazı kod sorunlarını tespit edip iyileştirme önerilerinde bulundu, ancak erişim kontrol sorunlarını tamamen kapsamadı.
Bir diğer denetim kuruluşu raporunda açıkça şunu öneriyor: “Bu kapsamda doğrulanmış farklı bileşenler tarafından çağrılan CorkHook işlevlerinin sabitlerini kanıtlamak, ilginç bir takip etkinliği olurdu.” Bu öneri, olay sonrası değerlendirme açısından oldukça hedefe yönelik görünmektedir.
Bu, v4 Hook çağının yeni bir denetim boşluğunu ortaya çıkarıyor: protokol karmaşıklığının patlayıcı artışının, kapsam belirleme işlemini kendisini bir güvenlik kararı haline getirmesi. Hook ile protokolün diğer sözleşmeleri arasındaki etkileşim zinciri çok uzundur; Hook sözleşmesini yalnızca incelemek, sözleşmeler arası kombinasyon sorunlarını tespit etmek için yeterli değildir; tersine, çevresel sözleşmeleri inceleyip Hook'u kapsam dışına almak, v4 çağının en büyük saldırı yüzeyini kaçırmaktadır.
5. Yansıma
Protokol mekanizması ve Cork saldırısını yan yana incelediğinde, v4 Hook güvenlik modelinin birkaç temel noktası ortaya çıkar:
(1) Hook geri çağırma işlevi, PoolManager tarafından sağlanan çağrı bağlamına bağlıysa, yalnızca PoolManager tarafından çağrılmasını açıkça sınırlamalıdır. BaseHook, bu işi geliştirici adına yapmaz; bu, v4 ile genel sözleşme denetimi deneyimi arasındaki en yaygın çatışma noktasıdır.
(2) Kancanın havuzla bağlantısı, PoolManager tarafından sınırlanmaz. Geliştiriciler, havuz beyaz listesini veya tek havuz bağlantısını beforeInitialize içinde kendileri uygulamalıdır.
(3) Bağlantı adresinin izin bitleri, fonksiyon uygulamasıyla tam olarak uyumlu olmalıdır. Hesaplanan adres, gelecekteki olası genişlemeler için tüm izin bitlerini önceden içermelidir.
(4) Async / Özel Eğri Bağlantısı, tamamen özelleştirilmiş bir takas uygulamasıdır. Uniswap protokol seviyesinde herhangi bir korumaya sahip değildir ve "tamamen özerk finansal sözleşme" standartlarına göre denetlenmelidir.
(5) Delta muhasebesindeki “korumalı” durum, “doğru” anlamına gelmez. NonzeroDeltaCount == 0, defterin sonunda dengeli olduğunu garanti eder, ancak defterin içeriğinin kasıtlı olarak manipüle edilmediğini garanti etmez.
(6) Çapraz pazar token türü karışıklığı, v4 dönemi için yeni bir saldırı yüzeyidir. Protokol kullanıcıların pazar oluşturmasına izin verdiğinde, tokenların semantik doğrulanması zorunludur ve yalnızca arayüz denetimine dayanılmamalıdır.
Her Hook, bağımsız bir güvenirlik domainidir ve her havuzun güvenliği, bağlı olduğu Hook tarafından belirlenir. Bu nedenle Hook güvenlik denetiminin karmaşıklığı, “bir kod dosyasını denetlemek”ten “tam bir alt protokolü denetlemek” haline gelir — bu değişim, hem proje sahipleri hem de denetim firmaları için yöntemsel bir yükselişi ifade eder.
Kaynaklar
(1) Cork Protocol. “28 Mayıs 2025 Saldırı Sonrası İnceleme.” 2025-06-04. https://www.cork.tech/blog/post-mortem
(2) OWASP Akıllı Sözleşme Güvenliği Top 10 2026, SC01: Erişim Kontrolü Zafiyetleri. https://scs.owasp.org/sctop10/SC01-AccessControlVulnerabilities/
(3) Uniswap v4 Beyaz Kağıt. https://app.uniswap.org/whitepaper-v4.pdf
(4) Uniswap v4-core. https://github.com/Uniswap/v4-core
(5) Uniswap v4-periphery. https://github.com/Uniswap/v4-periphery
Beosin, formel doğrulama alanında dünyanın ilk blockchain güvenlik şirketlerinden biridir ve “güvenlik + uyumluluk” tam ekosistem hizmetleriyle öne çıkmaktadır. 10'dan fazla ülkede ve bölgede şubeleri bulunmakta olup, hizmetleri projenin başlatılması öncesi kod güvenliği denetimi, proje çalışması sırasında güvenlik risklerinin izlenmesi ve engellenmesi, çalınan varlıkların geri kazanımı, sanal varlıklarla ilgili para aklama (AML) önlemleri ve yerel düzenleyici kurallara uygunluk değerlendirmeleri gibi “tek durakta” blockchain uyumluluk ürünleri ve güvenlik hizmetlerini kapsamaktadır. Bize ulaşmak için lütfen resmi kanalda mesaj bırakın.

