عبارات و ساختارهای کنترل 

ساخت وبلاگ

بیشتر ساختارهای کنترل شناخته شده از زبانهای بریس فرفری در استحکام موجود است:

وجود دارد: اگر ، در حالی که ، در حالی که ، برای شکستن ، ادامه دادن ، بازگشت ، با معناشناسی معمول شناخته شده از C یا JavaScript.

استحکام همچنین از استفاده از استثناء در قالب امتحان / گرفت ن-استفاده می کند ، اما فقط برای تماس های عملکرد خارجی و تماس های ایجاد قرارداد. خطاها را می توان با استفاده از عبارت REVERT ایجاد کرد.

پرانتزها را نمی توان برای شرط بندی حذف کرد ، اما بریس های فرفری می توانند در اطراف اجسام تک جمله حذف شوند.

توجه داشته باشید که هیچ نوع تبدیل از نوع غیر بولای به انواع بولی وجود ندارد ، همانطور که در C و JavaScript وجود دارد ، بنابراین اگر (1)< . >استحکام معتبر نیست.

تماسهای عملکردی

تماس های عملکرد داخلی

عملکردهای قرارداد فعلی را می توان مستقیماً ("داخلی") نیز به صورت بازگشتی خواند ، همانطور که در این مثال مزخرف مشاهده می شود:

این تماس های عملکردی به پرش های ساده در داخل EVM ترجمه می شوند. این تأثیر دارد که حافظه فعلی پاک نشود ، یعنی انتقال منابع حافظه به توابع داخلی بسیار کارآمد است. فقط توابع همان نمونه قرارداد را می توان داخلی نامید.

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

عملکردهای عملکرد خارجی

توابع را می توان با استفاده از this. g (8) نامید. و C. G (2) ؛نماد ، جایی که C یک نمونه قرارداد است و G تابعی است که متعلق به C است. فراخوانی عملکرد G از طریق هر دو روش باعث می شود که آن را "خارجی" خوانده شود ، با استفاده از یک تماس پیام و نه مستقیم از طریق پرش. لطفاً توجه داشته باشید که تماس های عملکردی با این کار در سازنده قابل استفاده نیست ، زیرا هنوز قرارداد واقعی ایجاد نشده است.

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

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

هنگام فراخوانی توابع سایر قراردادها ، می توانید میزان WEI یا گاز ارسال شده با تماس با گزینه های ویژه را مشخص کنید. توجه داشته باشید که مشخص کردن مقادیر گاز به صراحت ناامید شده است ، زیرا هزینه های گاز Opcodes می تواند در آینده تغییر کند. هر WEI که به قرارداد ارسال می کنید به کل مانده آن قرارداد اضافه می شود:

شما باید از اصلاح کننده قابل پرداخت با عملکرد اطلاعات استفاده کنید زیرا در غیر این صورت ، گزینه ارزش در دسترس نخواهد بود.

مراقب باشید که feed. info فقط به صورت محلی مقدار و مقدار گاز ارسال شده با فراخوانی تابع را تنظیم می کند و پرانتزهای انتهایی تماس واقعی را انجام می دهند. بنابراین feed. info تابع را فراخوانی نمی کند و مقدار و تنظیمات گاز از بین می رود، فقط feed. info () فراخوانی تابع را انجام می دهد.

با توجه به این واقعیت که EVM فراخوانی به یک قرارداد غیر موجود را همیشه موفق می‌داند، Solidity از کد opcodesize استفاده می‌کند تا بررسی کند قراردادی که قرار است فراخوانی شود واقعاً وجود دارد (دارای کد است) و در صورت وجود یک استثنا ایجاد می‌کند. نهدر صورتی که داده های برگشتی پس از تماس رمزگشایی شوند و بنابراین رمزگشای ABI موردی از یک قرارداد غیرموجود را تشخیص دهد، از این بررسی صرفنظر می شود.

توجه داشته باشید که این بررسی در مورد تماس‌های سطح پایین که بر روی آدرس‌ها به جای نمونه‌های قراردادی کار می‌کنند، انجام نمی‌شود.

هنگام استفاده از فراخوانی های سطح بالا برای قراردادهای از پیش کامپایل شده مراقب باشید، زیرا کامپایلر طبق منطق بالا آنها را غیر موجود می داند، حتی اگر آنها کد را اجرا کنند و می توانند داده ها را برگردانند.

فراخوانی توابع نیز در صورتی که قرارداد فراخوانی شده خود استثنایی ایجاد کند یا از گاز خارج شود، باعث ایجاد استثنا می شود.

هر گونه تعامل با قرارداد دیگری خطر بالقوه ای را به همراه دارد، به خصوص اگر کد منبع قرارداد از قبل مشخص نباشد. قرارداد فعلی کنترل را به قرارداد نامیده شده واگذار می کند و ممکن است تقریباً هر کاری انجام دهد. حتی اگر قرارداد فراخوانده شده از یک قرارداد مادر شناخته شده ارث می برد، قرارداد ارث فقط نیاز به داشتن یک رابط صحیح دارد. اما اجرای قرارداد می تواند کاملاً خودسرانه باشد و در نتیجه خطر ایجاد کند. علاوه بر این، در صورتی که قبل از بازگشت اولین تماس، قراردادهای دیگر سیستم شما را فراخوانی کند یا حتی به قرارداد تماس بازگردد، آماده باشید. این بدان معناست که قرارداد فراخوانی شده می تواند متغیرهای حالت قرارداد فراخوان را از طریق توابع خود تغییر دهد. توابع خود را به گونه ای بنویسید که برای مثال، فراخوانی توابع خارجی پس از هر تغییری در متغیرهای حالت در قرارداد شما اتفاق بیفتد تا قرارداد شما در برابر سوء استفاده مجدد آسیب پذیر نباشد.

قبل از Solidity 0. 6. 2، روش توصیه شده برای تعیین مقدار و گاز استفاده از f. value(x). gas(g)() بود. این در Solidity 0. 6. 2 منسوخ شده بود و از Solidity 0. 7. 0 دیگر امکان پذیر نیست.

فراخوانی تابع با پارامترهای نامگذاری شده

آرگومان‌های فراخوانی تابع را می‌توان با نام، به هر ترتیبی، در صورتی که داخل آن قرار داده شوند، ارائه کرد< >همانطور که در مثال زیر مشاهده می شود. لیست آرگومان باید با نام با لیست پارامترهای اعلامیه عملکرد مطابقت داشته باشد ، اما می تواند به ترتیب دلخواه باشد.

نام های حذف شده در تعاریف عملکرد

نام پارامترها و مقادیر بازگشت در اعلامیه عملکرد را می توان حذف کرد. این موارد با نام های حذف شده هنوز در پشته حضور خواهند داشت ، اما با نام آنها قابل دسترسی نیست. یک نام مقدار بازگشت حذف شده هنوز هم می تواند با استفاده از بیانیه بازگشت ، یک مقدار را به تماس گیرنده برگرداند.

ایجاد قراردادها از طریق جدید

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

همانطور که در مثال مشاهده می شود ، امکان ارسال اتر ضمن ایجاد نمونه ای از D با استفاده از گزینه Value امکان پذیر است ، اما محدود کردن میزان گاز امکان پذیر نیست. در صورت عدم موفقیت این خلقت (به دلیل خارج از پشته ، تعادل کافی یا مشکلات دیگر) ، یک استثناء پرتاب می شود.

ایجاد قرارداد نمکی / ایجاد 2

هنگام ایجاد قرارداد ، آدرس قرارداد از آدرس قرارداد ایجاد و پیشخوان محاسبه می شود که با ایجاد هر قرارداد افزایش می یابد.

اگر گزینه نمک (مقدار بایت 32) را مشخص کنید ، ایجاد قرارداد از مکانیسم متفاوتی برای ارائه آدرس قرارداد جدید استفاده می کند:

این آدرس را از آدرس قرارداد ایجاد ، مقدار نمک داده شده ، بایت (ایجاد) کد قرارداد ایجاد شده و آرگومان های سازنده محاسبه می کند.

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

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

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

ترتیب ارزیابی عبارات

ترتیب ارزیابی عبارات مشخص نشده است (به طور رسمی تر ، نظمی که فرزندان یک گره در درخت بیان ارزیابی می شوند مشخص نشده است ، اما البته آنها قبل از خود گره ارزیابی می شوند). فقط تضمین شده است که اظهارات به ترتیب اجرا می شوند و اتصال کوتاه برای عبارات بولی انجام می شود.

تکلیف

تکالیف تخریب و بازگشت مقادیر متعدد

استحکام داخلی به انواع Tuple اجازه می دهد ، یعنی لیستی از اشیاء با انواع بالقوه متفاوت که تعداد آنها در زمان کامپایل ثابت است. از این Tuples می توان برای بازگشت مقادیر همزمان به طور همزمان استفاده کرد. این موارد می توانند یا به متغیرهای تازه اعلام شده یا به متغیرهای از قبل موجود (یا به طور کلی lvalues) اختصاص داده شوند.

توپل ها از نظر استحکام انواع مناسبی نیستند ، فقط می توان از آنها برای تشکیل گروه بندی های نحوی عبارات استفاده کرد.

نمی توان اعلامیه های متغیر و تکالیف غیر دکوراسیون را مخلوط کرد ، یعنی موارد زیر معتبر نیست: (x ، uint y) = (1 ، 2) ؛

قبل از نسخه 0. 5. 0 می توان به Tuples با اندازه کوچکتر اختصاص داد ، یا در سمت چپ یا سمت راست (که همیشه خالی بود) پر شود. این اکنون مجاز نیست ، بنابراین هر دو طرف باید همان تعداد اجزای را داشته باشند.

در هنگام اختصاص به متغیرهای متعدد به طور همزمان هنگام درگیر شدن انواع مرجع ، مراقب باشید ، زیرا می تواند به رفتار کپی غیر منتظره منجر شود.

عوارض برای آرایه ها و ساختارها

معناشناسی تکالیف برای انواع غیر ارزش مانند آرایه ها و ساختارها از جمله بایت و رشته پیچیده تر است ، برای جزئیات بیشتر به مکان داده ها و رفتار تکالیف مراجعه کنید.

در مثال زیر فراخوان G (x) هیچ تاثیری در X ندارد زیرا یک نسخه مستقل از مقدار ذخیره سازی در حافظه ایجاد می کند. با این حال ، H (x) با موفقیت x را اصلاح می کند زیرا فقط یک مرجع و نه یک نسخه منتقل می شود.

scoping و اعلامیه ها

متغیری که اعلام شده است ، یک مقدار پیش فرض اولیه دارد که بازنمایی بایت همه صفرها است."مقادیر پیش فرض" متغیرها "حالت صفر" معمولی از هر نوع است. به عنوان مثال ، مقدار پیش فرض برای یک بول نادرست است. مقدار پیش فرض برای انواع UINT یا INT 0 است. برای آرایه های اندازه گیری آماری و بایت 1 به بایت 32 ، هر عنصر جداگانه به مقدار پیش فرض متناسب با نوع خود تنظیم می شود. برای آرایه های اندازه گیری پویا ، بایت و رشته ، مقدار پیش فرض یک آرایه یا رشته خالی است. برای نوع enum ، مقدار پیش فرض اولین عضو آن است.

Scoping in Stymition از قوانین گسترده Scoping C99 (و بسیاری از زبان های دیگر) پیروی می کند: متغیرها از نقطه درست پس از اعلامیه آنها تا پایان کوچکترین قابل مشاهده هستند< >-بول که حاوی اعلامیه است. به عنوان یک استثناء از این قاعده ، متغیرهای اعلام شده در قسمت اولیه سازی یک حلقه فقط تا پایان حلقه قابل مشاهده هستند.

متغیرهایی که مانند پارامتر هستند (پارامترهای عملکرد ، پارامترهای اصلاح کننده ، پارامترهای صید ، ...) در داخل بلوک کد قابل مشاهده هستند - بدنه عملکرد/اصلاح کننده برای یک پارامتر عملکرد و اصلاح کننده و بلوک Catch برای یک پارامتر صید.

متغیرها و سایر موارد اعلام شده در خارج از یک بلوک کد ، به عنوان مثال توابع ، قراردادها ، انواع تعریف شده توسط کاربر و غیره ، حتی قبل از اعلام آنها قابل مشاهده است. این بدان معنی است که شما می توانید قبل از اعلام آنها از متغیرهای حالت استفاده کنید و عملکردهای تماس را به صورت بازگشتی انجام دهید.

به عنوان یک نتیجه ، مثالهای زیر بدون هشدارها کامپایل می شوند ، زیرا این دو متغیر دارای یک نام یکسان هستند اما دامنه ها را از هم جدا می کنند.

به عنوان نمونه خاصی از قوانین Scoping C99 ، توجه داشته باشید که در ادامه ، اولین تکلیف به X در واقع بیرونی و نه متغیر داخلی را اختصاص می دهد. در هر صورت ، هشدار در مورد سایه بیرونی سایه دار دریافت خواهید کرد.

قبل از نسخه 0. 5. 0 استحکام همان قوانین scoping را به عنوان JavaScript دنبال می کند ، یعنی متغیری که در هر نقطه در یک تابع اعلام شده است ، صرف نظر از جایی که اعلام شده است ، برای کل عملکرد محدود خواهد بود. مثال زیر یک قطعه کد را نشان می دهد که برای کامپایل استفاده می شود اما منجر به خطایی می شود از نسخه 0. 5. 0.

حسابی بررسی شده یا بررسی نشده

سرریز یا زیر آب وضعیتی است که مقدار حاصل از یک عملیات حسابی ، هنگامی که بر روی یک عدد صحیح بدون محدودیت اجرا می شود ، خارج از محدوده نوع نتیجه قرار می گیرد.

قبل از استحکام 0. 8. 0 ، عملیات حسابی همیشه در صورت عدم وجود یا سرریز منجر به استفاده گسترده از کتابخانه هایی می شود که چک های اضافی را ارائه می دهند.

از آنجا که استحکام 0. 8. 0 ، تمام عملیات حسابی به طور پیش فرض بر روی بیش از حد و زیر آب برمی گردند ، بنابراین استفاده از این کتابخانه ها غیر ضروری است.

برای به دست آوردن رفتار قبلی ، می توان از یک بلوک بدون بررسی استفاده کرد:

تماس با F (2 ، 3) 2 ** 256-1 باز می گردد ، در حالی که G (2 ، 3) ادعای ناکام را ایجاد می کند.

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

این تنظیم فقط بر جمله هایی که به صورت نحوی در داخل بلوک قرار دارند تأثیر می گذارد. توابع فراخوانی شده از درون یک بلوک کنترل نشده ، خاصیت را به ارث نمی برند.

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

اپراتورهای زیر باعث ایجاد ادعای ناکامی در سرریز یا زیر جریان می شوند و در صورت استفاده در داخل یک بلوک بدون بررسی ، بدون خطایی بسته می شوند:

با استفاده از بلوک بدون چک ، نمی توان چک را برای تقسیم توسط صفر یا ماژول توسط صفر غیرفعال کرد.

Bitwise operators do not perform overflow or underflow checks. This is particularly visible when using bitwise shifts ( > , >=) به جای تقسیم عدد صحیح و ضرب توسط یک قدرت 2

عبارت دوم در int x = نوع (int) . min ؛-ایکس؛منجر به سرریز می شود زیرا دامنه منفی می تواند یک مقدار بیشتر از دامنه مثبت داشته باشد.

تبدیل های صریح همیشه کوتاه می شوند و هرگز به استثنای تبدیل از یک عدد صحیح به یک نوع enum ، ادعای ناکام را ایجاد نمی کنند.

رسیدگی به خطا: ادعا کنید ، نیاز ، برگردانید و استثنائات

استحکام از استثنائات اصلاح شده در حالت برای رسیدگی به خطاها استفاده می کند. چنین استثنائی تمام تغییراتی را که در تماس فعلی (و همه فراخوان های آن) به دولت ایجاد شده است ، خنثی می کند و خطایی را برای تماس گیرنده پرچم می گذارد.

هنگامی که استثنائات در یک فراخوان اتفاق می افتد ، آنها "حباب می شوند" (یعنی استثنائات تجدید نظر می شوند) به طور خودکار مگر اینکه در بیانیه آزمایشی/گرفتن گرفتار شوند. استثنائات این قانون ارسال شده است و توابع سطح پایین ، Delegatecall و StaticCall تماس می گیرند: آنها به عنوان اولین مقدار بازگشت خود در صورت وجود استثنا به جای "حباب کردن" ، به عنوان اولین مقدار بازگشت خود باز می گردند.

توابع سطح پایین تماس ، Delegatecall و StaticCall را به عنوان اولین مقدار بازده خود در صورت عدم وجود موجود ، به عنوان بخشی از طراحی EVM ، به عنوان اولین مقدار بازگشت خود باز می گردند. وجود حساب باید در صورت لزوم قبل از تماس بررسی شود.

استثنائات می توانند حاوی داده های خطا باشند که به صورت نمونه خطا به تماس گیرنده منتقل می شوند. خطای خطای داخلی (رشته) و وحشت (UINT256) توسط توابع ویژه استفاده می شود ، همانطور که در زیر توضیح داده شده است. خطا برای شرایط خطای "منظم" در حالی که از وحشت برای خطاهایی استفاده می شود که نباید در کد بدون اشکال وجود داشته باشد ، استفاده می شود.

وحشت از طریق ادعا و خطا از طریق نیاز

توابع راحتی ادعا می کنند و می توانند برای بررسی شرایط و در صورت عدم رعایت شرایط استفاده شود.

عملکرد Assert خطای وحشت نوع (UINT256) را ایجاد می کند. همان خطا توسط کامپایلر در موقعیت های خاص همانطور که در زیر ذکر شده است ایجاد می شود.

ادعا فقط باید برای آزمایش خطاهای داخلی و بررسی متغیرها استفاده شود. کد به درستی با عملکرد هرگز نباید وحشت ایجاد کند ، حتی در ورودی خارجی نامعتبر. اگر این اتفاق بیفتد ، یک اشکال در قرارداد شما وجود دارد که باید آن را برطرف کنید. ابزارهای تجزیه و تحلیل زبان می توانند قرارداد شما را برای شناسایی شرایط و تماس های عملکردی که باعث وحشت می شود ، ارزیابی کنند.

یک استثناء وحشت در شرایط زیر ایجاد می شود. کد خطای ارائه شده با داده های خطا نشان دهنده نوع وحشت است.

0x00: مورد استفاده برای کامپایلر عمومی درج شده است.

0x01: اگر با استدلال تماس بگیرید که به نادرست ارزیابی می شود.

0x11: اگر یک عملیات حسابی منجر به جریان یا سرریز خارج از یک کنترل نشده شود< . >مسدود کردن.

0x12 ؛اگر شما را به صفر تقسیم کنید یا ماژول را تقسیم کنید (به عنوان مثال 5 /0 یا 23 ٪ 0).

0x21: اگر مقداری را که خیلی بزرگ یا منفی است به یک نوع enum تبدیل کنید.

0x22: اگر به یک آرایه بایت ذخیره شده دسترسی پیدا کنید که به اشتباه رمزگذاری شده باشد.

0x31: اگر با یک آرایه خالی . pop () تماس می گیرید.

0x32: If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x. l طول یا من< 0 ).

0x41: اگر حافظه زیادی را اختصاص می دهید یا آرایه ای را ایجاد می کنید که خیلی بزرگ باشد.

0x51: اگر متغیر صفر از نوع عملکرد داخلی را صدا می کنید.

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

در حال حاضر استفاده از خطاهای سفارشی در ترکیب با نیاز امکان پذیر نیست. لطفاً از (! شرط) استفاده کنید. بجای.

یک خطای (رشته) استثنا (یا یک استثناء بدون داده) توسط کامپایلر در شرایط زیر ایجاد می شود:

فراخوانی نیاز (x) در جایی که x به کاذب ارزیابی می کند.

اگر از بازگشت () یا بازگشت ("توضیحات") استفاده می کنید.

اگر یک تماس عملکردی خارجی را انجام می دهید که یک قرارداد را هدف قرار می دهد که حاوی هیچ کد نیست.

اگر قرارداد شما اتر را از طریق یک تابع عمومی بدون اصلاح کننده قابل پرداخت (شامل سازنده و تابع بازگشتی) دریافت می کند.

اگر قرارداد شما اتر را از طریق تابع دریافت کننده عمومی دریافت کند.

برای موارد زیر، داده های خطا از تماس خارجی (در صورت ارائه) فوروارد می شود. این بدان معنی است که می تواند باعث خطا یا وحشت (یا هر چیز دیگری شود):

اگر یک . transfer () ناموفق باشد.

اگر تابعی را از طریق تماس پیامی فراخوانی می‌کنید اما به درستی تمام نمی‌شود (به عنوان مثال، بنزین تمام می‌شود، عملکرد منطبقی ندارد، یا خود استثنا ایجاد می‌کند)، به جز زمانی که یک عملیات سطح پایین تماس، ارسال، انتقال تماس، کد تماس یاstaticcall استفاده می شود. عملیات سطح پایین هرگز استثناء ایجاد نمی کند، اما با برگرداندن false، شکست را نشان می دهد.

اگر قراردادی را با استفاده از کلمه کلیدی جدید ایجاد می کنید اما ایجاد قرارداد به درستی تمام نمی شود.

شما می توانید به صورت اختیاری یک رشته پیام برای درخواست ارائه دهید، اما نه برای اظهار نظر.

اگر آرگومان رشته‌ای برای نیاز ارائه نکنید، با داده‌های خطای خالی، حتی شامل انتخابگر خطا، برمی‌گردد.

مثال زیر نشان می‌دهد که چگونه می‌توانید از نیاز برای بررسی شرایط ورودی‌ها و تأیید برای بررسی خطاهای داخلی استفاده کنید.

در داخل، Solidity یک عملیات برگرداندن را انجام می دهد (دستورالعمل 0xfd). این باعث می شود EVM تمام تغییرات ایجاد شده را به حالت برگرداند. دلیل برگرداندن این است که هیچ راه مطمئنی برای ادامه اجرا وجود ندارد، زیرا اثر مورد انتظار رخ نداده است. از آنجایی که می‌خواهیم اتمی بودن تراکنش‌ها را حفظ کنیم، مطمئن‌ترین اقدام این است که همه تغییرات را برگردانیم و کل تراکنش (یا حداقل فراخوانی) را بدون تأثیر بگذاریم.

در هر دو مورد، تماس‌گیرنده می‌تواند با استفاده از try/catch به چنین خطاهایی واکنش نشان دهد، اما تغییرات در تماس گیرنده همیشه برگردانده می‌شوند.

استثناهای هراس برای استفاده از کد عملیات نامعتبر قبل از Solidity 0. 8. 0 استفاده می‌شد که تمام گاز موجود برای تماس را مصرف می‌کرد. استثناهایی که استفاده از آنها نیاز به مصرف تمام گاز تا قبل از انتشار متروپلیس دارد.

برگرداندن 

بازگشت مستقیم را می توان با استفاده از دستور revert و تابع revert راه اندازی کرد.

دستور revert یک خطای سفارشی را به عنوان آرگومان مستقیم بدون پرانتز می گیرد:

برگرداندن CustomError(arg1, arg2);

به دلایل سازگاری با عقب، تابع revert() نیز وجود دارد که از پرانتز استفاده می کند و یک رشته را می پذیرد:

داده‌های خطا به تماس‌گیرنده بازگردانده می‌شوند و می‌توانند در آنجا ضبط شوند. استفاده از revert() باعث بازگشت بدون هیچ داده خطایی می شود در حالی که revert("description") یک خطای Error(string) ایجاد می کند.

استفاده از یک نمونه خطای سفارشی معمولاً بسیار ارزان تر از توضیحات رشته خواهد بود ، زیرا می توانید از نام خطا برای توصیف آن استفاده کنید ، که فقط در چهار بایت رمزگذاری شده است. توضیحات طولانی تری را می توان از طریق NATSPEC تهیه کرد که هیچ هزینه ای را متحمل نمی شود.

مثال زیر نحوه استفاده از یک رشته خطا و یک نمونه خطای سفارشی همراه با بازگشت و معادل آن را نشان می دهد:

دو روش اگر (! شرط) برگردانید (.) ؛و نیاز (شرط ،.) ؛معادل هستند تا زمانی که آرگومان برای بازگشت و نیاز به عوارض جانبی نداشته باشد ، به عنوان مثال اگر آنها فقط رشته هستند.

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

رشته ارائه شده به عنوان یک تماس با خطای عملکرد (رشته) رمزگذاری شده است. در مثال بالا ، برگردید ("اتر کافی ارائه نشده است.") ؛hexadecimal زیر را به عنوان داده های بازگشت خطا برمی گرداند:

پیام ارائه شده را می توان با استفاده از تماس گیرنده با استفاده از Try / Catch همانطور که در زیر آمده است ، بازیابی کرد.

قبلاً یک کلمه کلیدی به نام پرتاب با همان معنایی به عنوان بازگشت () وجود داشت که در نسخه 0. 4. 13 مستهلک شد و در نسخه 0. 5. 0 حذف شد.

امتحان کنید / گرفتن

خرابی در یک تماس خارجی می تواند با استفاده از بیانیه Try/Catch ، به شرح زیر گرفتار شود:

کلمه کلیدی TRY باید با عبارتی که نشان دهنده یک تماس عملکرد خارجی یا ایجاد قرارداد است (نام جدید قرارداد ()) دنبال شود. خطاهای موجود در بیان گرفتار نشده اند (به عنوان مثال اگر این یک عبارت پیچیده باشد که شامل تماس های عملکرد داخلی نیز می شود) ، فقط یک بازگشت در داخل تماس خارجی اتفاق می افتد. قسمت بازگشت (که اختیاری است) که در زیر اعلام می کند متغیرهای برگشتی را مطابق با انواع برگشتی توسط تماس خارجی اعلام می کند. در صورت عدم خطایی ، این متغیرها اختصاص داده می شوند و اجرای قرارداد در اولین بلوک موفقیت ادامه می یابد. در صورت رسیدن به پایان بلوک موفقیت ، اجرای پس از بلوک های صید ادامه می یابد.

استحکام بسته به نوع خطا از انواع مختلفی از بلوک های صید پشتیبانی می کند:

خطای گرفتن (دلیل حافظه رشته)< . >: اگر این خطا در اثر بازگشت ("مجدداً") یا نیاز به (نادرست ، "مجدداً") (یا خطای داخلی که باعث چنین استثنائی می شود) این بند صید اجرا شود.

Catch Panic (Uint ErrorCode)< . >: اگر خطا در اثر وحشت ایجاد شده باشد ، یعنی با یک ادعا ناکامی ، تقسیم صفر ، دسترسی به آرایه نامعتبر ، سرریز حسابی و دیگران ، این بند صید اجرا می شود.

گرفتن (بایت حافظه LowLevelData)< . >: اگر امضای خطا با هیچ بند دیگری مطابقت نداشته باشد ، این بند اجرا می شود ، در صورتی که هنگام رمزگشایی پیام خطا خطایی وجود داشته باشد ، یا در صورت عدم ارائه داده های خطایی ، این استثنا ارائه نشده است. متغیر اعلام شده دسترسی به داده های خطای سطح پایین در این حالت را فراهم می کند.

گرفتن< . >: اگر به داده های خطا علاقه ندارید ، فقط می توانید از Catch استفاده کنید< . >(حتی به عنوان تنها بند Catch) به جای بند قبلی.

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

برای گرفتن همه موارد خطا ، شما باید حداقل بند را داشته باشید< . >یا بند گرفتن (حافظه بایتز LowLevelData)< . >.

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

اگر خطایی در هنگام رمزگشایی داده های برگشتی در داخل یک آزمایش/بیان اتفاق بیفتد ، این امر باعث ایجاد استثناء در قرارداد در حال حاضر در حال اجرا می شود و به همین دلیل ، در بند گرفتن گرفتار نمی شود. اگر در هنگام رمزگشایی خطای گرفتن (دلیل حافظه رشته) خطایی وجود داشته باشد و یک بند صید سطح پایین وجود داشته باشد ، این خطا در آنجا گرفتار می شود.

اگر اعدام به یک بلوک صید برسد ، اثرات تغییر دهنده تماس خارجی برگردانده شده است. اگر اعدام به بلوک موفقیت برسد ، اثرات بازگردانده نمی شوند. اگر تأثیرات برگردانده شده باشد ، اجرای آن یا در یک بلوک صید ادامه می یابد یا اجرای عبارت Try/Catch خود باز می گردد (برای مثال به دلیل خرابی های رمزگشایی همانطور که در بالا ذکر شد یا به دلیل عدم ارائه بند صید پایین).

دلیل تماس ناموفق می تواند چند برابر باشد. فرض نکنید که پیام خطا مستقیماً از قرارداد نامیده می شود: ممکن است خطا در زنجیره تماس عمیق تر اتفاق بیفتد و قرارداد نامیده شده فقط آن را ارسال کرده است. همچنین ، این می تواند به دلیل وضعیت خارج از گاز باشد و نه یک خطای عمدی: تماس گیرنده همیشه در یک تماس حداقل 1/64 گاز را حفظ می کند و بنابراین حتی اگر قرارداد نامیده شده از گاز خارج شود ، تماس گیرندههنوز مقداری بنزین باقی مانده است.

آنالیز فاندامنتال...
ما را در سایت آنالیز فاندامنتال دنبال می کنید

برچسب : نویسنده : اسماعیل داورفر بازدید : 51 تاريخ : پنجشنبه 3 فروردين 1402 ساعت: 18:42