This report is about how malicious actors could hijack the system's solvency.
Any address with adequate funds can artificially manipulate the perceived solvency state of the DSCEngine.sol
contract.
The issue stems from these two functions in DSCEngine.sol
:
By using the depositCollateral()
function, addresses can deposit collateral which isn't actively backing any DSC debt. Moreover, the address that deposited this "collateral" can retrieve it anytime using redeemCollateral()
, without any restrictions or penalties.
Although _revertIfHealthFactorIsBroken()
is invoked inside redeemCollateral()
, for users with 0 DSC minted, this function won't revert. This is due to the health factor having it's maximum value if a user has no debt, a.k.a., 0 DSC minted.
System Initiation: Users begin interacting with the DecentralizedStableCoin.sol
and DSCEngine.sol
contracts.
Spotting the Loophole: A group of "mafiosos" identify a vulnerability. They deposit substantial collateral into the system, without incurring any actual debt.
False Security: The value of collateral falls, edging the system towards insolvency. However, the mafiosos' deposited funds paint a misleading picture of solvency. Other users, seeing the fund balance, remain unaware of the imminent risk.
The Blackmail Phase: Leveraging their unique position, the mafiosos approach users who invested big amounts of money in the stablecoin. They present an ultimatum: pay a "protection fee" or witness the system's solvency crumble. Moreover, any attempt to alert others will be met with an immediate system shutdown by the mafiosos.
This scenario exemplifies the potential dangers of such vulnerabilities. Not only can malicious entities manipulate the stablecoin's fate, but they can also exploit their position for extortion.
This vulnerability can result in scenarios where numerous user positions appear solvent due to the collateral that's held and "owned" by the engine. In reality, they are controlled by the original depositors, primarily due to the unrestricted nature of the redeemCollateral()
function and the capability to deposit collateral without minting any DSC.
The system may seem robust when tested with invariant_protocolMustHaveMoreValueThanTotalSupply()
. Yet, if the collateral's value drops, affecting many users' solvency, this can change abruptly. Addresses with "fake collateral" (collateral not backing any debt) can dictate the protocol's solvency.
This vulnerability enables single or multiple addresses to dominate the system's solvency, going against the goal of a decentralized and trustworthy engine. It also contradicts the principle that only natural fluctuations in the collateral's value should influence the system's solvency.
Manual audit.
Restrictive Collateral Entry: Make sure every collateral introduced is directly linked to some debt. This would prevent "fake collateral" entries that could be freely withdrawn.
Implement extra checkings in the depositCollateral()
function to make sure everyone has some degree of debt in the system:
🚧 Notice ⚠️: This change has not been tested, it's been added to help guiding the devs.
No minted DSC should be considered unhealthy: Make the situations where totalDscMinted
== 0 an unhealthy ones.
Return an unhealthy health factor value when totalDscMinted
== 0 like:
🚧 Notice ⚠️: This change has not been tested, it's been added to help guiding the devs.
🚧 Note ⚠️: Both solutions might be implemented independently or in combination to avoid this vulnerability, based on the system's desired complexity and goals. Regardless of the devs decision, after these changes,another audit is necessary.
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.