الورقة البيضاء · 08
إطار الأمان
نموذج التهديدات، والثوابت، والتحكم في الوصول، وحدّ الثقة في الخطافات، وإدارة مفاتيح الإنفاذ، وسلامة الترقية، وموقف التدقيق لتنفيذ A-REX Core المرجعي.
الموقف الأمني في فقرة واحدة
للرمز المرجعي نقطة مرور واحدة (_update)، وترتيب تقييم ثابت، وقفل إعادة دخول حول تسلسل الخطافات بأكمله، وسلطة قائمة على الأدوار لا تُشتق أبدًا من الأرصدة، وتخزين وفق ERC-7201، وسطح صغير: ثماني دوال خارجية تغيّر الحالة فيما وراء ERC-1155. وأقوى القدرات — التجميد والتحويل القسري وإدارة الخطافات والترقيات — أدوار منفصلة مخصصة للتوقيعات المتعددة والتأخيرات الزمنية، وكل استخدام لها حدث.
الثوابت
| الثابت | يُفرَض بواسطة | يُختبَر بواسطة |
|---|---|---|
تساوي totalSupply(id) مجموع الأرصدة للمعرّف id | ERC1155Supply في OpenZeppelin؛ وtransform تحرق ثم تسك عبر _update | اختبارات النسب (التقسيم والدمج والمعالجة) |
الحالة status == 255 نهائية | تتراجع setBatchStatus بالخطأ ARexInvalidStatusTransition | اختبارات الحالة |
| لا يجوز السك ولا التحويل على دفعة مسحوبة من التداول، ويجوز الحرق فقط | _update | اختبار الدفعة المسحوبة من التداول |
amount ≤ balance − frozen في التحركات التي يبدؤها الحامل | _update؛ وforcedTransfer تخفض frozen إلى balance − amount | اختبارات التجميد/القسري |
| لا يستطيع أي خطاف إعادة دخول دالة تغيّر الأرصدة | قفل تخزين يُضبط قبل الفحوص ويُزال بعد الإشعارات | اختبار ReentrantHook |
كل تغيير في الرصيد يُقيَّم بوصفه عمليته هو، مع data الخاصة به | تقرأ _update سياق العملية وتمحوه قبل أي فحص أو استدعاء خارجي | OpContext.test.js |
| تُقيَّم الخطافات بترتيب التسجيل؛ والإزالة تحفظ الترتيب | إزاحة المصفوفة في removeHook | اختبار الترتيب |
| العملية المرفوضة لا تغيّر أي رصيد ولا تُصدر أي تحويل | تعمل الفحوص قبل super._update | اختبار الرفض (عدد استدعاءات التنفيذ دون تغيير) |
| لا تُشتق السلطة من الرصيد أبدًا | كل دالة تغيّر الحالة مقيّدة بدور أو بتفويض ERC-1155 | اختبارات "حيازة الرموز لا تمنح شيئًا" |
canTransfer == (transferCheck == 0) | تُعرَّف canTransfer على هذا النحو | اختبارات المطابقة |
نموذج التهديدات
الجهات الفاعلة وقدراتها
| الفاعل | يستطيع | لا يستطيع |
|---|---|---|
| الحامل | تحويل الكميات غير المجمّدة إلى مستلمين مؤهلين؛ والحرق؛ وإعادة تكوين الدفعة بالسلعة ووحدة القياس نفسيهما مع حفظ الكمية في حسابه هو (to == from) | تغيير الحالة، والسك، والمعالجة إلى سلعة أخرى، وإعادة تكوين الدفعة في حساب آخر، وتحريك الكميات المجمّدة |
| المشغّل المعتمد | مثل الحامل بالنسبة إلى الحساب المانح للتفويض | أي شيء لا يستطيعه الحامل |
ISSUER_ROLE | إنشاء الدفعات | نقل رموز الآخرين |
TRANSFORMER_ROLE | عمليات التحويل التصنيعي للمعالجة، وعمليات التحويل التصنيعي التي تذهب مخرجاتها إلى حساب آخر، على الرموز التي يحوزها أو المفوَّض بشأنها | التحويل التصنيعي للرموز دون تفويض |
STATUS_ROLE | تغيير الحالة (بما في ذلك السحب من التداول)، وتحديث البيانات الوصفية | نقل الرموز |
ENFORCER_ROLE | تجميد أي مقدار؛ وفرض أي تحويل | تجاوز الخطافات (فهي تعمل مع OP_FORCED_TRANSFER) |
HOOK_ADMIN_ROLE | إضافة الخطافات/إزالتها | تغيير الأرصدة مباشرة |
PAUSER_ROLE | إيقاف كل شيء عدا التحويلات القسرية | — |
UPGRADER_ROLE | استبدال التنفيذ | — (هذه سلطة كاملة؛ انظر إدارة المفاتيح) |
ATTEST_ADMIN_ROLE | تحديد جهات الإصدار الموثوقة لكل موضوع إفادة؛ وفي الإصدارات المرجعية حتى 2.0.0-alpha.5، إبطال أي إفادة أيضًا؛ وبدءًا من 2.0.0-alpha.6 لا يُبطلها إلا جهة الإصدار أو جهة إبطال فوّضتها (ADR-019، مقترح: لا ينبغي أن يوجد إبطال إداري في 2.x، ويجب ألا يوجد بدءًا من 3.0) | الإفادة باسم جهة إصدار |
| جهة الإصدار الموثوقة | الإفادة بشأن الدفعات في مواضيعها؛ وإبطال إفاداتها هي، أو تفويض الإبطال | الإفادة في موضوع ليست موثوقة فيه |
| عقد الخطاف | رفض العمليات؛ ومراقبتها؛ والإجابة عن الأهلية | إعادة الدخول؛ وتغيير الأرصدة |
السيناريوهات
خطاف خبيث أو معيب (حرمان من الخدمة). الخطاف الذي يرفض دائمًا يمنع جميع تحويلات الرمز؛ والخطاف الذي يتراجع في check يفعل الشيء نفسه. التخفيف: يستطيع HOOK_ADMIN_ROLE إزالة أي خطاف في أي وقت (مع حفظ الترتيب)؛ ويستطيع PAUSER_ROLE الإيقاف أثناء التحقيق؛ وتظل التحويلات القسرية تعمل، فلا يضيع الإنفاذ. ويتحقق التسجيل من دعم ERC-165 ومن أن الأعلام غير صفرية، ويرفض حسابات EOA. التوصية: دقّق الخطافات قبل تسجيلها؛ وأبقِ عددها صغيرًا؛ وضع المسؤول خلف تأخير زمني حتى تكون تغييرات الخطافات مرئية قبل أن تسري.
إعادة دخول الخطاف. تستدعي onExecuted في أحد الخطافات safeTransferFrom استدعاءً رجعيًا. التخفيف: القفل؛ إذ يتراجع الاستدعاء بالخطأ ARexReentrantCall. ويُلاحظ أن الاستدعاء الرجعي لمستقبِل ERC-1155 (onERC1155Received) يعمل بعد فتح القفل، كما في كل رمز ERC-1155؛ وتكون حالة الرمز نهائية عندئذ.
سياق العملية في الاستدعاءات الرجعية للمستقبِل. يبدأ مستلمٌ من نوع العقد تحويلًا أو حرقًا من داخل onERC1155Received. وهذا الاستدعاء المتداخل عملية OP_TRANSFER أو OP_BURN لها data الخاصة بها، وليس جزءًا من العملية التي سلّمت الرموز. وحتى 2.0.0-alpha.2 كان الرمز المرجعي يحتفظ بالعملية الخارجية في التخزين إلى أن يعود الاستدعاء الخارجي، فكان الاستدعاء المتداخل بعد forcedTransfer يعمل بوصفه OP_FORCED_TRANSFER (متجاوزًا الإيقاف والأهلية والأرصدة المجمّدة)، والاستدعاء المتداخل بعد transform يعمل بوصفه OP_TRANSFORM، الذي تسمح بمروره الخطافات التي لا تضبط إلا OP_TRANSFER. التخفيف: تقرأ _update سياق العملية وتمحوه قبل أي فحص أو استدعاء خارجي، فيُقيَّم الاستدعاء الصادر من استدعاء رجعي بوصفه عملية قائمة بذاتها؛ ويستخدم OpContext.test.js مستلمًا يحوّل ويحرق من داخل استدعائه الرجعي.
التسليم عبر إعادة تكوين الدفعة. تشغّل كلتا عمليتي transform الخطافات مع OP_TRANSFORM. فلو استطاع حامل إعادة تكوين الدفعة في حساب آخر، لانتقلت السلع من يد إلى يد دون فحوص الخطافات التي لا تضبط إلا OP_TRANSFER، مثل إفادة مطلوبة قبل البيع أو كمية مقفلة لتسليم. التخفيف: من دون TRANSFORMER_ROLE لا يُسمح بإعادة تكوين الدفعة إلا حين to == from؛ وتصل الدفعات المعاد تكوينها إلى حامل آخر عبر تحويل عادي تُطبَّق عليه كل قواعد التحويل (ADR-007، المعدَّل في 2026-10-20).
الإفلات من القفل بالحرق أو بإعادة تكوين الدفعة. حالة الخطاف المحفوظة لكل معرّف دفعة لا تتبع الدفعة إلى مخرجاتها. فالخطاف الذي يقفل كمية ولا يفحص إلا OP_TRANSFER لا يمنع الحامل من حرق الكمية المقفلة، أو من إعادة تكوينها في المكان في معرّف جديد لا يشمله القفل. التخفيف: يرفض DeliveryHook بالرمز IN_TRANSIT أي حرق أو أي عملية إدخال في transform من شأنها أن تُنزل الرصيد دون الكمية المقفلة؛ وتبقى التحويلات القسرية بلا حد، ويُرجع الخطاف رمزًا بدلًا من التراجع بعد الاستيلاء. وينبغي للخطافات التي تحجز كميات أن تفحص OP_BURN وOP_TRANSFORM إلى جانب OP_TRANSFER.
اختراق مفتاح الإنفاذ. من يحمل ENFORCER_ROLE يستطيع نقل أي رموز. التخفيف: توقيع متعدد بإجراء موثّق (أمر قضائي، أو اتفاقية رهن، أو إخطار عقوبات)؛ وكل إجراء يُصدر ForcedTransfer/Frozen؛ ويمكن للخطافات أن تشترط مرجع أمر في بيانات التحويل (فالعملية OP_FORCED_TRANSFER ليست معفاة من الخطافات). ويمكن النظر في استخدام تأخير زمني للإنفاذ غير العاجل.
اختراق القائم بالترقية. اختراق كامل. التخفيف: توقيع متعدد مع تأخير زمني؛ وفحوص الترقية الخاصة بـ OpenZeppelin في التكامل المستمر؛ وتخزين ERC-7201 لتجنب حوادث تخطيط التخزين.
إساءة استخدام الحالة. يستطيع STATUS_ROLE سحب دفعة يحوزها آخرون من التداول. وهذا مقصود — كأن يعلن مستودع أو مفتش أو جهة تنظيمية أن دفعة ما غير صالحة — ويجب الإفصاح عنه للحاملين. التخفيف: الإسناد إلى مؤسسة خاضعة للمساءلة؛ وكل تغيير حدث مقرون بسبب.
احتيال جهة الإصدار. يستطيع ISSUER_ROLE إنشاء دفعة لا وجود لها ماديًا. ولا يستطيع الرمز منع ذلك؛ لكنه يجعله منسوبًا إلى فاعل (issuer وoriginRef وmetadataHash) ويتيح اشتراط إفادات من أطراف مستقلة (المستودع، والمفتش، والسجل) قبل التحويل عبر AttestationHook.
موقع مخفي في مرجع المنشأ. تبدو التجزئة أو الـ geohash أو أي ترميز آخر لإحداثيات قطعة الأرض في originRef مجهولة الهوية، لكن يمكن إعادة حسابها من قطعة أرض مخمَّنة، ولا يمكن محوها من السجل أبدًا. التخفيف: originRef مرجع إلى دليل أو مرجع عشوائي؛ ويبقى الموقع الجغرافي خارج السلسلة (وفي حالة EUDR، في نظام معلومات الاتحاد الأوروبي). وتجعل المسودة المقترحة مع ADR-019 (مقترح) عبارة "لا يُشتق أبدًا من الموقع" إلزامية (MUST)؛ وقد كان ذلك أصلًا قرار ADR-008.
مراجع منبع لم يُتحقق منها. الدفعة المصنوعة من دفعة رمز آخر تسمّيها في قائمة upstream في بياناتها الوصفية. وهذا ادعاء من جهة الإصدار اللاحقة: فقد تسمّي دفعة لم تحزها قط، أو تُغفل دفعة حازتها. التخفيف: تتحقق المفهرسات والمدققون وأدوات السحب من السوق من كل مرجع مقابل رمز المنبع (أن الدفعة موجودة، وأن تجزئة البيانات الوصفية مطابقة، وأن التحويل إلى جهة الإصدار قد حدث حين تُعطى تجزئة المعاملة) وتعرض المراجع التي تعذّر التحقق منها بوصفها غير متحقَّق منها.
استبدال البيانات الوصفية. تغيّر setBatchMetadata التجزئة وعنوان URI. التخفيف: التقييد بدور؛ وتحفظ أحداث BatchMetadataUpdated وURI التاريخ؛ وتظل المستندات السابقة قابلة للتحقق مقابل التجزئات السابقة.
الركض الأمامي على transferCheck. يمكن أن يصبح الفحص المسبق قديمًا قبل تنفيذ المعاملة (إذ تتغير حالة خطاف). وتعيد المعاملة التقييم؛ وأسوأ الحالات تراجع مع كود دقيق.
استنزاف الغاز عبر الخطافات. يضيف كل خطاف استدعاءً خارجيًا واحدًا لكل معرّف متأثر في كل مرحلة. والخطاف الذي يحتوي حلقات غير محدودة يجعل التحويلات غير ميسورة الكلفة. التخفيف: قواعد كتابة الخطافات (دالة check محدودة)، والمراجعة قبل التسجيل.
الثقة في الخطافات القابلة للترقية. يستطيع خطاف منشور خلف وكيل تغيير سياسة التحويل دون أي تغيير في الرمز. التخفيف: عامِل مفاتيح إدارة الخطافات بالعناية نفسها التي تعامل بها HOOK_ADMIN_ROLE؛ وفضّل الخطافات غير القابلة للتغيير في الإنتاج.
نموذج التحكم في الوصول
يستخدم النظام AccessControl من OpenZeppelin بثمانية أدوار على الرمز ودور واحد على سجل الإفادات؛ ويدير DEFAULT_ADMIN_ROLE جميعها. والتوزيع الموصى به في بيئة الإنتاج:
| الدور | الحامل |
|---|---|
DEFAULT_ADMIN_ROLE، UPGRADER_ROLE، HOOK_ADMIN_ROLE | توقيع متعدد للحوكمة خلف تأخير زمني |
ENFORCER_ROLE | توقيع متعدد للإنفاذ (الامتثال + الشؤون القانونية) |
PAUSER_ROLE | مفتاح الاستجابة للحوادث (سريع) |
ISSUER_ROLE، STATUS_ROLE، TRANSFORMER_ROLE | خدمات تشغيلية بأقل الصلاحيات، مع تدوير المفاتيح |
ATTEST_ADMIN_ROLE | حوكمة الرمز: تحدد جهات الإصدار الموثوقة لكل موضوع، لا ما تُفيد به تلك الجهات |
تمنح initialize كل شيء لمسؤول واحد للتيسير؛ وتشترط قائمة التحقق الخاصة بالنشر إعادة التوزيع قبل الإنتاج.
دلالات الإنفاذ والإيقاف المؤقت
- يمنع الإيقاف المؤقت عمليات السك والتحويل والحرق والتحويل التصنيعي؛ لكنه لا يمنع التحويلات القسرية، ولذلك يمكن تنفيذ أمر قانوني أثناء حادث.
- تتجاوز التحويلات القسرية
canSend/canReceiveوفحص الرصيد المجمّد، وتخفض المقدار المجمّد إلى ما تبقى، وتشغّل الخطافات معOP_FORCED_TRANSFER. وتُرجع الخطافات المرجعيةOKلتلك العملية؛ ويجوز لخطاف يحكم الإنفاذ أن يشترط مراجع أوامر فيdata. - يجوز أن يتجاوز التجميد الرصيد (ERC-7943)، ولذلك يمكن لحق امتياز أن يشمل الإيداعات المستقبلية.
القدرات في المعيار، والسياسات في ملفات السياسات
يرسم ADR-019 (مقترح) خطًا واحدًا عبر كل ميزات الإنفاذ. فالمعيار يثبّت ما هو موجود وما يضمنه: الأدوار، والأحداث، وما يوقفه الإيقاف المؤقت، والكودان AREX:PAUSED وAREX:SANCTIONED، ومن يجوز له إبطال الإفادة، وقواعد الخصوصية. أما ملف السياسات، الذي يُحفظ لكل ولاية قضائية ولكل مؤسسة وتُؤرَّخ إصداراته كما تُؤرَّخ اللوائح، فيحدد من يجوز له استخدام كل قدرة وبأي شروط:
| القدرة | ما يثبّته المعيار | ما يحدده ملف السياسات |
|---|---|---|
| التجميد والتحويل القسري | setFrozenTokens وforcedTransfer وأحداثهما، ودور مخصص منفصل عن الإدارة، وتشغيل الخطافات مع OP_FORCED_TRANSFER | هل يجوز تفعيل الدور أصلًا، ومن يحمله وبكم موقّعًا، وأي مرجع قانوني يجب أن يحمله كل استخدام، ومن يجب إخطاره |
| الإيقاف المؤقت | ما يوقفه الإيقاف المؤقت، وAREX:PAUSED، وبقاء التحويلات القسرية مسموحة | من يجوز له الإيقاف والاستئناف، والتأكيد والسبب المطلوبان، ومن يُبلَّغ |
| العقوبات | AREX:SANCTIONED ومعنى canSend / canReceive | أي القوائم الرسمية تنطبق (UN أو OFAC أو EU أو OFSI أو مزيج منها)، وكيف تُحدَّث، وأن يؤكد شخص التطابق قبل وسم أي حساب |
| إبطال الإفادة | تُبطلها جهة الإصدار، ويجوز ذلك لجهة إبطال فوّضتها؛ ولا ينبغي ذلك لدور إداري في 2.x، ويجب ألا يكون له ذلك بدءًا من 3.0؛ وإعادة الإفادة لا تستبدل أبدًا سجل جهة إصدار أخرى ولا تُحيي سجلًا مُبطَلًا | أي جهات الإصدار يثق بها الرمز لكل موضوع؛ وكيف يسجّل المشغّل نزاعًا |
| خصوصية المنشأ | لا يحمل originRef إحداثيات ولا معرّفات شخصية، ولا يُشتق من الموقع | أي مرجع تستخدمه جهة الإصدار، وأين يُحفظ الموقع الجغرافي خارج السلسلة |
وبذلك يصبح تغيّر القانون تحديثًا للملف، لا عقدًا جديدًا ولا إصدارًا جديدًا من المعيار أبدًا.
سلامة الترقية
- UUPS؛ و
_authorizeUpgradeمقيّدة بـUPGRADER_ROLE. - هيكل تخزين بفضاء أسماء وفق ERC-7201؛ بالإلحاق فقط.
- تعمل فحوص إضافة الترقيات الخاصة بـ OpenZeppelin في الاختبارات، وينبغي أن تعمل في التكامل المستمر قبل أي معاملة ترقية.
- يُبقي إعداد
optimizer.runs = 1الخاص بالملف التنفيذ تحت حد EIP-170؛ وأي تغيير يدفعه فوق الحد يفشل وقت الترجمة بتحذير وعند النشر بتراجع.
أمان الاعتماديات والبناء
- تثبيت OpenZeppelin Contracts وContracts-Upgradeable عند 5.3.0؛ وإيداع ملف القفل؛ ويستخدم التكامل المستمر
npm ci. - Solidity 0.8.22، وviaIR، وEVM
paris(دون اعتماد على التخزين العابر، وقابل للنشر على سلاسل لم تعتمد Cancun). - لا مكتبات خارجية مرتبطة؛ ولا delegatecall خارج وكيل UUPS.
موقف التدقيق
- 46 اختبارًا على التنفيذ المرجعي والخطافات والامتدادات تغطي كل ثابت أعلاه، بما في ذلك تشغيل عشوائي للثوابت ببذرة محددة.
- يُقاس الغاز والحجم بسكربتات في المستودع.
- يُعد تدقيق من طرف ثالث لـ
ARexTokenوARexAttestationsوالخطافات المرجعية شرطًا مسبقًا معلنًا لوجود مشارك محوري في الإنتاج ولتقديم ERC (انظر التطورات المستقبلية). - التحقق الصوري من ثوابت المسار مدرج في خارطة الطريق؛ والثوابت صغيرة بما يكفي لصياغتها خصائص.
النشرات الأمنية
| النشرة | تؤثر في | أُصلحت في | المشكلات |
|---|---|---|---|
| AREX-2026-001 | التنفيذ المرجعي حتى 2.0.0-alpha.2 وبما يشمله | 2.0.0-alpha.3 | تسرّب سياق العملية إلى الاستدعاءات الرجعية لمستقبِل ERC-1155؛ وكان بوسع إعادة تكوين الدفعة دون دور أن تسلّم السلع إلى حامل آخر متجاوزةً خطافات OP_TRANSFER؛ وكان يمكن الإفلات من أقفال DeliveryHook بالحرق أو بإعادة تكوين الدفعة |
يحلّ 2.0.0-alpha.3 محلّ 2.0.0-alpha.2. وتُرقّى وكلاء الرمز المنشورة إلى التنفيذ الجديد عبر UPGRADER_ROLE؛ ولا يتغير تخطيط التخزين. أما DeliveryHook فغير قابل للترقية: انشر الإصدار الجديد، وسجّله بـ registerHook، وأزل القديم بـ removeHook، وأعد جدولة عمليات التسليم الجارية، لأن أقفالها محفوظة في تخزين الخطاف القديم. وعلى عمليات التكامل التي تقسّم أو تدمج مباشرة في حساب المشتري أن تعيد تكوين الدفعة في المكان ثم تحوّل، أو أن تستخدم حسابًا يحمل TRANSFORMER_ROLE. ولا تتغير واجهات المعيار.
المخاطر المتبقية التي لا يزيلها المعيار
- الوجود المادي للدفعة وجودتها يُفاد بهما ولا يُثبتان؛ والرمز يجعل الادعاءات منسوبة إلى أصحابها، لا صحيحة.
- يعتمد توافر البيانات الوصفية خارج السلسلة على التخزين المختار؛ والتجزئة تضمن السلامة، لا التوافر.
- حوكمة الخطافات والوحدات لا تفوق في جودتها جودة المفاتيح التي تتحكم فيها.