The RToken.sol
contract fails to properly implement the scaled balance mechanism for interest-bearing tokens, leading to a systemic failure in interest distribution to depositors. While the protocol correctly tracks interest accrual through the liquidity index, the core token scaling logic is implemented incorrectly, causing all interest payments to become trapped in the protocol rather than being distributed to depositors.
The current RToken.sol
implementation incorrectly handles the scaling mechanism needed for interest-bearing tokens. In lending protocols, token balances need to be stored in a scaled form to track proportional ownership as interest accrues. This requires:
Scaling down deposit amounts by dividing by the current liquidity index when minting tokens
Storing these scaled balances internally
Scaling up by multiplying by the current liquidity index when calculating real balances or processing withdrawals
The RToken contract instead:
Stores unscaled balances during minting: _mint(onBehalfOf, amount)
Burns the unscaled amount: _burn(from, amount)
Transfers the unscaled amount: safeTransfer(receiverOfUnderlying, amount)
This fundamentally breaks the interest distribution mechanism as depositors always receive their exact deposit amount back, regardless of accrued interest.
High
Depositors never receive any interest on their deposits
Interest payments from borrowers become permanently trapped in the protocol
The error affects all depositors equally and consistently
The likelihood is certain (high) as this is not a situational bug but rather a systematic failure in the core token mechanics that will affect every deposit and withdrawal operation.
Convert the project into a foundry project, ensuring test in foundry.toml points to a designated test directory.
Comment out the forking object from the hardhat.congif.cjs
file:
Copy the following test into the directory:
Run Forge test --vv
, this will show logs
Logs after Lenders have lent 100_000 crvUSD for 1 year:
Modify RToken to implement proper balance scaling following the pattern used in DebtToken.sol
in RToken.sol::
mint()
burn()
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.