برنامه نویسی بلاکچین

آموزش زبان برنامه نویسی سالیدیتی solidity – فصل اول: انواع متغیرها (بخش سوم)

آموزش زبان برنامه نویسی سالیدیتی solidity ، در این بخش با داده های از نوع آدرس یاAddress آشنا می شویم .


آدرس یاAddress

نوع آدرس به دو قسمت تقسیم می شوند، که تا حد زیادی یکسان هستند:

  • آدرس یا address: یک مقدار 20 بایت (اندازه آدرس اتریوم) است.
  • آدرس قابل پرداخت یا address payable: مانند همان آدرس  است  اما  دارای عضو اضافی برای  انتقال و ارسال می باشد.

تمایز آنها در این است که آدرس قابل پرداخت یا address payable ، آدرسی است که می توانید اتر را برای آن ارسال کنید ، در حالی که  با یک آدرس ساده نمی توان اتر ارسال کرد.


انواع تبدیل:

تبدیل ضمنی از  address payable به  address  مجاز است ، در حالی که تبدیل ازaddress به address payableباید صریح و از طریق address payableباشد.

Address literals  می توانند به طور ضمنی به address payable  تبدیل شوند.

تبدیل صریح و روشن از address به  عدد صحیح ، integer literals ، bytes20و انواع قراردادها  مجاز است البته با  احتساب  نکته زیر:

نتیجه تبدیل ddress ،  از نوع آدرس address payable است.

اگر x از نوع بایت عدد صحیح یا ثابت باشد ، یک literal یا قراردادی با عملکرد برگشت پذیر یا قابل پرداخت است. اگر x یک قرارداد است  بدون عملکرد دریافتی یا پرداخت قابل پرداخت ، آنگاه address(x) از نوع address خواهد بود. در توابع خارجی امضاها، address هم برای address و هم برای نوع address payable استفاده می شود.

فقط عبارات نوع address را می توان از طریق address payable ، به نوع  address payable  تبدیل کرد (<آدرس]).

توجه: شاید خیلی خوب باشد که  تمایز آدرس و آدرس  اهمیتی ندهید و فقط  از address استفاده کنید .به عنوان مثال ، اگر از الگوی برداشت استفاده می کنید ، می توانید (و باید) آدرس خود را به عنوان address ذخیره کند ، زیرا شما از عملکرد انتقال  یا transfer در msg.sender استفاده می کنید ، که address payable است .


اپراتورها یا Operators

<=، <، ==،! =،> = و>

هشدار: اگر از متغیری با اندازه بایتهای  بزرگتر برای تبدیل به  نوع  address ، به عنوان مثال بایت32  استفاده می کنید  ،در این صورت address  کوتاه شده است. برای کاهش ابهام در تبدیل  در نسخه 0.4.24 و بالاتر،  کامپایلرشما را مجبور می کند تا تبدیل کوتاه  صریح انجام دهید . برای مثال مقدار 32 بایت را در نظر بگیرید

0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEFFFFCCCC.

می توانید از آدرس address(uint160(bytes20(b))) استفاده کنید ، که نتیجه آن به صورت زیر است:

0x111122223333444455556666777788889999aAaa

یا می توانید از address(uint160(uint256(b)))  استفاده کنید  که منجر به نتیجه زیر می شود:

 0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc.

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

در صورت وجود عملکرد دریافتی یا پرداختی قابل پرداخت ، برای پرداخت هزینه پرداخت.


اعضای آدرس

آموزش زبان برنامه نویسی solidity

تعادل یا balance و انتقال یا transfer

می توان برای جستجوی توازن  یک address  از ویژگی  تعادل یا balance و برای  ارسال اتر (در واحدهای وی یا wei) به  payable address  از تابع  انتقال استفاده کرد :

address payable x = address(0x123);

address myAddress = address(this);

if (x.balance < 10 && myAddress.balance >= 10)  x.transfer(10);

تابع انتقال یا transfer  با شکست روبرو می شود اگر توازن قرارداد فعلی به اندازه کافی بزرگ نباشد یا انتقال در  اتر  توسط دریافت کننده آن برگشت بخورد. در این صورت تابع انتقال یا transfer   انجام نمی پذیرد.

توجه: اگر x یک آدرس قرارداد باشد، کد آن (به طور خاص: تابع گرفتن اتر  ( Receive Ether Function  ) مربوط به آن، در صورت وجود ، یا در غیر این صورت تابع  بازگشت (Fallback Function)آن، در صورت وجود)  همراه با صدا کردن  انتقال  (transfer) اجرا خواهد شد (این ویژگی مربوط به  EVM  است و غیر قابل اجتناب است) . اگر آن اجرا  خارج  gas انجام شود یا به هر شیوه ای با شکست روبرو شود، انتقال اتر برگشت داده می شود وقرارداد مربوطه  با  یک استثنا متوقف می شود.


ارسال یا send

ارسال ، همتای سطح پایین transfer است. در صورت عدم موفقیت ، قراراداد فعلی با یک استثنا  متوقف نمی شود ، اما ارسال یا send ، falseرا برمی گرداند.

بیشتر بخوانید:  آموزش زبان برنامه نویسی solidity - فصل اول:انواع متغیرها (بخش دوم)

هشدار: در استفاده از ارسال  (send)خطرات زیادی وجود دارد: اگر عمق پشته صدا کردن روی  1024 باشد انتقال با شکست روبرو می شود (این اتفاق ممکن است همیشه توسط گیرنده تحمیل شود) و اگر گیرنده از gas خارج شود نیز از کار می افتد. بنابراین  برای امنیت بیشتر انتقال، همیشه مقدار بازگشتی  ارسال (send)   را چک کنید ، استفاده از انتقال (transfer)  نیز مهم است و یا حتی بهتر  است که  از الگویی استفاده کنید که در آن گیرنده پول را برداشت می کند.


callو delegatecall و  staticcall

به منظور رابطه  با قراردادهایی که به ABI پایبند نیستند ، یا کنترل مستقیم بیشتری روی رمزگذاری اعمال می شود ،توابع call، delegatecall و staticcall ارائه شده است. همه آنها یک بایت حافظه می گیرند و شرط موفقیت (به عنوان یک bool) و داده ها (حافظه بایت) را برمی گردانند.

توابع  abi.encode ، abi.encodePacked ، abi.encodeWithSelector و abi.encodeWithSignature می توانند برای رمزگذاری داده های ساخت یافته استفاده می شود.

مثال:

bytes memory payload = abi.encodeWithSignature(“register(string)”, “MyName”);

(bool success, bytes memory returnData) = address(nameReg).call(payload);

require(success);

هشدار: همه این عملکردها توابع سطح پایین هستند و باید با احتیاط مورد استفاده قرار گیرند. به طور خاص ، هر قرارداد ناشناخته  ای ممکن است مخرب باشد . اگر با آن تماس بگیرید ،  ممکن است کنترل آن قرارداد  را  گرفته  و آنکه می تواند به نوبه خود را دستکاری کند و به خود شما برگرداند. ، بنابراین هنگام بازگشت تماس ، برای تغییر متغیرهای حالت آماده باشید. روش درست و روتین  برای تعامل با سایر قراردادها این است که یک تابع را با  موضوع قرارداد (x.f()) فراخوانی کنید.

توجه: نسخه های قبلی Solid به این توابع اجازه می داد آرگومان های دلخواه را دریافت کنند و همچنین اولین آرگومان نوع bytes4 را   با شیوه ای متفاوت بگیرند. این موارد در نسخه 0.5.0 برداشته شد.

تنظیم gas عرضه شده با اصلاح کننده gas امکان پذیر است:

address(nameReg).call{gas: 1000000}(abi.encodeWithSignature(“register(string)”, ˓→”MyName”));

به طور مشابه ، مقدار اتر عرضه شده را نیز می توان کنترل کرد:

address(nameReg).call{value: 1 ether}(abi.encodeWithSignature(“register(string)”,˓→”MyName”));

در آخر ، این اصلاح کننده ها می توانند با هم ترکیب شوند. ترتیب آنها مهم نیست:

address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature(˓→”register(string)”, “MyName”));

در یک روش مشابه ، از تابع delegatecall می توان استفاده کرد: تفاوت آن ابن است  که فقط کد آدرسی که  مشخص شده است،استفاده می شود. تمام جنبه های دیگر (ذخیره ، تعادل ، …) از قرارداد فعلی گرفته می شود. هدف استفاده از delegatecall  به کار بردن کدهای كتابخانه ای است كه در قرارداد دیگری ذخیره می شود. کاربر باید اطمینان حاصل کند که نحوه ذخیره سازی  که در هر دو قرار داد  وجود دارد، قراردادها مناسب برای استفاده از delegatecall است.

توجه: قبل از Homestead ، فقط یک نوع محدود  به نام callcode در دسترس بود که دسترسی به  مقادیر اصلی msg.sender و msg.value را فراهم نمی کرد. این تابع در نسخه 0.5.0 حذف شد.

از آنجا که می توان از staticcall byzantium نیز استفاده کرد. این اساساً همان فراخوانی  یا call است اما برمی گردد اگر تابع ،حالت را به هر شکلی تغییر دهد.

هر سه تابع call، delegatecall و staticcall توابع سطح بسیار پایینی هستند و فقط باید به عنوان آخرین راه حل مورد استفاده قرار گیرند

، زیرا امنیت Solidity را به خطر می اندازند.

گزینه gas در هر سه روش موجود است ، در حالی که گزینه ا value برای نوع delegatecall  ساپورت نمی شود.

توجه: بهتر است از تکیه بر کد های سنگین  gas  در کد قرارداد هوشمند خودداری کنید. چه نوع متغیر حالت شما از نوع خواندن (read) یا نوشته شده است(written)  باشد، زیرا این می تواند مشکلات بسیاری داشته باشد. همچنین ، دسترسی به gas ممکن است در آینده تغییر کند.

توجه: کلیه قراردادها می توانند به نوع address تبدیل شوند ، بنابراین  امکان  جستجوی اتوازن قرارداد فعلی با استفاده از این با استفاده از این address وجود دارد.


برای دسترسی بهتر به آموزش زبان برنامه نویسی سالیدیتی solidity از طریق فصل به فصل به لینک های زیر مراجعه کنید.

ممنون از اینکه تا پایان ” آموزش زبان برنامه نویسی سالیدیتی solidity ” همراه ما بودید.

برچسب ها
مشاهده بیشتر

معصومه گودرزی

کارشناس ارشد ریاضی|تکنسین شبکه|مولف کتاب های اموزشی|مدرس دانشگاه های آزاد و علمی کاربردی|پژوهشگر در مورد ارزهای دیجیتال

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا
بستن
بستن