آموزش کدگذاری رابط باینری برنامه در سالیدیتی

آموزش کدگذاری رابط باینری برنامه در سالیدیتی

قبل از اینکه موضوع بعدی را یاد بگیریم، باید ابتدا یک نکته‌ ظاهراً بی‌ربط را بررسی کنیم که بعداً اهمیتش برایتان روشن می‌شود.

در این بخش، می‌خواهیم با مفاهیم زیر آشنا شویم:

  • abi.encode

  • abi.decode

  • abi.encodeWithSignature

برای اینکه ضرورت این مفاهیم را بهتر درک کنید، یک قرارداد هوشمند ساده می‌سازیم و از طریق منوی «debug» در ریمیکس، یک قطعه اطلاعات خاص را بررسی می‌کنیم.

زمانی که این تابع را در ریمیکس کپی می‌کنیم، خروجی زیر را دریافت خواهیم کرد:

0x92d62db5

این مقدار چیست؟

این در واقع امضای تابع (Function Signature) مربوط به تابع meaningOfLifeAndAllExistence() است. در ادامه یاد خواهید گرفت که این مقدار دقیقاً چگونه محاسبه می‌شود.

هر زمان که شما یک قرارداد هوشمند را “فراخوانی” می‌کنید، در واقع یک تراکنش اتریومی ارسال می‌کنید که شامل داده هایی است تا قرارداد هوشمند متوجه شود کدام تابع باید اجرا شود.

بیایید این اطلاعات را از زاویه‌ای دیگر بررسی کنیم.

ما نوع خروجی تابع را به bytes memory تغییر دادیم (نگران نباشید اگر هنوز با این نوع آشنا نیستید) و یک متغیر به نام msg.data را برگرداندیم (باز هم نگران نباشید که قبلاً آن را ندیده‌اید).

نکته مهم این است که دقیقاً همان دنباله بایت قبلی را دریافت می‌کنیم!

پس واقعاً چه اتفاقی می‌افتد؟

وقتی شما یک تابع را در یک قرارداد هوشمند صدا می‌زنید، در واقع یک «فراخوانی مستقیم تابع» انجام نمی‌دهید؛ بلکه در حال ارسال داده ای به قرارداد هستید که شامل اطلاعاتی است درباره اینکه کدام تابع باید اجرا شود.

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

وقتی شما یک «قرارداد هوشمند را صدا می‌زنید»، در واقع دارید داده ای به آن ارسال می‌کنید که شامل دستوراتی برای چگونگی اجراست.

در دنیا انواع مختلفی از فرمت های رمزگذاری داده وجود دارد؛ مثل JSON، XML، Protobuf و غیره. اما در سالیدیتی و اتریوم، از فرمت رمزگذاری ABI استفاده می‌شود.

ما فعلاً وارد مشخصات دقیق ABI نمی‌شویم، فقط کافی است بدانید که خروجی همیشه به شکل دنباله ای از بایت ها است.

توابع در ABI با دنباله ای از چهار بایت شناخته می‌شوند. دنباله بایتی که قبلاً دیدیم (0x92d62db5) شامل همین چهار بایت بود: 92، d6، 2d، b5.

به خاطر داشته باشید که یک بایت برابر با 8 بیت است، و 8 بیت می‌تواند مقادیری تا 255 (یعنی 2⁸ – 1) را نمایش دهد. وقتی یک بایت را به صورت هگزادسیمال بنویسیم، می‌تواند بین 0x00 تا 0xff باشد. اگر 0xff را به دسیمال تبدیل کنید، این موضوع برایتان روشن تر می‌شود.

اگر یک تابع هیچ آرگومانی نداشته باشد، تنها ارسال همین چهار بایت برای شناسایی و اجرای آن کافی است.

اما اگر تابع یک آرگومان داشته باشد، داده های ارسالی چه شکلی خواهند بود؟

ما مقدار زیر را دریافت می‌کنیم:

0xf8689fd30000000000000000000000000000000000000000000000000000000000000007

بخش f8689fd3 نشان‌دهنده این است که باید تابعی به نام takeOneArg فراخوانی شود، و بخش 07 (که با تعداد زیادی صفر در ابتدا همراه است) یعنی عدد ۷ باید به عنوان آرگومان به تابع ارسال شود.

اگر قرار بود این کار را دستی انجام دهیم، واقعاً گیج‌کننده و دشوار می‌شد.

خوشبختانه، نیازی نیست این کار را دستی انجام دهیم.

الان ببینید چطور می‌توانیم راحت‌تر این کار را انجام بدهیم.

لازم نیست فعلاً نگران جزئیات دقیق استاندارد ABI Encoding باشیم؛ در حال حاضر فقط کافی‌ست با نحوه استفاده از آن آشنا شویم.

به مثال زیر توجه کنید:

در این مثال، از abi.encode و abi.decode استفاده شده است. بخش withSignature زمانی استفاده می‌شود که توابع در کار باشند، اما اینجا ما فقط با داده ها سروکار داریم، نه فراخوانی تابع.

در اینجا، دو متغیر x و y توسط abi.encode به شکل زیر کدگذاری شده‌اند:

0x0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000f

اعداد ده دهی به مبنای شانزده (hex) تبدیل شده‌اند؛ به همین خاطر عدد ۵ همان “5” باقی مانده و عدد ۱۵ به “f” تبدیل شده است.

اگر از قبل بدانیم که این داده ها یک جفت uint256 هستند، می‌توانیم با استفاده از abi.decode آن‌ها را به درستی به همان جفت عدد برگردانیم.

پارامتر دومی که به abi.decode داده می‌شود، تعیین می‌کند که داده ورودی چگونه باید رمزگشایی شود. اگر نوع داده یا ساختار آرگومان ها اشتباه تعریف شود، نتیجه یا اشتباه خواهد بود یا اجرای قرارداد با خطا متوقف می‌شود (revert).

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

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

پکیج آموزش پیشرفته ASP.NET Core + طراحی فروشگاه اینترنتی
  • انتشار: ۱۴ اردیبهشت ۱۴۰۴

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

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

مشاهده همه

نظرات

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