آموزش توابع Payable در سالیدیتی

توابع Payable در سالیدیتی چیست و چرا اهمیت دارد؟

در دنیای قراردادهای هوشمند، تنها کد و منطق برنامه نویسی کافی نیست؛ گاهی لازم است این قراردادها بتوانند مستقیماً با ارز دیجیتال اصلی شبکه اتریوم یعنی اتر (Ether) تعامل داشته باشند. اینجاست که مفهوم توابع Payable در سالیدیتی وارد میدان می‌شود.

توابعی که با کلیدواژه payable مشخص می‌شوند، قابلیت دریافت اتر را دارند و به شما امکان می‌دهند تا قراردادتان در لحظه اجرا، مقدار مشخصی از ارز دیجیتال دریافت کند. این ویژگی برای سناریوهایی مانند فروش توکن، پرداخت هزینه خدمات، یا مدیریت کیف پول های هوشمند کاملاً ضروری است.

آموزش توابع Payable در سالیدیتی

تا اینجای کار، ما از توکن ها برای نمایش مقدار استفاده می‌کردیم، اما اگر بخواهیم مستقیماً با اتر (Ether) کار کنیم چه؟ بیایید بررسی کنیم که یک قرارداد هوشمند چگونه می‌تواند با اتر تعامل داشته باشد.

بعد از اینکه این قرارداد را در محیط Remix مستقر (Deploy) کردید، متوجه می‌شوید که دکمه مربوط به تابع payMe به رنگ قرمز در‌می‌آید. این به این معناست که می‌توانید هنگام فراخوانی این تابع، مقداری اتر (Ether) به آن ارسال کنید. فیلدی در بالای دکمه ظاهر می‌شود که می‌توانید مقدار دلخواه را وارد نمایید.

با استفاده از تابع howMuchEtherIHave می‌توانید بررسی کنید که چه مقدار اتر در آدرس این قرارداد ذخیره شده است.

شما می‌تونید اتر (Ether) را در واحدهای مختلفی مانند Wei، Gwei، Finney یا خود Ether ارسال کنید.

  • ۱ Wei برابر است با یک ده میلیارد میلیاردُم (1/10^18) اتر.

  • ۱ Gwei برابر است با یک میلیاردم اتر.

  • ۱ Finney برابر است با یک دهم اتر.

برای ساده شدن کار، فرض کنیم می‌خواهیم یک اتر ارسال کنیم.

وقتی تابع howMuchEtherIHave را اجرا می‌کنیم، عدد زیر به ما برمی‌گردد:

1000000000000000000

این به این معنا نیست که ما به طور جادویی مقدار زیادی اتر ایجاد کرده‌ایم!
بلکه چون در بلاکچین چیزی به نام عدد اعشاری (float) وجود ندارد، اتر هم مثل توکن های ERC20 برای نمایش اعشار از واحدهای کوچکتر استفاده می‌کند.

در واقع یک واحد «اتر» برابر با ۱۰ به توان ۱۸ وی (Wei) است.

راستی، ساختار .balance نه‌تنها برای قرارداد فعلی، بلکه برای هر آدرسی قابل استفاده است. یعنی یک قرارداد هوشمند می‌تواند بررسی کند که یک آدرس چقدر اتر دارد.

مثلاً با کدی مثل زیر می‌توانیم موجودی یک آدرس را ببینیم:

اگر به یک تابعی که دارای کلیدواژه payable نیست، مقدار 10000000000000000000 (یعنی ۱۰ اتر) ارسال کنید، تراکنش با خطا مواجه شده و بازمی‌گردد (revert).

دلیل این محدودیت چیست؟

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

اگر تابعی برای دریافت اتر طراحی نشده باشد، دریافت وجه از بیرون می‌تواند منجر به رفتارهای ناخواسته یا مبهم شود. بنابراین، وجود کلیدواژه payable به‌عنوان یک شرط لازم برای دریافت اتر، به حفظ امنیت و پیش‌بینی‌پذیری قرارداد کمک می‌کند.

ساختار Payable در سازنده (Constructor)

در سالیدیتی، این امکان وجود دارد که سازنده (Constructor) را نیز با کلیدواژه payable تعریف کنیم. این قابلیت زمانی کاربرد دارد که بخواهید قرارداد هوشمند شما در لحظه ایجاد، با دریافت اتر (Ether)، فعالیت خود را با امتیاز و برتری اولیه آغاز کند. البته توجه داشته باشید که ارسال اتر هنگام ساخت قرارداد باید به‌صورت صریح انجام شود؛ صرفاً payable بودن سازنده کافی نیست.

همچنین، صرفاً payable بودن یک تابع به این معنا نیست که الزاماً باید در هر بار فراخوانی آن، اتر ارسال شود. بلکه این تنها یک اجازه برای امکان دریافت اتر است.

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

ارسال اتر (Ether) از طریق محیط Remix بسیار ساده است، زیرا می‌توانید هنگام اجرای تابع، مقدار اتر را مستقیماً مشخص کنید.
اما اگر یک قرارداد هوشمند بخواهد به قرارداد دیگری اتر ارسال کند، چه باید کرد؟

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

ممکن است در ابتدا این ساختار کمی عجیب به نظر برسد، اما به‌مرور زمان به آن عادت خواهید کرد.

بیایید بخش‌های مختلف این ساختار را بررسی کنیم:

  • در اینجا، تابع call دارای یک شیء شبیه به JSON میان نام تابع و آرگومان ها است. این همان جایی است که مقدار اتر (Ether) برای ارسال مشخص می‌شود. کلید "value" تعیین‌کننده مقدار ارسالی است و به‌صورت پیش‌فرض صفر است.

  • در قسمت (bool ok,)، ما یک تاپل تعریف کرده‌ایم که مقدار دوم آن خالی گذاشته شده است. این بدان معناست که ما خروجی تابع takeMoney() را نادیده می‌گیریم. اگر نیاز به بررسی مقدار بازگشتی نداریم، از این ساختار استفاده می‌کنیم.

  • با این حال، همچنان برای ما مهم است که آیا انتقال با موفقیت انجام شده یا نه. به همین دلیل از require(ok) استفاده کرده‌ایم تا در صورت شکست انتقال، تراکنش بازگردانده شود.

چند آزمایش پیشنهادی:

  1. هر دو قرارداد را مستقر (Deploy) کنید، اما هنگام ساخت قرارداد SendMoney، مقداری اتر برای آن در نظر بگیرید. سپس مقدار myBalance را در هر دو قرارداد، قبل و بعد از فراخوانی sendMoney بررسی کنید.

  2. عبارت payable را از تابع takeMoney حذف کنید و نتیجه را ببینید. انتظار می‌رود تراکنش برگشت بخورد (Revert شود).

  3. هنگام فراخوانی sendMoney مقداری اتر ارسال کنید و ببینید چگونه موجودی receiveEther افزایش می‌یابد.

محدودیت توابع Payable در سالیدیتی

توابعی که با payable تعریف می‌شوند نمی‌توانند از نوع view یا pure باشند.

دلیل این امر آن است که تغییر موجودی اتر یک قرارداد هوشمند، نوعی تغییر وضعیت (state change) در بلاکچین محسوب می‌شود. این تغییر، دائمی و غیرقابل بازگشت است؛ مانند تغییر یک متغیر ذخیره شده در حافظه. بنابراین، کامپایلر سالیدیتی اجازه نخواهد داد که چنین توابعی به‌عنوان view یا pure تعریف شوند.

5/5 - (1 امتیاز)

راستی! برای دریافت مطالب جدید در کانال تلگرام یا پیج اینستاگرام سورس باران عضو شوید.

آموزش انیمیشن‌ سازی دو بعدی با موهو – خلق انیمیشن‌ های خلاقانه شبیه دیرین دیرین
  • انتشار: ۱۵ اردیبهشت ۱۴۰۴

دسته بندی موضوعات

آخرین محصولات فروشگاه

مشاهده همه

نظرات

بازخوردهای خود را برای ما ارسال کنید