Exchange Rate Manipulation for New and Empty Pools #165
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-92
edited-by-warden
unsatisfactory
does not satisfy C4 submission criteria; not eligible for awards
Lines of code
https://github.com/code-423n4/2023-07-moonwell/blob/fced18035107a345c31c9a9497d0da09105df4df/src/core/MToken.sol#L340-L370
Vulnerability details
Impact
mToken is a yield-bearing asset that users can obtain by depositing underlying tokens. The number of mTokens minted for a user depends on the amount of underlying tokens they deposit and the current exchange rate.
However, there is a critical bug in the MToken::mintFresh function that can be exploited to steal funds from initial depositors in a freshly deployed market.
exploitation route:
underlying.balanceOf(mToken)
value.As a result of the above steps, during the next legitimate user deposit, the
mTokens
value calculated for the user becomes less than 1 and is effectively rounded down to 0 by Solidity. Consequently, the user receives 0 mTokens against their deposit, and the entire supply of mTokens is now controlled by the attacker.The exchange rate is calculated using the formula:
The attack is made possible due to the way the exchange rate is calculated during a subsequent call to the contract. After the initial deposit by the attacker, when an unsuspecting user makes a deposit, the exchange rate is calculated by dividing the total cash by the market's total supply(this is since total borrows and total reserves is zero at this state). Let's assume the attacker's mToken balance is 1 mToken, and the market's total supply is 1. If the attacker performs a direct underlying token transfer to the mToken contract amounting to 99,999, assuming the attacker initial deposit is 1, then the exchange rate becomes 100,000.
The number of mTokens to be minted for the user is calculated as
amount / exchange rate
. As a result, all user deposits below this calculated amount will result in 0 mTokens being minted, due to how Solidity handles floating-point calculations.The attacker can extend the attack by not redeeming all of their mToken balance but rather redeeming only a portion during every user deposit.
Proof of Concept
https://github.com/code-423n4/2023-07-moonwell/blob/fced18035107a345c31c9a9497d0da09105df4df/src/core/MToken.sol#L340-L370
https://github.com/code-423n4/2023-07-moonwell/blob/fced18035107a345c31c9a9497d0da09105df4df/src/core/MToken.sol#L498-L563
See the Hundred finance hack : https://twitter.com/danielvf/status/1647332221131411463
Tools Used
Research
Recommended Mitigation Steps
To address this issue, I recommend implementing a fix by minting a small amount of mTokens to a dead address when the total supply equals zero. This approach ensures that the exchange rate remains stable for subsequent deposits and prevents the described attack scenario.
Assessed type
Other
The text was updated successfully, but these errors were encountered: