در این مطلب نحوه ساخت قرارداد هوشمند یا اسمارت کانترکت (Smart Contract) را در بایننس اسمارت چین (Binance Smart Chain) آموزش می‌دهیم. شبکه‌های بلاک چینی با قابلیت پشتیبانی از قرارداد های هوشمند در حال افزایش و رشد سریع هستند. قراردادهای هوشمند برنامه یا نرم افزارهایی هستند که بر بستر بلاک چین ساخته و هر زمان که کاربر درخواستی از آن داشته باشد، اجرا می‌شود. یکی از محبوب‌ترین شبکه‌هایی که از نوشتن و ساخت قرارداد هوشمند پشتیبانی می‌کند بلاک چین بی ان بی اسمارت چین یا زنجیره هوشمند بایننس (Binance Smart Chain) است.

در پلتفرمی مثل بایننس می‌توانیم به کمک پروتکل زنجیره هوشمند و قرارداد هوشمند، اپلیکیشن های غیر متمرکز میان‌زنجیره‌ای بسازیم و اجرا کنیم.

هدف از ساخت قرارداد هوشمند در بایننس اسمارت چین

توکن‌ها یا ارزهای دیجیتال در حقیقت ذرات بنیادی برای هر بلاک چین با قابلیت پشتیبانی از قرارداد هوشمند محسوب می‌شوند. به کمک ارزهای دیجیتال است که می‌توانیم اپلیکیشن‌های غیر متمرکز و پروتکل‌های دیفای بسازیم. در این مطلب قصد داریم به کمک ابزارهای سازگار با شبکه اتریوم مثل کیف پول متامسک (MetaMask) و محیط توسعه یکپارچه ریمیکس (Remix) و قرارداد هوشمند نحوه ساخت یک توکن در بایننس اسمارت چین را آموزش دهیم. در این فرآیند همچنین اصول اولیه را در مورد قراردادهای هوشمند، زبان برنامه‌نویسی سالیدیتی (Solidity) و عرضه کل و مدیریت و تخصیص توکن یاد می‌گیریم.

پیش‌نیازهای این مطلب:

  • دانش ابتدایی درباره فناوری بلاک چین
  • یک محیط توسعه یکپارچه برای قراردادهای هوشمند، مثل Remix IDE
  • یک کیف پول ارز دیجیتال، مثل متامسک

چرا زنجیره هوشمند بایننس برای ساخت قرارداد هوشمند؟

در گذر زمان و با استفاده زیاد کاربران، شبکه اتریوم به شدت دچار ازدحام شده است و متاسفانه Ethereum به خاطر ساختار ذاتی و الگوریتم اثبات کار استفاده‌شده در آن، مقیاس پذیری ضعیفی دارد. این ازدحام روی هزینه گس و سرعت تراکنش‌ها تاثیر منفی دارد و کاربران برای تایید عملیات‌های خود گاهی ملزم به چند ساعت صبر و پرداخت هزینه‌ای گزاف هستند. البته در ورزن 2 این شبکه قرار است از الگوریتم اثبات سهام استفاده شود، اما فعلا که خبری از این آپگرید به گوش نرسیده است. در سمت مقابل، بایننس اسمارت چین از الگوریتم اجماع اثبات اعتبار استفاده می‌کند که در بالا بردن سرعت تراکنش‌ها و کاهش هزینه پرداختی کاربران تاثیری بسیار زیاد دارد. به بیان دیگر، ساخت و اجرای قرارداد هوشمند در بایننس اسمارت چین بسیار ارزان‌تر و سریع‌تر از شبکه اتریوم انجام می‌شود.

در الگوریتم اجماع اثبات اعتبار زنجیره هوشمند بایننس سازندگان بلاک به نام اعتبارسنج شناخته می‌شوند. البته متاسفانه تنها 21 عدد از این اعتبارسنج‌ها وجود دارند و همگی توسط شرکت Binance احراز هویت و شناسایی شده‌اند. از آنجا که برای اعتبارسنج شدن در بایننس باید ابتدا این کمپانی هویت‌تان را تایید کند و کنترلی تمام و کمال بر عملیات‌های شما دارد، می‌توان کم و بیش این شبکه را کاملا متمرکز خطاب کرد و این برای یک شبکه بلاک چینی نکته‌ای بسیار منفی محسوب می‌شود. البته بایننس اسمارت چین کاملا با ماشین مجازی اتریوم سازگار و ساختن قرارداد هوشمند در آن آسان است و به نظر می‌آید متمرکز بودن تنها نکته منفی آن باشد.

راه اندازی محیط توسعه یکپارچه ریمیکس (Remix)

ریمیکس یک ابزار آنلاین و درون مرورگری رایگان برای اتریوم و زبان برنامه‌نویسی سالیدیتی است که همزمان قابلیت آزمایش، دیباگ و سوار کردن کد قرارداد هوشمند را بر بستر بلاک چین‌های Ethereum و Binance Smart Chain به کاربران خود ارائه می‌دهد. با مراجعه به وب سایت رسمی آن به آدرس remix.ethereum.org می‌توانید محیط توسعه یکپارچه ریمیکس را اجرا کنید. ادیتور ظاهری شبیه عکس زیر دارد:

محیط توسعه یکپارچه ریمیکس

در محیط ادیتور، ابتدا ورژن سالیدیتی مورد استفاده خود را انتخاب کنید. به عنوان مثال ما در این آموزش از version 0.8.2 استفاده می‌کنیم. سپس در بخش Workspaces، درون پوشه Contracts یک فایل جدید بسازید و نام آن را Token.sol بگذارید. هر فایلی که به زبان سالیدیتی نوشته شود باید حتما نوع لایسنس و ورژن زبان Solidity سازگار با کد و تنظیماتش را داشته باشد. درون فایل Token.sol دو خط کد زیر را اضافه کنید:

[js]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2; // compiler version
[/js]

کد ذکر شده در بالا بسیار واضح است.

  • سالیدیتی با استفاده از SPDX که در خط اول به عنوان شناساگر لایسنس مشخص شده است، تعیین می‌کند که کد ما با لایسنس MIT سازگار است.
  • خط pragma solidity ^0.8.2; به سالیدیتی می‌گوید که کد ما با نسخه 0.8.2 و بالاتر سازگاری دارد.

ساخت قرارداد هوشمند توکن در بایننس اسمارت چین

در بلاک چین‌هایی که از قرارداد هوشمند پشتیبانی می‌کنند، توسعه دهندگان باید بر اساس یک سری استاندارد از پیش تعیین شده توکن‌های خود را بسازند. این استانداردها در تمام ساختارهای شبکه از جمله اپلیکیشن غیر متمرکز، صرافی‌ها و کیف پول‌ها به کار می‌روند. در بلاک چین اتریوم معروف‌ترین استاندارد ERC20 نام دارد، اما بایننس اسمارت چین از استاندارد BEP-20 استفاده می‌کند که می‌توان گفت تا حد بسیار زیادی به ERC-20 شباهت دارد. از نمونه‌های محبوب توکن BEP-20 می‌توان به موارد زیر اشاره کرد:

  • توکن BUSD: این رمز ارز همان استیبل کوین دلار شبکه بایننس است که توسط Paxos ساخته شده.
  • توکن CAKE: رمز ارز کیک یک توکن BEP-20 برای پلتفرم پنکیک سواپ است.

تعریف قرارداد هوشمند برای توکن بایننس اسمارت چین

به طور کلی، هر فایل سالیدیتی باید یک قرارداد هوشمند درون خود داشته باشد. قرارداد هوشمند در زمان سالیدیتی را می‌توان به طریقی همان کلاس در زبان‌های شی‌گرا دانست، به این مفهوم که مجموعه‌ای از متغیرها، توابع، رویدادها، وضعیت بلاک چین و ویرایشگرها را شامل می‌شود. بنابراین کد خود را به این صورت آغاز می‌کنیم که در ابتدا یک قرارداد با نام Token می‌سازیم و متغیرهای وضعیت زیر را در آن قرار می‌دهیم:

[js]
contract Token{
uint public total_supply = 1500;
string public token_name = “Tutorial Token”; // token name – human – readable
string public symbol = “TTK”;
uint public decimals = 18; // will set the divisibility of your token
}
[/js]

  • متغیرهای وضعیت خارج از محدوده توابع قرارداد هوشمند تعریف می‌شوند. این متغیرها در حقیقت همانطور که از اسم‌شان پیداست، بر وضعیت قرارداد هوشمند نظارت می‌کنند و همواره در بلاک چین حضور دارند.
  • برای تعریف کردن متغیرهای Integer غیر منفی، از عبارت کلیدی uint استفاده می‌کنیم.
  • تمام متغیرهای تعریف شده به صورت عمومی توسط هر قرارداد هوشمند به صورت داخلی و بیرونی قابل دسترسی هستند.
  • خط کد uint public total_supply = 1500 یک متغیر وضعیت است که عرضه کل توکن ما را تعریف می‌کند. به بیان دیگر، با این قرارداد هوشمند می‌خواهیم تعداد 1500 توکن مثلی بسازیم.
  • خواندن بعضی آدرس‌ها سخت است، به همین خاطر از یک نوع داده رشته‌ای با نام token-name به عنوان اسم توکن خود استفاده می‌کنیم تا برای انسان‌ها خوانا باشد.
  • توکن‌های BEP-20 باید یک داده رشته‌ای symbol نیز داشته باشند که هنگام مبادله در صرافی‌ها استفاده شود.
  • واژه decimals در کدهای سالیدیتی و به طور کلی تمام رمز ارزها کوچک‌ترین بخش قابل خرید و فروش توکن را نشان می‌دهد. گزینه پیش‌فرض این متغیر 18 است، به این معنی که در هر تراکنش انتقالی، رقم مدنظر در 10 به توان 18 ضرب می‌شود. به عنوان مثال اگر بخواهیم 2 توکن را منتقل کنیم، رقم وارد شده در تراکنش در حقیقت 18 * 10 * 2 خواهد بود، یعنی 2,000,000,000,000,000,000 واحد از کوچک‌ترین دسیمال انتقال پیدا خواهد کرد.

اضافه کردن نگاشت (Mapping) و رویدادها

واژه نگاشت یک کلمه کلیدی در زبان سالیدیتی است که برای توسعه قرارداد هوشمند در بایننس اسمارت چین به کار می‌رود. کلید در اینجا اکثرا یک آدرس است که هر نگاشت ضبط شده را به موجودی (با واحد Integer) ارجاع می‌دهد. به بیان ساده‌تر، فلش همیشه به سمت نگاشت اشاره خواهد داشت. به عنوان مثال 0x0000 => 500 یک نگاشت است که نشان می‌دهد آدرس 0x0000 دقیقا 500 توکن موجودی دارد.

یک نگاشت برای موجودی‌ها تعریف کنید:

[js]
// mapping
mapping(address => uint) public _balance; // bal will constantly update
[/js]

آخرین نگاشت ما به نام allowance بخش خرج‌نشده توکن‌ها را محاسبه می‌کند که یک شخص ثالث به موجودی ما افزوده است. بعدا بیشتر در این باره توضیح می‌دهیم.

[js]
mapping(address => mapping(address => uint)) public allowance; //[allowance – how much spender is allowed to spend]

[/js]

ماشین مجازی اتریوم از رویدادها به گونه‌ای پشتیبانی می‌کند که نرم افزارهای بیرونی همچون کیف پول‌ها بتوانند از طرف کاربر عملیات‌های درون شبکه را زیر نظر داشته باشند. این رویدادها کلاینت را از وضعیت قرارداد هوشمند مطلع می‌کنند. رویداد Approval و Transfer را نیز اضافه کنید.

[js]
// event transfer
event Transfer(address indexed from, address indexed to, uint value);
// event emitted during an approval
event Approval(address indexed owner, address indexed spender, uint value);
[/js]

ساخت یک سازنده (Constructor) قرارداد هوشمند

در مرحله بعد باید یک سازنده به کد اضافه کنیم تا در هنگام اجرا شدن قرارداد فعال شود. برخلاف زبان‌های برنامه‌نویسی شی‌گرا که سازنده در آن‌ها با هر بار اجرا به وضعیت اولیه برمی‌گردد، سالیدیتی تنها یک بار و در زمان ساخت قرارداد هوشمند، سازنده را روی وضعیت init سوار می‌کند.

[js]
contract Token{
uint public total_supply = 1500;
string public token_name = “My Token”;
string public symbol = “MTK”;
uint public decimals = 18;
constructor(){
// send supply of tokens to the address that deployed smart contract
balances[msg.sender] = total_supply;
}
}
[/js]

در این قسمت سازنده را اضافه می‌کنیم تا تمام توکن‌های عرضه کل را به آدرس سازنده قرارداد هوشمند ارسال کند. دوره عمر توکن‌های در گردش از همین آدرس msg.sender آغاز می‌شود. گفتنی است که توزیع توکن‌ها می‌تواند از طریق عرضه اولیه سکه (ICO) یا ایردراپ انجام شود.

بازیابی موجودی در قرارداد های هوشمند

برای بررسی کردن تعداد توکن‌های درون آدرس هر کاربر، باید تابعی بسازید که آدرس را بگیرد و در ازای آن موجودی آدرس را برگرداند. توابع در قرارداد های هوشمند بایننس اسمارت چین برای عملیات‌های لحظه‌ای و درخواستی کاربران، همچون اعلام موجودی یا آپدیت وضعیت بلاک چین، به کار می‌روند.

[js]
function balanceOf(address owner) public view returns(uint) {
// return mapping balance of the owner
return balances[owner];
}
[/js]

استفاده از کلید واژه view در یک تابع نشان می‌دهد که تابع تنها برای خواندن اطلاعات ساخته شده است و تغییری در هیچ کدام از متغیرها ایجاد نمی‌کند. تمام توابعی که در آن‌ها از view استفاده می‌شود، هنگام اجرا هزینه گس ندارند و رایگان هستند.

انتقال مالکیت توکن‌ها

یکی از مراحل مهم آموزش ساخت قرارداد هوشمند در بلاک چین بایننس اسمارت چین این است که برای توکن‌مان تابع انتقال یا Transfer تعریف کنیم. درون این تابغ باید اطمینان کسب کنیم که شخص اجراکننده تراکنش انتقال واقعا صاحب توکن است.

[js]
function transfer(address to, uint value) public returns(bool){
// ensure sender has enough
require(balanceOf(msg.sender)>= value, ‘balance not enough’);
balances[to] += value;
balances[msg.sender] -= value;
// smart contracts emit event which external s/w e.g wallet
emit Transfer(msg.sender, to , value);
return true;
}
[/js]

  • تابع ()require نقش عملیات‌ها را در قرارداد هوشمند بررسی می‌کند. تابع require ما ارزش موجودی را از آدرس msg.sender می‌گیرد و بررسی می‌کنند که اجراکننده قرارداد هوشمند موجودی لازم برای این انتقال را در حساب خود دارد یا نه. اگر موجودی بیش از حد کم باشد، تراکنش لغو و ارور نمایش داده می‌شود.
  • تابع balances[msg.sender] به این معنی است که نگاشت ما می‌خواهد مقدار value را از توکن‌های فرستنده کم کند و در عوض balances[to] += value گیرنده را افزایش دهد. این عملیات‌ها حین اجرای تراکنش نگاشت قرارداد هوشمند را تغییر می‌دهند.
  • سپس تابع یک رویداد Transfer را ارسال می‌کند تا انتقال انجام شود.

تایید و انتقال

برای پشتیبانی کردن از تراکنش‌های واگذاری‌شده، باید عملیات‌های خرج‌کننده (Spender) را تایید کنیم تا صاحب حساب بتواند اجازه انتقال مقدار مشخص‌شده توکن را بدهد. تابع approve ارزش توکن‌های کم شده از موجودی فرستنده را محدود می‌کند.

کد تابع approve در قرارداد هوشمند ما برای بایننس اسمارت چین به شکل زیر است:

[js]
// Delegate a Transfer Functionn
function approve(address spender, uint value) public returns(bool){
allowance[msg.sender][spender] = value; // spender can spend *value* amount belonging to sender
emit Approval(msg.sender, spender, value); // emit approval event to allow spending
return true;
}
[/js]

برای انتقال دادن توکن‌ها از یک حساب به حسابی دیگر، باید از درون خود قرارداد هوشمند، تابع approve را روی آدرس spender فراخوانی کنیم.

  • خط allowance[msg.sender][spender] = value یک نگاشت است که می‌توانیم آن را به عنوان allowance[owner][recipient] = value ترجمه کنیم. این عمل موجب انجام تبادل (value به جای تعداد توکن‌ها قرار گرفته است) از طرف صاحب توکن‌ها می‌شود.
  • خط emit Approval(msg.sender, spender, value) رویدادی را از msg.sender می‌فرستد تا تایید کند spender می‌تواند مقدار مشخص شده در value را به آدرسش در قرارداد هوشمند خرج کند.

حال تابعی اضافه می‌کنیم تا انتقال‌ها از نمایندگان تاییدشده به صورت خودکار انجام شود. تابع transferFrom عملیات کاهش مقدار از حساب صاحب توکن‌ها و ارسال رویداد Transfer را انجام می‌دهد.

کد زیر را مشاهده کنید:

[js]
//
function transferFrom(address from, address to, uint value) public returns(bool){
// check allowance mapping if spender is approved
require(allowance[from][msg.sender] >=value, “allowance too low”);
// check balance
require(balanceOf(from) >= value, “balance is too low”);
// update mappings balances of sender & recipient
balances[to] += value;
balances[from] -= value;
// emit event
emit Transfer(from, to, value);
return true;
}
[/js]

  • خط اول require(allowance[from][msg.sender] >=value, “allowance too low”); تعداد کل توکن‌هایی را بررسی می‌کند که نماینده اجازه دارد از حساب صاحب توکن‌ها برداشت کند.
  • تابع balanceOf تعداد توکن‌هایی را بررسی می‌کند که آدرس باید خرج کردن‌شان را تایید کند. چرا که باید اول مطمئن شویم در آدرس موجودی لازم برای انتقال وجود دارد و دابل اسپندینگ رخ نمی‌دهد.
  • حالا نگاشت‌هایمان را آپدیت و رویداد Transfer را می‌فرستیم تا تراکنش تکمیل شود.

اجرای نهایی قرارداد هوشمند با متامسک

با کمک پلاگین کیف پول متامسک در ریمیکس می‌توانیم web3.js را به مرورگر وارد کنیم. اگر قرارداد هوشمند خود را قبل از راه‌اندازی روی بایننس اسمارت چین به صورت آزمایشی در یک محیط سندباکس اجرا کنیم، اپلیکیشن در مرحله نهایی باید به صورت زیر باشد. توجه داشته باشید که پیش از اجرای هر قرارداد هوشمند روی شبکه اصلی، ابتدا آن را روی شبکه‌های آزمایشی یا تست‌نت اجرا و راه اندازی کنید. همچنین گفتنی است که برای راه اندازی یک قرارداد هوشمند در شبکه آزمایشی نیازی به خرید بایننس کوین ندارید.

تابع قرارداد هوشمند بایننس اسمارت چین ریمیکس

سخن پایانی

تکنولوژی بلاک چین موج جدیدی از فناوری‌های مدرن را تقریبا در تمام حوزه‌های صنعتی این روزها ایجاد کرده است. به لطف قراردادهای هوشمند بی‌نیاز به مجوز و اعتماد، اشخاص کاملا غریبه می‌توانند با اطمینان کامل به تبادل و خرید و فروش توکن‌های مثلی و غیر مثلی با یکدیگر بپردازند. اما با وجود تمام این پیشرفت‌ها، وب3 و حوزه بلاک چین هنوز در دوران نوزادی به سر می‌برند و تا بلوغ فاصله زیادی دارند. تنها زمان می‌تواند مشخص کند که این تکنولوژی به بستر تمام فناوری‌ها بدل خواهد شد یا خیر. اما پر واضح است که یادگیری نحوه ساخت قراردادهای هوشمند به عنوان بخشی بنیادی از این تکنولوژی نوین، می‌تواند آینده‌ای روشن و پرسود برای کاربران این حوزه به ارمغان بیاورد.

تهیه شده در بیت 24