```\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); /// @dev invalid token index\n\n        /// Apply scale factors\n        uint256 scaledPrimaryBalance = primaryBalance * poolContext.primaryScaleFactor \n            / BalancerConstants.BALANCER_PRECISION;\n        uint256 scaledSecondaryBalance = secondaryBalance * poolContext.secondaryScaleFactor \n            / BalancerConstants.BALANCER_PRECISION;\n\n        /// @notice poolContext balances are always in BALANCER_PRECISION (1e18)\n        (uint256 balanceX, uint256 balanceY) = tokenIndex == 0 ?\n            (scaledPrimaryBalance, scaledSecondaryBalance) :\n            (scaledSecondaryBalance, scaledPrimaryBalance);\n\n        uint256 invariant = StableMath._calculateInvariant(\n            oracleContext.ampParam, StableMath._balances(balanceX, balanceY), true // round up\n        );\n\n        spotPrice = StableMath._calcSpotPrice({\n            amplificationParameter: oracleContext.ampParam,\n            invariant: invariant,\n            balanceX: balanceX, \n            balanceY: balanceY\n        });\n\n        /// Apply secondary scale factor in reverse\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