كيفية إنشاء رمز ERC20 بطريقة بسيطة

نشرت: 2022-03-11

الهدف من هذه المقالة هو توضيح كيفية إنشاء رمز مميز ERC20 في أقل وقت ممكن.

لنبدأ بالأساسيات: ما هو توكن ERC20؟

في السنوات الأخيرة ، أصبحت مواصفات رمز ERC20 هي المعيار الفعلي لرموز Ethereum. بمعنى آخر ، فإن معظم عقود Ethereum الموجودة اليوم متوافقة مع ERC20. ستوضح هذه المقالة بالتفصيل كيف يمكنك إنشاء رمز Ethereum الخاص بك ، ولكن قبل أن نبدأ ، دعنا نلقي نظرة فاحصة على معيار ERC20.

توضيح رمز ERC20

ما الذي يجعل توكنات ERC20 جذابة وناجحة للغاية؟ هناك عدة عوامل في اللعب:

  1. توكنات ERC20 بسيطة وسهلة النشر ، كما سترى في هذا البرنامج التعليمي.
  2. يحل معيار ERC20 مشكلة كبيرة ، حيث تحتاج الأسواق القائمة على blockchain والمحافظ المشفرة إلى مجموعة واحدة موحدة من الأوامر للتواصل مع مجموعة الرموز التي يديرونها. يتضمن ذلك قواعد التفاعل بين الرموز المختلفة ، بالإضافة إلى قواعد شراء الرموز المميزة.
  3. كانت أول مواصفات شائعة تقدم توحيد رمز Ethereum. لم يكن بأي حال من الأحوال الأول ، ولكن بفضل شعبيته ، سرعان ما أصبح معيار الصناعة.

تمامًا مثل الرموز المميزة الأخرى لـ Ethereum ، يتم تنفيذ الرموز المميزة لـ ERC20 كعقود ذكية ويتم تنفيذها على جهاز Ethereum Virtual Machine (EVM) بطريقة لامركزية.

Solidity: لغة برمجة العقود الذكية

تمت كتابة عقود Ethereum الذكية في Solidity. بينما توجد لغات بديلة ، نادرًا ما يستخدمها أي شخص لهذا الغرض. Solidity مشابه لـ JavaScript ، لذلك إذا كان لديك بعض المعرفة بجافا سكريبت ، أو حتى Java ولغات أخرى شبيهة بلغة C ، فلن تواجه مشكلة في معرفة أن جزءًا من التعليمات البرمجية في Solidity يفعل ذلك ، حتى قبل أن تتقن Solidity بدرجة كافية لاستخدامها هو - هي.

هذا هو المكان الذي تبدأ فيه المتعة ، حيث يجب أن تكون قادرًا على البدء في إنشاء عقد ERC20 بسيط في أي وقت من الأوقات. هذه مهمة مباشرة وبسيطة لدرجة أن هذه المقالة ستوضح كيف يمكنك كتابة ونشر رمز ERC20 في أقل من ساعة.

سيكون الرمز الذي سننشئه في هذا العرض التوضيحي عبارة عن تطبيق ERC20 مكشوف ، بدون الكثير من الأجراس والصفارات. ومع ذلك ، فقد رأيت العديد من الرموز البسيطة المماثلة في العالم الحقيقي ، وهي تميل إلى العمل بشكل جيد.

نظرة عامة على معيار الرمز المميز ERC20

ما هو ERC20؟

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

 function totalSupply() public view returns (uint256); function balanceOf(address tokenOwner) public view returns (uint); function allowance(address tokenOwner, address spender) public view returns (uint); function transfer(address to, uint tokens) public returns (bool); function approve(address spender, uint tokens) public returns (bool); function transferFrom(address from, address to, uint tokens) public returns (bool);

تسمح وظائف ERC20 للمستخدم الخارجي ، على سبيل المثال تطبيق المحفظة المشفرة ، بمعرفة رصيد المستخدم وتحويل الأموال من مستخدم إلى آخر بتفويض مناسب.

يحدد العقد الذكي حدثين محددين على وجه التحديد:

 event Approval(address indexed tokenOwner, address indexed spender, uint tokens); event Transfer(address indexed from, address indexed to, uint tokens);

سيتم استدعاء هذه الأحداث أو إرسالها عندما يتم منح المستخدم حقوق سحب الرموز من حساب ، وبعد نقل الرموز المميزة فعليًا.

بالإضافة إلى وظائف ERC20 القياسية ، تتميز العديد من رموز ERC20 أيضًا بحقول إضافية وأصبح بعضها جزءًا بحكم الواقع من معيار ERC20 ، إن لم يكن كتابيًا ، فعندئذٍ في الممارسة. فيما يلي بعض الأمثلة على هذه المجالات.

 string public constant name; string public constant symbol; uint8 public constant decimals;

فيما يلي بعض النقاط المتعلقة بتسميات ERC20 و Solidity:

  • يمكن الوصول إلى وظيفة public خارج العقد نفسه
  • view يعني في الأساس ثابتًا ، أي أن الحالة الداخلية للعقد لن تتغير من خلال الوظيفة
  • event هو طريقة Solidity للسماح للعملاء ، على سبيل المثال الواجهة الأمامية للتطبيق الخاص بك ليتم إخطارهم في حالات محددة في العقد

يجب أن تكون معظم تراكيب لغة Solidity واضحة إذا كنت تمتلك بالفعل مهارات Java / JavaScript أساسية.

كتابة رمز ERC20 في Solidity

توكنات ERC20 في الصلابة

الآن وقد حددنا الأساسيات وشرحنا ما يتطلبه الأمر لإنشاء رمز مميز ERC20 ، فقد حان الوقت لبدء كتابة بعض المنطق.

أولاً ، نحتاج إلى تحديد كائنين لرسم الخرائط. هذا هو مفهوم Solidity لمصفوفة ترابطية أو مفتاح / قيمة:

 mapping(address => uint256) balances; mapping(address => mapping (address => uint256)) allowed;

يعرّف mapping(address => uint256) تكون مفاتيحها من نوع address - رقم يُستخدم للإشارة إلى عناوين الحساب ، وقيمه من النوع uint256 - عدد صحيح 256 بت يُستخدم عادةً لتخزين أرصدة الرمز المميز.

سيحتفظ كائن التعيين الأول ، balances ، برصيد الرمز المميز لكل حساب مالك.

سيتضمن كائن التعيين الثاني ، allowed ، جميع الحسابات المعتمدة للسحب من حساب معين مع مبلغ السحب المسموح به لكل منها.

كما ترى ، فإن حقل القيمة للتعيين المسموح به هو في حد ذاته عنوان حساب تخطيط لمبلغ السحب المعتمد.

سيتم تخزين هذه التعيينات مع جميع حقول العقود الأخرى في blockchain وسيتم تعدينها مما يؤدي إلى نشر التغييرات على جميع عقد مستخدمي الشبكة.

تخزين Blockchain باهظ الثمن وسيحتاج مستخدمو عقدك إلى الدفع بطريقة أو بأخرى. لذلك يجب أن تحاول دائمًا تقليل حجم التخزين والكتابة في blockchain.

الآن بعد أن أصبح لدينا هياكل البيانات المطلوبة ، يمكننا البدء في كتابة منطق ERC20 في الوظائف المناسبة.

تحديد عدد رموز ICO

كيف نحدد عدد الرموز المميزة لـ ICO؟ حسنًا ، هناك عدد من الطرق لتعيين الحد الأقصى لعدد الرموز المميزة للعملة وقد تستحق هذه المسألة مناقشة مطولة في حد ذاتها.

لتلبية احتياجات برنامجنا التعليمي ECR20 ، سنستخدم أبسط نهج: تعيين المبلغ الإجمالي للرموز في وقت إنشاء العقد وتعيينها جميعًا في البداية إلى "مالك العقد" ، أي الحساب الذي نشر العقد الذكي:

 uint256 totalSupply_; constructor(uint256 total) public { totalSupply_ = total; balances[msg.sender] = _totalSupply; }

المُنشئ هو وظيفة خاصة تسمى تلقائيًا بواسطة Ethereum مباشرة بعد نشر العقد. يتم استخدامه عادةً لتهيئة حالة الرمز المميز باستخدام المعلمات التي تم تمريرها بواسطة حساب نشر العقد.

msg هو متغير عالمي تم الإعلان عنه وملؤه بواسطة Ethereum نفسها. يحتوي على بيانات مهمة لتنفيذ العقد. الحقل الذي نستخدمه هنا: يحتوي المرسل msg على حساب msg.sender الذي ينفذ وظيفة العقد الحالي.

يمكن فقط لحساب النشر أن يدخل مُنشئ العقد. عند بدء العقد ، تخصص هذه الوظيفة الرموز المميزة المتاحة لحساب "مالك العقد".

احصل على إجمالي توريد الرموز

 function totalSupply() public view returns (uint256) { return totalSupply_; }

ستعيد هذه الوظيفة عدد جميع الرموز المميزة التي خصصها هذا العقد بغض النظر عن المالك.

الحصول على رصيد المالك الرمز المميز

 function balanceOf(address tokenOwner) public view returns (uint) { return balances[tokenOwner]; }

balanceOf رصيد الرمز المميز الحالي للحساب المحدد بواسطة عنوان المالك.

تحويل الرموز إلى حساب آخر

 function transfer(address receiver, uint numTokens) public returns (bool) { require(numTokens <= balances[msg.sender]); balances[msg.sender] = balances[msg.sender] — numTokens; balances[receiver] = balances[receiver] + numTokens; emit Transfer(msg.sender, receiver, numTokens); return true; }

كما يوحي اسمها ، يتم استخدام وظيفة transfer لنقل numTokens من الرموز المميزة من رصيد المالك إلى رصيد مستخدم آخر أو receiver . مالك النقل هو msg.sender أي الشخص الذي يقوم بتنفيذ الوظيفة ، مما يعني أن مالك الرموز فقط يمكنه نقلها إلى الآخرين.

طريقة Solidity لتأكيد المسند require . في هذه الحالة أن يكون للحساب المحول رصيد كافٍ لتنفيذ التحويل. في حالة فشل بيان الطلب ، يتم التراجع عن المعاملة require الفور دون كتابة أي تغييرات في blockchain.

قبل الخروج مباشرة ، تطلق الوظيفة Transfer حدث ERC20 مما يسمح للمستمعين المسجلين بالرد على اكتمالها.

اعتماد المندوب لسحب الرموز

غالبًا ما تُستخدم هذه الوظيفة في سيناريو سوق الرمز المميز.

 function approve(address delegate, uint numTokens) public returns (bool) { allowed[msg.sender][delegate] = numTokens; emit Approval(msg.sender, delegate, numTokens); return true; }

ما تفعله approve هو السماح للمالك ، أي msg.sender ، بالموافقة على حساب مفوض - ربما يكون السوق نفسه - لسحب الرموز المميزة من حسابه وتحويلها إلى حسابات أخرى.

كما ترى ، تُستخدم هذه الوظيفة في السيناريوهات التي يعرض فيها المالكون الرموز المميزة في السوق. يسمح للسوق بإنهاء المعاملة دون انتظار الموافقة المسبقة.

في نهاية تنفيذها ، تطلق هذه الوظيفة حدث Approval .

احصل على عدد الرموز المعتمدة للسحب

 function allowance(address owner, address delegate) public view returns (uint) { return allowed[owner][delegate]; }

تقوم هذه الوظيفة بإرجاع العدد الحالي المعتمد من الرموز المميزة بواسطة المالك إلى مفوض معين ، كما هو محدد في وظيفة approve .

تحويل الرموز من قبل المندوب

وظيفة transferFrom هي نظير وظيفة approve ، والتي ناقشناها سابقًا. يسمح للمفوض المعتمد للسحب بتحويل أموال المالك إلى حساب جهة خارجية.

 function transferFrom(address owner, address buyer, uint numTokens) public returns (bool) { require(numTokens <= balances[owner]); require(numTokens <= allowed[owner][msg.sender]); balances[owner] = balances[owner] — numTokens; allowed[owner][msg.sender] = allowed[from][msg.sender] — numTokens; balances[buyer] = balances[buyer] + numTokens; Transfer(owner, buyer, numTokens); return true; }

إن العبارتين require عند بدء الوظيفة هما التحقق من شرعية المعاملة ، أي أن المالك لديه ما يكفي من الرموز لنقلها وأن المفوض لديه موافقة (على الأقل) numTokens .

بالإضافة إلى تحويل مبلغ numTokens من المالك إلى المشتري ، تطرح هذه الوظيفة أيضًا numTokens من بدل المندوب. يسمح هذا بشكل أساسي للمندوب الذي لديه بدل معين بتقسيمه إلى عدة عمليات سحب منفصلة ، وهو سلوك نموذجي في السوق.

يمكننا التوقف هنا والحصول على تنفيذ صالح لـ ERC20. ومع ذلك ، نريد أن نخطو خطوة إلى الأمام ، لأننا نريد رمزًا مميزًا للقوة الصناعية. يتطلب ذلك منا أن نجعل الكود الخاص بنا أكثر أمانًا ، على الرغم من أننا سنظل قادرين على الحفاظ على الرمز المميز بسيطًا نسبيًا ، إن لم يكن أساسيًا.

مكتبة صلابة SafeMath

SafeMath هي مكتبة Solidity تهدف إلى التعامل مع طريقة واحدة من المعروف أن المتسللين يكسرون العقود: هجوم تجاوز عدد صحيح. في مثل هذا الهجوم ، يجبر المخترق العقد على استخدام قيم رقمية غير صحيحة عن طريق تمرير المعلمات التي ستأخذ الأعداد الصحيحة ذات الصلة إلى ما بعد قيمها القصوى.

مكتبة Safemath في Solidity: توضيح

تحمي SafeMath من هذا عن طريق اختبار تجاوز التدفق قبل تنفيذ الإجراء الحسابي ، وبالتالي إزالة خطر هجوم تجاوز السعة. المكتبة صغيرة جدًا بحيث يكون التأثير على حجم العقد ضئيلًا ، ولا تتحمل أي أداء وغرامات قليلة على تكلفة التخزين.

دعنا نضيف SafeMath إلى الكود الخاص بنا:

 library SafeMath { // Only relevant functions function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a — b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } }

يستخدم SafeMath عبارات assert للتحقق من صحة المعلمات التي تم تمريرها. إذا تم assert على الفشل ، فسيتم إيقاف تنفيذ الوظيفة على الفور وسيتم إرجاع جميع تغييرات blockchain.

بعد ذلك ، دعنا نضيف العبارة التالية لتعريف المكتبة بمجمع Solidity:

using SafeMath for uint256;

بعد ذلك ، نستبدل العمليات الحسابية الساذجة التي استخدمناها في البداية بوظائف SafeMath:

 balances[msg.sender] = balances[msg.sender].sub(numTokens); balances[receiver] = balances[receiver].add(numTokens); balances[buyer] = balances[buyer].add(numTokens); balances[owner] = balances[owner].sub(numTokens);

نحزم كل شيء معًا

في Solidity ، يتم تغليف وظائف وأحداث العقد الذكي في كيان يسمى العقد والذي يمكنك ترجمته بصمت إلى "فئة blockchain". يوجد أدناه العقد المتوافق مع ERC20 الذي أنشأناه ، بما في ذلك جوهر الكود الخاص بنا. يمكن تغيير حقول الاسم والرمز حسب الرغبة. تحافظ معظم الرموز المميزة على القيمة العشرية عند 18 ، لذلك سنفعل الشيء نفسه.

نشر عقد Ethereum

حان الوقت لنشر عقدنا في blockchain. بعد النشر ، سيتم نقل عقدنا إلى جميع العقد المشاركة في الشبكة. سيتم نشر أي وجميع التغييرات التي تم إجراؤها على العقد على جميع العقد المشاركة.

يستخدم مطورو Ethereum عادةً أدوات النشر مثل Truffle. حتى الكمأة مبالغة في تلبية الاحتياجات المحدودة لهذه المقالة ، وستكون أداة بسيطة عبر الإنترنت تسمى Remix كافية.

لاستخدامه ، ستحتاج إلى تثبيت المكون الإضافي MetaMask على متصفحك وحساب Rinkeby (شبكة اختبار Ethereum) مع بعض Rinkeby Ether على الأقل. هذه خطوات بسيطة نسبيًا ، لذا لن نخوض في التفاصيل.

في حالة عدم وجود أي منهما ، توجه إلى MetaMask و Rinkeby للحصول على روابط التنزيل والحصول على إرشادات التثبيت والاستخدام الواضحة.

الآن بعد أن أصبح لدينا جميع وحدات البناء في مكانها الصحيح ، سننتقل إلى Remix ولصق الكود أعلاه ، بما في ذلك خط pragma ومكتبة SafeMath ، في المحرر عبر الإنترنت.

بعد ذلك ، سننتقل إلى علامة التبويب الثانية الموجودة على اليسار والتي تسمى " تشغيل " وانقر على " نشر ". ستظهر نافذة منبثقة MetaMask تطلب منا تأكيد المعاملة. بالطبع ، سنوافق عليه.

نص بديل للصورة

  • المربع الأخضر: تأكد من أنك في Rinkeby
  • المربع الأزرق: قم بتعيين إجمالي التوريد المميز الخاص بك
  • الصندوق الأحمر: انشر!

Gist : https://gist.github.com/giladHaimov/8e81dbde10c9aeff69a1d683ed6870be#file-basicerc20-sol

تهاني! لقد قمت للتو بنشر أول رمز مميز لـ ERC20 ، مثل محترف Ethereum حقيقي. كما هو موعود ، فإن الرمز المميز بسيط وخفيف الوزن ، ولكنه يعمل بكامل طاقته ، ومتوافق مع معيار ERC20 ، ومضمون مع MathSafe. إنه جاهز للشراء ، والدفع ، والتحويل في جميع أنحاء Blockchain.

هل هذا كل ما في العقود الذكية؟

لا ، ليس قريبًا ، حيث إن عرضنا الموجز بالكاد يخدش السطح ويتعامل فقط مع جانب واحد من تطوير العقود الذكية.

يمكن أن تكون العقود الذكية أكثر تعقيدًا اعتمادًا على منطق عملك ، ونمذجة تفاعل المستخدم ، سواء سمحت بسك الرموز المميزة وحرقها ، أو تغييرات دورة الحياة التي تدخلها في العقد ، والحاجة إلى إمكانات على مستوى المسؤول والتي تأتي عادةً مع مجموعة من الوظائف المصرح بها من قِبل المسؤول ، وما إلى ذلك. يمكنك الحصول على الصورة.

ومع ذلك ، إذا كان بإمكانك تكرار ما فعلناه هنا ، فهذا أساس متين لتوسيع معرفتك والانتقال إلى عقود أكثر تعقيدًا عند الضرورة.