مشاركة تقنيات تطوير العقود: التعلم من شفرة Uniswap المصدرية
مؤخراً، أثناء كتابة دليل تطوير لتبادل لا مركزي، قمت بالرجوع إلى تنفيذ كود Uniswap V3، وتعلمت العديد من النقاط القيمة. باعتباري مطوراً يحاول لأول مرة تطوير عقود Defi، فإن هذه الحيل ستكون مفيدة جداً للمبتدئين الذين يرغبون في تعلم تطوير العقود.
فيما يلي بعض النصائح التي تعلمتها، وبعضها يمكن اعتباره حيلًا غريبة.
عنوان نشر العقد القابل للتنبؤ
عادةً ما تكون العنوان الناتج عن نشر العقد يبدو عشوائيًا، لأنه مرتبط بـ nonce، لذا يصعب توقع عنوان العقد. ولكن في بعض السيناريوهات، نحتاج إلى استنتاج عنوان العقد من خلال أزواج التداول والمعلومات ذات الصلة. هذا مفيد في حالات مثل تحديد صلاحيات المعاملات أو الحصول على عنوان المسبح.
تقوم Uniswap بإضافة معلمة salt، وتستخدم CREATE2 لإنشاء العقد، مما يجعل عنوان العقد الذي تم إنشاؤه قابلاً للتنبؤ. منطق توليد العنوان هو: العنوان الجديد = hash("0xFF"، عنوان المُنشئ، salt، initcode).
استخدام دوال الاسترجاع بذكاء
في بعض السيناريوهات، تستدعي العقدة A طرق العقدة B، وتقوم B باستدعاء A في الطريقة التي تم استدعاؤها، وهذه الطريقة مفيدة جدًا.
على سبيل المثال، عند استدعاء طريقة swap لعقد UniswapV3Pool للتداول، ستقوم باستدعاء swapCallback، مع تمرير الرمز المميز المطلوب فعليًا للصفقة المحسوبة. يحتاج المستدعي في الاستدعاء العائد إلى تحويل الرمز المميز المطلوب للصفقة إلى UniswapV3Pool، بدلاً من تقسيم طريقة swap إلى جزئين ليقوم المستدعي باستدعائها. هذا يضمن أمان طريقة swap، ويضمن تنفيذ المنطق بالكامل، دون الحاجة إلى تسجيل متغيرات معقدة لضمان الأمان.
استخدام الاستثناءات لنقل المعلومات، وتحقيق تقدير الصفقة باستخدام try catch
في عقد Quoter الخاص بـ Uniswap، يتم تنفيذ طريقة swap الخاصة بـ UniswapV3Pool باستخدام try catch. وذلك لمحاكاة طريقة swap لتقدير الرموز المطلوبة للتداول. نظرًا لأن التقدير لا ينتج عنه تبادل فعلي للرموز، فسوف يحدث خطأ. يقوم Uniswap بإلقاء خطأ خاص في دالة رد الاتصال للتداول، ثم يلتقط هذا الخطأ، ويستخلص المعلومات المطلوبة من رسالة الخطأ.
تبدو هذه الطريقة وكأنها حيلة، لكنها عملية جداً. لا داعي لتعديل طريقة السواب لتقدير الطلبات التجارية، المنطق أبسط.
استخدام الأعداد الكبيرة لحل مشاكل الدقة
هناك الكثير من المنطق الحسابي في كود Uniswap، مثل حساب التوكنات المتبادلة بناءً على السعر الحالي والسيولة. لتجنب فقدان الدقة أثناء عمليات القسمة، غالبًا ما تستخدم العملية "<< FixedPoint96.RESOLUTION"، أي الإزاحة لليسار بمقدار 96 بت، مما يعادل الضرب في 2^96. بعد الإزاحة، يتم إجراء عملية القسمة، مما يضمن الدقة في حالة عدم حدوث فيضانات أثناء التداول العادي.
حساب العائد باستخدام طريقة المشاركة
في Uniswap، يجب تسجيل عائدات رسوم المعاملات لمزودي السيولة LP(. من الواضح أنه لا يمكن تسجيل رسوم المعاملات لكل LP في كل مرة يتم فيها إجراء صفقة، حيث سيؤدي ذلك إلى استهلاك كمية كبيرة من الغاز.
حل Uniswap هو تسجيل feeGrowthInside0LastX128 و feeGrowthInside1LastX128 في هيكل Position، مما يدل على رسوم المعاملات المستحقة لكل سيولة في آخر سحب للرسوم. يكفي تسجيل إجمالي الرسوم والرسوم المخصصة لكل سيولة، وعند سحب LP، يتم حساب الرسوم القابلة للسحب بناءً على السيولة المحتفظ بها. هذا مشابه لامتلاك أسهم في شركة، حيث يكفي معرفة العائد التاريخي لكل سهم وعائد آخر سحب.
![Web3 المبتدئين سلسلة: النصائح الصغيرة لتطوير العقود التي تعلمتها من كود Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
لا حاجة للحصول على معلومات غير ضرورية من السلسلة
تخزين البيانات على السلسلة مكلف نسبيًا، وليس من الضروري أن تكون جميع المعلومات موجودة على السلسلة أو يتم الحصول عليها من السلسلة. العديد من واجهات برمجة التطبيقات التي يستدعيها موقع Uniswap الأمامي هي واجهات برمجة تطبيقات تقليدية من Web2.
يمكن تخزين قائمة برك التداول ومعلومات برك التداول في قاعدة بيانات عادية، وقد يحتاج البعض إلى المزامنة من السلسلة بشكل دوري، لكن لا حاجة لاستدعاء واجهة RPC لخدمات السلسلة أو العقد للحصول على البيانات ذات الصلة في الوقت الحقيقي.
بالطبع، يجب أن تتم المعاملات الرئيسية على السلسلة.
تقسيم العقد بشكل معقول، واستخدام العقد القياسي الحالي
قد يتضمن المشروع عدة عقود تم نشرها فعليًا. حتى إذا تم نشر عقد واحد فقط فعليًا، يمكن تقسيم الكود إلى عدة عقود للحفاظ عليه من خلال طريقة الوراثة.
على سبيل المثال، يرث عقد NonfungiblePositionManager الخاص بـ Uniswap من عدة عقود. عند مراجعة تنفيذ عقد ERC721Permit، نجد أنه يستخدم مباشرة عقد @openzeppelin/contracts/token/ERC721/ERC721.sol. بهذه الطريقة، يكون من السهل إدارة المراكز عبر طريقة NFT، ويمكن أيضًا الاستفادة من العقود القياسية الحالية لتحسين كفاءة التطوير.
ملخص
الممارسة هي أفضل طريقة للتعلم. محاولة تنفيذ نسخة بسيطة من بورصة لامركزية بنفسك يمكن أن تساعدك على فهم أعمق لكود Uniswap وتعلم المزيد من النقاط المعرفية في المشاريع العملية.
![Web3 سلسلة المبتدئين: نصائح صغيرة في تطوير العقود تعلمتها من كود Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
كشف مصادر Uniswap: 7 تقنيات تطوير العقود لمساعدة مبتدئي Defi للإقلاع
مشاركة تقنيات تطوير العقود: التعلم من شفرة Uniswap المصدرية
مؤخراً، أثناء كتابة دليل تطوير لتبادل لا مركزي، قمت بالرجوع إلى تنفيذ كود Uniswap V3، وتعلمت العديد من النقاط القيمة. باعتباري مطوراً يحاول لأول مرة تطوير عقود Defi، فإن هذه الحيل ستكون مفيدة جداً للمبتدئين الذين يرغبون في تعلم تطوير العقود.
فيما يلي بعض النصائح التي تعلمتها، وبعضها يمكن اعتباره حيلًا غريبة.
عنوان نشر العقد القابل للتنبؤ
عادةً ما تكون العنوان الناتج عن نشر العقد يبدو عشوائيًا، لأنه مرتبط بـ nonce، لذا يصعب توقع عنوان العقد. ولكن في بعض السيناريوهات، نحتاج إلى استنتاج عنوان العقد من خلال أزواج التداول والمعلومات ذات الصلة. هذا مفيد في حالات مثل تحديد صلاحيات المعاملات أو الحصول على عنوان المسبح.
تقوم Uniswap بإضافة معلمة salt، وتستخدم CREATE2 لإنشاء العقد، مما يجعل عنوان العقد الذي تم إنشاؤه قابلاً للتنبؤ. منطق توليد العنوان هو: العنوان الجديد = hash("0xFF"، عنوان المُنشئ، salt، initcode).
استخدام دوال الاسترجاع بذكاء
في بعض السيناريوهات، تستدعي العقدة A طرق العقدة B، وتقوم B باستدعاء A في الطريقة التي تم استدعاؤها، وهذه الطريقة مفيدة جدًا.
على سبيل المثال، عند استدعاء طريقة swap لعقد UniswapV3Pool للتداول، ستقوم باستدعاء swapCallback، مع تمرير الرمز المميز المطلوب فعليًا للصفقة المحسوبة. يحتاج المستدعي في الاستدعاء العائد إلى تحويل الرمز المميز المطلوب للصفقة إلى UniswapV3Pool، بدلاً من تقسيم طريقة swap إلى جزئين ليقوم المستدعي باستدعائها. هذا يضمن أمان طريقة swap، ويضمن تنفيذ المنطق بالكامل، دون الحاجة إلى تسجيل متغيرات معقدة لضمان الأمان.
استخدام الاستثناءات لنقل المعلومات، وتحقيق تقدير الصفقة باستخدام try catch
في عقد Quoter الخاص بـ Uniswap، يتم تنفيذ طريقة swap الخاصة بـ UniswapV3Pool باستخدام try catch. وذلك لمحاكاة طريقة swap لتقدير الرموز المطلوبة للتداول. نظرًا لأن التقدير لا ينتج عنه تبادل فعلي للرموز، فسوف يحدث خطأ. يقوم Uniswap بإلقاء خطأ خاص في دالة رد الاتصال للتداول، ثم يلتقط هذا الخطأ، ويستخلص المعلومات المطلوبة من رسالة الخطأ.
تبدو هذه الطريقة وكأنها حيلة، لكنها عملية جداً. لا داعي لتعديل طريقة السواب لتقدير الطلبات التجارية، المنطق أبسط.
استخدام الأعداد الكبيرة لحل مشاكل الدقة
هناك الكثير من المنطق الحسابي في كود Uniswap، مثل حساب التوكنات المتبادلة بناءً على السعر الحالي والسيولة. لتجنب فقدان الدقة أثناء عمليات القسمة، غالبًا ما تستخدم العملية "<< FixedPoint96.RESOLUTION"، أي الإزاحة لليسار بمقدار 96 بت، مما يعادل الضرب في 2^96. بعد الإزاحة، يتم إجراء عملية القسمة، مما يضمن الدقة في حالة عدم حدوث فيضانات أثناء التداول العادي.
حساب العائد باستخدام طريقة المشاركة
في Uniswap، يجب تسجيل عائدات رسوم المعاملات لمزودي السيولة LP(. من الواضح أنه لا يمكن تسجيل رسوم المعاملات لكل LP في كل مرة يتم فيها إجراء صفقة، حيث سيؤدي ذلك إلى استهلاك كمية كبيرة من الغاز.
حل Uniswap هو تسجيل feeGrowthInside0LastX128 و feeGrowthInside1LastX128 في هيكل Position، مما يدل على رسوم المعاملات المستحقة لكل سيولة في آخر سحب للرسوم. يكفي تسجيل إجمالي الرسوم والرسوم المخصصة لكل سيولة، وعند سحب LP، يتم حساب الرسوم القابلة للسحب بناءً على السيولة المحتفظ بها. هذا مشابه لامتلاك أسهم في شركة، حيث يكفي معرفة العائد التاريخي لكل سهم وعائد آخر سحب.
![Web3 المبتدئين سلسلة: النصائح الصغيرة لتطوير العقود التي تعلمتها من كود Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
لا حاجة للحصول على معلومات غير ضرورية من السلسلة
تخزين البيانات على السلسلة مكلف نسبيًا، وليس من الضروري أن تكون جميع المعلومات موجودة على السلسلة أو يتم الحصول عليها من السلسلة. العديد من واجهات برمجة التطبيقات التي يستدعيها موقع Uniswap الأمامي هي واجهات برمجة تطبيقات تقليدية من Web2.
يمكن تخزين قائمة برك التداول ومعلومات برك التداول في قاعدة بيانات عادية، وقد يحتاج البعض إلى المزامنة من السلسلة بشكل دوري، لكن لا حاجة لاستدعاء واجهة RPC لخدمات السلسلة أو العقد للحصول على البيانات ذات الصلة في الوقت الحقيقي.
بالطبع، يجب أن تتم المعاملات الرئيسية على السلسلة.
تقسيم العقد بشكل معقول، واستخدام العقد القياسي الحالي
قد يتضمن المشروع عدة عقود تم نشرها فعليًا. حتى إذا تم نشر عقد واحد فقط فعليًا، يمكن تقسيم الكود إلى عدة عقود للحفاظ عليه من خلال طريقة الوراثة.
على سبيل المثال، يرث عقد NonfungiblePositionManager الخاص بـ Uniswap من عدة عقود. عند مراجعة تنفيذ عقد ERC721Permit، نجد أنه يستخدم مباشرة عقد @openzeppelin/contracts/token/ERC721/ERC721.sol. بهذه الطريقة، يكون من السهل إدارة المراكز عبر طريقة NFT، ويمكن أيضًا الاستفادة من العقود القياسية الحالية لتحسين كفاءة التطوير.
ملخص
الممارسة هي أفضل طريقة للتعلم. محاولة تنفيذ نسخة بسيطة من بورصة لامركزية بنفسك يمكن أن تساعدك على فهم أعمق لكود Uniswap وتعلم المزيد من النقاط المعرفية في المشاريع العملية.
![Web3 سلسلة المبتدئين: نصائح صغيرة في تطوير العقود تعلمتها من كود Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(