خمسة ملايين USDT مقابل 35 ألف دولار AAVE: كيف حدثت الكارثة؟ ومن يجب أن نلوم؟

هذه المقالة من: @Ehsan1579

ترجمة|Odaily Planet Daily(@OdailyChina);مترجم| Ethan(__@ethanzhang_web 3)

بالنظر فقط إلى عنوان الحدث، قد يخطئ الكثيرون في الظن بأنها هجمة استغلال ثغرة أمنية.

جوهر الحدث هو: شخص ما حول قيمة 50.4 مليون دولار من USDT إلى AAVE بقيمة 35.9 ألف دولار فقط في النهاية.

عندما سمعت عن الأمر لأول مرة، شعرت بالصدمة حقًا. لذلك، قمت بتحليل كامل للحدث من البداية إلى النهاية: تتبع المعاملات، مسار المحلل، استدعاءات العقود، الاحتياطيات التاريخية، بيانات التسوية، سير عمل الموصل، كود واجهة Aave، SDK لقروض CoW، بالإضافة إلى كود التوجيه الذي يحدد ما إذا كانت الأسعار “معقولة”.

**هذه ليست هجمة قرصنة.**​ بروتوكول Aave الأساسي لم يخطئ. تسوية CoW لم يخطئ. Uniswap لم يخطئ. SushiSwap لم يخطئ. المعاملة صحيحة، التوقيع صحيح، وكل العقود تنفذ وفقًا للكود بشكل صارم. ومع ذلك، تم تدمير معظم القيمة الاقتصادية، فقط لأن المسار المسموح به كان غريبًا جدًا.

السلسلة العامة لم تكن المشكلة، المشكلة في المسار.

في رأيي، إختزال الأمر إلى مجرد “خطأ في操作 المستخدم” هو موقف غير موضوعي وغير دقيق. صحيح أن المستخدم أنهى توقيع الأمر، لكن النظام البرمجي بأكمله سمح بعملية تتضمن تبديل ضمانات بقيمة تقارب 50 مليون دولار، وتمت عبر السعر، والتوقيع، وتخطيط المسار، وتنفيذها، وكل ذلك كان موجهاً إلى تجمع منخفض السيولة يملك حوالي 331 AAVE فقط. كان من المفترض أن يكون هذا مستحيلاً تمامًا، أو على الأقل يجب أن يتم اعتراضه ورده قبل بدء التسوية.

تتبع المعلومات الأساسية للمعاملة

الهاش الخاص بالمعاملة غير الطبيعية هو: 0x9fa9feab3c1989a33424728c23e6de07a40a26a98ff7ff5139f3492ce430801f، وتم تأكيدها في شبكة إيثيريوم الرئيسية عند البلوك رقم 24643151، مع مؤشر المعاملة 1، واستهلاك غاز قدره 3,780,570 وحدة، والمعاملة نفذت بنجاح. عنوان المحفظة المملوكة للطلب هو 0x98b9، وعنوان المحلل (المرسل للمعاملة) هو 0x3980، والذي تم تمييزه في بيانات مسابقة CoW باسم tsolver.

أولاً، يجب أن نفهم أن هذه ليست مجرد عملية تبادل USDT إلى AAVE على مستوى المحفظة فقط. العملة المباعة هي aEthUSDT، وهي شهادة إيداع USDT ذات فائدة على منصة Aave. العملة المشتراة هي aEthAAVE، وهي شهادة إيداع AAVE ذات فائدة على المنصة. إذن، في الواقع، هذه عملية تبديل ضمانات عبر نظام تسوية CoW وملحق القروض السريع الخاص به.

قبل المعاملة، كانت المحفظة تملك حوالي 50,432,693.075254 من aEthUSDT و0 من aEthAAVE. بعد المعاملة، لم يتبقَ لديها سوى 4.980399 من aEthUSDT، واستلمت 327.241335505966487788 من aEthAAVE. في الواقع، باعت تلك المحفظة تقريبًا جميع مراكزها.

البيانات الوصفية توضح بشكل أوضح أن المسار كان “سامًا” قبل التنفيذ. الطلب جاء من عملية aave-v3-interface-collateral-swap. واجهة برمجة التطبيقات الخاصة بـ CoW عرضته كطلب بيع موقع عليه توقيع، بينما البيانات الوصفية تشير إلى أنه تم استخدام سعر سوق مع انزلاق ذكي بنسبة 121 نقطة أساس لتبديل الضمانات. المبلغ الموقّع للبيع هو 50,432,688.41618 من aEthUSDT. الحد الأدنى للمبلغ المشتراة الموقع هو 324.949260918413591035 من aEthAAVE. وتم الدفع فعليًا بـ 327.241335505966487788 من aEthAAVE عند التسوية.

هذه نقطة مهمة جدًا. لم يكن من المتوقع أن يحصل الطلب على آلاف من AAVE، ثم يُدمر بشكل غامض أثناء التنفيذ. من البداية، كان مبنيًا حول نتائج مثل 300 AAVE تقريبًا.

السلسلة الكاملة لانهيار المسار

عند تتبع المعاملة، يتضح أن العملية كانت مباشرة وقاسية.

المصدر الرئيسي لتدفق الأموال هو عقد تسوية GPv2Settlement الخاص بـ CoW، والذي يبدأ برقم 0x9008. أولاً، عقد HooksTrampoline الذي يبدأ بـ 0x60bf، ينفذ عملية تفويض aEthUSDT، مما يسمح لمخزن CoW بالوصول إلى أصول المستخدم دون حاجة لتفويض منفصل؛ ثم، عقد GPv2VaultRelayer الذي يبدأ بـ 0xc92e، يسحب 50,432,688.41618 من aEthUSDT من محفظة المستخدم ويبدأ عملية التسوية. حتى هذه المرحلة، كل شيء يتوافق مع المنطق الطبيعي.

عقد التسوية يمنح صلاحية تنفيذ عمليات على aEthUSDT إلى عقد مساعد غير مفتوح المصدر يبدأ بـ 0xd524، ويتم استدعاؤه عبر محدد وظيفة 0x494b3137؛ ثم، ينقل هذا العقد صلاحية التنفيذ إلى عقد تنفيذي غير مفتوح المصدر يبدأ بـ 0x699c، وهكذا، تتكشف الصورة كاملة لعملية المسار غير الطبيعي.

أول استدعاء فعال يشير إلى عقد تجمع أموال Aave يبدأ بـ 0x87870، ويستخدم وظيفة السحب (withdraw) المحددة بـ 0x69328dec، ليقوم بتدمير aEthUSDT واسترداد USDT الأساسي؛ ثم، يتجه المسار إلى تجمع Uniswap V3 العميق لـ USDT/WETH، والذي يبدأ بـ 0x4e68، حيث يتم تبادل كامل 50,432,688.41618 USDT مقابل حوالي 17,957.810805702142342238 WETH.

هذه المرحلة من المعاملة كانت طبيعية تمامًا: سعر الصرف كان حوالي 2808.4 USDT مقابل 1 WETH، وهو مطابق للسوق في ذلك الوقت، ولا توجد مشكلة في السيولة، ولا انحراف في الحسابات، ولا شيء غير طبيعي في أول خطوة.

المشكلة تظهر في الخطوة الثانية، بمجرد أن ترى احتياطيات السيولة، يصبح الأمر واضحًا أكثر.

عند استلام 17,957.810805702142342238 WETH، يتم تحويلها بالكامل إلى عنوان 0xd75ea151a61d06868e31f8988d28dfe5e9df57b4، الذي ينتمي إلى تجمع SushiSwap V2 الخاص بـ AAVE/WETH.

لقد تحققت من بيانات الاحتياطيات التاريخية لهذا التجمع قبل وقوع المعاملة غير الطبيعية (عند البلوك رقم 24643150)، ووجدت أن الرصيد كان كالتالي:

331.631982538108027323 AAVE، و17.653276196397688066 WETH

هذه ليست أخطاء في الإدخال، بل حقائق ثابتة.

هذه المسار، حيث يتم ضخ حوالي 17958 WETH في تجمع صغير يملك فقط 17.65 WETH ويمتلك إجمالي AAVE يقدر بـ 331.63، هو أمر غير منطقي على الإطلاق. كمية WETH المدخلة تعادل حوالي 1017 مرة من احتياطيات التجمع.

هذه ليست مشكلة “انزلاق سعر مرتفع” أو “سيولة ضعيفة” بشكل عادي، بل مسار تنفيذ سوقي فائق السخافة، كأنه يجبر تجمع AMM صغير جدًا على استيعاب صفقة حجمها آلاف المرات أكبر من قدرته.

وبالفعل، قام تجمع SushiSwap بتنفيذ عملية Swap الأساسية، حيث استلم 17,957.810805702142342238 WETH، مقابل حوالي 331.305315608938235428 AAVE. بعد ذلك، تبقى في التجمع سيولة تقريبًا:

0.326666929169791895 AAVE، و17,975.464081898540030304 WETH

بمعنى آخر، حوالي 99.9% من مخزون AAVE في التجمع تم سحبه في تلك الخطوة.

وبحسب الاحتياطيات قبل المعاملة، فإن سعر AAVE المفترض كان حوالي 149.50 دولار، لكن السعر الفعلي عند التنفيذ كان حوالي 154,114.66 USDT مقابل 1 AAVE، أي أكثر من ألف مرة عن السعر قبل المعاملة.

ثم، تم إرجاع هذه AAVE إلى تجمع Aave، باستخدام محدد 0x617ba037، والذي يرمز إلى عملية إيداع (supply) (العنوان، المبلغ، العنوان، مدة القرض). النتيجة أن AAVE الجديدة المصدرة (aEthAAVE) أُعيدت إلى عقد التسوية. وفي النهاية، تم تحويل 327.241335505966487788 من aEthAAVE إلى المستخدم. وترك في العقد حوالي 4.06398010297174764 من aEthAAVE كربح للمستخدم، مقابل ما دفعه، بينما بقيت في العقد.

إذن، التسوية لم تفسد نتيجة تنفيذ جيدة إلى نتيجة سيئة، بل أنها ببساطة أكدت النتيجة التي كانت قد تهيأت مسبقًا عبر المسار.

هذه النقطة مهمة جدًا، ويجب توضيحها: ​النتيجة الكارثية كانت مُعدَّة مسبقًا قبل تنفيذ المسار.

في بيانات استدعاء العقد المدمجة في المسار، المبلغ المستهدف للشراء هو حوالي 331.272185078031026739 AAVE، والحد الأدنى الموقّع للشراء هو 324.949260918413591035 AAVE، والمبلغ الفعلي عند التسوية هو 327.241335505966487788 AAVE، وكل القيم الأساسية كانت محددة قبل التنفيذ في نطاق ثلاثمائة AAVE تقريبًا.

هذا المسار كان سيئًا من البداية.

أين الثغرة؟

الجواب هو: أن كل طبقة من آليات التحقق في النظام كانت تتفقد من زوايا خاطئة.

كل المستويات كانت تتحقق فقط من إمكانية تنفيذ المعاملة، وصحة التوقيع، وعدم صفرية المبالغ، لكنها كانت تكاد لا تتحقق من مدى معقولية المسار من الناحية الاقتصادية، وهو السبب الرئيسي لحدوث الخلل.

خلل في كود مسار تسعير واجهة Aave

أول نقطة واضحة لوجود خلل في الكود، تظهر في عملية استدعاء تسعير ملحق CoW على واجهة Aave: الدالة التي كانت تُستخدم لطلب التسعير مع البيانات الخاصة بالمُوصل، تم تعطيلها بشكل قاطع.

المصدر: rates.helpers.ts:93 و adapters.helpers.ts:194

وهذا يعني أن واجهة Aave عند طلبها للتسعير من CoW، لم تُرفق البيانات الخاصة بالملف الشخصي للملحق، مثل بيانات القروض السريعة (flashloan) والهوكات (hooks) عند إصدار الطلب. بعبارة أخرى، ما يتم عرضه كعرض سعر ليس هو بالضرورة ما سيتم تنفيذه فعليًا. والتعليقات على الكود تقول إن وظيفة المساعد هذه كانت لجعل التسعير أكثر دقة، لكن تم تعطيلها بشكل قسري.

منطق التنافس على التسعير في CoW غير معقول جدًا (ثغرة رئيسية)

المشكلة الثانية والأخطر، تتعلق بمنطق التنافس على التسعير في بروتوكول CoW: في الكود العام للخدمة، طالما أن سعر العرض يتطلب غازًا إيجابيًا، والمبلغ الناتج غير صفر، يُعتبر السعر “معقولًا”.

المصدر: quote.rs:31

بالنسبة لنظام مسار يتعامل مع أوامر بقيمة ثمانية أرقام، هذا تعريف ضعيف جدًا ومرعب لـ"المنطق المعقول".

النظام لا يستخدم سعرًا من خلال مصدر بيانات خارجي (oracle) للتحقق من صحة الأسعار، ولا يوجد آلية لوقف التسعير الذي يبتعد عن السعر السوقي بأكثر من 500 مرة، ولا يوجد تقييم لمخاطر استنزاف السيولة بشكل كامل، ولا تحذيرات عند وجود تفاوت كبير بين حجم الطلب واحتياطيات السيولة. فقط، طالما أن المحلل أعاد مسارًا قابلًا للتنفيذ وغير صفري، يُقبل، وهو الثغرة الأساسية في هذا الحدث.

خلل في نمذجة سيولة Uniswap V2

ثالث مشكلة، تتعلق بطريقة نمذجة تجمعات السيولة على نمط Uniswap V2: الكود يستخدم فقط خوارزمية الضرب الثابت (constant product)، ويرفض فقط الحالات المستحيلة من حيث الرياضيات، مثل الاحتياطيات الصفرية، أو الانزلاق، أو تجاوز السعة، لكنه لا يتحقق من مدى جدوى وجود السيولة من الناحية الاقتصادية.

المصدر: pool_fetching.rs:118 و pool_fetching.rs:153

هذا الجزء من الكود لا يتحقق من أن حجم السيولة في التجمع كافٍ لتحمل المعاملة، فقط يتحقق من أن العملية رياضيًا ممكنة. لذلك، حتى تجمع صغير جدًا يملك 331 AAVE فقط، يمكن اعتباره مكانًا صالحًا لتنفيذ طلب شراء 17,957 WETH، فقط لأنه يمكن حساب نتيجة غير صفرية، متجاهلاً تمامًا أن ذلك قد يؤدي إلى خسائر كارثية.

فشل SDK الخاص بالقروض السريعة وآلية التحقق من الطلبات

بعد ذلك، SDK الخاص بالقروض السريعة قام مباشرة بتثبيت هذا السعر غير الصحيح في الطلبات والهوكات، دون أي فحص للمخاطر مرة أخرى.

ثم،:

المصدر: index.js:484 و index.js:591

وهذا هو السبب في أنني أقول دائمًا أن هذا المسار “مُشوه من البداية”. طبقة الملحقات لم تكتشف أن السعر سيئ عند التنفيذ، بل قامت ببساطة بتسلسل السعر السيئ إلى بيانات الهوك والعنوان المحدد. بمجرد وجود سعر سيئ، تتسلسل باقي الآليات وتستمر في تمريره، دون أن تتدخل.

حتى منطق التحقق من الطلبات في CoW لم يحمي المستخدم بشكل حقيقي، لأنه يتحقق فقط من أن السعر لا يتجاوز سعر السوق عند الطلب، ولا يتحقق من مدى معقولية السعر نفسه بالنسبة للسيولة الفعلية.

المصدر: order_validation.rs:694

وهذا نوع من التحقق من التوافق، لكنه لا يوقف الطلب إذا كان السعر نفسه غير منطقي، حتى لو كان غير واقعي تمامًا.

آلية التحذير في واجهة المستخدم غير فعالة

واجهة Aave لديها تحذير من ارتفاع السعر، لكنه ليس قاطعًا، بل يتحول إلى مربع تأكيد عند خسارة أكثر من 20%.

بمجرد أن يختار المستخدم تأكيد، يُلغى الحاجز:

المصدر: helpers.ts:24 و HighPriceImpactWarning.tsx:35

وبالتالي، حتى لو كانت المعاملة ستقضي على كل أصول المستخدم، يُعتبر الأمر مجرد عملية يتعين على المستخدم تأكيدها، وليس عملية يُمنع تنفيذها قسرًا. آلية التحذير هنا غير قادرة على منع المخاطر.

وبناءً على كل ما سبق من خلل في الآليات، لا أوافق على أن “المستخدم فقط هو المخطئ”. المستخدم أنجز التوقيع، لكن النظام بأكمله كان لديه فرص كثيرة لاعتراض الكارثة، وكل طبقة من النظام كانت تكتفي بالتحقق الأساسي من أن المعاملة غير صفرية، وقابلة للتنفيذ، وموقعة، ثم تتركها تمر، مما أدى في النهاية إلى الكارثة.

لم يتم تعديل المسار

هذه النقطة مهمة جدًا، وتستبعد العديد من الافتراضات الخاطئة: أن عملية aave-v3-interface-collateral-swap على واجهة Aave الرسمية، عند السطر 139 من ملف useSwapOrderAmounts.ts، تحسب سعر الانزلاق بعد أخذ سعر العرض، وتحولها إلى قيمة buyAmountBigInt عند السطر 331، ثم في ملف CollateralSwapActionsViaCoWAdapters.tsx عند السطر 191، يتم توقيعها بدقة.

بعد ذلك، تتأكد العقود الملحقة في ملف AaveV3BaseAdapter.sol عند السطر 141 من أن توقيع الطلب يتطابق تمامًا مع القيم المخزنة؛ وعقد التسوية في ملف GPv2Settlement.sol عند السطر 337، يفرض قواعد الحد الأقصى للتوقيع. لذلك، نتائج التنفيذ على الشبكة لم تتجاوز نطاق الطلب الموقّع، والأصول التي استلمها المستخدم كانت حتى أعلى من الحد الأدنى المسموح به.

وهذا يثبت أن الكارثة حدثت قبل مرحلة التسوية، وأن الثغرة القاتلة كانت في المسار منذ البداية.

إلى أين ذهبت القيمة المفقودة؟

في نفس البلوك، المعاملة التالية (الهاش 0x45388b0f) كانت تنفذ عملية استرجاع (arbitrage) على تجمع SushiSwap AAVE/WETH، بعد أن ملأت المعاملة غير الطبيعية التجمع بكميات هائلة من WETH، وسحبت معظم AAVE. ثم، قام المُستغل ببيع AAVE مرة أخرى في التجمع، محققًا أرباحًا من عدم التوازن في السيولة.

تم استرجاع حوالي 17929.770158685933 WETH، ودفع حوالي 13087.73 ETH لمُنشئ البلوك، و4824.31 ETH لعنوان تنفيذ الاسترجاع.

كل القيمة الاقتصادية التي خسرها المستخدم تحولت بسرعة إلى أرباح MEV داخل نفس البلوك، وإلى أرباح منشئ البلوك.

كما يمكن التحقق من توقيت البلوك، لم يتم التلاعب بشكل خبيث في تجمع SushiSwap قبل المعاملة، وكانت أول عملية على زوج AAVE/WETH هي المعاملة غير الطبيعية (الطلب 1)، تليها عملية استرجاع (الطلب 2) التي استهدفت سعر السوق بعد التلاعب، ثم عملية أخرى في السوق بعد التصحيح (الطلب 3). التوقيت يوضح أن المعاملة غير الطبيعية تسببت في تلاعب شديد، ثم استغلها المُستغلون لتحقيق أرباح من التلاعب.

من المسؤول إذن؟

إذا سألت عما إذا كانت بروتوكولات Aave V3 قد انهارت، فالجواب: لا. فحافظات Aave نفذت العمليات بشكل طبيعي، واسترجعت USDT، وأودعت AAVE.

وإذا سألت عن عقد تسوية GPv2Settlement الخاص بـ CoW، فالجواب: لا. فهو نفذ طلب توقيع صحيح، ودفع أكثر من الحد الأدنى.

وإذا سألت عن عقود Uniswap V3 أو SushiSwap، فالجواب: لا. فهي نفذت المعاملات وفقًا لقواعدها.

الخلل الحقيقي كان في مستوى أعلى، وهو في المسارات وطبقات الرقابة:

الجهة المسؤولة الأساسية هي مسارات التسعير والتوجيه في بروتوكول CoW: النظام بأكمله يفتقر إلى معايير قوية لتحديد “المسارات المعقولة”، ويسمح بتنفيذ أوامر بملايين الدولارات، تصل إلى تجمعات ذات سيولة منخفضة، طالما أن المسار قابل للتنفيذ وغير صفري، دون النظر إلى مدى عدم معقولية ذلك من الناحية الاقتصادية.

الجهة الثانوية هي واجهة المستخدم الخاصة بـ Aave: لم تطلب بيانات التطبيق المرتبطة بالهوك عند طلب التسعير، وأرسلت نتائج خاطئة مباشرة إلى عملية التوقيع، واعتمدت فقط على التحذيرات، دون وجود آلية حاسمة للرفض، وهو ما لا يكفي لمنع عمليات بمبالغ ضخمة جدًا.

هذه كارثة في جودة المسارات وآليات الرقابة، أدت إلى تحويل عملية تبديل ضمانات قانونية إلى كارثة تدمير الأصول.

AAVE2.3%
COW0.12%
UNI3.44%
SUSHI2.07%
شاهد النسخة الأصلية
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
  • أعجبني
  • تعليق
  • إعادة النشر
  • مشاركة
تعليق
إضافة تعليق
إضافة تعليق
لا توجد تعليقات
  • Gate Fun الساخن

    عرض المزيد
  • القيمة السوقية:$2.42Kعدد الحائزين:1
    0.00%
  • القيمة السوقية:$0.1عدد الحائزين:2
    0.00%
  • القيمة السوقية:$2.43Kعدد الحائزين:2
    0.01%
  • القيمة السوقية:$2.45Kعدد الحائزين:1
    0.00%
  • القيمة السوقية:$2.44Kعدد الحائزين:1
    0.00%
  • تثبيت