آسیبپذیری بررسینشدن مقدار بازگشتی در فراخوانیها Unchecked Call Return Value ؛ ریسک پنهانی در قراردادهای هوشمند

در توسعه قراردادهای هوشمند، یکی از اشتباهات رایج اما خطرناک، نادیده گرفتن مقدار بازگشتی متدهای فراخوانی سطح پایین مثل call
، delegatecall
و staticcall
است. این اشتباه میتواند زمینهساز حملات امنیتی جدی یا رفتارهای پیشبینینشده در منطق قرارداد باشد.
در بسیاری از موارد، توسعهدهندگان از این متدها برای تعامل با سایر قراردادها یا انتقال وجه استفاده میکنند، اما فراموش میکنند که بررسی کنند آیا این فراخوانی واقعاً موفق بوده یا خیر. اگر چنین فراخوانیای با شکست مواجه شود و مقدار بازگشتی آن بررسی نشود، قرارداد به اجرای خود ادامه میدهد — گویی همهچیز درست پیش رفته است. اینجاست که آسیبپذیری Unchecked Call Return Value رخ میدهد.
چرا بررسی نتیجه فراخوانیهای سطح پایین اهمیت دارد؟
در قراردادهای هوشمند، حتی اگر قرارداد مقصد استثنایی ایجاد کند یا عمداً پاسخ ندهد، فراخوانی سطح پایین همچنان به اجرای برنامه اجازه میدهد ادامه پیدا کند. به عبارت دیگر، مگر اینکه توسعهدهنده خودش بررسی success
را انجام دهد، قرارداد متوجه نمیشود که عملیات شکست خورده است.
تصور کنید قراردادی قصد دارد توکنی به آدرس کاربر ارسال کند. اگر انتقال با استفاده از call
انجام شود و بررسی success
حذف شده باشد، در صورت شکست، کاربر هیچ مبلغی دریافت نمیکند — اما قرارداد همچنان گمان میکند انتقال موفق بوده و به کارش ادامه میدهد. این موضوع میتواند باعث از بین رفتن وجوه یا تغییرات ناخواسته در وضعیت قرارداد شود.
تأثیرات آسیبپذیری Unchecked Call Return Value
نادیده گرفتن نتیجهی فراخوانیهای خارجی میتواند منجر به:
-
اجرای منطق اشتباه در قرارداد
-
باقی ماندن وضعیت نادرست یا نیمهکاره
-
از بین رفتن وجه یا دارایی
-
ایجاد درگاهی برای حملات زنجیرهای یا رفتارهای پیشبینینشده
این آسیبپذیری بهویژه در شرایطی که قرارداد با آدرسهای ورودی تعامل دارد، میتواند بهشدت خطرناک باشد. مهاجم میتواند بهصورت هدفمند باعث شکست یک call
شود تا منطق قرارداد را دور بزند یا وضعیت آن را بهطور نادرست دستکاری کند.
راهکار؛ چگونه از این آسیبپذیری جلوگیری کنیم؟
اگر ناچار به استفاده از call
، delegatecall
یا staticcall
هستید، حتماً موارد زیر را رعایت کنید:
مقدار بازگشتی را بررسی کنید
حتماً خروجی تابع را در قالب زیر بررسی کنید:
solidity
CopyEdit
(bool success, ) = target.call{value: msg.value}(data); require(success, "Call failed");
این بررسی باعث میشود فقط در صورت موفقیت، منطق برنامه ادامه یابد.
اگر ممکن است، از متدهای امنتر استفاده کنید
در بسیاری از موارد، میتوان بهجای call
از متدهای سطح بالاتر مثل transfer
یا send
استفاده کرد که بهطور پیشفرض نتیجه را بررسی میکنند. اگرچه محدودیتهایی دارند، اما در سناریوهای ساده، انتخاب امنتری محسوب میشوند.
با استفاده از codeauditplus ، در کمترین زمان و با هزینه بسیار معقول، میتوانید آسیب پذیری ها را شناسایی و در نتیجه برای بهبود کد قرارداد اقدام متناسب انجام دهید.
جمعبندی
آسیبپذیری Unchecked Call Return Value شاید در ظاهر کوچک بهنظر برسد، اما میتواند باعث خطاهایی شود که تشخیص آنها پس از استقرار قرارداد بسیار دشوار و گاهی غیرممکن است. برای افزایش امنیت و پایداری پروژههای مبتنی بر Web3، باید حتماً در طراحی توابع و مدیریت فراخوانیهای خارجی دقت بیشتری به خرج داد.
امنیت قرارداد از جزئیات شروع میشود — و این یکی از آن جزئیات مهم است.
راهکار ما:
- ثبت درخواست ممیزی
- مشاهده راهنمای چگونگی ثبت درخواست ممیزی در آپارات
- مشاهده راهنمای چگونگی ثبت درخواست ممیزی در یوتیوب
منابع
https://swcregistry.io/docs/SWC-104/