There is a critical issue in the redeem_collateral, where the lock_internal_redeem_collateral_from_trove flag is permanently set to true. This effectively disables the redeem_collateral functionality, preventing users from redeeming USDF and severely impacting protocol operations.
Root Cause
The bug resides in the redeem_collateral_from_trove logic within the trove_manager. When a redemption operation is cancelled, the system fails to release the lock on internal_redeem_collateral_from_trove. This oversight prevents future invocations of the function, leaving the relevant troves perpetually locked.
Relevant Code
The issue arises in the following snippet of the trove_manager implementation:
#[storage(read, write)]fninternal_redeem_collateral_from_trove( borrower:Identity, max_usdf_amount:u64, price:u64, partial_redemption_hint:u64, upper_partial_hint:Identity, lower_partial_hint:Identity,) ->SingleRedemptionValues {// Prevent reentrancyrequire( storage.lock_internal_redeem_collateral_from_trove.read() ==false,"TroveManager: Internal redeem collateral from trove is locked", ); storage.lock_internal_redeem_collateral_from_trove.write(true);// ... not relevant partsif (new_debt < MIN_NET_DEBT) {// Issue: Lock is not released on cancellation single_redemption_values.cancelled_partial =true;return single_redemption_values; }
The missing lock release upon redemption cancellation results in a permanent lock on the function.
Impact
The perpetual lock prevents any subsequent calls to internal_redeem_collateral_from_trove, rendering the redeem_collateral function entirely inoperable. This effectively disables a core feature of the protocol, creating a severe usability issue for end-users.
Exploit Vector
An attacker can systematically exploit this vulnerability to disable the redemption functionality for all troves using the following steps:
Create a trove with an Initial Collateral Ratio (ICR) of 135% and a debt of $500.
Attempt to redeem a small amount (e.g., $100), triggering a redemption cancellation due to the resulting debt falling below the minimum net debt threshold.
Close the trove and withdraw the collateral.
This sequence can be repeated across all troves in a single transaction, effectively locking out the redeem_collateral functionality for the entire system. The attack carries no risk to the attacker, as it does not expose them to liquidation or full redemption vulnerabilities since the position is closed in the same transaction.
Proposed Solutions
There are two possible solutions:
Release the Lock on Cancellation
Ensure that the lock_internal_redeem_collateral_from_trove is reset to false when a redemption operation is cancelled.
Eliminate the Lock Mechanism
Evaluate the necessity of the lock mechanism in the current system design. If it is deemed redundant, remove it entirely. Additionally, The Fuel framework offers a better alternative to address reentrancy concerns without relying on storage based locks.
Immunefi Bath Robe Post
https://x.com/immunefi/status/1866040553491616112
Can I now get the bath robe?
Proof of Concept
Proof of Concept
Run forc test after applying the following steps:
Add the following method to the trove_manager_interface: