لأغراض تعليمية فقط؛ لا يشكل ذلك نصيحة استثمارية أو توصية استثمارية. قد تؤدي الاستثمارات إلى خسائر.
الإجابة المباشرة
ترفض بعض تطبيقات ERC-20 استدعاء approve(spender, newAmount) عندما تكون قيمة allowance الحالية وnewAmount غير صفريتين. مع هذه الرموز، أرسل approve(spender, 0) أولًا وانتظر تأكيدها، ثم أرسل الموافقة الجديدة غير الصفرية.
هذا القيد ليس إلزاميًا لكل رموز ERC-20. يعرّف ERC-20 الدالة approve على أنها استبدال لقيمة allowance الحالية، ويوصي واجهات العميل بالتصفير أولًا لتخفيف سباق تغيير الموافقة، لكنه ينص أيضًا على أن عقود الرموز ينبغي ألا تفرض ذلك حفاظًا على التوافق. ومع ذلك تفرضه بعض الرموز المنشورة. لذلك فالتصفير أولًا إجراء للتوافق ونقطة تحقق مفيدة، لكنه لا يضمن عدم إنفاق allowance القديمة قبل تأكيد معاملة التصفير.
إن استكمال هذه المراجعة لا يثبت أن الأصل أو المعاملة أو النظام آمن.
آلية العمل
- تحقق من الشبكة وعقد الرمز والمالك وspender والمبلغ المقصود. اقرأ
allowance(owner, spender)من عقد الرمز بدل الاعتماد فقط على تسمية في المحفظة. - إذا كانت allowance تساوي
0بالفعل، فأرسل الموافقة المطلوبة مرة واحدة. وإذا كانت غير صفرية، فقد ينجح الاستبدال المباشر بقيمة أخرى غير صفرية في تطبيق قياسي أو يرتد في رمز يشترط التصفير أولًا. - في مسار التصفير، أرسل
approve(spender, 0)وانتظر إيصالًا ناجحًا. ثم اقرأ allowance للزوج نفسه من المالك وspender مجددًا وتأكد من أنها0. - أعد التحقق من رصيد الرمز وspender والغرض. بعد ذلك فقط أرسل
approve(spender, newAmount)وانتظر التأكيد قبل اعتبار allowance الجديدة نشطة. - تحقق من allowance النهائية وراجع أحداث
TransferوApprovalالتي وقعت في أثناء ذلك. يثبت الإيصال الناجح التنفيذ، بينما تعرض حالة العقد الحالية الإذن المتبقي.
تقدم SafeERC20.forceApprove من OpenZeppelin مسارًا احتياطيًا لتوافق العقود: فهي تجرب القيمة المطلوبة، وإذا فشل الاستدعاء تجرب 0 ثم القيمة المطلوبة. تغيّر هذه الأداة allowance الخاصة بالعقد المستدعي نفسه. ولا تصلح تلقائيًا موافقة محفظة المستخدم، ولا تلغي ضرورة التحقق من ترتيب المعاملات والحالة النهائية.
مثال
منح مالك spender قيمة allowance قدرها 1000 رمز ويريد خفضها إلى 100. في رمز يشترط التصفير أولًا، يرتد approve(spender, 100)، لذلك تبقى allowance على السلسلة 1000؛ فالاستدعاء المرتد لا يحدّث الحالة جزئيًا.
يرسل المالك بدلًا من ذلك approve(spender, 0). قبل تأكيدها يستخدم spender مقدار 400، فيتبقى 600؛ ثم تستبدل معاملة التصفير المؤكدة الباقي بقيمة 0. بعد فحص رصيد الرموز المنخفض، يستطيع المالك أن يقرر هل يمنح 100 الجديدة. إذا منحها، يكون spender قد استخدم 400 ويمكنه لاحقًا استخدام ما يصل إلى 100 إضافية. كشف التصفير أولًا الإنفاق الوسيط قبل منح الإذن الجديد، لكنه لم يتراجع عن ذلك الإنفاق.
المخاطر
- تبقى allowance القديمة قابلة للاستخدام حتى تنفيذ معاملة التصفير. قد يسبق spender إلغاءً أو خفضًا معلقًا.
- يؤدي بث معاملتي التصفير والاستبدال من دون انتظار التأكيد الأول إلى إزالة نقطة التحقق المقصودة، وقد يخفي إنفاقًا وسيطًا.
- قد يؤدي اختيار شبكة أو عنوان رمز أو عنوان spender خاطئ إلى إنشاء إذن مختلف عن المقصود أو إلغائه. رموز التداول ليست معرّفات فريدة.
- يكلف المسار المؤلف من خطوتين معاملتين عند الحاجة إليهما، وقد تفشل أي منهما أو تُستبدل أو تظل معلقة. لا تستنتج الحالة من مجرد إرسال توقيع.
- قد تعرّض الموافقات غير المحدودة وspender القابل للترقية أو المخترق الإيداعات المستقبلية للخطر. استخدم أقل مبلغ عملي وتحقق من allowance المتبقية بعد الاستخدام.
- يجب أن تتعامل تكاملات العقود عن قصد مع قيم الإرجاع وسلوك الموافقة غير القياسيين. غلاف التوافق لا يجعل spender غير الموثوق آمنًا.
مفاهيم خاطئة شائعة
- كل ERC-20 يشترط التصفير أولًا. يوصي المعيار بالتسلسل من جانب العميل، لكنه يقول إن عقود الرموز ينبغي ألا تفرضه؛ بعض التطبيقات فقط يرفض الانتقال بين قيمتين غير صفريتين.
- يحل التصفير أولًا سباق الموافقة بالكامل. يظل بإمكان spender استخدام allowance القديمة قبل تأكيد معاملة التصفير.
- أدى الاستبدال المرتد إلى مسح allowance القديمة. يلغي الارتداد تغيير الحالة الذي جرت محاولته، لذلك تبقى allowance السابقة عادة.
- إرسال المعاملتين معًا يعادل الانتظار. تنشأ نقطة التحقق الأمنية من تأكيد حالة الصفر وفحصها قبل اتخاذ قرار الاستبدال.
- يؤدي فصل موقع الويب إلى إلغاء موافقته. حالة اتصال المحفظة وallowance المسجلة على السلسلة في عقد الرمز أمران منفصلان.
مواضيع ذات صلة
المصادر
- ERC-20: معيار الرموز - Ethereum Improvement Proposals (تاريخ الاطلاع: 2026-08-21)
- ERC20 | وثائق OpenZeppelin - OpenZeppelin (تاريخ الاطلاع: 2026-08-21)
- SafeERC20.sol - OpenZeppelin (تاريخ الاطلاع: 2026-08-21)