The MErc20DelegateFixer contract inherits from MErc20Delegate which inherits a hierarchy of contracts including MToken. While the MErc20DelegateFixer contract mentions a nonReentrant  modifier, it relies on the inheritance chain for reentrancy protection. This audit report identifies a potential reentrancy vulnerability in the following functions:
repayBadDebtWithCash
repayBadDebtWithReserves
The repayBadDebtWithCash and repayBadDebtWithReserves functions are vulnerable to reentrancy attacks because they lack an explicit nonReentrant modifier within the functions themselves. Here's why relying solely on inheritance is risky:
Modifier Placement:  The nonReentrant modifier might be placed in the parent contract (MToken) but not necessarily applied to every function. Even if the parent contract has the modifier, it might not be enough if the vulnerable function in the child contract (MErc20DelegateFixer) doesn't inherit it explicitly.
An attacker could exploit this vulnerability by calling the function recursively within the same transaction, manipulating the bad debt counter and potentially stealing user funds.
Here's a specific scenario of how the attack might work for repayBadDebtWithCash:
Attacker initiates a transaction calling repayBadDebtWithCash with a certain amount (X) to be repaid.
Within the repayBadDebtWithCash function:
The function calls transferFrom to withdraw X amount of tokens from the msg.sender (user) to the contract.
Before the transferFrom call completes (funds not yet transferred), the attacker calls a malicious contract function from another address.
The malicious contract function:
Re-enters the repayBadDebtWithCash function itself recursively.
Within the re-entered call, the attacker manipulates the badDebt state variable to a higher value (Y) greater than X. This can be done by providing a manipulated input or exploiting other logic vulnerabilities in the contract.
The initial call to repayBadDebtWithCash continues:
The function subtracts the initial amount X (intended repayment) from the inflated bad debt value Y, resulting in a bad debt reduction of only (Y - X).
Since the transferFrom has already been called successfully, the user's X amount is transferred to the contract.
In this scenario, the attacker achieves a double spend:
The bad debt is only reduced by (Y - X), leaving a higher bad debt than intended.
The attacker steals the user's X amount transferred to the contract through transferFrom.
A similar attack scenario can be constructed for the repayBadDebtWithReserves function.
A successful reentrancy attack could allow an attacker to:
Steal user funds intended for bad debt repayment.
Reduce the bad debt counter by a smaller amount than intended, leaving a higher bad debt burden.
Disrupt the normal operation of the contract by manipulating reserve levels.
manual code review
use openzepplin reentrancyGuard
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.