The LendingPool contract in the RAAC protocol lacks proper validation of the Stability Pool address, allowing an attacker to register and use a forged/fake Stability Pool to redirect liquidations to their fraudulent contract. This enables attackers to steal liquidated collateral instead of repaying the outstanding debt, leading to protocol insolvency.
The finalizeLiquidation() function currently lacks verification that ensures:
The Stability Pool processing the liquidation is authorized.
The debt repayment actually benefits the protocol.
As a result, an attacker can deploy a fake Stability Pool contract, redirect liquidations to their fraudulent contract, and steal the collateral.
An NFT-backed loan enters liquidation.
The attacker registers a fake Stability Pool (if the contract allows modifications).
They trigger the liquidation process, causing the fake pool to "receive" the collateral.
The attacker withdraws the stolen NFT collateral, leaving a bad debt in the protocol.
The function assumes that msg.sender == stabilityPool
, but does not validate if the Stability Pool is legitimate.
If the stabilityPool
address is updated to an attacker-controlled contract, liquidated collateral will be sent to the wrong address.
Example Attack Scenario
A user defaults on a loan, and their NFT is flagged for liquidation.
The attacker deploys a fake Stability Pool contract and sets it as the active Stability Pool.
The attacker calls finalizeLiquidation(), sending liquidated NFTs to their fake pool.
The attacker withdraws the stolen NFTs from their contract and sells them for profit.
The protocol does not recover debt, leading to bad debt accumulation.
Unauthorized Collateral Theft: Attackers can steal user NFTs and liquidated assets.
Protocol Insolvency: The protocol fails to repay debt, resulting in bad debt accumulation.
Loss of User Funds: Honest users are unable to reclaim their collateral after repaying debts.
Manual Review
Implement whitelist validation to ensure that only approved Stability Pools can process liquidations:
Use this modifier in finalizeLiquidation()
:
2. Ensure Collateral and Debt Are Transferred to the Correct Pool
Add a check to verify that liquidated collateral and debt match the expected tokens:
This prevents fake pools from receiving unauthorized assets.
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.