MEDIUM severity: The invariant calculation in the Balancer's Composable Pool codebase relies on the old version of th. The invariant calculation in the Balancer's Composable Pool codebase relies on the old version of the `StableMath._calculateInvariant` function, which allows the caller to specify whether the computation should round up or down via the `roundUp` parameter. This function is used to compute the spot p...

Vulnerable code:
```\nFile: StableMath.sol\n\nfunction _calculateInvariant(\n    uint256 amplificationParameter,\n    uint256[] memory balances,\n    bool roundUp\n) internal pure returns (uint256) {\n    unchecked {\n        uint256 sum = 0;\n        uint256 numTokens = balances.length;\n        for (uint256 i = 0; i < numTokens; i++) {\n            sum = sum.add(balances[i]);\n        }\n        if (sum == 0) {\n            return 0;\n        }\n\n        uint256 prevInvariant = 0;\n        uint256 invariant = sum;\n        uint256 ampTimesTotal = amplificationParameter * numTokens;\n\n        for (uint256 i = 0; i < 255; i++) {\n            uint256 P_D = balances[0] * numTokens;\n            for (uint256 j = 1; j < numTokens; j++) {\n                P_D = Math.div(Math.mul(Math.mul(P_D, balances[j]), numTokens), invariant, roundUp);\n            }\n            prevInvariant = invariant;\n            invariant = Math.div(\n                Math.mul(Math.mul(numTokens, invariant), invariant).add(\n                    Math.div(Math.mul(Math.mul(ampTimesTotal, sum), P_D), _AMP_PRECISION, roundUp)\n                ),\n                Math.mul(numTokens + 1, invariant).add(\n                    // No need to use checked arithmetic for the amp precision, the amp is guaranteed to be at least 1\n                    Math.div(Math.mul(ampTimesTotal - _AMP_PRECISION, P_D), _AMP_PRECISION,!roundUp)\n                ),\n                roundUp\n            );\n\n            if (invariant > prevInvariant) {\n                if (invariant - prevInvariant <= 1) {\n                    return invariant;\n                }\n            } else if (prevInvariant - invariant <= 1) {\n                return invariant;\n            }\n        }\n    }\n\n    revert CalculationDidNotConverge();\n}\n```\n```\nFile: BalancerSpotPrice.sol\n\nfunction _calculateStableMathSpotPrice(\n    uint256 ampParam,\n    uint256[] memory scalingFactors,\n    uint256[] memory balances,\n    uint256 scaledPrimary,\n    uint256 primaryIndex,\n    uint256 index2\n) internal pure returns (uint256 spotPrice) {\n    // Apply scale factors\n    uint256 secondary = balances[index2] * scalingFactors[index2] / BALANCER_PRECISION;\n\n    uint256 invariant = StableMath._calculateInvariant(\n        ampParam,\n        StableMath._balances(scaledPrimary, secondary),\n        true\n    );\n```\n```\nfunction _calculateInvariant(uint256 amplificationParameter, uint256[] memory balances)\n    internal\n    pure\n    returns (uint256) {\n    // invariant\n    // D = invariant\n    // D^(n+1)\n    // A = amplification coefficient\n    // A  n^n S + D = A D n^n + -----------\n    // S = sum of balances\n    // n^n P\n    // P = product of balances\n    // n = number of tokens\n\n    // Always round down, to match Vyper's arithmetic (which always truncates).\n    //..SNIP..\n```