HIGH severity: YIEDL — insufficient parameter validation. https://medium.com/neptune-mutual/taking-a-closer-look-at-the-yiedl-exploit-e31f04cea592 https://bscscan.com/address/0x4edda16ab4f4cc46b160abc42763ba63885862a4#code#F1#L296

Vulnerable code:
/* User Functions */
function redeem(uint256 sharesToRedeem, address receivingAsset, uint256 minTokensToReceive, bytes[] calldata dataList, bool useDiscount) external nonReentrant returns (uint256 tokensToReturn) { // <-- vulnerable point, dataList
  require(depositableAssets.contains(receivingAsset), "da");
  TxParams memory dp;
  (dp.aum, dp.assets, dp.prices, dp.usdValues) = _getAllocations(0);
  dp.nav = getNav();
  dp.nominalFinalAum = dp.aum - ((dp.nav * sharesToRedeem) / UNIT);
  require(dataList.length == dp.assets.length, "l");
  dp.totalSupply = totalSupply();
  uint256 rcvTokenAccumulator = ((receivingAsset == NATIVE_TOKEN ? address(this).balance : ERC20(receivingAsset).balanceOf(address(this))) * sharesToRedeem) / dp.totalSupply;

  for (uint256 i = 0; i < dp.assets.length; i++) {
    if (dp.assets[i] == receivingAsset) {
      continue;
    }
    uint256 rcvTokenSize = receivingAsset == NATIVE_TOKEN ? address(this).balance : ERC20(receivingAsset).balanceOf(address(this));

    if (dp.assets[i] != NATIVE_TOKEN) {
      ONE_INCH_AGG_ROUTER.functionCall(dataList[i]);
    } else {
      uint256 sizeToSwap = (address(this).balance * sharesToRedeem) / dp.totalSupply;
      ONE_INCH_AGG_ROUTER.functionCallWithValue(dataList[i], sizeToSwap);
    }

    rcvTokenAccumulator += receivingAsset == NATIVE_TOKEN ? address(this).balance - rcvTokenSize : ERC20(receivingAsset).balanceOf(address(this)) - rcvTokenSize;
  }
  _burn(msg.sender, sharesToRedeem);

  uint256 feePortion = (rcvTokenAccumulator * feePercentages[FeeType.REDEEM]) / UNIT;
  dp.feeRecipient = feeRecipient;
  if (useDiscount) {
    (uint256 discountTokensToSpend, uint256 discountMultiplier) = discountPolicy.computeDiscountTokensToSpend(_getUsdValue(receivingAsset, feePortion));
    ERC20(discountPolicy.discountToken()).safeTransferFrom(msg.sender, dp.feeRecipient, discountTokensToSpend);
    feePortion = (feePortion * discountMultiplier) / (10 ** discountPolicy.decimals());
    emit FeeCollected(discountPolicy.discountToken(), discountTokensToSpend);
  }

  tokensToReturn = rcvTokenAccumulator - feePortion;
  require((tokensToReturn) >= minTokensToReceive, "s4");
  if (receivingAsset == NATIVE_TOKEN) {
    payable(msg.sender).sendValue(tokensToReturn);
  } else {
    ERC20(receivingAsset).safeTransfer(msg.sender, tokensToReturn);
  }

  if (feePortion > 0) {
    uint256 feeTokenAmount;
    dp.feeAsset = feeAsset;
    if (receivingAsset == dp.feeAsset) {
      feeTokenAmount = feePortion;
    } else {
      feeTokenAmount = _directSwapForFee(
        feePortion,
        0, // don't hinder redemptions due to low liquidity for the fee conversion.
        receivingAsset,
        dp.feeAsset
      );
    }

    ERC20(dp.feeAsset).safeTransfer(dp.feeRecipient, feeTokenAmount);
    emit FeeCollected(dp.feeAsset, feeTokenAmount);
  }

  require(absSlippage(dp.nav, getNav(), UNIT) <= slippageTolerances[SlippageType.NAV], "s3");
  _postSwapHandler(receivingAsset, dp);

  emit Transaction(false, msg.sender, receivingAsset, tokensToReturn, sharesToRedeem);
}

Vulnerability type: Insufficient validation