Farseen0/scar-pairs huggingface dataset:
HIGH severity: RFB — Bad randomness. The attacker exploits this vulnerability by purchasing RFB tokens only when they are confident of winning. If their attempt fails, the function reverts, resulting in the attacker losing only the gas cost for the transaction. This strategy allows the attacker to optimize their attempts and minimize potential losses, making the system susceptible to manipulation.. https://twitter.com/BlockSecTeam/status/1599991294947778560 https://blog.solidityscan.com/roast-football-hack-analysis-e9316170c443 https://neptunemutual.com/blog/roast-football-lost-funds-through-exploited-reward-system/

Vulnerable code:
function randMod(address buyer, uint256 buyamount) internal returns (uint) {
    uint randnum = uint(keccak256(abi.encodePacked(block.number, block.timestamp, buyer, _balances[pair]))); // vulnerable point
    uint256 buyBNBamount = buyamount.div(10**_decimals).mul(getPrice());
    // increase nonce
    if (randnum % (10000 * luckyMultiplier) == 8888 && buyBNBamount > (0.1 ether)) {
        distributor.withdrawDistributor(buyer, 79);
        distributor.withdrawDistributor(marketingFeeReceiver, 9);
    } else if (randnum % (1000 * luckyMultiplier) == 888) {
        if (buyBNBamount.mul(100) > 10 ether) {
            buyBNBamount = 0.1 ether;
        }
        try distributor.withdrawPlazz(buyer, buyBNBamount.mul(100).mul(90).div(100)) {} catch {}
        try distributor.withdrawPlazz(marketingFeeReceiver, buyBNBamount.mul(100).mul(10).div(100)) {} catch {}
    } else if (randnum % (100 * luckyMultiplier) == 88) {
        if (buyBNBamount.mul(10) > 10 ether) {
            buyBNBamount = 1 ether;
        }
        try distributor.withdrawPlazz(buyer, buyBNBamount.mul(10).mul(90).div(100)) {} catch {}
        try distributor.withdrawPlazz(marketingFeeReceiver, buyBNBamount.mul(10).mul(10).div(100)) {} catch {}
    } else if (randnum % (10 * luckyMultiplier) == 8) {
        if (buyBNBamount > 10 ether) {
            buyBNBamount = 10 ether;
        }
        try distributor.withdrawPlazz(buyer, buyBNBamount.mul(90).div(100)) {} catch {}
        try distributor.withdrawPlazz(marketingFeeReceiver, buyBNBamount.mul(10).div(100)) {} catch {}
    }
    return randnum;
}

Vulnerability type: Bad randomness
HIGH severity: BEARNDAO — The attack exploited a bug in ConvertDustToEarned() and used a sandwich attack.
Relied on the current balance of the `wantToken` token. But the strategy contract is not supposed to hold a huge amount of dust tokens. The attacker the ALPACA/WBNB pool through large-valued swaps and invoked a call to the convertDustToEarned function, thereby artificially inflating the swap ratio of the tokens. The reverse swap allowed the attacker to perform a sandwich attack, letting them take away approximately $768,358 worth of assets as profits.. https://twitter.com/AnciliaInc/status/1732159377749180646

Vulnerable code:
function convertDustToEarned() public whenNotPaused {
    require(isAutoComp, "!isAutoComp");
    // Converts dust tokens into earned tokens, which will be reinvested on the next earn().

    // Converts token0 dust (if any) to earned tokens
    uint256 wantAmt = IERC20(wantAddress).balanceOf(address(this)); // <--vulnerable point 
    if (wantAddress != earnedAddress && wantAmt > 0) {
        IERC20(wantAddress).safeIncreaseAllowance(uniRouterAddress, wantAmt);

        // Swap all dust tokens to earned tokens
        IPancakeRouter02(uniRouterAddress).swapExactTokensForTokensSupportingFeeOnTransferTokens(wantAmt, 0, paths[wantAddress][earnedAddress], address(this), now + 60);
        emit ConvertDustToEarned(wantAddress, earnedAddress, wantAmt);
    }
}

Vulnerability type: Business Logic Flaw
HIGH severity: XSDWETHpool — The attacker executed a flash loan, borrowing a large amount of WETH. They swapped WETH to XSD and then swapped XSD back to WETH, transferring the required WETH back to the flash loan provider.. https://x.com/CertiKAlert/status/1706765042916450781

Vulnerable code:
function swapXSDForETH(uint amountOut, uint amountInMax) external override {
    require(!swap_paused, "Swaps have been paused");
    (uint reserveA, uint reserveB, ) = IXSDWETHpool(XSDWETH_pool_address).getReserves();
    uint amounts = BankXLibrary.quote(amountOut, reserveB, reserveA);
    require(amounts <= amountInMax, 'BankXRouter: EXCESSIVE_INPUT_AMOUNT');
    TransferHelper.safeTransferFrom(
        xsd_address, msg.sender, XSDWETH_pool_address, amountInMax
    );
    XSDWETHpool(XSDWETH_pool_address).swap(0, amountOut, address(this));
    // function will fail if conditions are not met
    // XSDWETHpool(XSDWETH_pool_address).flush();
    IWBNB(WETH).withdraw(amountOut);
    TransferHelper.safeTransferETH(msg.sender, amountOut);
    // burn xsd here 
    // value of xsd liquidity pool has to be greater than 20% of the total xsd value
    if (XSD.totalSupply() - CollateralPool(payable(collateral_pool_address)).collat_XSD() > amountOut / 10 && !pid_controller.bucket1()) {
        XSD.burnpoolXSD(amountInMax / 10);
    }
    refreshPID();
}

Vulnerability type: Flashloans
HIGH severity: PredyFinance — Reentrancy. https://predyfinance.medium.com/postmortem-report-on-the-details-of-the-events-of-may-14-2024-8690508c820b

Vulnerable code:
function trade(
        GlobalDataLibrary.GlobalData storage globalData,
        IPredyPool.TradeParams memory tradeParams,
        bytes memory settlementData
    ) external returns (IPredyPool.TradeResult memory tradeResult) { // <-- no reentrancy guard
        DataType.PairStatus storage pairStatus = globalData.pairs[tradeParams.pairId];

        // update interest growth
        ApplyInterestLib.applyInterestForToken(globalData.pairs, tradeParams.pairId);

        // update rebalance interest growth
        Perp.updateRebalanceInterestGrowth(pairStatus, pairStatus.sqrtAssetStatus);

        tradeResult = Trade.trade(globalData, tradeParams, settlementData);

        globalData.vaults[tradeParams.vaultId].margin +=
            tradeResult.fee + tradeResult.payoff.perpPayoff + tradeResult.payoff.sqrtPayoff;

        (tradeResult.minMargin,,, tradeResult.sqrtTwap) = PositionCalculator.calculateMinDeposit(
            pairStatus, globalData.vaults[tradeParams.vaultId], DataType.FeeAmount(0, 0)
        );

        // The caller deposits or withdraws margin from the callback that is called below.
        callTradeAfterCallback(globalData, tradeParams, tradeResult); // <-- vulnerable point

        // check vault safety
        tradeResult.minMargin =
            PositionCalculator.checkSafe(pairStatus, globalData.vaults[tradeParams.vaultId], DataType.FeeAmount(0, 0));

        emit PositionUpdated(
            tradeParams.vaultId,
            tradeParams.pairId,
            tradeParams.tradeAmount,
            tradeParams.tradeAmountSqrt,
            tradeResult.payoff,
            tradeResult.fee
        );
    }
    
    function callTradeAfterCallback(
        GlobalDataLibrary.GlobalData storage globalData,
        IPredyPool.TradeParams memory tradeParams,
        IPredyPool.TradeResult memory tradeResult
    ) internal {
        globalData.initializeLock(tradeParams.pairId);

        IHooks(msg.sender).predyTradeAfterCallback(tradeParams, tradeResult); // <-- vulnerable callback point

        (int256 marginAmountUpdate, int256 settledBaseAmount) = globalData.finalizeLock();

        if (settledBaseAmount != 0) {
            revert IPredyPool.BaseTokenNotSettled();
        }

        globalData.vaults[tradeParams.vaultId].margin += marginAmountUpdate;

        emit MarginUpdated(tradeParams.vaultId, marginAmountUpdate);
    }

Vulnerability type: Reentrancy
HIGH severity: GAIN — The root cause is the implement of $GAIN, the balance in transfer() is calculated by dividing `_gonsPerFragment` for normal account. But different when account is special. https://x.com/0xNickLFranklin/status/1760559768241160679

Vulnerable code:
uint256 gonAmount = amount.mul(_gonsPerFragment);
_gonBalances[sender] = _gonBalances[sender].sub(gonAmount);

uint256 gonAmountReceived = shouldTakeFee(sender) ? takeFee(sender, recipient, gonAmount) : gonAmount;
_gonBalances[recipient] = _gonBalances[recipient].add(gonAmountReceived);

if (keccak256(abi.encodePacked(_children_of_gainos[recipient])) != keccak256(abi.encodePacked(sideA)) &&
    keccak256(abi.encodePacked(_children_of_gainos[recipient])) != keccak256(abi.encodePacked(sideB))) {
    if (_rejoice == true) {
        _children_of_gainos[recipient] = sideA;
    } else {
        children_of_gainos[recipient] = sideB;
    }
} ... _totalSupply = INITIAL_FRAGMENTS_SUPPLY;
_gonBalances[treasuryReceiver] = TOTAL_GONS;
gonsPerFragment = TOTAL_GONS.div(_totalSupply);
_lastSnappedTime = block.timestamp;
autoSnap = false;

Vulnerability type: Deflationary token
HIGH severity: Conic Finance — Incorrect assumption about the address returned by the Curve element registry for ETH as the underlying for the Curve v2 pool.
Specifically, the Conic ETH Omnipool uses the `CurveHandlerV3` to check whether we are currently in a reentrant call. This check was only executed if the pool being interacted with contains ETH, which was checked by calling the `_isETH` method. Our assumption was that Curve v2 pools using ETH have the ETH address (`0xeee…eee`) as one of their coins. However, they instead have the WETH address. This led to `_isETH` returning false, and in turn, to the reentrancy guard of the rETH pool being bypassed.
After bypass the check, attacker can manipulate the price of rETH Curve LP Token.. https://twitter.com/BlockSecTeam/status/1682356244299010049 https://medium.com/@ConicFinance/post-mortem-eth-and-crvusd-omnipool-exploits-c9c7fa213a3d

Vulnerable code:
public override returns (uint256) {
    // Preparing Withdrawals
    require(lpToken.balanceOf(msg.sender) >= conicLpAmount, "insufficient balance");
    uint256 underlyingBalanceBefore = underlying.balanceOf(address(this));

    // Processing Withdrawals
    uint256 totalUnderlying;
    uint256 allocatedUnderlying;
    uint256[] memory allocatedPerPool = getTotalAndPerPoolUnderlying();
    uint256 underlyingToReceive = conicLpAmount.mulDown(_exchangeRate(totalUnderlying));
    if (underlyingBalanceBefore < underlyingToReceive) {
        int256 underlyingToWithdraw = underlyingToReceive - underlyingBalanceBefore;
        _withdrawFromCurve(allocatedUnderlying, allocatedPerPool, underlyingToWithdraw);
    }

    // Sending Underlying and burning LP Tokens
    uint256 underlyingWithdrawn = _min(
        underlying.balanceOf(address(this)),
        underlyingToReceive
    );
    require(underlyingWithdrawn >= minUnder$yingReceived, "too much slippage");
    ipToken.burn(msg.sender, conicLpAmount);
    underlying.safeTransfer(msg.sender, underlyingWithdrawn);
    _cachedTotalUnderlying = totalUnderlying - underlyingWithdrawn;
    _cacheUpdatedTimestamp = block.timestamp;
}

Vulnerability type: Reentrancy
HIGH severity: Beauty Chain — Arithmetic Overflow. The vulnerable code snippet shows an arithmetic overflow when calculating the total amount to be transferred. The line `uint256 amount = uint256(cnt) * _value;` multiplies the number of recipients (`cnt`) by the transfer value (`_value`). If `cnt` is large enough and `_value` is significant, the res

Vulnerable code:
function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
    uint cnt = _receivers.length;
    uint256 amount = uint256(cnt) * _value; // vulnerable point
    require(cnt > 0 && cnt <= 20);
    require(_value > 0 && balances[msg.sender] >= amount);

    balances[msg.sender] = balances[msg.sender].sub(amount);
    for (uint i = 0; i < cnt; i++) {
        balances[_receivers[i]] = balances[_receivers[i]].add(_value);
        Transfer(msg.sender, _receivers[i], _value);
    }
    return true;
}

Vulnerability type: ERC20, Under/Overflow
HIGH severity: 0vix — Incorrect use balanceOf.. https://twitter.com/BlockSecTeam/status/1651932529874853888 https://twitter.com/peckshield/status/1651923235603361793 https://twitter.com/Mudit__Gupta/status/1651958883634536448

Vulnerable code:
function totalGHST(address _user) public view returns (uint _totalGHST) {
    uint totalGHSTheld = GHST.balanceOf(_user);   // vulnerable point
    _totalGHST = totalGHSTheld + totalGHSTStaked + totalwapGHSTheld;
}

function convertVGHST(uint _share) public view returns (uint _ghst) {
    uint totalTokenLocked = totalGHST(address(this)); // vulnerable point
    _ghst = _share * totalTokenLocked / totalShares;
}

Vulnerability type: Donate, Oracle
HIGH severity: BelugaDex — In the `_withdrawFrom` function, the value `liabilityToBurn` is determined by the `asset.liability` and `asset.totalSupply`. However, the actual exchange/swap process is using the oracle as price feed. This introduces inconsistency for arbitrage. Attacker could deposit `USDT` token, swap them to `USDCE` using oracle price(however the `liability` is influenced), but during the withdraw process which uses asset liability, the attacker could get back more assets than the original deposit tokens.. https://twitter.com/AnciliaInc/status/1712676040471105870 https://twitter.com/CertiKAlert/status/1712707006979613097

Vulnerable code:
function _withdrawFrom(Asset asset, uint256 liquidity) private view returns (
        uint256 amount,
        uint256 liabilityToBurn,
        uint256 fee,
        bool enoughCash
    ) {
        liabilityToBurn = (asset.liability() * liquidity) / asset.totalSupply();
        require(liabilityToBurn > 0, 'INSUFFICIENT_LIQ_BURN');
        ...
    }

Vulnerability type: Price Manipulation
HIGH severity: GPU — self transfer. The root cause of the exploit was due to the _balance update logic, which did not properly account for transactions where the sender and recipient were the same. This allowed the attacker to manipulate their own token balance by performing self-transfers. During these self-transfers, the smart contract under the hood overwrote the sender's balance (_balances[sender]) with what should have been the recipient's balance (_balances[recipient]). Since the sender and recipient were the same, this resulted in artificially inflated balances without any real token inflow. By continuously initiating self-transfers, the attacker was able to repeatedly overwrite and increase their balance, leading to unauthorized token acquisition and a total loss of 32K USD.. https://blog.solidityscan.com/gpu-hack-analysis-bf11f7c00534

Vulnerable code:
function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");
        uint256 senderAmount = _balances[sender]; // <-- vulnerable point
        uint256 recipientAmount = _balances[recipient]; // <-- vulnerable point
        require(senderAmount >= amount, "ERC20: transfer amount exceeds balance");
        _balances[sender] = senderAmount.sub(amount);
        _balances[recipient] = recipientAmount.add(amount); // <-- vulnerable point
        emit Transfer(sender, recipient, amount);
    }

Vulnerability type: Business Logic Flaw
HIGH severity: Paraswap — When contract is handling of external callback functions, the contract allowed unauthorized redirection of funds.. https://medium.com/neptune-mutual/analysis-of-the-paraswap-exploit-1f97c604b4fe

Vulnerable code:
// Check if fromAddress is this contract
let fromAddress := calldataload(164)

switch eq(fromAddress, address())
// If fromAddress is this contract, execute transfer()
case 1 {
    // Prepare external call data
    ...
}
// If fromAddress is not this contract, execute transferFrom() or permitTransferFrom()
default {
    switch isPermit2
    ...
}

if eq(fromAddress, address())
// If fromAddress is this contract, execute transfer()
case 1 {
    ...
}
// If fromAddress is not this contract, execute transferFrom() or permitTransferFrom()
default {
    ...
}

Vulnerability type: Business Logic Flaw
HIGH severity: MonoX Finance — Insufficient validation. Due to to is controllable, attacker can remove anyone's liquidity. Attack can input tokenIn and tokenOut with same token because of without any validation. so attacker can perform multiple swap to manipulate the token price.. Insufficient validation. Due to to is controllable, attacker can remove anyone's liquidity. Attack can input tokenIn and tokenOut with same token because of without any validation. so attacker can perform multiple swap to manipulate the token price.

Vulnerable code:
// actually removes liquidity
function removeLiquidity(address _token, uint256 liquidity, address to, 
    uint256 minVcashOut, 
    uint256 minTokenOut) external returns(uint256 vcashOut, uint256 tokenOut) {
    (vcashOut, tokenOut) = _removeLiquidityHelper(_token, liquidity, to, minVcashOut, minTokenOut, false);
}
...
// swap from tokenIn to tokenOut with fixed tokenIn amount.
function swapIn(address tokenIn, address tokenOut, address from, address to,
    uint256 amountIn) internal lockToken(tokenIn) returns(uint256 amountOut) {
    ...
    // trading in
    if (tokenIn == address(vCash)) {
        vCash.burn(monoXPoolLocal, amountIn);
        // all fees go to the other side
        oneSideFeesInVcash = oneSideFeesInVcash.mul(2);
    } else {
        _updateTokenInfo(tokenIn, tokenInPrice, 0, tradeVcashValue.add(oneSideFeesInVcash), 0);
    }

    // trading out
    if (tokenOut == address(vCash)) {
        vCash.mint(to, amountOut);
    } else {
        if (to != monoXPoolLocal) {
            IMonoXPool(monoXPoolLocal).safeTransferERC20Token(tokenOut, to, amountOut);
        }
        _updateTokenInfo(tokenOut, tokenOutPrice, tradeVcashValue.add(oneSideFeesInVcash), 0, 
            to == monoXPoolLocal ? amountOut : 0);
    }
    // actually removes liquidity
    function _removeLiquidityHelper(address _token, uint256 liquidity, address to, 
        uint256 minVcashOut, 
        uint256 minTokenOut,
        bool isETH) lockToken(_token) internal returns(uint256 vcashOut, uint256 tokenOut) {
        require(tokenPoolStatus[_token] == 1, "MonoX:NO_TOKEN");
        PoolInfo memory pool = pools[_token];
        uint256 poolValue;
        uint256 liquidityIn;
        (poolValue, liquidityIn, vcashOut, tokenOut) = _removeLiquidity(_token, liquidity, to); // vulnerable point
        _mintFee(pool.pid, pool.lastPoolValue, poolValue);
        require(vcashOut >= minVcashOut, "MonoX:INSUFF_vCash");
        require(tokenOut >= minTokenOut, "MonoX:INSUFF_TOKEN");

        if (vcashOut > 0) {
            vCash.mint(to, vcashOut);
        }
        if (!isETH) {
            monoXPool.safeTransferERC20Token(_token, to, tokenOut);
        } else {
            monoXPool.withdrawWETH(tokenOut);
            monoXPool.safeTransferETH(to, tokenOut);
        }

        monoXPool.burn(to, pool.pid, liquidityIn);

        _syncPoolInfo(_token, 0, vcashOut);

        emit RemoveLiquidity(to, 
            pool.pid,
            _token,
            liquidityIn, 
            vcashOut, tokenOut, pool.price);
    }

Vulnerability type: Dex/AMM
HIGH severity: NUM — NUM token incompatible with the Multichain Router. The attacker took advantage of a vulnerability in the Multichain bridge Router contract by exploiting the lack of compatibility between the NUM token and the Router. **The NUM token did not implement the required permit()** function but had a fallback() function that could be exploited. To carry out the attack, the attacker created a fake token called anyToken, using NUM as the underlying token. They then deceived the Multichain Router by calling the anySwapOutUnderlyingWithPermit() function and providing the fake anyToken and a forged signature as parameters. Since the fallback function was present in NUM, the invocation of NUM.permit() succeeded. Subsequently, the attacker exchanged all the NUM tokens for approximately 13 Ether, making a profit from the attack. https://twitter.com/BlockSecTeam/status/1595346020237352960 https://medium.com/numbers-protocol/investigation-report-of-multi-chain-bridge-incident-d4773cb3e87b https://neptunemutual.com/blog/taking-a-closer-look-at-the-numbers-protocol-hack/

Vulnerable code:
function anySwapOutUnderlyingWithPermit(
    address from,
    address token,
    address to,
    uint amount,
    uint deadline,
    uint8 v,
    bytes32 r,
    bytes32 s,
    uint toChainID
) external {
    address _underlying = AnyswapV1ERC20(token).underlying();
    
    IERC20(_underlying).permit(from, address(this), amount, deadline, v, r, s);
    TransferHelper.safeTransferFrom(_underlying, from, token, amount);
    AnyswapV1ERC20(token).depositVault(amount, from);
    _anySwapOut(from, token, to, amount, toChainID);
}

Vulnerability type: CrossChain, ERC20, Token Incompatible
HIGH severity: LQDX — The problem lies in the `deposit` function where there is no check that the `account` should be `msg.sender`, thus `account`'s approval on the `zap` can be spent to buy tokens and add liquidity.. None

Vulnerable code:
function deposit(
    address account,
    address token,
    address tokenM,
    swapPath calldata path,
    address token0,
    address token1,
    uint256[3] calldata amount,
    uint256 basketId
) public payable returns (uint256) {
    address pair = ILiquidXv2Factory(factory).getPair(token0, token1);
    require(pair != address(0), "LiquidXv2Zap: no pair");

    // retAddLp 0, 1, 2
    // inAmount
    // token0Amount, token1Amount
    uint256[6] memory lvar;
    lvar[3] = msg.value;
    address inToken = token;
    if (token != address(0)) {
        lvar[3] = IERC20(token).balanceOf(address(this));
        IERC20(token).safeTransferFrom(account, address(this), amount[0]);
        lvar[3] = IERC20(token).balanceOf(address(this)) - lvar[3];
    } else {
        inToken = wrappedETH;
        IWETH(wrappedETH).deposit{value: lvar[3]}();
    }

    if (path.path.length > 0) {
        _approveTokenIfNeeded(inToken, swapPlus, lvar[3]);
        (, lvar[3]) = ISwapPlusv1(swapPlus).swap(inToken, lvar[3], tokenM, address(this), path.path);
        inToken = tokenM;
    }

    (lvar[4], lvar[5]) = _depositSwap(token0, token1, inToken, lvar[3]);
    (lvar[0], lvar[1], lvar[2]) = ILiquidXv2Router01(router).addLiquidity(token0, token1, lvar[4], lvar[5], amount[1], amount[2], address(this), block.timestamp);
    _refundReserveToken(account, token0, token1, lvar[4] - lvar[0], lvar[5] - lvar[1]);

    if (basketId == 0) {
        IERC20(pair).safeTransfer(account, lvar[2]);
    } else {
        _addBalance(account, pair, basketId, lvar[2]);
    }

    if (rewarder != address(0) && IRewarderv2(rewarder).getReward(account, pair) > 0) {
        IRewarderv2(rewarder).claim(account, pair);
    }

    emit Deposit(account, token0, token1, basketId, lvar[2]);
    return lvar[2];
}

Vulnerability type: Insufficient validation
HIGH severity: GFOX — Attacker can set merkleroot.. https://x.com/CertiKAlert/status/1788751142144401886

Vulnerable code:
// set the merkle root
bytes32 root = _merkleRoot(address(this), amount);
victim.setMerkleRoot(root);
// claim the GFOX
victim.claim(address(this), amount, new bytes32 );
...
v4 = stor_1_0_19.setMerkleRoot(keccak256(address(this), v3)).gas(msg.gas);

Vulnerability type: Access Control
HIGH severity: AffineDeFi — The contract's flashloan callback for Balancer only verified the caller but failed to validate user data from untrusted sources. This allowed attackers to exploit the function and steal collateral tokens by providing malicious inputs.. https://medium.com/neptune-mutual/how-was-affine-protocol-exploited-f4933c4035b4

Vulnerable code:
function _payDebtAndTransferCollateral(LidoLevV3 newStrategy) internal {
  // Pay debt in aave.
  uint256 debt = debtToken.balanceOf(address(this));
  AAVE.repay(address(WETH), debt, 2, address(this));

  // Transfer collateral (aTokens) to new Strategy.
  aToken.safeTransfer(address(newStrategy), aToken.balanceOf(address(this)));

  // Make the new strategy borrow exactly the same amount as this strategy originally had in debt.
  newStrategy.createAaveDebt(debt);
}

Vulnerability type: Insufficient validation