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.