معرفی آسیبپذیریها و حملات رایج در قراردادهای هوشمند
قرارداد هوشمند چیست؟
اتریوم دو نوع حساب رایج دارد: حسابهای با مالکیت خارجی (EOA) و حسابهای قرارداد هوشمند (SCA).
EOA بسیار شبیه به حسابهای مالی الکترونیکی هستند که ما معمولاً برای ذخیره وجوه و تعامل با برنامهها استفاده میکنیم. به عنوان مثال، کاربران از طریق پیپال ارز فیات واریز میکنند و با وبسایتها، فروشگاهها و برنامههای مختلف برای پرداخت تعامل دارند. ماینرهای (دیفای)DeFi معمولاً ارزهای رمزنگاری شده را در EOA خود ذخیره میکنند، با dApp های (دیفای)DeFi تعامل دارند و برای کسب سود وجوه را در dApp ها سپردهگذاری میکنند. با این حال، EOA ویژگیای دارند که حسابهای مالی الکترونیکی ندارند: کاربران باید کنترل خود بر EOA را از طریق مالکیت کلیدهای خصوصی تأیید کنند - اگر کلیدهای شما نباشد، سکههای شما هم نیست.
SCA نیز نوعی حساب هستند که اساساً با بخشی از بایتکد قابل اجرا (که به عنوان قرارداد هوشمند نیز شناخته میشود) مرتبط هستند. قرارداد هوشمند منطق تجاری مختلفی را توصیف میکند و به عنوان بکاند برای dApp ها عمل میکند. با این حال، علیرغم داشتن محدودیتهای بیشتر نسبت به زبانهای توسعه تورینگ کامل سنتی، قراردادهای هوشمند شبه-تورینگ کامل همچنان در برابر حملات متعددی آسیبپذیر بودهاند و ضربات بیشماری به صنعت بلاکچین وارد کردهاند.
حملات رایج قرارداد هوشمند
۱. حمله بازورود
رایجترین و بدنامترین حمله، حمله بازورود است که مسئول انشعاب اتریوم بود که منجر به ایجاد اتریوم کلاسیک شد. در سال ۲۰۱۶، هکرها یک حمله بازورود را بر روی قرارداد (دائو)DAO اجرا کردند و ۳،۶۰۰،۰۰۰ اتر به ارزش بیش از ۱۵۰ میلیون دلار در آن زمان را به سرقت بردند. این حمله که در مراحل اولیه اتریوم رخ داد، اکوسیستم را ویران کرد و اعتماد سرمایهگذاران را از بین برد و در نهایت منجر به یک انشعاب شد.
منطق خاص
در اینجا مثالی آورده شده است تا به شما کمک کند اصل حمله بازورود را بهتر درک کنید. بانک B قبلاً مقداری پول به بانک A قرض داده بود. یک روز، بانک B یک انتقال به بانک A آغاز میکند و درخواست میکند که تمام پول به بانک B بازگردانده شود. مسیر عادی به شرح زیر است:
گام ۱: بانک B درخواست برداشت وجه میکند
گام ۲: بانک A وجوه را به بانک B منتقل میکند
گام ۳: بانک A انتقال موفق به بانک B را تأیید میکند
مرحله 4: بانک A موجودی حساب بانک B را بهروزرسانی میکند.
با این حال، اگر بانک B پس از مرحله 2 حفرهای ایجاد کند و بدون تأیید در مرحله 3 به درخواست تمام پول از بانک A ادامه دهد، موجودی حساب بانک A در بانک B بدون تغییر باقی خواهد ماند. این فراخوانی بازگشتی تمام داراییهای بانک A را تخلیه خواهد کرد.
قراردادهای هوشمند مرتبط
قرارداد بانک A شامل دو تابع است:
- deposit(): تابع سپردهگذاری که پول را در بانک A سپردهگذاری میکند و موجودی کاربر را بهروزرسانی میکند؛
- withdraw(): تابع برداشت که به کاربران اجازه میدهد تمام وجوه خود را از بانک A برداشت کنند.
- قرارداد حمله بانک B عمدتاً شامل حلقهای است که تابع بازخوانی receive() را فعال میکند، که به نوبه خود تابع withdraw() قرارداد بانک را فراخوانی میکند تا داراییهای بانک A را از طریق یک توالی از 1 سپردهگذاری، 1 برداشت و فراخوانی تابع بازخوانی receive() تخلیه کند، و در نهایت موجودی B را در A بهروزرسانی میکند. این شامل دو تابع است:receive(): تابع بازخوانی که هنگام دریافت ETH فعال میشود و به طور بازگشتی تابع withdraw() قرارداد بانک را برای انجام برداشتها فراخوانی میکند.
- attack(): ابتدا تابع deposit() قرارداد بانک را فراخوانی میکند تا موجودی را تازه کند و سپس تابع withdraw() را برای آغاز اولین برداشت فراخوانی میکند، و تابع بازخوانی receive() را فعال میکند تا به طور بازگشتی withdraw() را فراخوانی کند تا داراییهای قرارداد بانک را تخلیه کند.
راه حل
پیادهسازی قفل ورود مجدد
قفل ورود مجدد یک اصلاحکننده است که برای جلوگیری از ورود مجدد استفاده میشود و اطمینان حاصل میکند که یک فراخوانی باید اجرای خود را قبل از اینکه بتواند دوباره فراخوانی شود، کامل کند. به عنوان مثال، از آنجایی که حمله توسط بانک B نیاز به فراخوانی چندین باره تابع withdraw() قرارداد Bank دارد، با پیادهسازی یک قفل ورود مجدد شکست خواهد خورد.
نحوه استفاده از آن
2. سوء استفاده از tx.origin
عملکرد اصلی tx.origin در یک قرارداد هوشمند، بازیابی حساب اصلی است که تراکنش را آغاز کرده است. در اینجا، ما در مورد دو متغیر رایج در قراردادهای هوشمند بحث خواهیم کرد: msg.sender و tx.origin. msg.sender حساب مستقیماً فراخوانی کننده قرارداد هوشمند را بازیابی میکند، در حالی که در دنیای بلاکچین، به دلیل فراخوانیهای تو در تو و متقابل قراردادهای هوشمند مختلف (مانند (دیفای)DeFi Lego)، tx.origin برای دستیابی به حساب اصلی که تراکنش را آغاز کرده است، مورد نیاز است. آسیبپذیری زمانی ایجاد میشود که توسعهدهندگان dApp فقط امنیت tx.origin را در کد بررسی میکنند و بررسی امنیتی مهاجمان که قراردادهای میانی را برای دور زدن tx.origin و راهاندازی حملات مستقر میکنند، نادیده میگیرند.
منطق خاص
در اینجا مثالی آورده شده است تا شما را عمیقاً با سناریوی حمله رایج آشنا کند. بیل یک کیف پول هوشمند دارد که بررسی میکند آیا بیل آغازگر انتقال است یا خیر. یک بار، بیل یک (ان اف تی)NFT را در یک وبسایت فیشینگ ضرب کرد. این امر به وبسایت اجازه داد تا هویت بیل را به دست آورد و با استفاده از هویت او، انتقالی را از کیف پول هوشمندش آغاز کند که منجر به از دست دادن داراییها شد. در شرایط عادی، احتمال اینکه کاربران در این دام بیفتند کمتر است، اما هنگام تعامل با dAppها با استفاده از کیف پول، آنها اغلب فراموش میکنند پیامهای تعاملی را بررسی کنند. به عنوان مثال، اگر هر دو شامل تابع Mint() باشند، کاربران بیدقت ممکن است به راحتی در دام فیشینگ بیفتند. منطق تجاری درون وبسایت فیشینگ پر از تله است، بنابراین مهم است که در طول تعاملات معمولی، پیامهای تعاملی را برای یافتن خطاها بررسی کنید.
قرارداد کیف پول هوشمند
قرارداد کیف پول هوشمند شامل یک تابع است:
- transfer(): یک تابع برداشت که فقط میتواند توسط مالک کیف پول، که در این مورد بیل است، آغاز شود.
قرارداد حمله فیشینگ
در یک قرارداد حمله فیشینگ، تابع Mint() کاربران را ترغیب میکند تا وجوه را به آدرس هکر منتقل کنند. این قرارداد شامل یک تابع است:
- Mint(): هنگامی که فراخوانی میشود، تابع فیشینگ به صورت داخلی transfer() قرارداد Wallet را اجرا میکند. از آنجایی که آغازگر اصلی خود کاربر است (در این مثال، بیل)، تأیید require(tx.origin == owner, "Not owner") مشکلی ایجاد نمیکند. با این حال، آدرس مقصد برای انتقال قبلاً به آدرس هکر تغییر یافته است که منجر به سرقت وجوه میشود.
راه حلها
1. استفاده از msg.sender به جای tx.origin
صرف نظر از تعداد فراخوانیهای قرارداد درگیر (قرارداد A → قرارداد B →...→ قرارداد هدف)، فقط msg.sender را تأیید کنید، یعنی فراخوان کننده مستقیم، تا از حملات ناشی از قراردادهای میانی مخرب جلوگیری شود.
2. تأیید tx.origin == msg.sender
این روش میتواند قراردادهای مخرب را دور نگه دارد، اما توسعه دهندگان باید واقعیتهای تجاری خود را در نظر بگیرند زیرا این روش به طور مؤثر تمام فراخوانیهای قرارداد خارجی دیگر را جدا میکند.
3. حمله مولد اعداد تصادفی (RNG)
این به روند برنامههای غیرمتمرکز قمار یا شرطبندی در حدود سالهای ۲۰۱۸ و ۲۰۱۹ بازمیگردد. معمولاً توسعهدهندگان از دانههای خاصی در قراردادهای هوشمند برای تولید اعداد تصادفی جهت انتخاب برندگان در قرعهکشیها استفاده میکنند. دانههای رایج شامل block.number، block.timestamp، blockhash و keccak256 هستند. با این حال، ماینرها میتوانند این دانهها را به طور کامل کنترل کنند، بنابراین در برخی موارد، ماینرهای بدخواه ممکن است متغیرها را برای کسب منافع دستکاری کنند.
قراردادهای تاس رایج
قرارداد تاس شامل یک تابع است:
- Bet(): تابع شرطبندی که در آن کاربران یک عدد شرطبندی را وارد کرده و یک ETH پرداخت میکنند. یک عدد تصادفی با چندین دانه تولید میشود و اگر عدد شرطبندی با عدد تصادفی مطابقت داشته باشد، کاربر کل جایزه را میبرد.
قرارداد حمله ماینر
ماینرها میتوانند به محض پیشمحاسبه عدد تصادفی برنده و اجرای آن در همان بلاک، برنده شوند. این شامل یک تابع است:
- attack(): تابع حمله شرطبندی، که در آن ماینر عدد تصادفی برنده را پیشمحاسبه میکند. از آنجایی که در همان بلاک اجرا میشود، blockhash(block.number - 1) و block.timestamp در همان بلاک یکسان هستند. سپس ماینر تابع Bet() قرارداد تاس را فراخوانی میکند تا حمله را تکمیل کند.
راه حل
استفاده از اعداد تصادفی خارج از زنجیره ارائه شده توسط پروژههای اوراکل
از طریق خدماتی که توسط پروژههای اوراکل مانند Chainlink ارائه میشود، اعداد تصادفی روی زنجیره به قراردادهای روی زنجیره تزریق میشوند تا تصادفی بودن و امنیت تضمین شود. با این حال، پروژههای اوراکل نیز خطرات تمرکزگرایی را به همراه دارند، بنابراین نیاز به خدمات اوراکل بالغتری را ضروری میسازند.
4. حمله بازپخش
حمله بازپخش شامل راهاندازی مجدد یک تراکنش با استفاده از یک امضای قبلاً استفاده شده برای سرقت وجوه است. یکی از معروفترین حملات بازپخش در سالهای اخیر، سرقت 20 میلیون توکن $OP از بازارساز Wintermute در Optimism بود که یک حمله بازپخش بین زنجیرهای بود. از آنجا که حساب کیف پول چند امضایی Wintermute موقتاً فقط در شبکه اصلی اتریوم مستقر شده بود، هکر از امضای تراکنش برای استقرار آدرس چند امضایی Wintermute در اتریوم استفاده کرد تا همان تراکنش را در زنجیره Optimism مجدداً اجرا کند و از این طریق کنترل حساب کیف پول چند امضایی در Optimism را به دست آورد. یک حساب کیف پول چند امضایی اساساً یک حساب قرارداد هوشمند است که تفاوت قابل توجهی بین SCA و EOA را نیز نشان میدهد. برای یک EOA، یک کاربر عادی تنها به یک کلید خصوصی نیاز دارد تا همه آدرسها را در اتریوم و زنجیرههای سازگار با EVM کنترل کند (رشتههای آدرس دقیقاً یکسان هستند)، در حالی که یک SCA پس از استقرار فقط در یک زنجیره موثر است.
منطق خاص
در اینجا، ما مثالی از یک حمله بازپخش معمولی (حمله بازپخش در همان زنجیره) ارائه میدهیم. بیل یک کیف پول هوشمند دارد که قبل از هر تراکنش نیاز به ورود امضای الکترونیکی او دارد. اکنون که هکر لوسی امضای الکترونیکی بیل را دزدیده است، او میتواند تعداد نامحدودی تراکنش را برای تخلیه کیف پول هوشمند بیل آغاز کند.
مثال
یک قرارداد با آسیبپذیریها شامل سه تابع است:
- checkSig(): تابع تأیید ECDSA، که اطمینان حاصل میکند نتیجه تأیید همان امضاکننده اصلی تنظیم شده است.
- getMsgHash(): تابع تولید هش، که به و مقدار را برای تشکیل هش ترکیب میکند.
- transfer(): تابع انتقال، که به کاربران اجازه میدهد وجوه را از استخر نقدینگی برداشت کنند. به دلیل عدم محدودیت در امضا، همان امضا میتواند مجدداً استفاده شود، که به هکرها اجازه میدهد به طور مداوم وجوه را سرقت کنند.
راه حل
برای جلوگیری از حملات تکراری، nonce را در ترکیب امضا قرار دهید. اصل پارامتر به شرح زیر است:
- nonce: این پارامتر متغیری است که تعداد تراکنشهای یک EOA را در شبکه بلاکچین توصیف میکند. این پارامتر دارای ترتیب و یکتایی است. با هر تراکنش اضافی، مقدار nonce یک واحد افزایش مییابد. شبکه بلاکچین بررسی خواهد کرد که آیا nonce تراکنش با nonce فعلی حساب مطابقت دارد یا خیر. بنابراین، اگر هکر از یک امضای استفاده شده استفاده کند، شکست خواهد خورد زیرا مقدار nonce در ترکیب امضا کمتر از مقدار nonce فعلی EOA است.
5. حمله منع سرویس (DoS)
حمله منع سرویس (DoS) در دنیای سنتی Web2 چیز جدیدی نیست. این حمله به هر گونه مداخله در یک سرور اشاره دارد، مانند ارسال مقدار زیادی اطلاعات نامربوط یا مخرب، که مانع یا کاملاً از بین برنده دسترسی میشود. به طور مشابه، قراردادهای هوشمند نیز از چنین حملاتی رنج میبرند که اساساً هدف آنها اختلال در عملکرد قرارداد هوشمند است.
منطق خاص
بیایید یک مثال را بررسی کنیم. پروژه A در حال انجام یک عرضه عمومی برای توکن پروتکل است، جایی که همه کاربران میتوانند وجوه خود را به استخر نقدینگی (قرارداد هوشمند) واریز کنند تا سهمیهها را بر اساس اولویت زمانی خریداری کنند، و وجوه اضافی به شرکتکنندگان بازگردانده خواهد شد. هکر آلیس از قرارداد حمله برای شرکت در عرضه عمومی استفاده میکند. هنگامی که استخر نقدینگی تلاش میکند وجوه را به قرارداد حمله آلیس بازگرداند، یک حمله DoS فعال میشود که مانع از تحقق عمل بازگشت میشود. در نتیجه، مقدار زیادی وجوه در قرارداد هوشمند قفل میشود.
نمونه قرارداد عرضه عمومی
مثال
قرارداد عرضه عمومی شامل دو تابع است:
- deposit(): تابع سپردهگذاری، که آدرس سپردهگذار و مبلغ مشارکت را ثبت میکند.
- refund(): تابع بازپرداخت، که با آن تیم پروژه وجوه را به سرمایهگذاران بازمیگرداند.
قرارداد حمله DoS
قرارداد حمله DoS شامل یک تابع است:
- attack(): با وجود اینکه یک تابع حمله است، هیچ مشکلی ندارد. مشکل اصلی در تابع بازخوانی پرداخت receive() است که در قرارداد هکر تعبیه شده و شامل قضاوت استثناهاست. هر قرارداد خارجی که وجوه را به قرارداد هکر منتقل کند، از طریق revert() یک استثنا را فعال میکند و در نتیجه از تکمیل عملیات جلوگیری میکند.
راه حلها
۱. از گیر افتادن عملکرد حیاتی هنگام فراخوانی قراردادهای خارجی جلوگیری کنید
عبارت require(success, "Refund Fail!"); را از تابع refund() قرارداد PublicSale در بالا حذف کنید تا اطمینان حاصل شود که عملیات بازپرداخت حتی در صورت شکست بازپرداخت به یک آدرس واحد میتواند ادامه یابد.
۲. جداسازی
در تابع refund() قرارداد PublicSale در بالا، به کاربران اجازه دهید تا خودشان بازپرداخت را مطالبه کنند به جای اینکه بازپرداختها توزیع شوند، و بدین ترتیب تعاملات غیرضروری با قراردادهای خارجی را به حداقل برسانید.
۶. حمله permit
در یک حمله مجوز، حساب A امضا را از قبل برای یک طرف تعیین شده فراهم میکند و سپس حساب B، پس از دریافت امضا، میتواند انتقالهای توکن مجاز را برای سرقت مقدار مشخصی از توکنها انجام دهد. در اینجا، ما عمدتاً دو تابع رایج برای مجوز توکن در قراردادهای هوشمند را بررسی میکنیم: approve() و permit().
در قرارداد معمول ERC20، حساب A میتواند approve() را فراخوانی کند تا مقدار مشخصی از توکنها را برای حساب B مجاز کند، که به حساب B اجازه میدهد آن توکنها را از حساب A منتقل کند. علاوه بر این، permit() در EIP-2612 به قراردادهای ERC20 معرفی شد و یونیسواپ در نوامبر 2022 یک استاندارد جدید مجوز توکن به نام Permit2 منتشر کرد.
منطق خاص
در اینجا یک مثال آورده شده است. یک روز، بیل در حال مرور یک وبسایت خبری بلاکچین بود که ناگهان یک پنجره بازشو برای امضای متامسک ظاهر شد. از آنجایی که بسیاری از وبسایتها یا برنامههای بلاکچین از امضاها برای تأیید ورود کاربران استفاده میکنند، بیل زیاد به آن فکر نکرد و مستقیماً امضا را تکمیل کرد. پنج دقیقه بعد، داراییهای متامسک او تخلیه شد. بیل سپس در مرورگر بلاکچین متوجه شد که یک آدرس ناشناس یک تراکنش permit() را آغاز کرده و به دنبال آن یک تراکنش transferFrom() کیف پول او را خالی کرده است.
مثال
دو تابع به شرح زیر هستند:
- approve(): یک تابع مجوز استاندارد که در آن حساب A مقدار مشخصی از وجوه را به حساب B مجاز میکند.
- permit(): یک تابع مجوز امضا که در آن حساب B تأیید امضا را ارسال و تکمیل میکند تا مقدار مجاز را از حساب A دریافت کند. پارامترها شامل مالک اعطای مجوز، مصرفکننده مجاز، مقدار مجاز، مهلت امضا و دادههای امضای مالک v، r و s میباشند.
راهحلها
۱. به هر امضای تعاملات روی زنجیره توجه کنید
با وجود اقداماتی که برخی کیف پولها برای رمزگشایی و نمایش اطلاعات امضای مجوز approve() انجام میدهند، آنها تقریباً هیچ هشداری برای فیشینگ امضای permit() ارائه نمیکنند که خطر حملات را افزایش میدهد. بنابراین، قویاً توصیه میشود که هر امضای ناشناخته را به دقت بررسی کنید تا مطمئن شوید که آیا هدف آن تابع permit() است یا خیر.
۲. کیف پول برای تعامل معمولی را از کیف پول ذخیره داراییها جدا کنید
این برای کاربران ارزهای دیجیتال بسیار مهم است، به ویژه برای شکارچیان ایردراپ، زیرا آنها روزانه با بیشمار dApp یا وبسایت تعامل دارند و مستعد افتادن در دام هستند. ذخیره تنها مقدار کمی از وجوه در یک کیف پول برای تعامل معمولی میتواند خسارات را در محدوده قابل کنترل نگه دارد.
۷. حمله هانیپات
در صنعت بلاکچین، حمله هانیپات به نوعی از قراردادهای توکن مخرب اشاره دارد که توسط تیمهای پروژه مستقر میشوند. قرارداد تنها به تیم پروژه اجازه فروش میدهد، در حالی که کاربران عادی فقط میتوانند خرید کنند و قادر به فروش نیستند، در نتیجه متحمل خسارت میشوند.
منطق خاص
در اینجا یک مثال آورده شده است. در یک اعلامیه در تلگرام، پروژه A به کاربران اطلاع میدهد که توکن در شبکه اصلی مستقر شده و برای معامله در دسترس است. از آنجایی که توکن را فقط میتوان خرید و نمیتوان فروخت، قیمت در ابتدا به سرعت افزایش مییابد و کاربرانی که از دست دادن فرصت میترسند، به خرید ادامه میدهند. پس از مدتی که کاربران متوجه میشوند قادر به فروش نیستند، تیم پروژه از این فرصت استفاده کرده و توکنها را دامپ میکند، که باعث سقوط قیمت میشود.
مثال
تابع اصلی:
- _beforeTokenTransfer(): یک تابع داخلی که در هنگام انتقال توکنها فراخوانی میشود و فقط زمانی موفق میشود که توسط مالک فراخوانی شود؛ فراخوانیها از سایر حسابها با شکست مواجه خواهند شد.
راه حل
استفاده از ابزارهای اسکن امنیتی
الف. Token Sniffer برای (توکن)Tokenهای اتریوم
ب. Ave Check برای (توکن)Tokenها در سایر زنجیرهها
ج. وبسایتهای بازار با ابزارهای تشخیص داخلی مانند Dextools
از معامله (توکن)Tokenهایی با امتیاز پایین خودداری کنید.
8. حمله پیشدستی (Front-Running)
پیشدستی در ابتدا در بازارهای مالی سنتی ظهور کرد، جایی که عدم تقارن اطلاعاتی به واسطههای مالی اجازه میداد تا با اقدامات سریع بر اساس اطلاعات خاص صنعت، سود کسب کنند. در صنعت بلاکچین، پیشدستی عمدتاً از پیشدستی درون زنجیرهای ناشی میشود که شامل دستکاری ماینرها برای اولویتبندی تراکنشهای خود در زنجیره به منظور کسب سود است.
در حوزه بلاکچین، ماینرها میتوانند با دستکاری تراکنشهایی که در بلوکها قرار میدهند، سود کسب کنند، مثلاً با حذف برخی تراکنشها و تغییر ترتیب تراکنشها. چنین سودی را میتوان با ارزش قابل استخراج ماینر (MEV) اندازهگیری کرد. قبل از اینکه تراکنش یک کاربر به شبکه اصلی اتریوم اضافه شود، اکثر تراکنشها در mempool جمع میشوند. ماینرها در این mempool به دنبال تراکنشهایی با هزینههای گاز بالاتر میگردند و آنها را برای به حداکثر رساندن سود خود در اولویت قرار میدهند. معمولاً، تراکنشهایی با هزینههای گاز بالاتر راحتتر توسط ماینرها بستهبندی میشوند. در همین حال، برخی رباتهای MEV نیز mempool را برای تراکنشهای سودآور جستجو میکنند.
منطق خاص
در زیر یک مثال آمده است. بیل یک (توکن)Token داغ جدید با نوسانات قیمت قابل توجه کشف میکند. برای اطمینان از موفقیت معاملات (توکن)Token در یونیسواپ، بیل محدوده لغزش بسیار گستردهای را تعیین میکند. متأسفانه، ربات MEV آلیس این تراکنش را در mempool تشخیص میدهد و فوراً هزینه گاز را افزایش میدهد، یک تراکنش خرید قبل از تراکنش بیل و یک تراکنش فروش بعد از تراکنش بیل در همان بلوک را آغاز میکند. پس از تأیید بلوک، این امر باعث ضررهای قابل توجه لغزش برای بیل میشود، در حالی که آلیس از یک عملیات آربیتراژ خرید ارزان و فروش گران سود میبرد.
مثال
تابع به شرح زیر است:
- solve(): تابعی برای حدس زدن که هر کسی میتواند پاسخی را ارسال کند و اگر پاسخ ارسال شده با پاسخ هدف مطابقت داشته باشد، فرستنده میتواند 10 اتر دریافت کند.
- فرآیند: بیل پاسخ صحیح را پیدا میکند.
- آلیس mempool را نظارت میکند، منتظر میماند تا کسی پاسخ صحیح را ارسال کند.
- بیل تابع solve() را فراخوانی میکند تا پاسخ را ارسال کند و قیمت گاز را 100 Gwei تنظیم میکند.
- آلیس تراکنش ارسال شده توسط بیل را میبیند و پاسخ را کشف میکند. او قیمت گاز را بالاتر از بیل، 200 Gwei تنظیم میکند و solve() را فراخوانی میکند.
- تراکنش آلیس قبل از تراکنش بیل توسط ماینر بستهبندی میشود.
- آلیس جایزهای به ارزش 10 اتر را میبرد.
راه حل
سه تابع اصلی به شرح زیر است:
- commitSolution(): تابعی برای ارسال نتایج، که پاسخ ارسالی کاربر solutionHash، زمان ارسال commitTime و وضعیت revealed را در ساختار Commit قرار میدهد.
- getMySolution(): تابعی برای دریافت نتایج، که به کاربران اجازه میدهد پاسخهای ارسالی خود و اطلاعات مربوطه را مشاهده کنند، از جمله پاسخ ارسالی کاربر solutionHash، زمان ارسال commitTime و وضعیت revealed.
- revealSolution(): تابعی برای ادعای جوایز برای حدس زدن پازل، که به کاربران اجازه میدهد پس از ارائه پاسخ و رمز عبوری که تنظیم کردهاند، جوایز را ادعا کنند.
فرآیند:
- بیل پاسخ صحیح را پیدا میکند.
- بیل برای ارسال پاسخ صحیح، تابع commitSolution() را فراخوانی میکند.
- در بلاک بعدی، بیل تابع revealSolution() را فراخوانی میکند و پاسخ و رمز عبوری که برای دریافت پاداش تنظیم کرده است را ارائه میدهد.
در تابع commitSolution()، بیل یک رشته رمزگذاری شده را ارسال میکند و دادههای متن ساده ارسالی را فقط برای خودش نگه میدارد. در این مرحله، زمان بلاک ارسال (commitTime) نیز ثبت میشود. سپس، در تابع revealSolution()، زمان بلاک بررسی میشود تا از پیشدستی در همان بلاک جلوگیری شود. از آنجا که فراخوانی تابع revealSolution() نیازمند ارسال پاسخ متن ساده است، این مرحله با هدف جلوگیری از دور زدن تابع commitSolution() و فراخوانی مستقیم تابع revealSolution() توسط دیگران انجام میشود. پس از تأیید موفقیتآمیز، اگر پاسخ صحیح باشد، پاداش توزیع خواهد شد.
نتیجهگیری
قراردادهای هوشمند نقش حیاتی در فناوری بلاکچین ایفا میکنند و مزایای متعددی را ارائه میدهند. اولاً، آنها اجرای غیرمتمرکز و خودکار را امکانپذیر میسازند و امنیت و قابلیت اطمینان تراکنشها را بدون نیاز به اشخاص ثالث تضمین میکنند. ثانیاً، قراردادهای هوشمند مراحل واسطه و هزینهها را کاهش میدهند و کارایی تراکنشها را افزایش میدهند.
علیرغم این همه مزایا، قراردادهای هوشمند همچنین با خطر حملاتی مواجه هستند که میتواند منجر به ضررهای مالی برای کاربران شود. به همین دلیل، برخی عادات برای کاربران زنجیره ضروری است. اولاً، کاربران باید همیشه با دقت برنامههای غیرمتمرکز را برای تعامل انتخاب کنند و کد قرارداد و قوانین مرتبط را به طور کامل بررسی نمایند. علاوه بر این، آنها باید به طور منظم کیف پولها و ابزارهای تعامل با قرارداد را بهروزرسانی کرده و از نسخههای امن استفاده کنند تا خطر حملات هکرها را کاهش دهند. همچنین، توصیه میشود که وجوه خود را در چندین آدرس ذخیره کنند تا خسارات احتمالی ناشی از حملات به قراردادها را به حداقل برسانند.
برای فعالان صنعت، تضمین امنیت و ثبات قراردادهای هوشمند از اهمیت یکسانی برخوردار است. اولویت اول باید تقویت حسابرسی قراردادهای هوشمند باشد تا آسیبپذیریها و خطرات امنیتی بالقوه شناسایی و اصلاح شوند. دوم، فعالان صنعت باید از آخرین تحولات بلاکچین مرتبط با حملات قراردادی مطلع باشند و اقدامات امنیتی متناسب را اتخاذ کنند. آخر اما نه کم اهمیت، آنها همچنین باید آموزش کاربران و آگاهی امنیتی را در زمینه استفاده صحیح از قراردادهای هوشمند افزایش دهند.
در نتیجه، با تلاشهای هماهنگ کاربران و فعالان صنعت، خطرات امنیتی ناشی از قراردادهای هوشمند میتواند به طور قابل توجهی کاهش یابد. کاربران باید همیشه با دقت قراردادها را انتخاب کنند و از داراییهای شخصی خود محافظت کنند، در حالی که فعالان صنعت باید حسابرسی قرارداد را تشدید کنند، با پیشرفتهای فناوری همگام باشند و آموزش کاربران و آگاهی امنیتی را افزایش دهند. با هم، ما توسعه امن و قابل اعتماد قراردادهای هوشمند را پیش خواهیم برد.
منابع:
Solidity به عنوان مثال:https://solidity-by-example.org/
دانش بلاکچین SlowMist:https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzU4ODQ3NTM2OA==&action=getalbum&album_id=1378673890158936067&scene=173&from_msgid=2247498135&from_itemidx=1&count=3&nolastread=1#wechat_redirect
Chainlink - ۱۰ بهترین روش امنیتی برتر (دیفای)DeFi:https://blog.chain.link/defi-security-best-practices/#post-title
WTF - امنیت قرارداد Solidity 104:https://www.wtf.academy/solidity-104/
آسیبپذیریهای قراردادهای هوشمند (دیفای)DeFi در ۴ دسته با ۳۸ سناریو:https://www.weiyangx.com/381670.html
OpenZeppelin:https://github.com/OpenZeppelin/