ارسال اتر به آدرس دیگری در شبکه اتریوم شامل تماس با نهاد دریافت کننده می باشد. این تماس خارجی بنا به دلایل متعددی ممکن است دچار شکست شود. در صورتی که این آدرس دریافتکننده، در قالب یک قرارداد باشد، میتواند اقدام به پیاده سازی یک تابع بازگشتی کند که به سادگی و پس از فراخوانی می تواند یک استثنا ایجاد میکند. از دیگر دلایل خرابی این تماس، تمام شدن گس می باشد. یعنی زمانی که باید در یک فراخوانی تک تابعی، بسیاری از تماس های خارجی انجام شوند، این اتفاق رخ می دهد. برای مثال هنگام ارسال سود یک شرط به چند برنده رخ می دهد. بنابراین توسعهدهندگان باید از اصل ساده ی "عدم اعتماد به فراخوان های خارجی برای اجرای بدون خطا" پیروی کنند. البته این موضوع در اکثر مواقع مطرح نیست، زیرا در نهایت وظیفه ی خود گیرندگان است که از دریافت پول خود مطمئن شوند و در صورتی که نتوانند پول خود را دریافت کنند، فقط خودش ضرر می کند. در این مقاله قصد داریم به بررسی الگو Pull over Push در کریپتو بپردازیم.
الگو Pull over Push در کریپتو
در رابطه با الگو Pull over Push می توان گفت، هنگامی که یک آدرس از طریق روش انتقال، قادر به دریافت اتر نباشد ( برای مثال زمانی که تابع بازگشتی نیازمند به گس ارسال شده باشد.) و جایگاه بالاترین پیشنهاد را بگیرد، قرارداد در وضعیتی غیر قابل حل قرار خواهد گرفت. هر تلاش جدید برای ارائه پیشنهاد بیش از حد به بالاترین پیشنهاد فعلی، انتقال اتر در خط 10 و ایجاد استثنا را به دنبال خواهد داشت. به همین دلیل برای رهبر فعلی، پیشنهاد بیش از حد غیر ممکن می شود.
هنگام تلاش برای ارسال اتر به چندین گیرنده با یک فراخوانی تابع، مشکل بالقوه دیگری ایجاد می شود. یعنی فقط باید یکی از انتقالها ناموفق باشد، تا بتوان اقدام به بازگرداندن همه انتقالهایی کرد که قبلاً اتفاق افتادند و یا از اجرای انتقالهای زیر جلوگیری کند. یک تکنیک خاصی برای این که بتوان بر این محدودیت ها غلبه کرد، پیشنهاد شده است که اقدام به ایزوله کردن هر تماس خارجی و انتقال خطر شکست از قرارداد به کاربر می کند. از آن جایی که نقل و انتقالات جدا هستند، هیچ منطق قرارداد یا انتقال دیگری نباید متکی به اجرای موفقیت آمیز آن باشد.
قابل اجرا بودن
از الگو Pull over Push می توان در موقعیت های زیر استفاده کرد:
- مدیریت چندین انتقال اتر با یک فراخوانی تابع
- اجتناب از ریسک مربوط به انتقال اتر
- انگیزه ای برای کاربران وجود دارد که به تنهایی از پس برداشت اتر برآیند.
شرکت کنندگان و همکاری ها
الگو Pull over Push شامل سه شرکت کننده می باشد. در ابتدا، فرآیند به عنوان اولین شرکت کننده، توسط نهاد مسئول شروع انتقال (مثلاً خود قرارداد و یا صاحب یک قرارداد) آغاز می شود. سپس قرارداد هوشمند به عنوان دومین شرکت کننده، مسئول پیگیری همه ی مانده ها می شود. گیرنده نیز به عنوان سومین شرکتکننده، صرفاً از طریق تراکنش، وجوه خود را دریافت نمیکند، بلکه باید برای جدا کردن فرآیند از سایر منطقهای پرداخت و قرارداد، به صورت فعالانه درخواست برداشت کند.
پیاده سازی
الگو Pull over Push برای جداسازی همه تماسهای خارجی از یکدیگر و منطق قرارداد، ریسک مربوط به انتقال اتر را به کاربر منتقل میکند و همچنین این اجازه را به کاربران میدهد که بتوانند مقدار معینی را برداشت کنند که در غیر این صورت باید ارسال شود. نقشه برداری یکی از اجزای اصلی این پیاده سازی می باشد که پیگیری ترازهای معوق کاربران را بر عهده دارد. بنابراین به جای انجام یک انتقال واقعی اتر از قرارداد به گیرنده، تابعی که قادر است ورودی را به نقشه اضافه کند و واجد شرایط بودن کاربر برای برداشت مبلغ مشخص شده را بیان کند، فراخوان می شود.
مبلغ در صورتی به آدرس موجود اضافه می شود که نقشه قبلاً حاوی یک ورودی برای این آدرس باشد. کاربر در این صورت مسئول برداشت وجه با صدور یک تراکنش به روش برداشت قرارداد هوشمند است که برای به روزرسانی مانده قبل از انتقال واقعی اتر، از الگو تعاملات تأثیرات چک استفاده میکند.
نتایج استفاده از الگو Pull over Push
استفاده از الگو Pull over Push دارای مزایا و معایب متعددی می باشد. برای مثال الگو Pull over Push برای کاهش مشکلاتی که با Solidity هنگام ارسال اتر به وجود میآیند، (به ویژه زمانی که چندین انتقال به صورت همزمان انجام می شود) بسیار موثر است. در واقع یک انتقال ناموفق منجر به برگرداندن عملیات های موفق نمی شود، زیرا در این الگو جدا سازی عملکرد انتقال مستعد خطا صورت گرفته است. همچنین به دلیل استفاده از این الگو، اطمینان از دریافت اتر، بر عهده کاربر درخواست کننده می باشد.
از پیامدهای منفی این الگو نیز می توان به مراحل اضافی مورد نیاز برای انجام تراکنش ها اشاره کرد. تعامل با قراردادی که به جای پرداخت های فشاری، از کشش استفاده میکند، کاربران را ملزم میکند تا تراکنش درخواست کننده برداشت را که یک تراکنش اضافی است، ارسال کنند. در نتیجه نیازهای گس بیشتر و هزینه های تراکنش بالاتر را به دنبال دارد، همچنین آسیب بزرگی به تجربه کاربر وارد می شود. کاربران نباید با یک قرارداد هوشمند بیش از حد لازم تعامل داشته باشند زیرا کاربران، مخصوصا کاربران کم تجربه، در معرض اشتباه کردن هستند.
تنها در صورتی از این الگو باید استفاده شود که همه شرکت کنندگان برای برداشت وجوه، انگیزه قوی داشته باشند. برای مثال، طی گزارش یکی از صاحبان قرارداد هوشمند، بیش از 10% کاربران اقدام به برداشت وجوه خود از قرارداد در هفت روزی که به آنها داده شده، نکرده اند. در غیر این صورت، ممکن است کاربران اصلاً از قرارداد استفاده نکنند و یا یک رقیب را در نظر بگیرند. در صورتی که انصراف صرفاً ارزشی نداشته باشد و بسیار پیچیده باشد. می توان استفاده از الگو Pull over Push را به عنوان یک معامله بین راحتی و امنیت برای کاربران در نظر گرفت. قبل از اجرای این الگو، باید قابل مدیریت بودن کاهش تجربه کاربر را ارزیابی کرد و همچنین بررسی کرد که آیا ممکن است برای رد هر گونه آسیب پذیری، استفاده هوشمندانه از الگو انتقال امن اتر کافی باشد؟
کاربردهای شناخته شده
قرارداد PullPayment توسط OpenZeppelin، یکی از نمونههای رایج استفاده از الگو Pull over Push می باشد که به صورت کلی، قرارداد الگو را پیاده سازی می کند. در قرارداد BlockParty نیز که قراردادی برای مدیریت سپرده حضور و غیاب برای رویدادهای رایگان می باشد، می توان پیاده سازی تخصصی تری را یافت. کاربران تنها در صورتی سپرده خود را پس می گیرند که در رویدادی که در آن ثبت نام کرده اند، حضور داشته باشند. همچنین شرکت کنندگان می توانند درخواست انصراف را پس از اینکه صاحب قرارداد، از طریق تراکنش حاوی آدرس اتریوم، حضور آنها را تایید کرد، ارائه دهند.