همانطور که در مقدمه اشاره کردم ، هزینه های مبادله مکانیسم اصلی Uniswap است. ارائه دهندگان نقدینگی برای نقدینگی که ارائه می دهند باید پرداخت کنند ، در غیر این صورت فقط از آن در جایی دیگر استفاده می کنند. برای تشویق آنها ، معاملات در طی هر مبادله هزینه کمی پرداخت می کنند. این هزینه ها سپس بین کلیه ارائه دهندگان نقدینگی Pro Rata (متناسب با سهم آنها در نقدینگی کل استخر) توزیع می شود.
برای درک بهتر مکانیسم جمع آوری و توزیع هزینه ها ، ببینیم که چگونه آنها کار می کنند.
نحوه جمع آوری هزینه های مبادله #

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

علاوه بر اینکه می دانیم محدوده قیمت درگیر و از بین می رود ، ما همچنین می خواهیم پیگیری کنیم که هر محدوده قیمت در هر محدوده قیمت جمع می شود.
برای ساده تر کردن حسابداری ، UNISWAP V3 هزینه های جهانی تولید شده توسط 1 واحد نقدینگی را ردیابی می کند. هزینه های دامنه قیمت سپس بر اساس هزینه های جهانی محاسبه می شود: هزینه های جمع آوری شده در خارج از محدوده قیمت از هزینه های جهانی کم می شوند. هزینه های انباشته شده در خارج از محدوده قیمت هنگام عبور از کنه ، ردیابی می شوند (و کنه ها هنگام جابجایی قیمت از آن عبور می کنند ؛ هزینه ها در هنگام تعویض جمع می شوند). با این رویکرد ، ما نیازی به به روزرسانی هزینه های جمع آوری شده توسط هر موقعیت در هر مبادله نداریم - این اجازه می دهد تا گاز زیادی را ذخیره کرده و با استخرهای ارزان تر تعامل برقرار کنیم.
بیایید قبل از حرکت یک تصویر واضح داشته باشیم:
- هزینه ها توسط کاربرانی که نشانه ها را عوض می کنند پرداخت می شود. مقدار کمی از نشانه ورودی کم می شود و بر روی تعادل استخر جمع می شود.
- هر استخر دارای متغیرهای حالت FeegrowthGlobal0x128 و FeegrowthGlobal1x128 است که کل هزینه های انباشته شده در هر واحد نقدینگی را ردیابی می کند (یعنی مبلغ هزینه تقسیم بر نقدینگی استخر).
- توجه کنید که در این مرحله موقعیت های واقعی برای بهینه سازی مصرف گاز به روز نمی شوند.
- کنه ها ثبت هزینه های انباشته شده در خارج از آنها را نگه می دارند. هنگام افزودن موقعیت جدید و فعال کردن کنه (اضافه کردن نقدینگی به کنه که قبلاً خالی است) ، کنه ثبت می کند که میزان هزینه های خارج از آن چقدر جمع شده است (با توجه به کنوانسیون ، فرض می کنیم تمام هزینه ها در زیر کنه جمع شده اند).
- هر زمان که کنه فعال شود ، هزینه های جمع آوری شده در خارج از کنه به عنوان تفاوت بین هزینه های جهانی انباشته شده در خارج از کنه و هزینه های انباشته شده در خارج از کنه از آخرین باری که از آن عبور کرده است ، به روز می شوند.
- داشتن کنه هایی که می دانند چقدر هزینه در خارج از آنها جمع شده است ، به ما امکان می دهد تا میزان هزینه های موجود در یک موقعیت را محاسبه کنیم (موقعیت بین دو کنه است).
- دانستن اینکه چقدر هزینه در یک موقعیت جمع شده است ، به ما این امکان را می دهد تا سهام هزینه های ارائه دهندگان نقدینگی را محاسبه کنیم. اگر موقعیتی در مبادله دخیل نبود ، هزینه های صفر در آن جمع می شود و ارائه دهندگان نقدینگی که نقدینگی را در این محدوده فراهم می کنند ، هیچ سود از آن نخواهد داشت.
اکنون ، می بینیم که چگونه می توان هزینه های انباشته شده توسط یک موقعیت را محاسبه کرد (مرحله 6).
محاسبه موقعیت انباشته شده موقعیت #
برای محاسبه کل هزینه های جمع شده توسط یک موقعیت ، باید دو مورد را در نظر بگیریم: وقتی قیمت فعلی در موقعیت قرار دارد و چه زمانی خارج از موقعیت است. در هر دو مورد ، ما هزینه های جمع آوری شده در خارج از کنه های پایین و فوقانی موقعیت را از هزینه های جمع آوری شده در سطح جهان جمع می کنیم. با این حال ، ما بسته به قیمت فعلی آن هزینه ها را متفاوت محاسبه می کنیم.
هنگامی که قیمت فعلی در موقعیت قرار دارد ، ما هزینه هایی را که در این لحظه در خارج از کنه جمع آوری شده اند ، کم می کنیم:

هنگامی که قیمت فعلی خارج از موقعیت است ، باید قبل از تفریق آنها از هزینه های جمع آوری شده در سطح جهان ، هزینه های جمع آوری شده توسط کنه های بالا یا پایین را به روز کنیم. ما آنها را فقط برای محاسبات به روز می کنیم و آنها را در کنه ها بازنویسی نمی کنیم زیرا کنه ها عبور نمی کنند.
اینگونه است که هزینه های جمع آوری شده در خارج از تیک را به روز می کنیم:
هزینه های جمع آوری شده در خارج از کنه ($ f_ (i) $)) تفاوت بین هزینه های جمع آوری شده در سطح جهان ($ f_ $) و هزینه های جمع آوری شده در خارج از کنه هنگام عبور از آخرین بار است. ما هنگام عبور از کنه ، پیشخوان را دوباره تنظیم می کنیم.
برای محاسبه هزینه های جمع آوری شده در یک موقعیت:
اکنون ، هنگامی که قیمت فعلی بالاتر از کنه پایین است (یعنی موقعیت درگیر است) ، ما نیازی به به روزرسانی هزینه های جمع آوری شده در زیر کنه پایین نداریم و می توانیم آنها را از کنه پایین تر بگیریم. در مورد هزینه های جمع آوری شده در خارج از کنه فوقانی در صورت قیمت فعلی زیر کنه بالا ، همین مسئله نیز صادق است. در دو مورد دیگر ، ما باید هزینه های به روز شده را در نظر بگیریم:
- هنگام گرفتن هزینه های جمع آوری شده در زیر کنه پایین و قیمت فعلی نیز زیر کنه است (اخیراً تیک پایین از آن عبور نکرده است).
- هنگام گرفتن هزینه بالاتر از کنه فوقانی و قیمت فعلی نیز بالاتر از کنه است (تیک فوقانی اخیراً عبور نکرده است).
امیدوارم این همه خیلی گیج کننده نباشد. خوشبختانه ، ما اکنون همه چیز را برای شروع برنامه نویسی می دانیم!
جمع آوری هزینه های مبادله #
برای ساده نگه داشتن آن ، ما به صورت مرحله به مرحله به پایگاه کد خود اضافه خواهیم کرد. و ما با هزینه های مبادله شروع خواهیم کرد.
افزودن متغیرهای حالت مورد نیاز #
اولین کاری که ما باید انجام دهیم این است که پارامتر مبلغ هزینه را به استخر اضافه کنیم - هر استخر هزینه ثابت و تغییر ناپذیر پیکربندی شده در هنگام استقرار خواهد داشت. در فصل قبل ، ما قرارداد کارخانه ای را اضافه کردیم که استقرار استخرهای متحد و ساده شده است. یکی از پارامترهای استخر مورد نیاز فاصله تیک بود. اکنون ، ما می خواهیم آن را با مبلغ هزینه جایگزین کنیم و مبلغ هزینه را برای فاصله تیک تیک قرار می دهیم: هرچه مبلغ هزینه بیشتر باشد ، فاصله تیک بزرگتر است. این به گونه ای است که استخرهای نوسانات کم (موارد stablecoin) هزینه کمتری دارند.
بیایید کارخانه را به روز کنیم:
مبلغ هزینه صدمین نقطه پایه است. یعنی 1 واحد هزینه 0. 0001 ٪ ، 500 0. 05 ٪ و 3000 0. 3 ٪ است.
مرحله بعدی شروع جمع آوری هزینه ها در استخر است. برای این کار ، ما دو متغیر جمع کننده هزینه جهانی اضافه خواهیم کرد:
یکی با شاخص 0 هزینه های آهنگ جمع آوری شده در Token0 ، یکی با هزینه های شاخص 1 در Token1 جمع شده است.
جمع آوری هزینه ها #
اکنون باید SwapMath.computeswapstep را به روز کنیم - این جایی است که ما مبلغ مبادله را محاسبه می کنیم و این نیز جایی است که هزینه های مبادله را محاسبه و تفریق می کنیم. در عملکرد ، ما تمام وقایع amountremaining را با amountremaininglessfee جایگزین می کنیم:
بنابراین ، ما هزینه را از مقدار توکن ورودی کم می کنیم و مقدار خروجی را از مقدار ورودی کوچکتر محاسبه می کنیم.
عملکرد اکنون مبلغ هزینه جمع آوری شده در طول مرحله را نیز باز می گرداند - بسته به اینکه آیا حد بالایی دامنه به دست آمده یا خیر ، متفاوت است:
هنگامی که به این نتیجه نرسید ، دامنه قیمت فعلی نقدینگی کافی برای تحقق مبادله دارد ، بنابراین ما به سادگی تفاوت بین مبلغی را که برای تحقق و مبلغ واقعی برآورده شده باز می گردانیم. توجه کنید که AmountRemaininglessFee در اینجا دخیل نیست زیرا مبلغ نهایی واقعی به صورت مقدار محاسبه شده است (بر اساس نقدینگی موجود محاسبه می شود).
با رسیدن به قیمت هدف ، ما نمی توانیم هزینه های کل را از بین ببریم زیرا دامنه قیمت فعلی نقدینگی کافی برای تحقق مبادله ندارد. بنابراین ، مبلغ هزینه از مبلغی که دامنه قیمت فعلی برآورده شده است (مبلغین) کم می شود.
پس از بازگشت SwapMath.computeswapstep ، ما باید هزینه های انباشته شده توسط مبادله را به روز کنیم. توجه کنید که فقط یک متغیر برای ردیابی آنها وجود دارد زیرا ، هنگام خیره شدن به مبادله ، ما از قبل نشانه ورودی را می شناسیم (در حین مبادله ، هزینه ها در Token0 یا Token1 جمع آوری می شود ، نه هر دو آنها):
اینجاست که ما هزینه های جمع شده را با میزان نقدینگی برای توزیع هزینه های بعدی بین ارائه دهندگان نقدینگی به روشی عادلانه تنظیم می کنیم.
به روزرسانی ردیاب های هزینه در کنه #
در مرحله بعد ، اگر در حین مبادله عبور می کرد ، باید ردیاب های هزینه را به روز کنیم (عبور از کنه به این معنی که ما وارد محدوده قیمت جدید می شویم):
از آنجا که ما هنوز متغیرهای حالت FeeGrowthGlobal0x128/feegrowthglobal1x128 را در این لحظه به روز نکرده ایم ، ما از حالت عبور می کنیم. عملکرد متقابل همانطور که در بالا بحث کردیم ، ردیاب های هزینه را به روز می کند:
ما اولیه سازی متغیرهای Feegrowthoutside0x128/feegrowthoutside1x128 را اضافه نکرده ایم - ما این کار را در مرحله بعدی انجام خواهیم داد.
به روزرسانی ردیاب های هزینه جهانی #
و سرانجام ، پس از تحقق مبادله ، می توانیم ردیاب های جهانی هزینه را به روز کنیم:
مجدداً ، در طی مبادله ، فقط یکی از آنها به روز می شود زیرا هزینه ها از نشانه ورودی گرفته می شود ، که بسته به جهت مبادله ، یا از Token0 یا token1 است.
این برای مبادله است! اکنون می بینیم که هنگام اضافه شدن نقدینگی ، چه اتفاقی می افتد.
ردیابی هزینه در مدیریت موقعیت #
هنگام افزودن یا از بین بردن نقدینگی (ما هنوز دومی را اجرا نکرده ایم) ، ما همچنین باید هزینه های اولیه یا به روزرسانی را انجام دهیم. هزینه ها باید هر دو در کنه (هزینه های جمع آوری شده در خارج از کنه ها - متغیرهای Feegrowthoutoutside که اکنون اضافه کردیم) و موقعیت ها (هزینه های جمع آوری شده در داخل موقعیت ها) ردیابی شوند. در صورت وجود موقعیت ها ، ما همچنین باید مقدار نشانه های جمع آوری شده به عنوان هزینه را پیگیری و به روز کنیم - یا به عبارت دیگر ، هزینه های هر نقدینگی را به مبلغ نشانه تبدیل می کنیم. مورد دوم به گونه ای مورد نیاز است که وقتی یک ارائه دهنده نقدینگی نقدینگی را از بین می برد ، نشانه های اضافی را به عنوان هزینه مبادله جمع می کنند.
بیایید دوباره این کار را انجام دهیم.
اولیه سازی ردیاب های هزینه در کنه #
در عملکرد Tick. Update ، هر زمان که یک تیک شروع شود (اضافه کردن نقدینگی به کنه که قبلاً خالی است) ، ما ردیاب های هزینه آن را آغاز می کنیم. با این حال ، ما فقط این کار را می کنیم که کنه زیر قیمت فعلی باشد ، یعنی وقتی که در محدوده قیمت فعلی قرار دارد:
اگر در محدوده قیمت فعلی نباشد ، ردیاب های هزینه آن 0 خواهند بود و وقتی دفعه دیگر از کنه عبور می شود ، به روز می شوند (به عملکرد صلیبی که در بالا به روز کردیم مراجعه کنید).
به روزرسانی هزینه موقعیت و مبلغ توکن #
مرحله بعدی محاسبه هزینه ها و نشانه های انباشته شده توسط یک موقعیت است. از آنجا که یک موقعیت بین دو کنه است ، ما این مقادیر را با استفاده از ردیاب های هزینه ای که در مرحله قبل به کنه اضافه کرده ایم محاسبه می کنیم. عملکرد بعدی ممکن است کثیف به نظر برسد ، اما فرمول های دقیق قیمت محدوده قیمت را که قبلاً دیدیم پیاده سازی می کند:
در اینجا ، ما در حال محاسبه هزینه های جمع آوری شده بین دو کنه (در محدوده قیمت) هستیم. برای این کار ، ما ابتدا هزینه های انباشته شده در زیر کنه پایین و سپس هزینه های محاسبه شده در بالای کنه را محاسبه می کنیم. در پایان ، ما آن هزینه ها را از انباشته های جهانی جمع می کنیم. این فرمولی است که قبلاً دیدیم:
هنگام محاسبه هزینه های جمع آوری شده در بالا و زیر یک کنه ، ما بسته به اینکه دامنه قیمت درگیر باشد یا خیر ، این کار را متفاوت انجام می دهیم (آیا قیمت فعلی بین کنه های مرزی دامنه قیمت است). وقتی درگیر شد ، ما به سادگی از ردیاب هزینه های فعلی یک کنه استفاده می کنیم. هنگامی که درگیر نیست ، ما باید ردیاب های به روز شده از یک تیک را بگیریم - می توانید این محاسبات را در دو شاخه دیگر در کد فوق مشاهده کنید.
پس از پیدا کردن هزینه های انباشته شده در یک موقعیت ، ما آماده هستیم تا هزینه و ردیاب های مبلغ را به روز کنیم:
هنگام محاسبه نشانه های بدهکار ، هزینه های انباشته شده توسط موقعیت توسط نقدینگی را ضرب می کنیم - برعکس آنچه در هنگام تعویض انجام دادیم. در پایان ، ما ردیاب های هزینه را به روز می کنیم و مبلغ توکن را به موارد قبلی ردیابی می کنیم.
اکنون ، هر زمان که یک موقعیت اصلاح شود (در حین افزودن یا حذف نقدینگی) ، هزینه های جمع آوری شده توسط یک موقعیت را محاسبه می کنیم و موقعیت را به روز می کنیم:
از بین بردن نقدینگی #
ما اکنون آماده هستیم تا تنها ویژگی اصلی را که هنوز اجرا نکرده ایم - بازپرداخت نقدینگی اضافه کنیم. برخلاف Minting ، ما این عملکرد را سوزانده خواهیم کرد. این عملکردی است که به ارائه دهندگان نقدینگی اجازه می دهد کسری یا نقدینگی کامل را از موقعیتی که قبلاً نقدینگی به آن اضافه کرده بودند ، حذف کنند. علاوه بر آن ، این هزینه را نیز محاسبه می کند که ارائه دهندگان نقدینگی توکن ها واجد شرایط هستند. با این حال ، انتقال واقعی نشانه ها در یک عملکرد جداگانه انجام می شود - جمع آوری.
سوزش نقدینگی #
سوزش نقدینگی مخالف مینینگ است. طراحی و اجرای فعلی ما آن را به یک کار بدون دردسر تبدیل می کند: سوزش نقدینگی به سادگی با علامت منفی ذوب می شود. این مانند اضافه کردن مقدار منفی نقدینگی است.
برای اجرای سوختگی ، من نیاز به اصلاح کد و استخراج همه چیز مربوط به مدیریت موقعیت (به روزرسانی کنه و موقعیت و محاسبه مقدار نشانه) را در عملکرد _modifyposition ، که توسط عملکرد نعنا و سوختگی استفاده می شود.
در عملکرد سوختگی ، ابتدا یک موقعیت را به روز می کنیم و مقداری نقدینگی را از آن حذف می کنیم. سپس ، ما مقدار نشانه مدیون موقعیت را به روز می کنیم - اکنون آنها شامل مبلغ انباشته شده از طریق هزینه ها و همچنین مبالغی است که قبلاً به عنوان نقدینگی ارائه شده بودند. ما همچنین می توانیم این را به عنوان تبدیل نقدینگی موقعیت به مقادیر نشانه مدیون موقعیت ببینیم - این مبلغ دیگر به عنوان نقدینگی استفاده نمی شوند و با فراخوانی عملکرد جمع آوری می توانند آزادانه بازخرید شوند:
این عملکرد به سادگی نشانه ها را از استخر منتقل می کند و تضمین می کند که فقط می توان مبلغ معتبری را منتقل کرد (نمی توان بیش از آنچه که سوزانده شده + هزینه هایی را که به دست آوردند منتقل کنند).
همچنین راهی برای جمع آوری هزینه ها فقط بدون سوزاندن نقدینگی وجود دارد: 0 مقدار نقدینگی را بسوزانید و سپس با جمع آوری تماس بگیرید. در حین سوزاندن ، موقعیت به روز می شود و مقدار نشانه ای که بدهکار است نیز به روز می شود.
اخبار رمز ارزها...
ما را در سایت اخبار رمز ارزها دنبال می کنید
برچسب :
نویسنده : منیژه سلیمی
بازدید : <-PostHit->
تاريخ : جمعه
12 خرداد
1402 ساعت: 18:27