برنامه نویسی Smart Contract روی بلاکچین - قسمت ۱

درود. تو این سری من می‌خوام راجع به Smart Contract ها یا همون قرارداد های هوشمند روی بلاکچین صحبت کنم. اول اینکه من تجربه زیادی در این مورد ندارم و صرفا میخوام اطلاعاتی که به دست اوردم رو با شما به اشتراک بذارم و تمام تلاشم رو میکنم تا کمترین میزان اشتباه رو داشته باشم. اگه اشتباهی دیدین لطفا تو کامنت ها بهم بگین تا حتما درستشون کنم. بریم که شروع کنیم. برای فهمیدن این نوشته انتظار میره شما درک کلی ای از برنامه نویسی داشته باشید و مفاهیمی مثل تابع یا متغییر ها رو درک کنید. نیازی به دانش عمیق برنامه نویسی نیست.قرارداد هوشمند یا Smart Contract چیه؟قرارداد هوشمند در واقع یه کد نوشته شده ای هست که توی بلاکچین قرار گرفته و غیر قابل تغییره. این کد یکسری توابع عمومی (public) داره که بقیه میتونن اونها رو صدا بزنن. این توابع میتونن اطلاعاتی که خودشون ایجاد کردن توی بلاکچین تغییر بدن یا اطلاعاتی جدیدی اونجا ثبت کنن. همچنین میتونن انواعی از رمزارز که روی بلاکچین وجود داره دریافت کنن و حتی اونها رو خرج کنن!خب این به چه درد میخوره؟بیاین با یه مثال خیلی ساده شروع کنیم. فکر کنیم آقای بهادری می‌خواد اختراع جدیدش که یه ریشتراش لیزری هستش رو تولید انبوه کنه. آقای بهادری برای شروع اینکار به ۱۰۰ میلیون تومن سرمایه احتیاج داره و قصد داره این سرمایه رو از طریق سرمایه گذاری جمعی (crowdfunding) تامین کنه. خب پس میاد شماره حسابش رو برای انجام این کار اعلام میکنه که کسانی که دوست دارن بیان و توی انجام این پروژه به حسابش پول بریزن. و اگه تا یک ماه به ۱۰۰ میلیون نرسید آقای بهادری پول همه رو پس میده.ولی این کار چندتا مشکل به داره!۱. اگه آقای بهادری موجودی حسابش رو دروغ بگه و به جای ۱۰۰ میلیون مثلا ۲۰۰ میلیون پول جمع کنه چی؟۲. از کجا معلوم که اگه پروژه به هدف ۱۰۰ میلیون نرسید آقای بهادری پول همه رو پس بده؟۳. از کجا معلوم آقای بهادری تو این فاصله یک ماهه از این پول ها استفاده نکنه؟یکی از راه حل هایی که برای این مشکل ها وجود داره پلتفرم های سرمایه گذاری جمعی مثل kickstarter هستن. مردم به اونها اعتماد دارن و پول رو به حساب اونها میریزن. در نهایت هم اگه پروژه به هدفش رسید پول رو به حساب صاحب پروژه میریزن و اگه نرسید پول مردم رو به اونها برمیگردونن. به ازای این خدمت هم درصدی از پول جمع شده رو برای خودشون نگه میدارن. پس این روش هم مشکلات خودش رو داره!‍۱. مجبوریم به پلتفرم ها اعتماد کنیم و ممکنه اونها از ما یا صاحب پروژه سو استفاده کنند.۲. یه قسمت قابل توجهی از سرمایه نصیب این پلتفرم ها میشه. سرمایه ای که میتونه خرج پروژه ای که ما میخوایم ازش حمایت کنیم بشه!یک قرارداد هوشمند سادهخب حالا بیاین ببینیم چجوری میتونیم با استفاده از Smart Contract ها این مشکل رو حل کنیم؟ لطفا به این تیکه کد توجه کنید. دقت کنید این کد به زبان خاصی نوشته نشده و فقط الکی برای درک بهتر موضوعه.int total; address owner; datetime deadline = '2021-01-31'; int goal = 100_000_000; map(address, amount) sender_amounts; function fund(int amount) { if ( now < deadline) { sender_amounts.add(sender, sender_amounts[sender] + amount); total = total + amount; } else { error(&quotDeadline reached!&quot); } } function refund() { if( now > deadline && total < goal ) { transfer_to(sender, sender_amounts[sender]; sender_amounts[sender] = 0; } else { error(&quotYou cannot get a refund&quot); } } function collect() { if ( now > deadline && total >= goal ) { transfer_to(owner, total); } else { error(&quotYou cannot collect funds&quot); } }اول اینکه اگه متوجه نشدین این چیه نگران نباشید چون قراره کامل و خط به خط توضیح بدیم چه اتفاقی داره میوفته. این کد کل چیزیه که ما برای سناریومون بهش احتیاج داریم و تمام مشکلاتی که مطرح کردیم رو حل میکنه. حالا بیاین توضیح بدیم دقیقا داره چه اتفاقی میوفته. به چند خط اول توجه کنید.int total; readonly address owner = '0xERt5...'; readonly datetime deadline = '2021-01-31'; readonly int goal = 100_000_000; map(address => int) sender_amounts;این قسمت فضای ذخیره سازی (Storage) قرارداد هوشمند ما هستش. اینجا ما میتونیم چیزایی که نیاز داریم رو ذخیره کنیم و بعدا بهشون دسترسی داشته باشیم. در واقع شبیه Global Variable ها هستن ولی توی بلاکچین ذخیره میشن. اولین متغییر ما total هستش؛ توی اون مقدار کل پولی که دریافت کردیم رو ذخیره میکنیم. متغییر بعدی owner هستش. توی این متغییر ما آدرس صاحب پروژه یعنی آقای بهادری رو نگه میداریم. دقت کنید که نوع این متغییر readonly تعریف شده و غیر قابل تغییره. دو متغییر بعدی deadline و goal هستن که به ترتیب مهلت پروژه و هدف پروژه که اینجا ۱۰۰ میلیون تومان تعریف شده قرار دارن.متغییر آخر یعنی sender_amounts کمی پیچیده تره و از نوع map تعریف شده و میتونه به ازای هر آدرس یک عدد نگه داره. این متغییر برای این تعریف شده که اگه قرار پروژه تا مهلت تعیین شده به هدفش نرسید ما بدونیم هر کسی چقدر پول واریز کرده تا به همون مقدار بهش برگردونیم.توابعتوابط اصلی ترین نقش رو توی قرارداد های هوشمند دارن. اما این توابع چطوری فراخوانی میشن؟کاربر از طریق کیف پولش (wallet) درخواست فراخوانی یک تابع رو میده و اون رو تو شبکه اعلام میکنه. ماینر ها این درخواست ها رو جمع میکنن و اونها رو روی قراردادی که از قبل توی بلاکچین قرار داده شده اجرا میکنن و بعد از اون تغییراتی که اون تابع روی فضای دخیره سازیش (storage) انجام داده رو توی بلاکچین ذخیره میکنن. بقیه کاربر ها هم میتونن اون توابع رو اجرا کنن و از صحت اطلاعاتی که ماینر نشون داده مطمعن بشن. این کار باعث میشه فقط کدی که توی بلاکچین ذخیره شده بتونه فضای ذخیره سازی رو تغییر بده و چون این کد بعد از اینکه تو بلاکچین قرار گرفت غیر قابل تغییره؛ امکان میتونیم به اون اعتماد کنیم. (در صورتی که اون کد رو بفهمیم)خب بریم سراغ اولین تابع. fundfunction fund(int amount) payable { if ( now < deadline) { sender_amounts.add(sender, sender_amounts[sender] + amount); total = total + amount; } else { error(&quotDeadline reached!&quot); } }این تابع برای سرمایه گذاری توسط بقیه تعریف شده. این تابع payable هست یعنی میتونه پول قبول کنه پس مردم با صدا زدن این تابع به مقدار amount برای پروژه آقای بهادری پول میفرستن. تو خط بعدی هم ما چک میکنیم مهلت پروژه نگذشته باشه و اگه نگذشته بود مقداری که ارسال شده رو توی sender_amounts نگه میداره و همچنین مقدار ارسال شده رو به total اضافه میکنه. اما اگه مهلت گذشته باشه ما ارور میدیم و هیچ تراکنشی انجام نمیشه!بریم سراغ تابع بعدی. refundfunction refund() { if( now > deadline && total < goal ) { transfer_to(sender, sender_amounts[sender]; sender_amounts[sender] = 0; } else { error(&quotYou cannot get a refund&quot); } }هدف تابع refund اینه که اگه مهلت سرمایه گذاری تموم شده بود و پروژه به هدف خودش نرسیده بود کسانی که توی پروژه سرمایه گذاری کرده بودن بتونن پولشون رو پس بگیرن. اولین چیزی که اینجا چک میشه اینه که زمانی کنونی (now) از زمان مهلت ما بزرگتر باشه. به عبارت دیگه مهلت ما تموم شده باشه و همچنین مقدار کل پولی که دریافت کردیم (total) از مقدار هدف کمتر باشه (goal). اگه این شرایط برقرار بود با استفاده از sender_amounts مقدار پولی که این کاربر فرستاده بود رو میگیریم و اون رو بهش بر می‌گردونیم. همچنین بعدش مقدار مربوط به این کاربر رو توی sender_amounts صفر میکنیم تا دوباره نتونه با صدا کردن این تابع از ما پول بگیره!تابع سوم هم تابع collect هستش.function collect() { if ( now > deadline && total >= goal ) { transfer_to(owner, total); } else { error(&quotYou cannot collect funds&quot); } }توی این تابع ما قصد داریم اگه مهلت پروژه تموم شده بود و به هدف رسیده بودیم کل مبلغی که دریافت کردیم رو به حساب صاحب پروژه بریزیم تا بتونه ازش استفاده کنه. اولین چیزی که چک میکنیم اینه که مهلت تموم شده باشه و به هدف مورد نظر رسیده باشیم total بزرگتر یا مساوی goal باشه. اگه اینطور بود کل مقداری که داریم رو به حساب owner میریزیم و اگه نبود ارور میدیم تا تراکنشی انجام نشه!خب می‌بینید که با یک کد بسیار ساده تونستیم یک سیستم سرمایه گذاری جمعی توضیع شده و قابل اعتماد درست کنیم. موارد استفاده از این تکنولوژه نامحدوده. یک نمونه از سیستم هایی که با این اسمارت کانترکت ها کار میکنه پلتفرمی به اسم Aave هست. توی این پلتفرم شما میتونین به صورت امنی پول قرض بدین و سود دریافت کنید یا پول قرض بگیرین و در واقع نیازی نیست این وسط به شخص یا شرکت خاصی اعتماد کنین چون کد این پلترفم توسط افراد زیادی بررسی و تایید شده و میشه گفت که امن هستش.در واقع این پلتفرم قدرت این رو داره که دنیا رو تغییر بده و کلی سیستم های توضیع شده و امن و غیر قابل سانسور ایجاد کنه.توی قسمت بعدی میخوام همین قرارداد هوشمندی که اینجا توضیح دادم رو با استفاده از زبان solidity روی بلاکچین اتریوم (ethereum) با هم مرحله به مرحله برنامه نویسی و اجرا کنیم.اگه سوالی داشتین حتما و حتما کامنت بزارین و سعی میکنم تو سریع ترین زمان جواب بدم. منتظر قسمت دوم باشید...