لقد قمت مؤخرا بإعادة تعلم الصلابة ، ودمج التفاصيل ، وكتابة “Solidity Minimalist Primer” للمبتدئين لاستخدامها (يمكن لرجال البرمجة العثور على برنامج تعليمي آخر) ، يتم تحديثه 1-3 مرات في الأسبوع.
جميع التعليمات البرمجية والبرامج التعليمية مفتوحة المصدر على GitHub: github.com/AmazingAng/WTFSolidity
في المحاضرة 17: إرسال ETH ، تحدثنا عن استخدام Call لإرسال ETH ، وفي هذه المحاضرة سنوضح لك كيفية استخدامه لاستدعاء العقود.
Call هي وظيفة عضو منخفضة المستوى من نوع العنوان ، والتي تستخدم للتفاعل مع العقود الأخرى. يتم إرجاع (bool ، data) ، والذي يتوافق مع نجاح المكالمة وقيمة إرجاع الوظيفة الموضوعية ، على التوالي.
call هي الطريقة الموصى بها رسميا لإرسال ETH عن طريق تشغيل الوظائف الاحتياطية أو المستلمة عن طريق الصلابة. لا يوصى باستدعاء عقد آخر بمكالمة ، لأنه عندما تستدعي وظيفة عقد غير آمن ، فإنك تعطيه المبادرة. لا تزال الطريقة الموصى بها هي استدعاء الوظيفة بعد إعلان متغير العقد ، راجع المحاضرة 19: استدعاء العقود الأخرى. إذا كنا لا نعرف شفرة المصدر أو ABI لعقد الطرف الآخر ، فلا يمكننا إنشاء متغيرات العقد ، ولكن لا يزال بإمكاننا استدعاء وظائف عقد الطرف الآخر من خلال الاتصال.
قواعد استخدام المكالمة هي كما يلي:

يستخدم الترميز الثنائي وظيفة الترميز الهيكلية abi.encodeWithSignature للحصول على:

توقيع الدالة هو “اسم الوظيفة (نوع المعلمة المفصولة بفواصل)”. على سبيل المثال، abi.encodeWithSignature(“f(uint256,address)”, _x, _addr).
بالإضافة إلى ذلك ، عند استدعاء العقد ، يمكنك تحديد كمية ETH والغاز التي سيتم إرسالها بواسطة المعاملة:

يبدو الأمر معقدا بعض الشيء ، لذلك لنأخذ مثالا على تطبيق المكالمة.
لنبدأ بكتابة عقد هدف بسيط ، OtherContract ، ونشره ، الكود هو نفسه في الأساس كما في المحاضرة 19 ، باستثناء إضافة وظيفة احتياطية.

يحتوي هذا العقد على متغير حالة x وسجل أحداث يتم تشغيله عند تلقي ETH وثلاث وظائف:
getBalance(): إرجاع رصيد ETH للعقد. setX (): وظيفة خارجية مستحقة الدفع ، والتي يمكنها تعيين قيمة x وإرسال ETH إلى العقد. getX (): يقرأ قيمة x.
دعنا نكتب عقد Call لاستدعاء وظيفة العقد المستهدف. بادئ ذي بدء ، اكتب تعريفا لحدث الاستجابة ، وقم بإخراج النجاح والبيانات التي تم إرجاعها بواسطة المكالمة ، حتى نتمكن من ملاحظة القيمة المرجعة.

نحدد الدالة callSetX لاستدعاء setX () للعقد الهدف ، ونقل مقدار ETH إلى msg.value ، وإصدار حدث الاستجابة لنجاح الإخراج والبيانات:

بعد ذلك ، نستدعي callSetX لتغيير متغير الحالة _x إلى 5 ، والمعلمات هي عنوان OtherContract و 5 ، لأن الدالة الموضوعية setX () لا ترجع قيمة ، وبالتالي فإن إخراج البيانات لحدث الاستجابة هو 0x ، وهو فارغ.
دعنا نسمي الدالة getX () ، والتي سترجع قيمة العقد الهدف _x ، من النوع uint256. يمكننا استخدام abi.decode لفك تشفير القيمة المرتجعة للمكالمة والبيانات وقراءة القيمة.

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

في المثال أعلاه ، أطلقنا على وظيفة foo غير الموجودة. لا يزال من الممكن تنفيذ المكالمة بنجاح وإرجاع النجاح ، ولكنها في الواقع الوظيفة الاحتياطية للعقد المستهدف الذي تم استدعاؤه.
في هذا الحديث ، أوضحنا كيفية استخدام استدعاء الوظيفة منخفضة المستوى لاستدعاء العقود الأخرى. Call ليست الطريقة الموصى بها لاستدعاء عقد لأنها غير آمنة. ولكن من المفيد السماح لنا بالاتصال بالعقد المستهدف دون معرفة شفرة المصدر و ABI.