ارتقای قراردادهای هوشمند
آخرین ویرایش: @sipbikardi(opens in a new tab), ۲۴ مرداد ۱۴۰۲
قراردادهای هوشمند در اتریوم برنامههای خودکاری هستند که در ماشین مجازی اتریوم (EVM) اجرا میشوند. این برنامه ها از نظر طراحی تغییر ناپذیر هستند که از هرگونه بهروز رسانی منطق تجاری پس از پیادهسازی و استقرار قرارداد جلوگیری می کند.
در حالی که این تغییرناپذیری برای حداقل سازی اعتماد، عدم تمرکز و امنیت قراردادهای هوشمند ضروریاند، ممکن است در برخی موارد مشکلاتی ایجاد کنند. برای مثال، کد تغییرناپذیر باعث میشود تا اصلاح کد قرارداد هوشمندی که دارای نقص امنیتی است امکانناپذیر شود.
با این حال، افزایش تحقیقات در مورد بهبود قراردادهای هوشمند منجر به معرفی چندین الگوی ارتقاء شده است. این الگوهای ارتقاء به توسعه دهندگان این امکان را می دهد تا با قرار دادن منطق تجاری در قراردادهای مختلف، قراردادهای هوشمند را (در عین حفظ تغییر ناپذیری) ارتقا دهند.
پیشنیازها
شما باید درک خوبی از قراردادهای هوشمند، آناتومی قراردادهای هوشمند و ماشین مجازی اتریوم (EVM) داشته باشید. این راهنما همچنین فرض میکند که خوانندگان درک درستی از برنامهنویسی قراردادهای هوشمند دارند.
ارتقاء قرارداد هوشمند چیست؟
ارتقای قرارداد هوشمند شامل تغییر منطق تجاری یک قرارداد هوشمند و در عین حال حفظ وضعیت قرارداد است. واضح است که قابلیت ارتقا و تغییرپذیری یکسان نیستند، به خصوص در زمینه قراردادهای هوشمند.
شما هنوز نمی توانید یک برنامه مستقر شده را به آدرسی در شبکه اتریوم تغییر دهید. اما میتوانید کدی را که هنگام تعامل کاربران با یک قرارداد هوشمند اجرا میشود، تغییر دهید.
این کار از طریق روش های زیر قابل انجام است:
ایجاد چندین نسخه از یک قرارداد هوشمند و انتقال حالت (یعنی داده ها) از قرارداد قدیمی به نمونه جدیدی از قرارداد.
ایجاد قراردادهای جداگانه برای ذخیره کردن منطق تجاری و حالت.
استفاده از الگوهای پراکسی برای واگذاری فراخوانی های تابع از یک قرارداد پروکسی تغییرناپذیر به یک قرارداد منطقی قابل تغییر.
ایجاد یک قرارداد اصلی تغییر ناپذیر که با قراردادهای ماهواره ای انعطاف پذیر برای اجرای عملکردهای خاص ارتباط برقرار می کند و به آنها متکی است.
استفاده از الگوی الماس برای واگذاری فراخوانی های تابع از یک قرارداد پراکسی به قراردادهای منطقی.
مکانیسم ارتقا شماره 1: انتقال قرارداد
انتقال قرارداد مبتنی بر نسخه سازی است - ایده ایجاد و مدیریت حالت های منحصر به فرد یک نرم افزار. انتقال قرارداد شامل استقرار یک نمونه جدید از یک قرارداد هوشمند موجود و انتقال ذخیره و موجودی به قرارداد جدید است.
قراردادی که به تازگی مستقر شده است یک فضای ذخیره خالی خواهد داشت که به شما امکان می دهد داده ها را از قرارداد قدیمی بازیابی کنید و آن را در پیاده سازی جدید بنویسید. پس از آن، باید همه قراردادهایی را که با قرارداد قدیمی در تعامل بودند، بهروزرسانی کنید تا نشانی جدید را منعکس کنند.
آخرین مرحله در انتقال قرارداد متقاعد کردن کاربران برای تغییر استفاده از قرارداد جدید است. نسخه جدید قرارداد تعادل و آدرس های کاربر را حفظ می کند که تغییر ناپذیری را حفظ می کند. اگر این قرارداد مبتنی بر توکن است، همچنین باید با صرافیها تماس بگیرید تا قرارداد قدیمی را کنار بگذارید و از قرارداد جدید استفاده کنید.
انتقال قرارداد یک اقدام نسبتاً ساده و ایمن برای ارتقاء قراردادهای هوشمند بدون ایجاد اختلال در تعاملات کاربر است. با این حال، انتقال دستی ذخیره سازی و موجودی کاربر به قرارداد جدید زمان بر است و می تواند کارمزد گس زیادی را به همراه داشته باشد.
اطلاعات بیشتر در مورد انتقال قرارداد.(opens in a new tab)
مکانیسم ارتقاء شماره 2: جداسازی داده ها
روش دیگر برای ارتقای قراردادهای هوشمند، تفکیک منطق تجاری و ذخیره داده ها به قراردادهای جداگانه است. این بدان معنی است که کاربران با قرارداد منطقی تعامل دارند، در حالی که داده ها در قرارداد ذخیره سازی ذخیره می شوند.
قرارداد منطقی شامل کدی است که هنگام تعامل کاربران با برنامه اجرا می شود. همچنین آدرس قرارداد ذخیره سازی را نگه می دارد و برای دریافت و تنظیم داده ها با آن تعامل دارد.
در همین حال، قرارداد ذخیره سازی وضعیت مرتبط با قرارداد هوشمند، مانند موجودی ها و آدرس های کاربر را حفظ می کند. توجه داشته باشید که قرارداد ذخیره سازی متعلق به قرارداد منطقی است و با آدرس دومی در هنگام استقرار پیکربندی شده است. این امر از تماس قراردادهای غیرمجاز با قرارداد ذخیره سازی یا به روز رسانی داده های آن جلوگیری می کند.
بهطور پیشفرض، قرارداد ذخیرهسازی تغییر ناپذیر است، اما میتوانید قرارداد منطقی را که به آن اشاره میکند با یک پیادهسازی جدید جایگزین کنید. با این کار کدی که در EVM اجرا میشود، تغییر میکند، در حالی که فضای ذخیرهسازی و تعادل را دست نخورده نگه میدارد.
استفاده از این روش ارتقا مستلزم بروز رسانی آدرس قرارداد منطقی در قرارداد ذخیره سازی است. همچنین به دلایلی که قبلا توضیح داده شد، باید قرارداد منطقی جدید را با آدرس قرارداد ذخیره سازی پیکربندی کنید.
پیاده سازی الگوی جداسازی داده ها در مقایسه با انتقال قرارداد ساده تر است. با این حال، باید چندین قرارداد را مدیریت کنید و طرحهای مجوز پیچیده را برای محافظت از قراردادهای هوشمند در برابر ارتقاهای مخرب اجرا کنید.
مکانیسم ارتقاء شماره 3: الگوهای پراکسی
الگوی پراکسی همچنین از جداسازی داده ها برای حفظ منطق تجاری و داده ها در قراردادهای جداگانه استفاده می کند. با این حال، در یک الگوی پراکسی، قرارداد ذخیرهسازی (به نام پراکسی) قرارداد منطقی را در طول اجرای کد فراخوانی می کند. این روش برعکس روش جداسازی داده است، که در آن قرارداد منطقی قرارداد ذخیره سازی را فرامیخواند.
این چیزی است که در یک الگوی پراکسی اتفاق می افتد:
کاربران با قرارداد پراکسی تعامل دارند، که دادهها را ذخیره میکند، اما منطق تجاری را حفظ نمیکند.
قرارداد پراکسی آدرس قرارداد منطقی را ذخیره می کند و تمام فراخوانی های تابع را با استفاده از تابع
delegatecall
به قرارداد منطقی (که منطق تجاری را نگه می دارد) واگذار می کند.پس از ارسال فراخوانی به قرارداد منطقی، داده های برگشتی از قرارداد منطقی بازیابی شده و به کاربر بازگردانده می شود.
استفاده از الگوهای پراکسی نیاز به درک عملکرد delegatecall دارد. اساساً، delegatecall
یک کد عملیاتی است که به یک قرارداد اجازه میدهد قرارداد دیگری را فراخوانی کند، در حالی که اجرای کد واقعی در متن قرارداد فراخوانی اتفاق میافتد. مفهوم استفاده از delegatecall
در الگوهای پراکسی این است که قرارداد پراکسی در حافظه خود می خواند و می نویسد و منطق ذخیره شده در قرارداد منطقی را اجرا می کند که گویی در حال فراخوانی یک تابع داخلی است.
از اسناد سالیدیتی(opens in a new tab):
نوع خاصی از تماس پیام وجود دارد، به نام delegatecall که با فراخوانی پیام یکسان است، صرف نظر از این که کد در آدرس مورد نظر در متن (یعنی در آدرس) اجرا می شود قرارداد فراخوانی و
msg.sender
وmsg.value
مقادیر خود را تغییر نمی دهند. این بدان معناست که یک قرارداد می تواند به صورت پویا کد را از آدرسی متفاوت در زمان اجرا بارگیری کند. محل ذخیره، آدرس فعلی و موجودی همچنان به قرارداد فراخوانی استناد میکنند، فقط کد از آدرس فراخوانی گرفته میشود.
قرارداد پراکسی میداند که هر زمان که کاربر تابعی را فراخوانی میکند، delegatecall
را فراخوانی میکند زیرا یک تابع fallback
در آن تعبیه شده است. در برنامه نویسی سالیدیتی، تابع fallback(opens in a new tab) زمانی اجرا می شود که یک فراخوانی تابع با توابع مشخص شده در قرارداد مطابقت نداشته باشد.
برای کارکرد الگوی پراکسی نیاز به نوشتن یک تابع بازگشتی سفارشی است که مشخص میکند قرارداد پراکسی چگونه باید فراخوانیهای تابعی را که پشتیبانی نمیکند مدیریت کند. در این مورد، تابع fallback پراکسی برای شروع یک فراخوانی واگذاری و تغییر مسیر درخواست کاربر به اجرای قرارداد منطقی فعلی برنامه ریزی شده است.
قرارداد پراکسی به طور پیش فرض تغییر ناپذیر است، اما قراردادهای منطقی جدید با منطق تجاری به روز شده می توانند ایجاد شوند. در این صورت انجام ارتقاء به تغییر آدرس قرارداد منطقی اشاره شده در قرارداد پراکسی بستگی دارد.
با اشاره قرارداد پراکسی به یک قرارداد منطقی جدید، کد اجرا شده هنگام فراخوانی تابع قرارداد پراکسی تغییر می کند. این به ما امکان میدهد تا منطق قرارداد را بدون درخواست از کاربران برای تعامل با یک قرارداد جدید ارتقا دهیم.
الگوهای پراکسی روشی محبوب برای ارتقای قراردادهای هوشمند هستند زیرا مشکلات مربوط به انتقال قرارداد را از بین می برند. با این حال، استفاده از الگوهای پراکسی پیچیدهتر است و در صورت استفاده نادرست، میتواند نقصهای مهمی مانند برخورد انتخابگر تابع(opens in a new tab) ایجاد کند.
اطلاعات بیشتر در مورد الگوهای پراکسی(opens in a new tab).
مکانیسم ارتقاء شماره 4: الگوی استراتژی
این تکنیک تحت تأثیر الگوی استراتژی(opens in a new tab) است، که ایجاد برنامههای نرمافزاری را تشویق میکند که با برنامههای دیگر برای پیادهسازی ویژگیهای خاص ارتباط برقرار کنند. اعمال الگوی استراتژی برای توسعه اتریوم به معنای ساخت یک قرارداد هوشمند است که توابع قراردادهای دیگر را فراخوانی می کند.
قرارداد اصلی در این مورد حاوی منطق اصلی تجارت است، اما با سایر قراردادهای هوشمند ("قراردادهای ماهواره ای") برای اجرای عملکردهای خاص ارتباط برقرار می کند. این قرارداد اصلی همچنین آدرس هر قرارداد اقماری را ذخیره می کند و می تواند بین پیاده سازی های مختلف قرارداد اقماری جابجا شود.
می توانید یک قرارداد اقماری جدید بسازید و قرارداد اصلی را با آدرس جدید پیکربندی کنید. این به شما امکان میدهد استراتژیها (یعنی اجرای منطق جدید) را برای یک قرارداد هوشمند تغییر دهید.
اگرچه شبیه به الگوی پراکسی که قبلاً مورد بحث قرار گرفت، الگوی استراتژی متفاوت است زیرا قرارداد اصلی که کاربران با آن تعامل دارند، منطق تجاری را حفظ می کند. استفاده از این الگو به شما این فرصت را می دهد که تغییرات محدودی را در یک قرارداد هوشمند بدون تأثیر بر زیرساخت اصلی ایجاد کنید.
اشکال اصلی این است که این الگو بیشتر برای بهروزرسانیهای جزئی مفید است. همچنین، اگر قرارداد اصلی به خطر بیفتد (به عنوان مثال، از طریق هک)، نمی توانید از این روش ارتقا استفاده کنید.
مکانیسم ارتقاء شماره 5: الگوی الماس
الگوی الماس را می توان بهبود در الگوی پروکسی در نظر گرفت. الگوهای الماس با الگوهای پراکسی متفاوت هستند زیرا قرارداد پروکسی الماس می تواند فراخوانی های تابع را به بیش از یک قرارداد منطقی واگذار کند.
قراردادهای منطقی در الگوی الماس به عنوان فاست شناخته می شوند. برای اینکه الگوی الماس کار کند، باید در قرارداد پراکسی یک نقشه برداری ایجاد کنید که انتخابگرهای تابع(opens in a new tab) را به آدرسهای جنبههای مختلف نگاشت میکند.
هنگامی که یک کاربر یک تابع را فراخوانی می کند، قرارداد پراکسی نگاشت را بررسی می کند تا فاست مسئول اجرای آن تابع را پیدا کند. سپس delegatecall
را فراخوانی میکند (با استفاده از تابع fallback) و فراخوانی را به قرارداد منطقی مناسب هدایت میکند.
الگوی ارتقاء الماس دارای مزایایی نسبت به الگوهای ارتقاء پراکسی سنتی است:
این به شما امکان می دهد بخش کوچکی از قرارداد را بدون تغییر تمام کد ارتقا دهید. استفاده از الگوی پراکسی برای ارتقاء مستلزم ایجاد یک قرارداد منطقی کاملاً جدید است، حتی برای ارتقاهای جزئی.
همه قراردادهای هوشمند (از جمله قراردادهای منطقی مورد استفاده در الگوهای پراکسی) دارای محدودیت اندازه 24 کیلوبایت هستند که می تواند یک محدودیت باشد – به خصوص برای قراردادهای پیچیده که به عملکردهای بیشتری نیاز دارند. الگوی الماس حل این مشکل را با تقسیم توابع در چندین قرارداد منطقی آسان می کند.
الگوهای پراکسی یک رویکرد همه جانبه را برای کنترل های دسترسی اتخاذ می کنند. یک نهاد با دسترسی به توابع ارتقا میتواند قرارداد کل را تغییر دهد. اما الگوی الماس یک رویکرد مجوزهای مدولار را فعال می کند، که در آن می توانید موجودیت ها را به ارتقاء عملکردهای خاص در یک قرارداد هوشمند محدود کنید.
اطلاعات بیشتر در مورد الگوی الماس(opens in a new tab).
مزایا و معایب ارتقای قراردادهای هوشمند
نقاط مثبت | نقاط منفی |
---|---|
ارتقای قرارداد هوشمند میتواند رفع آسیبپذیریهای کشف شده در مرحله پس از استقرار را آسانتر کند. | ارتقای قراردادهای هوشمند، ایده تغییرناپذیری کد را که پیامدهایی برای تمرکززدایی و امنیت دارد، نفی میکند. |
توسعه دهندگان می توانند از ارتقاء منطقی برای افزودن ویژگی های جدید به برنامه های غیرمتمرکز استفاده کنند. | کاربران باید به توسعه دهندگان اعتماد کنند که قراردادهای هوشمند را خودسرانه تغییر ندهند. |
ارتقاء قراردادهای هوشمند می تواند ایمنی را برای کاربران نهایی بهبود بخشد زیرا باگ ها را می توان به سرعت برطرف کرد. | برنامه نویسی عملکرد ارتقاء به قراردادهای هوشمند لایه دیگری از پیچیدگی را اضافه می کند و احتمال نقص های مهم را افزایش می دهد. |
ارتقاء قرارداد به توسعه دهندگان فضای بیشتری برای آزمایش ویژگی های مختلف و بهبود دپ ها در طول زمان می دهد. | فرصت ارتقای قراردادهای هوشمند ممکن است توسعهدهندگان را تشویق کند پروژهها را سریعتر راهاندازی کنند بدون اینکه در مرحله توسعه دقت لازم را انجام دهند. |
کنترل دسترسی ناامن یا متمرکز شدن در قراردادهای هوشمند میتواند بهروزرسانیهای غیرمجاز را برای عوامل مخرب آسانتر کند. |
ملاحظات ارتقای قراردادهای هوشمند
برای جلوگیری از ارتقاء قراردادهای هوشمند غیرمجاز، به ویژه اگر از الگوهای پراکسی، الگوهای استراتژی یا جداسازی داده ها استفاده می شود، از مکانیسم های کنترل دسترسی/مجوز دسترسی ایمن استفاده کنید. یک مثال محدود کردن دسترسی به عملکرد ارتقاء است، طوری که فقط مالک قرارداد می تواند آن را فراخوانی کند.
ارتقای قراردادهای هوشمند یک فعالیت پیچیده است و برای جلوگیری از معرفی آسیبپذیریها نیاز به دقت بالایی دارد.
کاهش مفروضات اعتماد با تمرکززدایی از فرآیند اجرای ارتقاء. استراتژیهای احتمالی شامل استفاده از قرارداد کیف پول چند امضایی برای کنترل ارتقاء، یا الزام اعضای DAO برای رای دادن به تایید ارتقاء است.
از هزینه های مربوط به ارتقاء قراردادها آگاه باشید. به عنوان مثال، کپی کردن حالت (به عنوان مثال، موجودی کاربر) از یک قرارداد قدیمی به یک قرارداد جدید در طول انتقال قرارداد ممکن است به بیش از یک تراکنش نیاز داشته باشد، به این معنی که کارمزدهای گس بیشتر است.
برای محافظت از کاربران، قفل های زمانی را در نظر بگیرید. قفل زمانی به تاخیر اعمال شده در تغییرات یک سیستم اشاره دارد. قفلهای زمانی را میتوان با یک سیستم حاکمیت چند امضایی برای کنترل ارتقاها ترکیب کرد: اگر یک اقدام پیشنهادی به آستانه تأیید لازم برسد، تا زمانی که دوره تاخیر از پیش تعریفشده سپری نشود، اجرا نمیشود.
قفلهای زمانی به کاربران در صورت مخالفت با تغییر پیشنهادی (مثلاً ارتقاء منطقی یا طرحهای هزینه جدید) مدتی زمان میدهند تا از سیستم خارج شوند. بدون قفل زمانی، کاربران باید به توسعه دهندگان اعتماد کنند تا بدون اطلاع قبلی تغییرات دلخواه را در یک قرارداد هوشمند اعمال نکنند. اشکال در اینجا این است که قفل های زمانی توانایی اصلاح سریع آسیب پذیری ها را محدود می کنند.
منابع
پلاگین های ارتقاء OpenZeppelin - مجموعه ای از ابزارها برای استقرار و ایمنسازی قراردادهای هوشمند قابل ارتقا.
آموزشها
- به روز رسانی قراردادهای هوشمند | آموزش یوتیوب(opens in a new tab) از پاتریک کالینز
- آموزش انتقال قرارداد هوشمند اتریوم(opens in a new tab) توسط آستین گریفیث
- استفاده از الگوی پراکسی UUPS برای ارتقاء قراردادهای هوشمند(opens in a new tab) از Pranesh A.S
- آموزش Web3: نوشتن قرارداد هوشمند قابل ارتقا (پراکسی) با استفاده از OpenZeppelin(opens in a new tab) از fangjun.eth
بیشتر بخوانید
- حالت ارتقاهای قرارداد هوشمند(opens in a new tab) از سانتیاگو پالادینو
- روش های متعدد برای ارتقاء قرارداد هوشمند سالیدیتی(opens in a new tab) - وبلاگ Crypto Market Pool
- بیاموزید: ارتقای قراردادهای هوشمند(opens in a new tab) - در اسناد OpenZeppelin
- الگوهای پراکسی برای ارتقای قراردادهای سالیدیتی: شفاف در مقابل پروکسی های UUPS(opens in a new tab) از نوین ساهو
- ارتقاء الماس چگونه کار می کند(opens in a new tab) از نیک ماج