Loss of ETH yield due to rounding error when updating the yield rate in the `updateYield` function
Updating the vault's yield rate in the `LibVault.updateYield` function can lead to a loss of yield if the newly received ETH yield is small due to rounding errors.\\nThe `updateYield` function in the `LibVault` library is called by the permissionless `YieldFacet.updateYield` function and used to update the vault's yield rate from staking rewards earned by bridge contracts holding LSD.\\nThe newly accumulated yield, i.e., ETH received since the last update, is calculated by subtracting the current `zethTotalNew` from the previously stored yield `zethTotal`, as seen in line 75 of the `updateYield` function.\\ncontracts/libraries/LibVault.sol#L92\\n```\\nfunction updateYield(uint256 vault) internal {\\n    AppStorage storage s = appStorage();\\n    STypes.Vault storage Vault = s.vault[vault];\\n    STypes.VaultUser storage TAPP = s.vaultUser[vault][address(this)];\\n    // Retrieve vault variables\\n    uint88 zethTotalNew = uint88(getZethTotal(vault)); // @dev(safe-cast)\\n    uint88 zethTotal = Vault.zethTotal;\\n    uint88 zethCollateral = Vault.zethCollateral;\\n    uint88 zethTreasury = TAPP.ethEscrowed;\\n    // Calculate vault yield and overwrite previous total\\n    if (zethTotalNew <= zethTotal) return;\\n    uint88 yield = zethTotalNew - zethTotal;\\n    Vault.zethTotal = zethTotalNew;\\n    // If no short records, yield goes to treasury\\n    if (zethCollateral == 0) {\\n        TAPP.ethEscrowed += yield;\\n        return;\\n    }\\n    // Assign yield to zethTreasury\\n    uint88 zethTreasuryReward = yield.mul(zethTreasury).divU88(zethTotal);\\n    yield -= zethTreasuryReward;\\n    // Assign tithe of the remaining yield to treasuryF\\n    uint88 tithe = yield.mulU88(vault.zethTithePercent());\\n    yield -= tithe;\\n    // Realize assigned yields\\n    TAPP.ethEscrowed += zethTreasuryReward + tithe;\\n❌  Vault.zethYieldRate += yield.divU80(zethCollateral);\\n    Vault.zethCollateralReward += yield;\\n}\\n```\\n\\nAfter determining the new `yield` (ETH), a fraction of the `yield` is assigned to the TAPP (treasury). Thereafter, the remaining `yield` is realized by adding it to the vault's `yield` rate (zethYieldRate), which is calculated by dividing the `yield` by the vault's short collateral, `zethCollateral`.\\n[!NOTE] Both the `yield` and `zethCollateral` values are in 18 decimal precision due to tracking ETH balances.\\nBy using the `divU80` function, the `zethYieldRate` is calculated as $zethYieldRate = \\frac{yield \\cdot 10^{18}}{zethCollateral}$\\nHowever, if the numerator is smaller than the denominator, i.e., the received ETH yield is very small and the vault's collateral large enough, the result of the division will be rounded down to 0, leading to a loss of the remaining yield.\\nAs anyone is able to call the public `YieldFacet.updateYield` function, this can be used to maliciously cause a loss of yield for all users if the newly received yield is small.\\nThe following test case demonstrates the described rounding error:\\n
Consider storing the rounding error and applying the correcting factor (error stored) the next time, or alternatively, prevent (skip) updating the yield if the resulting yield is 0.
Loss of LSD ETH yield for users of the same vault.
```\\nfunction updateYield(uint256 vault) internal {\\n    AppStorage storage s = appStorage();\\n    STypes.Vault storage Vault = s.vault[vault];\\n    STypes.VaultUser storage TAPP = s.vaultUser[vault][address(this)];\\n    // Retrieve vault variables\\n    uint88 zethTotalNew = uint88(getZethTotal(vault)); // @dev(safe-cast)\\n    uint88 zethTotal = Vault.zethTotal;\\n    uint88 zethCollateral = Vault.zethCollateral;\\n    uint88 zethTreasury = TAPP.ethEscrowed;\\n    // Calculate vault yield and overwrite previous total\\n    if (zethTotalNew <= zethTotal) return;\\n    uint88 yield = zethTotalNew - zethTotal;\\n    Vault.zethTotal = zethTotalNew;\\n    // If no short records, yield goes to treasury\\n    if (zethCollateral == 0) {\\n        TAPP.ethEscrowed += yield;\\n        return;\\n    }\\n    // Assign yield to zethTreasury\\n    uint88 zethTreasuryReward = yield.mul(zethTreasury).divU88(zethTotal);\\n    yield -= zethTreasuryReward;\\n    // Assign tithe of the remaining yield to treasuryF\\n    uint88 tithe = yield.mulU88(vault.zethTithePercent());\\n    yield -= tithe;\\n    // Realize assigned yields\\n    TAPP.ethEscrowed += zethTreasuryReward + tithe;\\n❌  Vault.zethYieldRate += yield.divU80(zethCollateral);\\n    Vault.zethCollateralReward += yield;\\n}\\n```\\n