Treasury contract is designed to manage protocol funds. The only contract that interacts with the Treasury contract is the FeeCollector contract, to transfer RAAC tokens in distributeCollectedFees and emergencyWithdraw functions.
The problem arises because both distributeCollectedFees and emergencyWithdraw functions send tokens to the Treasury contract using direct transfers with safeTransfer function.
Because deposit function is not used to send funds, _balances mapping token is not updated, making it impossible to execute future withdraw.
The only way to withdraw tokens from Treasury contract is through the withdraw function:
Withdrawals require that _balances[token] >= amount which will not be the case if deposit function is not used to send tokens.
The impact of this issue is high as it leads to protocol funds being stuck in the treasury forever.
Manual review.
Make sure to use deposit function of Treasury contract when distributing collected fees or during emergency withdraw procedure. Note that this will require an approval from the FeeCollector contract to the Treasury contract to allow transferFrom function to transfer tokens in deposit function. This approval can be done in FeeCollector constructor or with a decidated additionnal function.
Possible implementation for processDistribution and 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.