When calculating RToken's dust amount, contractBalance is deflated and totalRealBalance is inflated. Calculated dust amount will be less than actual accrued amount. The impact of this vulnerability is high because calculateDustAmount represents protocol's profit, and transferAccruedDustis the only way to withdraw protocol's profit from RToken.
Take a look into RToken.calculateDustAmount:
contractBalance is calculated as the following:
while totalRealBalance is calculated as the following:
Since RToken is minted 1:1 to asset deposited amount, and RToken's totalSupply is multiplied by liquidityIndex, we can derive the following:
We can see that there are two mistakes in calculateDustAmount:
contractBalance is deflated by liquidityIndex. There is no need to divide asset balance by liquidityIndex
totalRealBalance is inflated by liquidityIndex ^ 2
As a result, calculated dust amount will be deflated by
As a side note, liquidityIndex will be greater than 1 as long as protocol works.
calculateDustAmountand transferAccruedDustare very important functions, whatever their names are. Because it's the only way to withdraw protocol's profit from RToken.
Let's see how Lending Pool makes profit.
RAAC protocol implemented (or tried to do) similar math with other lending protocols such as AAVE and Compound
usageRateis guaranteed to be greater thanliquidityRate, andusageIndexis guaranteed to be greater thanliquidityIndex.
What this means, we can see in the following example:
Alice deposits 100K crvUSD and receives 100K RToken
Bob borrows 100K crvUSD and receives 100K DebtToken
1 year passes
Alice now has 103593 RToken - i.e liquidityIndex = 1.03593
Bob now has 107452 DebtToken - i.e. usageIndex = 1.07452
Bob clears debt by paying 107452 crvUSD
Alice withdraws 103593 RToken and receives 103593 crvUSD
Now RToken has accrued 107452 - 103593 = 3859crvUSD, thanks to gap between usageIndexand liquidityIndex
This 3859 USD is protcol's profit - that's how any other decentralized lending protocols (AAVE, Compound etc) and banks work.
So if there's any gap between contractBalanceand totalRealBalance, it's due to either one of the following:
Protocol's profit due to usageIndexand liquidityIndexgap, or
Donation
This amount is calculated by calculateDustAmountand can be retrieved by calling transferAccruedDust.
So this vulnerability will lead to underestimation of protocol's profit and stuck of unclaimed profit in the protocol.
Manual Review
contractBalance should be calculated as the following:
totalRealBalance should be calculated as the following:
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.