روشی برای جلوگیری از راگ پول (Rug Pull) ها!

راگ پول ها در DEX ها یا همان صرافی های غیر متمرکز گسترش چشمگیری پیدا کرده است، در قرارداد های هوشمند این صرافی ها روش هایی (methods) وجود دارد که با permit یا مجوز کار می کنند و همین permit ها که از استاندارد EIP-2612 استفاده می کنند راهی برای جلوگیری از راگ پول ها هستند اما چطور؟


صرافی های غیر متمرکز از اسمارت کانترکت های مختلفی برای انجام امور مختلفشان استفاده می کنند:

  • Factory Contracts
  • Router Contracts
  • LP-Tokens Contract
من در این مقاله از یونی سواپ برای توضیحاتم استفاده کردم اما به دلیل مشترک بودن سورس کد های آن با پنکیک سواپ و دیگر فورک های آن این توضیحات بر روی آن ها نیز صادق است.

هنگامی که می خواهید نقدینگی که در گذشته در یونی سواپ تأمین کرده اید را برداشت کنید با توجه به روش های موجود در کانترکت Router آن ملزم به استفاده از :

  • removeLiquidityWithPermit
  • removeLiquidityETHWithPermit

در سمت فرانت اند هستید که شامل 3 مرحله است :

تفاوت removeLiquidityWithPermit و removeLiquidityETHWithPermit در خارج کردن نقدینگی از استخر های ERC20-ERC20 و ERC20-ETH است.
  1. در ابتدا کاربر متقاضی یک مجوز را امضا می کند که به کانترکت Router این اجازه را می دهد که LP-Token ها را خرج کند (استفاده از permit استاندارد EIP-2612) سپس متود removeLiquidityETHWithPermit یا removeLiquidityWithPermit کانترکت Router را فراخوانی می کند.
  2. کانترکت Router مجوز گرفته شده از سوی متقاضی را در کانترکت LP-Tokens قرار می هد و امکان خرج کردن LP-Token ها را می گیرد.
  3. در این مرحله کانترکت Router میتواند LP-Token ها را از ولت متقاضی خارج کرده و توکن های موجود در استخر نقدینگی را آزاد و به ولت او ارسال کند.


function removeLiquidityETHWithPermit( 
address token, 
uint liquidity, 
uint amountTokenMin, 
uint amountETHMin, 
address to, 
uint deadline, 
bool approveMax, uint8 v, bytes32 r, bytes32 s   
 ) external virtual override returns (uint amountToken, uint amountETH) { address pair = UniswapV2Library.pairFor(factory, token, WETH); 
uint value = approveMax ? uint(-1) : liquidity; IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);       
(amountToken, amountETH) = removeLiquidityETH(token, liquidity, amountTokenMin, amountETHMin, to, deadline);   
}

استفاده از permit در سورس کد یونی سواپ


همانطور که گفته شد با در دست داشتن مجوزی که کاربر در اختیار کانترکت Router قرار می دهد امکان ثبت کردن آن در کانترکت LP-Tokens برای تمامی کسایی که آن مجوز را دارند وجود دارد و دقیقا کاربرد استفاده از EIP-2612 نیز همین است.

راهکاری که اینجا به وجود می آید این است که اگر بتوانید تراکنشی که در آن راگ پولر می خواهد تمامی نقدینگی را از کانترکت خارج کند را در ممپول (mempool) بیابید و مجوز (permit) را از آرگومان های ورودی توابع removeLiquidityETHWithPermit یا removeLiquidityWithPermit در قسمت داده های تراکنش خارج سازید، می توانید پیش از راگ پولر خودتان آن مجوز را در کانترکت LP-Tokens ثبت نمایید و جلوی خارج شدن نقدینگی توسط راگ پولر را بگیرید. اما چطور؟


دلیل تایید نشدن تراکنش راگ پولر بعد از انجام این کار بی اعتبار شدن مجوز ساخته شده توسط راگ پولر هست چرا که نانسی (nonce) که در ساخت مجوز توسط راگ پولر استفاده شده بود توسط شما در کانترکت ثبت و تکراری شده است و راگ پولر ملزم به از سر گیری تمامی مراحل فوق می شود.


تراکنش تایید نشده راگ پولر
تراکنش تایید نشده راگ پولر


بعد از این کار شما مدتی زمان خواهید داشت تا توکن هایتان را بفروشید و پولتان را از کانترکت خارج کنید.