أمان العقود الذكية
تتميز العقود الذكية بمرونة فائقة، وقدرة على التحكم في كميات كبيرة من القيمة والبيانات، بينما تقوم بتشغيل منطق غير قابل للتغيير بناءً على كود منشور على سلسلة الكتل. وقد أدى ذلك إلى إنشاء نظام بيئي نابض بالحياة من التطبيقات اللامركزية ومنزوعة الثقة التي توفر العديد من المزايا مقارنة بالأنظمة القديمة. كما أنها تمثل فرصاً للمهاجمين الذين يتطلعون إلى الاستفادة من استغلال الثغرات الأمنية في العقود الذكية.
تزيد سلاسل الكتل العامة، مثل إيثيريوم، من تعقيد مسألة تأمين العقود الذكية. عادةً ما لا يمكن تغيير كود العقد المنشور لإصلاح الثغرات الأمنية، في حين أن الأصول المسروقة من العقود الذكية يصعب تتبعها للغاية ولا يمكن استردادها في الغالب بسبب عدم القابلية للتغيير.
على الرغم من اختلاف الأرقام، يُقدر أن إجمالي القيمة المسروقة أو المفقودة بسبب العيوب الأمنية في العقود الذكية يتجاوز بسهولة $1 مليار. يشمل ذلك حوادث بارزة، مثل اختراق المنظمة المستقلة اللامركزية (DAO) (يفتح في علامة تبويب جديدة) (سرقة 3.6M ETH، بقيمة تزيد عن $1B بأسعار اليوم)، واختراق محفظة Parity متعددة التوقيعات (يفتح في علامة تبويب جديدة) (خسارة $30M لصالح المخترقين)، ومشكلة محفظة Parity المجمدة (يفتح في علامة تبويب جديدة) (أكثر من $300M من ETH مقفلة للأبد).
تجعل المشكلات المذكورة أعلاه من الضروري للمطورين استثمار الجهد في بناء عقود ذكية آمنة وقوية ومرنة. أمان العقود الذكية هو أمر بالغ الأهمية، ويجدر بكل مطور أن يتعلمه جيداً. سيغطي هذا الدليل الاعتبارات الأمنية لمطوري إيثيريوم ويستكشف الموارد اللازمة لتحسين أمان العقود الذكية.
المتطلبات الأساسية
تأكد من إلمامك بـ أساسيات تطوير العقود الذكية قبل التطرق إلى موضوع الأمان.
إرشادات لبناء عقود ذكية آمنة على إيثيريوم
1. تصميم ضوابط وصول مناسبة
في العقود الذكية، يمكن استدعاء الدوال المحددة بـ public أو external بواسطة أي حسابات مملوكة خارجياً (EOAs) أو حسابات عقود. تحديد الرؤية العامة (public) للدوال ضروري إذا كنت تريد أن يتفاعل الآخرون مع عقدك. ومع ذلك، فإن الدوال المحددة بـ private لا يمكن استدعاؤها إلا بواسطة دوال داخل العقد الذكي نفسه، وليس بواسطة حسابات خارجية. منح كل مشارك في الشبكة حق الوصول إلى دوال العقد يمكن أن يسبب مشاكل، خاصة إذا كان ذلك يعني أن أي شخص يمكنه تنفيذ عمليات حساسة (مثل عملية سك رموز مميزة جديدة).
لمنع الاستخدام غير المصرح به لدوال العقد الذكي، من الضروري تنفيذ ضوابط وصول آمنة. تقيد آليات التحكم في الوصول القدرة على استخدام دوال معينة في العقد الذكي على الكيانات المعتمدة، مثل الحسابات المسؤولة عن إدارة العقد. يعد نمط الملكية (Ownable pattern) والتحكم القائم على الأدوار (role-based control) نمطين مفيدين لتنفيذ التحكم في الوصول في العقود الذكية:
نمط الملكية (Ownable pattern)
في نمط الملكية، يتم تعيين عنوان كـ "مالك" للعقد أثناء عملية إنشاء العقد. يتم تعيين مُعدِّل OnlyOwner للدوال المحمية، مما يضمن قيام العقد بمصادقة هوية العنوان المستدعي قبل تنفيذ الدالة. تتراجع (revert) دائماً الاستدعاءات للدوال المحمية من عناوين أخرى غير مالك العقد، مما يمنع الوصول غير المرغوب فيه.
التحكم في الوصول القائم على الأدوار
تسجيل عنوان واحد كـ Owner في عقد ذكي يقدم خطر المركزية ويمثل نقطة فشل وحيدة. إذا تم اختراق مفاتيح حساب المالك، يمكن للمهاجمين مهاجمة العقد المملوك. لهذا السبب، قد يكون استخدام نمط التحكم في الوصول القائم على الأدوار مع حسابات إدارية متعددة خياراً أفضل.
في التحكم في الوصول القائم على الأدوار، يتم توزيع الوصول إلى الدوال الحساسة بين مجموعة من المشاركين الموثوقين. على سبيل المثال، قد يكون أحد الحسابات مسؤولاً عن عملية سك الرموز المميزة، بينما يقوم حساب آخر بإجراء ترقيات أو إيقاف العقد مؤقتاً. تؤدي لامركزية التحكم في الوصول بهذه الطريقة إلى القضاء على نقاط الفشل الوحيدة وتقليل افتراضات الثقة للمستخدمين.
استخدام محافظ متعددة التوقيعات
نهج آخر لتنفيذ تحكم آمن في الوصول هو استخدام حساب متعدد التوقيعات لإدارة العقد. على عكس الحساب المملوك خارجياً (EOA) العادي، فإن الحسابات متعددة التوقيعات مملوكة لكيانات متعددة وتتطلب توقيعات من حد أدنى من الحسابات — لنقل 3 من أصل 5 — لتنفيذ المعاملات.
يضيف استخدام حساب متعدد التوقيعات للتحكم في الوصول طبقة إضافية من الأمان نظراً لأن الإجراءات على العقد المستهدف تتطلب موافقة من أطراف متعددة. هذا مفيد بشكل خاص إذا كان استخدام نمط الملكية ضرورياً، حيث يجعل من الصعب على المهاجم أو المطلع الخبيث التلاعب بدوال العقد الحساسة لأغراض خبيثة.
2. استخدام عبارات require() و assert() و revert() لحماية عمليات العقد
كما ذكرنا، يمكن لأي شخص استدعاء الدوال العامة في عقدك الذكي بمجرد نشره على سلسلة الكتل. نظراً لأنك لا تستطيع معرفة مسبقاً كيف ستتفاعل الحسابات الخارجية مع العقد، فمن المثالي تنفيذ ضمانات داخلية ضد العمليات الإشكالية قبل النشر. يمكنك فرض السلوك الصحيح في العقود الذكية باستخدام عبارات require() و assert() و revert() لإطلاق استثناءات والتراجع عن تغييرات الحالة إذا فشل التنفيذ في تلبية متطلبات معينة.
require(): يتم تعريف require في بداية الدوال وتضمن استيفاء الشروط المحددة مسبقاً قبل تنفيذ الدالة المستدعاة. يمكن استخدام عبارة require للتحقق من صحة مدخلات المستخدم، أو فحص متغيرات الحالة، أو مصادقة هوية الحساب المستدعي قبل المضي قدماً في الدالة.
assert(): تُستخدم assert() لاكتشاف الأخطاء الداخلية والتحقق من انتهاكات "الثوابت" (invariants) في الكود الخاص بك. الثابت هو تأكيد منطقي حول حالة العقد يجب أن يظل صحيحاً لجميع عمليات تنفيذ الدوال. مثال على الثابت هو الحد الأقصى لإجمالي العرض أو الرصيد لعقد رمز مميز. يضمن استخدام assert() عدم وصول عقدك أبداً إلى حالة ضعيفة، وإذا حدث ذلك، يتم التراجع عن جميع التغييرات التي طرأت على متغيرات الحالة.
revert(): يمكن استخدام revert() في عبارة if-else التي تطلق استثناءً إذا لم يتم استيفاء الشرط المطلوب. يستخدم العقد النموذجي أدناه revert() لحماية تنفيذ الدوال:
pragma solidity ^0.8.4;
contract VendingMachine {
address owner;
error Unauthorized();
function buy(uint amount) public payable {
if (amount > msg.value / 2 ether)
revert("Not enough Ether provided.");
// تنفيذ عملية الشراء.
}
function withdraw() public {
if (msg.sender != owner)
revert Unauthorized();
payable(msg.sender).transfer(address(this).balance);
}
}
3. اختبار العقود الذكية والتحقق من صحة الكود
إن عدم القابلية للتغيير للكود الذي يعمل في آلة إيثريوم الافتراضية (EVM) يعني أن العقود الذكية تتطلب مستوى أعلى من تقييم الجودة خلال مرحلة التطوير. سيؤدي اختبار عقدك بشكل مكثف ومراقبته بحثاً عن أي نتائج غير متوقعة إلى تحسين الأمان بشكل كبير وحماية مستخدميك على المدى الطويل.
الطريقة المعتادة هي كتابة اختبارات وحدة (unit tests) صغيرة باستخدام بيانات وهمية يُتوقع أن يتلقاها العقد من المستخدمين. يعد اختبار الوحدة جيداً لاختبار وظائف دوال معينة والتأكد من أن العقد الذكي يعمل كما هو متوقع.
لسوء الحظ، يكون اختبار الوحدة فعالاً بشكل ضئيل في تحسين أمان العقد الذكي عند استخدامه بمعزل عن غيره. قد يثبت اختبار الوحدة أن الدالة تُنفذ بشكل صحيح للبيانات الوهمية، لكن اختبارات الوحدة تكون فعالة فقط بقدر جودة الاختبارات المكتوبة. هذا يجعل من الصعب اكتشاف الحالات الطرفية (edge cases) المفقودة ونقاط الضعف التي يمكن أن تكسر أمان عقدك الذكي.
النهج الأفضل هو الجمع بين اختبار الوحدة والاختبار القائم على الخصائص الذي يتم إجراؤه باستخدام التحليل الثابت والديناميكي. يعتمد التحليل الثابت على تمثيلات منخفضة المستوى، مثل رسوم تدفق التحكم (control flow graphs) (يفتح في علامة تبويب جديدة) وأشجار النحو المجردة (abstract syntax trees) (يفتح في علامة تبويب جديدة) لتحليل حالات البرنامج والمسارات التنفيذية التي يمكن الوصول إليها. في غضون ذلك، تقوم تقنيات التحليل الديناميكي، مثل اختبار التشويش (fuzzing) للعقود الذكية (يفتح في علامة تبويب جديدة)، بتنفيذ كود العقد بقيم إدخال عشوائية لاكتشاف العمليات التي تنتهك خصائص الأمان.
يعد التحقق الشكلي تقنية أخرى للتحقق من خصائص الأمان في العقود الذكية. على عكس الاختبار العادي، يمكن للتحقق الشكلي أن يثبت بشكل قاطع عدم وجود أخطاء في العقد الذكي. يتم تحقيق ذلك من خلال إنشاء مواصفات شكلية تلتقط خصائص الأمان المطلوبة وإثبات أن النموذج الشكلي للعقود يلتزم بهذه المواصفات.
4. اطلب مراجعة مستقلة للكود الخاص بك
بعد اختبار عقدك، من الجيد أن تطلب من الآخرين فحص الكود المصدري بحثاً عن أي مشكلات أمنية. لن يكشف الاختبار عن كل عيب في العقد الذكي، لكن الحصول على مراجعة مستقلة يزيد من احتمالية اكتشاف نقاط الضعف.
التدقيقات (Audits)
يعد التكليف بإجراء تدقيق للعقد الذكي إحدى طرق إجراء مراجعة مستقلة للكود. يلعب المدققون دوراً مهماً في ضمان أن العقود الذكية آمنة وخالية من عيوب الجودة وأخطاء التصميم.
ومع ذلك، يجب تجنب التعامل مع التدقيقات كحل سحري. لن تكتشف تدقيقات العقود الذكية كل خطأ، وهي مصممة في الغالب لتوفير جولة إضافية من المراجعات، والتي يمكن أن تساعد في اكتشاف المشكلات التي فاتها المطورون أثناء التطوير والاختبار الأوليين. يجب عليك أيضاً اتباع أفضل الممارسات للعمل مع المدققين، مثل توثيق الكود بشكل صحيح وإضافة تعليقات مضمنة، لتعظيم الاستفادة من تدقيق العقد الذكي.
- نصائح وحيل لتدقيق العقود الذكية (يفتح في علامة تبويب جديدة) - @tinchoabbate
- حقق أقصى استفادة من تدقيقك (يفتح في علامة تبويب جديدة) - Inference
مكافآت اكتشاف الأخطاء (Bug bounties)
يعد إعداد برنامج مكافآت اكتشاف الأخطاء نهجاً آخر لتنفيذ مراجعات الكود الخارجية. مكافأة اكتشاف الأخطاء هي مكافأة مالية تُمنح للأفراد (عادةً قراصنة القبعات البيضاء) الذين يكتشفون نقاط ضعف في تطبيق ما.
عند استخدامها بشكل صحيح، تمنح مكافآت اكتشاف الأخطاء أعضاء مجتمع القراصنة حافزاً لفحص الكود الخاص بك بحثاً عن عيوب حرجة. مثال من الحياة الواقعية هو "خطأ الأموال اللانهائية" الذي كان سيسمح للمهاجم بإنشاء كمية غير محدودة من الإيثر على أوبتيميزم (يفتح في علامة تبويب جديدة)، وهو بروتوكول طبقة 2 (L2) يعمل على إيثيريوم. لحسن الحظ، اكتشف قرصان قبعة بيضاء الخلل (يفتح في علامة تبويب جديدة) وأبلغ الفريق، وحصل على تعويض كبير في هذه العملية (يفتح في علامة تبويب جديدة).
تتمثل الإستراتيجية المفيدة في تحديد تعويض برنامج مكافآت اكتشاف الأخطاء بما يتناسب مع مقدار الأموال المعرضة للخطر. يوفر هذا النهج، الموصوف بـ "مكافأة اكتشاف الأخطاء المتدرجة (يفتح في علامة تبويب جديدة)"، حوافز مالية للأفراد للكشف عن نقاط الضعف بمسؤولية بدلاً من استغلالها.
5. اتبع أفضل الممارسات أثناء تطوير العقد الذكي
إن وجود التدقيقات ومكافآت اكتشاف الأخطاء لا يعفيك من مسؤوليتك في كتابة كود عالي الجودة. يبدأ الأمان الجيد للعقد الذكي باتباع عمليات التصميم والتطوير المناسبة:
-
تخزين جميع الأكواد في نظام للتحكم في الإصدارات، مثل git
-
إجراء جميع تعديلات الكود عبر طلبات السحب (pull requests)
-
التأكد من أن طلبات السحب تحتوي على مراجع مستقل واحد على الأقل — إذا كنت تعمل بمفردك في مشروع، ففكر في العثور على مطورين آخرين وتبادل مراجعات الكود
-
استخدام بيئة تطوير لاختبار وتصريف ونشر العقود الذكية
-
تمرير الكود الخاص بك عبر أدوات تحليل الكود الأساسية، مثل Cyfrin Aderyn (يفتح في علامة تبويب جديدة) و Mythril و سليذر. من الناحية المثالية، يجب عليك القيام بذلك قبل دمج كل طلب سحب ومقارنة الاختلافات في المخرجات
-
التأكد من تصريف الكود الخاص بك دون أخطاء، وأن مُصرّف Solidity لا يصدر أي تحذيرات
-
توثيق الكود الخاص بك بشكل صحيح (باستخدام NatSpec (يفتح في علامة تبويب جديدة)) ووصف التفاصيل حول بنية العقد بلغة سهلة الفهم. سيجعل هذا من السهل على الآخرين تدقيق ومراجعة الكود الخاص بك.
6. تنفيذ خطط قوية للتعافي من الكوارث
يمكن أن يؤدي تصميم ضوابط وصول آمنة، وتنفيذ مُعدِّلات الدوال، والاقتراحات الأخرى إلى تحسين أمان العقد الذكي، لكنها لا يمكن أن تستبعد إمكانية الاستغلال الخبيث. يتطلب بناء عقود ذكية آمنة "الاستعداد للفشل" ووجود خطة بديلة للاستجابة بفعالية للهجمات. ستتضمن خطة التعافي من الكوارث المناسبة بعض أو كل المكونات التالية:
ترقيات العقد
في حين أن العقود الذكية على إيثيريوم غير قابلة للتغيير افتراضياً، فمن الممكن تحقيق درجة معينة من القابلية للتغيير باستخدام أنماط الترقية. تعد ترقية العقود ضرورية في الحالات التي يجعل فيها خلل حرج عقدك القديم غير قابل للاستخدام ويكون نشر منطق جديد هو الخيار الأكثر جدوى.
تعمل آليات ترقية العقد بشكل مختلف، لكن "نمط الوكيل" (proxy pattern) هو أحد الأساليب الأكثر شيوعاً لترقية العقود الذكية. تقسم أنماط الوكيل (يفتح في علامة تبويب جديدة) حالة التطبيق ومنطقه بين عقدين. يخزن العقد الأول (يسمى "عقد وكيل") متغيرات الحالة (مثل أرصدة المستخدمين)، بينما يحتفظ العقد الثاني (يسمى "عقد المنطق") بالكود لتنفيذ دوال العقد.
تتفاعل الحسابات مع العقد الوكيل، والذي يرسل جميع استدعاءات الدوال إلى عقد المنطق باستخدام الاستدعاء منخفض المستوى delegatecall() (يفتح في علامة تبويب جديدة). على عكس استدعاء رسالة عادي، يضمن delegatecall() تنفيذ الكود الذي يعمل في عنوان عقد المنطق في سياق العقد المستدعي. هذا يعني أن عقد المنطق سيكتب دائماً في تخزين الوكيل (بدلاً من تخزينه الخاص) ويتم الحفاظ على القيم الأصلية لـ msg.sender و msg.value.
يتطلب تفويض الاستدعاءات إلى عقد المنطق تخزين عنوانه في تخزين العقد الوكيل. وبالتالي، فإن ترقية منطق العقد هي مجرد مسألة نشر عقد منطق آخر وتخزين العنوان الجديد في العقد الوكيل. نظراً لأن الاستدعاءات اللاحقة للعقد الوكيل يتم توجيهها تلقائياً إلى عقد المنطق الجديد، فستكون قد "رقيت" العقد دون تعديل الكود فعلياً.
الإيقاف في حالات الطوارئ
كما ذكرنا، لا يمكن للتدقيق والاختبار المكثف اكتشاف جميع الأخطاء في العقد الذكي. إذا ظهرت نقطة ضعف في الكود الخاص بك بعد النشر، فإن تصحيحها مستحيل لأنك لا تستطيع تغيير الكود الذي يعمل في عنوان العقد. أيضاً، قد تستغرق آليات الترقية (مثل أنماط الوكيل) وقتاً لتنفيذها (غالباً ما تتطلب موافقة من أطراف مختلفة)، مما يمنح المهاجمين مزيداً من الوقت لإحداث المزيد من الضرر.
الخيار الجذري هو تنفيذ دالة "إيقاف في حالات الطوارئ" تمنع الاستدعاءات للدوال الضعيفة في العقد. تتكون عمليات الإيقاف في حالات الطوارئ عادةً من المكونات التالية:
-
متغير منطقي (Boolean) عام يشير إلى ما إذا كان العقد الذكي في حالة توقف أم لا. يتم تعيين هذا المتغير إلى
falseعند إعداد العقد، ولكنه سيتغير إلىtrueبمجرد إيقاف العقد. -
الدوال التي تشير إلى المتغير المنطقي في تنفيذها. يمكن الوصول إلى مثل هذه الدوال عندما لا يكون العقد الذكي متوقفاً، وتصبح غير قابلة للوصول عند تشغيل ميزة الإيقاف في حالات الطوارئ.
-
كيان لديه حق الوصول إلى دالة الإيقاف في حالات الطوارئ، والذي يعين المتغير المنطقي إلى
true. لمنع الإجراءات الخبيثة، يمكن تقييد الاستدعاءات لهذه الدالة على عنوان موثوق (مثل مالك العقد).
بمجرد أن ينشط العقد الإيقاف في حالات الطوارئ، لن تكون بعض الدوال قابلة للاستدعاء. يتم تحقيق ذلك عن طريق تغليف دوال محددة في مُعدِّل يشير إلى المتغير العام. يوجد أدناه مثال (يفتح في علامة تبويب جديدة) يصف تنفيذاً لهذا النمط في العقود:
// لم يتم تدقيق هذا الكود بشكل احترافي ولا يقدم أي وعود بشأن الأمان أو الصحة. استخدمه على مسؤوليتك الخاصة.
contract EmergencyStop {
bool isStopped = false;
modifier stoppedInEmergency {
require(!isStopped);
_;
}
modifier onlyWhenStopped {
require(isStopped);
_;
}
modifier onlyAuthorized {
// تحقق من تفويض msg.sender هنا
_;
}
function stopContract() public onlyAuthorized {
isStopped = true;
}
function resumeContract() public onlyAuthorized {
isStopped = false;
}
function deposit() public payable stoppedInEmergency {
// منطق الإيداع يحدث هنا
}
function emergencyWithdraw() public onlyWhenStopped {
// السحب الطارئ يحدث هنا
}
}
يوضح هذا المثال الميزات الأساسية لعمليات الإيقاف في حالات الطوارئ:
-
isStoppedهو متغير منطقي يتم تقييمه إلىfalseفي البداية وإلىtrueعندما يدخل العقد في وضع الطوارئ. -
تتحقق مُعدِّلات الدوال
onlyWhenStoppedوstoppedInEmergencyمن المتغيرisStopped. يُستخدمstoppedInEmergencyللتحكم في الدوال التي يجب أن تكون غير قابلة للوصول عندما يكون العقد ضعيفاً (مثلdeposit()). الاستدعاءات لهذه الدوال ستتراجع (revert) ببساطة.
يُستخدم onlyWhenStopped للدوال التي يجب أن تكون قابلة للاستدعاء أثناء حالة الطوارئ (مثل emergencyWithdraw()). يمكن أن تساعد مثل هذه الدوال في حل الموقف، ومن هنا جاء استبعادها من قائمة "الدوال المقيدة".
يوفر استخدام وظيفة الإيقاف في حالات الطوارئ حلاً مؤقتاً فعالاً للتعامل مع نقاط الضعف الخطيرة في عقدك الذكي. ومع ذلك، فإنه يزيد من حاجة المستخدمين إلى الثقة في المطورين لعدم تنشيطه لأسباب تخدم مصالحهم الذاتية. تحقيقاً لهذه الغاية، فإن لامركزية التحكم في الإيقاف في حالات الطوارئ إما عن طريق إخضاعه لآلية تصويت على السلسلة، أو قفل زمني (timelock)، أو موافقة من محفظة متعددة التوقيعات هي حلول ممكنة.
مراقبة الأحداث
تسمح لك الأحداث (يفتح في علامة تبويب جديدة) بتتبع الاستدعاءات لدوال العقد الذكي ومراقبة التغييرات في متغيرات الحالة. من المثالي برمجة عقدك الذكي لإصدار حدث كلما اتخذ طرف ما إجراءً حرجاً للسلامة (مثل سحب الأموال).
يوفر تسجيل الأحداث ومراقبتها خارج السلسلة رؤى حول عمليات العقد ويساعد في اكتشاف أسرع للإجراءات الخبيثة. هذا يعني أن فريقك يمكنه الاستجابة بشكل أسرع للاختراقات واتخاذ إجراءات للتخفيف من التأثير على المستخدمين، مثل إيقاف الدوال مؤقتاً أو إجراء ترقية.
يمكنك أيضاً اختيار أداة مراقبة جاهزة تقوم تلقائياً بإعادة توجيه التنبيهات كلما تفاعل شخص ما مع عقودك. ستسمح لك هذه الأدوات بإنشاء تنبيهات مخصصة بناءً على محفزات مختلفة، مثل حجم المعاملة، أو تكرار استدعاءات الدوال، أو الدوال المحددة المعنية. على سبيل المثال، يمكنك برمجة تنبيه يظهر عندما يتجاوز المبلغ المسحوب في معاملة واحدة حداً معيناً.
7. تصميم أنظمة حوكمة آمنة
قد ترغب في جعل تطبيقك لامركزياً عن طريق تسليم التحكم في العقود الذكية الأساسية لأعضاء المجتمع. في هذه الحالة، سيتضمن نظام العقد الذكي وحدة حوكمة — وهي آلية تسمح لأعضاء المجتمع بالموافقة على الإجراءات الإدارية عبر نظام حوكمة على السلسلة. على سبيل المثال، قد يتم التصويت على مقترح لترقية عقد وكيل إلى تنفيذ جديد من قبل حاملي الرموز المميزة.
يمكن أن تكون الحوكمة اللامركزية مفيدة، خاصة لأنها توائم بين مصالح المطورين والمستخدمين النهائيين. ومع ذلك، قد تقدم آليات حوكمة العقد الذكي مخاطر جديدة إذا تم تنفيذها بشكل غير صحيح. السيناريو المعقول هو إذا اكتسب المهاجم قوة تصويت هائلة (تُقاس بعدد الرموز المميزة المحتفظ بها) عن طريق الحصول على قرض سريع ودفع مقترح خبيث.
إحدى طرق منع المشاكل المتعلقة بالحوكمة على السلسلة هي استخدام قفل زمني (timelock) (يفتح في علامة تبويب جديدة). يمنع القفل الزمني العقد الذكي من تنفيذ إجراءات معينة حتى يمر مقدار معين من الوقت. تشمل الاستراتيجيات الأخرى تعيين "وزن تصويت" لكل رمز مميز بناءً على مدة قفله، أو قياس قوة التصويت لعنوان في فترة تاريخية (على سبيل المثال، 2-3 كتل في الماضي) بدلاً من الكتلة الحالية. تقلل كلتا الطريقتين من إمكانية جمع قوة التصويت بسرعة للتأثير على الأصوات على السلسلة.
المزيد حول تصميم أنظمة حوكمة آمنة (يفتح في علامة تبويب جديدة)، وآليات التصويت المختلفة في المنظمات المستقلة اللامركزية (DAOs) (يفتح في علامة تبويب جديدة)، ونواقل هجوم المنظمات المستقلة اللامركزية (DAOs) الشائعة التي تستفيد من التمويل اللامركزي (DeFi) (يفتح في علامة تبويب جديدة) في الروابط المشتركة.
8. تقليل التعقيد في الكود إلى الحد الأدنى
مطورو البرمجيات التقليديون على دراية بمبدأ KISS ("اجعله بسيطاً يا غبي")، والذي ينصح بعدم إدخال تعقيد غير ضروري في تصميم البرمجيات. يتبع هذا التفكير السائد منذ فترة طويلة بأن "الأنظمة المعقدة تفشل بطرق معقدة" وتكون أكثر عرضة للأخطاء المكلفة.
يعد الحفاظ على بساطة الأمور ذا أهمية خاصة عند كتابة العقود الذكية، نظراً لأن العقود الذكية تتحكم في الغالب في كميات كبيرة من القيمة. نصيحة لتحقيق البساطة عند كتابة العقود الذكية هي إعادة استخدام المكتبات الحالية، مثل عقود أوبن زبلن (يفتح في علامة تبويب جديدة)، حيثما أمكن ذلك. نظراً لأن هذه المكتبات قد تم تدقيقها واختبارها على نطاق واسع من قبل المطورين، فإن استخدامها يقلل من فرص إدخال أخطاء عن طريق كتابة وظائف جديدة من الصفر.
نصيحة شائعة أخرى هي كتابة دوال صغيرة والحفاظ على العقود معيارية (modular) عن طريق تقسيم منطق الأعمال عبر عقود متعددة. لا يقلل كتابة كود أبسط من سطح الهجوم في العقد الذكي فحسب، بل يسهل أيضاً التفكير في صحة النظام العام واكتشاف أخطاء التصميم المحتملة مبكراً.
9. الدفاع ضد نقاط ضعف العقد الذكي الشائعة
إعادة الدخول (Reentrancy)
لا تسمح آلة إيثريوم الافتراضية (EVM) بالتزامن، مما يعني أن عقدين متورطين في استدعاء رسالة لا يمكن تشغيلهما في وقت واحد. يوقف الاستدعاء الخارجي تنفيذ العقد المستدعي وذاكرته مؤقتاً حتى يعود الاستدعاء، وعند هذه النقطة يستمر التنفيذ بشكل طبيعي. يمكن وصف هذه العملية رسمياً بأنها نقل تدفق التحكم (يفتح في علامة تبويب جديدة) إلى عقد آخر.
على الرغم من أنه غير ضار في الغالب، إلا أن نقل تدفق التحكم إلى عقود غير موثوقة يمكن أن يسبب مشاكل، مثل إعادة الدخول. يحدث هجوم إعادة الدخول عندما يستدعي عقد خبيث عقداً ضعيفاً مرة أخرى قبل اكتمال استدعاء الدالة الأصلية. أفضل طريقة لشرح هذا النوع من الهجوم هي بمثال.
تأمل عقداً ذكياً بسيطاً ("الضحية") يسمح لأي شخص بإيداع وسحب الإيثر:
// هذا العقد عرضة للاختراق. لا تستخدمه في بيئة الإنتاج
contract Victim {
mapping (address => uint256) public balances;
function deposit() external payable {
balances[msg.sender] += msg.value;
}
function withdraw() external {
uint256 amount = balances[msg.sender];
(bool success, ) = msg.sender.call.value(amount)("");
require(success);
balances[msg.sender] = 0;
}
}
يعرض هذا العقد دالة withdraw() للسماح للمستخدمين بسحب ETH المودع مسبقاً في العقد. عند معالجة السحب، يقوم العقد بالعمليات التالية:
- يتحقق من رصيد ETH للمستخدم
- يرسل الأموال إلى العنوان المستدعي
- يعيد تعيين رصيدهم إلى 0، مما يمنع عمليات السحب الإضافية من المستخدم
تتبع دالة withdraw() في عقد Victim نمط "التحققات-التفاعلات-التأثيرات" (checks-interactions-effects). فهي تتحقق مما إذا كانت الشروط اللازمة للتنفيذ مستوفاة (أي أن المستخدم لديه رصيد ETH إيجابي) وتقوم بـ التفاعل عن طريق إرسال ETH إلى عنوان المستدعي، قبل تطبيق تأثيرات المعاملة (أي تقليل رصيد المستخدم).
إذا تم استدعاء withdraw() من حساب مملوك خارجياً (EOA)، يتم تنفيذ الدالة كما هو متوقع: يرسل msg.sender.call.value() ETH إلى المستدعي. ومع ذلك، إذا كان msg.sender حساب عقد ذكي يستدعي withdraw()، فإن إرسال الأموال باستخدام msg.sender.call.value() سيؤدي أيضاً إلى تشغيل الكود المخزن في ذلك العنوان.
تخيل أن هذا هو الكود المنشور في عنوان العقد:
contract Attacker {
function beginAttack() external payable {
Victim(victim_address).deposit.value(1 ether)();
Victim(victim_address).withdraw();
}
function() external payable {
if (gasleft() > 40000) {
Victim(victim_address).withdraw();
}
}
}
تم تصميم هذا العقد للقيام بثلاثة أشياء:
- قبول إيداع من حساب آخر (من المحتمل أن يكون الحساب المملوك خارجياً للمهاجم)
- إيداع 1 ETH في عقد الضحية
- سحب 1 ETH المخزن في العقد الذكي
لا يوجد شيء خاطئ هنا، باستثناء أن Attacker لديه دالة أخرى تستدعي withdraw() في Victim مرة أخرى إذا كان الغاز المتبقي من msg.sender.call.value الوارد أكثر من 40,000. هذا يمنح Attacker القدرة على إعادة الدخول إلى Victim وسحب المزيد من الأموال قبل اكتمال الاستدعاء الأول لـ withdraw. تبدو الدورة هكذا:
- Attacker's EOA calls `Attacker.beginAttack()` with 1 ETH
- `Attacker.beginAttack()` deposits 1 ETH into `Victim`
- `Attacker` calls `withdraw() in `Victim`
- `Victim` checks `Attacker`’s balance (1 ETH)
- `Victim` sends 1 ETH to `Attacker` (which triggers the default function)
- `Attacker` calls `Victim.withdraw()` again (note that `Victim` hasn’t reduced `Attacker`’s balance from the first withdrawal)
- `Victim` checks `Attacker`’s balance (which is still 1 ETH because it hasn’t applied the effects of the first call)
- `Victim` sends 1 ETH to `Attacker` (which triggers the default function and allows `Attacker` to reenter the `withdraw` function)
- The process repeats until `Attacker` runs out of gas, at which point `msg.sender.call.value` returns without triggering additional withdrawals
- `Victim` finally applies the results of the first transaction (and subsequent ones) to its state, so `Attacker`’s balance is set to 0
الخلاصة هي أنه نظراً لعدم تعيين رصيد المستدعي إلى 0 حتى يكتمل تنفيذ الدالة، ستنجح الاستدعاءات اللاحقة وتسمح للمستدعي بسحب رصيده عدة مرات. يمكن استخدام هذا النوع من الهجوم لاستنزاف أموال العقد الذكي، مثل ما حدث في اختراق DAO عام 2016 (يفتح في علامة تبويب جديدة). لا تزال هجمات إعادة الدخول تمثل مشكلة حرجة للعقود الذكية اليوم كما تظهر القوائم العامة لاستغلالات إعادة الدخول (يفتح في علامة تبويب جديدة).
كيفية منع هجمات إعادة الدخول
يتمثل أحد الأساليب للتعامل مع إعادة الدخول في اتباع نمط التحققات-التأثيرات-التفاعلات (يفتح في علامة تبويب جديدة). يرتب هذا النمط تنفيذ الدوال بطريقة تجعل الكود الذي يقوم بالتحققات اللازمة قبل المضي قدماً في التنفيذ يأتي أولاً، يليه الكود الذي يعالج حالة العقد، مع وصول الكود الذي يتفاعل مع العقود الأخرى أو الحسابات المملوكة خارجياً (EOAs) أخيراً.
يُستخدم نمط التحققات-التأثيرات-التفاعلات في نسخة منقحة من عقد Victim الموضح أدناه:
contract NoLongerAVictim {
function withdraw() external {
uint256 amount = balances[msg.sender];
balances[msg.sender] = 0;
(bool success, ) = msg.sender.call.value(amount)("");
require(success);
}
}
يقوم هذا العقد بـ التحقق من رصيد المستخدم، ويطبق تأثيرات دالة withdraw() (عن طريق إعادة تعيين رصيد المستخدم إلى 0)، ويشرع في إجراء التفاعل (إرسال ETH إلى عنوان المستخدم). يضمن هذا قيام العقد بتحديث تخزينه قبل الاستدعاء الخارجي، مما يقضي على شرط إعادة الدخول الذي مكّن الهجوم الأول. لا يزال بإمكان عقد Attacker الاستدعاء مرة أخرى إلى NoLongerAVictim، ولكن نظراً لأنه تم تعيين balances[msg.sender] إلى 0، فإن عمليات السحب الإضافية ستطرح خطأً.
خيار آخر هو استخدام قفل الاستبعاد المتبادل (يوصف عادةً باسم "mutex") الذي يقفل جزءاً من حالة العقد حتى يكتمل استدعاء الدالة. يتم تنفيذ ذلك باستخدام متغير منطقي يتم تعيينه إلى true قبل تنفيذ الدالة ويعود إلى false بعد الانتهاء من الاستدعاء. كما يظهر في المثال أدناه، فإن استخدام mutex يحمي الدالة من الاستدعاءات العودية (recursive calls) بينما لا يزال الاستدعاء الأصلي قيد المعالجة، مما يوقف إعادة الدخول بشكل فعال.
pragma solidity ^0.7.0;
contract MutexPattern {
bool locked = false;
mapping(address => uint256) public balances;
modifier noReentrancy() {
require(!locked, "Blocked from reentrancy.");
locked = true;
_;
locked = false;
}
// هذه الدالة محمية بواسطة كائن استبعاد متبادل (mutex)، لذا فإن استدعاءات إعادة الدخول من داخل `msg.sender.call` لا يمكنها استدعاء `withdraw` مرة أخرى.
// تُقيّم عبارة `return` إلى `true` ولكنها لا تزال تُقيّم عبارة `locked = false` في المُعدِّل
function withdraw(uint _amount) public payable noReentrancy returns(bool) {
require(balances[msg.sender] >= _amount, "No balance to withdraw.");
balances[msg.sender] -= _amount;
(bool success, ) = msg.sender.call{value: _amount}("");
require(success);
return true;
}
}
يمكنك أيضاً استخدام نظام مدفوعات السحب (pull payments) (يفتح في علامة تبويب جديدة) الذي يتطلب من المستخدمين سحب الأموال من العقود الذكية، بدلاً من نظام "مدفوعات الدفع" (push payments) الذي يرسل الأموال إلى الحسابات. يؤدي هذا إلى إزالة إمكانية تشغيل الكود عن غير قصد في عناوين غير معروفة (ويمكن أن يمنع أيضاً بعض هجمات الحرمان من الخدمة).
تجاوز السعة (Overflows) والنقصان (Underflows) للأعداد الصحيحة
يحدث تجاوز السعة للعدد الصحيح عندما تقع نتائج عملية حسابية خارج النطاق المقبول للقيم، مما يتسبب في "التفافها" (roll over) إلى أدنى قيمة يمكن تمثيلها. على سبيل المثال، يمكن لـ uint8 تخزين قيم تصل إلى 2^8-1=255 فقط. العمليات الحسابية التي تؤدي إلى قيم أعلى من 255 ستتجاوز السعة وتعيد تعيين uint إلى 0، على غرار كيفية إعادة تعيين عداد المسافات في السيارة إلى 0 بمجرد وصوله إلى الحد الأقصى للمسافة المقطوعة (999999).
يحدث النقصان للأعداد الصحيحة لأسباب مماثلة: تقع نتائج عملية حسابية أقل من النطاق المقبول. لنفترض أنك حاولت إنقاص 0 في uint8، فإن النتيجة ستلتف ببساطة إلى أقصى قيمة يمكن تمثيلها (255).
يمكن أن يؤدي كل من تجاوز السعة والنقصان للأعداد الصحيحة إلى تغييرات غير متوقعة في متغيرات حالة العقد ويؤدي إلى تنفيذ غير مخطط له. يوجد أدناه مثال يوضح كيف يمكن للمهاجم استغلال تجاوز السعة الحسابي في عقد ذكي لإجراء عملية غير صالحة:
pragma solidity ^0.7.6;
// تم تصميم هذا العقد ليعمل كقبو زمني.
// يمكن للمستخدم الإيداع في هذا العقد ولكنه لا يستطيع السحب لمدة أسبوع على الأقل.
// يمكن للمستخدم أيضاً تمديد وقت الانتظار إلى ما بعد فترة الانتظار البالغة أسبوعاً واحداً.
/*
1. نشر TimeLock
2. نشر Attack مع عنوان TimeLock
3. استدعاء Attack.attack مع إرسال 1 إيثر. ستتمكن على الفور من
سحب الإيثر الخاص بك.
ماذا حدث؟
تسبب Attack في تجاوز السعة لـ TimeLock.lockTime وتمكن من السحب
قبل فترة الانتظار البالغة أسبوعاً واحداً.
*/
contract TimeLock {
mapping(address => uint) public balances;
mapping(address => uint) public lockTime;
function deposit() external payable {
balances[msg.sender] += msg.value;
lockTime[msg.sender] = block.timestamp + 1 weeks;
}
function increaseLockTime(uint _secondsToIncrease) public {
lockTime[msg.sender] += _secondsToIncrease;
}
function withdraw() public {
require(balances[msg.sender] > 0, "Insufficient funds");
require(block.timestamp > lockTime[msg.sender], "Lock time not expired");
uint amount = balances[msg.sender];
balances[msg.sender] = 0;
(bool sent, ) = msg.sender.call{value: amount}("");
require(sent, "Failed to send Ether");
}
}
contract Attack {
TimeLock timeLock;
constructor(TimeLock _timeLock) {
timeLock = TimeLock(_timeLock);
}
fallback() external payable {}
function attack() public payable {
timeLock.deposit{value: msg.value}();
/*
إذا كان t = وقت القفل الحالي، فإننا نحتاج إلى إيجاد x بحيث
x + t = 2**256 = 0
لذا x = -t
2**256 = type(uint).max + 1
لذا x = type(uint).max + 1 - t
*/
timeLock.increaseLockTime(
type(uint).max + 1 - timeLock.lockTime(address(this))
);
timeLock.withdraw();
}
}
كيفية منع تجاوز السعة والنقصان للأعداد الصحيحة
اعتباراً من الإصدار 0.8.0، يرفض مُصرّف Solidity الكود الذي يؤدي إلى تجاوز السعة والنقصان للأعداد الصحيحة. ومع ذلك، يجب على العقود المُصرّفة بإصدار مُصرّف أقل إما إجراء فحوصات على الدوال التي تتضمن عمليات حسابية أو استخدام مكتبة (مثل SafeMath (يفتح في علامة تبويب جديدة)) تتحقق من النقصان/تجاوز السعة.
التلاعب بالأوراكل
تستمد الأوراكل المعلومات من خارج السلسلة وترسلها على السلسلة لتستخدمها العقود الذكية. باستخدام الأوراكل، يمكنك تصميم عقود ذكية تتفاعل مع أنظمة خارج السلسلة، مثل أسواق رأس المال، مما يوسع نطاق تطبيقها بشكل كبير.
ولكن إذا كان الأوراكل تالفاً ويرسل معلومات غير صحيحة على السلسلة، فسيتم تنفيذ العقود الذكية بناءً على مدخلات خاطئة، مما قد يسبب مشاكل. هذا هو أساس "مشكلة الأوراكل"، والتي تتعلق بمهمة التأكد من أن المعلومات الواردة من أوراكل البلوكتشين دقيقة ومحدثة وفي الوقت المناسب.
من المخاوف الأمنية ذات الصلة استخدام أوراكل على السلسلة، مثل منصة تداول لامركزية (DEX)، للحصول على السعر الفوري لأصل ما. غالباً ما تفعل منصات الإقراض في صناعة التمويل اللامركزي (DeFi) ذلك لتحديد قيمة ضمان المستخدم لتحديد المبلغ الذي يمكنه اقتراضه.
غالباً ما تكون أسعار منصات التداول اللامركزية (DEX) دقيقة، ويرجع ذلك إلى حد كبير إلى قيام المراجحين (arbitrageurs) باستعادة التكافؤ في الأسواق. ومع ذلك، فهي مفتوحة للتلاعب، خاصة إذا كان الأوراكل على السلسلة يحسب أسعار الأصول بناءً على أنماط التداول التاريخية (كما هو الحال عادةً).
على سبيل المثال، يمكن للمهاجم رفع السعر الفوري لأصل ما بشكل مصطنع عن طريق الحصول على قرض سريع قبل التفاعل مباشرة مع عقد الإقراض الخاص بك. سيؤدي الاستعلام من منصة التداول اللامركزية (DEX) عن سعر الأصل إلى إرجاع قيمة أعلى من المعتاد (بسبب "أمر الشراء" الكبير للمهاجم الذي يحرف الطلب على الأصل)، مما يسمح له باقتراض أكثر مما ينبغي. تم استخدام مثل هذه "هجمات القروض السريعة" لاستغلال الاعتماد على أوراكل الأسعار بين تطبيقات التمويل اللامركزي (DeFi)، مما كلف البروتوكولات الملايين من الأموال المفقودة.
كيفية منع التلاعب بالأوراكل
الحد الأدنى من المتطلبات لـ تجنب التلاعب بالأوراكل (يفتح في علامة تبويب جديدة) هو استخدام شبكة أوراكل لامركزية تستعلم عن المعلومات من مصادر متعددة لتجنب نقاط الفشل الوحيدة. في معظم الحالات، تحتوي الأوراكل اللامركزية على حوافز اقتصادية مشفرة مدمجة لتشجيع عقد الأوراكل على الإبلاغ عن المعلومات الصحيحة، مما يجعلها أكثر أماناً من الأوراكل المركزية.
إذا كنت تخطط للاستعلام من أوراكل على السلسلة عن أسعار الأصول، ففكر في استخدام واحد ينفذ آلية متوسط السعر المرجح بالوقت (TWAP). يستعلم أوراكل TWAP (يفتح في علامة تبويب جديدة) عن سعر الأصل في نقطتين زمنيتين مختلفتين (والتي يمكنك تعديلها) ويحسب السعر الفوري بناءً على المتوسط الذي تم الحصول عليه. يحمي اختيار فترات زمنية أطول بروتوكولك من التلاعب بالأسعار نظراً لأن الطلبات الكبيرة المنفذة مؤخراً لا يمكن أن تؤثر على أسعار الأصول.
موارد أمان العقود الذكية للمطورين
أدوات لتحليل العقود الذكية والتحقق من صحة الكود
-
أدوات ومكتبات الاختبار - مجموعة من الأدوات والمكتبات المتوافقة مع معايير الصناعة لإجراء اختبارات الوحدة، والتحليل الثابت، والتحليل الديناميكي على العقود الذكية.
-
أدوات التحقق الشكلي - أدوات للتحقق من الصحة الوظيفية في العقود الذكية والتحقق من الثوابت.
-
خدمات تدقيق العقود الذكية - قائمة بالمؤسسات التي تقدم خدمات تدقيق العقود الذكية لمشاريع تطوير إيثيريوم.
-
منصات مكافآت اكتشاف الثغرات - منصات لتنسيق مكافآت اكتشاف الثغرات ومكافأة الإفصاح المسؤول عن نقاط الضعف الحرجة في العقود الذكية.
-
Fork Checker (يفتح في علامة تبويب جديدة) - أداة مجانية عبر الإنترنت للتحقق من جميع المعلومات المتاحة بخصوص عقد متفرع.
-
ABI Encoder (يفتح في علامة تبويب جديدة) - خدمة مجانية عبر الإنترنت لتشفير دوال عقد Solidity الخاص بك ووسائط المُنشئ.
-
Aderyn (يفتح في علامة تبويب جديدة) - محلل ثابت للغة Solidity، يجتاز أشجار النحو المجردة (AST) لتحديد نقاط الضعف المشتبه بها وطباعة المشكلات بتنسيق ماركداون سهل القراءة.
أدوات لمراقبة العقود الذكية
- تنبيهات Tenderly في الوقت الفعلي (يفتح في علامة تبويب جديدة) - أداة للحصول على إشعارات في الوقت الفعلي عند حدوث أحداث غير عادية أو غير متوقعة في عقودك الذكية أو محافظك.
أدوات للإدارة الآمنة للعقود الذكية
-
Safe (يفتح في علامة تبويب جديدة) - محفظة عقد ذكي تعمل على إيثيريوم تتطلب حداً أدنى من الأشخاص للموافقة على معاملة قبل حدوثها (M-of-N).
-
عقود أوبن زبلن (يفتح في علامة تبويب جديدة) - مكتبات عقود لتنفيذ الميزات الإدارية، بما في ذلك ملكية العقد، والترقيات، وضوابط الوصول، والحوكمة، وقابلية الإيقاف المؤقت، والمزيد.
خدمات تدقيق العقود الذكية
-
كونسينسيس ديلجينس (ConsenSys Diligence) (يفتح في علامة تبويب جديدة) - خدمة تدقيق العقود الذكية تساعد المشاريع عبر نظام سلسلة الكتل البيئي على ضمان جاهزية بروتوكولاتها للإطلاق وبنائها لحماية المستخدمين.
-
CertiK (يفتح في علامة تبويب جديدة) - شركة أمن سلسلة الكتل رائدة في استخدام تكنولوجيا التحقق الشكلي المتطورة على العقود الذكية وشبكات سلسلة الكتل.
-
Trail of Bits (يفتح في علامة تبويب جديدة) - شركة أمن سيبراني تجمع بين الأبحاث الأمنية وعقلية المهاجم لتقليل المخاطر وتحصين الكود.
-
PeckShield (يفتح في علامة تبويب جديدة) - شركة أمن سلسلة الكتل تقدم منتجات وخدمات للأمن، والخصوصية، وقابلية الاستخدام لنظام سلسلة الكتل البيئي بأكمله.
-
QuantStamp (يفتح في علامة تبويب جديدة) - خدمة تدقيق تسهل التبني السائد لتكنولوجيا سلسلة الكتل من خلال خدمات تقييم الأمن والمخاطر.
-
أوبن زبلن (يفتح في علامة تبويب جديدة) - شركة أمن العقود الذكية تقدم عمليات تدقيق أمني للأنظمة الموزعة.
-
Runtime Verification (يفتح في علامة تبويب جديدة) - شركة أمنية متخصصة في النمذجة والتحقق الشكلي للعقود الذكية.
-
Hacken (يفتح في علامة تبويب جديدة) - مدقق أمن سيبراني في Web3 يقدم نهجاً شاملاً لأمن سلسلة الكتل.
-
نيذرميند (يفتح في علامة تبويب جديدة) - خدمات تدقيق Solidity وCairo، لضمان سلامة العقود الذكية وأمان المستخدمين عبر إيثيريوم وستارك نت.
-
HashEx (يفتح في علامة تبويب جديدة) - تركز HashEx على تدقيق سلسلة الكتل والعقود الذكية لضمان أمن العملات المشفرة، وتقدم خدمات مثل تطوير العقود الذكية، واختبار الاختراق، واستشارات سلسلة الكتل.
-
Code4rena (يفتح في علامة تبويب جديدة) - منصة تدقيق تنافسية تحفز خبراء أمن العقود الذكية على العثور على الثغرات والمساعدة في جعل Web3 أكثر أماناً.
-
CodeHawks (يفتح في علامة تبويب جديدة) - منصة تدقيق تنافسية تستضيف مسابقات تدقيق العقود الذكية للباحثين الأمنيين.
-
Cyfrin (يفتح في علامة تبويب جديدة) - قوة رائدة في أمن Web3، تحتضن أمن الكريبتو من خلال المنتجات وخدمات تدقيق العقود الذكية.
-
ImmuneBytes (يفتح في علامة تبويب جديدة) - شركة أمن Web3 تقدم عمليات تدقيق أمني لأنظمة سلسلة الكتل من خلال فريق من المدققين ذوي الخبرة وأفضل الأدوات في فئتها.
-
Oxorio (يفتح في علامة تبويب جديدة) - عمليات تدقيق العقود الذكية وخدمات أمن سلسلة الكتل مع خبرة في آلة إيثريوم الافتراضية (EVM)، وSolidity، وإثبات المعرفة الصفرية (ZK)، وتكنولوجيا عبر السلاسل لشركات الكريبتو ومشاريع التمويل اللامركزي (DeFi).
-
Inference (يفتح في علامة تبويب جديدة) - شركة تدقيق أمني، متخصصة في تدقيق العقود الذكية لسلاسل الكتل القائمة على آلة إيثريوم الافتراضية (EVM). بفضل مدققيها الخبراء، يقومون بتحديد المشكلات المحتملة واقتراح حلول قابلة للتنفيذ لإصلاحها قبل النشر.
منصات مكافآت اكتشاف الثغرات
-
Immunefi (يفتح في علامة تبويب جديدة) - منصة مكافآت اكتشاف الثغرات للعقود الذكية ومشاريع التمويل اللامركزي (DeFi)، حيث يقوم الباحثون الأمنيون بمراجعة الكود، والإفصاح عن الثغرات، والحصول على أموال، وجعل الكريبتو أكثر أماناً.
-
HackerOne (يفتح في علامة تبويب جديدة) - منصة لتنسيق الثغرات ومكافآت اكتشافها تربط الشركات بمختبري الاختراق وباحثي الأمن السيبراني.
-
HackenProof (يفتح في علامة تبويب جديدة) - منصة متخصصة في مكافآت اكتشاف الثغرات لمشاريع الكريبتو (التمويل اللامركزي، العقود الذكية، المحافظ، منصات التداول المركزية والمزيد)، حيث يقدم محترفو الأمن خدمات الفرز ويحصل الباحثون على أموال مقابل تقارير الأخطاء ذات الصلة والمتحقق منها.
-
Sherlock (يفتح في علامة تبويب جديدة) - ضامن في Web3 لأمن العقود الذكية، مع إدارة مدفوعات المدققين عبر العقود الذكية لضمان دفع مكافآت الأخطاء ذات الصلة بشكل عادل.
-
CodeHawks (يفتح في علامة تبويب جديدة) - منصة تنافسية لمكافآت اكتشاف الثغرات حيث يشارك المدققون في مسابقات وتحديات أمنية، و(قريباً) في عمليات التدقيق الخاصة بهم.
منشورات حول الثغرات والاستغلالات المعروفة في العقود الذكية
-
كونسينسيس: الهجمات المعروفة على العقود الذكية (يفتح في علامة تبويب جديدة) - شرح مبسط للمبتدئين لأهم ثغرات العقود، مع كود نموذجي لمعظم الحالات.
-
سجل SWC (يفتح في علامة تبويب جديدة) - قائمة منسقة لعناصر تعداد نقاط الضعف الشائعة (CWE) التي تنطبق على عقود إيثيريوم الذكية.
-
Rekt (يفتح في علامة تبويب جديدة) - منشور يتم تحديثه بانتظام حول اختراقات واستغلالات الكريبتو البارزة، إلى جانب تقارير مفصلة بعد وقوع الحوادث.
تحديات لتعلم أمن العقود الذكية
-
Awesome BlockSec CTF (يفتح في علامة تبويب جديدة) - قائمة منسقة من ألعاب الحرب الأمنية لسلسلة الكتل، والتحديات، ومسابقات التقط العلم (Capture The Flag) (يفتح في علامة تبويب جديدة) ومقالات الحلول.
-
Damn Vulnerable DeFi (يفتح في علامة تبويب جديدة) - لعبة حرب لتعلم الأمن الهجومي لعقود التمويل اللامركزي (DeFi) الذكية وبناء المهارات في صيد الثغرات والتدقيق الأمني.
-
Ethernaut (يفتح في علامة تبويب جديدة) - لعبة حرب قائمة على Web3/Solidity حيث يكون كل مستوى عبارة عن عقد ذكي يحتاج إلى "اختراقه".
-
HackenProof x HackTheBox (يفتح في علامة تبويب جديدة) - تحدي اختراق العقود الذكية، تدور أحداثه في مغامرة خيالية. يتيح الإكمال الناجح للتحدي أيضاً الوصول إلى برنامج خاص لمكافآت اكتشاف الثغرات.
أفضل الممارسات لتأمين العقود الذكية
-
كونسينسيس: أفضل الممارسات الأمنية لعقود إيثيريوم الذكية (يفتح في علامة تبويب جديدة) - قائمة شاملة من الإرشادات لتأمين عقود إيثيريوم الذكية.
-
Nascent: مجموعة أدوات الأمان البسيطة (يفتح في علامة تبويب جديدة) - مجموعة من الأدلة العملية التي تركز على الأمان وقوائم المراجعة لتطوير العقود الذكية.
-
أنماط Solidity (يفتح في علامة تبويب جديدة) - تجميع مفيد للأنماط الآمنة وأفضل الممارسات للغة برمجة العقود الذكية Solidity.
-
مستندات Solidity: اعتبارات الأمان (يفتح في علامة تبويب جديدة) - إرشادات لكتابة عقود ذكية آمنة باستخدام Solidity.
-
معيار التحقق من أمان العقود الذكية (يفتح في علامة تبويب جديدة) - قائمة مراجعة من أربعة عشر جزءاً تم إنشاؤها لتوحيد أمان العقود الذكية للمطورين، والمهندسين المعماريين، والمراجعين الأمنيين، والموردين.
-
تعلم أمن وتدقيق العقود الذكية (يفتح في علامة تبويب جديدة) - الدورة التدريبية الشاملة لأمن وتدقيق العقود الذكية، تم إنشاؤها لمطوري العقود الذكية الذين يتطلعون إلى الارتقاء بأفضل ممارساتهم الأمنية ليصبحوا باحثين أمنيين.