في عالم العملات الرقمية، قد تؤدي نقرة خاطئة إلى حدوث “كارثة رقمية”. أحد أكثر الكوابيس شيوعًا هو إرسال الأصول إلى عنوان blockchain خاطئ. على سبيل المثال، كنت أريد إرسال ETH إلى عنوان على شبكة اختبار Sepolia الخاصة بـ Ethereum، لكنني أرسلتها عن غير قصد إلى عنوان على شبكة Ethereum الرئيسية. في مثل هذه الحالة، هل يمكن استرداد الأموال التي أرسلتها عن طريق الخطأ من الشبكة الرئيسية لإيثيريوم؟ وهل يمكن استرجاع الأصول أم لا، يعتمد الأمر بشكل رئيسي على نوع عنوان المستلم. ستتم التحليلات في هذا المقال حسب الحالات المختلفة.
1. السيناريو الأول: عنوان الاستلام هو EOA
EOA ( الحساب المملوك خارجيًا ) هو ببساطة عنوان محفظة عادي يتم التحكم فيه بواسطة المفتاح الخاص أو عبارة الاسترداد.
متطلبات استرداد الأصول:
قمت بتحويل الأصول إلى عنوان EOA.
تمتلك المفتاح الخاص أو عبارة الاسترداد لهذا العنوان المستهدف (عادةً هو عنوان محفظة آخر خاص بك، أو عنوان صديق، وهو مستعد للمساعدة).
السلسلة المستهدفة هي سلسلة متوافقة مع EVM.
طريقة استرداد الأصول:
مالك عنوان EOA المستلم يمكنه ببساطة سحب الأموال مباشرة على الشبكة المستهدفة.
2. السيناريو الثاني: عنوان الاستلام هو عقد ذكي
هذا أحد أكثر السيناريوهات يأسًا. نظرًا لأن عنوان العقد الذكي لا يتم إنشاؤه بواسطة مفتاح خاص، فلا يوجد أحد يملك المفتاح الخاص للعقد، وبالتالي، لا يمكن التحكم في هذا العقد مثلما يتم مع EOA. وإذا لم يكن هناك دالة معالجة “التحويل الخاطئ للأصول” في العقد مسبقًا، فالأموال التي أرسلت عن طريق الخطأ قد تبقى مغلقة بشكل دائم في العقد، ولا يمكن لأحد سحبها.
ومع ذلك، في بعض الحالات، هناك أمل ضئيل. سنقوم ببناء سيناريو حيث يتم قفل ETH في شبكة إيثيريوم الرئيسية، ثم نشرح كيف يمكن إنقاذ الأموال.
2.1. مقدمة السيناريو
باختصار، في هذا السيناريو، كان المستخدم ينوي استدعاء عقد على شبكة اختبار Sepolia، وتحويل ETH إلى العقد لعمل نسخة من التوكنات، لكنه أثناء إجراء المعاملة، اتصل بالشبكة الرئيسية عن غير قصد، مما أدى إلى قفل ETH في عقد على الشبكة الرئيسية. التفاصيل كما يلي:
1.على شبكة إيثيريوم Sepolia، قام فريق المشروع (EOA) بنشر عقد تنفيذ، ويفترض أن الوظيفة الأساسية لهذا العقد هي استقبال ETH من المستخدمين، لعمل نسخة من AToken، والكود المبدئي كالوظيفة mintTokens. العنوان الذي تم نشره هو A. من المهم ملاحظة أن، لا يوجد في A دالة تسمح مباشرة بسحب ETH.
2.على شبكة إيثيريوم Sepolia، قام فريق المشروع (EOA) بنشر عقد مصنع (factory contract)، ووظيفته هي نشر عقد وكيل (Proxy) باستخدام تقنية النسخ (Clones) استنادًا إلى عنوان العقد التنفيذي (implementation contract) و salt، بحيث يتم إنشاء عقد وكيل يشير إلى العقد التنفيذي (كما في دالة deployProxyByImplementation). العنوان المنشور هو B. هنا، استدعينا deployProxyByImplementation مع تمرير عنوان العقد A كـ _implementation، مما أدى إلى إنشاء عقد وكيل يشير إلى A، والعنوان الخاص به هو C.
3. المستخدم يريد على شبكة اختبار Sepolia، استدعاء عقد proxy C عبر تحويل ETH، بحيث يتم استدعاء وظيفة mintTokens في العقد A عبر الوكيل. عادةً، سيكون عقد الوكيل C ينفذ استدعاء إلى العقد A لتنفيذ العملية. لكن المستخدم قام أثناء ذلك بالاتصال بالشبكة الرئيسية (Mainnet) عن غير قصد. لذا، قام بتحويل ETH مباشرة إلى عنوان C على الشبكة الرئيسية. في الوقت الحالي، لا يوجد عقد على عنوان C في الشبكة الرئيسية، ولا يملك أحد المفتاح الخاص لهذا العنوان، لذلك، الأموال الآن مقفلة في عنوان C على الشبكة الرئيسية.
2.2. النقاط الأساسية
قبل شرح خطة الإنقاذ بالتفصيل، نُعطي لمحة عن المفاهيم الأساسية التي نحتاجها في عملية الإنقاذ.
2.2.1. create & create2
create و create2 هما طريقتان شائعتان لنشر العقود في Solidity.
create ينشئ عقدًا، ويعتمد عنوان العقد على عنوان المرسل وعدد المعاملات (nonce)، ولا يعتمد على محتوى العقد.
create2 لا يعتمد على nonce، بل يعتمد على أربعة عوامل:
0xff
عنوان العقد المنشئ (address))
القيمة المشوشة (salt)
الشيفرة الابتدائية (init_code) للعقد المراد إنشاؤه
العقد الوكيل الصغيرة، أو المعروفة أيضًا باسم العقود المستنسخة (Clones)، تعتمد على فكرة بسيطة: نشر عقد وكيل منخفض التكلفة (Gas) يشير إلى عقد تنفيذي محدد. يمكن نشرها باستخدام create أو create2، مثلاً من خلال دالة cloneDeterministic التي تستخدم create2.
في دالة cloneDeterministic، يكون الكود الخاص بالعقد الوكيل الناتج قصير جدًا، ويكون بصيغة: 0x363d3d373d3d3d363d73<عنوان العقد التنفيذي>5af43d82803e903d91602b57fd5bf3، حيث يتم تضمين عنوان العقد التنفيذي مباشرة في الكود، ويقوم كل استدعاء لهذا الوكيل بتنفيذ delegatecall إلى العقد التنفيذي.
كما أن دالة cloneDeterministic تستخدم create2، ونتيجة ذلك، فإن عنوان الوكيل الناتج يعتمد على عنوان المنشئ، و salt، والعقد التنفيذي، وليس على محتوى الكود الخاص بالعقد التنفيذي.
2.3. خطة الإنقاذ
الآن، سنشرح كيف يمكن إنقاذ ETH الموجودة على العنوان C في الشبكة الرئيسية. الفكرة الأساسية هي نشر كود عقد على عنوان العنوان C في الشبكة الرئيسية، بحيث يتم التحكم في العنوان، ويُسحب ETH منه. خطوة بخطوة:
1. نشر عقد مصنع (factory contract) على الشبكة الرئيسية بنفس العنوان B، نفس عنوان المصنع ضروري لأنه عند استدعاء دالة cloneDeterministic لنشر عقد الوكيل، حساب العنوان يعتمد على عنوان المصنع. من خلال مراجعة المعاملة التي أنشأت عقد المصنع على شبكة Sepolia، يمكن معرفة nonce الخاص بالمشروع (EOA) عند نشره. ثم، على الشبكة الرئيسية، ندفع nonce الخاص بالمشروع إلى نفس القيمة، وننشر عقد المصنع، وبما أن عنوان المنشئ و nonce مطابقان، فإن العنوان الناتج للعقد هو B نفسه.
2. نشر عقد تنفيذي (implementation contract) على الشبكة الرئيسية بنفس العنوان A، كما في جزء #最小代理合约(Clones)#، حيث أن حساب عنوان الوكيل باستخدام cloneDeterministic يعتمد على salt، والعقد التنفيذي، وليس على محتوى الكود. لذلك، يمكن نشر عقد واحد على عنوان A، ويجب أن يكون وظيفته استرجاع ETH. الكود أدناه كمثال.
بالنسبة لشبكة الاختبار،، العقد A يُنشر بواسطة فريق المشروع، لذا، عنوانه يعتمد فقط على المرسل و nonce الخاص به. من خلال مراجعة معاملات نشر العقد، يمكن معرفة nonce، ثم دفع عنوان المرسل إلى nonce المطلوب، ونشر العقد A.
3. نشر عقد وكيل على الشبكة الرئيسية بنفس العنوان C، من خلال مراجعة المعاملة التي أنشأت الوكيل C على شبكة الاختبار، نأخذ salt، ثم نستدعي دالة deployProxyByImplementation مع عنوان العقد A و salt، لنشر الوكيل على عنوان C في الشبكة الرئيسية.
4. استدعاء وظيفة السحب (withdraw) على عقد الوكيل C في الشبكة الرئيسية. يقوم مالك العقد (EOA) باستدعاء وظيفة withdraw، وتحديد المستلم، وبالتالي يتم سحب ETH المجمّد في العقد الوكيل C وإعادته للمستخدم.
2.4. الخلاصة
كما يظهر من خطة الإنقاذ أعلاه، إمكانية استرجاع الأموال تتطلب شروطًا عديدة، مثل أن يكون للمنشئ على الشبكة الهدف nonce غير مستخدم، وأن يحتوي العقد المغلق على وظيفة سحب، أو أن يكون من الممكن نشر وظيفة سحب عبر طرق مختلفة (مثل ترقية العقد أو باستخدام Clones).
لذا، عند إجراء المعاملات، يجب أن تكون حذرًا جدًا، وتتحقق من كل معاملة قبل تنفيذها مع العقود، ويمكنك استخدام أداة ZAN AI SCAN لفحص أمان العقود. وإذا حدث ووقعت في مشكلة قفل الأموال، فلا تقلق، يمكنك التواصل مع فريق تدقيق أمان العقود الخاص بـ ZAN لمحاولة إنقاذ أموالك.
تم كتابة هذا المقال بواسطة فريق ZAN (@zan_team)، وAntChain OpenLabs (@AntChainOpenLab)، وCara (@Cara6289).
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
سلسلة أمان Web3: هل يمكن إنقاذ الأموال التي تم تحويلها عن طريق الخطأ إلى سلسلة أخرى؟
في عالم العملات الرقمية، قد تؤدي نقرة خاطئة إلى حدوث “كارثة رقمية”. أحد أكثر الكوابيس شيوعًا هو إرسال الأصول إلى عنوان blockchain خاطئ. على سبيل المثال، كنت أريد إرسال ETH إلى عنوان على شبكة اختبار Sepolia الخاصة بـ Ethereum، لكنني أرسلتها عن غير قصد إلى عنوان على شبكة Ethereum الرئيسية. في مثل هذه الحالة، هل يمكن استرداد الأموال التي أرسلتها عن طريق الخطأ من الشبكة الرئيسية لإيثيريوم؟ وهل يمكن استرجاع الأصول أم لا، يعتمد الأمر بشكل رئيسي على نوع عنوان المستلم. ستتم التحليلات في هذا المقال حسب الحالات المختلفة.
1. السيناريو الأول: عنوان الاستلام هو EOA
EOA ( الحساب المملوك خارجيًا ) هو ببساطة عنوان محفظة عادي يتم التحكم فيه بواسطة المفتاح الخاص أو عبارة الاسترداد.
متطلبات استرداد الأصول:
طريقة استرداد الأصول:
مالك عنوان EOA المستلم يمكنه ببساطة سحب الأموال مباشرة على الشبكة المستهدفة.
2. السيناريو الثاني: عنوان الاستلام هو عقد ذكي
هذا أحد أكثر السيناريوهات يأسًا. نظرًا لأن عنوان العقد الذكي لا يتم إنشاؤه بواسطة مفتاح خاص، فلا يوجد أحد يملك المفتاح الخاص للعقد، وبالتالي، لا يمكن التحكم في هذا العقد مثلما يتم مع EOA. وإذا لم يكن هناك دالة معالجة “التحويل الخاطئ للأصول” في العقد مسبقًا، فالأموال التي أرسلت عن طريق الخطأ قد تبقى مغلقة بشكل دائم في العقد، ولا يمكن لأحد سحبها.
ومع ذلك، في بعض الحالات، هناك أمل ضئيل. سنقوم ببناء سيناريو حيث يتم قفل ETH في شبكة إيثيريوم الرئيسية، ثم نشرح كيف يمكن إنقاذ الأموال.
2.1. مقدمة السيناريو
باختصار، في هذا السيناريو، كان المستخدم ينوي استدعاء عقد على شبكة اختبار Sepolia، وتحويل ETH إلى العقد لعمل نسخة من التوكنات، لكنه أثناء إجراء المعاملة، اتصل بالشبكة الرئيسية عن غير قصد، مما أدى إلى قفل ETH في عقد على الشبكة الرئيسية. التفاصيل كما يلي:
1. على شبكة إيثيريوم Sepolia، قام فريق المشروع (EOA) بنشر عقد تنفيذ، ويفترض أن الوظيفة الأساسية لهذا العقد هي استقبال ETH من المستخدمين، لعمل نسخة من AToken، والكود المبدئي كالوظيفة mintTokens. العنوان الذي تم نشره هو A. من المهم ملاحظة أن، لا يوجد في A دالة تسمح مباشرة بسحب ETH.
2. على شبكة إيثيريوم Sepolia، قام فريق المشروع (EOA) بنشر عقد مصنع (factory contract)، ووظيفته هي نشر عقد وكيل (Proxy) باستخدام تقنية النسخ (Clones) استنادًا إلى عنوان العقد التنفيذي (implementation contract) و salt، بحيث يتم إنشاء عقد وكيل يشير إلى العقد التنفيذي (كما في دالة deployProxyByImplementation). العنوان المنشور هو B. هنا، استدعينا deployProxyByImplementation مع تمرير عنوان العقد A كـ _implementation، مما أدى إلى إنشاء عقد وكيل يشير إلى A، والعنوان الخاص به هو C.
3. المستخدم يريد على شبكة اختبار Sepolia، استدعاء عقد proxy C عبر تحويل ETH، بحيث يتم استدعاء وظيفة mintTokens في العقد A عبر الوكيل. عادةً، سيكون عقد الوكيل C ينفذ استدعاء إلى العقد A لتنفيذ العملية. لكن المستخدم قام أثناء ذلك بالاتصال بالشبكة الرئيسية (Mainnet) عن غير قصد. لذا، قام بتحويل ETH مباشرة إلى عنوان C على الشبكة الرئيسية. في الوقت الحالي، لا يوجد عقد على عنوان C في الشبكة الرئيسية، ولا يملك أحد المفتاح الخاص لهذا العنوان، لذلك، الأموال الآن مقفلة في عنوان C على الشبكة الرئيسية.
2.2. النقاط الأساسية
قبل شرح خطة الإنقاذ بالتفصيل، نُعطي لمحة عن المفاهيم الأساسية التي نحتاجها في عملية الإنقاذ.
2.2.1. create & create2
create و create2 هما طريقتان شائعتان لنشر العقود في Solidity.
2.2.2. العقود الوكيل الصغيرة (Clones)
العقد الوكيل الصغيرة، أو المعروفة أيضًا باسم العقود المستنسخة (Clones)، تعتمد على فكرة بسيطة: نشر عقد وكيل منخفض التكلفة (Gas) يشير إلى عقد تنفيذي محدد. يمكن نشرها باستخدام create أو create2، مثلاً من خلال دالة cloneDeterministic التي تستخدم create2.
في دالة cloneDeterministic، يكون الكود الخاص بالعقد الوكيل الناتج قصير جدًا، ويكون بصيغة: 0x363d3d373d3d3d363d73<عنوان العقد التنفيذي>5af43d82803e903d91602b57fd5bf3، حيث يتم تضمين عنوان العقد التنفيذي مباشرة في الكود، ويقوم كل استدعاء لهذا الوكيل بتنفيذ delegatecall إلى العقد التنفيذي.
كما أن دالة cloneDeterministic تستخدم create2، ونتيجة ذلك، فإن عنوان الوكيل الناتج يعتمد على عنوان المنشئ، و salt، والعقد التنفيذي، وليس على محتوى الكود الخاص بالعقد التنفيذي.
2.3. خطة الإنقاذ
الآن، سنشرح كيف يمكن إنقاذ ETH الموجودة على العنوان C في الشبكة الرئيسية. الفكرة الأساسية هي نشر كود عقد على عنوان العنوان C في الشبكة الرئيسية، بحيث يتم التحكم في العنوان، ويُسحب ETH منه. خطوة بخطوة:
1. نشر عقد مصنع (factory contract) على الشبكة الرئيسية بنفس العنوان B، نفس عنوان المصنع ضروري لأنه عند استدعاء دالة cloneDeterministic لنشر عقد الوكيل، حساب العنوان يعتمد على عنوان المصنع. من خلال مراجعة المعاملة التي أنشأت عقد المصنع على شبكة Sepolia، يمكن معرفة nonce الخاص بالمشروع (EOA) عند نشره. ثم، على الشبكة الرئيسية، ندفع nonce الخاص بالمشروع إلى نفس القيمة، وننشر عقد المصنع، وبما أن عنوان المنشئ و nonce مطابقان، فإن العنوان الناتج للعقد هو B نفسه.
2. نشر عقد تنفيذي (implementation contract) على الشبكة الرئيسية بنفس العنوان A، كما في جزء #最小代理合约(Clones)#، حيث أن حساب عنوان الوكيل باستخدام cloneDeterministic يعتمد على salt، والعقد التنفيذي، وليس على محتوى الكود. لذلك، يمكن نشر عقد واحد على عنوان A، ويجب أن يكون وظيفته استرجاع ETH. الكود أدناه كمثال.
بالنسبة لشبكة الاختبار،، العقد A يُنشر بواسطة فريق المشروع، لذا، عنوانه يعتمد فقط على المرسل و nonce الخاص به. من خلال مراجعة معاملات نشر العقد، يمكن معرفة nonce، ثم دفع عنوان المرسل إلى nonce المطلوب، ونشر العقد A.
3. نشر عقد وكيل على الشبكة الرئيسية بنفس العنوان C، من خلال مراجعة المعاملة التي أنشأت الوكيل C على شبكة الاختبار، نأخذ salt، ثم نستدعي دالة deployProxyByImplementation مع عنوان العقد A و salt، لنشر الوكيل على عنوان C في الشبكة الرئيسية.
4. استدعاء وظيفة السحب (withdraw) على عقد الوكيل C في الشبكة الرئيسية. يقوم مالك العقد (EOA) باستدعاء وظيفة withdraw، وتحديد المستلم، وبالتالي يتم سحب ETH المجمّد في العقد الوكيل C وإعادته للمستخدم.
2.4. الخلاصة
كما يظهر من خطة الإنقاذ أعلاه، إمكانية استرجاع الأموال تتطلب شروطًا عديدة، مثل أن يكون للمنشئ على الشبكة الهدف nonce غير مستخدم، وأن يحتوي العقد المغلق على وظيفة سحب، أو أن يكون من الممكن نشر وظيفة سحب عبر طرق مختلفة (مثل ترقية العقد أو باستخدام Clones).
لذا، عند إجراء المعاملات، يجب أن تكون حذرًا جدًا، وتتحقق من كل معاملة قبل تنفيذها مع العقود، ويمكنك استخدام أداة ZAN AI SCAN لفحص أمان العقود. وإذا حدث ووقعت في مشكلة قفل الأموال، فلا تقلق، يمكنك التواصل مع فريق تدقيق أمان العقود الخاص بـ ZAN لمحاولة إنقاذ أموالك.
تم كتابة هذا المقال بواسطة فريق ZAN (@zan_team)، وAntChain OpenLabs (@AntChainOpenLab)، وCara (@Cara6289).