🎓 دانشکدهٔ ۱۲ · مسیرهای تخصصی
مسیر توسعهدهندهٔ قرارداد هوشمند
Track: smart contract developer
پیشنیازها: امنیت قرارداد هوشمند
📚 آموزش در سه سطح
از سطح ساده شروع کنید؛ اگر روشن بود، سطح بعد را بخوانید. سطح مناسب شما ذخیره میشود.
🌱 توضیح ساده
توسعهدهندهٔ قرارداد هوشمند کدی مینویسد که پس از استقرار، دارایی واقعی را بدون واسطه مدیریت میکند و معمولاً بهآسانی قابل اصلاح نیست. به همین دلیل این مسیر بیش از سرعت به احتیاط نیاز دارد: هر خط کد بالقوه یک سطح حمله است و هر تابع عمومی دری برای ورود مهاجمان. شعار حرفهای این مسیر «ساده نگه دار» است، چون کد سادهتر را راحتتر میتوان آزمود، فهمید و ممیزی کرد.
ابزار و دانش پایه عبارتاند از زبانهایی مانند Solidity یا Vyper، ماشین مجازی اتریوم و هزینهٔ گس، چارچوبهای توسعه و آزمون، استانداردهای توکن (ERC-20 و ERC-721)، کتابخانههای ممیزیشده و الگوهای امنیتی مانند بررسیها-اثرها-تعاملها. دانستن تاریخچهٔ حملههای بزرگ هم بخشی از دانش فنی است، چون بیشتر باگها تکرار الگوهای قدیمیاند.
چرخهٔ کار حرفهای این است: مشخصات دقیق رفتار مورد انتظار، طراحی با کمترین اختیارات لازم، نوشتن آزمون پیش و همزمان با کد، فازینگ و آزمون ویژگیمحور، ممیزی داخلی و مستقل، استقرار روی شبکهٔ آزمایشی، برنامهٔ پاداش باگ و سپس استقرار تدریجی با سقف سپرده. هر مرحله دستهای از خطاها را میگیرد که مرحلهٔ دیگر نمیگیرد.
📘 توضیح متوسط
«مقداردهی اولیه» یکی از حساسترین بخشهاست: قراردادی که تابع مقداردهی دارد، مثلاً برای تعیین مالک، باید هنگام استقرار مقداردهی و قفل شود؛ وگرنه هر کسی میتواند آن را صدا بزند و مالک شود. این خطر در الگوهای «پراکسی» و «کتابخانهٔ مشترک» دوچندان است، چون قرارداد منطق جداگانه مستقر میشود و ممکن است مقداردهی خودِ آن فراموش شود.
الگوهای «قابل ارتقا» با پراکسی و فراخوانی delegatecall کار میکنند: قرارداد پراکسی وضعیت را نگه میدارد و منطق را از قرارداد دیگری قرض میگیرد. این الگو انعطاف میدهد اما خطرهای ویژه دارد: ناسازگاری چیدمان حافظه بین نسخهها، قرارداد منطقی که خودش مقداردهی نشده، و توابع خطرناکی مانند selfdestruct در قرارداد منطق که میتواند همهٔ پراکسیهای وابسته را از کار بیندازد.
آزمون حرفهای فراتر از «مسیر خوش» است: آزمون حالتهای مرزی، ورودیهای بدخواهانه، ترتیبهای غیرمنتظرهٔ فراخوانی و «ثابتها»؛ یعنی ویژگیهایی که باید همیشه برقرار بمانند، مثلاً «مجموع موجودی کاربران هرگز از ذخیرهٔ قرارداد بیشتر نمیشود». فازینگ ویژگیمحور این ثابتها را با هزاران ورودی تصادفی میآزماید و باگهایی را مییابد که آزمون دستی نمییابد.
🔬 توضیح تخصصی
«اصل کمترین اختیار» در طراحی قرارداد یعنی هر نقش فقط اختیارات لازم را داشته باشد، توابع مدیریتی محدود و پشت چندامضایی و تایملاک باشند و توابع غیرقابل برگشت، مانند نابودی قرارداد یا انتقال کامل وجوه، یا حذف شوند یا با محافظت چندلایه همراه باشند. هر اختیار اضافه هم هدف مهاجم است و هم ریسک خطای انسانی.
ممیزی آخرین خط دفاع است، نه اولین. ممیزان کد را در زمانی محدود و بر اساس مشخصات شما بررسی میکنند؛ اگر مشخصات ناقص باشد، رفتار نادرستی که «مطابق مشخصات» است دیده نمیشود. توسعهدهندهٔ حرفهای مستندات معماری، مدل تهدید و فهرست ثابتها را به ممیز میدهد، یافتهها را با دقت رفع میکند و پس از هر تغییر بزرگ دوباره ممیزی میگیرد.
سبد کاری این مسیر شامل مخزنهای کد با آزمونهای جامع و پوشش بالا؛ مشارکت در مسابقههای ممیزی یا برنامههای پاداش باگ؛ بازنویسی امن یک قرارداد آسیبدیدهٔ تاریخی همراه با آزمونی که باگ اصلی را بازتولید میکند؛ و مستندسازی تصمیمهای طراحی است. توانایی توضیح اینکه «چرا این کد امن است» از توانایی نوشتن آن مهمتر است.
🌍 مثال واقعی: فریز کیفپولهای چندامضایی Parity — ۶ نوامبر ۲۰۱۷
کیفپولهای چندامضایی Parity از دو بخش ساخته میشدند: یک قرارداد سبک برای هر کیفپول و یک «کتابخانه» مشترک که منطق اصلی را داشت و همهٔ کیفپولها از طریق delegatecall از آن استفاده میکردند. پس از حملهٔ ۱۹ ژوئیهٔ ۲۰۱۷ به همین کیفپولها، کتابخانهٔ اصلاحشده در ۲۰ ژوئیه مستقر شد؛ اما خودِ قرارداد کتابخانه مقداردهی نشده بود و تابع نابودی (selfdestruct) کیفپول اصلی را هم در خود داشت.
در ۶ نوامبر ۲۰۱۷ کاربری با نام devops199 تابع مقداردهی کتابخانه را صدا زد، خود را مالک آن کرد و سپس آن را نابود کرد؛ او بعداً نوشت که این کار تصادفی بوده است. با نابودی کتابخانه، ۵۸۷ کیفپول که پس از ۲۰ ژوئیه ساخته شده بودند و در مجموع ۵۱۳٬۷۷۴٫۱۶ ETH و توکنهای دیگر داشتند، از کار افتادند و وجوهشان قفل شد. درس برای توسعهدهنده: قرارداد منطق یا کتابخانه را هنگام استقرار مقداردهی و قفل کنید، توابع غیرقابل برگشت را از کد مشترک حذف کنید و برای هر تابع عمومی سناریوی «اگر یک غریبه این را صدا بزند» را بیازمایید.
🔤 واژگان تخصصی
تنظیم وضعیت آغازین قرارداد، مانند مالک، که باید یک بار و هنگام استقرار انجام و قفل شود.
مثال: فراخوانی initialize هنگام استقرار و جلوگیری از فراخوانی دوباره.
قراردادی که وضعیت را نگه میدارد و منطق را با delegatecall از قرارداد دیگری اجرا میکند.
مثال: ارتقای منطق بدون تغییر نشانی قرارداد کاربران.
ویژگیای که باید در همهٔ حالتهای قرارداد برقرار بماند.
مثال: مجموع موجودی کاربران کمتر یا مساوی ذخیرهٔ قرارداد.
دادن فقط اختیارات لازم به هر نقش و محدود کردن توابع مدیریتی.
مثال: تابع توقف فقط در اختیار چندامضایی با تایملاک.
آزمودن ثابتها با هزاران ورودی و ترتیب تصادفی فراخوانی.
مثال: یافتن ترتیبی از فراخوانیها که ثابت موجودی را میشکند.
🔑 نکات کلیدی
- هر خط کد و هر تابع عمومی یک سطح حمله است؛ ساده نگه دارید.
- قرارداد منطق و کتابخانهٔ مشترک را هنگام استقرار مقداردهی و قفل کنید.
- ثابتها را تعریف و با فازینگ ویژگیمحور بیازمایید.
- فریز Parity در ۶ نوامبر ۲۰۱۷ با نابودی کتابخانهٔ مقداردهینشده ۵۱۳٬۷۷۴ ETH را در ۵۸۷ کیفپول قفل کرد.
- ممیزی آخرین خط دفاع است؛ مشخصات، مدل تهدید و ثابتها را به ممیز بدهید.
⚠️ اشتباهات رایج
- فراموش کردن مقداردهی قرارداد منطق یا کتابخانه؛ اشتباه است چون هر کسی میتواند مالک آن شود.
- نگه داشتن توابع غیرقابل برگشت در کد مشترک؛ اشتباه است چون یک فراخوانی میتواند همهٔ وابستگان را از کار بیندازد.
- آزمون فقط مسیر خوش؛ اشتباه است چون مهاجم دقیقاً حالتهای مرزی و ترتیبهای غیرمنتظره را امتحان میکند.
- تکیه بر ممیزی به جای طراحی امن؛ اشتباه است چون ممیزی به زمان و مشخصات دادهشده محدود است.
🛠 تمرین عملی: بازتولید و رفع باگ مقداردهی
- یک قرارداد نمونهٔ ساده با الگوی کتابخانه یا پراکسی بنویسید که تابع مقداردهی آن قفل نشده است.
- آزمونی بنویسید که نشان دهد یک نشانی غریبه میتواند مقداردهی کند و مالک شود؛ سپس قرارداد را طوری اصلاح کنید که مقداردهی فقط یک بار و هنگام استقرار ممکن باشد.
- دستکم دو ثابت برای قرارداد تعریف کنید، آنها را با یک ابزار فازینگ بیازمایید و نتیجه را در گزارشی کوتاه بنویسید.
✅ معیار درستی: آزمون باگ مقداردهی را بازتولید میکند، نسخهٔ اصلاحشده آن را مسدود میکند و ثابتها تعریف و با فازینگ آزموده شدهاند.
🔒 در هیچ تمرینی از سرمایهٔ واقعی، عبارت بازیابی (Seed Phrase)، کلید خصوصی یا اتصال کیف پول اصلی استفاده نکنید.
📝 آزمون تطبیقی
هر بار ۵ سؤال از بانک ۹ سؤالی این درس انتخاب میشود؛ سؤالهایی که قبلاً اشتباه زدهاید زودتر برمیگردند. حدنصاب قبولی ۸۰٪ (۴ از ۵) است و درس بعد با قبولی باز میشود.
✍️ پرسش تشریحی
برای یک قرارداد خزانهٔ قابل ارتقا که میلیونها دلار نگه میدارد، برنامهٔ توسعه و استقرار امن بنویسید. به مقداردهی، الگوی ارتقا، اختیارات، آزمون، ممیزی و استقرار تدریجی بپردازید.
بعد از نوشتن، پاسخ خود را با این معیارها بسنجید
خودارزیابی: هر نکتهای را که پاسخ شما بهروشنی پوشش داده علامت بزنید.
🤖 دستیار آموزشی
دستیار آفلاین آکادمی: پاسخها فقط از متن درسها و واژگان همین آکادمی پیدا میشوند و منبع هر پاسخ نشان داده میشود. هوش مصنوعی مولد نیست، حدس نمیزند و هیچ سیگنال خرید و فروشی نمیدهد.
📎 منابع مطالعاتی
- Parity Technologies — A Postmortem on the Parity Multi-Sig Library Self-Destruct
- Solidified — Parity Hack: How It Happened, And Its Aftermath
🏁 معیار تسلط بر این درس: میتوانید قرارداد هوشمندی با کمترین اختیار و مقداردهی امن طراحی کنید، ثابتها را با فازینگ بیازمایید، یک باگ تاریخی را بازتولید و رفع کنید و برنامهٔ ممیزی و استقرار تدریجی بنویسید.