Staticcall عملکردی مشابه فراخوانی معمول در اتریوم دارد، با این تفاوت که اگر باعث تغییر در وضعیت (State) شود، تراکنش را برمیگرداند (revert میکند). این نوع فراخوانی اجازه انتقال اتر را نمیدهد. در سطح ماشین مجازی اتریوم (EVM)، این قابلیت به صورت یک دستورالعمل (opcode)، در زبان اسمبلی Yul به شکل یک تابع، و در خود سالیدیتی نیز به عنوان یک تابع داخلی با نام staticcall
قابل استفاده است.
معرفی EIP 214 در سالیدیتی
قابلیت Staticcall برای نخستین بار در سال ۲۰۱۷ با پیشنهاد بهبود EIP 214 و در قالب هاردفورک Byzantium به اتریوم اضافه شد. هدف از این قابلیت، افزایش ایمنی در مواردی است که تنها به خروجی تابع نیاز داریم و نمیخواهیم هیچ تغییری در وضعیت قرارداد اتفاق بیفتد. اگر تابعی که با staticcall فراخوانی شده، عملیاتی انجام دهد که منجر به تغییر وضعیت شود، اجرای آن با شکست مواجه خواهد شد. این تغییرات شامل موارد زیر است:
-
ثبت یک رویداد (Event)
-
ارسال اتر
-
ایجاد یک قرارداد جدید
-
نابود کردن یک قرارداد
-
تغییر مقدار یک متغیر ذخیره شده در حافظه قرارداد (Storage)
اما خواندن مقادیر از حافظه (Storage) مجاز است. همچنین، فراخوانیای که در آن اتر جابهجا نمیشود مجاز است، به شرط آنکه موجب تغییر وضعیت نشود.
توابع View در سالیدیتی
در زبان سالیدیتی، توابعی که به صورت view
تعریف شدهاند و در آنها به قراردادهای خارجی ارجاع داده میشود، بهصورت خودکار با استفاده از staticcall
کامپایل میشوند. این کار باعث میشود از تغییر ناخواسته وضعیت در این توابع جلوگیری شود.
مثال ساده
در ادامه، یک مثال ساده از نحوه استفاده از staticcall ارائه میشود:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
contract ERC20User { IERC20 public token; // rest of the code function myBalance() public view returns (uint256 balance) { balance = token.balanceOf(address(this)); } function myBalanceLowLevelEquivalent() public view returns (uint256 balance) { (bool ok, bytes memory result) = token.staticcall(abi.encodeWithSignature("balanceOf(address)", address(this))); require(ok); balance = abi.decode(result, (uint256)); } } |
اگر balanceOf
باعث تغییر وضعیت شود، اجرای کد متوقف خواهد شد
در صورتی که تابع balanceOf
در یک قرارداد توکن، تغییری در وضعیت بلاک چین ایجاد کند (مثلاً با نوشتن در حافظه یا ارسال رویداد)، استفاده از staticcall
برای فراخوانی آن باعث برگشت تراکنش (revert) خواهد شد.
پارامترهای متا (Meta Arguments)
مقدار گازی که باید به staticcall
منتقل شود، را میتوان به شکل زیر مشخص کرد:
1 |
staticcall{gas: gasAmount}(abiEncodedArguments); |
اما باید توجه داشت که این گاز تحت تأثیر قانون ۶۳/۶۴ تعریف شده در EIP-150 قرار میگیرد. بر اساس این قانون، تنها ۶۳/۶۴ گاز باقیمانده از تراکنش اصلی به فراخوانی داخلی منتقل میشود، تا از مصرف کامل گاز جلوگیری شود.
بردارهای حمله (Attack Vectors)
اگرچه staticcall
از بعضی جهات ایمنتر از call
عادی است، اما این به معنی بینیازی از بررسیهای امنیتی نیست. در ادامه به دو نوع حمله رایج اشاره میکنیم:
حمله انکار سرویس (Denial of Service)
درست است که staticcall
اجازه تغییر وضعیت را نمیدهد، اما همچنان در برابر حملات مبتنی بر سوءاستفاده از گاز (gas griefing) آسیبپذیر است. تصور کنید که تابع balanceOf
در یک توکن ERC20 بهصورت عمدی دارای حلقه بینهایت باشد. در این حالت، حتی اگر فراخوانی برگشت نخورد، قرارداد فراخواننده ممکن است تنها با یکشصتوچهارم گاز باقیمانده مواجه شود، که این میتواند منجر به توقف یا اختلال در ادامه اجرای کد شود.
بازدرونیابی فقطخواندنی (Read-Only Re-entrancy)
نوع دیگری از حمله، بازدرونیابی فقطخواندنی است. در این سناریو، مهاجم با استفاده از وام آنی (flash loan) مقدار داراییها را به صورت موقتی دستکاری میکند. در نتیجه، قراردادهایی که صرفاً با staticcall
مقادیر را بررسی میکنند، ممکن است با مقدارهای نادرست مواجه شده و در معرض حملاتی از نوع دستکاری اوراکل قرار گیرند.
استفاده از Staticcall در اسمبلی Yul
در زبان اسمبلی Yul، ساختار staticcall
به شکل زیر تعریف میشود:
1 |
let ok := staticcall(gas, addressToCall, in, insize, out, outsize) |
out
و outsize
مشخص میکنند که مقدار بازگشتی باید در کدام بخش از حافظه قرار بگیرد. با این حال، معمولاً این دو پارامتر صفر در نظر گرفته میشوند، و به جای آن از دو دستور زیر برای مدیریت انعطافپذیر مقدار بازگشتی استفاده میشود:
1 |
returndatacopy(0, 0, returndatasize()) |
این قابلیتها با EIP 211 معرفی شدند و نیاز به پیشبینی اندازه خروجی قرارداد خارجی را از بین بردند.
همچنین پارامترهای in
و insize
به بخشی از حافظه اشاره دارند که دادههای ABI-Encoded مربوط به فراخوانی قرارداد خارجی در آن قرار دارد.
مقدار ok
نیز نشان میدهد که آیا فراخوانی موفقیتآمیز بوده یا با شکست مواجه شده است. توجه داشته باشید که در صورت revert، خطا bubbled up نمیشود (به سطح بالاتر انتقال نمییابد).
استفاده در قراردادهای از پیش کامپایل شده (Precompiled Contracts)
برای تعامل با قراردادهای از پیش کامپایل شده اتریوم (آدرسهای 0x01 تا 0x09)، استفاده از staticcall
روش صحیح است؛ چرا که هیچکدام از این قراردادها وضعیت را تغییر نمیدهند.
مثال زیر هش SHA256
یک عدد را با استفاده از قرارداد از پیش کامپایل شده آدرس 0x02
محاسبه میکند. توجه داشته باشید که این قرارداد داده را مستقیم هش میکند و نیازی به کدگذاری ABI نیست.
1 2 3 4 5 6 |
function getSha256(uint256 x) public view returns (bytes32 hashOut) { (bool ok, bytes memory result) = address(0x02).staticcall(abi.encode(x)); require(ok); hashOut = abi.decode(result, (bytes32)); } |
راستی! برای دریافت مطالب جدید در کانال تلگرام یا پیج اینستاگرام سورس باران عضو شوید.
- انتشار: ۵ خرداد ۱۴۰۴
دسته بندی موضوعات
- آموزش ارز دیجیتال
- آموزش برنامه نویسی
- آموزش متنی برنامه نویسی
- اطلاعیه و سایر مطالب
- پروژه برنامه نویسی
- دوره های تخصصی برنامه نویسی
- رپورتاژ
- فیلم های آموزشی
- ++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
- اچ تی ام ال
- بانک اطلاعاتی
- برنامه نویسی سوکت
- برنامه نویسی موبایل
- پاسکال
- پایان نامه
- پایتون
- جاوا
- جاوا اسکریپت
- جی کوئری
- داده کاوی
- دلفی
- رباتیک
- سئو
- سایر کتاب ها
- سخت افزار
- سی اس اس
- سی پلاس پلاس
- سی شارپ
- طراحی الگوریتم
- فتوشاپ
- مقاله
- مهندسی نرم افزار
- هک و امنیت
- هوش مصنوعی
- ویژوال بیسیک
- نرم افزار و ابزار برنامه نویسی
- وردپرس