The YieldFacet#updateYield() is supposed to be called when the YieldFacet#_distributeYield() would be called via the YieldFacet#distributeYield(). Because the zethYieldRate used in the YieldFacet#_distributeYield() is supposed to be the latest rate.
However, within both the YieldFacet#distributeYield() and the YieldFacet#_distributeYield(), the YieldFacet#updateYield() would not be called.
This lead to a bad situation that the stale zethYieldRate, which is not the latest zethYieldRate, would be applied for the calculation in the YieldFacet#_distributeYield().
Since the YieldFacet#_distributeYield() would called via the YieldFacet#distributeYield(), the zETH yield, which is calculated based on the stale zethYieldRate, would be distributed to the Shorter (msg.sender).
When the YieldFacet#updateYield() would be called, the vault yield rate from staking rewards earned by bridge contracts holding LSD would be updated.
Within the YieldFacet#updateYield(), the LibVault#updateYield() would be called like this:
https://github.com/Cyfrin/2023-09-ditto/blob/main/contracts/facets/YieldFacet.sol#L42
Within the LibVault#updateYield(), the zethYieldRate would be updated to the latest rate and it would be stored into the AppStorage.vault storage (Vault.zethYieldRate) like this:
https://github.com/Cyfrin/2023-09-ditto/blob/main/contracts/libraries/LibVault.sol#L92
Within the YieldFacet#distributeYield(), the YieldFacet#_distributeYield() would be called like this:
https://github.com/Cyfrin/2023-09-ditto/blob/main/contracts/facets/YieldFacet.sol#L58
Within the YieldFacet#_distributeYield(), the zethYieldRate-stored in the AppStorage.vault storage(s.vault[vault].zethYieldRate) would be used like this:
https://github.com/Cyfrin/2023-09-ditto/blob/main/contracts/facets/YieldFacet.sol#L83
Based on above, the YieldFacet#updateYield() is supposed to be called when the YieldFacet#_distributeYield() would be called via the YieldFacet#distributeYield(). Because the zethYieldRate used in the YieldFacet#_distributeYield() is supposed to be the latest rate.
However, within both the YieldFacet#distributeYield() and the YieldFacet#_distributeYield(), the YieldFacet#updateYield() would not be called.
This lead to a bad situation that the stale zethYieldRate, which is not the latest zethYieldRate, would be applied for the calculation in the YieldFacet#_distributeYield().
Since the YieldFacet#_distributeYield() would called via the YieldFacet#distributeYield(), the zETH yield, which is calculated based on the stale zethYieldRate, would be distributed to the Shorter (msg.sender).
This lead to a bad situation that the stale zethYieldRate, which is not the latest zethYieldRate, would be applied for the calculation in the YieldFacet#_distributeYield().
Since the YieldFacet#_distributeYield() would called via the YieldFacet#distributeYield(), the zETH yield, which is calculated based on the stale zethYieldRate, would be distributed to the Shorter (msg.sender).
Foundry
Within the YieldFacet#distributeYield(), consider calling the YieldFacet#updateYield() before the YieldFacet#_distributeYield() would be called like his:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.