مشاركة نصائح صغيرة لتطوير العقود: الدروس المستفادة من Uniswap
مؤخراً، أثناء تطوير مشروع تبادل لامركزي، استندت إلى تنفيذ الشيفرة لمشروع DEX معروف، وتعلمت العديد من النقاط المفيدة. كوني مبتدئاً في تطوير عقود DeFi، كانت هذه التقنيات ملهمة لي، وأعتقد أنها ستفيد أصدقاء آخرين يرغبون في تعلم تطوير العقود الذكية.
عنوان العقد القابل للتنبؤ
عادةً ما تبدو العناوين التي يتم الحصول عليها من نشر العقود عشوائية، لأنها مرتبطة بالـ nonce. ولكن في بعض السيناريوهات، نحتاج إلى استنتاج عنوان العقد من خلال معلومات المعاملات، مثل تحديد أذونات المعاملات أو الحصول على عنوان مجموعة السيولة.
يمكن تحقيق ذلك من خلال إنشاء عقد باستخدام طريقة CREATE2. الطريقة المحددة هي إضافة معلمة salt عند إنشاء العقد:
سلطنة
pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))} ());
عنوان العقد الذي تم إنشاؤه بهذه الطريقة يمكن التنبؤ به، ويتبع المنطق التالي:
عنوان جديد = hash("0xFF", عنوان المنشئ, الملح, initcode)
الاستخدام المعقول لدوال الاسترجاع
في بعض السيناريوهات، يكون من المفيد استدعاء بعض العقود لبعضها البعض. على سبيل المثال، تستدعي طريقة A الطريقة B، ثم تستدعي B طريقة A في طريقة الاستدعاء.
عند استدعاء طريقة swap للتداول في DEX معين، ستقوم باستدعاء swapCallback، وتمرير الرموز المطلوبة فعليًا لهذه المعاملة. يجب على الطرف المستدعي في استدعاء العودة نقل الرموز المطلوبة إلى بركة التداول، بدلاً من تقسيم طريقة swap. هذا يضمن التنفيذ الكامل لطريقة swap دون الحاجة إلى سجلات متغيرة معقدة لضمان الأمان.
استخدام الاستثناءات لنقل المعلومات
عند تقدير الصفقة، نحتاج إلى محاكاة طريقة التبديل، ولكننا لن نقوم بتبادل الرموز فعليًا، لذا سيظهر خطأ. تقوم بعض منصات التداول اللامركزية بتنفيذ التقدير من خلال رمي خطأ خاص في دالة رد الاتصال للمعاملة، ثم التقاط ذلك الخطأ وتحليل المعلومات المطلوبة منه.
تبدو هذه الطريقة كأنها حيلة، لكنها عملية للغاية. لا حاجة لتعديل طريقة السواب لتقدير الطلب، فهي منطقية أكثر.
استخدام الأعداد الكبيرة لحل مشكلة الدقة
في الأكواد المتعلقة بالحسابات، يجب تجنب فقدان الدقة عند إجراء عمليات القسمة. يستخدم بعض DEX بشكل متكرر عملية "<< FixedPoint96.RESOLUTION"، والتي تعادل الضرب في 2^96. بعد الإزاحة إلى اليسار، يمكن إجراء القسمة مع ضمان الدقة دون حدوث تجاوز.
على الرغم من أنه قد يكون هناك فقدان دقة من الناحية النظرية، إلا أنه عادة ما يكون فقط فقدان الحد الأدنى من الوحدة، وهو مقبول.
حساب العائد بطريقة المشاركة
بالنسبة لحساب أرباح الرسوم لمزودي السيولة (LP)، لا يمكن تسجيل كل صفقة، فهذا سيستهلك كمية كبيرة من الغاز. تعتمد بعض DEX على تسجيل إجمالي الرسوم وطرق توزيع الرسوم لكل سيولة.
عند سحب رسوم LP، يتم حساب المبلغ القابل للسحب بناءً على السيولة المحتفظ بها. يشبه الأمر الاحتفاظ بأسهم الشركة، فعند سحب الأرباح، تحتاج فقط إلى معرفة العائد التاريخي لكل سهم والعائد في آخر سحب.
اختيار وسيلة الحصول على المعلومات بشكل معقول
التخزين على السلسلة مكلف نسبيًا، وليس كل المعلومات تحتاج إلى أن تكون على السلسلة أو يتم الحصول عليها من السلسلة. مثل قائمة تجمع المعاملات والمعلومات يمكن تخزينها في قاعدة بيانات عادية، وتزامنها بشكل دوري من السلسلة.
تقدم بعض مزودي خدمات RPC في البلوكشين واجهات متقدمة للحصول على البيانات بشكل أسرع. لكن يجب أن تتم المعاملات الأساسية على السلسلة.
تقسيم العقود وإعادة استخدام العقود القياسية
يمكن أن يحتوي المشروع على عدة عقود، حتى إذا تم نشر عقد واحد فعليًا، يمكن تقسيمه إلى عدة عقود للصيانة من خلال الوراثة.
عقد إدارة موقع NFT الخاص بـ DEX معين قد ورث عدة عقود:
صلابة
عقد غير قابل للفطرياتPositionManager هو
INonfungiblePositionManager ،
ملتيكول
الدولة المحيطية غير القابلة للتغيير,
PoolInitializer ،
إدارة السيولة،
التحقق الهامشي,
التصريح الذاتي ،
إي آر سي 721 تصريح
{...}
في الوقت نفسه، فإنه يستخدم أيضًا عقد معيار ERC721 من OpenZeppelin، مما يسهل إدارة المراكز ويزيد من كفاءة التطوير.
ملخص
قم بتطوير نسخة بسيطة من بورصة لامركزية بنفسك، مما سيمكنك من فهم أعمق لتنفيذ كود المشاريع الناضجة، وتعلم المزيد من النقاط المعرفية العملية. آمل أن تلهمك هذه النصائح الصغيرة، وأتمنى لك التوفيق في التطوير!
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
سبع نصائح عملية لتطوير عقود DEX الرئيسية
مشاركة نصائح صغيرة لتطوير العقود: الدروس المستفادة من Uniswap
مؤخراً، أثناء تطوير مشروع تبادل لامركزي، استندت إلى تنفيذ الشيفرة لمشروع DEX معروف، وتعلمت العديد من النقاط المفيدة. كوني مبتدئاً في تطوير عقود DeFi، كانت هذه التقنيات ملهمة لي، وأعتقد أنها ستفيد أصدقاء آخرين يرغبون في تعلم تطوير العقود الذكية.
عنوان العقد القابل للتنبؤ
عادةً ما تبدو العناوين التي يتم الحصول عليها من نشر العقود عشوائية، لأنها مرتبطة بالـ nonce. ولكن في بعض السيناريوهات، نحتاج إلى استنتاج عنوان العقد من خلال معلومات المعاملات، مثل تحديد أذونات المعاملات أو الحصول على عنوان مجموعة السيولة.
يمكن تحقيق ذلك من خلال إنشاء عقد باستخدام طريقة CREATE2. الطريقة المحددة هي إضافة معلمة salt عند إنشاء العقد:
سلطنة pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))} ());
عنوان العقد الذي تم إنشاؤه بهذه الطريقة يمكن التنبؤ به، ويتبع المنطق التالي:
عنوان جديد = hash("0xFF", عنوان المنشئ, الملح, initcode)
الاستخدام المعقول لدوال الاسترجاع
في بعض السيناريوهات، يكون من المفيد استدعاء بعض العقود لبعضها البعض. على سبيل المثال، تستدعي طريقة A الطريقة B، ثم تستدعي B طريقة A في طريقة الاستدعاء.
عند استدعاء طريقة swap للتداول في DEX معين، ستقوم باستدعاء swapCallback، وتمرير الرموز المطلوبة فعليًا لهذه المعاملة. يجب على الطرف المستدعي في استدعاء العودة نقل الرموز المطلوبة إلى بركة التداول، بدلاً من تقسيم طريقة swap. هذا يضمن التنفيذ الكامل لطريقة swap دون الحاجة إلى سجلات متغيرة معقدة لضمان الأمان.
استخدام الاستثناءات لنقل المعلومات
عند تقدير الصفقة، نحتاج إلى محاكاة طريقة التبديل، ولكننا لن نقوم بتبادل الرموز فعليًا، لذا سيظهر خطأ. تقوم بعض منصات التداول اللامركزية بتنفيذ التقدير من خلال رمي خطأ خاص في دالة رد الاتصال للمعاملة، ثم التقاط ذلك الخطأ وتحليل المعلومات المطلوبة منه.
تبدو هذه الطريقة كأنها حيلة، لكنها عملية للغاية. لا حاجة لتعديل طريقة السواب لتقدير الطلب، فهي منطقية أكثر.
استخدام الأعداد الكبيرة لحل مشكلة الدقة
في الأكواد المتعلقة بالحسابات، يجب تجنب فقدان الدقة عند إجراء عمليات القسمة. يستخدم بعض DEX بشكل متكرر عملية "<< FixedPoint96.RESOLUTION"، والتي تعادل الضرب في 2^96. بعد الإزاحة إلى اليسار، يمكن إجراء القسمة مع ضمان الدقة دون حدوث تجاوز.
سوليديتي uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; uint256 البسط2 = sqrtRatioBX96 - sqrtRatioAX96; amount0 = البسط 1 * البسط2 / (sqrtRatioBX96 * sqrtRatioAX96) ؛
على الرغم من أنه قد يكون هناك فقدان دقة من الناحية النظرية، إلا أنه عادة ما يكون فقط فقدان الحد الأدنى من الوحدة، وهو مقبول.
حساب العائد بطريقة المشاركة
بالنسبة لحساب أرباح الرسوم لمزودي السيولة (LP)، لا يمكن تسجيل كل صفقة، فهذا سيستهلك كمية كبيرة من الغاز. تعتمد بعض DEX على تسجيل إجمالي الرسوم وطرق توزيع الرسوم لكل سيولة.
عند سحب رسوم LP، يتم حساب المبلغ القابل للسحب بناءً على السيولة المحتفظ بها. يشبه الأمر الاحتفاظ بأسهم الشركة، فعند سحب الأرباح، تحتاج فقط إلى معرفة العائد التاريخي لكل سهم والعائد في آخر سحب.
اختيار وسيلة الحصول على المعلومات بشكل معقول
التخزين على السلسلة مكلف نسبيًا، وليس كل المعلومات تحتاج إلى أن تكون على السلسلة أو يتم الحصول عليها من السلسلة. مثل قائمة تجمع المعاملات والمعلومات يمكن تخزينها في قاعدة بيانات عادية، وتزامنها بشكل دوري من السلسلة.
تقدم بعض مزودي خدمات RPC في البلوكشين واجهات متقدمة للحصول على البيانات بشكل أسرع. لكن يجب أن تتم المعاملات الأساسية على السلسلة.
تقسيم العقود وإعادة استخدام العقود القياسية
يمكن أن يحتوي المشروع على عدة عقود، حتى إذا تم نشر عقد واحد فعليًا، يمكن تقسيمه إلى عدة عقود للصيانة من خلال الوراثة.
عقد إدارة موقع NFT الخاص بـ DEX معين قد ورث عدة عقود:
صلابة عقد غير قابل للفطرياتPositionManager هو INonfungiblePositionManager ، ملتيكول الدولة المحيطية غير القابلة للتغيير, PoolInitializer ، إدارة السيولة، التحقق الهامشي, التصريح الذاتي ، إي آر سي 721 تصريح {...}
في الوقت نفسه، فإنه يستخدم أيضًا عقد معيار ERC721 من OpenZeppelin، مما يسهل إدارة المراكز ويزيد من كفاءة التطوير.
ملخص
قم بتطوير نسخة بسيطة من بورصة لامركزية بنفسك، مما سيمكنك من فهم أعمق لتنفيذ كود المشاريع الناضجة، وتعلم المزيد من النقاط المعرفية العملية. آمل أن تلهمك هذه النصائح الصغيرة، وأتمنى لك التوفيق في التطوير!