آموزش کدگذاری رابط باینری برنامه در سالیدیتی
قبل از اینکه موضوع بعدی را یاد بگیریم، باید ابتدا یک نکته ظاهراً بیربط را بررسی کنیم که بعداً اهمیتش برایتان روشن میشود.
در این بخش، میخواهیم با مفاهیم زیر آشنا شویم:
-
abi.encode
-
abi.decode
-
abi.encodeWithSignature
برای اینکه ضرورت این مفاهیم را بهتر درک کنید، یک قرارداد هوشمند ساده میسازیم و از طریق منوی «debug» در ریمیکس، یک قطعه اطلاعات خاص را بررسی میکنیم.
1 2 3 4 5 6 7 8 9 |
contract ExampleContract { function meaningOfLifeAndAllExistence() public pure returns (uint256) { return 42; } } |
0x92d62db5
این مقدار چیست؟
این در واقع امضای تابع (Function Signature) مربوط به تابع meaningOfLifeAndAllExistence()
است. در ادامه یاد خواهید گرفت که این مقدار دقیقاً چگونه محاسبه میشود.
هر زمان که شما یک قرارداد هوشمند را “فراخوانی” میکنید، در واقع یک تراکنش اتریومی ارسال میکنید که شامل داده هایی است تا قرارداد هوشمند متوجه شود کدام تابع باید اجرا شود.
بیایید این اطلاعات را از زاویهای دیگر بررسی کنیم.
1 2 3 4 5 6 7 8 9 |
contract ExampleContract { function meaningOfLifeAndAllExistence() public pure returns (bytes memory) { return msg.data; } } |
ما نوع خروجی تابع را به 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
را به دسیمال تبدیل کنید، این موضوع برایتان روشن تر میشود.
اگر یک تابع هیچ آرگومانی نداشته باشد، تنها ارسال همین چهار بایت برای شناسایی و اجرای آن کافی است.
اما اگر تابع یک آرگومان داشته باشد، داده های ارسالی چه شکلی خواهند بود؟
1 2 3 4 5 6 7 8 9 |
contract ExampleContract { function takeOneArg(uint256 x) public pure returns (bytes memory) { // we won't do anything with x return msg.data; } } |
0xf8689fd30000000000000000000000000000000000000000000000000000000000000007
بخش f8689fd3
نشاندهنده این است که باید تابعی به نام takeOneArg
فراخوانی شود، و بخش 07
(که با تعداد زیادی صفر در ابتدا همراه است) یعنی عدد ۷ باید به عنوان آرگومان به تابع ارسال شود.
اگر قرار بود این کار را دستی انجام دهیم، واقعاً گیجکننده و دشوار میشد.
خوشبختانه، نیازی نیست این کار را دستی انجام دهیم.
الان ببینید چطور میتوانیم راحتتر این کار را انجام بدهیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
contract ExampleContract { function getEncoding(uint x) public pure returns (bytes memory) { return abi.encodeWithSignature("takeOneArg()", x); } function takeOneArg(uint256 x) public pure returns (bytes memory) { return msg.data; } } |
لازم نیست فعلاً نگران جزئیات دقیق استاندارد ABI Encoding باشیم؛ در حال حاضر فقط کافیست با نحوه استفاده از آن آشنا شویم.
به مثال زیر توجه کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
contract ExampleContract { function encodingXY(uint x, uint256 y) public pure returns (bytes memory) { return abi.encode(x,y); } function getATuple(bytes memory encoding) public pure returns (uint256, uint256) { (uint256 x, uint256 y) = abi.decode(encoding, (uint256, uint256)); return(x,y); } } |
در این مثال، از abi.encode
و abi.decode
استفاده شده است. بخش withSignature
زمانی استفاده میشود که توابع در کار باشند، اما اینجا ما فقط با داده ها سروکار داریم، نه فراخوانی تابع.
در اینجا، دو متغیر x
و y
توسط abi.encode
به شکل زیر کدگذاری شدهاند:
0x0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000f
اعداد ده دهی به مبنای شانزده (hex) تبدیل شدهاند؛ به همین خاطر عدد ۵ همان “5” باقی مانده و عدد ۱۵ به “f” تبدیل شده است.
اگر از قبل بدانیم که این داده ها یک جفت uint256
هستند، میتوانیم با استفاده از abi.decode
آنها را به درستی به همان جفت عدد برگردانیم.
پارامتر دومی که به abi.decode
داده میشود، تعیین میکند که داده ورودی چگونه باید رمزگشایی شود. اگر نوع داده یا ساختار آرگومان ها اشتباه تعریف شود، نتیجه یا اشتباه خواهد بود یا اجرای قرارداد با خطا متوقف میشود (revert).
راستی! برای دریافت مطالب جدید در کانال تلگرام یا پیج اینستاگرام سورس باران عضو شوید.
- انتشار: ۱۴ اردیبهشت ۱۴۰۴
دسته بندی موضوعات
- آموزش ارز دیجیتال
- آموزش برنامه نویسی
- آموزش متنی برنامه نویسی
- اطلاعیه و سایر مطالب
- پروژه برنامه نویسی
- دوره های تخصصی برنامه نویسی
- رپورتاژ
- فیلم های آموزشی
- ++C
- ADO.NET
- Adobe Flash
- Ajax
- AngularJS
- apache
- ARM
- Asp.Net
- ASP.NET MVC
- AVR
- Bootstrap
- CCNA
- CCNP
- CMD
- CSS
- Dreameaver
- EntityFramework
- HTML
- IOS
- jquery
- Linq
- Mysql
- Oracle
- PHP
- PHPMyAdmin
- Rational Rose
- silver light
- SQL Server
- Stimulsoft Reports
- Telerik
- UML
- VB.NET&VB6
- WPF
- Xml
- آموزش های پروژه محور
- اتوکد
- الگوریتم تقریبی
- امنیت
- اندروید
- اندروید استودیو
- بک ترک
- بیسیک فور اندروید
- پایتون
- جاوا
- جاوا اسکریپت
- جوملا
- دلفی
- دوره آموزش Go
- دوره های رایگان پیشنهادی
- زامارین
- سئو
- ساخت CMS
- سی شارپ
- شبکه و مجازی سازی
- طراحی الگوریتم
- طراحی بازی
- طراحی وب
- فتوشاپ
- فریم ورک codeigniter
- فلاتر
- کانستراکت
- کریستال ریپورت
- لاراول
- معماری کامپیوتر
- مهندسی اینترنت
- هوش مصنوعی
- یونیتی
- کتاب های آموزشی
- Android
- ASP.NET
- AVR
- LINQ
- php
- Workflow
- اچ تی ام ال
- بانک اطلاعاتی
- برنامه نویسی سوکت
- برنامه نویسی موبایل
- پاسکال
- پایان نامه
- پایتون
- جاوا
- جاوا اسکریپت
- جی کوئری
- داده کاوی
- دلفی
- رباتیک
- سئو
- سایر کتاب ها
- سخت افزار
- سی اس اس
- سی پلاس پلاس
- سی شارپ
- طراحی الگوریتم
- فتوشاپ
- مقاله
- مهندسی نرم افزار
- هک و امنیت
- هوش مصنوعی
- ویژوال بیسیک
- نرم افزار و ابزار برنامه نویسی
- وردپرس