FeeDistributionBranch._handleWethRewardDistribution distributes the fee of a market by incrementing the valuePerShare of all connected vaults.
If one market received $1 fee, all vaults connected to the market increments its valuePerShare as if they received $1.
Market.receiveWethReward adds the all receivedVaultsWethRewardX18 to self.wethRewardPerVaultShare.
https://github.com/Cyfrin/2025-01-zaros-part-2/blob/fc64c07f42ca7811aa4a8929b206e0c936a8b373/src/market-making/leaves/Market.sol#L524-L525
FeeDistributionBranch._handleWethRewardDistribution calls Vault.recalculateVaultsCreditCapacity to update
Distribution.Data.valuePerShare of all connected vaults.
https://github.com/Cyfrin/2025-01-zaros-part-2/blob/fc64c07f42ca7811aa4a8929b206e0c936a8b373/src/market-making/branches/FeeDistributionBranch.sol#L395
Vault.recalculateVaultsCreditCapacity calls _recalculateConnectedMarketsState to calculate the vault's total
WETH reward change. It is in the for loop, so every vault calls _recalculateConnectedMarketsState.
https://github.com/Cyfrin/2025-01-zaros-part-2/blob/fc64c07f42ca7811aa4a8929b206e0c936a8b373/src/market-making/leaves/Vault.sol#L398-L399
_recalculateConnectedMarketsState calls market.getVaultAccumulatedValues for all connected markets.
https://github.com/Cyfrin/2025-01-zaros-part-2/blob/fc64c07f42ca7811aa4a8929b206e0c936a8b373/src/market-making/leaves/Vault.sol#L327
Market.getVaultAccumulatedValues calculates the difference between wethRewardPerVaultShare of the market and
lastVaultDistributedWethRewardPerShareX18 of the vault. The problem is that wethRewardPerVaultShare is
increased by receivedVaultsWethRewardX18, namely the whole amount of fee in step1.
https://github.com/Cyfrin/2025-01-zaros-part-2/blob/fc64c07f42ca7811aa4a8929b206e0c936a8b373/src/market-making/leaves/Market.sol#L321
_recalculateConnectedMarketsState updates Distribution.Data.valuePerShare
of the vault through self.wethRewardDistribution.distributeValue.
The for loop in Vault.recalculateVaultsCreditCapacity mentioned in step 2, continues and updates all the other
vaults with the same wethRewardPerVaultShare.
This double counts the fee for vaults.
In the test settings, every market is connected to all vaults. By calling receiveMarketFee for ETH_USD_MARKET_ID,
the fee is distributed to all vaults. However, the fee is double counted for each vault.
https://github.com/Cyfrin/2025-01-zaros-part-2/blob/fc64c07f42ca7811aa4a8929b206e0c936a8b373/test/Base.t.sol#L581'
Copy testPOC_receiveMarketFee_doubleCounts test function at the end of
unstake.t.sol.
Then run forge test --mt testPOC_receiveMarketFee_doubleCounts.
These functions in FeeDistributionBranch uses _handleWethRewardDistribution, so double count fees.
receiveMarketFee
convertAccumulatedFeesToWeth
Foundry.
Market.receiveWethReward must increase receivedVaultsWethRewardX18 not by the all fee but by the fee per vault
share.
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.