توابع بازگشتی در سالیدیتی
12 خرداد 1401 1401-03-22 13:00توابع بازگشتی در سالیدیتی
توابع بازگشتی در سالیدیتی
در دنیای امروزی بسیاری از افراد از طریق رمزارزها درآمد کسب می کنند. شاید فکر کنید این درآمد فقط از طریق خرید و فروش ، ترید و کارهای مشابه بدست می آید ، اما اینگونه نیست. بسیاری از این افراد از طریق برنامه نویسیقراردادهای هوشمند در پلتفرم های مختلف بالک چین، به ویژه اتریوم درآمد کسب می کنند. در این مقاله می خواهیم به معرفی تابع بازگشتی در زبان برنامه نویسی Solidity و کاربرد توابع بازگشتی در سالیدیتی را بررسی کنیم. زیرا وقتی صحبت از استقرار قراردادهای هوشمند در بالک چین اتریوم می شود، اهمیت توابع بازگشتی به دلیل تغییر ناپذیری آن ها بیشتر می شود.
آشنایی با زبان برنامه نویسی سالیدیتی(Solidity)
زبان برنامه نویسی سالیدیتی (Solidity) یک زبان برنامه نویسی جدید است که توسط اتریوم، دومین بازار بزرگ
ارزهای دیجیتال از نظر سرمایه گذاری، توسعه یافته است .سالیدیتی یک زبان برنامه نویسی شیء گرا برای پیاده سازیقراردادهای هوشمند در پلتفرم های مختلف بالک چین، به ویژه اتریوم می باشد. برنامه های سالیدیتی روی ماشینمجازی اتریوم (EVM) اجرا می شوند. می توان گفت سالیدیتی زبان اصلی در اتریوم و همچنین سایر بلاک چین های خصوصی در پلتفرمهایی است که با اتریوم رقابت می کنند. پلتفرمهایی مانند Monax و بلاک چین Hyperledger Burrow
زبان برنامه نویسی سالیدیتی (Solidity)از برخی جهات مهم با سایر زبان های هدف EVM مانند Serpent و
Mutan متفاوت است. این زبان از متغیرهای پیچیده برای قراردادها، از جمله نگاشت ها و ساختارهای سلسله مراتبی دلخواه پشتیبانی می کند. با این حال ، این زبان شباهت های زیادی با زبان C و C ++دارد و یادگیری و درک آن بسیارساده است. به عنوان مثال، “main”در C معادل “contract “یا همان قرارداد در سالیدیتی می باشد. مانند سایر زبان های برنامه نویسی، سالیدیتی نیز دارای متغیرها، توابع، کالس ها، عملیات حسابی، رشته ها و بسیاری مفاهیم دیگر است.یکی از مهم ترین توابع زبان برنامه نویسی سالیدیتی ، تابع بازگشتی (Function Fallback) می باشد .
تابع بازگشتی (Fallback Function) چیست؟
پس از استقرار یک قرارداد هوشمند، بازگشتی وجود ندارد. پس توابع بازگشتی دقیقاً چه کاری انجام می دهند؟ توابع بازگشتی در سالیدیتی (Solidity) زمانی اجرا می شوند که یک شناسه تابع با هیچ یک از عملکردهای موجود در قرارداد هوشمند مطابقت نداشته باشد یا اصلا داده ای ارائه نشده باشد.
تابع بازگشتی (Fallback Function) در قراردادهای هوشمند Solidity زمانی اجرا می شود که یک قرارداد اتر را بدون هیچ داده اضافی دریافت کند. برای اینکه قرارداد شما اتر را دریافت کند و به کل موجودی قرارداد اضافه شود، باید یک تابع بازگشتی وجود داشته باشد و باید به عنوان قابل پرداخت اعلام شود. اگر این تابع وجود نداشته باشد، قرارداد نمی تواند اتر را دریافت کند و یک استثنا ایجاد می کند. اگر این تابع را ندارید و قرارداد اتر دریافت می کند، برای فرستنده بازگردانده می شود.توابع بازگشتی در سالیدیتی تنها می تواند به مقدار کمی گس در دسترس (2300 gwei) تکیه کند که فضای کمی برای انجام هر عملیات دیگری به جز ثبت اولیه ایجاد می کند. عملیات زیر بیشتر از سهمیه گس 2300 گس مصرف می کند.
- در صورتی که هیچ یک از توابع مخالف با شناسه تابع مطابقت نداشته باشد. به عبارتی دیگر اگر شناسه تابع با هیچ یک از عملکردهای موجود در قرارداد هوشمند مطابقت نداشته باشد
- در صورتی که هیچ داده ای همراه با فراخوانی تابع ارائه نشده باشد
- در صورتی که هیچ داده ای همراه با فراخوانی تابع ارائه نشده باشد
- زمانی که قرارداد اِتر ، ساده و بدون داده باشد
در نظر داشته باشید که تابع بازگشتی برای دریافت اِتر و اضافه کردن آن به کل موجودی قرارداد قابل پرداخت ، باید علامت گذاری شود.یک قرارداد می تواند یک تابع بدون نام داشته باشد. این تابع نمی تواند هیچ آرگومانی داشته باشد، نمی تواند چیزی را برگرداند و باید به صورت external تعریف شود. این تابع زمانی اجرا می شود که هیچ یک از توابع دیگر با شناسه تابع داده شده مطابقت نداشته باشد (یا هیچ داده ای در پیام تراکنش ارائه نشده باشد).مانند هر تابع Solidity دیگر، تابع بازگشتی می تواند تا زمانی که گس کافی برای انجام تراکنش وجود داشته باشد، عملیات پیچیده را اجرا کند.
ویژگی های توابع بازگشتی (Function Fallback)
- بی نام یا بدون اسم هستند
- نمی توانند استدلال بپذیرند
- نمی توانند چیزی را برگردانند
- در هر قرارداد هوشمند تنها یک تابع بازگشتی می تواند وجود داشته باشد
- علامت گذاری خارجی آن ها الزامی است
- نمی تواند آرگومان داشته باشد
- برای دریافت اتر باید به عنوان Payable اعلام شود
همان طور که گفتیم ، یک قرارداد می تواند حداکثر یک تابع بازگشتی (Function Fallback) داشته باشد. مانند توابع دیگر ، این تابع نیز تا زمانی که گس (gwei – GAS ) کافی به آن ارسال شده باشد، می تواند عملیات پیچیده را اجرا کند. این تابع می تواند نهایتاً 2300 گس دریافت کند. بنابراین نمی تواند عملیات پیچیده ای که گس بیشتری مصرف می کنند را انجام دهد. برای مثال اگر یک تابع بازگشتی قابل پرداخت به جای تابع دریافت نیز استفاده شود،2300 گس مصرف می شود .
به طور خالصه می توان گفت که تابع بازگشتی یک نوع سوپاپ امنیتی می باشد. توسعه دهندگان سالیدیتی (Solidity) یک گزینه ی طراحی پیش فرض با توابع بازگشتی را طراحی کرده اند. این موضوع می تواند بسیار جالب باشد. چرا که توابع بازگشتی در صورتی اجرا می شوند که یک قرارداد خاص ، اِتر را بدون هیچ داده دیگری مرتبط با تراکنش دریافت کند. این طراحی پیش فرض معقول است و موجب محافظت از کاربران می شود.تابعی برای قراردادهای هوشمند ساده اِتر با این حال با توجه به نوع استفاده ما ، بسیار مهم است که قرارداد هوشمند ساده اِتر را از طریق یک تابع بازگشتی دریافت کند. برای انجام این کار تابع بازگشتی باید شامل اصالح کننده قابل پرداخت باشد. اگر تابع بازگشتی قابل پرداخت وجود نداشته باشد، قرارداد استثنا صادر می کند و اِتر را به فرستنده باز می گرداند. به این ترتیب قرارداد ساده ی اِتر را بدون هیچ داده دیگری دریافت می کند.
همان طور که گفتیم ، تابع بازگشتی (Function Fallback) می تواند نهایتاً 2300 گس (gwei) دریافت کند. این مقدار فضای زیادی را برای انجام سایر عملیات ها و عملیات پیچیده باقی نمی گذارد. به عبارتی دیگر ، با این نوع تابع نمی توان عملیاتی مثل ایجاد قرارداد ، فراخوانی توابع خارجی و ارسال اِتر انجام داد. بنابراین توابع بازگشتی باید ساده و آسان باشند
عملیات زیر سهم زیادی از گس (Gas) مصرف می کنند
- نوشتن در بلاکچین
- تولید قراردادهای هوشمند
- بازخوانی یک تابع خارجی که میزان بالایی گس استفاده می کند
- فرستادن تراکنش اتر
هر قرارداد می تواند توابع بدون اسم داشته باشد. لازم است تا این تابع به شکل اکسترنال معرفی شود. همچنین نمی تواند دارای آرگومان باشد یا چیزی را برگرداند. این تابع موقعی قابل پیاده سازی است که هیچ کدام از توابع دیگر با شناسه تابع مورد نظر همخوانی نداشته باشند یا این که اطلاعات دیگری در پیغام تراکنش ها دیده نشود. مثل توابع سالیدیتی، تابع بازگشتی قادر است تا هنگامی که گس به اندازه کافی برای انجام دادن تراکنش ها داشته باشد عملیات سخت که دارای پیچیدگی هستند را پیاده سازی نماید.
توابع بازگشتی هنگامی بازخوانی می شوند که یکی از دو وضعیت زیر برقرار باشد:
- فراخوانی تابعی که در قرارداد موجود نیست.
- هنگامی که اتر را به یک قرارداد با دستوراتی مثل send یا call یا transfer بفرستیم.
در مثال زیر قراردادی را مشاهده می کنیم که نحوه عملکرد تابع بازگشتی را نشان می دهد.
pragma solidity ^0.4.0;
// Creating a contract
contract GeeksForGeeks
{
// Declaring the state variable
uint x;
// Mapping of addresses to their balances
mapping(address => uint) balance;
// Creating a constructor
constructor() public
{
// Set x to default
// value of 10
x=10;
}
// Creating a function
function SetX(uint _x) public returns(bool)
{
// Set x to the
// value sent
x=_x;
return true;
}
// This fallback function
// will keep all the Ether
function() public payable
{
balance[msg.sender] += msg.value;
}
}
// Creating the sender contract
contract Sender
{
function transfer() public payable
{
// Address of GeeksForGeeks contract
address _receiver =
0xbcc0185441de06F0452D45AEd6Ad8b98017796fb;
// Transfers 100 Eth to above contract
_receiver.transfer(100);
}
}
تصویر خروجی کد های توابع بازگشتی در سالیدیتی:
قرارداد GeeksForGeeks دارای یک متغیر x است که در ()constructor روی مقدار پیش فرض 10تنظیم شده است. این قرارداد دارای تابعی به نام SetX(uint_x) می باشد که مقدار تابع را به پارامتر دلخواه ارسال شده در طول فراخوانی تابع تنظیم می کند. اعلان زیر نقشه آدرسی به نام تعادل را ایجاد می کند که آدرس ها را به تعادل آنها نگاشت می کند .
mapping(address => uint) balance;
فرستنده قرارداد : (Sender Contract)یک قرارداد کامال مستقل و غیر مرتبط است. سپس اِتر به قرارداد
GeeksForGeeks ارسال می شود.
عبارات زیر یک متغیر receiver _از نوع آدرس را اعلام می کند که آدرس قرارداد GeeksForGeeks را ذخیره می کند. سپس از (value(transfer.address برای انتقال اِتر به قرارداد استفاده می کند .
address _receiver = 0xbcc0185441de06F0452D45AEd6Ad8b98017796fb; //Address of GeeksForGeeks contract _receiver.transfer(100);
تابع payable public() Function یک تابع بازگشتی است. پس از اعلام و تشخیص قابل پرداخت بودن ، انتقال اِتر را می پذیرد .
تابع بازگشتی (Function Fallback) به ما کمک می کند تا از بروز خطا جلوگیری کنیم. در مثال فوق ، قرارداد GeeksForGeeks فقط اِتر را دریافت می کند و تابع بازگشتی از مقدار دریافتی برای اضافه کردن موجودی مربوط به آدرس ارسال استفاده می کند.
تابع payable در سالیدیتی
تابع payable همان تابع قابل پرداخت در سالیدیتی است. زمانی که می خواهید یک قرارداد هوشمند بنویسید لازم است تا مطمئن شوید که پول به قزارداد و خارج از آن فرستاده می شود. payable این کار را برای شما به انجام می رساند. هر تابع در سالیدیتی با این اصلاح کننده به شما ضمانت می دهد که تابه می تواند اتر را بفرستد و بگیرد. این تابع می تواند تراکنش های اتری که صفر نباشند را پردازش نماید؛ اما هر تراکنش با اتر صفر را قبول نمی کند. به علاوه چنانچه تابعی را جهت پردازش کردن تراکنش ها خواستار هستید، اما واژه کلیدی قابل پرداخت را وارد نکردید تراکنش به خود به خود رد می شود.