Skip to main contentA-REX Foundation

الورقة البيضاء · 07

الخطافات والوحدات المرجعية

كيف تُضاف الوظائف إلى رمز مطابق دون المساس بالمعيار: عقد الخطاف، والخطافات المرجعية، والامتدادات المرافقة، وكيفية كتابة خطافك الخاص واختباره وتسجيله.

الوحدات عروض توضيحية، وليست المعيار

العلاقة بين A-REX Core ووحداتها هي العلاقة نفسها بين ERC-3643 ووحدات الامتثال في T-REX: الواجهة التي تتصل بها الوحدات موحَّدة؛ أما الوحدات فليست كذلك. والرمز المطابق الذي لا خطاف له رمز A-REX صالح. والخطاف الذي يكتبه أي شخص متوافق مع كل رمز مطابق. وهذا ما يجعل المنظومة تنمو دون أن يتغير المعيار.

graph LR
    T["ARexToken<br/>رمز مطابق"] -->|"check / onExecuted / canSend / canReceive"| H1[EligibilityHook]
    T --> H2[ExpiryHook]
    T --> H3[AttestationHook]
    T --> H4["خطافك الخاص"]
    H3 --> A[ARexAttestations]

عقد الخطاف

الاستدعاءمتىما يجب عليه
checkقبل تغيّر الأرصدة، لكل معرّف متأثر، بترتيب تسجيل الخطافات، مع التوقف عند أول قيمة غير صفريةأن تكون دالة عرض؛ وألا تتراجع أبدًا لأسباب تتعلق بالسياسة
onExecutedبعد تغيّر الأرصدة، لكل معرّف، بالترتيبألا تستدعي دوال الرمز التي تغيّر الأرصدة (فالرمز مقفل)
canSend / canReceiveعند كل تحويل ولدوال عرض ERC-7943 في الرمزأن تكونا دالتَي عرض

تكون op واحدة من OP_MINT (1) وOP_TRANSFER (2) وOP_BURN (3) وOP_FORCED_TRANSFER (4) وOP_TRANSFORM (5). وفي التحويل التصنيعي تصل المدخلات بـ to == 0 والمخرجات بـ from == 0. وdata هي بيانات تحويل ERC-1155، وهي abi.encode(processRef) في عمليات التحويل التصنيعي، وفارغة في التحويلات القسرية.

الرمز المستدعي هو msg.sender. والخطاف الذي يحتاج إلى الدفعة يقرأ IARexBatch(msg.sender).batchOf(id). والخطاف المرتبط برمز واحد عند نشره (ADR-025، مقترح) يعلن عنه عبر token() ويرفض الاستدعاءات من أي عنوان آخر.

حين تقرأ أكثر من قاعدة data، يجعلها ADR-023 (مقترح) مظروفًا موسومًا: حتى 8 مُدخلات (bytes32 key, bytes32 value)، مفاتيحها في نطاقات أسماء مثل الأكواد (keccak256("AREX:DELIVERY_ID")، وkeccak256("AREX:DOCUMENT_REF"))، ولا تقرأ كل قاعدة إلا مفتاحها. وتحتفظ data ذات الـ32 بايت بالمعنى الوحيد الذي كان لها من قبل لدى كل قاعدة؛ وأي محتوى آخر لا يحمل قيمة، ولا تتراجع القراءة أبدًا. والقاعدة المكتوبة قبل المظروف تقرؤه على أنه بلا قيمة، لذا لا يبني المُرسِل مظروفًا إلا حين تكون كل قواعد الرمز التي تقرأ data قادرة على قراءة المظاريف. ويفعل ذلك DeliveryHook وTraceabilityHook المرجعيان بدءًا من الإصدار 2.0.0-alpha.7.

الخطافات المرجعية

EligibilityHook — السماح والحظر والعقوبات

يوضّح HOOK_ELIGIBILITY. ويحتفظ بقائمة سماح اختيارية وقائمة حظر وقائمة عقوبات؛ وتُرجع canSend/canReceive اقترانهما المنطقي؛ وتُرجع check القيمة SANCTIONED أو SENDER_INELIGIBLE أو RECEIVER_INELIGIBLE كي تتمكن واجهات المستخدم من تفسير الرفض. والتحويلات القسرية مسموحة دائمًا: فحجز السلع من حساب خاضع للعقوبات هو جوهر الإنفاذ. وفي بيئة الإنتاج تُغذَّى القوائم من سجل هوية (ONCHAINID أو EAS أو بيانات الاعتماد القابلة للتحقق) أو من أوراكل عقوبات؛ ولا يهتم الخطاف بأيهما.

ExpiryHook — قابلية التلف دون وحدة

بلا حالة. يقرأ expiresAt وproducedAt من الدفعة. يمنع سك الدفعات المنتهية الصلاحية وتحويلها (BATCH_EXPIRED) لكنه لا يمنع الحرق (الشطب) ولا التحويلات القسرية (الإنفاذ). ويمنع اختياريًا تحويل الدفعات التي لم تُنتَج بعد (BATCH_NOT_PRODUCED) — فالمنصة التي تموّل ما قبل الحصاد تضبط العلم للسماح بها؛ والسوق الفورية تضبطه لمنعها. ويغطي هذا الخطاف وحده جزء المنع من قابلية التلف؛ أما منحنيات التدهور فتصبح دالة عرض مساعدة أو تقييمًا خارج السلسلة.

AttestationHook — تقييد تنظيمي لكل سلعة

يربط كود السلعة بموضوع إفادة مطلوب. وقبل التحويل يقرأ الدفعة، ويبحث عن المتطلب، ويسأل سجل الإفادات isAttested، ويُرجع ATTESTATION_MISSING في غير ذلك. فعبارات "يحتاج البن إلى مرجع عناية واجبة وفق EUDR"، و"تحتاج الدفعات الموسومة بأنها عضوية إلى شهادة عضوية سارية"، و"تحتاج الماشية إلى شهادة صحية" يتحقق كل منها باستدعاء واحد إلى setRequirement. وبدءًا من الإصدار المرجعي 2.0.0-alpha.7 يمكن لمالكه تفعيل checksTransform (معطّل افتراضيًا): وعندئذ تحتاج دفعات الإدخال في transform إلى شهادتها أيضًا، فلا يستطيع حامل لديه TRANSFORMER_ROLE أن يسلّم دفعة غير معتمدة إلى حساب آخر في صورة دفعة جديدة. أما المخرجات فهي دفعات جديدة ولا تُفحص.

PerishabilityHook — نماذج التدهور

ضبط التدهور لكل كود سلعة مع تجاوز لكل دفعة؛ والنماذج NONE وLINEAR (حتى حد أدنى عند انتهاء الصلاحية) وEXPONENTIAL (عمر النصف) وSTEP (انخفاض كل فترة زمنية). دوال العرض: valueBps وsecondsRemaining وisExpired. ويمنع سك الدفعات المنتهية الصلاحية وتحويلها (BATCH_EXPIRED) وتحويل الدفعات التي تساوي قيمتها المتبقية صفرًا (PERISH:NO_VALUE)؛ ولا يمنع الحرق ولا الإنفاذ أبدًا.

SeasonalHook — نوافذ الحصاد والتداول

نوافذ مطلقة [start, end] لكل سلعة وعملية (16 نافذة كحد أقصى لكل مفتاح). والسلعة/العملية التي لا نوافذ لها غير مقيّدة. الاستخدام المعتاد: تقييد OP_MINT بنافذة الحصاد، وOP_TRANSFER بنافذة التداول؛ وSEASON_CLOSED في غير ذلك. وبدءًا من الإصدار المرجعي 2.0.0-alpha.7 يزيل المدير نافذة واحدة بحدودها (removeWindow)، لا بموضعها أبدًا، والنوافذ المنتهية تُفسح المجال: فحين يمتلئ مفتاح، تُسقط إضافة نافذة جديدة أولًا نوافذه المنتهية. وكل إزالة تُصدر WindowRemoved، ليتمكن المفهرس من إعادة بناء النوافذ من الأحداث.

DeliveryHook — الحيازة والتسوية

يجدول المُرسِل تسليم كمية amount إلى مستلم عبر ناقل؛ وتُقفل الكمية (بعدّاد O(1)، فلا تمرّ check على التاريخ أبدًا). ويسجّل الناقل والمستشعرات الاستلام والعبور وقراءات درجة الحرارة (مع علم المخالفة)؛ ويؤكد المستلم التسليم؛ وتُحال النزاعات إلى محكّم. والتسوية هي تحويل ERC-1155 نفسه: من المُرسِل إلى المستلم، بالمقدار الدقيق، مع رقم التسليم في data (32 بايت، abi.encode(deliveryId)، أو بدءًا من الإصدار 2.0.0-alpha.7 مُدخل AREX:DELIVERY_ID في مظروف)؛ ولا تسمح به check إلا حين يكون التسليم DELIVERED، وتضع onExecuted علامة SETTLED عليه وتفتح القفل. وتظل الكمية الحرة (غير المقفلة) قابلة للحركة. ولا يمكن تحويل الكمية المقفلة ولا حرقها ولا استخدامها مدخلات لعملية transform: إذ تُرجع check الرمز IN_TRANSIT لأي عملية من شأنها أن تُنزل رصيد الحامل دون المقدار المقفل، باستثناء تحويل التسوية والسك والتحويلات القسرية. وبعد أن يستولي تحويل قسري على كمية مقفلة، تظل check تُرجع رمزًا بدلًا من التراجع. وبدءًا من الإصدار المرجعي 2.0.0-alpha.7 لا تكون الكمية التي جمّدها الرمز (getFrozenTokens في ERC-7943) حرّةً لجدولة تسليم (وتبيّن freeUnits مقدار الحرّ منها)؛ والتسليم الذي أخذ تحويلٌ قسري كميته لا يمكن تأكيده ولا قبوله بوصفه مُسلَّمًا (LockedUnitsMoved)، إذ لا يمكن أن تحدث تسويته أبدًا، لكن يظل ممكنًا الاعتراض عليه وإعادته؛ ويُرفض نطاق حرارة لا يقل حدّه الأدنى عن حدّه الأعلى (InvalidRange).

TraceabilityHook — سجل أحداث بصيغة EPCIS

يراقب كل عملية على الرمز ويصنّفها وفق خطوات الأعمال في CBV (commissioning وshipping وdestroying وtransforming) وحالات التصرف (active وin_transit وdestroyed وseized)؛ ويسجّل RECORDER_ROLE أحداث التتبع الحرجة غير المتعلقة بالرمز (التبريد، والتعبئة، والاستلام) مع readPoint وbizLocation. وله وضعان: الإصدار فقط (نحو +17 k غاز لكل تحويل؛ ويعيد المفهرس بناء السجل) أو الحفظ (نحو +184 k؛ وتجيب getEvents على السلسلة، مع ترقيم الصفحات). والنسخة 2 من الخطاف، في الإصدار المرجعي 2.0.0-alpha.7، مربوطة برمز واحد عند النشر: فلا يُبلغ عن العمليات إلا ذلك الرمز، ولا تقبل recordEvent إلا دفعات موجودة عليه، فلا يستطيع أحد كتابة مُدخلات باسم الرمز. ويحمل حدثها EPCISEvent كل حقول المُدخل (العملية ونقطة القراءة والموقع ومن سجّله)، فلا يفقد وضع الإصدار فقط شيئًا. ويُؤخذ مرجع مستند الحركة من data ذات الـ32 بايت أو من مُدخل AREX:DOCUMENT_REF في مظروف، ولا يؤخذ أبدًا من مُدخل قاعدة أخرى. والخطاف غير قابل للترقية: تبقى مثيلات النسخة 1 وأحداثها كما كانت، والنسخة 2 نشر جديد.

CompanyFactsHook — السجلات الخاصة بالشركة

يوضّح HOOK_EXECUTED وحده: لا يرفض أي عملية أبدًا، ولا تتراجع onExecuted فيه أبدًا، وهو مربوط برمز واحد. ويدوّن السجلات الخاصة بالشركة كما يصفها واصف المفردات في المعيار (interop/VOCABULARY.md، "Records on the ledger"): وقائع عن دفعة أو موقع أو عن الشركة (recordHash مع 8 قيم علنية على الأكثر)، وعلامات المراحل (مراجع مراحل مملّحة عند مؤشرات البت 0–255، واحدة أو حتى 50 في المعاملة)، والمراحل المستلمة من رمز شركة أخرى، والمراسي اليومية (جذر Merkle وعدد)، والإلغاءات. وتحمل كل كتابة approvalHash، وهو تجزئة سجل الشركة لمن وافق عليها. تسجّل Safe الشركة التعريفات والمراحل، ويكتب السجلاتِ مفتاحُ تسجيل يمكن تفويضه. وعند transform ينقل إلى المخرجات المراحل التي مرّت بها كل دفعة أصل. ولا يضيف مرحلة نوع العملية إلا لـ processRef التُزم به في الكتلة نفسها (commitRun)، ولا يُعمل بكل التزام إلا مرة واحدة. وينقل بالطريقة نفسها نموذج سلسلة الحيازة (cocModel، الأدنى بين دفعات الأصل) وتغطية EUDR (eudrCovered، حاصل AND لدفعات الأصل). الأحداث: FactRecorded, StageRecorded, ReceivedStageRecorded, Anchored, FactVoided, RunCommitted, StagesCarried, CustodyDeclared. الإصدار المرجعي 2.0.0-alpha.9.

RequireStageHook — لا تسليم دون المراحل المطلوبة

يوضّح HOOK_CHECK فوق CompanyFactsHook. حتى 16 متطلبًا، يذكر كل منها العمليات التي يشملها (التسليمات، واختياريًا مدخلات transform) والسلع والمراحل التي يجب أن تكون الدفعة قد مرّت بها. وتُرفض الدفعة التي تنقصها مرحلة بالرمز REQUIRE_STAGE:MISSING، وتُرفض الدفعة أو وحدة المراحل التي لا يستطيع قراءتها بالرمز REQUIRE_STAGE:UNREADABLE، ولا يكون ذلك بتراجع أبدًا. ولا يُرفض السكّ ولا الحرق ولا النقل بأمر قانوني أبدًا. ولكل متطلب appliesFrom خاص به: فلا تُفحص الدفعات المنشأة قبله. وتحدد Safe الخاصة بالشركة المتطلبات عبر configure، لذلك قد تتغير نقطة البداية عند استبدال المتطلبات؛ ويُصدر كل تغيير الحدث Configured. الإصدار المرجعي 2.0.0-alpha.9.

الامتدادات المرافقة

ثلاثة جوانب لم تكن تحتاج قط إلى أن تكون قواعد تحويل؛ فهي عقود عادية تقرأ الإفادات أو تكتبها:

الامتدادما يفعله
CommodityPriceOracleيرسل المُبلِّغون الأسعار لكل سلعة؛ وتُرقَّم الجولات وتُحسم عند اكتمال النصاب باعتماد الوسيط، أو يدويًا متى بُلغ الحد الأدنى؛ latestAnswer، isStale
CarbonImmobilizationWrapperيسجّل الأرصدة المحتجزة في سجل (السجل، ونطاق الأرقام التسلسلية، وسنة الإصدار، والأطنان، والإثبات)، ويربط الأطنان بالدفعات، ويعكس السحب من التداول والإفراج، ويكتب الإفادة AREX:CARBON:IMMOBILIZED؛ ولا يسك الأرصدة أبدًا
ParametricInsuranceصندوق ERC-20؛ ووثيقة لكل دفعة مع موضوع محفّز؛ وتُصرف المطالبة عندما تُثبَت إفادة المحفّز قبل انتهاء الصلاحية

الدفعات القديمة والدفعات الجديدة

القاعدة التي تُفعَّل لرمز يحوز دفعات من قبل إما أن تحكم كل دفعة، وإما ألا تحكم إلا الدفعات المنشأة ابتداءً من لحظة زمنية معيّنة. وتأخذ الخطافات المرجعية ExpiryHook وAttestationHook وSeasonalHook وPerishabilityHook تلك اللحظة (appliesFrom، و0 لكل الدفعات) عند نشرها. ولا يمكن تغييرها بعد ذلك، فلا يستطيع أحد أن يُعفي مزيدًا من الدفعات لاحقًا؛ وأي اختيار مختلف يعني نشرًا جديدًا للقاعدة. ويُستثنى من ذلك RequireStageHook: فلكل متطلب من متطلباته appliesFrom خاص به، ويمكن لـ Safe الخاصة بالشركة استبدال المتطلبات عبر configure.

وصف القاعدة للأنظمة التي تستخدمها

يمكن للقاعدة أو للإضافة أن تنشر واصف arex.module/1 إلى جانب شيفرتها. وهو مستند JSON ذو إصدارات يسمّي معاملات العقد وإعداداته، وحقول الدفعة التي يقرؤها، وأنواع الشهادات التي يتوقعها، وأحداثه وأكواد الرفض فيه، وكيف تنتقل حالته إلى إصدار جديد. وتقرؤه المنصة أو المحفظة أو المفهرس أو المدقق لعرض القاعدة وضبطها وتفسير الرفض دون شيفرة مكتوبة لتلك القاعدة. ومنذ المراجعة 1.1 يمكن للواصف أيضًا أن يذكر العمليات التي تحكمها القاعدة (ops: mint، transfer، burn، forced_transfer، transform). والحقل إعلامي: إذا غاب فالعمليات غير معروفة، ولا يجوز لأي مستهلك الاعتماد عليه في الإنفاذ، لأن فحوص الخطاف نفسه هي التي تقرر. وتضيف المراجعة 1.2 أمرين. يمكن للإعداد أن يسمّي مكانًا (ref:site): ويُخزَّن على أنه originRef الذي تحمله الدفعات المنشأة فيه، أو مرجع دليل المنشأ خارج السلسلة الذي تحمله بدلًا منه (إقرار العناية الواجبة وفق EUDR مثلًا)، ولا يُخزَّن أبدًا عنوانًا أو إحداثيات. ويُقاس الغاز المعلن لـ check وonExecuted والإعدادات ممتلئة: فقبل القياس يستدعي المدقق كل عملية تضبط قيمة أو تضيفها setup مرة لكل مفتاح بقيم اختبارية (8 ما لم يذكر الواصف غير ذلك، و32 على الأكثر)، فتعلن القاعدة التي تمرّ على قائمة قابلة للضبط كلفتها والقائمة ممتلئة. وتدوّن المراجعة 1.3 ما يستخدمه أول مستهلك للواصف فعلًا، كي تجتاز واصفاته التحقق وفق المخطط المنشور: الإجراءات التي يسجّلها الأشخاص عبر موافقة (سجلات الإضافة، كلٌّ منها مع الدور الذي يحق له استدعاؤه)، وأخطاء العقد الخاصة بكلمات مفهومة، ومقاييس على سجلاته، وبيانات كل تسليم التي تقرؤها القاعدة، وصيغة كاملة لأحداثه بحقولها ونصوصها، وأنواع قيم أخرى (دفعة، وسجل من سجلات الوحدة، ونص قصير، ونص يُحفظ ببصمته فقط). وكل حقل تضيفه اختياري، فيبقى كل واصف سابق صالحًا. وتصف المراجعة 1.4 كل قيمة بما يكفي لبناء نموذج منها: أنواع قيم جديدة (مبلغ بعملته، وتاريخ ووقت، ومستند يُحفظ ببصمته، ورمز ذو صيغة مثل GTIN، وبلد أو منطقة، ووحدة قياس، وشخص أو طرف من الدليل)، وما يصل إلى السجل (القيمة، أو بصمتها فقط، أو لا شيء؛ ولا بيانات شخصية أبدًا)، وعنوان كل حقل ومساعدته ومثاله وقسمه وشروط ظهوره، وتحققات بين الحقول من قائمة مغلقة، وقيمًا محسوبة، وتفاصيل تبقى خارج السجل، وعروضًا للقراءة فقط بجانب الدفعة، وطريقة عرض السجل: دائمًا على أنه تصريح من المنظمة التي سجّلته، لا على أنه مُتحقَّق منه أبدًا. تضيف المراجعة 1.5 ملحًا إلى كل بصمة: الواصف الذي يصرّح بـ fingerprint: { "scheme": "salted-jcs/1" } يسجّل تجزئة كل قيمة مع ملح خاص بها من 32 بايت، فلا يمكن العثور على النصوص القصيرة أو الأرقام أو حدود القطع بتجربة الاحتمالات. وتضيف المراجعة 1.6 مقاييس ليست مجاميع: إلى جانب count وsum، يمكن أن يكون المقياس المتوسط أو أدنى قيمة أو أعلى قيمة (avg وmin وmax) لحقل رقمي في السجلات. وهي تحتاج إلى ذلك الحقل الرقمي ولا تُجمع أبدًا عبر المجموعات أو الشركات: فمتوسط شركتين هو متوسط سجلاتهما، لا متوسط متوسطيهما. ويمكن أيضًا تجميع المقاييس حسب الطرف الذي أنشأ الدفعة (party) وحسب موقعها (site). ويصرّح قالب الإضافة الخاصة بالرطوبة في الإصدار المرجعي 2.0.0-alpha.10 بمقياس منها: متوسط الرطوبة عند الاستلام حسب المنتج والموقع. ويصرّح المقياس المبني على قيمة مسجلة بنقاط الأساس بـ unit: "bp"، ويعرضه المستخدم مقسومًا على 100 بوصفه نسبة مئوية. وتتيح المراجعة 1.7 أن يأخذ visibleWhen الخاص بالحقل شجرةَ الشروط في واصف المفردات على حقول النموذج نفسه الأخرى: أوراق { field, op, value } تُجمع بـ all وany وnot، بـ 3 مستويات و12 ورقة على الأكثر، دون أي تعبير ودون سياق السجل. ويبقى الشرط الواحد في المراجعة 1.4 صالحًا، لكنه مهمل، ويُقرأ بوصفه الورقة المكافئة.

الواصف إرشادي ومقترح: اقترحته A-REX Platform، أول من يستخدمه، ويصبح صيغة موصى بها حين يستخدمه منفّذ ثانٍ مستقل. والحقول التي تضيفها القاعدة إلى مستند البيانات الوصفية للدفعة ستوضع تحت extensions.<key>، ويتحقق منها جزء المخطط الوارد في الواصف (ADR-017، مقترح، لمخطط البيانات الوصفية 1.3.0).

يمكن للمنظمة أيضًا أن تنشر مفرداتها الخاصة كتعريفات arex.vocab/1: أنواع الأعمال الحقلية (التقليم، أخذ عينات التربة)، وأنواع العمليات (تخمير لمدة 72 ساعة، فرز حسب مقاس الغربال)، وقوائم المراحل لكل منتج (الحصاد، التجفيف، التقشير، الفرز، التصدير). إنها بيانات وليست شيفرة. يستخدم كل تعريف كائن الحقل الخاص بالواصف، ويذكر إصداره، ويُربط بفئة مرحلة مرجعية وبخطوة عمل من GS1 CBV، بحيث يفهمه القارئ الذي لا يعرف المنظمة. نوع العملية هو transform له نوع، وليس عملية جديدة أبدًا: يحمل processRef الخاص به وسمًا من 4 بايتات للنوع وبصمة لقيم التشغيل، فتستطيع القاعدة أن تتصرف بحسب النوع ويستطيع أي شخص التحقق من التشغيل. تصل السجلات إلى السجل الموزع واحدًا تلو الآخر أو كجذر Merkle يومي، وكل قيمة ملتزم بها بملح خاص بها، بحيث يمكن للمنظمة أن تكشف بعض الحقول وتحتفظ بأخرى. البصمة المطابقة تُظهر أن السجل لم يتغير منذ تسجيله، ولا تُظهر أبدًا أن العمل أُنجز كما صُرّح به. الصيغة إرشادية ومقترحة (المراجعة 1.5 لواصف المفردات). تضيف المراجعة 1.1 حقل form اختياريًا يرتّب الحقول في أقسام وعروض ويحدد سلوك كل حقل (الشروط، والقيم الافتراضية، والقيم للقراءة فقط والمحسوبة، والأقنعة والأنماط)؛ وهو لا يفعل سوى تضييق ما تقبله الحقول، فالقارئ الذي يتجاهله يقرأ كل سجل كما كان من قبل. وتمنح المراجعة 1.2 الشروطَ لغةً صغيرة واحدة يتقاسمها مع واصف القاعدة: not، وحتى 3 مستويات و12 ورقة، وأوراقًا تقرأ ما تعرفه المنصة عن السجل برموز تُقرأ بالطريقة نفسها في كل لغة (المحصول برمز EPPO، والأيام منذ الزراعة، ونوع الموقع، والبلد، وبند النظام المنسق HS لمنتج الدفعة، وآخر مرحلة لها). ويُقرأ السياق غير المعروف على أنه فارغ، ويبقى كل شرط من المراجعة 1.1 صالحًا كما كُتب. وتتيح المراجعة 1.3 لقائمة المراحل أن تحدد ترتيبها (order): في strict، وهو الافتراضي، لا تُسجَّل الدفعة في مرحلة ما دامت تنقصها مرحلة مطلوبة سابقة، بدءًا من موضع دخولها إلى القائمة؛ وفي flexible تُسجَّل المراحل بأي ترتيب وتُترك الفجوات للتقارير. ولا تُرفض أبدًا مرحلةٌ تنتج عن تاريخ الدفعة نفسه (تسجيلها، أو تحويل، أو استلام)، وكل قائمة سابقة تُقرأ على أنها strict. وتتيح المراجعة 1.4 لنوع المعالجة أن يحدد طريقة معالجة البن التي تحملها مخرجاته (washed وnatural وhoney بأنواعها الأصفر والأحمر والأسود، وpulped_natural وwet_hulled وanaerobic وother)، مأخوذةً من حقل في التشغيل أو ثابتةً في النوع، ويمكن أن تحمل بيانات process الوصفية للدفعة الطريقة (method) (وmixed للدفعة فقط). إنها تصريح من المنظمة، لا شهادة، وترافق الدفعة حتى حيث تبقى قيم الخطوات خاصة. وتتيح المراجعة 1.5 لربطٍ بإحدى الفئات العامة separating أو conditioning أو sorting_grading أو heat_treating أن يضيف subclass من قائمة مغلقة لكل فئة (مثل hulling وcuring وscreen وroasting)، ولا يطابق القارئ خطوةً من فئة عامة لدى منظمة أخرى إلا بفئتها الفرعية أو بربط صريح لكل مُرسِل. وتضيف المراجعة 1.6 الفئة الفرعية to_processor للفئة transporting: بضائع تُرسَل إلى جهة معالجة تعالجها لصالح مالكها (التصنيع لحساب الغير)، فتنتقل الحيازة دون الملكية.

كتابة خطافك الخاص

يبقى المثال contracts/examples/SeasonHook.sol في المستودع. ويختبره test/standard/ImplementationGuide.test.js للقرّاء الذين لديهم وصول. وSeasonalHook هو الوحدة المرجعية لعدة نوافذ لكل سلعة ولكل عملية.

قواعد عملية:

  1. الرمزان OK وOP_FORCED_TRANSFER معرّفان في النص المعياري.
  2. سلوك الحرق معرّف في النص المعياري.
  3. الاستدعاء check معرّف في النص المعياري.
  4. أسماء الأكواد مثل ARexCodes.code("MYNS", "NAME") معرّفة في النص المعياري.
  5. قيم الأعلام معرّفة في النص المعياري.
  6. الاستدعاءان onExecuted وcheck معرّفان في النص المعياري.

التسجيل والترتيب

ضع القواعد الرخيصة ذات معدل الرفض المرتفع أولًا. وينبغي أن يوضع HOOK_ADMIN_ROLE خلف توقيع متعدد أو تأخير زمني: فمن يتحكم في المسار يتحكم في التحويلات الممكنة.

الاختبار

ينشر test/standard/helpers.js الحزمة المرجعية. ويسجّل RecordingHook كل استدعاء ويمكن توجيهه إلى الرفض بأي كود؛ ويحاول ReentrantHook إعادة دخول الرمز من onExecuted ويثبت فعالية القفل. ويغطي DomainHooks.test.js وExtensions.test.js الخطافات والمرافقات المنقولة؛ ويشغّل Invariants.test.js تسلسلًا عشوائيًا ببذرة محددة من العمليات ويتحقق من حفظ المعروض والحالة النهائية ومن أن canTransfer تتنبأ بكل نتيجة. ومنذ الإصدار المرجعي 2.0.0-alpha.8 يوفّر التنفيذ المرجعي أيضًا حزمة اختبار للخطافات (conformance/hooks/)، وهي مجموعات اختبارات Foundry يجب أن تجتازها كل قاعدة، وقالب وحدة (templates/module/). ويضيف الإصدار 2.0.0-alpha.9 حزمة اختبار للإضافات (conformance/addons/) وثلاثة قوالب إضافات مختبرة بها: الرطوبة عند الاستلام (GrainMoisture)، وشهادة التجارة العادلة المسجلة بوصفها واقعة صرّحت بها الشركة (FairTradeCertificate)، وعلاوة مدفوعة لمنتج لا يُسجَّل مبلغها ولا المستفيد منها إلا في صورة بصمات مملّحة (PremiumPayments).

التشغيل البيني مع امتثال ERC-3643

تكشف وحدة امتثال ERC-3643 الدالة moduleCheck(from, to, value, compliance). والخطاف الذي يستدعيها للعملية OP_TRANSFER ويحوّل false إلى كود يجعل قيود الدول وسقوف الأرصدة والأقفال الزمنية المكتوبة لرموز الأوراق المالية قابلة لإعادة الاستخدام على رموز الدفعات. والعكس — أي إتاحة خطاف A-REX لرمز ERC-3643 — آلي بالقدر نفسه. ويتكامل Automated Compliance Engine من Chainlink عبر النمط نفسه: فيصبح محرك سياساته خطافًا واحدًا. وهذان الاتجاهان تصميمان غير منفّذين. أما المهايئ المرجعي الموجود فيسير في الاتجاه المعاكس ويقرأ فقط: إذ يتيح لمحافظ ERC-3643 وأدوات الامتثال رؤية كل دفعة بوصفها رمز ERC-3643 عبر خطاف يتلقى الإشعارات فقط ولا يستطيع أن يسمح بتحويل أو يرفضه (ADR-020، مقترح).