Back to Blog

Yaklaşık 3,87 milyon USD kayıp: Autheo Network ve UNCX saldırıları | BlockSec Haftalık Bülteni

Code Auditing
22 Ekim 2026
9 min read
Key Insights
  • Bu rapor, toplam tahmini kaybın yaklaşık 3,87 milyon USD olduğu 3 önemli güvenlik olayını ele alıyor. Olaylar, bir özel anahtarın ele geçirilmesini, hak ediş muhasebesindeki bir hatayı ve cüzdan başlangıç değerinin zayıf üretilmesini içeriyordu.

  • UNCX Network'ün Smart Token Vesting V2 olayı, Ethereum, BNB Chain, Base ve Robinhood Chain genelinde 10 varlığı etkiledi. Hatalı bir toplam hisse hesaplaması, farklı token-hisse oranlarıyla oluşturulmuş hak ediş dilimlerini bir araya getirerek gerçekleşmiş veya yönlendirilmiş değerden yaklaşık 807 bin USD elde edilmesine olanak tanıdı.

  • Havuzlanmış muhasebe, her bir dilimin token miktarı, hisse hesaplama esası ve hak ediş ilerlemesi arasındaki ilişkiyi korumalıdır. Bunları tek bir oran altında birleştirmek, bir pozisyonun ortak bakiyeden olması gerekenden fazla çekmesine ve diğer pozisyonların karşılanması için mevcut varlıkların azalmasına yol açabilir.

Geçtiğimiz hafta (12.10.2026–18.10.2026), toplam tahmini kaybı yaklaşık 3,87 milyon USD olan şu 3 önemli güvenlik olayı öne çıkıyor.

Tarih Olay Tür Tahmini Kayıp
12.10.2026 Autheo Network Özel Anahtarın Ele Geçirilmesi ~1,76 milyon USD
14.10.2026 UNCX Network Muhasebe Hatası ~807 bin USD
18.10.2026 Qubic Wallet Zayıf Seed Oluşturma ~1,30 milyon USD

Kayıp rakamları, gerçekleşen değer temel alınarak yapılan tahminlerdir.

  • UNCX Network: Hatalı toplam pay hesaplaması, sözleşme muhasebesi açısından haftanın en açık dersini sunduğu için bu olay ayrıntılı olarak inceleniyor.

Ücretsiz Güvenlik Taraması

Kendi geliştirdiğimiz otomatik analiz motoruyla hızlı bir güvenlik incelemesi.

Ücretsiz tarayın

Haftanın Öne Çıkan Olayı: UNCX Network

14.10.2026 tarihinde saldırganlar, UNCX Network'ün Ethereum, BNB Chain, Base ve Robinhood Chain üzerindeki Smart Token Vesting V2 sözleşmelerinden yararlandı. Olay, doğrulanmış 11 fon boşaltma işleminde 10 varlığı etkiledi ve gerçekleşen veya yönlendirilen değer olarak yaklaşık 807,609 bin USD tutarla sonuçlandı [1]. Temel neden, farklı token-pay oranlarında oluşturulan hak ediş dilimlerini bir araya getiren hatalı bir toplam pay hesaplamasıydı. Bu durum, pozisyon düzeyindeki kayıtların küresel pay arzından ayrışmasına yol açarak saldırganların kontrolündeki pozisyonlardan, saldırganların sağladığından daha fazla token çekilmesine olanak tanıdı.

Arka Plan

UNCX Network, Smart Token Vesting V2 ürünüyle projelerin ERC-20 tokenlarını zamana dayalı hak ediş takvimlerine göre kilitlemesine olanak tanıyan çok zincirli bir DeFi altyapı sağlayıcısıdır. Her takvim bir hak ediş ID'siyle temsil edilir; tokenı, oluşturucuyu, lehtarı, toplam tutarı, hâlihazırda serbest bırakılmış tutarı ve bir veya daha fazla kilit açma dilimini kaydeder. Esnek ve sonradan ekleme yapılabilen bir pozisyon, oluşturulduktan sonra ek dilimler alabilir; oluşturucusu ise henüz hak edilmemiş kısmı iptal edebilir.

Aynı tokena ait pozisyonlar VestingManager içinde tek bir bakiyeyi paylaşır ve protokol, her pozisyonun bu bakiyenin ne kadarına sahip olduğunu belirlemek için payları kullanır. Dolayısıyla muhasebesi birbiriyle ilişkili iki katmandan oluşur:

Global pool, per token
  create / topUp: receive tokens and mint shares
  release: convert releasable shares into tokens
  _totalTokenShares[token]: active shares across all positions

Position record, per vesting ID
  _depositedShares[id]: share basis assigned to the position
  totalAmount: token amount represented by its tranches
  released: shares already paid to the beneficiary

Yönetici, serbest bırakma işleminde önce takvimin ne kadarının hak edildiğini hesaplar. totalAmount değerinin bu oranını _depositedShares[vestingId] kullanarak hak edilmiş paylara dönüştürür, released değerini çıkarır ve sonuca releasableShares adını verir. Aşağıdaki formülde tokenBalance, takvimin tokenı için yöneticinin mevcut ERC-20 bakiyesidir ve bu tokena ait tüm pozisyonlar arasında paylaşılır; _totalTokenShares[token] ise buna karşılık gelen küresel aktif pay arzıdır. Token ödemesi, bu ikisi arasındaki orana bağlıdır:

amount = releasableShares * tokenBalance / _totalTokenShares[token]

Hak ediş işlevleri aracılığıyla yatırma yapmak hem token bakiyesini hem de pay arzını artırır. Yöneticiye doğrudan yapılan bir ERC-20 transferi yalnızca token bakiyesini değiştirir; dolayısıyla her payın temsil ettiği token sayısını değiştirir. Bu pay modeli, havuzlanmış pozisyonları ancak yaşam döngüsündeki her işlem pozisyon kayıtlarıyla küresel arzın mutabakatını korursa destekleyebilir.

Güvenlik Açığı Analizi

Ethereum üzerindeki etkilenen 0xA98F...99F5 adresli VestingManager, release(), topUpVesting() ve cancel() işlevleri boyunca istismar edilebilir hâle gelen hatalı bir toplam pay hesaplaması içerir. Diğer üç ağda da aynı şekilde etkilenen dağıtımlar bulunmaktadır.

Durum değişikliklerini karşılaştırmayı kolaylaştırmak için aşağıdaki analizde D, R ve V kısaltmaları kullanılıyor. Bu semboller sözleşme kodunda yer almaz; tablo, her birini karşılık gelen sözleşme değişkeni veya ifadesiyle eşleştirir. Eşleştirilen değerler iki miktar türüne ayrılır:

Sembol Sözleşme değişkeni / ifadesi Miktar türü Anlamı
D _depositedShares[vestingId] Pay miktarı Pozisyon için kaydedilen tüm yatırımlara atanan kümülatif pay bazı
R schedule.released Pay miktarı Lehtara hâlihazırda ödenmiş kümülatif paylar
- schedule.totalAmount Token miktarı Pozisyonun mevcut dilimleri genelinde kaydedilen toplam token miktarı
- vestedAmount Token miktarı totalAmount değerinin, bu dilimler kapsamında şu anda hak edilmiş kısmı
V vestedShare Pay miktarı Tek bir harmanlanmış hak edilmiş token oranının D değerine uygulanmasıyla hesaplanan kümülatif hak edilmiş paylar

release() işlevinde sözleşme, releasableShares değerini hesaplar, schedule.released değerini artırır ve aynı miktarı _totalTokenShares[schedule.token] değerinden çıkarır. _depositedShares[vestingId] değerini azaltmaz. Bu nedenle serbest bırakma işleminden sonra pozisyon, saklanan pay bazı D olarak kalsa da küresel arza yalnızca D - R canlı pay katkısında bulunur.

function release(uint256 vestingId) external nonReentrant {
    ...
    uint256 releasableShares = _getReleasableShares(vestingId);
    uint256 balance = IERC20(schedule.token).balanceOf(address(this));
    uint256 amount =
        (releasableShares * balance) / _totalTokenShares[schedule.token];

    schedule.released += releasableShares;
    _totalTokenShares[schedule.token] -= releasableShares;
    IERC20(schedule.token).safeTransfer(msg.sender, amount);
}

cancel(), pozisyonun toplam pay bazına tek bir harmanlanmış hak ediş oranı uygular. Önce vestedAmount değerini getVestedAmount(vestingId) aracılığıyla hesaplar, ardından token cinsinden ifade edilen hak edilmiş oranı V = (vestedAmount * D) / totalAmount olarak paylara dönüştürür. Son olarak işlev, D - V değerini pozisyonun çıkarılabilir, henüz hak edilmemiş payları olarak kabul eder. V, önceki ödemelerden sonra kalan hak edilmiş paylar değil, kümülatif bir değerdir.

function cancel(uint256 vestingId) external nonReentrant {
    ...
    uint256 vestedAmount = getVestedAmount(vestingId);
    uint256 remainingAmount = schedule.totalAmount - vestedAmount;

    uint256 vestedShare =
        vestedAmount * _depositedShares[vestingId] / schedule.totalAmount;
    uint256 sharesToRemove =
        _depositedShares[vestingId] - vestedShare;
    _totalTokenShares[schedule.token] -= sharesToRemove;

    _depositedShares[vestingId] = vestedShare;
    schedule.totalAmount = vestedAmount;
    schedule.cancelled = true;

    IERC20(schedule.token).safeTransfer(schedule.creator, remainingAmount);
}

Hata, harmanlanmış hesaplamanın kendisindedir. Her dilimin ayrı bir token miktarı, hak ediş ilerlemesi ve eklendiği sırada geçerli olan havuz oranına göre basılmış pay sayısı vardır. Bu nedenle her dilimin hak edilmiş payları ayrı ayrı hesaplanıp ardından toplanmalıdır. Bunun yerine sözleşme, token miktarlarını ve pay bazını önce bir araya getirir, ardından yalnızca bir D ve bir totalAmount sakladığı için birleşik pozisyona tek bir hak ediş oranı uygular. Bu iki yaklaşım yalnızca dilimlerin token başına pay oranı veya hak ediş ilerlemesi aynı olduğunda eşdeğerdir. Doğrudan token transferi, ekleme yapılmadan önce havuz oranını değiştirir; böylece yeni dilim, ilk dilime göre token başına çok daha az pay alır. Her iki dilime tek bir harmanlanmış hak ediş oranı uygulamak, artık dilimlerin birleşik hak edilmiş paylarını temsil etmeyen bir V üretebilir.

R, pozisyonun kümülatif hak edilmiş paylarından zaten ödenmiş olduğundan, tutarlı bir takvim R <= V koşulunu sağlamalıdır. Bu eşitsizliğin ihlali, harmanlanmış hesaplama hatasının doğrudan belirtisidir. Kod, pozisyon için ayrı bir canlı pay bakiyesi tutmaz; D - V değerini doğrudan küresel _totalTokenShares değerinden çıkarır. Diğer pozisyonların 1000 pay katkısında bulunduğunu, bu pozisyonun ise D = 100 ve R = 80 değerlerine sahip olduğunu varsayalım. İptalden önce küresel arz 1,000 + (D - R) = 1,020 pay içerir. Harmanlanmış hesaplama V = 60 sonucunu üretirse cancel(), D - V = 40 değerini çıkarır ve geriye yalnızca 980 küresel pay bırakır; bu, diğer pozisyonların katkıda bulunduğu 1000 paydan 20 daha azdır. Küresel arz yalnızca bu pozisyonun 20 canlı payını içerseydi, 40 değerinin çıkarılması alt taşmaya yol açar ve işlem geri alınırdı; fazla çıkarma ancak paylaşılan havuz diğer pozisyonların katkıda bulunduğu payları içerdiği için başarılı olur. Ardından işlev _depositedShares[vestingId] = 60 değerini saklarken schedule.released, 80 olarak kalır ve pozisyon kaydını imkânsız olan D < R durumunda bırakır.

Kod ne R <= V koşulunu zorunlu kılar ne de sharesToRemove değerini pozisyonun canlı paylarıyla sınırlar. Bu nedenle iptal işlemi, artık küresel arzın parçası olmayan geçmiş payları çıkarabilir. Aynı zamanda, iadeyi havuzun pay oranı üzerinden dönüştürmeden totalAmount - vestedAmount miktarını doğrudan token birimleriyle transfer eder. İptal işleminin kendisi fazla ödeme üretmez; yalnızca küresel pay arzını pozisyonlar genelinde kaydedilen canlı payların altına indirerek daha sonraki bir fazla tahsilatın koşullarını oluşturur.

Saldırı Analizi

Aşağıdaki analiz, Ethereum üzerindeki temsilî bir işlem olan 0x352065...c23823 işlemini kullanır. Saldırı sözleşmesi, işlem içinde beş tokena karşı aynı temel diziyi yürüttü ve her token için flash likidite kullandı.

  • Adım 1: Saldırgan, hemen hak edilmiş küçük bir pozisyon olan #5058 ile hemen hak edilmiş, esnek ve sonradan ekleme yapılabilen çok daha büyük iki pozisyon olan #5059 ve #5060 pozisyonlarını oluşturdu. Küçük pozisyon son çekim için tutulacak, büyük pozisyonlar ise küresel muhasebeyi bozmak için gereken geçmiş pay kayıtlarını sağlayacaktı.

  • Adım 2: Saldırgan, iki büyük pozisyonun hak edilmiş kısmını serbest bıraktı. Başlangıçtaki yaklaşık 1:1 havuz oranında her serbest bırakma işlemi, yaklaşık olarak ilgili net yatırımı geri verdi. Karşılık gelen paylar _totalTokenShares değerinden çıktı; ancak ilk değerler, #5059 ve #5060 pozisyonlarına ait _depositedShares kayıtlarında kaldı ve serbest bırakılmış olarak yalnızca her takvimin ayrı released alanına kaydedildi.

  • Adım 3: Saldırgan, tokenları doğrudan VestingManager sözleşmesine transfer etti. Bu, serbest bırakılmış payları geri getirmeden token bakiyesini eski düzeyine çıkardı; böylece kalan her payın temsil ettiği token miktarı keskin biçimde arttı.

  • Adım 4: Saldırgan, daha önce serbest bırakılmış büyük pozisyonlara ekleme yaptı. Ek yatırımlar, yeni yükselmiş olan pay başına token oranıyla fiyatlandığından, yüksek tutarlı token yatırımları yalnızca az sayıda yeni pay bastı. Pozisyonlar artık büyük, güncelliğini yitirmiş bir geçmiş pay bazı ile küçük bir canlı pay katkısını bir arada içeriyordu.

  • Adım 5: Saldırgan, ekleme yaptığı iki pozisyonu iptal etti. Her iptal işlemi, toplam yatırılmış pay geçmişine tek bir harmanlanmış hak ediş oranı uyguladı. Yeniden hesaplanan vestedShare, hâlihazırda serbest bırakılmış payların altına düştü; böylece sharesToRemove, pozisyonun canlı katkısını aştı. Her pozisyon ekleme sırasında yalnızca az miktarda canlı pay katmış olmasına rağmen küresel arz, pozisyon başına yaklaşık 5.0e25 hayalî pay azaltıldı.

  • Adım 6: Payda ciddi ölçüde düşük gösterilmişken saldırgan, elinde tuttuğu küçük pozisyonun hak edilmiş kısmını serbest bıraktı. İncelenen token örneğinde yaklaşık 5.73e22 ham birimlik net yatırımla yaklaşık 1.07e26 ham birim çekildi; bu, yatırılan miktarın yaklaşık 1,873 katıydı. Saldırgan, bozulan orandan yararlanarak pozisyon oluşturma ve serbest bırakma döngülerini tekrarladı ve flash likiditeyi geri ödedi.

Resmî olay raporu, doğrulanmış 11 fon boşaltma işleminde aynı örüntüyü tespit etti. Bazı varyantlar tek bir atomik işlemde tamamlanırken diğerlerinde son serbest bırakma bağlantılı bir işlemde gerçekleştirildi. UNCX, yaklaşık 807,609 bin USD tutarındaki rakamı saldırganın ana parasını, geçici flash işlem hacmini ve iade edilen varlıkları hariç tutarak gerçekleşen veya yönlendirilen gelirlerden hesapladı [1].

Phalcon Explorer ile Başlayın

Bilinçli Hareket Etmek İçin İşlemleri Derinlemesine İnceleyin

Şimdi ücretsiz deneyin

Sonuç

Temel neden, hatalı toplam pay muhasebesiydi. Protokol, farklı token-pay oranlarında oluşturulmuş dilimleri birleştirdi ve ardından bunların toplam pay bazına tek bir hak ediş oranı uyguladı. Bu, kümülatif hak edilmiş payların yanlış hesaplanmasına yol açtı, bir pozisyonun hâlâ katkıda bulunduğundan daha fazla pay çıkarmasına olanak tanıdı ve pozisyon düzeyindeki kayıtların küresel pay arzından ayrışmasına neden oldu. Saldırganlar, olduğundan düşük gösterilen küresel arzdan yararlanarak paylaşılan bakiyeden, diğer hak ediş pozisyonlarının karşılanması için gerekli olmaya devam eden tokenları çekti.

Değişen pay oranlarında sonradan yatırmaya izin veren bir muhasebe modeli, dilimleri tek bir oran altında harmanlamak yerine her dilimin token miktarını, pay bazını ve hak ediş ilerlemesini ayrı ayrı korumalıdır. Ayrıca kümülatif ödemelerin kümülatif hak edilmiş payları hiçbir zaman aşmamasını ve bir pozisyonun canlı katkısından daha fazlasını çıkaramamasını zorunlu kılmalıdır.

Kaynaklar

[1] UNCX Network Smart Token Vesting V2 Olay Raporu

Web3 için En İyi Güvenlik Denetçisi

Yayına almadan önce tasarımı, kodu ve iş mantığını doğrulayın

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit