When doing emergency withdraw via emergencyWithdraw(), we send ALL the raacToken to Treasury.
However, these tokens are tracked using collectedFees.
And we do NOT delete collectedFees state variable during emergency withdrawal, which leads to wrong accounting, and fee distribution will always FAIL, as the contract balance will NEVER exceed the collectedFee balance.
FeeCollector contract takes care of fee collection and distribution of fees.
Fee which is collected by the FeeCollector is in the form of raacToken. Whenever someone deposits fee(for any feeType), it is updated in collectedFees struct for tracking & distribution.
This collected fee is later sent to treasury, repairFund, etc while processing distribution(via distributeCollectedFees()).
Then, we delete this state variable collectedFees which simply resets all the different feeType values to zero.
So, the whole process starts all over again, and this is how collection and distribution of fee is carried out.
If there is an emergency situation, all the raacTokens in the FeeCollector can be sent to the treasury contract via emergencyWithdraw()
Notice that we are sending all our raacTokens to treasury contract.
However, there lies an issue here i.e. We do NOT delete state variable collectedFees.
This results in incorrect accounting which becomes a problem later on.
When the distribution of fee is carried out, there is a validation check which verifies whether our contract has sufficient balance(Raac Tokens) to pay the fee otherwise it will revert.
#_processDistributions()
After withdrawing all raac tokens via emergency withdraw, the collection of fee will start again.
However, this time the collectedFees will start with the balanceOf(address(this)) value prior to withdrawal.
But, now the balance of raac tokens in contract is ZERO.
So, after collecting new fees, whenever the above function is invoked(via distribution), it will ALWAYS lead to a REVERT because the collectedFee will NEVER match balanceOf the contract.
Although, we can still withdraw these tokens via emergency, but this will break the fee distribution functionality.
Contract becomes inoperable after emergency withdrawals since fee distributions will always fail.
Users cannot receive their entitled fees.
Manual
Consider adding this in emergencyWithdraw()
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.