Scaling factor of the wrapped token is incorrect
The scaling factor of the wrapped token within the Boosted3Token leverage vault is incorrect. Thus, all the computations within the leverage vault will be incorrect. This leads to an array of issues such as users being liquidated prematurely or users being able to borrow more than they are allowed to.\\nIn Line 120, it calls the `getScalingFactors` function of the LinearPool to fetch the scaling factors of the LinearPool.\\nIn Line 123, it computes the final scaling factor of the wrapped token by multiplying the main token's decimal scaling factor with the wrapped token rate, which is incorrect.\\n```\\nFile: Boosted3TokenPoolMixin.sol\\n    function _underlyingPoolContext(ILinearPool underlyingPool) private view returns (UnderlyingPoolContext memory) {\\n        (uint256 lowerTarget, uint256 upperTarget) = underlyingPool.getTargets();\\n        uint256 mainIndex = underlyingPool.getMainIndex();\\n        uint256 wrappedIndex = underlyingPool.getWrappedIndex();\\n\\n        (\\n            /* address[] memory tokens */,\\n            uint256[] memory underlyingBalances,\\n            /* uint256 lastChangeBlock */\\n        ) = Deployments.BALANCER_VAULT.getPoolTokens(underlyingPool.getPoolId());\\n\\n        uint256[] memory underlyingScalingFactors = underlyingPool.getScalingFactors();\\n        // The wrapped token's scaling factor is not constant, but increases over time as the wrapped token increases in\\n        // value.\\n        uint256 wrappedScaleFactor = underlyingScalingFactors[mainIndex] * underlyingPool.getWrappedTokenRate() /\\n            BalancerConstants.BALANCER_PRECISION;\\n\\n        return UnderlyingPoolContext({\\n            mainScaleFactor: underlyingScalingFactors[mainIndex],\\n            mainBalance: underlyingBalances[mainIndex],\\n            wrappedScaleFactor: wrappedScaleFactor,\\n            wrappedBalance: underlyingBalances[wrappedIndex],\\n            virtualSupply: underlyingPool.getVirtualSupply(),\\n            fee: underlyingPool.getSwapFeePercentage(),\\n            lowerTarget: lowerTarget,\\n            upperTarget: upperTarget    \\n        });\\n    }\\n```\\n\\nThe correct way of calculating the final scaling factor of the wrapped token is to multiply the wrapped token's decimal scaling factor by the wrapped token rate as shown below:\\n```\\nscalingFactors[_wrappedIndex] = _scalingFactorWrappedToken.mulDown(_getWrappedTokenRate());\\n```\\n\\nThe `_scalingFactorWrappedToken` is the scaling factor that, when multiplied to a token amount, normalizes its balance as if it had 18 decimals. The `_getWrappedTokenRate` function returns the wrapped token rate.\\nIt is important to note that the decimal scaling factor of the main and wrapped tokens are not always the same. Thus, they cannot be used interchangeably.\\n```\\n    // Scaling factors\\n\\n    function _scalingFactor(IERC20 token) internal view virtual returns (uint256) {\\n        if (token == _mainToken) {\\n            return _scalingFactorMainToken;\\n        } else if (token == _wrappedToken) {\\n            // The wrapped token's scaling factor is not constant, but increases over time as the wrapped token\\n            // increases in value.\\n            return _scalingFactorWrappedToken.mulDown(_getWrappedTokenRate());\\n        } else if (token == this) {\\n            return FixedPoint.ONE;\\n        } else {\\n            _revert(Errors.INVALID_TOKEN);\\n        }\\n    }\\n\\n    /**\\n     * @notice Return the scaling factors for all tokens, including the BPT.\\n     */\\n    function getScalingFactors() public view virtual override returns (uint256[] memory) {\\n        uint256[] memory scalingFactors = new uint256[](_TOTAL_TOKENS);\\n\\n        // The wrapped token's scaling factor is not constant, but increases over time as the wrapped token increases in\\n        // value.\\n        scalingFactors[_mainIndex] = _scalingFactorMainToken;\\n        scalingFactors[_wrappedIndex] = _scalingFactorWrappedToken.mulDown(_getWrappedTokenRate());\\n        scalingFactors[_BPT_INDEX] = FixedPoint.ONE;\\n\\n        return scalingFactors;\\n    }\\n```\\n
There is no need to manually calculate the final scaling factor of the wrapped token again within the code. This is because the wrapped token scaling factor returned by the `LinearPool.getScalingFactors()` function already includes the token rate. Refer to the Balancer's source code above for referen\\n```\\nfunction _underlyingPoolContext(ILinearPool underlyingPool) private view returns (UnderlyingPoolContext memory) {\\n    (uint256 lowerTarget, uint256 upperTarget) = underlyingPool.getTargets();\\n    uint256 mainIndex = underlyingPool.getMainIndex();\\n    uint256 wrappedIndex = underlyingPool.getWrappedIndex();\\n\\n    (\\n        /* address[] memory tokens */,\\n        uint256[] memory underlyingBalances,\\n        /* uint256 lastChangeBlock */\\n    ) = Deployments.BALANCER_VAULT.getPoolTokens(underlyingPool.getPoolId());\\n\\n    uint256[] memory underlyingScalingFactors = underlyingPool.getScalingFactors();\\n// Remove the line below\\n   // The wrapped token's scaling factor is not constant, but increases over time as the wrapped token increases in\\n// Remove the line below\\n   // value.\\n// Remove the line below\\n   uint256 wrappedScaleFactor = underlyingScalingFactors[mainIndex] * underlyingPool.getWrappedTokenRate() /\\n// Remove the line below\\n       BalancerConstants.BALANCER_PRECISION;\\n\\n    return UnderlyingPoolContext({\\n        mainScaleFactor: underlyingScalingFactors[mainIndex],\\n        mainBalance: underlyingBalances[mainIndex],\\n// Remove the line below\\n       wrappedScaleFactor: wrappedScaleFactor,\\n// Add the line below\\n       wrappedScaleFactor: underlyingScalingFactors[wrappedIndex],        \\n        wrappedBalance: underlyingBalances[wrappedIndex],\\n        virtualSupply: underlyingPool.getVirtualSupply(),\\n        fee: underlyingPool.getSwapFeePercentage(),\\n        lowerTarget: lowerTarget,\\n        upperTarget: upperTarget    \\n    });\\n}\\n```\\n
Within the Boosted 3 leverage vault, the balances are scaled before passing them to the stable math function for computation since the stable math function only works with balances that have been normalized to 18 decimals. If the scaling factor is incorrect, all the computations within the leverage vault will be incorrect, which affects almost all the vault functions.\\nFor instance, the `Boosted3TokenAuraVault.convertStrategyToUnderlying` function relies on the wrapped scaling factor for its computation under the hood. This function is utilized by Notional's `VaultConfiguration.calculateCollateralRatio` function to determine the value of the vault share when computing the collateral ratio. If the underlying result is wrong, the collateral ratio will be wrong too, and this leads to an array of issues such as users being liquidated prematurely or users being able to borrow more than they are allowed to.
```\\nFile: Boosted3TokenPoolMixin.sol\\n    function _underlyingPoolContext(ILinearPool underlyingPool) private view returns (UnderlyingPoolContext memory) {\\n        (uint256 lowerTarget, uint256 upperTarget) = underlyingPool.getTargets();\\n        uint256 mainIndex = underlyingPool.getMainIndex();\\n        uint256 wrappedIndex = underlyingPool.getWrappedIndex();\\n\\n        (\\n            /* address[] memory tokens */,\\n            uint256[] memory underlyingBalances,\\n            /* uint256 lastChangeBlock */\\n        ) = Deployments.BALANCER_VAULT.getPoolTokens(underlyingPool.getPoolId());\\n\\n        uint256[] memory underlyingScalingFactors = underlyingPool.getScalingFactors();\\n        // The wrapped token's scaling factor is not constant, but increases over time as the wrapped token increases in\\n        // value.\\n        uint256 wrappedScaleFactor = underlyingScalingFactors[mainIndex] * underlyingPool.getWrappedTokenRate() /\\n            BalancerConstants.BALANCER_PRECISION;\\n\\n        return UnderlyingPoolContext({\\n            mainScaleFactor: underlyingScalingFactors[mainIndex],\\n            mainBalance: underlyingBalances[mainIndex],\\n            wrappedScaleFactor: wrappedScaleFactor,\\n            wrappedBalance: underlyingBalances[wrappedIndex],\\n            virtualSupply: underlyingPool.getVirtualSupply(),\\n            fee: underlyingPool.getSwapFeePercentage(),\\n            lowerTarget: lowerTarget,\\n            upperTarget: upperTarget    \\n        });\\n    }\\n```\\n