Different spot prices used during the comparison
The spot prices used during the comparison are different, which might result in the trade proceeding even if the pool is manipulated, leading to a loss of assets.\\n```\\nFile: BalancerComposableAuraVault.sol\\n    function _checkPriceAndCalculateValue() internal view override returns (uint256) {\\n        (uint256[] memory balances, uint256[] memory spotPrices) = SPOT_PRICE.getComposableSpotPrices(\\n            BALANCER_POOL_ID,\\n            address(BALANCER_POOL_TOKEN),\\n            PRIMARY_INDEX()\\n        );\\n\\n        // Spot prices are returned in native decimals, convert them all to POOL_PRECISION\\n        // as required in the _calculateLPTokenValue method.\\n        (/* */, uint8[] memory decimals) = TOKENS();\\n        for (uint256 i; i < spotPrices.length; i++) {\\n            spotPrices[i] = spotPrices[i] * POOL_PRECISION() / 10 ** decimals[i];\\n        }\\n\\n        return _calculateLPTokenValue(balances, spotPrices);\\n    }\\n```\\n\\nLine 91 above calls the `SPOT_PRICE.getComposableSpotPrices` function to fetch the spot prices. Within the function, it relies on the `StableMath._calcSpotPrice` function to compute the spot price. Per the comments of this function, `spot price of token Y in token X` and `spot price Y/X` means that the Y (base) / X (quote). Thus, secondary (base) / primary (quote).\\n```\\nFile: StableMath.sol\\n    /**\\n     * @dev Calculates the spot price of token Y in token X.\\n     */\\n    function _calcSpotPrice(\\n        uint256 amplificationParameter,\\n        uint256 invariant, \\n        uint256 balanceX,\\n        uint256 balanceY\\n    ) internal pure returns (uint256) {\\n        /**************************************************************************************************************\\n        //                                                                                                           //\\n        //                             2.a.x.y + a.y^2 + b.y                                                         //\\n        // spot price Y/X = - dx/dy = -----------------------                                                        //\\n        //                             2.a.x.y + a.x^2 + b.x                                                         //\\n        //                                                                                                           //\\n        // n = 2                                                                                                     //\\n        // a = amp param * n                                                                                         //\\n        // b = D + a.(S - D)                                                                                         //\\n        // D = invariant                                                                                             //\\n        // S = sum of balances but x,y = 0 since x  and y are the only tokens                                        //\\n        **************************************************************************************************************/\\n\\n        unchecked {\\n            uint256 a = (amplificationParameter * 2) / _AMP_PRECISION;\\n```\\n\\nThe above spot price will be used within the `_calculateLPTokenValue` function to compare with the oracle price to detect any potential pool manipulation. However, the oracle price returned is in primary (base) / secondary (quote) format. As such, the comparison between the spot price (secondary-base/primary-quote) and oracle price (primary-base/secondary-quote) will be incorrect.\\n```\\nFile: SingleSidedLPVaultBase.sol\\n    function _calculateLPTokenValue(\\n..SNIP..\\n                uint256 price = _getOraclePairPrice(primaryToken, address(tokens[i]));\\n\\n                // Check that the spot price and the oracle price are near each other. If this is\\n                // not true then we assume that the LP pool is being manipulated.\\n                uint256 lowerLimit = price * (Constants.VAULT_PERCENT_BASIS - limit) / Constants.VAULT_PERCENT_BASIS;\\n                uint256 upperLimit = price * (Constants.VAULT_PERCENT_BASIS + limit) / Constants.VAULT_PERCENT_BASIS;\\n                if (spotPrices[i] < lowerLimit || upperLimit < spotPrices[i]) {\\n                    revert Errors.InvalidPrice(price, spotPrices[i]);\\n                }\\n```\\n
Consider verifying if the comment of the `StableMath._calcSpotPrice` function is aligned with its implementation with the Balancer team.\\nIn addition, the `StableMath._calcSpotPrice` function is no longer used or found within the current version of Balancer's composable pool. Thus, there is no guarantee that the math within the `StableMath._calcSpotPrice` works with the current implementation. It is recommended to use the existing method in the current Composable Pool's StableMath, such as `_calcOutGivenIn` (ensure the fee is excluded) to compute the spot price.
If the spot price is incorrect, it might potentially fail to detect the pool has been manipulated or result in unintended reverts due to false positives. In the worst-case scenario, the trade proceeds to execute against the manipulated pool, leading to a loss of assets.
```\\nFile: BalancerComposableAuraVault.sol\\n    function _checkPriceAndCalculateValue() internal view override returns (uint256) {\\n        (uint256[] memory balances, uint256[] memory spotPrices) = SPOT_PRICE.getComposableSpotPrices(\\n            BALANCER_POOL_ID,\\n            address(BALANCER_POOL_TOKEN),\\n            PRIMARY_INDEX()\\n        );\\n\\n        // Spot prices are returned in native decimals, convert them all to POOL_PRECISION\\n        // as required in the _calculateLPTokenValue method.\\n        (/* */, uint8[] memory decimals) = TOKENS();\\n        for (uint256 i; i < spotPrices.length; i++) {\\n            spotPrices[i] = spotPrices[i] * POOL_PRECISION() / 10 ** decimals[i];\\n        }\\n\\n        return _calculateLPTokenValue(balances, spotPrices);\\n    }\\n```\\n