#37607 [SC-Low] bricking redeem function
#37607 [SC-Low] Bricking Redeem Function
Submitted on Dec 10th 2024 at 12:11:56 UTC by @Blockian for IOP | Fluid Protocol
Report ID: #37607
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/Hydrogen-Labs/fluid-protocol/tree/main/contracts/protocol-manager-contract/src/main.sw
Impacts:
Protocol insolvency
Permanent freezing of funds
Description
Fluid Bug Report
Bricking Redeem Functionality
Overview
A critical issue in the redeem_collateral
function causes it to always revert, effectively preventing the redemption of USDF. This renders the redeem_collateral
functionality inoperable under certain conditions.
Root Cause Analysis
The problem originates from the get_all_assets_info
function. Specifically, when it attempts to populate the current borrower for a specific asset, it calls trove_manager.get_current_icr
for the candidate current_borrower
. If this call is made for a non-existent identity (e.g., null_identity_address
), the function reverts.
This behavior occurs because trove_manager.get_current_icr
tries to read from an uninitialized storage address, resulting in a revert in Sway. The chain of function calls leading to this issue is as follows:
trove_manager.get_current_icr
→internal_get_current_icr
→internal_get_entire_debt_and_coll
→internal_get_pending_asset_reward
.
The problematic code snippet:
Why Does This Occur?
The get_all_assets_info
function calls trove_manager.get_current_icr
with the candidate current_borrower
has an ICR lower than the MCR. In this case, the function fetches the previous borrower using sorted_troves.get_prev
. If the previous borrower is null
, it results in a revert.
Relevant code snippet:
How Can This Occur?
This issue arises when all borrowers in a specific trove have an ICR below the MCR. This scenario can occur due to:
Sudden token price drops (e.g., rug pulls, de-pegging, or hacks).
Other events leading to a significant decrease in collateral value.
While the likelihood of this issue may seem low, the protocol's support for a wide variety of tokens—along with future additions—amplifies the probability of encountering such a situation over time.
Impact
The inability to call redeem_collateral
disrupts the protocol's core functionality. A potential workaround could involve liquidating the entire trove. However, the protocol enforces a constraint (require_more_than_one_trove_in_system
) that prevents liquidating all troves. As a result, the affected trove cannot be liquidated, leaving the redeem_collateral
function effectively bricked.
Proposed Solution
Modify the behavior of trove_manager.get_current_icr
to return u64::max
when called for a non-existent trove. This change ensures the function handles edge cases gracefully, avoiding reverts in scenarios where borrowers or troves are invalid.
Proof of Concept
Proof of Concept
Run the following commands after applying the git diff:
forc test test_works_for_existing_trove --logs
-> runs the control test
forc test test_reverts_for_non_existing_trove --logs
-> run the test that fails
Apply the git patch below: