MEDIUM severity: The vulnerability arises when a two-token vault comprises tokens with different decimals, leading to. The vulnerability arises when a two-token vault comprises tokens with different decimals, leading to the breakdown of several key functions. For instance, rewards cannot be reinvested, and the vault cannot be settled. The `Stable2TokenOracleMath._getSpotPrice` function, responsible for computing the...

Vulnerable code:
```\nFile: Stable2TokenOracleMath.sol\nlibrary Stable2TokenOracleMath {\n    using TypeConvert for int256;\n    using Stable2TokenOracleMath for StableOracleContext;\n\n    function _getSpotPrice(\n        StableOracleContext memory oracleContext, \n        TwoTokenPoolContext memory poolContext, \n        uint256 primaryBalance,\n        uint256 secondaryBalance,\n        uint256 tokenIndex\n    ) internal view returns (uint256 spotPrice) {\n        require(tokenIndex < 2);\n\n        uint256 scaledPrimaryBalance = primaryBalance * poolContext.primaryScaleFactor / BalancerConstants.BALANCER_PRECISION;\n        uint256 scaledSecondaryBalance = secondaryBalance * poolContext.secondaryScaleFactor / BalancerConstants.BALANCER_PRECISION;\n\n        (uint256 balanceX, uint256 balanceY) = tokenIndex == 0? \n            (scaledPrimaryBalance, scaledSecondaryBalance) : \n            (scaledSecondaryBalance, scaledPrimaryBalance);\n\n        uint256 invariant = StableMath._calculateInvariant(\n            oracleContext.ampParam, \n            StableMath._balances(balanceX, balanceY), \n            true\n        );\n\n        spotPrice = StableMath._calcSpotPrice({\n            amplificationParameter: oracleContext.ampParam, \n            invariant: invariant, \n            balanceX: balanceX, \n            balanceY: balanceY\n        });\n\n        uint256 scaleFactor = tokenIndex == 0? \n            poolContext.secondaryScaleFactor * BalancerConstants.BALANCER_PRECISION / poolContext.primaryScaleFactor : \n            poolContext.primaryScaleFactor * BalancerConstants.BALANCER_PRECISION / poolContext.secondaryScaleFactor;\n        spotPrice = spotPrice * BalancerConstants.BALANCER_PRECISION / scaleFactor;\n    }\n```\n```\nscaleFactor = poolContext.secondaryScaleFactor * BalancerConstants.BALANCER_PRECISION / poolContext.primaryScaleFactor\nscaleFactor = 1e30 * 1e18 / 1e18\nscaleFactor = 1e30\n```\n```\nspotPrice = spotPrice * BalancerConstants.BALANCER_PRECISION / scaleFactor;\nspotPrice = (1e18 * 1e18) / 1e30;\nspotPrice = 1e6\n```\n```\nscaleFactor = poolContext.secondaryScaleFactor * BalancerConstants.BALANCER_PRECISION / poolContext.primaryScaleFactor\nscaleFactor = 1e18 * 1e18 / 1e30\nscaleFactor = 1e6\n```\n```\nspotPrice = spotPrice * BalancerConstants.BALANCER_PRECISION / scaleFactor;\n\nspotPrice = (1e18 * 1e18) / 1e6\nspotPrice = 1e30\n```\n```\nuint256 oraclePrice = poolContext._getOraclePairPrice(strategyContext.tradingModule);\n```\n```\nFile: Stable2TokenOracleMath.sol\n\nfunction _getMinExitAmounts(\n    StableOracleContext calldata oracleContext,\n    TwoTokenPoolContext calldata poolContext,\n    StrategyContext calldata strategyContext,\n    uint256 oraclePrice,\n    uint256 bptAmount\n) internal view returns (uint256 minPrimary, uint256 minSecondary) {\n    oracle price is always specified in terms of primary, so tokenIndex == 0 for primary\n    uint256 spotPrice = _getSpotPrice({\n        oracleContext: oracleContext,\n        poolContext: poolContext,\n        primaryBalance: poolContext.primaryBalance,\n        secondaryBalance: poolContext.secondaryBalance,\n        tokenIndex: 0\n    });\n    _checkPriceLimit(strategyContext, oraclePrice, spotPrice);\n```