パンケーキフラッシュローン攻撃学習

コントラクト アドレス:
BunnyMinterV2: https://bscscan.com/address/0x819eea71d3f93bb604816f1797d4828c90219b5d#code
efh:
https://bscscan.com/address/0x73feaa1ee314f8c655e354234017be2193c9e24e#code
pancakePair : https://bscscan.com/address/0x16b9a82891338f9ba80e2d6970fdda79d1eb0dae#code
PancakeRouter: https://bscscan.com/address/0x10ED43C718714eb63d5aA57B78B54704E256024E#code tx
/ 0x88fcffc3256faac76cde4bbd0df6ea3603b1438a5a0409b2e2b91e7c2ba3371a bscscan.com/tx/0x897c2de73dd55d7701e1b69ffb3a17b0f4801ced88b0c75fe1551c5fcce6a979参考記事: PancakeBunny 攻撃イベント リプレイ分析 | ゼロ タイム テクノロジー: http://www.xilian.link/depth/75435.html




スローミスト: PancakeBunny ハック分析:
https://slowmist.medium.com/slowmist-pancakebunny-hack-analysis-4a708e284693


コントラクト BunnyMinterv2 の関数 mintForV2 は、performanceFee と valueInBNB を介して mint によって生成された金額を計算します。

		uint performanceFee = canMint() ? _minter.performanceFee(amount) : 0;        
        if (performanceFee > DUST) {
    
    
            _minter.mintForV2(address(_stakingToken), 0, performanceFee, msg.sender, depositTimestamp);
            amount = amount.sub(performanceFee);
        }
function mintForV2(address asset, uint _withdrawalFee, uint _performanceFee, address to, uint) external payable override onlyMinter {
    
    
        uint feeSum = _performanceFee.add(_withdrawalFee);  
        _transferAsset(asset, feeSum);
        if (asset == BUNNY) {
    
    
            IBEP20(BUNNY).safeTransfer(DEAD, feeSum);
            return;
        }
        uint bunnyBNBAmount = _zapAssetsToBunnyBNB(asset, feeSum, true);
        if (bunnyBNBAmount == 0) return;

        IBEP20(BUNNY_BNB).safeTransfer(BUNNY_POOL, bunnyBNBAmount);
        IStakingRewards(BUNNY_POOL).notifyRewardAmount(bunnyBNBAmount);

        (uint valueInBNB,) = priceCalculator.valueOfAsset(BUNNY_BNB, bunnyBNBAmount);
        uint contribution = valueInBNB.mul(_performanceFee).div(feeSum);
        uint mintBunny = amountBunnyToMint(contribution);
        if (mintBunny == 0) return;
        _mint(mintBunny, to);
    }

ただし、_zapAssetsToBunnyBNB関数によって返される bunnyBNBAmount の金額は、IBEP20(BUNNY_BNB).balanceOf(address(this)).sub(_initBunnyBNBAmount)操作後に操作前の残高を差し引いて計算されます。
同時に、removeLiquidity途中で操作があります。
removeLiquidity コードをもう一度見てください。

function removeLiquidity()
......
address pair = PancakeLibrary.pairFor(factory, tokenA, tokenB);
        IPancakePair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
        (uint amount0, uint amount1) = IPancakePair(pair).burn(to);
.............
 
------------
function burn(address to) external lock returns (uint amount0, uint amount1) {
    
    
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        address _token0 = token0;                                // gas savings
        address _token1 = token1;                                // gas savings
        uint balance0 = IERC20(_token0).balanceOf(address(this));
        uint balance1 = IERC20(_token1).balanceOf(address(this));
        uint liquidity = balanceOf[address(this)];
        bool feeOn = _mintFee(_reserve0, _reserve1);
        uint _totalSupply = totalSupply; 
        amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
        amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
        _burn(address(this), liquidity);
        _safeTransfer(_token0, to, amount0);
        _safeTransfer(_token1, to, amount1); 

burn が再度呼び出されると、現在のペアのすべての lptoken が焼き付けられ、対応するトークンがターゲット アドレスに送信されます。
事前にlptokenをペアで保存しておくと、関数が呼び出されると、_zapAssetsToBunnyBNBremoveLiquidity操作により、事前に預けられたlptokenもトークンに変換されてコントラクトに送り返され、大量のbnbとusdtが処理されます。契約に来ます。
zapInToken はこれらのトークンを bnb に変換し、(金額の半分を bnb に変換します。bnb の半分) を bunny:bnb プールに 1:1 の比率で入金し、プール内の bnb の数を増やします (価格に影響します)。 bunnyBNBAの金額_zapAssetsToBunnyBNBも異常に多いです。
zapInToken の運用により(uint valueInBNB,) = priceCalculator.valueOfAsset(BUNNY_BNB, bunnyBNBAmount);、valueInBNB の計算結果も非常に高くなります。
最終的に大量のバニートークンが生成されました。

おすすめ

転載: blog.csdn.net/Timmbe/article/details/123365321