DittoETH

Ditto
DeFiFoundryOracle
55,000 USDC
View results
Submission Details
Severity: medium
Invalid

LibVault.updateYield should not accrue rewards to treasury, except yield tithe

Summary

LibVault.updateYield should not accrue rewards to treasury, except yield tithe.

Vulnerability Details

When shorters create new short position, then zethCollateral variable is increased with their collateral + bidder's eth. Shorters that have minted assets are eligible to receive eth rewards that are coming from LST yield. According to the docs, only zeth that is backing asset is eligible for rewards.

LibVault.updateYield function is called to calculate distribution rate.
https://github.com/Cyfrin/2023-09-ditto/blob/main/contracts/libraries/LibVault.sol#L62-L94

function updateYield(uint256 vault) internal {
AppStorage storage s = appStorage();
STypes.Vault storage Vault = s.vault[vault];
STypes.VaultUser storage TAPP = s.vaultUser[vault][address(this)];
// Retrieve vault variables
uint88 zethTotalNew = uint88(getZethTotal(vault)); // @dev(safe-cast)
uint88 zethTotal = Vault.zethTotal;
uint88 zethCollateral = Vault.zethCollateral;
uint88 zethTreasury = TAPP.ethEscrowed;
// Calculate vault yield and overwrite previous total
if (zethTotalNew <= zethTotal) return;
uint88 yield = zethTotalNew - zethTotal;
Vault.zethTotal = zethTotalNew;
// If no short records, yield goes to treasury
if (zethCollateral == 0) {
TAPP.ethEscrowed += yield;
return;
}
// Assign yield to zethTreasury
uint88 zethTreasuryReward = yield.mul(zethTreasury).divU88(zethTotal);
yield -= zethTreasuryReward;
// Assign tithe of the remaining yield to treasuryF
uint88 tithe = yield.mulU88(vault.zethTithePercent());
yield -= tithe;
// Realize assigned yields
TAPP.ethEscrowed += zethTreasuryReward + tithe;
Vault.zethYieldRate += yield.divU80(zethCollateral);
Vault.zethCollateralReward += yield;
}

As you can see, in case if zethCollateral == 0 everything goes to the treasury as it means that there are no open short positions, so shorters do not receive yields.
Then we can see, that part of yield is going to the treasury.
uint88 zethTreasuryReward = yield.mul(zethTreasury).divU88(zethTotal);

Amount depends on ethEscrowed of treasury. This is violation of the rule. ethEscrowed of treasury is increasing with each withdrawing and unstaking, also when shorter loses yields and this amount doesn't actually participate in asset minting and can be easily withdrawn by dao. Moreover, after that treasury takes one more part of yield as fee(tithe).

As result shorters receive smaller amount of rewards as part of them is distributed to the treasury.

Impact

Shorters receive smaller amount of rewards.

Tools Used

VsCode

Recommendations

In case if zethCollateral != 0 then treasury should receive tithe fee only.

Updates

Lead Judging Commences

0xnevi Lead Judge
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.