میهن بلاکچین
  • اخبار
    • همه
    • رمزارز در ایران
    • اخبار بیت کوین
    • اخبار اتریوم
    • اخبار آلتکوین
    • اخبار بلاکچین
    • اخبار عمومی
    • اطلاعیه صرافی‌های داخلی
  • تحلیل
    • همه
    • تحلیل آنچین
    • تحلیل اقتصادی
    • تحلیل تکنیکال
    • تحلیل فاندامنتال
  • آموزش
    • همه
    • کریپتو پدیا
    • کریپتو کده
    • دیفای
    • سرمایه گذاری
    • آموزش همه صرافی های ارز دیجیتال
    • ترید
    • کیف پول
    • بازی
    • استخراج
    • NFT
    • مقالات عمومی
  • ایردراپ
  • هک و کلاهبرداری
  • قیمت ارزهای دیجیتال
  • ماشین حساب ارزهای دیجیتال
  • مقایسه قیمت در صرافی
No Result
مشاهده همه‌ی نتایج
  • اخبار
    • همه
    • رمزارز در ایران
    • اخبار بیت کوین
    • اخبار اتریوم
    • اخبار آلتکوین
    • اخبار بلاکچین
    • اخبار عمومی
    • اطلاعیه صرافی‌های داخلی
  • تحلیل
    • همه
    • تحلیل آنچین
    • تحلیل اقتصادی
    • تحلیل تکنیکال
    • تحلیل فاندامنتال
  • آموزش
    • همه
    • کریپتو پدیا
    • کریپتو کده
    • دیفای
    • سرمایه گذاری
    • آموزش همه صرافی های ارز دیجیتال
    • ترید
    • کیف پول
    • بازی
    • استخراج
    • NFT
    • مقالات عمومی
  • ایردراپ
  • هک و کلاهبرداری
  • قیمت ارزهای دیجیتال
  • ماشین حساب ارزهای دیجیتال
  • مقایسه قیمت در صرافی
No Result
مشاهده همه‌ی نتایج
میهن بلاکچین
No Result
مشاهده همه‌ی نتایج
میهن بلاکچین آموزش مقالات عمومی

کالبدشکافی اکسپلویت Balancer V2؛ چگونه خطایی کوچک در گِرد کردن منجر به بحرانی بزرگ شد؟

نگارش:‌رضا حضرتی
16 آبان 1404 - 22:00
در مقالات عمومی
زمان مطالعه: 9 دقیقه
0
فیچر اکسپلویت بالانسر

در روز دوشنبه، ساعت ۱۱:۱۶ به وقت تهران، سیستم مانیتورینگ Hypernative اولین نشانه‌های یک اکسپلویت (سوءاستفاده امنیتی) را که استخرهای پایدار ترکیبی (Composable Stable Pools) در Balancer V2 را هدف قرار داده بود، شناسایی کرد. تحلیل‌های بعدی تأیید کرد که این مشکل، استخرهای پایدار ترکیبی را در چندین شبکه از جمله اتریوم، بِیس (Base)، آوالانچ، جنوسیس (Gnosis)، براجین (Berachain)، پالیگان، سونیک (Sonic)، آربیتروم و آپتیمیزم تحت تأثیر قرار داده است. این حادثه محدود به استخرهای پایدار ترکیبی در Balancer V2 و فورک‌های آن در زنجیره‌های دیگر مانند BEX و Beets بود. Balancer V3 و تمام انواع دیگر استخرها تحت تأثیر قرار نگرفته‌اند.

تلاش‌های واکنش فوری با هماهنگی مشارکت‌کنندگان بالانسر، شرکای امنیتی و پاسخ‌دهندگان کلاه‌سفید آغاز شد که منجر به مهار اکسپلویت و بازیابی یا مسدودسازی بخشی از دارایی‌های آسیب‌دیده گردید. یک اتاق جنگ (War Room) هماهنگی لازم برای مهار، اطلاع‌رسانی و بازیابی در سراسر شبکه‌ها را بر عهده گرفت. استخرهای CSPv6 به حالت بازیابی (Recovery Mode) منتقل شدند، مسدودسازی دارایی‌ها با همکاری شرکا اجرا شد و تعامل با کلاه‌سفیدها تحت چارچوب «پناهگاه امن» SEAL ادامه یافت.

به گزارش میهن بلاکچین، اگرچه ارقام نهایی خسارت همچنان در دست بررسی است، اما این اکسپلویت قابل توجه بود. گزارش کامل تحلیلی پسارویداد (Post-mortem) پس از تکمیل تمام بررسی‌های فنی و حقوقی منتشر خواهد شد.

آنچه در این مطلب می‌خوانید

Toggle
  • علت اولیه
  • تحلیل فنی اولیه
  • تحلیل فنی
  • سخن پایانی

علت اولیه

خزانه (Vault) نسخه ۲ (V2) از دو نوع سوآپ (Swap) ساده و دسته‌ای (Batch) پشتیبانی می‌کند. سوآپ دسته‌ای اجازه می‌دهد تا چندین عملیات در یک تراکنش واحد ترکیب شوند که این امر از انتقال توکن‌های میانی جلوگیری کرده و باعث صرفه‌جویی قابل توجهی در کارمزد گس (Gas) می‌شود.

فیچر هک و اکسپلویت

یک ویژگی کلیدی سوآپ دسته‌ای، تسویه با تأخیر (Deferred Settlement) است که در آن کال‌کنندگان می‌توانند عملاً توکن‌ها را وام آنی (Flashloan) بگیرند تا سوآپ‌ها را انجام دهند، به شرطی که همه‌چیز در انتها تسویه شود. برای استخرهای پایدار ترکیبی، توکن‌های رسید تأمین نقدینگی (BPT) مانند توکن‌های معمولی رفتار می‌شوند که این امر اجازه می‌دهد محدودیت حداقل عرضه استخر دور زده شود و سطح نقدینگی در استخر به مقادیر بسیار پایینی برسد.

اکسپلویت از جهت گِرد کردن (Rounding Direction) در تابع upscale که بر سوآپ‌های نوع EXACT_OUT در استخرهای پایدار ترکیبی تأثیر می‌گذاشت، نشأت گرفت. این تابع زمانی که فاکتورهای مقیاس‌بندی مقادیر غیرصحیح هستند (شرایطی که هنگام لحاظ شدن نرخ توکن‌ها در آن فاکتورهای مقیاس‌بندی رخ می‌دهد)، اعداد را به پایین گِرد می‌کند. مهاجمان توانستند از این رفتار نادرست گِرد کردن در ترکیب با قابلیت batchSwap (سوآپ دسته‌ای) سوءاستفاده کنند تا موجودی استخر را دستکاری کرده و ارزش را از آن خارج سازند. در بسیاری از موارد، وجوه اکسپلویت شده پیش از آنکه در تراکنش‌های بعدی برداشت شوند، به‌عنوان موجودی‌های داخلی (Internal Balances) در داخل Vault باقی مانده بودند.

دامنه تأثیر

  • استخرهای Composable Stable v5 که پنجره‌های زمانی توقف (Pause windows) آن‌ها منقضی شده بود، عمدتاً تحت تأثیر قرار گرفتند.
  • استخرهای Composable Stable v6 به‌طور خودکار توسط Hypernative متوقف و محافظت شدند.
  • بر اساس بازبینی فعلی و بازبینی‌های خارجی، Balancer v3 و انواع استخرهای غیرپایدار v2 تحت تأثیر قرار نگرفته‌اند.

خسارت

بالانسر در حالی که تحقیقات همچنان فعال است، اولویت را به کاهش خسارت و بازیابی وجوه داده‌ است. برآوردهای خسارت همچنان با هماهنگی تیم‌های امنیتی خارجی و پاسخ‌دهندگان کلاه‌سفید در حال تطبیق و بررسی در زنجیره‌ها، انواع استخرها و آدرس‌های مختلف است.

آنها یک دفتر کل داخلی یکپارچه برای ردیابی موارد زیر نگهداری می‌کنند:

جریان‌های مالی اکسپلویت‌کننده، نجات‌های انجام‌شده توسط کلاه‌سفیدها، دارایی‌های مسدود شده، وجوه بازیابی‌شده و برداشت‌های پروتکل/کاربر. این موارد به‌طور مداوم در حال راستی‌آزمایی هستند.

مقادیر نهایی تنها پس از اعتبارسنجی چندجانبه (بررسی ردپای آن‌چین، تأییدیه‌های شرکا و تطبیق موجودی‌های بلوک به بلوک) منتشر خواهند شد.

هرگونه ارقامی که به‌صورت عمومی منتشر می‌شود، تأیید نشده است و نباید رسمی تلقی شود.

گزارش بازبینی تأیید شده از استخرهای آسیب‌دیده و دارایی‌های بازیابی‌شده، شامل متدولوژی و مراجع تراکنش‌ها، در گزارش نهایی پسارویداد منتشر خواهد شد.

اقدامات کاهشی (Mitigations)

علی‌رغم گستردگی اکسپلویت، چندین واکنش سریع، مجموع زیان‌ها را کاهش داد. موارد زیر نشان‌دهنده اقدامات تأیید شده است؛ هر جا مبالغی ذکر شده، به‌صورت موقت و برای آگاهی از وضعیت است. تمرکز بالانسر همچنان بر کاهش خسارت و بازیابی با هماهنگی فعال شرکا و پاسخ‌دهندگان کلاه‌سفید است.

  • پناهگاه امن کلاه‌سفید SEAL (BIP-726، اکتبر ۲۰۲۴): چارچوب قانونی از پیش پذیرفته‌شده، امکان مداخله سریع و هماهنگ کلاه‌سفیدها را در طول حادثه فراهم کرد.
  • Hypernative — اتوماسیون توقف اضطراری: در ساعت ۰۸:۰۶ UTC، کنترل‌های اضطراری CSPv6 فعال شدند؛ تا ساعت ۰۸:۰۷ UTC، تمام استخرهای CSPv6 در شبکه‌های آسیب‌دیده متوقف شدند و از گسترش بیشتر خسارت جلوگیری شد.
  • تمام استخرهای قابل توقف CSPv6 متوقف و در حالت بازیابی هستند: این شامل استخرهای با ارزش قفل شده پایین (TVL) که زیر آستانه‌های گزارش‌دهی قبلی بودند نیز می‌شود.
  • کارخانه (Factory) CSPv6 غیرفعال شد: امکان ایجاد استخرهای آسیب‌پذیر جدید تا زمان رفع مشکل وجود ندارد.
  • Gauges (مربوط به پاداش‌ها) برای استخرهای آسیب‌دیده متوقف شدند: انتشار توکن و مشوق‌ها برای حفظ BAL و مشوق‌های شرکا متوقف شد.
  • امکان خروج LPها (تأمین‌کنندگان نقدینگی) با توقف CSPv6 فراهم شد: LPهای عمده از جمله Crypto.com (۸۰۰ هزار دلار، cdcETH/wstETH) و Ether.fi (۱.۰۶۱ میلیون دلار، eBTC/wBTC) با خیال راحت نقدینگی خود را خارج کردند.
  • بازیابی Stakewise: ۵٬۰۴۱ osETH (معادل ۱۹ میلیون دلار) و ۱۳٬۴۹۵ osGNO (حدود ۱.۷ تا ۲ میلیون دلار) بازپس‌گیری شد (تقریباً ۷۳.۵٪ از osETH به سرقت رفته) تا به‌صورت نسبی (pro-rata) به کاربران آسیب‌دیده بازگردانده شود.
  • اعتبارسنج‌های (Validators) براجین — توقف شبکه: عملیات زنجیره برای مهار قرار گرفتن در معرض خطر مربوط به Balancer v2 در BEX متوقف شد؛ اقدامات اضطراری هاردفورک آغاز شد.
  • Sonic Labs — مسدودسازی اضطراری: Sonic Labs آدرس‌های مشکوک مهاجم را مسدود کرد و مانع انتقال یا تبدیل وجوه مرتبط با Beets (فورک Balancer v2 فعال در Sonic) شد.
  • بات MEV در شبکه Base — مشارکت در بازیابی: حدود ۱۵۰ هزار دلار در چندین تراکنش بازیابی شد.
  • بازیابی کلاه‌سفید BitFinding: تیم BitFinding حدود ۶۰۰ هزار دلار از دارایی‌ها را در شبکه اصلی رهگیری و بازپس‌گیری کرد.
  • Monerium — مسدودسازی EURe: حدود ۱.۳ میلیون EURe در Vault مسدود شد تا از انتقال بیشتر در پلتفرم‌های آسیب‌دیده جلوگیری شود.
  • Gnosis — محدودیت‌های بریج (Bridge): با هماهنگی تیم Monerium، کنترل‌های موقتی برای محدود کردن فعالیت بریج خروجی از زنجیره Gnosis اعمال شد تا ریسک انتشار بین زنجیره‌ای کاهش یابد.
  • ارتباط SEAL و شرکا با مهاجم (مهاجمان): تعامل مستمر تحت چارچوب SEAL برای پیگیری بازگشت وجوه در حال انجام است.
  • مشارکت‌کنندگان کلاه‌سفید دیگر درگیر شدند: تیم‌های متعددی (از جمله SNP و دیگران) در حال کمک به تریاژ (اولویت‌بندی)، نجات و مسیرهای بازگشت وجوه هستند.

بالانسر به همکاری با شرکا، محققان، صرافی‌ها و تیم‌های کلاه‌سفید برای بازیابی وجوه ادامه می‌دهد. گزارش جامع پسارویداد با مجموع مبالغ اعتبارسنجی‌شده، مراجع تراکنش‌ها و جریان‌های بازیابی/توزیع پس از تکمیل اعتبارسنجی و تطبیق توسط شرکا منتشر خواهد شد.

انجام سوآپ و عملیات نقدینگی در استخرهای تأثیرناپذیر کاملاً امن باقی می‌ماند. وکتور اکسپلویت فقط برای انواع خاصی از استخرهای پایدار ترکیبی در Balancer v2 اعمال می‌شود. Balancer V3 و تمام انواع دیگر استخرهای V2 تحت تأثیر قرار نگرفته‌اند و به‌طور عادی به کار خود ادامه می‌دهند.

برای کاربران در استخرهای متوقف‌شده Composable Stable v6، حالت بازیابی (Recovery Mode) فعال شده است تا امکان برداشت متناسب دارایی‌های پایه فراهم شود. استخرهای Composable Stable v5 تحت تأثیر قرار گرفته‌اند و همچنان تحت بررسی هستند؛ کاربران باید از تعامل با این قراردادها تا زمان صدور تأییدیه رسمی خودداری کنند.

تمام اطلاعات و دستورالعمل‌های تأیید شده منحصراً از طریق کانال‌های رسمی Balancer به اشتراک گذاشته خواهد شد.

بازیابی جاری و گام‌های بعدی

بازیابی و تطبیق (Reconciliation) در سراسر شبکه‌های آسیب‌دیده با شرکای امنیتی، بازبینان و پاسخ‌دهندگان کلاه‌سفید ادامه دارد. ردیابی دارایی‌ها و بازیابی قانونی به‌طور مشترک توسط SEAL و zeroShadow تحت چارچوب پناهگاه امن Balancer هدایت می‌شود تا مسیری شفاف و قانونی برای بازگشت وجوه تضمین شود.

گزارش نهایی پسارویداد شامل موارد زیر خواهد بود:

  • علت ریشه‌ای و توضیح در سطح اینواریانت (invariant).
  • ترتیب اقدامات کاهشی و متدولوژی بازیابی.
  • نتایج اعتبارسنجی و تطبیق توسط شرکا.
  • توصیه‌هایی برای مهاجرت به Balancer V3.

تحلیل فنی اولیه

در تاریخ ۳ نوامبر ۲۰۲۵، پروتکل Balancer توسط هکرها در چندین زنجیره عمومی مانند آربیتروم و اتریوم مورد حمله قرار گرفت که منجر به زیان ۱۲۰ میلیون دلاری دارایی‌ها شد. هسته این حمله ناشی از یک آسیب‌پذیری دوگانه‌ی از دست رفتن دقت (Precision loss) و دستکاری اینواریانت (Invariant manipulation) بود.

hack

مشکل اصلی در این حمله به منطق پروتکل برای مدیریت تراکنش‌های کوچک بازمی‌گردد. زمانی که کاربر یک مبادله کوچک انجام می‌دهد، پروتکل تابع _upscaleArray را فراخوانی می‌کند که از mulDown برای گرد کردن مقدار به پایین استفاده می‌کند. اگر موجودی در تراکنش و مقدار ورودی هر دو در یک مرز گرد کردن خاصی (مانند محدوده ۸ تا ۹ wei) قرار گیرند، خطای دقت نسبی قابل توجهی رخ می‌دهد.

خطای دقت به محاسبه مقدار اینواریانت (D) در پروتکل انتشار یافت و باعث شد که مقدار D به‌طور غیرعادی کاهش یابد. تغییر در مقدار D مستقیماً قیمت BPT (توکن استخر Balancer) را در پروتکل Balancer کاهش داد. هکرها از این قیمت سرکوب‌شده BPT سوءاستفاده کردند تا از طریق مسیرهای تراکنشی از پیش طراحی‌شده، آربیتراژ را تکمیل کنند و در نهایت باعث زیان عظیم دارایی شوند.

لینک اکسپلویت آسیب‌پذیری:

https://etherscan.io/tx/0x6ed07db1a9fe5c0794d44cd36081d6a6df103fab868cdd75d581e3bd23bc9742

لینک انتقال دارایی:

https://etherscan.io/tx/0xd155207261712c35fa3d472ed1e51bfcd816e616dd4f517fa5959836f5b48569

تحلیل فنی

نقطه ورود حمله، قرارداد Balancer: Vault (خزانه) و تابع ورودی متناظر، تابع batchSwap است که در داخل خود onSwap را برای انجام مبادلات توکن فراخوانی می‌کند.

 function onSwap(
  SwapRequest memory swapRequest,
  uint256[] memory balances,
  uint256 indexIn,
  uint256 indexOut
 ) external override onlyVault(swapRequest.poolId) returns (uint256) {
  _beforeSwapJoinExit();

  _validateIndexes(indexIn, indexOut, _getTotalTokens());
  uint256[] memory scalingFactors = _scalingFactors();

  return
  swapRequest.kind == IVault.SwapKind.GIVEN_IN
  ? _swapGivenIn(swapRequest, balances, indexIn, indexOut, scalingFactors)
  : _swapGivenOut(swapRequest, balances, indexIn, indexOut, scalingFactors);
 }

از پارامترها و محدودیت‌های تابع، می‌توان به چند اطلاعات دست یافت:

  1. مهاجمان باید این تابع را از طریق Vault فراخوانی کنند؛ آن‌ها نمی‌توانند مستقیماً آن را فراخوانی کنند.
  2. تابع در داخل خود _scalingFactors() را برای به دست آوردن فاکتورهای مقیاس‌بندی جهت عملیات مقیاس‌بندی فراخوانی می‌کند.
  3. عملیات مقیاس‌بندی یا در _swapGivenIn یا _swapGivenOut انجام می‌شود.

تحلیل الگوی حمله

در مدل استخر پایدار Balancer، قیمت BPT یک نقطه مرجع مهم است که تعیین می‌کند کاربر چه تعداد BPT دریافت می‌کند و به ازای هر BPT چه مقدار دارایی دریافت می‌شود.

قیمت BPT = D / totalSupply

که در آن D = اینواریانت (invariant)، برگرفته از مدل StableSwap پلتفرم Curve.

در محاسبه مبادله استخر:

 // StableMath._calcOutGivenIn
 function _calcOutGivenIn(
  uint256 amplificationParameter,
  uint256[] memory balances,
  uint256 tokenIndexIn,
  uint256 tokenIndexOut,
  uint256 tokenAmountIn,
  uint256 invariant
 ) internal pure returns (uint256) {
  /**********************************************************************************************************
  // outGivenIn token x for y - polynomial equation to solve //
  // ay = amount out to calculate //
  // by = balance token out //
  // y = by - ay (finalBalanceOut) //
  // D = invariant DD^(n+1) //
  // A = amplification coefficient y^2 + ( S + ---------- - D) * y - ------------- = 0 //
  // n = number of tokens (A * n^n) A * n^2n * P //
  // S = sum of final balances but y //
  // P = product of final balances but y //
  **************************************************************************************************************/

  // Amount out, so we round down overall.
  balances[tokenIndexIn] = balances[tokenIndexIn].add(tokenAmountIn);

  uint256 finalBalanceOut = _getTokenBalanceGivenInvariantAndAllOtherBalances(
  amplificationParameter,
  balances,
  invariant, // با استفاده از D قدیمی
  tokenIndexOut
  );

  // No need to use checked arithmetic since `tokenAmountIn` was actually added to the same balance right before
  // calling `_getTokenBalanceGivenInvariantAndAllOtherBalances` which doesn't alter the balances array.
  balances[tokenIndexIn] = balances[tokenIndexIn] - tokenAmountIn;

  return balances[tokenIndexOut].sub(finalBalanceOut).sub(1);
 }

بخشی که به‌عنوان معیار قیمت BPT عمل می‌کند، مقدار ثابت D است؛ یعنی دستکاری قیمت BPT نیازمند دستکاری D است. بیایید فرآیند محاسبه D را تحلیل کنیم:

 // StableMath._calculateInvariant
 function _calculateInvariant(uint256 amplificationParameter, uint256[] memory balances)
  internal
  pure
  returns (uint256)
 {
  /**********************************************************************************************
  // invariant //
  // D = invariant D^(n+1) //
  // A = amplification coefficient A n^n S + D = AD n^n + ----------- //
  // S = sum of balances n^n P //
  // P = product of balances //
  // n = number of tokens //
  **********************************************************************************************/

  // همیشه به پایین گرد کن، تا با محاسبات Vyper (که همیشه کوتاه می‌کند) مطابقت داشته باشد.

  uint256 sum = 0; // S in the Curve version
  uint256 numTokens = balances.length;
  for (uint256 i = 0; i < numTokens; i++) {
  sum = sum.add(balances[i]); // balances مقدار مقیاس‌بندی شده است
  }
  if (sum == 0) {
  return 0;
  }

  uint256 prevInvariant; // Dprev in the Curve version
  uint256 invariant = sum; // D in the Curve version
  uint256 ampTimesTotal = amplificationParameter * numTokens; // Ann in the Curve version

  // محاسبه تکراری D...
  // محاسبه D بر دقت balances تأثیر می‌گذارد
  for (uint256 i = 0; i < 255; i++) {
  uint256 D_P = invariant;

  for (uint256 j = 0; j < numTokens; j++) {
  // (D_P * invariant) / (balances[j] * numTokens)
  D_P = Math.divDown(Math.mul(D_P, invariant), Math.mul(balances[j], numTokens));
  }

  prevInvariant = invariant;

  invariant = Math.divDown(
  Math.mul(
  // (ampTimesTotal * sum) / AMP_PRECISION + D_P * numTokens
  (Math.divDown(Math.mul(ampTimesTotal, sum), _AMP_PRECISION).add(Math.mul(D_P, numTokens))),
  invariant
  ),
  // ((ampTimesTotal - _AMP_PRECISION) * invariant) / _AMP_PRECISION + (numTokens + 1) * D_P
  (
  Math.divDown(Math.mul((ampTimesTotal - _AMP_PRECISION), invariant), _AMP_PRECISION).add(
  Math.mul((numTokens + 1), D_P)
  )
  )
  );

  if (invariant > prevInvariant) {
  if (invariant - prevInvariant <= 1) {
  return invariant;
  }
  } else if (prevInvariant - invariant <= 1) {
  return invariant;
  }
  }

  _revert(Errors.STABLE_INVARIANT_DIDNT_CONVERGE);
 }

در کد بالا، محاسبه D به آرایه balances (موجودی‌های) مقیاس‌بندی‌شده بستگی دارد. این بدان معناست که عملیاتی برای تغییر دقت این موجودی‌ها مورد نیاز است که منجر به خطا در محاسبه D می‌شود.

علت ریشه‌ای از دست رفتن دقت

 // BaseGeneralPool._swapGivenIn
 function _swapGivenIn(
  SwapRequest memory swapRequest,
  uint256[] memory balances,
  uint256 indexIn,
  uint256 indexOut,
  uint256[] memory scalingFactors
 ) internal virtual returns (uint256) {
  // Fees are subtracted before scaling, to reduce the complexity of the rounding direction analysis.
  swapRequest.amount = _subtractSwapFeeAmount(swapRequest.amount);

  _upscaleArray(balances, scalingFactors); // نکته کلیدی: افزایش مقیاس موجودی
  swapRequest.amount = _upscale(swapRequest.amount, scalingFactors[indexIn]);

  uint256 amountOut = _onSwapGivenIn(swapRequest, balances, indexIn, indexOut);

  // توکن‌های amountOut در حال خروج از استخر هستند، بنابراین به پایین گرد می‌کنیم.
  return _downscaleDown(amountOut, scalingFactors[indexOut]);
 }

عملیات مقیاس‌بندی:

 // ScalingHelpers.sol
 function _upscaleArray(uint256[] memory amounts, uint256[] memory scalingFactors) pure {
  uint256 length = amounts.length;
  InputHelpers.ensureInputLengthMatch(length, scalingFactors.length);

  for (uint256 i = 0; i < length; ++i) {
  amounts[i] = FixedPoint.mulDown(amounts[i], scalingFactors[i]); // گرد کردن به پایین
  }
 }

 // FixedPoint.mulDown
 function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {
  uint256 product = a * b;
  _require(a == 0 || product / a == b, Errors.MUL_OVERFLOW);

  return product / ONE; // گرد کردن به پایین: کوتاه کردن مستقیم
 }

همانطور که در بالا نشان داده شده است، هنگام استفاده از _upscaleArray، اگر موجودی بسیار کوچک باشد (مثلاً ۸-۹ wei)، گرد کردن به پایین mulDown منجر به از دست رفتن قابل توجه دقت می‌شود.

جزئیات فرآیند حمله

فاز ۱: تنظیم در مرز گرد کردن

  • مهاجم: BPT → cbETH
  • هدف: تنظیم موجودی cbETH در مرز گرد کردن (مثلاً ختم شدن به ۹).

فرض کنید حالت اولیه:

  • موجودی cbETH (اصلی): ...00000000009 wei (رقم آخر ۹ است)

فاز ۲: فعال‌سازی از دست رفتن دقت (آسیب‌پذیری اصلی)

  • مهاجم: wstETH (8 wei) → cbETH

قبل از مقیاس‌بندی:

  • موجودی cbETH: ...000000000009 wei
  • ورودی wstETH: 8 wei

اجرای _upscaleArray:

 // مقیاس‌بندی cbETH: 9 * 1e18 / 1e18 = 9
 // اما اگر مقدار واقعی ۹.۵ باشد، به دلیل گرد کردن به پایین، ۹ می‌شود.
 scaled_cbETH = floor(9.5) = 9
 
 // از دست رفتن دقت: ۰.۵ / ۹.۵ = ۵.۳٪ خطای نسبی
 // محاسبه مبادله:
 // ورودی (wstETH): 8 wei (مقیاس‌بندی شده)
 // موجودی (cbETH): 9 (نادرست، باید ۹.۵ باشد)
 
 // از آنجا که cbETH کم‌ ارزش‌گذاری شده، موجودی جدید محاسبه‌شده نیز کم‌ ارزش‌گذاری می‌شود،
 // که منجر به خطا در محاسبه D می‌گردد.
 D_original = f(9.5, ...)
 D_new = f(9, ...) < D_original

فاز ۳: سود بردن از قیمت سرکوب‌شده BPT

  • مهاجم: دارایی پایه → BPT

در این زمان:

  • D_new = D_original - ΔD
  • قیمت BPT = D_new / totalSupply < D_original / totalSupply

مهاجمان با دارایی‌های پایه کمتر، همان تعداد BPT را به دست می‌آورند.

یا دارایی‌های پایه یکسان را با BPTهای بیشتری مبادله می‌کنند.

مهاجم در بالا از Batch Swap (سوآپ دسته‌ای) برای انجام چندین سوآپ در یک تراکنش واحد استفاده کرد:

  1. مبادله اول: BPT → cbETH (تنظیم موجودی)
  2. مبادله دوم: wstETH (8) → cbETH (فعال‌سازی از دست رفتن دقت)
  3. مبادله سوم: دارایی‌های پایه → BPT (کسب سود)

این سوآپ‌ها همگی در یک تراکنش batchSwap قرار دارند و از وضعیت موجودی یکسانی استفاده می‌کنند، اما _upscaleArray برای تغییر آرایه balances برای هر سوآپ فراخوانی می‌شود.

فقدان مکانیزم بازخوانی (Callback)

فرآیند اصلی توسط Vault آغاز می‌شود، پس چگونه این امر منجر به انباشت از دست رفتن دقت می‌شود؟ پاسخ در مکانیزم انتقال آرایه balances نهفته است.

 // تابع منطقی زمانی که Vault تابع onSwap را فراخوانی می‌کند: _processGeneralPoolSwapRequest
 private
 returns (uint256 amountCalculated)
 {
  // ... (بخش‌هایی از کد برای خواندن موجودی‌ها)

  uint256 tokenAmount = poolBalances.length();
  uint256[] memory currentBalances = new uint256[](tokenAmount);

  request.lastChangeBlock = 0;
  for (uint256 i = 0; i < tokenAmount; i++) {
  // ...
  bytes32 balance = poolBalances.unchecked_valueAt(i);

  currentBalances[i] = balance.total(); // خواندن از حافظه (storage)
  request.lastChangeBlock = Math.max(request.lastChangeBlock, balance.lastChangeBlock());

  // ... (بخش‌هایی از کد)
  }
  
  // انجام سوآپ
  // فراخوانی بازخوانی (callback) درخواست سوآپ و محاسبه موجودی‌های جدید برای 'token in' و 'token out' پس از سوآپ
  amountCalculated = pool.onSwap(request, currentBalances, indexIn, indexOut);
  (uint256 amountIn, uint256 amountOut) = _getAmounts(request.kind, request.amount, amountCalculated);
  tokenInBalance = tokenInBalance.increaseCash(amountIn);
  tokenOutBalance = tokenOutBalance.decreaseCash(amountOut);

  // به‌روزرسانی حافظه (storage)
  poolBalances.unchecked_setAt(indexIn, tokenInBalance);
  poolBalances.unchecked_setAt(indexOut, tokenOutBalance);
 }

با تحلیل کد بالا، اگرچه Vault هر بار که onSwap فراخوانی می‌شود، یک آرایه currentBalances جدید ایجاد می‌کند، اما در Batch Swap:

  1. پس از مبادله اول، موجودی به‌روزرسانی می‌شود (اما مقدار به‌روز شده ممکن است به دلیل از دست رفتن دقت، نادرست باشد).
  2. مبادله دوم، محاسبه را بر اساس نتیجه مبادله اول ادامه می‌دهد.
  3. از دست رفتن انباشته دقت در نهایت منجر به کاهش قابل توجه مقدار اینواریانت D می‌شود.

مسائل کلیدی:

 // BaseGeneralPool._swapGivenIn
 function _swapGivenIn(
  SwapRequest memory swapRequest,
  uint256[] memory balances,
  uint256 indexIn,
  uint256 indexOut,
  uint256[] memory scalingFactors
 ) internal virtual returns (uint256) {
  // ...
  _upscaleArray(balances, scalingFactors); // تغییر آرایه درجا (in place).
  // ...
  uint256 amountOut = _onSwapGivenIn(swapRequest, balances, indexIn, indexOut);
  // ...
 }

اگرچه Vault هر بار یک آرایه جدید ارسال می‌کند، اما:

۱. اگر موجودی بسیار کوچک باشد (۸-۹ wei)، از دست رفتن دقت در طول مقیاس‌بندی قابل توجه است.

۲. در Batch Swap، سوآپ‌های بعدی محاسبات را بر اساس موجودی که قبلاً دقت خود را از دست داده ادامه می‌دهند.

۳. بررسی نشد که آیا تغییر در مقدار اینواریانت D در محدوده معقولی بوده است یا خیر.

سخن پایانی

دلایل حمله به Balancer را می‌توان به شرح زیر خلاصه کرد:

۱. تابع مقیاس‌بندی از گرد کردن به پایین استفاده می‌کند: _upscaleArray از mulDown برای مقیاس‌بندی استفاده می‌کند که هنگام بسیار کوچک بودن موجودی (مانند ۸-۹ wei) باعث از دست رفتن قابل توجه دقت نسبی می‌شود.

۲. محاسبه مقدار اینواریانت به دقت حساس است: محاسبه مقدار اینواریانت D به آرایه balances مقیاس‌بندی‌شده بستگی دارد و از دست رفتن دقت مستقیماً به محاسبه D منتقل می‌شود و آن را کوچک‌تر می‌کند.

۳. فقدان اعتبارسنجی تغییرات در مقادیر اینواریانت: در طول فرآیند مبادله، بررسی نشد که آیا تغییرات در مقدار اینواریانت D در محدوده معقولی قرار دارد یا خیر که این امر به مهاجمان اجازه داد تا به‌طور مکرر از خطای دقت برای کاهش قیمت BPT سوءاستفاده کنند.

۴. انباشت از دست رفتن دقت در سوآپ دسته‌ای (Batch Swap): در یک batchSwap واحد، از دست رفتن دقت ناشی از چندین سوآپ انباشته شده و در نهایت به زیان‌های مالی هنگفت تبدیل می‌شود.

این دو مسئله (از دست رفتن دقت و فقدان اعتبارسنجی) در ترکیب با طراحی دقیق شرایط مرزی توسط مهاجم، منجر به این زیان شد.

تگ: صرافی ارز دیجیتالهک
اشتراک‌گذاریتوئیت

نوشته‌های مشابه

برایان آرمسترانگ: صرافی کوین بیس از شبکه لایتنینگ پشتیبانی خواهد کرد
تحلیل فاندامنتال

کوین‌بیس از وزارت خزانه‌داری خواست روح قانون GENIUS را تحریف نکند

15 آبان 1404 - 17:00
27
رابین هود بیت کوین
تحلیل فاندامنتال

رابینهود، درخشان‌تر از همیشه؛ جهش ۳۰۰ درصدی درآمد‌های کریپتویی در سه‌ماهه سوم سال ۲۰۲۵

15 آبان 1404 - 12:00
40
لازاروس کره شمالی مسئول هک ۱۰۰ میلیون دلاری هک هارمونی
اخبار عمومی

پشت لبخند فریلنسرها؛ وقتی مأموران کره شمالی در پروژه‌های جهانی نفوذ می‌کنند

14 آبان 1404 - 18:00
41
ووبلاکچین: سقوط ۱۱ اکتبر نتیجه حمله هدفمند به سیستم مارجین بایننس بود
تحلیل فاندامنتال

زمزمه‌های شکایت از بایننس بی‌اساس از آب درآمد؛ واکنش تند مدیرعامل وینترمیوت

13 آبان 1404 - 21:00
149
پروژه‌های کلاهبرداری

هک ۱۰۰ میلیون دلاری بالانسر؛ اعتبار حسابرسی‌های دیفای زیر سؤال رفت

13 آبان 1404 - 17:00
43
فیچر هک و اکسپلویت
اخبار فوری

براداشت فوری براچین برای مقابله با آسیب‌پذیری Balancer V2

13 آبان 1404 - 11:43
24
اشتراک
اطلاع از
0 دیدگاه
جدید ترین
قدیمی ترین محبوب ترین
Inline Feedbacks
View all comments

آموزش

فیچر اکسپلویت بالانسر
مقالات عمومی

کالبدشکافی اکسپلویت Balancer V2؛ چگونه خطایی کوچک در گِرد کردن منجر به بحرانی بزرگ شد؟

16 آبان 1404 - 22:00
0
فیچر پاول دورف - پاول دوروف
مقالات عمومی

پاول دورف کیست؟ نگاهی به زندگی‌نامه بنیان‌گذار تلگرام

16 آبان 1404 - 20:00
32
bitcoin
مقالات عمومی

عرضه اولیه پنهان بیت کوین؛ چرا این فاز تثبیت همان چیزی نیست که فکر می‌کنید؟

16 آبان 1404 - 16:00
121
فیچر نومنال
مقالات عمومی

رایانه ترمودینامیکی چیست؟ تراشه‌ها با نومنال به مغز انسان شبیه‌تر می‌شوند!

16 آبان 1404 - 12:00
42
بیش از ۲ میلیارد دلار از ETFهای اسپات بیت کوین در ۶ روز خارج شد!
مقالات عمومی

وابستگی پنهان آلت‌کوین‌ها به بیت کوین؛ تحلیلی از ریسک سیستماتیک بازار کریپتو

15 آبان 1404 - 22:00
121
بای بک و توکن سوزی فیچر
مقالات عمومی

چرا بعضی توکن‌سوزی‌ها شکست می‌خورند؟ نگاهی موشکافانه به این موضوع

14 آبان 1404 - 22:00
117

پیشنهاد سردبیر

تاخیر برداشت در اکسکوینو

بررسی مشکلات تاخیر برداشت ریالی و رمزارزی در صرافی اکسکوینو؛ دلایل، پیامدها و راهکارها

5 مرداد 1404 - 17:00
8608

کلاهبرداری با کیف پول چند امضایی چیست و چگونه از آن در امان بمانیم؟

حمله انتقال صفر (Zero-Transfer)؛ راهنمای کامل شناسایی و مقابله با تهدید کیف پول‌های رمزارزی

تاثیر تصویب قانون GENIUS بر ریسک فریز و مسدود شدن دارایی‌های تتر ایرانی‌ها؛ چه باید کرد؟

اشتباه ۶۰ هزار دلاری کاربر بیت کوین در پرداخت کارمزد؛ مراقب باشید این اشتباه را تکرار نکنید!

تسلیم یا کاپیتولاسیون (Capitulation) در کریپتو چیست؟ نشانه ترس یا فرصتی برای ورود به بازار؟

  • خانه
  • قیمت ارز
  • صرافی ها
  • ماشین حساب
No Result
مشاهده همه‌ی نتایج
  • اخبار
    • همه
    • رمزارز در ایران
    • اخبار بیت کوین
    • اخبار اتریوم
    • اخبار آلتکوین
    • اخبار بلاکچین
    • اخبار عمومی
    • اطلاعیه صرافی‌های داخلی
  • تحلیل
    • همه
    • تحلیل آنچین
    • تحلیل اقتصادی
    • تحلیل تکنیکال
    • تحلیل فاندامنتال
  • آموزش
    • همه
    • کریپتو پدیا
    • کریپتو کده
    • دیفای
    • سرمایه گذاری
    • آموزش همه صرافی های ارز دیجیتال
    • ترید
    • کیف پول
    • بازی
    • استخراج
    • NFT
    • مقالات عمومی
  • ایردراپ
  • هک و کلاهبرداری
  • قیمت ارزهای دیجیتال
  • ماشین حساب ارزهای دیجیتال
  • مقایسه قیمت در صرافی

© 2025 - تمامی حقوق مادی و معنوی این وبسایت نزد میهن بلاکچین محفوظ است

سرویس‌ها
لیست قیمت ارزهای دیجیتال مقایسه قیمت صرافی‌ها مقایسه ویژگی صرافی‌ها ماشین حساب ارزهای دیجیتال مقایسه رمزارز‌ها
خبر و آموزش
اخبار آموزش ویدیو پیشنهاد سردبیر
میهن بلاکچین
درباره ما ارتباط با ما تبلیغات و همکاری تجاری قوانین و مقررات سیاست های حریم خصوصی فرصت های شغلی
تگ‌های پربازدید
قانون گذاری سرمایه‌ گذاری افراد معروف صرافی ارز دیجیتال دوج‌کوین بیت‌کوین استیبل کوین رمزارز در ایران پیش بینی بازار تکنولوژی بلاک چین اتریوم ‌کاردانو شیبا هک و کلاهبرداری
سرویس‌ها
لیست قیمت ارزهای دیجیتال مقایسه قیمت صرافی‌ها مقایسه ویژگی صرافی‌ها ماشین حساب ارزهای دیجیتال مقایسه رمزارز‌ها
خبر و آموزش
اخبار آموزش ویدیو پیشنهاد سردبیر
میهن بلاکچین
درباره ما ارتباط با ما تبلیغات و همکاری تجاری قوانین و مقررات سیاست های حریم خصوصی فرصت های شغلی
تگ‌های پربازدید
قانون گذاری سرمایه‌ گذاری افراد معروف صرافی ارز دیجیتال دوج‌کوین بیت‌کوین استیبل کوین رمزارز در ایران پیش بینی بازار تکنولوژی بلاک چین اتریوم ‌کاردانو شیبا هک و کلاهبرداری
میهن بلاکچین دست در دست، بی‌نهایت برای میهن

© 2025 - تمامی حقوق مادی و معنوی این وبسایت نزد میهن بلاکچین محفوظ است.