The RAAC Token is designed to be able to collect fees and burn a certain amount of transferred assets. The collected fees from every transaction, if taxes are enabled within the contract, will transfer the funds directly into the FeeCollector
contract. The issue arising here is, that the contract lacks functionality to effectively deal with directly transferred funds.
As you can see in the following RAACToken::_update
function:
In the case of a transfer between users, while taxes are enabled and a fee collector is set, the update function will directly transfer the funds into the FeeCollector
contract.
Looking now into the collector contract:
we can already see within this function, that the RAAC Token is not using the intended functionality to deposit the tokens into the Fee Collector.
Going a bit further down within the contract we will than see the following:
The total amount of fees collected is reliant on FeeCollector::_updateCollectedFees
written by the FeeCollector::collectFee
function. The total amount for distribution is calculated within FeeCollector::_calculateTotalFees
which simply returns state being written by the collectFee
function. The total amount calculated here will directly be passed into FeeCollector::_processDistributions
. Therefore the contract lacks the functionality to effectively deal with directly transferred RAAC Tokens, since they are bypassing important state updates to effectively be distributed.
A certainly mitigating factor for this is though, that the FeeCollector possesses a rescue function, so funds, which would be send into the contract bypassing the accounting are not lost, however it requires manual intervention from the admin side to free those funds. Furthermore those funds are not accounted for within the type of fee they are meant for and this will still be an impact, since it is in the implementation as it is, impossible to tell in which category of fees funds fall, which did not go through the accounting. As an example, those fees could easily be mistaken as donations and easily sent into the wrong fee bucket leaving potentially holes in the balance somewhere else.
Also, the emergency withdraw can only send RAAC Tokens into the treasury and on top of that, would remove the whole balanceOf()
from the contract, it should pretty much only be used sparely.
The likelihood rating for me is a clear high, since it happens during normal operations, while the impact is a strong low, funds aren't lost, but almost certainly misrouted and would require an emergency withdraw. Therefore I conclude the total severity as a Medium in this case.
Manual Review
Use collectFee
within the RAAC Token Contract to deposit the fees into the Fee Collector like so:
If the above solution seems suitable, please don't forget to tie the whitelisting of the Fee Collector
a) into the constructor
b) enable/disable events
otherwise funds will not be transferable, but every transaction would revert with an OOG.
Alternative solution would be a nested if-else-block
.
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.