بهترین روشهای Solidity برای امنیت قرارداد هوشمند

وبلاگ 1NewsDevelopersEnterpriseBlockchain ExplainedEvent ها و کنفرانس ها Pressخبرنامه ها

Contents

مشترک شدن در خبرنامه ما.

آدرس ایمیل

ما به حریم خصوصی شما احترام می گذاریم

صفحه اصلی وبلاگ توسعه Blockchain

بهترین روشهای Solidity برای امنیت قرارداد هوشمند

از نظارت تا ملاحظات زمان سنجی ، در اینجا چند نکته مفید برای اطمینان از تقویت قرارداد های هوشمند Ethereum آورده شده است. توسط ConsenSys 21 آگوست 2020 ارسال شده در 21 آگوست 2020

جامدادی بهترین عملکرد قهرمان

توسط ConsenSys Diligence ، تیم متخصص امنیت بلاکچین ما.

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

خوب ، بیایید داخل برویم.

به طور صحیح از assert () ، Require () ، () برگردانید

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

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

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

پیروی از این پارادایم به ابزارهای تجزیه و تحلیل رسمی اجازه می دهد تا تأیید کنند که کد کد نامعتبر هرگز قابل دسترسی نیست: به این معنی که هیچ تغییری در کد نقض نمی شود و کد به طور رسمی تأیید می شود.

استحکام پراگما ^ 0.5.0؛ contract Sharer {تابع sendHalf (آدرس قابل پرداخت قابل پرداخت) بازده قابل پرداخت عمومی (توازن uint) {نیاز (msg.value٪ 2 == 0, "حتی ارزش لازم است.") // Require () می تواند یک پیام اختیاری داشته باشد رشته uint balanceBeforeTransfer = آدرس (این) .balance؛ (موفقیت bool ،) = addr.call.value (msg.value / 2) ("") نیاز (موفقیت) // از آنجایی که در صورت عدم موفقیت در انتقال ، ما برگشتیم ، هیچ راهی برای ما باقی نمی ماند که نیمی از پول را در اختیار داشته باشیم. assert (آدرس (این) .balance == balanceBeforeTransfer – msg.value / 2)؛ // برای بررسی خطای داخلی آدرس بازگشت (این) استفاده می شود. تعادل؛ }} زبان کد: JavaScript (javascript)


دیدن SWC-110 & SWC-123

از اصلاح کننده ها فقط برای چک استفاده کنید

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

قرارداد ثبت نام {صاحب آدرس؛ تابع isVoter (آدرس _addr) بازده خارجی (bool) {// Code}} contract Election {Registry Register؛ modifier isEligible (آدرس _addr) {Require (Register.isVoter (_addr))؛ _؛ } vote vote () قابل قبول است (msg.sender) عمومی {// Code}} زبان کد: JavaScript (javascript)

در این حالت ، قرارداد رجیستری می تواند با تماس با Election.vote () داخل isVoter () حمله مجدد را انجام دهد..

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

مراقب گرد کردن با تقسیم عدد صحیح باشید

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

(در آینده ، Solidity دارای یک نقطه ثابت نوع ، که این کار را آسان تر می کند.)

// بد uint x = 5/2؛ // نتیجه 2 است ، تمام بخشهای تقسیم عدد پایین به نزدیکترین عدد صحیح دور می شوند زبان کد: JavaScript (javascript)

با استفاده از یک ضریب جلوگیری از گرد کردن ، باید این ضرب را هنگام کار با x حساب کنید:

// ضریب خوب uint = 10؛ uint x = (5 * ضرب) / 2 ؛ زبان کد: JavaScript (javascript)

ذخیره عدد و مخرج به این معنی است که می توانید نتیجه عدد / مخرج خارج از زنجیره را محاسبه کنید:

// خوب uint number = 5؛ مخرج uint = 2 ؛ زبان کد: جاوا اسکریپت (جاوا اسکریپت)

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

هر دو رابط و قراردادهای انتزاعی رویکردی قابل تنظیم و قابل استفاده مجدد را برای قراردادهای هوشمند ارائه می دهند. رابط هایی که در Solidity 0.4.11 معرفی شدند ، مشابه قراردادهای انتزاعی هستند اما نمی توانند عملکردی را اجرا کنند. رابط ها همچنین محدودیت هایی از جمله عدم دسترسی به ذخیره سازی یا ارث بردن از رابط های دیگر دارند که به طور کلی قراردادهای انتزاعی را عملی تر می کند. اگرچه ، رابط ها مطمئناً برای طراحی قراردادها قبل از اجرا مفید هستند. علاوه بر این ، مهم است که به خاطر داشته باشید که اگر یک قرارداد از یک قرارداد انتزاعی ارث می برد ، باید تمام توابع غیر اجرا شده را از طریق لغو اجرا کند ، در غیر این صورت انتزاعی خواهد بود.

توابع بازگشت

توابع بازگشتی را ساده نگه دارید

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

// عملکرد بد () قابل پرداخت {مانده [msg.sender] + = msg.value؛ } // سپرده عملکرد خوب () قابل پرداخت {مانده) [msg.sender] + = msg.value؛ } تابع () قابل پرداخت {نیاز (msg.data.length == 0)؛ LogDepositReceived را منتشر کنید (msg.sender) ؛ } زبان کد: جاوا اسکریپت (جاوا اسکریپت)

طول داده ها را در عملکردهای برگشتی بررسی کنید

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

// عملکرد بد () قابل پرداخت {emit LogDepositReceived (msg.sender)؛ } // عملکرد خوب () قابل پرداخت {نیاز (msg.data.length == 0)؛ LogDepositReceived را منتشر کنید (msg.sender) ؛ } زبان کد: جاوا اسکریپت (جاوا اسکریپت)

توابع قابل پرداخت و متغیرهای حالت را به طور واضح علامت گذاری کنید

با شروع از Solid 0.4.0 ، هر تابعی که اتر دریافت می کند باید از اصلاح کننده قابل پرداخت استفاده کند ، در غیر این صورت اگر تراکنش دارای msg.value باشد. > 0 برمی گردد (مگر هنگام اجبار).

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

به وضوح قابل مشاهده بودن در توابع و متغیرهای حالت را علامت گذاری می کند

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

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

// بد uint x ؛ // پیش فرض داخلی برای متغیرهای حالت است ، اما باید تابع خرید صریح باشد () {// پیش فرض عمومی است // کد عمومی} // خوب uint private y؛ تابع خرید () خارجی {// فقط قابل فراخوانی از خارج یا استفاده از this.buy ()} ابزار تابع () عمومی {// قابل فراخوانی خارجی ، و همچنین داخلی: تغییر این کد مستلزم تفکر درباره هر دو حالت است. } تابع internalAction () داخلی {// کد داخلی} زبان کد: PHP (php)

دیدن SWC-100 و SWC-108

عملگرها را به نسخه کامپایلر خاص قفل کنید

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

// استحکام پراگما بد ^ 0.4.4؛ // solid pragma solidity 0.4.4؛ زبان کد: JavaScript (javascript)

توجه: یک نسخه پراگما شناور (به عنوان مثال ^ 0.4.25 ^) با 0.4.26-nightly.2018.9.25 کامپایل می شود ، اما از ساخت شبانه هرگز نباید برای تدوین کد تولید استفاده شود.

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

دیدن SWC-103

از رویدادها برای نظارت بر فعالیت قرارداد استفاده کنید

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

contract Charity {نقشه برداری (آدرس => uint) تعادل function donate () قابل پرداخت عمومی {مانده (msg.sender) + = msg.value؛ }} contract Game {تابع buyCoins () قابل پرداخت {/ 5٪ به خیریه خیریه می رود. donon.value (msg.value / 20) ()؛ }} زبان کد: JavaScript (javascript)

در اینجا ، قرارداد Game یک تماس داخلی با Charity.donate () برقرار می کند. این معامله در لیست معاملات خارجی خیریه نشان داده نمی شود ، اما فقط در معاملات داخلی قابل مشاهده است.

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

contract Charity {// تعریف رویداد LogDonate رویداد (uint _amount)؛ نقشه برداری (آدرس => uint) تعادل function donate () قابل پرداخت عمومی {مانده (msg.sender) + = msg.value؛ // emit event را منتشر کنید LogDonate (msg.value)؛ }} contract Game {تابع buyCoins () قابل پرداخت {/ 5٪ به خیریه خیریه می رود. donon.value (msg.value / 20) ()؛ }} زبان کد: JavaScript (javascript)

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

توجه: سازه های Solidid جدیدتر را ترجیح دهید. ساختارها / نام های مستعار مانند خودساختی (نسبت به خودکشی) و keccak256 (بیش از sha3) را ترجیح دهید. الگوهایی مانند نیاز (msg.sender.send (1 اتر)) را می توان با استفاده از transfer () ساده کرد ، همانطور که در msg.sender.transfer (1 اتر). وارسی ثبت تغییر جامدادی برای تغییرات مشابه بیشتر.

توجه داشته باشید که “ساخته شده” را می توان سایه زد

در حال حاضر امکان پذیر است سایه گلوبال های داخلی در جامدادی. این اجازه می دهد تا قراردادها عملکرد داخلی را مانند msg و revert () نادیده بگیرند. گرچه این در نظر گرفته شده, این می تواند کاربران یک قرارداد را در مورد رفتار واقعی قرارداد گمراه کند.

contract PretendingToRevert {function revert () ثابت داخلی {}} contract ExampleContract is PretendingToRevert {function somethingBad () public {revert ()؛ }}

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

از استفاده از tx.origin خودداری کنید

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

قرارداد MyContract {صاحب آدرس؛ تابع MyContract () public {صاحب = msg.sender؛ } تابع sendTo (گیرنده آدرس ، مقدار uint) عمومی {نیاز (tx.origin == صاحب)؛ (موفقیت bool ،) = گیرنده. مقدار تماس (مقدار) ("") نیاز (موفقیت) }} contract AttackingContract {MyContract myContract؛ آدرس مهاجم؛ تابع AttackingContract (آدرس myContractAddress) public {myContract = MyContract (myContractAddress)؛ مهاجم = msg.sender؛ } function () public {myContract.sendTo (مهاجم ، msg.sender.balance)؛ }} زبان کد: JavaScript (javascript)

برای مجوز باید از msg.sender استفاده کنید (اگر قرارداد دیگری قرارداد شما را فراخوانی می کند. ارسال کننده آدرس قرارداد خواهد بود نه آدرس کاربری که قرارداد را فراخوانده است).

در اینجا شما میتوانید اطلاعات بیشتری راجع به آن بخوانید: اسناد جامدادی

هشدار: علاوه بر مسئله مجوز ، این احتمال وجود دارد که tx.origin در آینده از پروتکل Ethereum حذف شود ، بنابراین کدی که از tx استفاده می کند با نسخه های آینده سازگار نخواهد بود ویتالیک: “تصور نکنید که tx.origin همچنان قابل استفاده یا معنی دار خواهد بود.”

همچنین لازم به ذکر است که با استفاده از tx.origin شما قابلیت همکاری بین قراردادها را محدود می کنید زیرا قراردادی که از tx.origin استفاده می کند توسط قرارداد دیگری قابل استفاده نیست زیرا قرارداد نمی تواند tx.origin باشد.

دیدن SWC-115

وابستگی به مهر زمان

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

دستکاری مهر زمان

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

uint256 ثابت نمک خصوصی = block.timestamp؛ عملکرد تصادفی (uint Max) بازده ثابت ثابت (نتیجه uint256) {// بهترین دانه را برای تصادفی دریافت کنید uint256 x = نمک * 100 / حداکثر؛ uint256 y = نمک * block.number / (نمک٪ 5)؛ uint256 seed = block.number / 3 + (نمک٪ 300) + آخرین_پرداخت + y ؛ uint256 h = uint256 (block.blockhash (دانه)) ؛ بازگشت uint256 ((h / x))٪ حداکثر + 1؛ // عدد تصادفی بین 1 و حداکثر} زبان کد: PHP (php)

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

قانون 15 ثانیه ای

 کاغذ زرد (مشخصات مرجع Ethereum) محدودیتی در مورد میزان بلوک های زمانی ایجاد نمی کند ، اما مشخص می کند که هر مهر زمان باید بزرگتر از مهر زمان اصلی آن باشد. پیاده سازی محبوب پروتکل Ethereum گت و برابری هر دو بلوک های دارای مهر زمان را بیش از 15 ثانیه در آینده رد می کنند. بنابراین ، یک قاعده کلی خوب در ارزیابی استفاده از مهر زمان این است: اگر مقیاس رویداد وابسته به زمان شما می تواند 15 ثانیه تغییر کند و یکپارچگی را حفظ کند ، استفاده از یک block.timestamp ایمن است.

از استفاده از block.number به عنوان زمان سنج خودداری کنید

می توان با استفاده از ویژگی block.number و دلتا زمان را تخمین زد زمان بلوک متوسط, با این حال این اثبات آینده نیست زیرا ممکن است زمان بلوک تغییر کند (مانند سازماندهی مجدد چنگال و بمب دشواری) در روزهای گسترده فروش ، قانون 15 ثانیه ای به شخص اجازه می دهد تا زمان تقریبی بیشتری را بدست آورد.

دیدن SWC-116

احتیاط ارث چندگانه

هنگام استفاده از وراثت چندگانه در Solidity ، مهم است که درک کنیم کامپایلر نمودار وراثت را چگونه ترکیب می کند.

قرارداد نهایی {uint public a؛ تابع Final (uint f) public {a = f؛ }} قرارداد B نهایی است {هزینه عمومی؛ تابع B (uint f) نهایی (f) عمومی {} تابع setFee () عمومی {هزینه = 3؛ }} قرارداد C نهایی است {هزینه عمومی؛ تابع C (uint f) نهایی (f) عمومی {} تابع setFee () عمومی {هزینه = 5؛ }} قرارداد A B ، C {تابع A () عمومی B (3) C (5) {setFee () است. }} زبان کد: PHP (php)

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

نهایی <- ب <- ج <- آ

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

برای کمک به مشارکت ، Solidity’s Github دارای یک پروژه با تمام مسائل مربوط به ارث.

دیدن SWC-125

برای ایمنی نوع ، به جای آدرس از نوع رابط استفاده کنید

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

در اینجا ما دو گزینه را مشاهده می کنیم:

contract Validator {تابع اعتبارسنجی (uint) بازده خارجی (bool)؛ } contract TypeSafeAuction {// تابع good validateBet (Validator _validator، uint _value) بازده داخلی (bool) {bool valid = _validator.validate (_value)؛ معتبر برگرداندن؛ }} contract TypeUnsafeAuction {// عملکرد بد validateBet (آدرس _addr ، uint _value) بازده داخلی (bool) {Validator validator = Validator (_addr)؛ bool valid = validator.validate (_value)؛ معتبر برگرداندن؛ }} زبان کد: JavaScript (javascript)

مزایای استفاده از قرارداد TypeSafeAuction فوق را می توان از مثال زیر مشاهده کرد. اگر () validateBet با یک آرگومان آدرس یا نوع دیگری از قرارداد به غیر از Validator فراخوانی شود ، کامپایلر این خطا را انجام می دهد:

contract NonValidator {} contract Auction is TypeSafeAuction {NonValidator nonValidator؛ شرط تابع (uint _value) {bool valid = validateBet (nonValidator، _value)؛ // TypeError: نوع نامعتبر برای آرگومان در فراخوانی عملکرد. // تبدیل ضمنی نامعتبر از قرارداد NonValidator // به اعتبار سنجی قرارداد درخواست شده است. }} زبان کد: JavaScript (javascript)

برای بررسی حسابهای متعلق به خارج از استفاده از extcodesize خودداری کنید

اصلاح کننده زیر (یا چک مشابه) اغلب برای بررسی اینکه آیا تماس از یک حساب خارجی (EOA) یا یک قرارداد انجام شده است استفاده می شود:

// اصلاح کننده بد isNotContract (آدرس _a) {uint size؛ اسمبلی {size: = extcodesize (_a)} نیاز (size == 0)؛ _؛ } زبان کد: جاوا اسکریپت (جاوا اسکریپت)

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

قرارداد OnlyForEOA {uint flag عمومی؛ // اصلاح کننده بد isNotContract (آدرس _a) {uint len؛ اسمبلی {len: = extcodesize (_a)} نیاز (len == 0)؛ _؛ } function setFlag (uint i) public isNotContract (msg.sender) {flag = i؛ }} contract FakeEOA {سازنده (آدرس _a) public {OnlyForEOA c = OnlyForEOA (_a)؛ c.setFlag (1) ؛ }} زبان کد: JavaScript (javascript)

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

هشدار: این مسئله ظریف است. اگر هدف شما جلوگیری از تماس سایر قراردادها با قرارداد شما است ، احتمالاً بررسی اندازه اضافی کافی است. یک روش جایگزین بررسی مقدار (tx.origin == msg.sender) است ، البته این نیز اشکالاتی دارد.

ممکن است شرایط دیگری نیز وجود داشته باشد که در آن چک کردن گزینه extcode برای شما مناسب است. توصیف همه آنها در اینجا خارج از حیطه است. رفتارهای اساسی EVM را درک کنید و از قضاوت خود استفاده کنید.

آیا کد Blockchain شما امن است?

با کارشناسان امنیتی ما یک چک نقطه ای 1 روزه رزرو کنید. رزرو امروز شما با تلاش ، امنیت ، قراردادهای هوشمند ، اخبار ، اخبار ، ویدئو ، اخبار Ethereum ، راه حل های سازمانی ، منابع توسعه دهنده و موارد دیگر در خبرنامه ما مشترک شوید. آدرس ایمیل محتوای اختصاصیچگونه یک محصول بلاکچین موفق بسازیموبینار

چگونه یک محصول بلاکچین موفق بسازیم

نحوه تنظیم و اجرای گره Ethereumوبینار

نحوه تنظیم و اجرای گره Ethereum

چگونه API Ethereum خود را بسازیموبینار

چگونه API Ethereum خود را بسازیم

چگونه یک نشانه اجتماعی ایجاد کنیموبینار

چگونه یک نشانه اجتماعی ایجاد کنیم

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

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

آینده دارایی های دیجیتال مالی و DeFiوبینار

آینده مالی: دارایی های دیجیتال و DeFi

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me
Like this post? Please share to your friends:
Adblock
detector
map