اختبار العقود الذكية
سلاسل الكتل العامة مثل إيثيريوم غير قابلة للتغيير، مما يجعل من الصعب تغيير كود العقد الذكي بعد النشر. توجد أنماط ترقية العقد لإجراء "ترقيات افتراضية"، ولكن يصعب تنفيذها وتتطلب إجماعًا اجتماعيًا. علاوة على ذلك، لا يمكن للترقية إصلاح الخطأ إلا بعد اكتشافه — إذا اكتشف المهاجم الثغرة الأمنية أولاً، فإن عقدك الذكي معرض لخطر الاستغلال.
لهذه الأسباب، يعد اختبار العقود الذكية قبل النشر على الشبكة الرئيسية حدًا أدنى من متطلبات الأمان. هناك العديد من التقنيات لاختبار العقود وتقييم صحة الكود؛ وما تختاره يعتمد على احتياجاتك. ومع ذلك، فإن مجموعة الاختبار المكونة من أدوات وأساليب مختلفة تعتبر مثالية لاكتشاف العيوب الأمنية الطفيفة والكبيرة في كود العقد.
المتطلبات الأساسية
تشرح هذه الصفحة كيفية اختبار العقود الذكية قبل النشر على شبكة إيثيريوم. وتفترض أنك على دراية بـ العقود الذكية.
ما هو اختبار العقود الذكية؟
اختبار العقود الذكية هو عملية التحقق من أن كود العقد الذكي يعمل كما هو متوقع. الاختبار مفيد للتحقق مما إذا كان عقد ذكي معين يلبي متطلبات الموثوقية وقابلية الاستخدام والأمان.
على الرغم من اختلاف الأساليب، تتطلب معظم طرق الاختبار تنفيذ عقد ذكي باستخدام عينة صغيرة من البيانات التي يُتوقع أن يتعامل معها. إذا أنتج العقد نتائج صحيحة لبيانات العينة، يُفترض أنه يعمل بشكل صحيح. توفر معظم أدوات الاختبار موارد لكتابة وتنفيذ حالات الاختبار (opens in a new tab) للتحقق مما إذا كان تنفيذ العقد يتطابق مع النتائج المتوقعة.
لماذا من المهم اختبار العقود الذكية؟
نظرًا لأن العقود الذكية غالبًا ما تدير أصولًا مالية عالية القيمة، فإن أخطاء البرمجة الطفيفة يمكن أن تؤدي وغالبًا ما تؤدي إلى خسائر فادحة للمستخدمين (opens in a new tab). ومع ذلك، يمكن أن يساعدك الاختبار الصارم في اكتشاف العيوب والمشكلات في كود العقد الذكي مبكرًا وإصلاحها قبل الإطلاق على الشبكة الرئيسية.
في حين أنه من الممكن ترقية العقد إذا تم اكتشاف خطأ، فإن الترقيات معقدة ويمكن أن تؤدي إلى أخطاء (opens in a new tab) إذا تم التعامل معها بشكل غير صحيح. كما أن ترقية العقد تنفي مبدأ عدم القابلية للتغيير وتثقل كاهل المستخدمين بافتراضات الثقة الإضافية. على العكس من ذلك، فإن الخطة الشاملة لاختبار عقدك تخفف من المخاطر الأمنية للعقود الذكية وتقلل من الحاجة إلى إجراء ترقيات منطقية معقدة بعد النشر.
طرق اختبار العقود الذكية
تندرج طرق اختبار العقود الذكية على إيثيريوم تحت فئتين عريضتين: الاختبار الآلي والاختبار اليدوي. يقدم الاختبار الآلي والاختبار اليدوي فوائد ومقايضات فريدة، ولكن يمكنك الجمع بينهما لإنشاء خطة قوية لتحليل عقودك.
الاختبار الآلي
يستخدم الاختبار الآلي أدوات تتحقق تلقائيًا من كود العقد الذكي بحثًا عن أخطاء في التنفيذ. تأتي فائدة الاختبار الآلي من استخدام البرامج النصية (opens in a new tab) لتوجيه تقييم وظائف العقد. يمكن جدولة الاختبارات المبرمجة لتعمل بشكل متكرر بأقل تدخل بشري، مما يجعل الاختبار الآلي أكثر كفاءة من طرق الاختبار اليدوية.
يكون الاختبار الآلي مفيدًا بشكل خاص عندما تكون الاختبارات متكررة وتستغرق وقتًا طويلاً؛ أو يصعب إجراؤها يدويًا؛ أو عرضة للخطأ البشري؛ أو تتضمن تقييم وظائف العقد الحرجة. لكن أدوات الاختبار الآلي يمكن أن يكون لها عيوب — فقد تفوت بعض الأخطاء وتنتج العديد من النتائج الإيجابية الخاطئة (opens in a new tab). وبالتالي، فإن إقران الاختبار الآلي بالاختبار اليدوي للعقود الذكية هو الحل الأمثل.
الاختبار اليدوي
الاختبار اليدوي يتم بمساعدة بشرية ويتضمن تنفيذ كل حالة اختبار في مجموعة الاختبار الخاصة بك واحدة تلو الأخرى عند تحليل صحة العقد الذكي. هذا على عكس الاختبار الآلي حيث يمكنك تشغيل اختبارات معزولة متعددة في وقت واحد على عقد والحصول على تقرير يوضح جميع الاختبارات الفاشلة والناجحة.
يمكن إجراء الاختبار اليدوي بواسطة فرد واحد يتبع خطة اختبار مكتوبة تغطي سيناريوهات اختبار مختلفة. يمكنك أيضًا جعل عدة أفراد أو مجموعات يتفاعلون مع عقد ذكي خلال فترة محددة كجزء من الاختبار اليدوي. سيقارن المختبرون السلوك الفعلي للعقد بالسلوك المتوقع، مع الإبلاغ عن أي اختلاف كخطأ.
يتطلب الاختبار اليدوي الفعال موارد كبيرة (المهارة والوقت والمال والجهد)، ومن الممكن — بسبب الخطأ البشري — تفويت بعض الأخطاء أثناء تنفيذ الاختبارات. لكن الاختبار اليدوي يمكن أن يكون مفيدًا أيضًا — على سبيل المثال، قد يستخدم المختبر البشري (مثل المدقق) الحدس لاكتشاف الحالات الطرفية التي قد تفوتها أداة الاختبار الآلي.
الاختبار الآلي للعقود الذكية
اختبار الوحدة
يُقيّم اختبار الوحدة وظائف العقد بشكل منفصل ويتحقق من أن كل مكون يعمل بشكل صحيح. يجب أن تكون اختبارات الوحدة الجيدة بسيطة وسريعة التشغيل وتوفر فكرة واضحة عما حدث من خطأ في حالة فشل الاختبارات.
تعتبر اختبارات الوحدة مفيدة للتحقق من أن الوظائف تُرجع القيم المتوقعة وأن تخزين العقد يتم تحديثه بشكل صحيح بعد تنفيذ الوظيفة. علاوة على ذلك، فإن تشغيل اختبارات الوحدة بعد إجراء تغييرات على قاعدة كود العقد يضمن أن إضافة منطق جديد لا يؤدي إلى حدوث أخطاء. فيما يلي بعض الإرشادات لتشغيل اختبارات وحدة فعالة:
إرشادات لاختبار وحدة العقود الذكية
1. فهم منطق العمل وسير العمل لعقدك
قبل كتابة اختبارات الوحدة، من المفيد معرفة الوظائف التي يقدمها العقد الذكي وكيف سيصل المستخدمون إلى تلك الوظائف ويستخدمونها. هذا مفيد بشكل خاص لتشغيل اختبارات المسار السعيد (opens in a new tab) التي تحدد ما إذا كانت الوظائف في العقد تُرجع المخرجات الصحيحة لمدخلات المستخدم الصالحة. سنشرح هذا المفهوم باستخدام هذا المثال (المختصر) لـ عقد مزاد (opens in a new tab)
constructor(
uint biddingTime,
address payable beneficiaryAddress
) {
beneficiary = beneficiaryAddress;
auctionEndTime = block.timestamp + biddingTime;
}
function bid() external payable {
if (block.timestamp > auctionEndTime)
revert AuctionAlreadyEnded();
if (msg.value <= highestBid)
revert BidNotHighEnough(highestBid);
if (highestBid != 0) {
pendingReturns[highestBidder] += highestBid;
}
highestBidder = msg.sender;
highestBid = msg.value;
emit HighestBidIncreased(msg.sender, msg.value);
}
function withdraw() external returns (bool) {
uint amount = pendingReturns[msg.sender];
if (amount > 0) {
pendingReturns[msg.sender] = 0;
if (!payable(msg.sender).send(amount)) {
pendingReturns[msg.sender] = amount;
return false;
}
}
return true;
}
function auctionEnd() external {
if (block.timestamp < auctionEndTime)
revert AuctionNotYetEnded();
if (ended)
revert AuctionEndAlreadyCalled();
ended = true;
emit AuctionEnded(highestBidder, highestBid);
beneficiary.transfer(highestBid);
}
}
هذا عقد مزاد بسيط مصمم لتلقي العطاءات خلال فترة تقديم العطاءات. إذا زاد highestBid، يتلقى صاحب أعلى عطاء سابق أمواله؛ وبمجرد انتهاء فترة تقديم العطاءات، يستدعي beneficiary العقد للحصول على أمواله.
ستغطي اختبارات الوحدة لعقد مثل هذا وظائف مختلفة قد يستدعيها المستخدم عند التفاعل مع العقد. مثال على ذلك هو اختبار الوحدة الذي يتحقق مما إذا كان بإمكان المستخدم تقديم عطاء أثناء استمرار المزاد (أي نجاح استدعاءات bid()) أو اختبار يتحقق مما إذا كان بإمكان المستخدم تقديم عطاء أعلى من highestBid الحالي.
يساعد فهم سير العمل التشغيلي للعقد أيضًا في كتابة اختبارات الوحدة التي تتحقق مما إذا كان التنفيذ يلبي المتطلبات. على سبيل المثال، يحدد عقد المزاد أنه لا يمكن للمستخدمين تقديم عطاءات عند انتهاء المزاد (أي عندما يكون auctionEndTime أقل من block.timestamp). وبالتالي، قد يقوم المطور بتشغيل اختبار وحدة يتحقق مما إذا كانت استدعاءات وظيفة bid() تنجح أو تفشل عند انتهاء المزاد (أي عندما يكون auctionEndTime > block.timestamp).
2. تقييم جميع الافتراضات المتعلقة بتنفيذ العقد
من المهم توثيق أي افتراضات حول تنفيذ العقد وكتابة اختبارات وحدة للتحقق من صحة تلك الافتراضات. بصرف النظر عن توفير الحماية ضد التنفيذ غير المتوقع، فإن اختبار التأكيدات يجبرك على التفكير في العمليات التي يمكن أن تكسر النموذج الأمني للعقود الذكية. نصيحة مفيدة هي تجاوز "اختبارات المستخدم السعيد" وكتابة اختبارات سلبية تتحقق مما إذا كانت الوظيفة تفشل عند إدخال بيانات خاطئة.
تسمح لك العديد من أطر عمل اختبار الوحدة بإنشاء تأكيدات — عبارات بسيطة توضح ما يمكن للعقد وما لا يمكنه فعله — وتشغيل اختبارات لمعرفة ما إذا كانت تلك التأكيدات تصمد أثناء التنفيذ. يمكن للمطور الذي يعمل على عقد المزاد الموصوف سابقًا تقديم التأكيدات التالية حول سلوكه قبل تشغيل الاختبارات السلبية:
-
لا يمكن للمستخدمين تقديم عطاءات عندما ينتهي المزاد أو لم يبدأ بعد.
-
يتراجع عقد المزاد إذا كان العطاء أقل من الحد المقبول.
-
يتم إضافة أموال المستخدمين الذين يفشلون في الفوز بالعطاء إلى حساباتهم.
ملاحظة: طريقة أخرى لاختبار الافتراضات هي كتابة اختبارات تُشغّل مُعدِّلات الوظائف (opens in a new tab) في العقد، وخاصة عبارات require و assert و if…else.
3. قياس تغطية الكود
تغطية الكود (opens in a new tab) هي مقياس اختبار يتتبع عدد الفروع والأسطر والعبارات في الكود الخاص بك التي تم تنفيذها أثناء الاختبارات. يجب أن تتمتع الاختبارات بتغطية كود جيدة لتقليل مخاطر الثغرات الأمنية غير المختبرة. بدون تغطية كافية، قد تفترض خطأً أن عقدك آمن لأن جميع الاختبارات تنجح، بينما لا تزال الثغرات الأمنية موجودة في مسارات الكود غير المختبرة. ومع ذلك، فإن تسجيل تغطية كود عالية يعطي ضمانًا بأن جميع العبارات/الوظائف في العقد الذكي قد تم اختبارها بشكل كافٍ للتأكد من صحتها.
4. استخدام أطر عمل اختبار متطورة
تعتبر جودة الأدوات المستخدمة في تشغيل اختبارات الوحدة لعقودك الذكية أمرًا بالغ الأهمية. إطار عمل الاختبار المثالي هو الذي يتم صيانته بانتظام؛ ويوفر ميزات مفيدة (مثل إمكانيات التسجيل وإعداد التقارير)؛ ويجب أن يكون قد تم استخدامه وفحصه على نطاق واسع من قبل مطورين آخرين.
تأتي أطر عمل اختبار الوحدة للعقود الذكية المكتوبة بلغة Solidity بلغات مختلفة (في الغالب JavaScript و Python و Rust). راجع بعض الأدلة أدناه للحصول على معلومات حول كيفية البدء في تشغيل اختبارات الوحدة باستخدام أطر عمل اختبار مختلفة:
- تشغيل اختبارات الوحدة باستخدام Brownie (opens in a new tab)
- تشغيل اختبارات الوحدة باستخدام Foundry (opens in a new tab)
- تشغيل اختبارات الوحدة باستخدام Waffle (opens in a new tab)
- تشغيل اختبارات الوحدة باستخدام Remix (opens in a new tab)
- تشغيل اختبارات الوحدة باستخدام Ape (opens in a new tab)
- تشغيل اختبارات الوحدة باستخدام Hardhat (opens in a new tab)
- تشغيل اختبارات الوحدة باستخدام Wake (opens in a new tab)
اختبار التكامل
بينما يقوم اختبار الوحدة بتصحيح أخطاء وظائف العقد بشكل منفصل، تُقيّم اختبارات التكامل مكونات العقد الذكي ككل. يمكن لاختبار التكامل اكتشاف المشكلات الناشئة عن الاستدعاءات عبر العقود أو التفاعلات بين الوظائف المختلفة في نفس العقد الذكي. على سبيل المثال، يمكن أن تساعد اختبارات التكامل في التحقق مما إذا كانت أشياء مثل الوراثة (opens in a new tab) وحقن التبعية تعمل بشكل صحيح.
يكون اختبار التكامل مفيدًا إذا كان عقدك يعتمد بنية معيارية أو يتفاعل مع عقود أخرى على السلسلة أثناء التنفيذ. إحدى طرق تشغيل اختبارات التكامل هي عند ارتفاع معين (باستخدام أداة مثل Forge (opens in a new tab) أو Hardhat (opens in a new tab) ومحاكاة التفاعلات بين عقدك والعقود المنشورة.
ستتصرف سلسلة الكتل المتفرعة بشكل مشابه للشبكة الرئيسية وستحتوي على حسابات ذات حالات وأرصدة مرتبطة بها. لكنها تعمل فقط كبيئة تطوير محلية معزولة، مما يعني أنك لن تحتاج إلى ETH حقيقي للمعاملات، على سبيل المثال، ولن تؤثر تغييراتك على بروتوكول إيثيريوم الحقيقي.
الاختبار القائم على الخصائص
الاختبار القائم على الخصائص هو عملية التحقق من أن العقد الذكي يلبي خاصية محددة. تؤكد الخصائص حقائق حول سلوك العقد والتي يُتوقع أن تظل صحيحة في سيناريوهات مختلفة — مثال على خاصية العقد الذكي يمكن أن يكون "العمليات الحسابية في العقد لا تتجاوز السعة أبدًا بالزيادة أو النقصان".
التحليل الثابت والتحليل الديناميكي هما تقنيتان شائعتان لتنفيذ الاختبار القائم على الخصائص، وكلاهما يمكنه التحقق من أن كود البرنامج (عقد ذكي في هذه الحالة) يلبي بعض الخصائص المحددة مسبقًا. تأتي بعض أدوات الاختبار القائم على الخصائص بقواعد محددة مسبقًا حول خصائص العقد المتوقعة وتتحقق من الكود مقابل تلك القواعد، بينما يسمح لك البعض الآخر بإنشاء خصائص مخصصة لعقد ذكي.
التحليل الثابت
يأخذ المحلل الثابت كمدخل الكود المصدري لعقد ذكي ويخرج نتائج تعلن ما إذا كان العقد يلبي خاصية أم لا. على عكس التحليل الديناميكي، لا يتضمن التحليل الثابت تنفيذ عقد لتحليله للتأكد من صحته. بدلاً من ذلك، يستنتج التحليل الثابت جميع المسارات الممكنة التي يمكن أن يتخذها العقد الذكي أثناء التنفيذ (أي من خلال فحص بنية الكود المصدري لتحديد ما سيعنيه ذلك لعملية العقد في وقت التشغيل).
يعد فحص الكود (Linting) (opens in a new tab) والاختبار الثابت (opens in a new tab) من الطرق الشائعة لتشغيل التحليل الثابت على العقود. يتطلب كلاهما تحليل تمثيلات منخفضة المستوى لتنفيذ العقد مثل أشجار النحو المجردة (opens in a new tab) ورسوم بيانية لتدفق التحكم (opens in a new tab) التي يخرجها المترجم.
في معظم الحالات، يكون التحليل الثابت مفيدًا لاكتشاف مشكلات السلامة مثل استخدام بنيات غير آمنة، أو أخطاء في بناء الجملة، أو انتهاكات لمعايير الترميز في كود العقد. ومع ذلك، من المعروف أن المحللات الثابتة غير سليمة بشكل عام في اكتشاف الثغرات الأمنية الأعمق، وقد تنتج نتائج إيجابية خاطئة مفرطة.
التحليل الديناميكي
يولد التحليل الديناميكي مدخلات رمزية (على سبيل المثال، في التنفيذ الرمزي (opens in a new tab)) أو مدخلات ملموسة (على سبيل المثال، في الاختبار العشوائي (fuzzing) (opens in a new tab)) لوظائف العقد الذكي لمعرفة ما إذا كان أي تتبع (تتبعات) للتنفيذ ينتهك خصائص محددة. يختلف هذا الشكل من الاختبار القائم على الخصائص عن اختبارات الوحدة في أن حالات الاختبار تغطي سيناريوهات متعددة ويتعامل البرنامج مع إنشاء حالات الاختبار.
يعد الاختبار العشوائي (Fuzzing) (opens in a new tab) مثالاً على تقنية التحليل الديناميكي للتحقق من الخصائص التعسفية في العقود الذكية. يستدعي المُختبِر العشوائي (fuzzer) وظائف في عقد مستهدف بتنويعات عشوائية أو مشوهة لقيمة إدخال محددة. إذا دخل العقد الذكي في حالة خطأ (على سبيل المثال، حالة يفشل فيها التأكيد)، يتم الإبلاغ عن المشكلة ويتم إنتاج المدخلات التي تدفع التنفيذ نحو المسار الضعيف في تقرير.
يعد الاختبار العشوائي مفيدًا لتقييم آلية التحقق من صحة إدخال العقد الذكي نظرًا لأن التعامل غير السليم مع المدخلات غير المتوقعة قد يؤدي إلى تنفيذ غير مقصود وينتج عنه تأثيرات خطيرة. يمكن أن يكون هذا الشكل من الاختبار القائم على الخصائص مثاليًا لأسباب عديدة:
-
كتابة حالات اختبار لتغطية العديد من السيناريوهات أمر صعب. يتطلب اختبار الخاصية فقط تحديد سلوك ونطاق من البيانات لاختبار السلوك به — يقوم البرنامج تلقائيًا بإنشاء حالات اختبار بناءً على الخاصية المحددة.
-
قد لا تغطي مجموعة الاختبار الخاصة بك جميع المسارات الممكنة داخل البرنامج بشكل كافٍ. حتى مع تغطية بنسبة 100%، من الممكن تفويت الحالات الطرفية.
-
تثبت اختبارات الوحدة أن العقد يتم تنفيذه بشكل صحيح لبيانات العينة، ولكن ما إذا كان العقد يتم تنفيذه بشكل صحيح للمدخلات خارج العينة يظل غير معروف. تنفذ اختبارات الخصائص عقدًا مستهدفًا بتنويعات متعددة لقيمة إدخال معينة للعثور على تتبعات التنفيذ التي تسبب فشل التأكيد. وبالتالي، يوفر اختبار الخاصية المزيد من الضمانات بأن العقد يتم تنفيذه بشكل صحيح لفئة واسعة من بيانات الإدخال.
إرشادات لتشغيل الاختبار القائم على الخصائص للعقود الذكية
يبدأ تشغيل الاختبار القائم على الخصائص عادةً بتحديد خاصية (على سبيل المثال، عدم وجود تجاوز السعة للأعداد الصحيحة (opens in a new tab)) أو مجموعة من الخصائص التي تريد التحقق منها في عقد ذكي. قد تحتاج أيضًا إلى تحديد نطاق من القيم التي يمكن للبرنامج من خلالها إنشاء بيانات لمدخلات المعاملة عند كتابة اختبارات الخصائص.
بمجرد تكوينها بشكل صحيح، ستقوم أداة اختبار الخصائص بتنفيذ وظائف عقودك الذكية بمدخلات تم إنشاؤها عشوائيًا. إذا كانت هناك أي انتهاكات للتأكيد، فيجب أن تحصل على تقرير ببيانات إدخال ملموسة تنتهك الخاصية قيد التقييم. راجع بعض الأدلة أدناه للبدء في تشغيل الاختبار القائم على الخصائص باستخدام أدوات مختلفة:
- التحليل الثابت للعقود الذكية باستخدام سليذر (opens in a new tab)
- التحليل الثابت للعقود الذكية باستخدام Wake (opens in a new tab)
- الاختبار القائم على الخصائص باستخدام Brownie (opens in a new tab)
- الاختبار العشوائي للعقود باستخدام Foundry (opens in a new tab)
- الاختبار العشوائي للعقود باستخدام إيكيدنا (opens in a new tab)
- الاختبار العشوائي للعقود باستخدام Wake (opens in a new tab)
- التنفيذ الرمزي للعقود الذكية باستخدام مانتيكور (opens in a new tab)
- التنفيذ الرمزي للعقود الذكية باستخدام Mythril (opens in a new tab)
الاختبار اليدوي للعقود الذكية
غالبًا ما يأتي الاختبار اليدوي للعقود الذكية لاحقًا في دورة التطوير بعد تشغيل الاختبارات الآلية. يُقيّم هذا الشكل من الاختبار العقد الذكي كمنتج واحد متكامل تمامًا لمعرفة ما إذا كان يعمل كما هو محدد في المتطلبات الفنية.
اختبار العقود على سلسلة كتل محلية
في حين أن الاختبار الآلي الذي يتم إجراؤه في بيئة تطوير محلية يمكن أن يوفر معلومات مفيدة لتصحيح الأخطاء، فستحتاج إلى معرفة كيف يتصرف عقدك الذكي في بيئة الإنتاج. ومع ذلك، فإن النشر على سلسلة إيثيريوم الرئيسية يتكبد رسوم غاز — ناهيك عن أنك أو مستخدميك يمكن أن تفقدوا أموالًا حقيقية إذا كان عقدك الذكي لا يزال يحتوي على أخطاء.
يعد اختبار عقدك على سلسلة كتل محلية (تُعرف أيضًا باسم شبكة التطوير) بديلاً موصى به للاختبار على الشبكة الرئيسية. سلسلة الكتل المحلية هي نسخة من سلسلة كتل إيثيريوم تعمل محليًا على جهاز الكمبيوتر الخاص بك والتي تحاكي سلوك طبقة التنفيذ في إيثيريوم. على هذا النحو، يمكنك برمجة المعاملات للتفاعل مع عقد دون تكبد نفقات عامة كبيرة.
يمكن أن يكون تشغيل العقود على سلسلة كتل محلية مفيدًا كشكل من أشكال اختبار التكامل اليدوي. العقود الذكية قابلة للتركيب بدرجة عالية، مما يسمح لك بالتكامل مع البروتوكولات الحالية — ولكنك ستظل بحاجة إلى التأكد من أن مثل هذه التفاعلات المعقدة على السلسلة تنتج النتائج الصحيحة.
اختبار العقود على شبكات الاختبار
تعمل شبكة الاختبار تمامًا مثل شبكة إيثيريوم الرئيسية، باستثناء أنها تستخدم إيثر (ETH) ليس له قيمة في العالم الحقيقي. نشر عقدك على شبكة اختبار يعني أنه يمكن لأي شخص التفاعل معه (على سبيل المثال، عبر الواجهة الأمامية للتطبيق اللامركزي (dapp)) دون تعريض الأموال للخطر.
هذا الشكل من الاختبار اليدوي مفيد لتقييم التدفق الشامل لتطبيقك من وجهة نظر المستخدم. هنا، يمكن لمختبري الإصدار التجريبي (بيتا) أيضًا إجراء عمليات تشغيل تجريبية والإبلاغ عن أي مشكلات تتعلق بمنطق عمل العقد والوظائف العامة.
يعد النشر على شبكة اختبار بعد الاختبار على سلسلة كتل محلية أمرًا مثاليًا لأن الأولى أقرب إلى سلوك آلة إيثيريوم الافتراضية. لذلك، من الشائع للعديد من المشاريع الأصلية على إيثيريوم نشر التطبيقات اللامركزية (dapps) على شبكات الاختبار لتقييم عملية العقود الذكية في ظل ظروف العالم الحقيقي.
المزيد عن شبكات اختبار إيثيريوم.
الاختبار مقابل التحقق الشكلي
في حين أن الاختبار يساعد في تأكيد أن العقد يُرجع النتائج المتوقعة لبعض مدخلات البيانات، فإنه لا يمكن أن يثبت بشكل قاطع نفس الشيء للمدخلات التي لم يتم استخدامها أثناء الاختبارات. لذلك، لا يمكن لاختبار العقد الذكي ضمان "الصحة الوظيفية" (أي أنه لا يمكن أن يُظهر أن البرنامج يتصرف كما هو مطلوب لـ جميع مجموعات قيم الإدخال).
التحقق الشكلي هو نهج لتقييم صحة البرامج عن طريق التحقق مما إذا كان النموذج الشكلي للبرنامج يتطابق مع المواصفات الشكلية. النموذج الشكلي هو تمثيل رياضي مجرد لبرنامج، بينما تحدد المواصفات الشكلية خصائص البرنامج (أي التأكيدات المنطقية حول تنفيذ البرنامج).
نظرًا لأن الخصائص مكتوبة بمصطلحات رياضية، يصبح من الممكن التحقق من أن النموذج الشكلي (الرياضي) للنظام يلبي المواصفات باستخدام قواعد الاستدلال المنطقية. وبالتالي، يُقال إن أدوات التحقق الشكلي تنتج "دليلًا رياضيًا" على صحة النظام.
على عكس الاختبار، يمكن استخدام التحقق الشكلي للتحقق من أن تنفيذ العقد الذكي يلبي مواصفات شكلية لـ جميع عمليات التنفيذ (أي أنه لا يحتوي على أخطاء) دون الحاجة إلى تنفيذه باستخدام بيانات العينة. لا يقلل هذا من الوقت المستغرق في تشغيل العشرات من اختبارات الوحدة فحسب، بل إنه أيضًا أكثر فعالية في اكتشاف الثغرات الأمنية الخفية. ومع ذلك، تقع تقنيات التحقق الشكلي على طيف واسع اعتمادًا على صعوبة تنفيذها وفائدتها.
المزيد عن التحقق الشكلي للعقود الذكية.
الاختبار مقابل عمليات التدقيق ومكافآت اكتشاف الأخطاء
كما ذكرنا، نادرًا ما يضمن الاختبار الصارم عدم وجود أخطاء في العقد؛ يمكن أن توفر مناهج التحقق الشكلي ضمانات أقوى للصحة ولكن يصعب استخدامها حاليًا وتتكبد تكاليف كبيرة.
ومع ذلك، يمكنك زيادة إمكانية اكتشاف الثغرات الأمنية في العقد من خلال الحصول على مراجعة مستقلة للكود. تعد عمليات تدقيق العقود الذكية (opens in a new tab) ومكافآت اكتشاف الأخطاء (opens in a new tab) طريقتين لجعل الآخرين يحللون عقودك.
يتم إجراء عمليات التدقيق بواسطة مدققين ذوي خبرة في العثور على حالات العيوب الأمنية وممارسات التطوير السيئة في العقود الذكية. عادةً ما تتضمن عملية التدقيق الاختبار (وربما التحقق الشكلي) بالإضافة إلى مراجعة يدوية لقاعدة الكود بأكملها.
على العكس من ذلك، يتضمن برنامج مكافآت اكتشاف الأخطاء عادةً تقديم مكافأة مالية لفرد (يُوصف عادةً بـ قراصنة القبعة البيضاء (opens in a new tab) يكتشف ثغرة أمنية في عقد ذكي ويكشف عنها للمطورين. تتشابه مكافآت اكتشاف الأخطاء مع عمليات التدقيق لأنها تتضمن مطالبة الآخرين بالمساعدة في العثور على عيوب في العقود الذكية.
الفرق الرئيسي هو أن برامج مكافآت اكتشاف الأخطاء مفتوحة لمجتمع المطورين/القراصنة الأوسع وتجذب فئة واسعة من القراصنة الأخلاقيين ومحترفي الأمن المستقلين ذوي المهارات والخبرات الفريدة. قد يكون هذا ميزة على عمليات تدقيق العقود الذكية التي تعتمد بشكل أساسي على فرق قد تمتلك خبرة محدودة أو ضيقة.
أدوات ومكتبات الاختبار
أدوات اختبار الوحدة
-
solidity-coverage (opens in a new tab) - أداة تغطية الكود للعقود الذكية المكتوبة بلغة Solidity.
-
Waffle (opens in a new tab) - إطار عمل لتطوير واختبار العقود الذكية المتقدمة (يعتمد على Ethers.js).
-
Remix Tests (opens in a new tab) - أداة لاختبار العقود الذكية المكتوبة بلغة Solidity. تعمل تحت المكون الإضافي "Solidity Unit Testing" في بيئة التطوير المتكاملة Remix والذي يُستخدم لكتابة وتشغيل حالات الاختبار للعقد.
-
أوبن زبلن Test Helpers (opens in a new tab) - مكتبة تأكيد لاختبار العقود الذكية على إيثيريوم. تأكد من أن عقودك تتصرف كما هو متوقع!
-
إطار عمل اختبار الوحدة Brownie (opens in a new tab) - يستخدم Brownie إطار عمل Pytest، وهو إطار اختبار غني بالميزات يتيح لك كتابة اختبارات صغيرة بأقل قدر من الكود، ويتوسع بشكل جيد للمشاريع الكبيرة، وقابل للتوسيع بدرجة كبيرة.
-
Foundry Tests (opens in a new tab) - تقدم Foundry أداة Forge، وهي إطار عمل اختبار سريع ومرن لإيثيريوم قادر على تنفيذ اختبارات وحدة بسيطة، وفحوصات تحسين استهلاك الغاز، والاختبار العشوائي للعقود.
-
Hardhat Tests (opens in a new tab) - إطار عمل لاختبار العقود الذكية يعتمد على Ethers.js و Mocha و Chai.
-
ApeWorx (opens in a new tab) - إطار عمل للتطوير والاختبار يعتمد على Python للعقود الذكية التي تستهدف آلة إيثيريوم الافتراضية.
-
Wake (opens in a new tab) - إطار عمل يعتمد على Python لاختبار الوحدة والاختبار العشوائي مع إمكانات قوية لتصحيح الأخطاء ودعم الاختبار عبر السلاسل، باستخدام pytest و Anvil للحصول على أفضل تجربة مستخدم وأداء.
أدوات الاختبار القائم على الخصائص
أدوات التحليل الثابت
-
سليذر (opens in a new tab) - إطار عمل للتحليل الثابت للغة Solidity يعتمد على Python للعثور على الثغرات الأمنية، وتعزيز فهم الكود، وكتابة تحليلات مخصصة للعقود الذكية.
-
Ethlint (opens in a new tab) - أداة فحص كود (Linter) لفرض أفضل ممارسات الأسلوب والأمان للغة برمجة العقود الذكية Solidity.
-
Cyfrin Aderyn (opens in a new tab) - محلل ثابت يعتمد على Rust مصمم خصيصًا لأمان وتطوير العقود الذكية في Web3.
-
Wake (opens in a new tab) - إطار عمل للتحليل الثابت يعتمد على Python مع كاشفات للثغرات الأمنية وجودة الكود، وطابعات لاستخراج معلومات مفيدة من الكود ودعم لكتابة وحدات فرعية مخصصة.
-
Slippy (opens in a new tab) - أداة فحص كود (Linter) بسيطة وقوية للغة Solidity.
أدوات التحليل الديناميكي
-
إيكيدنا (opens in a new tab) - أداة اختبار عشوائي سريعة للعقود لاكتشاف الثغرات الأمنية في العقود الذكية من خلال الاختبار القائم على الخصائص.
-
Diligence Fuzzing (opens in a new tab) - أداة اختبار عشوائي آلية مفيدة لاكتشاف انتهاكات الخصائص في كود العقد الذكي.
-
مانتيكور (opens in a new tab) - إطار عمل للتنفيذ الرمزي الديناميكي لتحليل رمز البايت لآلة إيثيريوم الافتراضية (EVM).
-
Mythril (opens in a new tab) - أداة تقييم رمز البايت لآلة إيثيريوم الافتراضية (EVM) لاكتشاف الثغرات الأمنية في العقد باستخدام تحليل التلوث (taint analysis)، والتحليل الرمزي الملموس (concolic analysis)، والتحقق من تدفق التحكم.
-
Diligence Scribble (opens in a new tab) - Scribble هي لغة مواصفات وأداة تحقق في وقت التشغيل تتيح لك إضافة تعليقات توضيحية للعقود الذكية بخصائص تسمح لك باختبار العقود تلقائيًا باستخدام أدوات مثل Diligence Fuzzing أو MythX.
برامج تعليمية ذات صلة
- نظرة عامة ومقارنة بين منتجات الاختبار المختلفة _
- كيفية استخدام إيكيدنا لاختبار العقود الذكية
- كيفية استخدام مانتيكور للعثور على أخطاء العقود الذكية
- كيفية استخدام سليذر للعثور على أخطاء العقود الذكية
- كيفية محاكاة عقود Solidity للاختبار
- كيفية تشغيل اختبارات الوحدة في Solidity باستخدام Foundry (opens in a new tab)
قراءة إضافية
- دليل متعمق لاختبار العقود الذكية على إيثيريوم (opens in a new tab)
- كيفية اختبار العقود الذكية على إيثيريوم (opens in a new tab)
- دليل اختبار الوحدة للمطورين من MolochDAO (opens in a new tab)
- كيفية اختبار العقود الذكية كالمحترفين (opens in a new tab)
برامج تعليمية: اختبار العقود الذكية على إيثيريوم
- كيفية تطوير واختبار تطبيق لامركزي (dapp) على شبكة اختبار محلية متعددة العملاء – إرشادات تفصيلية لنشر عقد ذكي على شبكة اختبار محلية وإجراء الاختبارات.
- كيفية محاكاة العقود الذكية المكتوبة بلغة Solidity للاختبار – برنامج تعليمي متوسط حول كيفية استخدام البيانات الوهمية وتنفيذ اختبار الوحدة.
- كيفية استخدام إيكيدنا لاختبار العقود الذكية – نهج متقدم للاختبار العشوائي واختبار العقود الذكية.