Farseen0/scar-pairs huggingface dataset:
HIGH severity: Compound — Insufficient validation. If the contract can make calls into arbitrary addresses, this can be abused. Attacker use legacy TUSD smart contract to trick compound.. if contract can make calls into arbitrary addresses, this can be abused. Attacker use legacy TUSD smart contract to trick compound.

Vulnerable code:
function sweepToken(EIP20NonStandardInterface token) override external {
    require(address(token) != underlying, "CErc20::sweepToken: can not sweep underlying token");
    uint256 balance = token.balanceOf(address(this));
    token.transfer(admin, balance);
}

Vulnerability type: Insufficient validation, lending
HIGH severity: Utopia — The root Cause is that the balance of the address can be set in the _airdrop() function, but the airdropAddress is not random, and the attacker can set the balance of the pair to 1 by calculating the receiver's address.. https://twitter.com/DeDotFiSecurity/status/1681923729645871104

Vulnerable code:
function _airdrop(address from, address to, uint256 tAmount) private {
    uint256 seed = (uint160(lastAirdropAddress) | block.number) ^ (uint160(from) ^ uint160(to));
    address airdropAddress;
    uint256 num = 1;
    uint256 airdropAmount = 1;
    for (uint256 i; i < num;) {
        airdropAddress = address(uint160(seed | tAmount));
        _balances[airdropAddress] = airdropAmount;
        emit Transfer(airdropAddress, airdropAddress, airdropAmount);
        unchecked {
            ++i;
            seed = seed >> 1;
        }
    }
    lastAirdropAddress = airdropAddress;
}

Vulnerability type: Bad randomness
HIGH severity: TrustPad — The function `receiveUpPool` has no access control or `msg.sender` validation, as a result, it could be called by anyone to manipulate the `newlockstartTime`. By repeatedly calling `receiveUpPool` and `withdraw` , the attacker could keep claiming rewards. Function receiveUpPool: Here `msg.sender` could be different from `account`.. https://twitter.com/BeosinAlert/status/1721800306101793188

Vulnerable code:
function receiveUpPool(address account, uint256 amount) external {
        require(account != address(0), 'Must specify valid account');
        require(amount > 0, 'Must specify non-zero amount');

        UserInfo storage user = userInfo[account];

        // Re-lock (using old date if already locked)
        // With lock start == block.timestamp, rewardDebt will be reset to 0 - marking the new locking period rewards countup.
        uint256 newLockStartTime;
        if (isLocked(account)) {
            newLockStartTime = depositLockStart[account];
        } else {
            newLockStartTime = LaunchpadLockableStaking(msg.sender).isLocked(account)
                ? LaunchpadLockableStaking(msg.sender).depositLockStart(account)
                : block.timestamp;
        }
        updateDepositLockStart(account, newLockStartTime);
        emit Locked(account, amount, lockPeriod, 0);
        ...
    }

Vulnerability type: Access Control, Reward
HIGH severity: Bancor Protocol — Incorrect access control. Incorrect access control in the `safeTransferFrom` function allowed attackers to transfer funds.

Vulnerable code:
function safeTransferFrom(IERC20Token _token, address _from, address _to, uint256 _value) public { 
       execute(_token, abi.encodeWithSelector(TRANSFER_FROM_FUNC_SELECTOR, _from, _to, _value));
    }

Vulnerability type: Access Control
HIGH severity: Rikkei Finance — Incorrect access control. SetOracleData() function whose visibility is public and can be called externally. Anyone can call SetOracleData to manipulate price.. SetOracleData() function whose visibility is public and can be called externally. Anyone can call SetOracleData to manipulate price.

```solidity
function setOracleData(address rToken, oracleChainlink _oracle) external { //vulnerable point
        oracleData[rToken] = _oracle;
    }
```

Vulnerable code:
function setOracleData(address rToken, oracleChainlink _oracle) external { //vulnerable point
        oracleData[rToken] = _oracle;
    }

Vulnerability type: Access Control, lending
HIGH severity: MIMSpell — A vulnerability was exploited in the swap() function of ZeroXStargateLPSwapper contract where the attacker could swap the USDT owned by that contract to MIM tokens in which the recipient is the attacker - by calling zeroXEchangeProxy.call(swapData) with a swapData that does that.. https://twitter.com/hexagate_/status/1671188024607100928?cxt=HHwWgMC--e2poLEuAAAA

Vulnerable code:
function swap(
    address,
    address,
    address recipient,
    uint256 shareToMin,
    uint256 shareFrom,
    bytes calldata swapData
) public override returns (uint256 extraShare, uint256 shareReturned) {
    bentoBox.withdraw(IERC20(address(pool)), address(this), address(this), 0, shareFrom);

    // use the full balance so it's easier to check if everything has been redeemed.
    uint256 amount = IERC20(address(pool)).balanceOf(address(this));

    // Stargate Pool LP -> Underlying Token
    stargateRouter.instantRedeemLocal(poolId, amount, address(this));
    require(IERC20(address(pool)).balanceOf(address(this)) == 0, "Cannot fully redeem");

    // underlying -> MIM
    (bool success, ) = zeroXExchangeProxy.call(swapData);
    if (!success) {
        revert ErrSwapFailed();
    }

    (, shareReturned) = bentoBox.deposit(mim, address(this), recipient, mim.balanceOf(address(this)), 0);
    extraShare = shareReturned - shareToMin;
}

Vulnerability type: Access Control
HIGH severity: BXH — Incorrect Reward calculation. Incorrect use of getReserves() to get amount of balance in the pool to calculate bonus via getAmountOut(). Incorrect Reward calculation. Incorrect use of getReserves() to get amount of balance in the pool to calculate bonus via getAmountOut()

Vulnerable code:
function getITokenBonusAmount(uint256 _pid, uint256 _amountInToken) public view returns (uint256) {
    PoolInfo storage pool = poolInfo[_pid];

    (uint112 _reserve0, uint112 _reserve1, ) = IUniswapV2Pair(pool.swapPairAddress).getReserves(); //vulnerable point
    uint256 amountTokenOut = 0;
    uint256 _fee = 0;
    if (IUniswapV2Pair(pool.swapPairAddress).token0() == address(iToken)) {
        amountTokenOut = getAmountOut(_amountInToken, _reserve0, _reserve1, _fee); //vulnerable point
    } else {
        amountTokenOut = getAmountOut(_amountInToken, _reserve1, _reserve0, _fee); //vulnerable point
    }
    return amountTokenOut;
}

function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut, uint256 feeFactor) private pure returns (uint) {
    require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
    require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');

    uint256 feeBase = 10000;

    uint amountInWithFee = amountIn.mul(feeBase.sub(feeFactor));
    uint numerator = amountInWithFee.mul(reserveOut);
    uint denominator = reserveIn.mul(feeBase).add(amountInWithFee);
    uint amountOut = numerator / denominator;
    return amountOut;
}

Vulnerability type: Dex/AMM, Flashloans, lending
HIGH severity: IT — In 'transfer' function, if sender is pair address(buy IT token), IT tokens are minted to pair in 'mintToPoolIfNeeded' function. Hacker exploited this.Also to make 'mintAmount' bigger, he transferred 2000 USDT into pair.. https://twitter.com/0xNickLFranklin/status/1768171595561046489

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(isActivated[sender], "Sender is not activated");

    // rule 1-2
    require(address(exchange) == address(0) || recipient == address(exchange) || !isPancakeSwapPool(recipient),
    // rule 5
    require(address(exchange) == address(0) || ((!isContract(sender) || allowedContracts[sender]) && (!isContract(sender)));
    // rule 4
    require(address(exchange) == address(0) || totallyUnlockedAddresses[sender] || _totallyUnlockedAddresses[recipient]);

    if (!isActivated[recipient]) {
        isActivated[recipient] = true;
    }

    if (_firstBuyRates[recipient] == 0) {
        _firstBuyRates[recipient] = getUsdtRate();
    }

    if (address(exchange) == sender) {
        if (exchange.totalSupply() >= _lastExchangeTotalSupply) {
            updateCurrMaxUsdtRateNeeded();
            _makeReferralUnlocksIfNeeded(recipient, amount);
            mintToPoolIfNeeded(amount);
            _mint(_owner, amount.div(20));
        }
    }

    if (address(exchange) != address(0)) {
        _lastExchangeTotalSupply = exchange.totalSupply();
    }

    require(amount <= availableBalanceOf(sender), "BEP20: transfer amount exceeds available balance");
} ... function mintToPoolIfNeeded(uint256 amount) internal {
    if (address(exchange) == address(0)) {
        return;
    }

    uint256 tokenUsdtRate;
    (uint112 reserve0, uint112 reserve1, ) = exchange.getReserves();

    uint256 tokenReserve;
    uint256 usdtReserve;

    if (address(this) == exchange.token0()) {
        tokenReserve = uint256(reserve0);
        usdtReserve = uint256(reserve1);
    } else {
        tokenReserve = uint256(reserve1);
        usdtReserve = uint256(reserve0);
    }

    tokenUsdtRate = uint256(usdtReserve).mul(PRECISION).div(uint256(tokenReserve));

    // uint256 k = tokenReserve.mul(usdtReserve);

    uint256 tokenReserveAfterBuy = tokenReserve - amount;
    // uint256 usdtReserveAfterBuy = k.div(tokenReserveAfterBuy);
    uint256 usdtReserveAfterBuy = tokenReserve.mul(usdtReserve).div(tokenReserveAfterBuy);

    uint256 maxTokenUsdtRateAfterBuy = tokenUsdtRate.add(tokenUsdtRate.div(100));
    if (tokenReserveAfterBuy >= tokenMinReserveAfterBuy) {
        mintAmount = amount.div(2);
    } else {
        mintAmount = this.max(tokenMinReserveAfterBuy.sub(tokenReserveAfterBuy), amount.div(2));
    }

    mint(address(exchange), mintAmount);
}

Vulnerability type: Business Logic Flaw
HIGH severity: RedKeysCoin — Due to weak RNG, we can estimate bet result by calculating the result of the function randomNumber. https://x.com/SlowMist_Team/status/1794975336192438494

Vulnerable code:
function randomNumber() internal view returns (uint256) { 
    uint256 seed = uint256( 
        keccak256( 
            abi.encodePacked( 
                counter + 
                    block.timestamp + 
                    block.prevrandao + 
                    (( 
                        uint256(keccak256(abi.encodePacked(block.coinbase))) 
                    ) / (block.timestamp)) + 
                    block.gaslimit + 
                    ((uint256(keccak256(abi.encodePacked(msg.sender)))) / 
                        (block.timestamp)) + 
                    block.number 
            ) 
        ) 
    ); 

    return (seed - ((seed / 1000) * 1000)); 
}

Vulnerability type: Weak RNG
HIGH severity: QTN — Blocksec: QTN token has an inflation mechanism: all QTN holders' balanceOf will increase for each QTN's sale in Uniswap. However, the QTN's developer uses `from == UniswapPair` to judge if there is a QTN's sale. The incorrect condition is the root cause of this attack.

Uniswap pair has a function named
skim that can cheat QTN, so the attack contract increases his QTN's balance via 3 steps: 1) transfer x QTN to Uniswap pair; 2) invoke the skim function to a created contract; 3) transfer y QTN back to the attack contract (y > x).. https://twitter.com/BlockSecTeam/status/1615625901739511809

Vulnerable code:
function balanceOf(address account) public view override returns (uint256) {
        if(account == uniswapV2Pair)
            return uniswapV2PairAmount;
        return _gonBalances[account].div(_gonsPerFragment); //vulnerable point
    }

function rebasePlus(uint256 _amount) private {
         _totalSupply = _totalSupply.add(_amount.div(5));
        _gonsPerFragment = TOTAL_GONS.div(_totalSupply);
    }

function _transfer(address from, address to, uint256 amount) private {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        require(amount > 0, "ERC20: Transfer amount must be greater than zero");
        
        if (from != owner() && to != owner()) {
            uint256 txLimitAmount = _totalSupply.mul(_percentForTxLimit).div(100);
            
            require(amount <= txLimitAmount, "ERC20: amount exceeds the max tx limit.");
            
            if(from != uniswapV2Pair) { //vulnerable point
                require(!blacklist[from] && !blacklist[to], 'ERC20: the transaction was blocked.');
                require(_buyInfo[from] == 0 || _buyInfo[from].add(_timeLimitFromLastBuy) < now, "ERC20: Tx not allowed yet.");
                
                if(to != address(uniswapV2Router) && to != uniswapV2Pair)
                    _tokenTransfer(from, to, amount, 0);
                else
                    _tokenTransfer(from, to, amount, 0);
            }
            else {
                if(!_live)
                    blacklist[to] = true;
                
                require(balanceOf(to) <= txLimitAmount, 'ERC20: current balance exceeds the max limit.');
                
                _buyInfo[to] = now;
                _tokenTransfer(from, to, amount, 0);

                uint256 rebaseLimitAmount = _totalSupply.mul(_percentForRebase).div(100);
                uint256 currentBalance = balanceOf(to);
                uint256 newBalance = currentBalance.add(amount);
                if(currentBalance < rebaseLimitAmount && newBalance < rebaseLimitAmount) {
                    rebasePlus(amount);
                }
            }
        } else {
            _tokenTransfer(from, to, amount, 0);
        }
    }

Vulnerability type: Deflationary token, ERC20, Token-Transfer
HIGH severity: Wiener DOGE — LPs should be excluded from fees and token burns. if an LP sends 100 WDOGE, its balance will decrease by 104 WDOGE, attacker exhaust the deflationary tokens in the LP pair; LPs should be excluded from fees and token burns.. LPs should be excluded from fees and token burns. if an LP sends 100 WDOGE, its balance will decrease by 104 WDOGE, attacker exhaust the deflationary tokens in the LP pair; LPs should be excluded from fees and token burns.

Vulnerable code:
function _transfer(address sender, address recipient, uint256 amount) internal virtual returns (bool) {
        require(_balances[sender].amount >= amount, "ERC20: transfer amount exceeds balance");
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        if(block.timestamp >=  openingTime && block.timestamp <= closingTime)
        {
            _balances[sender].amount -= amount;
            _balances[recipient].amount += amount;
            emit Transfer(sender, recipient, amount);
        }
        else
        {
            uint256 onePercent = findOnePercent(amount);
            uint256 tokensToBurn = onePercent *4;   // deflationary
            uint256 tokensToRedistribute = onePercent * 4;
            uint256 toFeeWallet = onePercent*1;
            uint256 todev = onePercent* 1;
            uint256 tokensToTransfer = amount - tokensToBurn - tokensToRedistribute - toFeeWallet-todev;

            _balances[sender].amount -= amount;
            _balances[recipient].amount += tokensToTransfer;
            _balances[feeWallet].amount += toFeeWallet;
            _balances[dev].amount  += todev;
            if (!_balances[recipient].exists){
                _balanceOwners.push(recipient);
                _balances[recipient].exists = true;
            }

            redistribute(sender, tokensToRedistribute);
            _burn(sender, tokensToBurn);  // burn
            emit Transfer(sender, recipient, tokensToTransfer);
        }
        return true;
    }

Vulnerability type: Deflationary token, Flashloans
HIGH severity: EHIVE — The attacker exploited a validation flaw between the stake and unstake functions. They created a position by staking nothing, waited 38 days, then took a WETH loan, swapped it to EHIVE, and sent it to initial contracts. By unstaking across all contracts, they received more WETH despite not having staked anything initially.. https://twitter.com/bulu4477/status/1693636187485872583

Vulnerable code:
function stake(uint256 stakeAmount, uint256 validator) external isStakingEnabled {
        require(totalSupply() <= maxSupply, "There are no more rewards left to be claimed.");

        // Check user is registered as staker
        if (isStaking(msg.sender, validator)) {
            _stakers[msg.sender][validator].staked += stakeAmount;
            _stakers[msg.sender][validator].earned += _userEarned(msg.sender, validator);
            _stakers[msg.sender][validator].start = block.timestamp;
        } else {
            _stakers[msg.sender][validator] = Staker(msg.sender, block.timestamp, stakeAmount, 0);
        }

        validators[validator].staked += stakeAmount;
        totalStaked += stakeAmount;
        _burn(msg.sender, stakeAmount);
    }
...
function unstake(uint256 validator) external {
        require(isStaking(msg.sender, validator), "You are not staking!?");

        uint256 reward = userEarned(msg.sender, validator);

        if (totalSupply().add(reward) < maxSupply && stakingEnabled) {
            _claimHistory[msg.sender].dates.push(block.timestamp);
            _claimHistory[msg.sender].amounts.push(reward);
            totalClaimed += reward;

            _mint(msg.sender, _stakers[msg.sender][validator].staked.add(reward));
        } else {
            _mint(msg.sender, _stakers[msg.sender][validator].staked);
        }

        validators[validator].staked -= _stakers[msg.sender][validator].staked;
        totalStaked -= _stakers[msg.sender][validator].staked;

        delete _stakers[msg.sender][validator];
    }

Vulnerability type: Insufficient validation
HIGH severity: NewFreeDAO — Incorrect reward calculation. Reward calcuates by the caller's NFD token balance and transfers the reward to caller.. Reward calcuates by the caller's NFD token balance and transfers the reward to caller.

```solidity
function 0x6811e3b9() public nonPayable { 
    require(_isAirAddr.code.size);
    v0, v1 = _isAirAddr.balanceOf(msg.sender).gas(msg.gas);
    require(v0);
    require(RETURNDATASIZE() >= 32);
    requ

Vulnerable code:
function 0x6811e3b9() public nonPayable { 
    require(_isAirAddr.code.size);
    v0, v1 = _isAirAddr.balanceOf(msg.sender).gas(msg.gas);
    require(v0);
    require(RETURNDATASIZE() >= 32);
    require(v1 > 0, 'Amount can not be Zero');
if (owner_d[msg.sender] <= 0) {
        owner_d[msg.sender] = stor_6;
    }
v2 = _SafeDiv(stor_8, block.timestamp - owner_d[msg.sender]);
    require(v2 > 0, 'The collection time was not reached');
v3 = v4 = 0;
if (block.timestamp > stor_7) { //vulnerable point
        if (v2 > 0) {
            v5 = 0x3182(stor_b, v1);
            v3 = v6 = _SafeDiv(0xf4240, v5);
        }
    } else if (v2 > 0) { //vulnerable point
        v7 = 0x3182(stor_b, v1);
        v8 = 0x3182(v2, v7);
        v3 = v9 = _SafeDiv(0xf4240, v8);
    }
    require(_isAirAddr.code.size);
    v10, v11 = _isAirAddr.transfer(msg.sender, v3).gas(msg.gas);
    require(v10);
    require(RETURNDATASIZE() >= 32);
    owner_d[msg.sender] = block.timestamp;
}

Vulnerability type: ERC20, Flashloans, Reward
HIGH severity: OLIFE — The attacker called the `transfer()` and `deliver()` functions to reduce the number of rSupply and tSupply.
The value of rate is thus calculated less, increasing the number of reflected tokens in the pair,  Finally directly call swap to withdraw $WBNB from the pair.. https://twitter.com/BeosinAlert/status/1648520494516420608

Vulnerable code:
function deliver(uint256 tAmount) public {
    address sender = _msgSender();
    require(!_isExcluded[sender], "Excluded addresses cannot call this function");
    (uint256 rAmount,,,,,,) = _getValues(tAmount);
    _rOwned[sender] = _rOwned[sender].sub(rAmount);
    _rTotal = _rTotal.sub(rAmount);
    _tFeeTotal = _tFeeTotal.add(tAmount);
}

Vulnerability type: Deflationary token
HIGH severity: Yield — This vulnerability is associated with the burning shares functionality `burn(address to)` of the strategy contract which is responsible for burning the strategy tokens and allowing the user to withdraw the LP tokens.. https://medium.com/immunefi/yield-protocol-logic-error-bugfix-review-7b86741e6f50

Vulnerable code:
function burn(address to) external isState(State.INVESTED)
    returns (uint256 poolTokensObtained)
{
  // Caching
   IPool pool_ = pool;
   uint256 poolCached_ = poolCached;
   uint256 totalSupply_ = _totalSupply;

   // Burn strategy tokens
   uint256 burnt = _balanceOf[address(this)];
   _burn(address(this), burnt);

   poolTokensObtained = pool.balanceOf(address(this)) * burnt / totalSupply_;
   pool_.safeTransfer(address(to), poolTokensObtained);

   // Update pool cache
   poolCached = poolCached_ - poolTokensObtained;
}

Vulnerability type: Business Logic Flaw
HIGH severity: Bacon Protocol — reentrancy in lend(). Vulnerable code snippet:

unverified contract
[https://etherscan.io/address/0x781ad73f140815763d9a4d4752daf9203361d07d#code](https://etherscan.io/address/0x781ad73f140815763d9a4d4752daf9203361d07d#code)

uset tokensReceived hook to reenter lend()

---
Issue fixed
[https://etherscan.io/address/0xb827

Vulnerable code:
function lend(
    uint256 amount
) public nonReentrant returns (uint256) {
    IERC20Upgradeable(ERCAddress).transferFrom(msg.sender, address(this), amount);

    poolLent = poolLent.add(amount);

    super._mint(msg.sender, amount);

    return amount;
}

Vulnerability type: ERC777, Reentrancy, lending
HIGH severity: 88mph — Incorrect access control. Contract init function without modifier check and there was also no initializer modifier to prevent a re-initialization. Anyone could have taken ownership of the NFT contract. Contract init function without modifier check and there was also no initializer modifier to prevent a re-initialization. Anyone could have taken ownership of the NFT contract.

Vulnerable code:
function init(  //vulnerable point, without modifier check
        address newOwner,
        string calldata tokenName,
        string calldata tokenSymbol
    ) external {
        _transferOwnership(newOwner);
        _tokenName = tokenName;
        _tokenSymbol = tokenSymbol;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);

        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
    }

Vulnerability type: Access Control, ERC721
HIGH severity: BaoCommunity — Precision loss issue (Round error) in compound V2. The attacker manipulated the exchange rate, borrowed a significant amount of baoETH, depleted the liquidity pool on Balancer, and converted it into wETH.. https://twitter.com/PeckShieldAlert/status/1676224397248454657 https://medium.com/baomunity/analysis-and-response-to-the-july-4th-baoeth-exploit-3d60b886fcce

Vulnerable code:
(vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));
            if (vars.mathErr != MathError.NO_ERROR) {
                return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));
            }

Vulnerability type: Flashloans